commit 08fddcd73e6a523c3eec3582f9b3f52c3ddb66a5
Author: anonymous
Date: Fri Jul 11 21:28:24 2025 +0200
Upload
diff --git a/Pandora/- Pandora V1.0.7 b/Pandora/- Pandora V1.0.7
new file mode 100644
index 0000000..06d7405
Binary files /dev/null and b/Pandora/- Pandora V1.0.7 differ
diff --git a/Pandora/AppCover.jpg b/Pandora/AppCover.jpg
new file mode 100644
index 0000000..d51a25a
Binary files /dev/null and b/Pandora/AppCover.jpg differ
diff --git a/Pandora/MD5 Read Me.txt b/Pandora/MD5 Read Me.txt
new file mode 100644
index 0000000..33dd142
--- /dev/null
+++ b/Pandora/MD5 Read Me.txt
@@ -0,0 +1,30 @@
+************************************************************************
+************************************************************************
+ Use your D-Pad UP and Down to scoll UP and Down.
+ To close this window press the "Back" button.
+************************************************************************
+************************************************************************
+
+The files are double packed to avoid some problems and make easy use
+of UX unzip instead of copy.
+
+Just in case a user do something like " Ohhh I have copied it but let
+me copy it 20 times more just because I can".
+That would lead into errors or me coding writing a copy dummy file
+delete dumm file routine first before the file be be copied.
+Unzip on the other hand just overwrites the file which, as I said,
+copy doesn't do.
+
+So the first MD5 of the first zip will not match up!
+
+When you unpack the first zip you get another one which will match
+the given MD5!
+
+
+************************************************************************
+************************************************************************
+
+PEACE!
+
+************************************************************************
+************************************************************************
\ No newline at end of file
diff --git a/Pandora/Pandora-linux-x64.zip b/Pandora/Pandora-linux-x64.zip
new file mode 100644
index 0000000..ec5cf34
Binary files /dev/null and b/Pandora/Pandora-linux-x64.zip differ
diff --git a/Pandora/Pandora-osx-x64.zip b/Pandora/Pandora-osx-x64.zip
new file mode 100644
index 0000000..3a60263
Binary files /dev/null and b/Pandora/Pandora-osx-x64.zip differ
diff --git a/Pandora/Pandora-win-x64.zip b/Pandora/Pandora-win-x64.zip
new file mode 100644
index 0000000..bbce783
Binary files /dev/null and b/Pandora/Pandora-win-x64.zip differ
diff --git a/PrometheOS/Aladdin 1MB Prometheos V1.5.0.bin b/PrometheOS/Aladdin 1MB Prometheos V1.5.0.bin
new file mode 100644
index 0000000..35c1ad1
Binary files /dev/null and b/PrometheOS/Aladdin 1MB Prometheos V1.5.0.bin differ
diff --git a/PrometheOS/Aladdin 2MB Prometheos V1.5.0.bin b/PrometheOS/Aladdin 2MB Prometheos V1.5.0.bin
new file mode 100644
index 0000000..5c6c309
Binary files /dev/null and b/PrometheOS/Aladdin 2MB Prometheos V1.5.0.bin differ
diff --git a/PrometheOS/ModXo.zip b/PrometheOS/ModXo.zip
new file mode 100644
index 0000000..450e0ef
Binary files /dev/null and b/PrometheOS/ModXo.zip differ
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/Build/.gitignore b/PrometheOS/PrometheOS-Firmware-1.5.0/Build/.gitignore
new file mode 100644
index 0000000..e5656c4
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/Build/.gitignore
@@ -0,0 +1,3 @@
+*.bin
+*.uf2
+^.xbe
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/Input/.gitignore b/PrometheOS/PrometheOS-Firmware-1.5.0/Input/.gitignore
new file mode 100644
index 0000000..834529d
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/Input/.gitignore
@@ -0,0 +1,3 @@
+*.bin
+*.uf2
+*.xbe
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/Input/Readme.md b/PrometheOS/PrometheOS-Firmware-1.5.0/Input/Readme.md
new file mode 100644
index 0000000..3ab2953
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/Input/Readme.md
@@ -0,0 +1 @@
+Place your source prometheos-[modchip].bin folder here, so we can extract the bootloader from it.
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/LICENSE.md b/PrometheOS/PrometheOS-Firmware-1.5.0/LICENSE.md
new file mode 100644
index 0000000..f288702
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/LICENSE.md
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+ .
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/.gitignore b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/.gitignore
new file mode 100644
index 0000000..2648964
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/.gitignore
@@ -0,0 +1,12 @@
+*.suo
+*.user
+
+.vs/
+
+obj/
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+
+Build/
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/BundlerMinifierVsix.vsix b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/BundlerMinifierVsix.vsix
new file mode 100644
index 0000000..759fdfd
Binary files /dev/null and b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/BundlerMinifierVsix.vsix differ
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/Helpers/Block.cs b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/Helpers/Block.cs
new file mode 100644
index 0000000..95eccb6
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/Helpers/Block.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+public class Block
+{
+ private const int BLOCK_SIZE = 256;
+
+ private uint mAddress;
+ private byte[] mBlockBytes = new byte[BLOCK_SIZE];
+
+ public int BlockSize { get; } = BLOCK_SIZE;
+
+ public Block(uint address)
+ {
+ mAddress = address;
+ }
+
+ public void SetBlockBytes(byte[] bytes)
+ {
+ Array.Clear(mBlockBytes, 0, BLOCK_SIZE);
+ Array.Copy(bytes, mBlockBytes, bytes.Length);
+ }
+
+ public byte[] Encode(int blockno, int numblocks, uint familyId)
+ {
+ const uint UF2_MAGIC_START0 = 0x0A324655;
+ const uint UF2_MAGIC_START1 = 0x9E5D5157;
+ const uint UF2_MAGIC_END = 0x0AB16F30;
+ const uint flags = 0x2000; // withFamilyId flag
+
+ using var memoryStream = new MemoryStream();
+ using var binaryWriter = new BinaryWriter(memoryStream);
+
+ binaryWriter.Write(UF2_MAGIC_START0);
+ binaryWriter.Write(UF2_MAGIC_START1);
+ binaryWriter.Write(flags);
+ binaryWriter.Write(mAddress);
+ binaryWriter.Write(BlockSize);
+ binaryWriter.Write(blockno);
+ binaryWriter.Write(numblocks);
+ binaryWriter.Write(familyId);
+ binaryWriter.Write(mBlockBytes);
+
+ // Pad with zeros
+ while (memoryStream.Position < (512 - sizeof(uint)))
+ {
+ binaryWriter.Write((byte)0);
+ }
+
+ binaryWriter.Write(UF2_MAGIC_END);
+ return memoryStream.ToArray();
+ }
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/Helpers/FlashBin.cs b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/Helpers/FlashBin.cs
new file mode 100644
index 0000000..2175d1b
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/Helpers/FlashBin.cs
@@ -0,0 +1,92 @@
+public static class FlashBin
+{
+ private static uint GetFlashAddressMask(uint biosSize)
+ {
+ var maskBits = 0u;
+
+ biosSize -= 1;
+ while (biosSize > 0)
+ {
+ biosSize >>= 1;
+ maskBits++;
+ }
+
+ var memCapacity = (uint)(1 << (int)maskBits);
+ var addressMask = memCapacity - 1;
+ return addressMask;
+ }
+
+ private static List GetUF2BlocksFromData(byte[] data, uint flashRomAddress)
+ {
+ var blocks = new List();
+
+ var blockAddress = flashRomAddress;
+
+ using var ms = new MemoryStream(data);
+ while (true)
+ {
+ var currentBlock = new Block(blockAddress);
+ var buffer = new byte[currentBlock.BlockSize];
+ var bytesRead = ms.Read(buffer, 0, currentBlock.BlockSize);
+ if (bytesRead == 0)
+ {
+ break;
+ }
+
+ currentBlock.SetBlockBytes(buffer);
+ blocks.Add(currentBlock);
+ blockAddress += (uint)currentBlock.BlockSize;
+ }
+ return blocks;
+ }
+
+ private static List GetUF2RomaddrMaskBlock(uint maskAddress, uint romaddrMask)
+ {
+ var blocks = new List();
+ var currentBlock = new Block(maskAddress);
+ currentBlock.SetBlockBytes(BitConverter.GetBytes(romaddrMask));
+
+ // Copy 16 times a 256 block to fill a 4096 byte sector
+ for (var i = 0; i < 16; i++)
+ {
+ blocks.Add(currentBlock);
+ }
+
+ return blocks;
+ }
+
+ private static byte[] CombineByteArrays(byte[] first, byte[] second)
+ {
+ byte[] combined = new byte[first.Length + second.Length];
+ Buffer.BlockCopy(first, 0, combined, 0, first.Length);
+ Buffer.BlockCopy(second, 0, combined, first.Length, second.Length);
+ return combined;
+ }
+
+ public static byte[] ProcessUf2(byte[] data, uint baseAddress, uint maskAddress, uint familyId)
+ {
+ var uf2Blocks = new List();
+ var byteStream = Array.Empty();
+
+ uint romaddrMask = GetFlashAddressMask(256 * 1024);
+ if (maskAddress != 0xffffffff)
+ {
+ uf2Blocks.AddRange(GetUF2RomaddrMaskBlock(maskAddress, romaddrMask));
+ }
+
+ uf2Blocks.AddRange(GetUF2BlocksFromData(data, baseAddress));
+
+ int totalBlocks = uf2Blocks.Count;
+ int currentBlock = 0;
+
+ foreach (var block in uf2Blocks)
+ {
+ byteStream = CombineByteArrays(byteStream, block.Encode(currentBlock, totalBlocks, familyId));
+ currentBlock++;
+ }
+
+ Console.WriteLine("Total blocks written: " + totalBlocks);
+
+ return byteStream;
+ }
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/Helpers/Minify.cs b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/Helpers/Minify.cs
new file mode 100644
index 0000000..54827b2
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/Helpers/Minify.cs
@@ -0,0 +1,123 @@
+using BundlerMinifier;
+using System.Text;
+
+namespace PrometheOSPacker.Helpers
+{
+ internal static class Minify
+ {
+ private static void BundleFile(string sourceFolder, string destFolder, string filename)
+ {
+ var sourceFile = Path.Combine(sourceFolder, filename);
+ var destFile = Path.Combine(destFolder, filename);
+
+ if (Path.GetExtension(filename).Equals(".ico", StringComparison.OrdinalIgnoreCase))
+ {
+ File.Copy(sourceFile, destFile, true);
+ return;
+ }
+
+ var bundleJson = Path.Combine(Utility.GetAppFolder(), "bundle.json");
+ if (File.Exists(bundleJson))
+ {
+ File.Delete(bundleJson);
+ }
+
+ var bundle = new Bundle
+ {
+ IncludeInProject = false,
+ OutputFileName = destFile
+ };
+ bundle.InputFiles.Add(sourceFile);
+
+ BundleHandler.AddBundle(bundleJson, bundle);
+
+ var bundleProcessor = new BundleFileProcessor();
+ var bundles = BundleHandler.GetBundles(bundleJson);
+ bundleProcessor.Process(bundleJson, bundles);
+
+ var minFile = Path.Combine(destFolder, $"{Path.GetFileNameWithoutExtension(filename)}.min{Path.GetExtension(filename)}");
+ if (File.Exists(minFile) == true && File.Exists(destFile))
+ {
+ File.Move(minFile, destFile, true);
+ }
+
+ File.Delete(bundleJson);
+ }
+
+ private static void IncludeFile(string ipToReplace, string sourceFolder, string destFolder, string filename)
+ {
+ var includeName = filename.Replace(".", "_");
+ var headerName = $"{includeName}.h";
+
+ var sourceFile = Path.Combine(sourceFolder, filename);
+ var destFile = Path.Combine(destFolder, headerName);
+
+ byte[] sourceData;
+ if (Path.GetExtension(sourceFile).Equals(".ico", StringComparison.OrdinalIgnoreCase))
+ {
+ sourceData = File.ReadAllBytes(sourceFile);
+ }
+ else
+ {
+ var sourceText = File.ReadAllText(sourceFile);
+ sourceText = sourceText.Replace($"http://{ipToReplace}", "");
+ sourceData = Encoding.UTF8.GetBytes(sourceText);
+ }
+
+ var resultBuilder = new StringBuilder();
+ resultBuilder.AppendLine("#pragma once");
+ resultBuilder.AppendLine("");
+ resultBuilder.AppendLine($"const uint8_t {includeName}[] = {{");
+
+ for (var i = 0; i < sourceData.Length; i++)
+ {
+ if (i % 16 == 0)
+ {
+ resultBuilder.Append(" ");
+ }
+ resultBuilder.Append("0x");
+ resultBuilder.Append(sourceData[i].ToString("x2"));
+ if (i < sourceData.Length - 1)
+ {
+ resultBuilder.Append(',');
+ if (i % 16 != 15)
+ {
+ resultBuilder.Append(' ');
+ }
+ }
+ if (i % 16 == 15)
+ {
+ resultBuilder.AppendLine();
+ }
+ }
+ resultBuilder.AppendLine();
+ resultBuilder.AppendLine("};");
+
+ var result = resultBuilder.ToString();
+ File.WriteAllText(destFile, result);
+ }
+
+ public static void Process(string ipToReplace)
+ {
+ var slnFolder = Utility.GetSlnFolder();
+
+ var webFolder = Path.Combine(slnFolder, "PrometheOSWeb", "wwwroot");
+ var bundleFolder = Path.Combine(slnFolder, "PrometheOSPacker", "bundle");
+ Directory.CreateDirectory(bundleFolder);
+
+ var webFiles = Directory.GetFiles(webFolder);
+ foreach (var webFile in webFiles)
+ {
+ BundleFile(webFolder, bundleFolder, Path.GetFileName(webFile));
+ }
+
+ var includeFolder = Path.GetFullPath("..\\PrometheOSXbe\\PrometheOSXbe\\Assets\\Web", slnFolder);
+
+ var bundleFiles = Directory.GetFiles(bundleFolder);
+ foreach (var bundleFile in bundleFiles)
+ {
+ IncludeFile(ipToReplace, bundleFolder, includeFolder, Path.GetFileName(bundleFile));
+ }
+ }
+ }
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/Helpers/Package.cs b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/Helpers/Package.cs
new file mode 100644
index 0000000..e39429f
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/Helpers/Package.cs
@@ -0,0 +1,318 @@
+using FluentFTP;
+using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.ImageSharp.Processing;
+using System.Net;
+using System.Net.Http.Headers;
+using System.Text;
+
+namespace PrometheOSPacker.Helpers
+{
+ //Bank1_256k = 3 0x000000 - 0x03ffff Sector Size 65536 Total 262144
+ //Bank2_256k = 4 0x040000 - 0x07ffff Sector Size 65536 Total 262144
+ //Bank3_256k = 5 0x080000 - 0x0bffff Sector Size 65536 Total 262144
+ //Bank4_256k = 6 0x0c0000 - 0x0fffff Sector Size 65536 Total 262144
+ //Bank1_512k = 7 0x000000 - 0x07ffff Sector Size 65536 Total 524288
+ //Bank2_512k = 8 0x080000 - 0x0fffff Sector Size 65536 Total 524288
+ //Bank1_1024k = 9 0x000000 - 0x0fffff Sector Size 65536 Total 1048576
+ //Bank_PrometheOS = 2 0x100000 - 0x17ffff Sector Size 65536 Total 524288
+ //Bank_Bootloader = 1 0x180000 - 0x1bffff Sector Size 65536 Total 262144
+ //Bank_Recovery = 10 0x1c0000 - 0x1fffff See Below Total 262144
+
+ //0x1c0000 - 0x1effff Sector Size 65536 Total 196608 (PrometheOS Continued)
+ //0x1f0000 - 0x1f7fff Sector Size 32768 Total 32768 (Installer Logo)
+ //0x1f8000 - 0x1f9fff Sector Size 8192 Total 8192 (Settings)
+ //0x1fa000 - 0x1fbfff Sector Size 8192 Total 8192 (Spare)
+ //0x1fc000 - 0x1fffff Sector Size 16384 Total 16384 (Spare)
+
+ //Suggested byes for PrometheOS = 720896 (524288 bytes Bank_PrometheOS + First 196608 bytes of Bank_Recovery)
+
+ internal class Package
+ {
+ public static byte[] CompressBank(string filePath, int size)
+ {
+ var fileData = File.ReadAllBytes(filePath);
+ var compressedData = new byte[fileData.Length];
+ var compressedSize = K4os.Compression.LZ4.LZ4Codec.Encode(fileData, compressedData, K4os.Compression.LZ4.LZ4Level.L12_MAX);
+ if (compressedSize <= 0)
+ {
+ throw new Exception("Compress failed.");
+ }
+ byte[] promethosLengthBytes = BitConverter.GetBytes(fileData.Length);
+ byte[] compressedLengthBytes = BitConverter.GetBytes(compressedSize);
+
+ var bank = new byte[size];
+ Array.Copy(promethosLengthBytes, 0, bank, 0, promethosLengthBytes.Length);
+ Array.Copy(compressedLengthBytes, 0, bank, 4, compressedLengthBytes.Length);
+ Array.Copy(compressedData, 0, bank, 8, compressedSize);
+
+ var checksum = 0;
+ for (int i = 0; i < bank.Length; i++)
+ {
+ checksum = checksum + bank[i] & 0xffff;
+ }
+
+ Console.WriteLine($"Compressed Size = {compressedSize + 8} of {size} - Checksum {checksum}");
+
+ return bank;
+ }
+
+ public static byte[] ExtractPrometheOS(string modchip)
+ {
+ var slnFolder = Utility.GetSlnFolder();
+ var prometheosSourcePath = Path.GetFullPath($"..\\Input\\prometheos-{modchip}.bin", slnFolder);
+ if (File.Exists(prometheosSourcePath) == false)
+ {
+ Console.WriteLine($"Error: Looks like you didnt suppliy prometheos-{modchip}.bin in input folder.");
+ throw new Exception("Failed: ExtractPrometheOS");
+ }
+
+ var prometheosSource = File.ReadAllBytes(prometheosSourcePath);
+ var firmware = new byte[256 * 1024];
+
+ if (modchip.Equals("Xenium", StringComparison.CurrentCultureIgnoreCase))
+ {
+ Array.Copy(prometheosSource, 0x180000, firmware, 0, 256 * 1024);
+ return firmware;
+ }
+
+ if (modchip.Equals("Xecuter", StringComparison.CurrentCultureIgnoreCase))
+ {
+ Array.Copy(prometheosSource, 0x000000, firmware, 0, 256 * 1024);
+ return firmware;
+ }
+
+ if (modchip.Equals("Xchanger", StringComparison.CurrentCultureIgnoreCase))
+ {
+ Array.Copy(prometheosSource, 0x0C0000, firmware, 0, 256 * 1024);
+ return firmware;
+ }
+
+ if (modchip.Equals("Aladdin1mb", StringComparison.CurrentCultureIgnoreCase))
+ {
+ Array.Copy(prometheosSource, 0x0C0000, firmware, 0, 256 * 1024);
+ return firmware;
+ }
+
+ if (modchip.Equals("Aladdin2mb", StringComparison.CurrentCultureIgnoreCase))
+ {
+ Array.Copy(prometheosSource, 0x100000, firmware, 0, 256 * 1024);
+ return firmware;
+ }
+
+ if (modchip.StartsWith("Modxo", StringComparison.CurrentCultureIgnoreCase))
+ {
+ Array.Copy(prometheosSource, 0x040000, firmware, 0, 256 * 1024);
+ return firmware;
+ }
+
+ throw new Exception($"Failed: Unrecognized modchip {modchip}.");
+ }
+
+ public static void PackageTools()
+ {
+ var slnFolder = Utility.GetSlnFolder();
+ var promethosToolsXbePath = Path.GetFullPath($"..\\PrometheOSXbe\\PrometheOSXbe\\Release-Tools\\PrometheOS-Tools.xbe", slnFolder);
+ var tools = File.ReadAllBytes(promethosToolsXbePath);
+
+ var buildPath = Path.Combine(slnFolder, "..\\Build");
+ Directory.CreateDirectory(buildPath);
+ File.WriteAllBytes(Path.Combine(buildPath, $"prometheos-tools.xbe"), tools);
+ }
+
+ public static void PackageXenium(string modchip)
+ {
+ var slnFolder = Utility.GetSlnFolder();
+ var prometheos = ExtractPrometheOS(modchip);
+
+ var promethosXbePath = Path.GetFullPath($"..\\PrometheOSXbe\\PrometheOSXbe\\Release-{modchip}\\PrometheOS.xbe", slnFolder);
+ if (File.Exists(promethosXbePath) == false)
+ {
+ Console.WriteLine("Error: Looks like you didnt build PrometheOSXbe.");
+ return;
+ }
+
+ Console.WriteLine("Packing PrometheOS Xbe...");
+ var promethosxbeBank = CompressBank(promethosXbePath, (512 + 96) * 1024);
+
+ var firmware = new byte[2048 * 1024];
+ Array.Copy(promethosxbeBank, 0, firmware, 0x100000, 512 * 1024);
+ Array.Copy(promethosxbeBank, 512 * 1024, firmware, 0x1e0000, 96 * 1024);
+ Array.Copy(prometheos, 0, firmware, 0x180000, prometheos.Length);
+
+ //var logo = GetInstallerLogo();
+ //Array.Copy(logo, 0, firmware, 0x1F0000 , logo.Length);
+
+ var buildPath = Path.Combine(slnFolder, "..\\Build");
+ Directory.CreateDirectory(buildPath);
+ File.WriteAllBytes(Path.Combine(buildPath, $"prometheos-{modchip.ToLower()}.bin"), firmware);
+ }
+
+ public static void PackageXecuter(string modchip)
+ {
+ var slnFolder = Utility.GetSlnFolder();
+ var prometheos = ExtractPrometheOS(modchip);
+
+ var promethosXbePath = Path.GetFullPath($"..\\PrometheOSXbe\\PrometheOSXbe\\Release-{modchip}\\PrometheOS.xbe", slnFolder);
+ if (File.Exists(promethosXbePath) == false)
+ {
+ Console.WriteLine("Error: Looks like you didnt build PrometheOSXbe.");
+ return;
+ }
+
+ Console.WriteLine("Packing PrometheOS Xbe...");
+ var promethosxbeBank = CompressBank(promethosXbePath, 655360);
+
+ var firmware = new byte[2048 * 1024];
+ Array.Copy(promethosxbeBank, 0, firmware, 0x040000, promethosxbeBank.Length);
+ Array.Copy(prometheos, 0, firmware, 0x000000, prometheos.Length);
+
+ //var logo = GetInstallerLogo();
+ //Array.Copy(logo, 0, firmware, 0x0e0000 , logo.Length);
+
+ var buildPath = Path.Combine(slnFolder, "..\\Build");
+ Directory.CreateDirectory(buildPath);
+ File.WriteAllBytes(Path.Combine(buildPath, $"prometheos-{modchip.ToLower()}.bin"), firmware);
+ }
+
+ public static void PackageXchanger(string modchip)
+ {
+ var slnFolder = Utility.GetSlnFolder();
+ var prometheos = ExtractPrometheOS(modchip);
+
+ var promethosXbePath = Path.GetFullPath($"..\\PrometheOSXbe\\PrometheOSXbe\\Release-{modchip}\\PrometheOS.xbe", slnFolder);
+ if (File.Exists(promethosXbePath) == false)
+ {
+ Console.WriteLine("Error: Looks like you didnt build PrometheOSXbe.");
+ return;
+ }
+
+ Console.WriteLine("Packing PrometheOS Xbe...");
+ var promethosxbeBank = CompressBank(promethosXbePath, 508 * 1024);
+
+ var firmware = new byte[1024 * 1024];
+ Array.Copy(promethosxbeBank, 0, firmware, 0x000000, 508 * 1024);
+ Array.Copy(prometheos, 0, firmware, 0x0C0000, prometheos.Length);
+
+
+ var buildPath = Path.Combine(slnFolder, "..\\Build");
+ Directory.CreateDirectory(buildPath);
+ File.WriteAllBytes(Path.Combine(buildPath, $"prometheos-{modchip.ToLower()}.bin"), firmware);
+ }
+
+ private static void PackageModxoVariant(byte[] prometheos, string variant, string modchip, uint familyId)
+ {
+ var slnFolder = Utility.GetSlnFolder();
+
+ var promethosXbePath = Path.GetFullPath($"..\\PrometheOSXbe\\PrometheOSXbe\\Release-{modchip}\\PrometheOS.xbe", slnFolder);
+ if (File.Exists(promethosXbePath) == false)
+ {
+ Console.WriteLine("Error: Looks like you didnt build PrometheOSXbe.");
+ return;
+ }
+
+ Console.WriteLine("Packing PrometheOS Xbe...");
+ var promethosxbeBank = CompressBank(promethosXbePath, 0x080000 - 0x1000);
+
+ var firmware = new byte[1 * 1024 * 1024];
+ Array.Copy(promethosxbeBank, 0, firmware, 0x080000, promethosxbeBank.Length);
+ Array.Copy(prometheos, 0, firmware, 0x040000, prometheos.Length);
+
+ var modxo = File.ReadAllBytes($"modxo-{variant}.bin");
+ Array.Copy(modxo, 0, firmware, 0x000000, modxo.Length);
+
+ var buildPath = Path.Combine(slnFolder, "..\\Build");
+ Directory.CreateDirectory(buildPath);
+ File.WriteAllBytes(Path.Combine(buildPath, $"prometheos-{modchip.ToLower()}-{variant.ToLower()}.bin"), firmware);
+
+ var uf2 = FlashBin.ProcessUf2(firmware, 0x10000000, 0xffffffff, familyId);
+ File.WriteAllBytes(Path.Combine(buildPath, $"prometheos-{modchip.ToLower()}-{variant.ToLower()}.uf2"), uf2);
+ }
+
+ public static void PackageModxo(string modchip)
+ {
+ var slnFolder = Utility.GetSlnFolder();
+ var prometheos = ExtractPrometheOS(modchip);
+ uint defaultFamilyId = 0xE48BFF56;
+
+ PackageModxoVariant(prometheos, "official-pico", modchip, defaultFamilyId);
+ PackageModxoVariant(prometheos, "official-pico2", modchip, 0xE48BFF59);
+ PackageModxoVariant(prometheos, "rp2040-zero-tiny", modchip, defaultFamilyId);
+ PackageModxoVariant(prometheos, "yd-rp2040", modchip, defaultFamilyId);
+ PackageModxoVariant(prometheos, "xiao-rp2040", modchip, defaultFamilyId);
+ PackageModxoVariant(prometheos, "ultra", modchip, defaultFamilyId);
+
+ if (File.Exists("modxo-custom.bin"))
+ {
+ PackageModxoVariant(prometheos, "custom", modchip, defaultFamilyId);
+ }
+ }
+
+ public static void PackageAladdin1mb(string modchip)
+ {
+ var slnFolder = Utility.GetSlnFolder();
+ var prometheos = ExtractPrometheOS(modchip);
+
+ var promethosXbePath = Path.GetFullPath($"..\\PrometheOSXbe\\PrometheOSXbe\\Release-{modchip}\\PrometheOS.xbe", slnFolder);
+ if (File.Exists(promethosXbePath) == false)
+ {
+ Console.WriteLine("Error: Looks like you didnt build PrometheOSXbe.");
+ return;
+ }
+
+ Console.WriteLine("Packing PrometheOS Xbe...");
+ var promethosxbeBank = CompressBank(promethosXbePath, 508 * 1024);
+
+ var firmware = new byte[1024 * 1024];
+ Array.Copy(promethosxbeBank, 0, firmware, 0x000000, 508 * 1024);
+ Array.Copy(prometheos, 0, firmware, 0x0C0000, prometheos.Length);
+
+ var buildPath = Path.Combine(slnFolder, "..\\Build");
+ Directory.CreateDirectory(buildPath);
+ File.WriteAllBytes(Path.Combine(buildPath, $"prometheos-{modchip.ToLower()}.bin"), firmware);
+ }
+
+ public static void PackageAladdin2mb(string modchip)
+ {
+ var slnFolder = Utility.GetSlnFolder();
+ var prometheos = ExtractPrometheOS(modchip);
+
+ var promethosXbePath = Path.GetFullPath($"..\\PrometheOSXbe\\PrometheOSXbe\\Release-{modchip}\\PrometheOS.xbe", slnFolder);
+ if (File.Exists(promethosXbePath) == false)
+ {
+ Console.WriteLine("Error: Looks like you didnt build PrometheOSXbe.");
+ return;
+ }
+
+ Console.WriteLine("Packing PrometheOS Xbe...");
+ var promethosxbeBank = CompressBank(promethosXbePath, (768 - 36) * 1024);
+
+ var firmware = new byte[2 * 1024 * 1024];
+ Array.Copy(promethosxbeBank, 0, firmware, 0x140000, (768 - 36) * 1024);
+ Array.Copy(prometheos, 0, firmware, 0x100000, prometheos.Length);
+
+ var buildPath = Path.Combine(slnFolder, "..\\Build");
+ Directory.CreateDirectory(buildPath);
+ File.WriteAllBytes(Path.Combine(buildPath, $"prometheos-{modchip.ToLower()}.bin"), firmware);
+ }
+
+ public static void FtpXeniumOS()
+ {
+ var slnFolder = Utility.GetSlnFolder();
+ var buildPath = Path.Combine(slnFolder, "Build");
+
+ try
+ {
+ using (FtpClient ftpClient = new FtpClient("ftp://xenium.local", "admin", "Blu3P3t3r!"))
+ {
+ ftpClient.Connect();
+ ftpClient.UploadFile(Path.Combine(buildPath, "xeniumos.bin"), "/home/admin/xenium-programmer/xenium-bin/xeniumos.bin");
+ Console.WriteLine($"File uploaded successfully");
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Error uploading file: {ex.Message}");
+ }
+ }
+ }
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/Helpers/Utility.cs b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/Helpers/Utility.cs
new file mode 100644
index 0000000..d644c08
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/Helpers/Utility.cs
@@ -0,0 +1,27 @@
+namespace PrometheOSPacker.Helpers
+{
+ internal static class Utility
+ {
+ public static string GetAppFolder()
+ {
+ return AppDomain.CurrentDomain.BaseDirectory;
+ }
+
+ public static string GetSlnFolder()
+ {
+ var directory = GetAppFolder();
+ var files = Directory.GetFiles(directory, "*.sln");
+ while (files.Length == 0)
+ {
+ var parentDirectoryInfo = Directory.GetParent(directory);
+ if (parentDirectoryInfo == null)
+ {
+ throw new Exception("Unable to get parent directory.");
+ }
+ directory = parentDirectoryInfo.FullName;
+ files = Directory.GetFiles(directory, "*.sln");
+ }
+ return directory;
+ }
+ }
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/Program.cs b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/Program.cs
new file mode 100644
index 0000000..aeccbe4
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/Program.cs
@@ -0,0 +1,136 @@
+using PrometheOSPacker.Helpers;
+using System.Diagnostics;
+
+namespace PrometheOSPacker
+{
+ internal class Program
+ {
+ static async Task DownloadFileAsync(string url, string filename)
+ {
+ using (HttpClient client = new HttpClient())
+ {
+ try
+ {
+ byte[] fileBytes = await client.GetByteArrayAsync(url);
+ await File.WriteAllBytesAsync(filename, fileBytes);
+ return true;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"An error occurre downloading file: {ex.Message}");
+ return false;
+ }
+ }
+ }
+
+ static void Main()
+ {
+ var version = "V1.0.7";
+ //version = "latest";
+
+ var baseUrl = $"https://github.com/Team-Resurgent/Modxo/releases/download/{version}";
+
+ Console.WriteLine("Downloading 'modxo-official-pico.bin'.");
+ if (DownloadFileAsync($"{baseUrl}/modxo_official_pico.bin", "modxo-official-pico.bin").GetAwaiter().GetResult() == false)
+ {
+ return;
+ }
+ Console.WriteLine("Downloading 'modxo-official-pico2.bin'.");
+ if (DownloadFileAsync($"{baseUrl}/modxo_official_pico2.bin", "modxo-official-pico2.bin").GetAwaiter().GetResult() == false)
+ {
+ return;
+ }
+ Console.WriteLine("Downloading 'modxo-yd-rp2040.bin'.");
+ if (DownloadFileAsync($"{baseUrl}/modxo_yd_rp2040.bin", "modxo-yd-rp2040.bin").GetAwaiter().GetResult() == false)
+ {
+ return;
+ }
+ Console.WriteLine("Downloading 'modxo-rp2040-zero-tiny.bin'.");
+ if (DownloadFileAsync($"{baseUrl}/modxo_rp2040_zero_tiny.bin", "modxo-rp2040-zero-tiny.bin").GetAwaiter().GetResult() == false)
+ {
+ return;
+ }
+ Console.WriteLine("Downloading 'modxo-xiao-rp2040.bin'.");
+ if (DownloadFileAsync($"{baseUrl}/modxo_xiao_rp2040.bin", "modxo-xiao-rp2040.bin").GetAwaiter().GetResult() == false)
+ {
+ return;
+ }
+ Console.WriteLine("Downloading 'modxo-ultra.bin'.");
+ if (DownloadFileAsync($"{baseUrl}/modxo_ultra.bin", "modxo-ultra.bin").GetAwaiter().GetResult() == false)
+ {
+ return;
+ }
+ Console.WriteLine();
+
+ var prometheosWebTestIp = "192.168.1.66"; // If you change ip in PrometheOSWeb update here
+
+ Console.WriteLine("1) Updating embeded web files in XBE...");
+ Minify.Process(prometheosWebTestIp);
+ Console.WriteLine();
+
+ Console.WriteLine("2) Please now build as Release PrometheOSTools and PrometheOSXbe for every modchip...");
+ Console.WriteLine();
+ Console.WriteLine("Press Enter when done.");
+ Console.ReadLine();
+
+ Console.WriteLine("3) Packaging PrometheOSTools and PrometheOS firmware for each modchip...");
+
+ Package.PackageTools();
+
+ var modchips = new string[]
+ {
+ "Aladdin1mb",
+ "Aladdin2mb",
+ "Xenium",
+ "Xecuter",
+ "Xchanger",
+ "Aladdin1mb",
+ "Aladdin2mb",
+ "Modxo",
+ };
+
+ foreach (var modchip in modchips)
+ {
+ if (modchip.Equals("Xenium", StringComparison.CurrentCultureIgnoreCase))
+ {
+ Package.PackageXenium(modchip);
+ }
+
+ if (modchip.Equals("Xecuter", StringComparison.CurrentCultureIgnoreCase))
+ {
+ Package.PackageXecuter(modchip);
+ }
+
+ if (modchip.Equals("Xchanger", StringComparison.CurrentCultureIgnoreCase))
+ {
+ Package.PackageXchanger(modchip);
+ }
+
+ if (modchip.Equals("Aladdin1mb", StringComparison.CurrentCultureIgnoreCase))
+ {
+ Package.PackageAladdin1mb(modchip);
+ }
+
+ if (modchip.Equals("Aladdin2mb", StringComparison.CurrentCultureIgnoreCase))
+ {
+ Package.PackageAladdin2mb(modchip);
+ }
+
+ if (modchip.Equals("Modxo", StringComparison.CurrentCultureIgnoreCase))
+ {
+ Package.PackageModxo(modchip);
+ }
+
+ // Edit and enable below lines if you wish to ftp to xbox / xenium programmer
+ //Console.WriteLine("4) FTP PrometheOS firmware...");
+ //Package.FtpPrometheOS("127.0.0.1", "xbox", "xbox", $"/c/prometheos-{modchip}.bin");
+ }
+
+ Console.WriteLine("Done\n");
+ Console.WriteLine();
+ Console.WriteLine("Press Enter to finish.");
+ Console.ReadLine();
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/PrometheOSPacker.csproj b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/PrometheOSPacker.csproj
new file mode 100644
index 0000000..190e7d3
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/PrometheOSPacker.csproj
@@ -0,0 +1,27 @@
+
+
+
+ Exe
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/cerbiosini.html b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/cerbiosini.html
new file mode 100644
index 0000000..437433b
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/cerbiosini.html
@@ -0,0 +1 @@
+PrometheOS
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/cerbiosini.js b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/cerbiosini.js
new file mode 100644
index 0000000..5522a02
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/cerbiosini.js
@@ -0,0 +1,61 @@
+window.onload = function () {
+ getCerbiosIni();
+};
+
+async function getCerbiosIni()
+{
+ await fetch("http://192.168.1.66/api/cerbiosini").then(async response => {
+
+ const reader = response.body.getReader();
+ const decoder = new TextDecoder("utf-8");
+
+ let body = '';
+
+ while (true)
+ {
+ const { done, value } = await reader.read();
+ if (done)
+ {
+ break;
+ }
+ const chunk = decoder.decode(value, { stream: true });
+ body += chunk;
+ }
+
+ let contentBody = "";
+ contentBody += "
";
+ let content = document.getElementById("content");
+ content.innerHTML = contentBody;
+
+ }).catch(error => {
+
+ let content = document.getElementById("content");
+ content.innerHTML = "Failed to connect."
+
+ });
+}
+
+async function setCerbiosIni()
+{
+ let content = document.getElementById("cerbiosini");
+
+ var data = new FormData();
+ data.append('body', content.innerText);
+ await fetch("http://192.168.1.66/api/cerbiosini", {
+ method: 'POST',
+ body: data
+ }).then(response => {
+ if (response.status == 200) {
+ window.location.href = "/index.html";
+ } else {
+ uploadFailure();
+ }
+ }).catch(() => {
+ uploadFailure()
+ }
+ );
+}
+
+function uploadFailure() {
+ alert("Upload failed.");
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/download.html b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/download.html
new file mode 100644
index 0000000..4e2e18b
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/download.html
@@ -0,0 +1 @@
+PrometheOS
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/download.js b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/download.js
new file mode 100644
index 0000000..7d1b66c
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/download.js
@@ -0,0 +1,37 @@
+window.onload = function () {
+ getBankInfo();
+};
+
+async function getBankInfo() {
+ await fetch("http://192.168.1.66/api/bankinfo.json").then(async response => {
+
+ const json = await response.json();
+
+ let contentBody = "";
+ for (let i = 0; i < json.length; i++) {
+ if (json[i].slots > 0) {
+ contentBody += "
";
+ }
+ }
+ let content = document.getElementById("content");
+ content.innerHTML = contentBody == "" ? "No items found." : contentBody;
+ }).catch(error => {
+ let content = document.getElementById("content");
+ content.innerHTML = "Failed to connect."
+ });
+}
+
+async function downloadBank(id, name)
+{
+ await fetch("http://192.168.1.66/api/downloadbank?" + id).catch(error => {
+ content.innerHTML = "Failed to connect."
+ }).then(response => response.blob()).then(blob => {
+ var url = window.URL.createObjectURL(blob);
+ var a = document.createElement('a');
+ a.href = url;
+ a.download = name;
+ document.body.appendChild(a);
+ a.click();
+ a.remove();
+ });
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/downloads.html b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/downloads.html
new file mode 100644
index 0000000..f503617
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/downloads.html
@@ -0,0 +1 @@
+PrometheOS
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/downloads.js b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/downloads.js
new file mode 100644
index 0000000..7706a59
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/downloads.js
@@ -0,0 +1 @@
+async function downloadEeprom(){await fetch("http://192.168.1.66/api/downloadeeprom").catch(()=>{content.innerHTML="Failed to connect."}).then(n=>n.blob()).then(n=>{var i=window.URL.createObjectURL(n),t=document.createElement("a");t.href=i;t.download="EEPROM.bin";document.body.appendChild(t);t.click();t.remove()})}async function downloadPrometheOS(){await fetch("http://192.168.1.66/api/downloadprom").catch(()=>{content.innerHTML="Failed to connect."}).then(n=>n.blob()).then(n=>{var i=window.URL.createObjectURL(n),t=document.createElement("a");t.href=i;t.download="PrometheOS.bin";document.body.appendChild(t);t.click();t.remove()})}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/favicon.ico b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/favicon.ico
new file mode 100644
index 0000000..f4fd3c8
Binary files /dev/null and b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/favicon.ico differ
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/flash.html b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/flash.html
new file mode 100644
index 0000000..b245cdd
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/flash.html
@@ -0,0 +1 @@
+PrometheOS
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/flash.js b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/flash.js
new file mode 100644
index 0000000..3a33214
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/flash.js
@@ -0,0 +1,129 @@
+let ledColorState = 0;
+
+window.onload = function () {
+ refreshFileInfo();
+};
+
+function getFileSize()
+{
+ const file = document.getElementById("file");
+ if (file.value == "") {
+ return -1;
+ }
+ const fileSize = file.files[0].size;
+ if (fileSize == 0) {
+ return -1;
+ } else if (fileSize % (256 * 1024) != 0) {
+ return -1;
+ } else if (fileSize > (1024 * 1024)) {
+ return -1;
+ }
+ return fileSize;
+}
+
+async function refreshFileInfo()
+{
+ const file = document.getElementById("file");
+ if (file.value != "") {
+ const name = document.getElementById("name");
+ name.value = file.files[0].name.substring(0, 40);
+ }
+
+ await fetch("http://192.168.1.66/api/freeslots.json").then(async response => {
+
+ const json = await response.json();
+ const freeSlots = document.getElementById("freeSlots");
+ freeSlots.textContent = json["freeslots"];
+
+ const upload = document.getElementById("upload");
+ const slotsNeeeded = document.getElementById("slotsNeeded");
+ const fileSize = getFileSize();
+
+ if (fileSize < 0) {
+ upload.setAttribute("disabled", "disabled");
+ slotsNeeeded.textContent = "NA";
+ }
+ else
+ {
+ const slotsNeededValue = fileSize / (256 * 1024);
+ slotsNeeeded.textContent = slotsNeededValue;
+ if (slotsNeededValue > json["freeslots"]) {
+ upload.setAttribute("disabled", "disabled");
+ } else {
+ upload.removeAttribute("disabled");
+ }
+ }
+
+ }).catch(error => {
+ //
+ });
+}
+
+function setLedColor(ledColor)
+{
+ ledColorState = ledColor;
+
+ let ledColorText = document.getElementById("ledColor");
+ switch (ledColor) {
+ case 1:
+ ledColorText.textContent = "Red";
+ break;
+ case 2:
+ ledColorText.textContent = "Green";
+ break;
+ case 3:
+ ledColorText.textContent = "Yellow";
+ break;
+ case 4:
+ ledColorText.textContent = "Blue";
+ break;
+ case 5:
+ ledColorText.textContent = "Purple";
+ break;
+ case 6:
+ ledColorText.textContent = "Turquoise";
+ break;
+ case 7:
+ ledColorText.textContent = "White";
+ break;
+ default:
+ ledColorText.textContent = "Off";
+ }
+}
+
+async function upload()
+{
+ const upload = document.getElementById("upload");
+ upload.setAttribute("disabled", "disabled");
+ const file = document.getElementById("file");
+ file.setAttribute("disabled", "disabled");
+
+ const name = document.getElementById("name");
+
+ var data = new FormData();
+ data.append('file', file.files[0]);
+ data.append('body', "{\"ledColor\":" + ledColorState + ",\"bankName\":\"" + name.value + "\"}");
+ await fetch("http://192.168.1.66/api/upload", {
+ method: 'POST',
+ body: data
+ }).then(response => {
+ if (response.status == 200) {
+ window.location.href = "/index.html";
+ } else {
+ uploadFailure();
+ }
+ }).catch(() => {
+ uploadFailure()
+ }
+ );
+
+}
+
+function uploadFailure()
+{
+ alert("Upload failed.");
+ let upload = document.getElementById("upload");
+ upload.removeAttribute("disabled");
+ let file = document.getElementById("file");
+ file.removeAttribute("disabled");
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/index.html b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/index.html
new file mode 100644
index 0000000..80d5e4e
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/index.html
@@ -0,0 +1 @@
+PrometheOS
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/index.js b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/index.js
new file mode 100644
index 0000000..a92e1e7
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/index.js
@@ -0,0 +1 @@
+async function screenshot(){await fetch("http://192.168.1.66/api/screenshot").catch(()=>{content.innerHTML="Failed to connect."}).then(n=>n.blob()).then(n=>{var i=window.URL.createObjectURL(n),t=document.createElement("a");t.href=i;t.download="screenshot.png";document.body.appendChild(t);t.click();t.remove()})}async function reboot(){await fetch("http://192.168.1.66/api/reboot")}async function shutdown(){await fetch("http://192.168.1.66/api/shutdown")}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/launch.html b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/launch.html
new file mode 100644
index 0000000..74b7a4c
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/launch.html
@@ -0,0 +1 @@
+PrometheOS
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/launch.js b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/launch.js
new file mode 100644
index 0000000..c74dac9
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/launch.js
@@ -0,0 +1,53 @@
+window.onload = function () {
+ getBankInfo();
+};
+
+async function getBankInfo() {
+ await fetch("http://192.168.1.66/api/bankinfo.json").then(async response => {
+
+ const json = await response.json();
+
+ let contentBody = "";
+ for (let i = 0; i < json.length; i++) {
+ if (json[i].slots > 0) {
+ contentBody += "
";
+ }
+ }
+ contentBody += "
";
+
+ let content = document.getElementById("content");
+ content.innerHTML = contentBody;
+ }).catch(error => {
+ let content = document.getElementById("content");
+ content.innerHTML = "Failed to connect."
+ });
+}
+
+async function launchBank(id)
+{
+ await fetch("http://192.168.1.66/api/launchbank?" + id).catch(error => {
+ content.innerHTML = "Failed to connect."
+ }).then(response => {
+ if (response.status == 200) {
+ let content = document.getElementById("content");
+ content.innerHTML = "Launching..."
+ } else {
+ let content = document.getElementById("content");
+ content.innerHTML = "Failed to launch."
+ }
+ });
+}
+
+async function launchTsop() {
+ await fetch("http://192.168.1.66/api/launchtsop").catch(error => {
+ content.innerHTML = "Failed to connect."
+ }).then(response => {
+ if (response.status == 200) {
+ let content = document.getElementById("content");
+ content.innerHTML = "Launching..."
+ } else {
+ let content = document.getElementById("content");
+ content.innerHTML = "Failed to launch."
+ }
+ });
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/main.css b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/main.css
new file mode 100644
index 0000000..33f6bb8
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/main.css
@@ -0,0 +1 @@
+.btn-ledoff{color:#fff;background-color:#404040;border-color:#000}.btn-ledoff:hover,.btn-ledoff:focus,.btn-ledoff:active,.btn-ledoff.active{color:#fff;background-color:#202020;border-color:#000}.btn-ledred{color:#000;background-color:#aa0a00;border-color:#000}.btn-ledred:hover,.btn-ledred:focus,.btn-ledred:active,.btn-ledred.active{color:#000;background-color:#d40c00;border-color:#000}.btn-ledgreen{color:#000;background-color:#289a23;border-color:#000}.btn-ledgreen:hover,.btn-ledgreen:focus,.btn-ledgreen:active,.btn-ledgreen.active{color:#000;background-color:#32c12c;border-color:#000}.btn-ledyellow{color:#000;background-color:#cca400;border-color:#000}.btn-ledyellow:hover,.btn-ledyellow:focus,.btn-ledyellow:active,.btn-ledyellow.active{color:#000;background-color:#ffcd00;border-color:#000}.btn-ledblue{color:#000;background-color:#4358cc;border-color:#000}.btn-ledblue:hover,.btn-ledblue:focus,.btn-ledblue:active,.btn-ledblue.active{color:#fff;background-color:#526eff;border-color:#000}.btn-ledpurple{color:#000;background-color:#663fa1;border-color:#000}.btn-ledpurple:hover,.btn-ledpurple:focus,.btn-ledpurple:active,.btn-ledpurple.active{color:#000;background-color:#7f4fc9;border-color:#000}.btn-ledturquoise{color:#000;background-color:#0096ae;border-color:#000}.btn-ledturquoise:hover,.btn-ledturquoise:focus,.btn-ledturquoise:active,.btn-ledturquoise.active{color:#000;background-color:#00bcd9;border-color:#000}.btn-ledwhite{color:#000;background-color:#c0c0c0;border-color:#000}.btn-ledwhite:hover,.btn-ledwhite:focus,.btn-ledwhite:active,.btn-ledwhite.active{color:#000;background-color:#f0f0f0;border-color:#000}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/pico.css b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/pico.css
new file mode 100644
index 0000000..52205b2
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/pico.css
@@ -0,0 +1,2576 @@
+:root {
+ --font-family: system-ui,-apple-system,"Segoe UI","Roboto","Ubuntu","Cantarell","Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";
+ --line-height: 1.5;
+ --font-weight: 400;
+ --font-size: 16px;
+ --border-radius: 0.25rem;
+ --border-width: 1px;
+ --outline-width: 3px;
+ --spacing: 1rem;
+ --typography-spacing-vertical: 1.5rem;
+ --block-spacing-vertical: calc(var(--spacing) * 2);
+ --block-spacing-horizontal: var(--spacing);
+ --grid-spacing-vertical: 0;
+ --grid-spacing-horizontal: var(--spacing);
+ --form-element-spacing-vertical: 0.75rem;
+ --form-element-spacing-horizontal: 1rem;
+ --nav-element-spacing-vertical: 1rem;
+ --nav-element-spacing-horizontal: 0.5rem;
+ --nav-link-spacing-vertical: 0.5rem;
+ --nav-link-spacing-horizontal: 0.5rem;
+ --form-label-font-weight: var(--font-weight);
+ --transition: 0.2s ease-in-out;
+ --modal-overlay-backdrop-filter: blur(0.25rem)
+}
+
+@media (min-width:576px) {
+ :root {
+ --font-size: 17px
+ }
+}
+
+@media (min-width:768px) {
+ :root {
+ --font-size: 18px
+ }
+}
+
+@media (min-width:992px) {
+ :root {
+ --font-size: 19px
+ }
+}
+
+@media (min-width:1200px) {
+ :root {
+ --font-size: 20px
+ }
+}
+
+@media (min-width:576px) {
+ body > footer, body > header, body > main, section {
+ --block-spacing-vertical: calc(var(--spacing) * 2.5)
+ }
+}
+
+@media (min-width:768px) {
+ body > footer, body > header, body > main, section {
+ --block-spacing-vertical: calc(var(--spacing) * 3)
+ }
+}
+
+@media (min-width:992px) {
+ body > footer, body > header, body > main, section {
+ --block-spacing-vertical: calc(var(--spacing) * 3.5)
+ }
+}
+
+@media (min-width:1200px) {
+ body > footer, body > header, body > main, section {
+ --block-spacing-vertical: calc(var(--spacing) * 4)
+ }
+}
+
+@media (min-width:576px) {
+ article {
+ --block-spacing-horizontal: calc(var(--spacing) * 1.25)
+ }
+}
+
+@media (min-width:768px) {
+ article {
+ --block-spacing-horizontal: calc(var(--spacing) * 1.5)
+ }
+}
+
+@media (min-width:992px) {
+ article {
+ --block-spacing-horizontal: calc(var(--spacing) * 1.75)
+ }
+}
+
+@media (min-width:1200px) {
+ article {
+ --block-spacing-horizontal: calc(var(--spacing) * 2)
+ }
+}
+
+dialog > article {
+ --block-spacing-vertical: calc(var(--spacing) * 2);
+ --block-spacing-horizontal: var(--spacing)
+}
+
+@media (min-width:576px) {
+ dialog > article {
+ --block-spacing-vertical: calc(var(--spacing) * 2.5);
+ --block-spacing-horizontal: calc(var(--spacing) * 1.25)
+ }
+}
+
+@media (min-width:768px) {
+ dialog > article {
+ --block-spacing-vertical: calc(var(--spacing) * 3);
+ --block-spacing-horizontal: calc(var(--spacing) * 1.5)
+ }
+}
+
+a {
+ --text-decoration: none
+}
+
+ a.contrast, a.secondary {
+ --text-decoration: underline
+ }
+
+small {
+ --font-size: 0.875em
+}
+
+h1, h2, h3, h4, h5, h6 {
+ --font-weight: 700
+}
+
+h1 {
+ --font-size: 2rem;
+ --typography-spacing-vertical: 3rem
+}
+
+h2 {
+ --font-size: 1.75rem;
+ --typography-spacing-vertical: 2.625rem
+}
+
+h3 {
+ --font-size: 1.5rem;
+ --typography-spacing-vertical: 2.25rem
+}
+
+h4 {
+ --font-size: 1.25rem;
+ --typography-spacing-vertical: 1.874rem
+}
+
+h5 {
+ --font-size: 1.125rem;
+ --typography-spacing-vertical: 1.6875rem
+}
+
+[type=checkbox], [type=radio] {
+ --border-width: 2px
+}
+
+ [type=checkbox][role=switch] {
+ --border-width: 3px
+ }
+
+tfoot td, tfoot th, thead td, thead th {
+ --border-width: 3px
+}
+
+:not(thead,tfoot) > * > td {
+ --font-size: 0.875em
+}
+
+code, kbd, pre, samp {
+ --font-family: "Menlo","Consolas","Roboto Mono","Ubuntu Monospace","Noto Mono","Oxygen Mono","Liberation Mono",monospace,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"
+}
+
+kbd {
+ --font-weight: bolder
+}
+
+:root:not([data-theme=dark]), [data-theme=light] {
+ --background-color: #fff;
+ --color: hsl(205, 20%, 32%);
+ --h1-color: hsl(205, 30%, 15%);
+ --h2-color: #24333e;
+ --h3-color: hsl(205, 25%, 23%);
+ --h4-color: #374956;
+ --h5-color: hsl(205, 20%, 32%);
+ --h6-color: #4d606d;
+ --muted-color: hsl(205, 10%, 50%);
+ --muted-border-color: hsl(205, 20%, 94%);
+ --primary: hsl(195, 85%, 41%);
+ --primary-hover: hsl(195, 90%, 32%);
+ --primary-focus: rgba(16, 149, 193, 0.125);
+ --primary-inverse: #fff;
+ --secondary: hsl(205, 15%, 41%);
+ --secondary-hover: hsl(205, 20%, 32%);
+ --secondary-focus: rgba(89, 107, 120, 0.125);
+ --secondary-inverse: #fff;
+ --contrast: hsl(205, 30%, 15%);
+ --contrast-hover: #000;
+ --contrast-focus: rgba(89, 107, 120, 0.125);
+ --contrast-inverse: #fff;
+ --mark-background-color: #fff2ca;
+ --mark-color: #543a26;
+ --ins-color: #388e3c;
+ --del-color: #c62828;
+ --blockquote-border-color: var(--muted-border-color);
+ --blockquote-footer-color: var(--muted-color);
+ --button-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+ --button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+ --form-element-background-color: transparent;
+ --form-element-border-color: hsl(205, 14%, 68%);
+ --form-element-color: var(--color);
+ --form-element-placeholder-color: var(--muted-color);
+ --form-element-active-background-color: transparent;
+ --form-element-active-border-color: var(--primary);
+ --form-element-focus-color: var(--primary-focus);
+ --form-element-disabled-background-color: hsl(205, 18%, 86%);
+ --form-element-disabled-border-color: hsl(205, 14%, 68%);
+ --form-element-disabled-opacity: 0.5;
+ --form-element-invalid-border-color: #c62828;
+ --form-element-invalid-active-border-color: #d32f2f;
+ --form-element-invalid-focus-color: rgba(211, 47, 47, 0.125);
+ --form-element-valid-border-color: #388e3c;
+ --form-element-valid-active-border-color: #43a047;
+ --form-element-valid-focus-color: rgba(67, 160, 71, 0.125);
+ --switch-background-color: hsl(205, 16%, 77%);
+ --switch-color: var(--primary-inverse);
+ --switch-checked-background-color: var(--primary);
+ --range-border-color: hsl(205, 18%, 86%);
+ --range-active-border-color: hsl(205, 16%, 77%);
+ --range-thumb-border-color: var(--background-color);
+ --range-thumb-color: var(--secondary);
+ --range-thumb-hover-color: var(--secondary-hover);
+ --range-thumb-active-color: var(--primary);
+ --table-border-color: var(--muted-border-color);
+ --table-row-stripped-background-color: #f6f8f9;
+ --code-background-color: hsl(205, 20%, 94%);
+ --code-color: var(--muted-color);
+ --code-kbd-background-color: var(--contrast);
+ --code-kbd-color: var(--contrast-inverse);
+ --code-tag-color: hsl(330, 40%, 50%);
+ --code-property-color: hsl(185, 40%, 40%);
+ --code-value-color: hsl(40, 20%, 50%);
+ --code-comment-color: hsl(205, 14%, 68%);
+ --accordion-border-color: var(--muted-border-color);
+ --accordion-close-summary-color: var(--color);
+ --accordion-open-summary-color: var(--muted-color);
+ --card-background-color: var(--background-color);
+ --card-border-color: var(--muted-border-color);
+ --card-box-shadow: 0.0145rem 0.029rem 0.174rem rgba(27, 40, 50, 0.01698),0.0335rem 0.067rem 0.402rem rgba(27, 40, 50, 0.024),0.0625rem 0.125rem 0.75rem rgba(27, 40, 50, 0.03),0.1125rem 0.225rem 1.35rem rgba(27, 40, 50, 0.036),0.2085rem 0.417rem 2.502rem rgba(27, 40, 50, 0.04302),0.5rem 1rem 6rem rgba(27, 40, 50, 0.06),0 0 0 0.0625rem rgba(27, 40, 50, 0.015);
+ --card-sectionning-background-color: #fbfbfc;
+ --dropdown-background-color: #fbfbfc;
+ --dropdown-border-color: #e1e6eb;
+ --dropdown-box-shadow: var(--card-box-shadow);
+ --dropdown-color: var(--color);
+ --dropdown-hover-background-color: hsl(205, 20%, 94%);
+ --modal-overlay-background-color: rgba(213, 220, 226, 0.7);
+ --progress-background-color: hsl(205, 18%, 86%);
+ --progress-color: var(--primary);
+ --loading-spinner-opacity: 0.5;
+ --tooltip-background-color: var(--contrast);
+ --tooltip-color: var(--contrast-inverse);
+ --icon-checkbox: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(65, 84, 98)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-chevron-button: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-chevron-button-inverse: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-close: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(115, 130, 140)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");
+ --icon-date: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(65, 84, 98)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");
+ --icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(198, 40, 40)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");
+ --icon-minus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E");
+ --icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(65, 84, 98)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");
+ --icon-time: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(65, 84, 98)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(56, 142, 60)' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
+ color-scheme: light
+}
+
+@media only screen and (prefers-color-scheme:dark) {
+ :root:not([data-theme]) {
+ --background-color: #11191f;
+ --color: hsl(205, 16%, 77%);
+ --h1-color: hsl(205, 20%, 94%);
+ --h2-color: #e1e6eb;
+ --h3-color: hsl(205, 18%, 86%);
+ --h4-color: #c8d1d8;
+ --h5-color: hsl(205, 16%, 77%);
+ --h6-color: #afbbc4;
+ --muted-color: hsl(205, 10%, 50%);
+ --muted-border-color: #1f2d38;
+ --primary: hsl(195, 85%, 41%);
+ --primary-hover: hsl(195, 80%, 50%);
+ --primary-focus: rgba(16, 149, 193, 0.25);
+ --primary-inverse: #fff;
+ --secondary: hsl(205, 15%, 41%);
+ --secondary-hover: hsl(205, 10%, 50%);
+ --secondary-focus: rgba(115, 130, 140, 0.25);
+ --secondary-inverse: #fff;
+ --contrast: hsl(205, 20%, 94%);
+ --contrast-hover: #fff;
+ --contrast-focus: rgba(115, 130, 140, 0.25);
+ --contrast-inverse: #000;
+ --mark-background-color: #d1c284;
+ --mark-color: #11191f;
+ --ins-color: #388e3c;
+ --del-color: #c62828;
+ --blockquote-border-color: var(--muted-border-color);
+ --blockquote-footer-color: var(--muted-color);
+ --button-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+ --button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+ --form-element-background-color: #11191f;
+ --form-element-border-color: #374956;
+ --form-element-color: var(--color);
+ --form-element-placeholder-color: var(--muted-color);
+ --form-element-active-background-color: var(--form-element-background-color);
+ --form-element-active-border-color: var(--primary);
+ --form-element-focus-color: var(--primary-focus);
+ --form-element-disabled-background-color: hsl(205, 25%, 23%);
+ --form-element-disabled-border-color: hsl(205, 20%, 32%);
+ --form-element-disabled-opacity: 0.5;
+ --form-element-invalid-border-color: #b71c1c;
+ --form-element-invalid-active-border-color: #c62828;
+ --form-element-invalid-focus-color: rgba(198, 40, 40, 0.25);
+ --form-element-valid-border-color: #2e7d32;
+ --form-element-valid-active-border-color: #388e3c;
+ --form-element-valid-focus-color: rgba(56, 142, 60, 0.25);
+ --switch-background-color: #374956;
+ --switch-color: var(--primary-inverse);
+ --switch-checked-background-color: var(--primary);
+ --range-border-color: #24333e;
+ --range-active-border-color: hsl(205, 25%, 23%);
+ --range-thumb-border-color: var(--background-color);
+ --range-thumb-color: var(--secondary);
+ --range-thumb-hover-color: var(--secondary-hover);
+ --range-thumb-active-color: var(--primary);
+ --table-border-color: var(--muted-border-color);
+ --table-row-stripped-background-color: rgba(115, 130, 140, 0.05);
+ --code-background-color: #18232c;
+ --code-color: var(--muted-color);
+ --code-kbd-background-color: var(--contrast);
+ --code-kbd-color: var(--contrast-inverse);
+ --code-tag-color: hsl(330, 30%, 50%);
+ --code-property-color: hsl(185, 30%, 50%);
+ --code-value-color: hsl(40, 10%, 50%);
+ --code-comment-color: #4d606d;
+ --accordion-border-color: var(--muted-border-color);
+ --accordion-active-summary-color: var(--primary);
+ --accordion-close-summary-color: var(--color);
+ --accordion-open-summary-color: var(--muted-color);
+ --card-background-color: #141e26;
+ --card-border-color: var(--card-background-color);
+ --card-box-shadow: 0.0145rem 0.029rem 0.174rem rgba(0, 0, 0, 0.01698),0.0335rem 0.067rem 0.402rem rgba(0, 0, 0, 0.024),0.0625rem 0.125rem 0.75rem rgba(0, 0, 0, 0.03),0.1125rem 0.225rem 1.35rem rgba(0, 0, 0, 0.036),0.2085rem 0.417rem 2.502rem rgba(0, 0, 0, 0.04302),0.5rem 1rem 6rem rgba(0, 0, 0, 0.06),0 0 0 0.0625rem rgba(0, 0, 0, 0.015);
+ --card-sectionning-background-color: #18232c;
+ --dropdown-background-color: hsl(205, 30%, 15%);
+ --dropdown-border-color: #24333e;
+ --dropdown-box-shadow: var(--card-box-shadow);
+ --dropdown-color: var(--color);
+ --dropdown-hover-background-color: rgba(36, 51, 62, 0.75);
+ --modal-overlay-background-color: rgba(36, 51, 62, 0.8);
+ --progress-background-color: #24333e;
+ --progress-color: var(--primary);
+ --loading-spinner-opacity: 0.5;
+ --tooltip-background-color: var(--contrast);
+ --tooltip-color: var(--contrast-inverse);
+ --icon-checkbox: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-chevron-button: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-chevron-button-inverse: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(0, 0, 0)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-close: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(115, 130, 140)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");
+ --icon-date: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");
+ --icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(183, 28, 28)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");
+ --icon-minus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E");
+ --icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");
+ --icon-time: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(46, 125, 50)' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
+ color-scheme: dark
+ }
+}
+
+[data-theme=dark] {
+ --background-color: #11191f;
+ --color: hsl(205, 16%, 77%);
+ --h1-color: hsl(205, 20%, 94%);
+ --h2-color: #e1e6eb;
+ --h3-color: hsl(205, 18%, 86%);
+ --h4-color: #c8d1d8;
+ --h5-color: hsl(205, 16%, 77%);
+ --h6-color: #afbbc4;
+ --muted-color: hsl(205, 10%, 50%);
+ --muted-border-color: #1f2d38;
+ --primary: hsl(204, 70%, 30%);
+ --primary-hover: hsl(195, 85%, 41%);
+ --primary-focus: rgba(16, 149, 193, 0.25);
+ --primary-inverse: #fff;
+ --secondary: hsl(205, 15%, 41%);
+ --secondary-hover: hsl(205, 10%, 50%);
+ --secondary-focus: rgba(115, 130, 140, 0.25);
+ --secondary-inverse: #fff;
+ --contrast: hsl(205, 20%, 94%);
+ --contrast-hover: #fff;
+ --contrast-focus: rgba(115, 130, 140, 0.25);
+ --contrast-inverse: #000;
+ --mark-background-color: #d1c284;
+ --mark-color: #11191f;
+ --ins-color: #388e3c;
+ --del-color: #c62828;
+ --blockquote-border-color: var(--muted-border-color);
+ --blockquote-footer-color: var(--muted-color);
+ --button-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+ --button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+ --form-element-background-color: #11191f;
+ --form-element-border-color: #374956;
+ --form-element-color: var(--color);
+ --form-element-placeholder-color: var(--muted-color);
+ --form-element-active-background-color: var(--form-element-background-color);
+ --form-element-active-border-color: var(--primary);
+ --form-element-focus-color: var(--primary-focus);
+ --form-element-disabled-background-color: hsl(205, 25%, 23%);
+ --form-element-disabled-border-color: hsl(205, 20%, 32%);
+ --form-element-disabled-opacity: 0.5;
+ --form-element-invalid-border-color: #b71c1c;
+ --form-element-invalid-active-border-color: #c62828;
+ --form-element-invalid-focus-color: rgba(198, 40, 40, 0.25);
+ --form-element-valid-border-color: #2e7d32;
+ --form-element-valid-active-border-color: #388e3c;
+ --form-element-valid-focus-color: rgba(56, 142, 60, 0.25);
+ --switch-background-color: #374956;
+ --switch-color: var(--primary-inverse);
+ --switch-checked-background-color: var(--primary);
+ --range-border-color: #24333e;
+ --range-active-border-color: hsl(205, 25%, 23%);
+ --range-thumb-border-color: var(--background-color);
+ --range-thumb-color: var(--secondary);
+ --range-thumb-hover-color: var(--secondary-hover);
+ --range-thumb-active-color: var(--primary);
+ --table-border-color: var(--muted-border-color);
+ --table-row-stripped-background-color: rgba(115, 130, 140, 0.05);
+ --code-background-color: #18232c;
+ --code-color: var(--muted-color);
+ --code-kbd-background-color: var(--contrast);
+ --code-kbd-color: var(--contrast-inverse);
+ --code-tag-color: hsl(330, 30%, 50%);
+ --code-property-color: hsl(185, 30%, 50%);
+ --code-value-color: hsl(40, 10%, 50%);
+ --code-comment-color: #4d606d;
+ --accordion-border-color: var(--muted-border-color);
+ --accordion-active-summary-color: var(--primary);
+ --accordion-close-summary-color: var(--color);
+ --accordion-open-summary-color: var(--muted-color);
+ --card-background-color: #141e26;
+ --card-border-color: var(--card-background-color);
+ --card-box-shadow: 0.0145rem 0.029rem 0.174rem rgba(0, 0, 0, 0.01698),0.0335rem 0.067rem 0.402rem rgba(0, 0, 0, 0.024),0.0625rem 0.125rem 0.75rem rgba(0, 0, 0, 0.03),0.1125rem 0.225rem 1.35rem rgba(0, 0, 0, 0.036),0.2085rem 0.417rem 2.502rem rgba(0, 0, 0, 0.04302),0.5rem 1rem 6rem rgba(0, 0, 0, 0.06),0 0 0 0.0625rem rgba(0, 0, 0, 0.015);
+ --card-sectionning-background-color: #18232c;
+ --dropdown-background-color: hsl(205, 30%, 15%);
+ --dropdown-border-color: #24333e;
+ --dropdown-box-shadow: var(--card-box-shadow);
+ --dropdown-color: var(--color);
+ --dropdown-hover-background-color: rgba(36, 51, 62, 0.75);
+ --modal-overlay-background-color: rgba(36, 51, 62, 0.8);
+ --progress-background-color: #24333e;
+ --progress-color: var(--primary);
+ --loading-spinner-opacity: 0.5;
+ --tooltip-background-color: var(--contrast);
+ --tooltip-color: var(--contrast-inverse);
+ --icon-checkbox: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-chevron-button: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-chevron-button-inverse: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(0, 0, 0)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-close: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(115, 130, 140)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");
+ --icon-date: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");
+ --icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(183, 28, 28)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");
+ --icon-minus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E");
+ --icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");
+ --icon-time: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(46, 125, 50)' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
+ color-scheme: dark
+}
+
+[type=checkbox], [type=radio], [type=range], progress {
+ accent-color: var(--primary)
+}
+
+*, ::after, ::before {
+ box-sizing: border-box;
+ background-repeat: no-repeat
+}
+
+::after, ::before {
+ text-decoration: inherit;
+ vertical-align: inherit
+}
+
+:where(:root) {
+ -webkit-tap-highlight-color: transparent;
+ -webkit-text-size-adjust: 100%;
+ -moz-text-size-adjust: 100%;
+ text-size-adjust: 100%;
+ background-color: var(--background-color);
+ color: var(--color);
+ font-weight: var(--font-weight);
+ font-size: var(--font-size);
+ line-height: var(--line-height);
+ font-family: var(--font-family);
+ text-rendering: optimizeLegibility;
+ overflow-wrap: break-word;
+ cursor: default;
+ -moz-tab-size: 4;
+ -o-tab-size: 4;
+ tab-size: 4
+}
+
+main {
+ display: block
+}
+
+body {
+ width: 100%;
+ margin: 0
+}
+
+ body > footer, body > header, body > main {
+ width: 100%;
+ margin-right: auto;
+ margin-left: auto;
+ padding: var(--block-spacing-vertical) 0
+ }
+
+.container, .container-fluid {
+ width: 100%;
+ margin-right: auto;
+ margin-left: auto;
+ padding-right: var(--spacing);
+ padding-left: var(--spacing)
+}
+
+@media (min-width:576px) {
+ .container {
+ max-width: 510px;
+ padding-right: 0;
+ padding-left: 0
+ }
+}
+
+@media (min-width:768px) {
+ .container {
+ max-width: 700px
+ }
+}
+
+@media (min-width:992px) {
+ .container {
+ max-width: 920px
+ }
+}
+
+@media (min-width:1200px) {
+ .container {
+ max-width: 1130px
+ }
+}
+
+section {
+ margin-bottom: var(--block-spacing-vertical)
+}
+
+.grid {
+ grid-column-gap: var(--grid-spacing-horizontal);
+ grid-row-gap: var(--grid-spacing-vertical);
+ display: grid;
+ grid-template-columns: 1fr;
+ margin: 0
+}
+
+@media (min-width:992px) {
+ .grid {
+ grid-template-columns: repeat(auto-fit,minmax(0%,1fr))
+ }
+}
+
+.grid > * {
+ min-width: 0
+}
+
+figure {
+ display: block;
+ margin: 0;
+ padding: 0;
+ overflow-x: auto
+}
+
+ figure figcaption {
+ padding: calc(var(--spacing) * .5) 0;
+ color: var(--muted-color)
+ }
+
+b, strong {
+ font-weight: bolder
+}
+
+sub, sup {
+ position: relative;
+ font-size: .75em;
+ line-height: 0;
+ vertical-align: baseline
+}
+
+sub {
+ bottom: -.25em
+}
+
+sup {
+ top: -.5em
+}
+
+address, blockquote, dl, figure, form, ol, p, pre, table, ul {
+ margin-top: 0;
+ margin-bottom: var(--typography-spacing-vertical);
+ color: var(--color);
+ font-style: normal;
+ font-weight: var(--font-weight);
+ font-size: var(--font-size)
+}
+
+[role=link], a {
+ --color: var(--primary);
+ --background-color: transparent;
+ outline: 0;
+ background-color: var(--background-color);
+ color: var(--color);
+ -webkit-text-decoration: var(--text-decoration);
+ text-decoration: var(--text-decoration);
+ transition: background-color var(--transition),color var(--transition),box-shadow var(--transition),-webkit-text-decoration var(--transition);
+ transition: background-color var(--transition),color var(--transition),text-decoration var(--transition),box-shadow var(--transition);
+ transition: background-color var(--transition),color var(--transition),text-decoration var(--transition),box-shadow var(--transition),-webkit-text-decoration var(--transition)
+}
+
+ [role=link]:is([aria-current],:hover,:active,:focus), a:is([aria-current],:hover,:active,:focus) {
+ --color: var(--primary-hover);
+ --text-decoration: underline
+ }
+
+ [role=link]:focus, a:focus {
+ --background-color: var(--primary-focus)
+ }
+
+ [role=link].secondary, a.secondary {
+ --color: var(--secondary)
+ }
+
+ [role=link].secondary:is([aria-current],:hover,:active,:focus), a.secondary:is([aria-current],:hover,:active,:focus) {
+ --color: var(--secondary-hover)
+ }
+
+ [role=link].secondary:focus, a.secondary:focus {
+ --background-color: var(--secondary-focus)
+ }
+
+ [role=link].contrast, a.contrast {
+ --color: var(--contrast)
+ }
+
+ [role=link].contrast:is([aria-current],:hover,:active,:focus), a.contrast:is([aria-current],:hover,:active,:focus) {
+ --color: var(--contrast-hover)
+ }
+
+ [role=link].contrast:focus, a.contrast:focus {
+ --background-color: var(--contrast-focus)
+ }
+
+h1, h2, h3, h4, h5, h6 {
+ margin-top: 0;
+ margin-bottom: var(--typography-spacing-vertical);
+ color: var(--color);
+ font-weight: var(--font-weight);
+ font-size: var(--font-size);
+ font-family: var(--font-family)
+}
+
+h1 {
+ --color: var(--h1-color)
+}
+
+h2 {
+ --color: var(--h2-color)
+}
+
+h3 {
+ --color: var(--h3-color)
+}
+
+h4 {
+ --color: var(--h4-color)
+}
+
+h5 {
+ --color: var(--h5-color)
+}
+
+h6 {
+ --color: var(--h6-color)
+}
+
+:where(address,blockquote,dl,figure,form,ol,p,pre,table,ul) ~ :is(h1,h2,h3,h4,h5,h6) {
+ margin-top: var(--typography-spacing-vertical)
+}
+
+.headings, hgroup {
+ margin-bottom: var(--typography-spacing-vertical)
+}
+
+ .headings > *, hgroup > * {
+ margin-bottom: 0
+ }
+
+ .headings > :last-child, hgroup > :last-child {
+ --color: var(--muted-color);
+ --font-weight: unset;
+ font-size: 1rem;
+ font-family: unset
+ }
+
+p {
+ margin-bottom: var(--typography-spacing-vertical)
+}
+
+small {
+ font-size: var(--font-size)
+}
+
+:where(dl,ol,ul) {
+ padding-right: 0;
+ padding-left: var(--spacing);
+ -webkit-padding-start: var(--spacing);
+ padding-inline-start: var(--spacing);
+ -webkit-padding-end: 0;
+ padding-inline-end: 0
+}
+
+ :where(dl,ol,ul) li {
+ margin-bottom: calc(var(--typography-spacing-vertical) * .25)
+ }
+
+ :where(dl,ol,ul) :is(dl,ol,ul) {
+ margin: 0;
+ margin-top: calc(var(--typography-spacing-vertical) * .25)
+ }
+
+ul li {
+ list-style: square
+}
+
+mark {
+ padding: .125rem .25rem;
+ background-color: var(--mark-background-color);
+ color: var(--mark-color);
+ vertical-align: baseline
+}
+
+blockquote {
+ display: block;
+ margin: var(--typography-spacing-vertical) 0;
+ padding: var(--spacing);
+ border-right: none;
+ border-left: .25rem solid var(--blockquote-border-color);
+ -webkit-border-start: 0.25rem solid var(--blockquote-border-color);
+ border-inline-start: 0.25rem solid var(--blockquote-border-color);
+ -webkit-border-end: none;
+ border-inline-end: none
+}
+
+ blockquote footer {
+ margin-top: calc(var(--typography-spacing-vertical) * .5);
+ color: var(--blockquote-footer-color)
+ }
+
+abbr[title] {
+ border-bottom: 1px dotted;
+ text-decoration: none;
+ cursor: help
+}
+
+ins {
+ color: var(--ins-color);
+ text-decoration: none
+}
+
+del {
+ color: var(--del-color)
+}
+
+::-moz-selection {
+ background-color: var(--primary-focus)
+}
+
+::selection {
+ background-color: var(--primary-focus)
+}
+
+:where(audio,canvas,iframe,img,svg,video) {
+ vertical-align: middle
+}
+
+audio, video {
+ display: inline-block
+}
+
+ audio:not([controls]) {
+ display: none;
+ height: 0
+ }
+
+:where(iframe) {
+ border-style: none
+}
+
+img {
+ max-width: 100%;
+ height: auto;
+ border-style: none
+}
+
+:where(svg:not([fill])) {
+ fill: currentColor
+}
+
+svg:not(:root) {
+ overflow: hidden
+}
+
+button {
+ margin: 0;
+ overflow: visible;
+ font-family: inherit;
+ text-transform: none
+}
+
+[type=button], [type=reset], [type=submit], button {
+ -webkit-appearance: button
+}
+
+button {
+ display: block;
+ width: 100%;
+ margin-bottom: var(--spacing)
+}
+
+[role=button] {
+ display: inline-block;
+ text-decoration: none
+}
+
+[role=button], button, input[type=button], input[type=reset], input[type=submit] {
+ --background-color: var(--primary);
+ --border-color: var(--primary);
+ --color: var(--primary-inverse);
+ --box-shadow: var(--button-box-shadow, 0 0 0 rgba(0, 0, 0, 0));
+ padding: var(--form-element-spacing-vertical) var(--form-element-spacing-horizontal);
+ border: var(--border-width) solid var(--border-color);
+ border-radius: var(--border-radius);
+ outline: 0;
+ background-color: var(--background-color);
+ box-shadow: var(--box-shadow);
+ color: var(--color);
+ font-weight: var(--font-weight);
+ font-size: 1rem;
+ line-height: var(--line-height);
+ text-align: center;
+ cursor: pointer;
+ transition: background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)
+}
+
+ [role=button]:is([aria-current],:hover,:active,:focus), button:is([aria-current],:hover,:active,:focus), input[type=button]:is([aria-current],:hover,:active,:focus), input[type=reset]:is([aria-current],:hover,:active,:focus), input[type=submit]:is([aria-current],:hover,:active,:focus) {
+ --background-color: var(--primary-hover);
+ --border-color: var(--primary-hover);
+ --box-shadow: var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0));
+ --color: var(--primary-inverse)
+ }
+
+ [role=button]:focus, button:focus, input[type=button]:focus, input[type=reset]:focus, input[type=submit]:focus {
+ --box-shadow: var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)),0 0 0 var(--outline-width) var(--primary-focus)
+ }
+
+:is(button,input[type=submit],input[type=button],[role=button]).secondary, input[type=reset] {
+ --background-color: var(--secondary);
+ --border-color: var(--secondary);
+ --color: var(--secondary-inverse);
+ cursor: pointer
+}
+
+ :is(button,input[type=submit],input[type=button],[role=button]).secondary:is([aria-current],:hover,:active,:focus), input[type=reset]:is([aria-current],:hover,:active,:focus) {
+ --background-color: var(--secondary-hover);
+ --border-color: var(--secondary-hover);
+ --color: var(--secondary-inverse)
+ }
+
+ :is(button,input[type=submit],input[type=button],[role=button]).secondary:focus, input[type=reset]:focus {
+ --box-shadow: var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)),0 0 0 var(--outline-width) var(--secondary-focus)
+ }
+
+:is(button,input[type=submit],input[type=button],[role=button]).contrast {
+ --background-color: var(--contrast);
+ --border-color: var(--contrast);
+ --color: var(--contrast-inverse)
+}
+
+ :is(button,input[type=submit],input[type=button],[role=button]).contrast:is([aria-current],:hover,:active,:focus) {
+ --background-color: var(--contrast-hover);
+ --border-color: var(--contrast-hover);
+ --color: var(--contrast-inverse)
+ }
+
+ :is(button,input[type=submit],input[type=button],[role=button]).contrast:focus {
+ --box-shadow: var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)),0 0 0 var(--outline-width) var(--contrast-focus)
+ }
+
+:is(button,input[type=submit],input[type=button],[role=button]).outline, input[type=reset].outline {
+ --background-color: transparent;
+ --color: var(--primary)
+}
+
+ :is(button,input[type=submit],input[type=button],[role=button]).outline:is([aria-current],:hover,:active,:focus), input[type=reset].outline:is([aria-current],:hover,:active,:focus) {
+ --background-color: transparent;
+ --color: var(--primary-hover)
+ }
+
+ :is(button,input[type=submit],input[type=button],[role=button]).outline.secondary, input[type=reset].outline {
+ --color: var(--secondary)
+ }
+
+ :is(button,input[type=submit],input[type=button],[role=button]).outline.secondary:is([aria-current],:hover,:active,:focus), input[type=reset].outline:is([aria-current],:hover,:active,:focus) {
+ --color: var(--secondary-hover)
+ }
+
+ :is(button,input[type=submit],input[type=button],[role=button]).outline.contrast {
+ --color: var(--contrast)
+ }
+
+ :is(button,input[type=submit],input[type=button],[role=button]).outline.contrast:is([aria-current],:hover,:active,:focus) {
+ --color: var(--contrast-hover)
+ }
+
+:where(button,[type=submit],[type=button],[type=reset],[role=button])[disabled], :where(fieldset[disabled]) :is(button,[type=submit],[type=button],[type=reset],[role=button]), a[role=button]:not([href]) {
+ opacity: .5;
+ pointer-events: none
+}
+
+input, optgroup, select, textarea {
+ margin: 0;
+ font-size: 1rem;
+ line-height: var(--line-height);
+ font-family: inherit;
+ letter-spacing: inherit
+}
+
+input {
+ overflow: visible
+}
+
+select {
+ text-transform: none
+}
+
+legend {
+ max-width: 100%;
+ padding: 0;
+ color: inherit;
+ white-space: normal
+}
+
+textarea {
+ overflow: auto
+}
+
+[type=checkbox], [type=radio] {
+ padding: 0
+}
+
+::-webkit-inner-spin-button, ::-webkit-outer-spin-button {
+ height: auto
+}
+
+[type=search] {
+ -webkit-appearance: textfield;
+ outline-offset: -2px
+}
+
+ [type=search]::-webkit-search-decoration {
+ -webkit-appearance: none
+ }
+
+::-webkit-file-upload-button {
+ -webkit-appearance: button;
+ font: inherit
+}
+
+::-moz-focus-inner {
+ padding: 0;
+ border-style: none
+}
+
+:-moz-focusring {
+ outline: 0
+}
+
+:-moz-ui-invalid {
+ box-shadow: none
+}
+
+::-ms-expand {
+ display: none
+}
+
+[type=file], [type=range] {
+ padding: 0;
+ border-width: 0
+}
+
+input:not([type=checkbox],[type=radio],[type=range]) {
+ height: calc(1rem * var(--line-height) + var(--form-element-spacing-vertical) * 2 + var(--border-width) * 2)
+}
+
+fieldset {
+ margin: 0;
+ margin-bottom: var(--spacing);
+ padding: 0;
+ border: 0
+}
+
+ fieldset legend, label {
+ display: block;
+ margin-bottom: calc(var(--spacing) * .25);
+ font-weight: var(--form-label-font-weight,var(--font-weight))
+ }
+
+input:not([type=checkbox],[type=radio]), select, textarea {
+ width: 100%
+}
+
+input:not([type=checkbox],[type=radio],[type=range],[type=file]), select, textarea {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ padding: var(--form-element-spacing-vertical) var(--form-element-spacing-horizontal)
+}
+
+input, select, textarea {
+ --background-color: var(--form-element-background-color);
+ --border-color: var(--form-element-border-color);
+ --color: var(--form-element-color);
+ --box-shadow: none;
+ border: var(--border-width) solid var(--border-color);
+ border-radius: var(--border-radius);
+ outline: 0;
+ background-color: var(--background-color);
+ box-shadow: var(--box-shadow);
+ color: var(--color);
+ font-weight: var(--font-weight);
+ transition: background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)
+}
+
+ :where(select,textarea):is(:active,:focus), input:not([type=submit],[type=button],[type=reset],[type=checkbox],[type=radio],[readonly]):is(:active,:focus) {
+ --background-color: var(--form-element-active-background-color)
+ }
+
+ :where(select,textarea):is(:active,:focus), input:not([type=submit],[type=button],[type=reset],[role=switch],[readonly]):is(:active,:focus) {
+ --border-color: var(--form-element-active-border-color)
+ }
+
+ input:not([type=submit],[type=button],[type=reset],[type=range],[type=file],[readonly]):focus, select:focus, textarea:focus {
+ --box-shadow: 0 0 0 var(--outline-width) var(--form-element-focus-color)
+ }
+
+ :where(fieldset[disabled]) :is(input:not([type=submit],[type=button],[type=reset]),select,textarea), input:not([type=submit],[type=button],[type=reset])[disabled], select[disabled], textarea[disabled] {
+ --background-color: var(--form-element-disabled-background-color);
+ --border-color: var(--form-element-disabled-border-color);
+ opacity: var(--form-element-disabled-opacity);
+ pointer-events: none
+ }
+
+:where(input,select,textarea):not([type=checkbox],[type=radio],[type=date],[type=datetime-local],[type=month],[type=time],[type=week])[aria-invalid] {
+ padding-right: calc(var(--form-element-spacing-horizontal) + 1.5rem) !important;
+ padding-left: var(--form-element-spacing-horizontal);
+ -webkit-padding-start: var(--form-element-spacing-horizontal) !important;
+ padding-inline-start: var(--form-element-spacing-horizontal) !important;
+ -webkit-padding-end: calc(var(--form-element-spacing-horizontal) + 1.5rem) !important;
+ padding-inline-end: calc(var(--form-element-spacing-horizontal) + 1.5rem) !important;
+ background-position: center right .75rem;
+ background-size: 1rem auto;
+ background-repeat: no-repeat
+}
+
+:where(input,select,textarea):not([type=checkbox],[type=radio],[type=date],[type=datetime-local],[type=month],[type=time],[type=week])[aria-invalid=false] {
+ background-image: var(--icon-valid)
+}
+
+:where(input,select,textarea):not([type=checkbox],[type=radio],[type=date],[type=datetime-local],[type=month],[type=time],[type=week])[aria-invalid=true] {
+ background-image: var(--icon-invalid)
+}
+
+:where(input,select,textarea)[aria-invalid=false] {
+ --border-color: var(--form-element-valid-border-color)
+}
+
+ :where(input,select,textarea)[aria-invalid=false]:is(:active,:focus) {
+ --border-color: var(--form-element-valid-active-border-color) !important;
+ --box-shadow: 0 0 0 var(--outline-width) var(--form-element-valid-focus-color) !important
+ }
+
+:where(input,select,textarea)[aria-invalid=true] {
+ --border-color: var(--form-element-invalid-border-color)
+}
+
+ :where(input,select,textarea)[aria-invalid=true]:is(:active,:focus) {
+ --border-color: var(--form-element-invalid-active-border-color) !important;
+ --box-shadow: 0 0 0 var(--outline-width) var(--form-element-invalid-focus-color) !important
+ }
+
+[dir=rtl] :where(input,select,textarea):not([type=checkbox],[type=radio]):is([aria-invalid],[aria-invalid=true],[aria-invalid=false]) {
+ background-position: center left .75rem
+}
+
+input::-webkit-input-placeholder, input::placeholder, select:invalid, textarea::-webkit-input-placeholder, textarea::placeholder {
+ color: var(--form-element-placeholder-color);
+ opacity: 1
+}
+
+input:not([type=checkbox],[type=radio]), select, textarea {
+ margin-bottom: var(--spacing)
+}
+
+ select::-ms-expand {
+ border: 0;
+ background-color: transparent
+ }
+
+ select:not([multiple],[size]) {
+ padding-right: calc(var(--form-element-spacing-horizontal) + 1.5rem);
+ padding-left: var(--form-element-spacing-horizontal);
+ -webkit-padding-start: var(--form-element-spacing-horizontal);
+ padding-inline-start: var(--form-element-spacing-horizontal);
+ -webkit-padding-end: calc(var(--form-element-spacing-horizontal) + 1.5rem);
+ padding-inline-end: calc(var(--form-element-spacing-horizontal) + 1.5rem);
+ background-image: var(--icon-chevron);
+ background-position: center right .75rem;
+ background-size: 1rem auto;
+ background-repeat: no-repeat
+ }
+
+[dir=rtl] select:not([multiple],[size]) {
+ background-position: center left .75rem
+}
+
+:where(input,select,textarea,.grid) + small {
+ display: block;
+ width: 100%;
+ margin-top: calc(var(--spacing) * -.75);
+ margin-bottom: var(--spacing);
+ color: var(--muted-color)
+}
+
+label > :where(input,select,textarea) {
+ margin-top: calc(var(--spacing) * .25)
+}
+
+[type=checkbox], [type=radio] {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ width: 1.25em;
+ height: 1.25em;
+ margin-top: -.125em;
+ margin-right: .375em;
+ margin-left: 0;
+ -webkit-margin-start: 0;
+ margin-inline-start: 0;
+ -webkit-margin-end: .375em;
+ margin-inline-end: .375em;
+ border-width: var(--border-width);
+ font-size: inherit;
+ vertical-align: middle;
+ cursor: pointer
+}
+
+ [type=checkbox]::-ms-check, [type=radio]::-ms-check {
+ display: none
+ }
+
+ [type=checkbox]:checked, [type=checkbox]:checked:active, [type=checkbox]:checked:focus, [type=radio]:checked, [type=radio]:checked:active, [type=radio]:checked:focus {
+ --background-color: var(--primary);
+ --border-color: var(--primary);
+ background-image: var(--icon-checkbox);
+ background-position: center;
+ background-size: .75em auto;
+ background-repeat: no-repeat
+ }
+
+ [type=checkbox] ~ label, [type=radio] ~ label {
+ display: inline-block;
+ margin-right: .375em;
+ margin-bottom: 0;
+ cursor: pointer
+ }
+
+ [type=checkbox]:indeterminate {
+ --background-color: var(--primary);
+ --border-color: var(--primary);
+ background-image: var(--icon-minus);
+ background-position: center;
+ background-size: .75em auto;
+ background-repeat: no-repeat
+ }
+
+[type=radio] {
+ border-radius: 50%
+}
+
+ [type=radio]:checked, [type=radio]:checked:active, [type=radio]:checked:focus {
+ --background-color: var(--primary-inverse);
+ border-width: .35em;
+ background-image: none
+ }
+
+[type=checkbox][role=switch] {
+ --background-color: var(--switch-background-color);
+ --border-color: var(--switch-background-color);
+ --color: var(--switch-color);
+ width: 2.25em;
+ height: 1.25em;
+ border: var(--border-width) solid var(--border-color);
+ border-radius: 1.25em;
+ background-color: var(--background-color);
+ line-height: 1.25em
+}
+
+ [type=checkbox][role=switch]:focus {
+ --background-color: var(--switch-background-color);
+ --border-color: var(--switch-background-color)
+ }
+
+ [type=checkbox][role=switch]:checked {
+ --background-color: var(--switch-checked-background-color);
+ --border-color: var(--switch-checked-background-color)
+ }
+
+ [type=checkbox][role=switch]:before {
+ display: block;
+ width: calc(1.25em - (var(--border-width) * 2));
+ height: 100%;
+ border-radius: 50%;
+ background-color: var(--color);
+ content: "";
+ transition: margin .1s ease-in-out
+ }
+
+ [type=checkbox][role=switch]:checked {
+ background-image: none
+ }
+
+ [type=checkbox][role=switch]:checked::before {
+ margin-left: calc(1.125em - var(--border-width));
+ -webkit-margin-start: calc(1.125em - var(--border-width));
+ margin-inline-start: calc(1.125em - var(--border-width))
+ }
+
+ [type=checkbox]:checked[aria-invalid=false], [type=checkbox][aria-invalid=false], [type=checkbox][role=switch]:checked[aria-invalid=false], [type=checkbox][role=switch][aria-invalid=false], [type=radio]:checked[aria-invalid=false], [type=radio][aria-invalid=false] {
+ --border-color: var(--form-element-valid-border-color)
+ }
+
+ [type=checkbox]:checked[aria-invalid=true], [type=checkbox][aria-invalid=true], [type=checkbox][role=switch]:checked[aria-invalid=true], [type=checkbox][role=switch][aria-invalid=true], [type=radio]:checked[aria-invalid=true], [type=radio][aria-invalid=true] {
+ --border-color: var(--form-element-invalid-border-color)
+ }
+
+[type=color]::-webkit-color-swatch-wrapper {
+ padding: 0
+}
+
+[type=color]::-moz-focus-inner {
+ padding: 0
+}
+
+[type=color]::-webkit-color-swatch {
+ border: 0;
+ border-radius: calc(var(--border-radius) * .5)
+}
+
+[type=color]::-moz-color-swatch {
+ border: 0;
+ border-radius: calc(var(--border-radius) * .5)
+}
+
+input:not([type=checkbox],[type=radio],[type=range],[type=file]):is([type=date],[type=datetime-local],[type=month],[type=time],[type=week]) {
+ --icon-position: 0.75rem;
+ --icon-width: 1rem;
+ padding-right: calc(var(--icon-width) + var(--icon-position));
+ background-image: var(--icon-date);
+ background-position: center right var(--icon-position);
+ background-size: var(--icon-width) auto;
+ background-repeat: no-repeat
+}
+
+input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=time] {
+ background-image: var(--icon-time)
+}
+
+[type=date]::-webkit-calendar-picker-indicator, [type=datetime-local]::-webkit-calendar-picker-indicator, [type=month]::-webkit-calendar-picker-indicator, [type=time]::-webkit-calendar-picker-indicator, [type=week]::-webkit-calendar-picker-indicator {
+ width: var(--icon-width);
+ margin-right: calc(var(--icon-width) * -1);
+ margin-left: var(--icon-position);
+ opacity: 0
+}
+
+[dir=rtl] :is([type=date],[type=datetime-local],[type=month],[type=time],[type=week]) {
+ text-align: right
+}
+
+@-moz-document url-prefix() {
+ [type=date], [type=datetime-local], [type=month], [type=time], [type=week] {
+ padding-right: var(--form-element-spacing-horizontal) !important;
+ background-image: none !important
+ }
+}
+
+[type=file] {
+ --color: var(--muted-color);
+ padding: calc(var(--form-element-spacing-vertical) * .5) 0;
+ border: 0;
+ border-radius: 0;
+ background: 0 0
+}
+
+ [type=file]::file-selector-button {
+ --background-color: var(--secondary);
+ --border-color: var(--secondary);
+ --color: var(--secondary-inverse);
+ margin-right: calc(var(--spacing)/ 2);
+ margin-left: 0;
+ -webkit-margin-start: 0;
+ margin-inline-start: 0;
+ -webkit-margin-end: calc(var(--spacing)/ 2);
+ margin-inline-end: calc(var(--spacing)/ 2);
+ padding: calc(var(--form-element-spacing-vertical) * .5) calc(var(--form-element-spacing-horizontal) * .5);
+ border: var(--border-width) solid var(--border-color);
+ border-radius: var(--border-radius);
+ outline: 0;
+ background-color: var(--background-color);
+ box-shadow: var(--box-shadow);
+ color: var(--color);
+ font-weight: var(--font-weight);
+ font-size: 1rem;
+ line-height: var(--line-height);
+ text-align: center;
+ cursor: pointer;
+ transition: background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)
+ }
+
+ [type=file]::file-selector-button:is(:hover,:active,:focus) {
+ --background-color: var(--secondary-hover);
+ --border-color: var(--secondary-hover)
+ }
+
+ [type=file]::-webkit-file-upload-button {
+ --background-color: var(--secondary);
+ --border-color: var(--secondary);
+ --color: var(--secondary-inverse);
+ margin-right: calc(var(--spacing)/ 2);
+ margin-left: 0;
+ -webkit-margin-start: 0;
+ margin-inline-start: 0;
+ -webkit-margin-end: calc(var(--spacing)/ 2);
+ margin-inline-end: calc(var(--spacing)/ 2);
+ padding: calc(var(--form-element-spacing-vertical) * .5) calc(var(--form-element-spacing-horizontal) * .5);
+ border: var(--border-width) solid var(--border-color);
+ border-radius: var(--border-radius);
+ outline: 0;
+ background-color: var(--background-color);
+ box-shadow: var(--box-shadow);
+ color: var(--color);
+ font-weight: var(--font-weight);
+ font-size: 1rem;
+ line-height: var(--line-height);
+ text-align: center;
+ cursor: pointer;
+ -webkit-transition: background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition);
+ transition: background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)
+ }
+
+ [type=file]::-webkit-file-upload-button:is(:hover,:active,:focus) {
+ --background-color: var(--secondary-hover);
+ --border-color: var(--secondary-hover)
+ }
+
+ [type=file]::-ms-browse {
+ --background-color: var(--secondary);
+ --border-color: var(--secondary);
+ --color: var(--secondary-inverse);
+ margin-right: calc(var(--spacing)/ 2);
+ margin-left: 0;
+ margin-inline-start: 0;
+ margin-inline-end: calc(var(--spacing)/ 2);
+ padding: calc(var(--form-element-spacing-vertical) * .5) calc(var(--form-element-spacing-horizontal) * .5);
+ border: var(--border-width) solid var(--border-color);
+ border-radius: var(--border-radius);
+ outline: 0;
+ background-color: var(--background-color);
+ box-shadow: var(--box-shadow);
+ color: var(--color);
+ font-weight: var(--font-weight);
+ font-size: 1rem;
+ line-height: var(--line-height);
+ text-align: center;
+ cursor: pointer;
+ -ms-transition: background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition);
+ transition: background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)
+ }
+
+ [type=file]::-ms-browse:is(:hover,:active,:focus) {
+ --background-color: var(--secondary-hover);
+ --border-color: var(--secondary-hover)
+ }
+
+[type=range] {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ width: 100%;
+ height: 1.25rem;
+ background: 0 0
+}
+
+ [type=range]::-webkit-slider-runnable-track {
+ width: 100%;
+ height: .25rem;
+ border-radius: var(--border-radius);
+ background-color: var(--range-border-color);
+ -webkit-transition: background-color var(--transition),box-shadow var(--transition);
+ transition: background-color var(--transition),box-shadow var(--transition)
+ }
+
+ [type=range]::-moz-range-track {
+ width: 100%;
+ height: .25rem;
+ border-radius: var(--border-radius);
+ background-color: var(--range-border-color);
+ -moz-transition: background-color var(--transition),box-shadow var(--transition);
+ transition: background-color var(--transition),box-shadow var(--transition)
+ }
+
+ [type=range]::-ms-track {
+ width: 100%;
+ height: .25rem;
+ border-radius: var(--border-radius);
+ background-color: var(--range-border-color);
+ -ms-transition: background-color var(--transition),box-shadow var(--transition);
+ transition: background-color var(--transition),box-shadow var(--transition)
+ }
+
+ [type=range]::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ width: 1.25rem;
+ height: 1.25rem;
+ margin-top: -.5rem;
+ border: 2px solid var(--range-thumb-border-color);
+ border-radius: 50%;
+ background-color: var(--range-thumb-color);
+ cursor: pointer;
+ -webkit-transition: background-color var(--transition),transform var(--transition);
+ transition: background-color var(--transition),transform var(--transition)
+ }
+
+ [type=range]::-moz-range-thumb {
+ -webkit-appearance: none;
+ width: 1.25rem;
+ height: 1.25rem;
+ margin-top: -.5rem;
+ border: 2px solid var(--range-thumb-border-color);
+ border-radius: 50%;
+ background-color: var(--range-thumb-color);
+ cursor: pointer;
+ -moz-transition: background-color var(--transition),transform var(--transition);
+ transition: background-color var(--transition),transform var(--transition)
+ }
+
+ [type=range]::-ms-thumb {
+ -webkit-appearance: none;
+ width: 1.25rem;
+ height: 1.25rem;
+ margin-top: -.5rem;
+ border: 2px solid var(--range-thumb-border-color);
+ border-radius: 50%;
+ background-color: var(--range-thumb-color);
+ cursor: pointer;
+ -ms-transition: background-color var(--transition),transform var(--transition);
+ transition: background-color var(--transition),transform var(--transition)
+ }
+
+ [type=range]:focus, [type=range]:hover {
+ --range-border-color: var(--range-active-border-color);
+ --range-thumb-color: var(--range-thumb-hover-color)
+ }
+
+ [type=range]:active {
+ --range-thumb-color: var(--range-thumb-active-color)
+ }
+
+ [type=range]:active::-webkit-slider-thumb {
+ transform: scale(1.25)
+ }
+
+ [type=range]:active::-moz-range-thumb {
+ transform: scale(1.25)
+ }
+
+ [type=range]:active::-ms-thumb {
+ transform: scale(1.25)
+ }
+
+input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search] {
+ -webkit-padding-start: calc(var(--form-element-spacing-horizontal) + 1.75rem);
+ padding-inline-start: calc(var(--form-element-spacing-horizontal) + 1.75rem);
+ border-radius: 5rem;
+ background-image: var(--icon-search);
+ background-position: center left 1.125rem;
+ background-size: 1rem auto;
+ background-repeat: no-repeat
+}
+
+ input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid] {
+ -webkit-padding-start: calc(var(--form-element-spacing-horizontal) + 1.75rem) !important;
+ padding-inline-start: calc(var(--form-element-spacing-horizontal) + 1.75rem) !important;
+ background-position: center left 1.125rem,center right .75rem
+ }
+
+ input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid=false] {
+ background-image: var(--icon-search),var(--icon-valid)
+ }
+
+ input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid=true] {
+ background-image: var(--icon-search),var(--icon-invalid)
+ }
+
+[type=search]::-webkit-search-cancel-button {
+ -webkit-appearance: none;
+ display: none
+}
+
+[dir=rtl] :where(input):not([type=checkbox],[type=radio],[type=range],[type=file])[type=search] {
+ background-position: center right 1.125rem
+}
+
+ [dir=rtl] :where(input):not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid] {
+ background-position: center right 1.125rem,center left .75rem
+ }
+
+:where(table) {
+ width: 100%;
+ border-collapse: collapse;
+ border-spacing: 0;
+ text-indent: 0
+}
+
+td, th {
+ padding: calc(var(--spacing)/ 2) var(--spacing);
+ border-bottom: var(--border-width) solid var(--table-border-color);
+ color: var(--color);
+ font-weight: var(--font-weight);
+ font-size: var(--font-size);
+ text-align: left;
+ text-align: start
+}
+
+tfoot td, tfoot th {
+ border-top: var(--border-width) solid var(--table-border-color);
+ border-bottom: 0
+}
+
+table[role=grid] tbody tr:nth-child(odd) {
+ background-color: var(--table-row-stripped-background-color)
+}
+
+code, kbd, pre, samp {
+ font-size: .875em;
+ font-family: var(--font-family)
+}
+
+pre {
+ -ms-overflow-style: scrollbar;
+ overflow: auto
+}
+
+code, kbd, pre {
+ border-radius: var(--border-radius);
+ background: var(--code-background-color);
+ color: var(--code-color);
+ font-weight: var(--font-weight);
+ line-height: initial
+}
+
+code, kbd {
+ display: inline-block;
+ padding: .375rem .5rem
+}
+
+pre {
+ display: block;
+ margin-bottom: var(--spacing);
+ overflow-x: auto
+}
+
+ pre > code {
+ display: block;
+ padding: var(--spacing);
+ background: 0 0;
+ font-size: 14px;
+ line-height: var(--line-height)
+ }
+
+code b {
+ color: var(--code-tag-color);
+ font-weight: var(--font-weight)
+}
+
+code i {
+ color: var(--code-property-color);
+ font-style: normal
+}
+
+code u {
+ color: var(--code-value-color);
+ text-decoration: none
+}
+
+code em {
+ color: var(--code-comment-color);
+ font-style: normal
+}
+
+kbd {
+ background-color: var(--code-kbd-background-color);
+ color: var(--code-kbd-color);
+ vertical-align: baseline
+}
+
+hr {
+ height: 0;
+ border: 0;
+ border-top: 1px solid var(--muted-border-color);
+ color: inherit
+}
+
+[hidden], template {
+ display: none !important
+}
+
+canvas {
+ display: inline-block
+}
+
+details {
+ display: block;
+ margin-bottom: var(--spacing);
+ padding-bottom: var(--spacing);
+ border-bottom: var(--border-width) solid var(--accordion-border-color)
+}
+
+ details summary {
+ line-height: 1rem;
+ list-style-type: none;
+ cursor: pointer;
+ transition: color var(--transition)
+ }
+
+ details summary:not([role]) {
+ color: var(--accordion-close-summary-color)
+ }
+
+ details summary::-webkit-details-marker {
+ display: none
+ }
+
+ details summary::marker {
+ display: none
+ }
+
+ details summary::-moz-list-bullet {
+ list-style-type: none
+ }
+
+ details summary::after {
+ display: block;
+ width: 1rem;
+ height: 1rem;
+ -webkit-margin-start: calc(var(--spacing,1rem) * 0.5);
+ margin-inline-start: calc(var(--spacing,1rem) * .5);
+ float: right;
+ transform: rotate(-90deg);
+ background-image: var(--icon-chevron);
+ background-position: right center;
+ background-size: 1rem auto;
+ background-repeat: no-repeat;
+ content: "";
+ transition: transform var(--transition)
+ }
+
+ details summary:focus {
+ outline: 0
+ }
+
+ details summary:focus:not([role=button]) {
+ color: var(--accordion-active-summary-color)
+ }
+
+ details summary[role=button] {
+ width: 100%;
+ text-align: left
+ }
+
+ details summary[role=button]::after {
+ height: calc(1rem * var(--line-height,1.5));
+ background-image: var(--icon-chevron-button)
+ }
+
+ details summary[role=button]:not(.outline).contrast::after {
+ background-image: var(--icon-chevron-button-inverse)
+ }
+
+ details[open] > summary {
+ margin-bottom: calc(var(--spacing))
+ }
+
+ details[open] > summary:not([role]):not(:focus) {
+ color: var(--accordion-open-summary-color)
+ }
+
+ details[open] > summary::after {
+ transform: rotate(0)
+ }
+
+[dir=rtl] details summary {
+ text-align: right
+}
+
+ [dir=rtl] details summary::after {
+ float: left;
+ background-position: left center
+ }
+
+article {
+ margin: var(--block-spacing-vertical) 0;
+ padding: var(--block-spacing-vertical) var(--block-spacing-horizontal);
+ border-radius: var(--border-radius);
+ background: var(--card-background-color);
+ box-shadow: var(--card-box-shadow)
+}
+
+ article > footer, article > header {
+ margin-right: calc(var(--block-spacing-horizontal) * -1);
+ margin-left: calc(var(--block-spacing-horizontal) * -1);
+ padding: calc(var(--block-spacing-vertical) * .66) var(--block-spacing-horizontal);
+ background-color: var(--card-sectionning-background-color)
+ }
+
+ article > header {
+ margin-top: calc(var(--block-spacing-vertical) * -1);
+ margin-bottom: var(--block-spacing-vertical);
+ border-bottom: var(--border-width) solid var(--card-border-color);
+ border-top-right-radius: var(--border-radius);
+ border-top-left-radius: var(--border-radius)
+ }
+
+ article > footer {
+ margin-top: var(--block-spacing-vertical);
+ margin-bottom: calc(var(--block-spacing-vertical) * -1);
+ border-top: var(--border-width) solid var(--card-border-color);
+ border-bottom-right-radius: var(--border-radius);
+ border-bottom-left-radius: var(--border-radius)
+ }
+
+:root {
+ --scrollbar-width: 0px
+}
+
+dialog {
+ display: flex;
+ z-index: 999;
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ align-items: center;
+ justify-content: center;
+ width: inherit;
+ min-width: 100%;
+ height: inherit;
+ min-height: 100%;
+ padding: var(--spacing);
+ border: 0;
+ -webkit-backdrop-filter: var(--modal-overlay-backdrop-filter);
+ backdrop-filter: var(--modal-overlay-backdrop-filter);
+ background-color: var(--modal-overlay-background-color);
+ color: var(--color)
+}
+
+ dialog article {
+ max-height: calc(100vh - var(--spacing) * 2);
+ overflow: auto
+ }
+
+@media (min-width:576px) {
+ dialog article {
+ max-width: 510px
+ }
+}
+
+@media (min-width:768px) {
+ dialog article {
+ max-width: 700px
+ }
+}
+
+dialog article > footer, dialog article > header {
+ padding: calc(var(--block-spacing-vertical) * .5) var(--block-spacing-horizontal)
+}
+
+ dialog article > header .close {
+ margin: 0;
+ margin-left: var(--spacing);
+ float: right
+ }
+
+dialog article > footer {
+ text-align: right
+}
+
+ dialog article > footer [role=button] {
+ margin-bottom: 0
+ }
+
+ dialog article > footer [role=button]:not(:first-of-type) {
+ margin-left: calc(var(--spacing) * .5)
+ }
+
+dialog article p:last-of-type {
+ margin: 0
+}
+
+dialog article .close {
+ display: block;
+ width: 1rem;
+ height: 1rem;
+ margin-top: calc(var(--block-spacing-vertical) * -.5);
+ margin-bottom: var(--typography-spacing-vertical);
+ margin-left: auto;
+ background-image: var(--icon-close);
+ background-position: center;
+ background-size: auto 1rem;
+ background-repeat: no-repeat;
+ opacity: .5;
+ transition: opacity var(--transition)
+}
+
+ dialog article .close:is([aria-current],:hover,:active,:focus) {
+ opacity: 1
+ }
+
+dialog:not([open]), dialog[open=false] {
+ display: none
+}
+
+.modal-is-open {
+ padding-right: var(--scrollbar-width,0);
+ overflow: hidden;
+ pointer-events: none;
+ touch-action: none
+}
+
+ .modal-is-open dialog {
+ pointer-events: auto
+ }
+
+:where(.modal-is-opening,.modal-is-closing) dialog, :where(.modal-is-opening,.modal-is-closing) dialog > article {
+ animation-duration: .2s;
+ animation-timing-function: ease-in-out;
+ animation-fill-mode: both
+}
+
+:where(.modal-is-opening,.modal-is-closing) dialog {
+ animation-duration: .8s;
+ animation-name: modal-overlay
+}
+
+ :where(.modal-is-opening,.modal-is-closing) dialog > article {
+ animation-delay: .2s;
+ animation-name: modal
+ }
+
+.modal-is-closing dialog, .modal-is-closing dialog > article {
+ animation-delay: 0s;
+ animation-direction: reverse
+}
+
+@keyframes modal-overlay {
+ from {
+ -webkit-backdrop-filter: none;
+ backdrop-filter: none;
+ background-color: transparent
+ }
+}
+
+@keyframes modal {
+ from {
+ transform: translateY(-100%);
+ opacity: 0
+ }
+}
+
+:where(nav li)::before {
+ float: left;
+ content: ""
+}
+
+nav, nav ul {
+ display: flex
+}
+
+nav {
+ justify-content: space-between
+}
+
+ nav ol, nav ul {
+ align-items: center;
+ margin-bottom: 0;
+ padding: 0;
+ list-style: none
+ }
+
+ nav ol:first-of-type, nav ul:first-of-type {
+ margin-left: calc(var(--nav-element-spacing-horizontal) * -1)
+ }
+
+ nav ol:last-of-type, nav ul:last-of-type {
+ margin-right: calc(var(--nav-element-spacing-horizontal) * -1)
+ }
+
+ nav li {
+ display: inline-block;
+ margin: 0;
+ padding: var(--nav-element-spacing-vertical) var(--nav-element-spacing-horizontal)
+ }
+
+ nav li > * {
+ --spacing: 0
+ }
+
+ nav :where(a,[role=link]) {
+ display: inline-block;
+ margin: calc(var(--nav-link-spacing-vertical) * -1) calc(var(--nav-link-spacing-horizontal) * -1);
+ padding: var(--nav-link-spacing-vertical) var(--nav-link-spacing-horizontal);
+ border-radius: var(--border-radius);
+ text-decoration: none
+ }
+
+ nav :where(a,[role=link]):is([aria-current],:hover,:active,:focus) {
+ text-decoration: none
+ }
+
+ nav[aria-label=breadcrumb] {
+ align-items: center;
+ justify-content: start
+ }
+
+ nav[aria-label=breadcrumb] ul li:not(:first-child) {
+ -webkit-margin-start: var(--nav-link-spacing-horizontal);
+ margin-inline-start: var(--nav-link-spacing-horizontal)
+ }
+
+ nav[aria-label=breadcrumb] ul li:not(:last-child) ::after {
+ position: absolute;
+ width: calc(var(--nav-link-spacing-horizontal) * 2);
+ -webkit-margin-start: calc(var(--nav-link-spacing-horizontal)/ 2);
+ margin-inline-start: calc(var(--nav-link-spacing-horizontal)/ 2);
+ content: "/";
+ color: var(--muted-color);
+ text-align: center
+ }
+
+ nav[aria-label=breadcrumb] a[aria-current] {
+ background-color: transparent;
+ color: inherit;
+ text-decoration: none;
+ pointer-events: none
+ }
+
+ nav [role=button] {
+ margin-right: inherit;
+ margin-left: inherit;
+ padding: var(--nav-link-spacing-vertical) var(--nav-link-spacing-horizontal)
+ }
+
+aside li, aside nav, aside ol, aside ul {
+ display: block
+}
+
+aside li {
+ padding: calc(var(--nav-element-spacing-vertical) * .5) var(--nav-element-spacing-horizontal)
+}
+
+ aside li a {
+ display: block
+ }
+
+ aside li [role=button] {
+ margin: inherit
+ }
+
+[dir=rtl] nav[aria-label=breadcrumb] ul li:not(:last-child) ::after {
+ content: "\\"
+}
+
+progress {
+ display: inline-block;
+ vertical-align: baseline
+}
+
+progress {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ display: inline-block;
+ appearance: none;
+ width: 100%;
+ height: .5rem;
+ margin-bottom: calc(var(--spacing) * .5);
+ overflow: hidden;
+ border: 0;
+ border-radius: var(--border-radius);
+ background-color: var(--progress-background-color);
+ color: var(--progress-color)
+}
+
+ progress::-webkit-progress-bar {
+ border-radius: var(--border-radius);
+ background: 0 0
+ }
+
+ progress[value]::-webkit-progress-value {
+ background-color: var(--progress-color)
+ }
+
+ progress::-moz-progress-bar {
+ background-color: var(--progress-color)
+ }
+
+@media (prefers-reduced-motion:no-preference) {
+ progress:indeterminate {
+ background: var(--progress-background-color) linear-gradient(to right,var(--progress-color) 30%,var(--progress-background-color) 30%) top left/150% 150% no-repeat;
+ animation: progress-indeterminate 1s linear infinite
+ }
+
+ progress:indeterminate[value]::-webkit-progress-value {
+ background-color: transparent
+ }
+
+ progress:indeterminate::-moz-progress-bar {
+ background-color: transparent
+ }
+}
+
+@media (prefers-reduced-motion:no-preference) {
+ [dir=rtl] progress:indeterminate {
+ animation-direction: reverse
+ }
+}
+
+@keyframes progress-indeterminate {
+ 0% {
+ background-position: 200% 0
+ }
+
+ 100% {
+ background-position: -200% 0
+ }
+}
+
+details[role=list], li[role=list] {
+ position: relative
+}
+
+ details[role=list] summary + ul, li[role=list] > ul {
+ display: flex;
+ z-index: 99;
+ position: absolute;
+ top: auto;
+ right: 0;
+ left: 0;
+ flex-direction: column;
+ margin: 0;
+ padding: 0;
+ border: var(--border-width) solid var(--dropdown-border-color);
+ border-radius: var(--border-radius);
+ border-top-right-radius: 0;
+ border-top-left-radius: 0;
+ background-color: var(--dropdown-background-color);
+ box-shadow: var(--card-box-shadow);
+ color: var(--dropdown-color);
+ white-space: nowrap
+ }
+
+ details[role=list] summary + ul li, li[role=list] > ul li {
+ width: 100%;
+ margin-bottom: 0;
+ padding: calc(var(--form-element-spacing-vertical) * .5) var(--form-element-spacing-horizontal);
+ list-style: none
+ }
+
+ details[role=list] summary + ul li:first-of-type, li[role=list] > ul li:first-of-type {
+ margin-top: calc(var(--form-element-spacing-vertical) * .5)
+ }
+
+ details[role=list] summary + ul li:last-of-type, li[role=list] > ul li:last-of-type {
+ margin-bottom: calc(var(--form-element-spacing-vertical) * .5)
+ }
+
+ details[role=list] summary + ul li a, li[role=list] > ul li a {
+ display: block;
+ margin: calc(var(--form-element-spacing-vertical) * -.5) calc(var(--form-element-spacing-horizontal) * -1);
+ padding: calc(var(--form-element-spacing-vertical) * .5) var(--form-element-spacing-horizontal);
+ overflow: hidden;
+ color: var(--dropdown-color);
+ text-decoration: none;
+ text-overflow: ellipsis
+ }
+
+ details[role=list] summary + ul li a:hover, li[role=list] > ul li a:hover {
+ background-color: var(--dropdown-hover-background-color)
+ }
+
+ details[role=list] summary::after, li[role=list] > a::after {
+ display: block;
+ width: 1rem;
+ height: calc(1rem * var(--line-height,1.5));
+ -webkit-margin-start: 0.5rem;
+ margin-inline-start: .5rem;
+ float: right;
+ transform: rotate(0);
+ background-position: right center;
+ background-size: 1rem auto;
+ background-repeat: no-repeat;
+ content: ""
+ }
+
+details[role=list] {
+ padding: 0;
+ border-bottom: none
+}
+
+ details[role=list] summary {
+ margin-bottom: 0
+ }
+
+ details[role=list] summary:not([role]) {
+ height: calc(1rem * var(--line-height) + var(--form-element-spacing-vertical) * 2 + var(--border-width) * 2);
+ padding: var(--form-element-spacing-vertical) var(--form-element-spacing-horizontal);
+ border: var(--border-width) solid var(--form-element-border-color);
+ border-radius: var(--border-radius);
+ background-color: var(--form-element-background-color);
+ color: var(--form-element-placeholder-color);
+ line-height: inherit;
+ cursor: pointer;
+ transition: background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)
+ }
+
+ details[role=list] summary:not([role]):active, details[role=list] summary:not([role]):focus {
+ border-color: var(--form-element-active-border-color);
+ background-color: var(--form-element-active-background-color)
+ }
+
+ details[role=list] summary:not([role]):focus {
+ box-shadow: 0 0 0 var(--outline-width) var(--form-element-focus-color)
+ }
+
+ details[role=list][open] summary {
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0
+ }
+
+ details[role=list][open] summary::before {
+ display: block;
+ z-index: 1;
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ background: 0 0;
+ content: "";
+ cursor: default
+ }
+
+nav details[role=list] summary, nav li[role=list] a {
+ display: flex;
+ direction: ltr
+}
+
+ nav details[role=list] summary + ul, nav li[role=list] > ul {
+ min-width: -moz-fit-content;
+ min-width: fit-content;
+ border-radius: var(--border-radius)
+ }
+
+ nav details[role=list] summary + ul li a, nav li[role=list] > ul li a {
+ border-radius: 0
+ }
+
+ nav details[role=list] summary, nav details[role=list] summary:not([role]) {
+ height: auto;
+ padding: var(--nav-link-spacing-vertical) var(--nav-link-spacing-horizontal)
+ }
+
+nav details[role=list][open] summary {
+ border-radius: var(--border-radius)
+}
+
+nav details[role=list] summary + ul {
+ margin-top: var(--outline-width);
+ -webkit-margin-start: 0;
+ margin-inline-start: 0
+}
+
+nav details[role=list] summary[role=link] {
+ margin-bottom: calc(var(--nav-link-spacing-vertical) * -1);
+ line-height: var(--line-height)
+}
+
+ nav details[role=list] summary[role=link] + ul {
+ margin-top: calc(var(--nav-link-spacing-vertical) + var(--outline-width));
+ -webkit-margin-start: calc(var(--nav-link-spacing-horizontal) * -1);
+ margin-inline-start: calc(var(--nav-link-spacing-horizontal) * -1)
+ }
+
+li[role=list] a:active ~ ul, li[role=list] a:focus ~ ul, li[role=list]:hover > ul {
+ display: flex
+}
+
+li[role=list] > ul {
+ display: none;
+ margin-top: calc(var(--nav-link-spacing-vertical) + var(--outline-width));
+ -webkit-margin-start: calc(var(--nav-element-spacing-horizontal) - var(--nav-link-spacing-horizontal));
+ margin-inline-start: calc(var(--nav-element-spacing-horizontal) - var(--nav-link-spacing-horizontal))
+}
+
+li[role=list] > a::after {
+ background-image: var(--icon-chevron)
+}
+
+label > details[role=list] {
+ margin-top: calc(var(--spacing) * .25);
+ margin-bottom: var(--spacing)
+}
+
+[aria-busy=true] {
+ cursor: progress
+}
+
+ [aria-busy=true]:not(input,select,textarea,html)::before {
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+ border: .1875em solid currentColor;
+ border-radius: 1em;
+ border-right-color: transparent;
+ content: "";
+ vertical-align: text-bottom;
+ vertical-align: -.125em;
+ animation: spinner .75s linear infinite;
+ opacity: var(--loading-spinner-opacity)
+ }
+
+ [aria-busy=true]:not(input,select,textarea,html):not(:empty)::before {
+ margin-right: calc(var(--spacing) * .5);
+ margin-left: 0;
+ -webkit-margin-start: 0;
+ margin-inline-start: 0;
+ -webkit-margin-end: calc(var(--spacing) * .5);
+ margin-inline-end: calc(var(--spacing) * .5)
+ }
+
+ [aria-busy=true]:not(input,select,textarea,html):empty {
+ text-align: center
+ }
+
+a[aria-busy=true], button[aria-busy=true], input[type=button][aria-busy=true], input[type=reset][aria-busy=true], input[type=submit][aria-busy=true] {
+ pointer-events: none
+}
+
+@keyframes spinner {
+ to {
+ transform: rotate(360deg)
+ }
+}
+
+[data-tooltip] {
+ position: relative
+}
+
+ [data-tooltip]:not(a,button,input) {
+ border-bottom: 1px dotted;
+ text-decoration: none;
+ cursor: help
+ }
+
+ [data-tooltip]::after, [data-tooltip]::before, [data-tooltip][data-placement=top]::after, [data-tooltip][data-placement=top]::before {
+ display: block;
+ z-index: 99;
+ position: absolute;
+ bottom: 100%;
+ left: 50%;
+ padding: .25rem .5rem;
+ overflow: hidden;
+ transform: translate(-50%,-.25rem);
+ border-radius: var(--border-radius);
+ background: var(--tooltip-background-color);
+ content: attr(data-tooltip);
+ color: var(--tooltip-color);
+ font-style: normal;
+ font-weight: var(--font-weight);
+ font-size: .875rem;
+ text-decoration: none;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ opacity: 0;
+ pointer-events: none
+ }
+
+ [data-tooltip]::after, [data-tooltip][data-placement=top]::after {
+ padding: 0;
+ transform: translate(-50%,0);
+ border-top: .3rem solid;
+ border-right: .3rem solid transparent;
+ border-left: .3rem solid transparent;
+ border-radius: 0;
+ background-color: transparent;
+ content: "";
+ color: var(--tooltip-background-color)
+ }
+
+ [data-tooltip][data-placement=bottom]::after, [data-tooltip][data-placement=bottom]::before {
+ top: 100%;
+ bottom: auto;
+ transform: translate(-50%,.25rem)
+ }
+
+ [data-tooltip][data-placement=bottom]:after {
+ transform: translate(-50%,-.3rem);
+ border: .3rem solid transparent;
+ border-bottom: .3rem solid
+ }
+
+ [data-tooltip][data-placement=left]::after, [data-tooltip][data-placement=left]::before {
+ top: 50%;
+ right: 100%;
+ bottom: auto;
+ left: auto;
+ transform: translate(-.25rem,-50%)
+ }
+
+ [data-tooltip][data-placement=left]:after {
+ transform: translate(.3rem,-50%);
+ border: .3rem solid transparent;
+ border-left: .3rem solid
+ }
+
+ [data-tooltip][data-placement=right]::after, [data-tooltip][data-placement=right]::before {
+ top: 50%;
+ right: auto;
+ bottom: auto;
+ left: 100%;
+ transform: translate(.25rem,-50%)
+ }
+
+ [data-tooltip][data-placement=right]:after {
+ transform: translate(-.3rem,-50%);
+ border: .3rem solid transparent;
+ border-right: .3rem solid
+ }
+
+ [data-tooltip]:focus::after, [data-tooltip]:focus::before, [data-tooltip]:hover::after, [data-tooltip]:hover::before {
+ opacity: 1
+ }
+
+@media (hover:hover) and (pointer:fine) {
+ [data-tooltip]:hover::after, [data-tooltip]:hover::before, [data-tooltip][data-placement=bottom]:focus::after, [data-tooltip][data-placement=bottom]:focus::before, [data-tooltip][data-placement=bottom]:hover [data-tooltip]:focus::after, [data-tooltip][data-placement=bottom]:hover [data-tooltip]:focus::before {
+ animation-duration: .2s;
+ animation-name: tooltip-slide-top
+ }
+
+ [data-tooltip]:hover::after, [data-tooltip][data-placement=bottom]:focus::after, [data-tooltip][data-placement=bottom]:hover [data-tooltip]:focus::after {
+ animation-name: tooltip-caret-slide-top
+ }
+
+ [data-tooltip][data-placement=bottom]:focus::after, [data-tooltip][data-placement=bottom]:focus::before, [data-tooltip][data-placement=bottom]:hover::after, [data-tooltip][data-placement=bottom]:hover::before {
+ animation-duration: .2s;
+ animation-name: tooltip-slide-bottom
+ }
+
+ [data-tooltip][data-placement=bottom]:focus::after, [data-tooltip][data-placement=bottom]:hover::after {
+ animation-name: tooltip-caret-slide-bottom
+ }
+
+ [data-tooltip][data-placement=left]:focus::after, [data-tooltip][data-placement=left]:focus::before, [data-tooltip][data-placement=left]:hover::after, [data-tooltip][data-placement=left]:hover::before {
+ animation-duration: .2s;
+ animation-name: tooltip-slide-left
+ }
+
+ [data-tooltip][data-placement=left]:focus::after, [data-tooltip][data-placement=left]:hover::after {
+ animation-name: tooltip-caret-slide-left
+ }
+
+ [data-tooltip][data-placement=right]:focus::after, [data-tooltip][data-placement=right]:focus::before, [data-tooltip][data-placement=right]:hover::after, [data-tooltip][data-placement=right]:hover::before {
+ animation-duration: .2s;
+ animation-name: tooltip-slide-right
+ }
+
+ [data-tooltip][data-placement=right]:focus::after, [data-tooltip][data-placement=right]:hover::after {
+ animation-name: tooltip-caret-slide-right
+ }
+}
+
+@keyframes tooltip-slide-top {
+ from {
+ transform: translate(-50%,.75rem);
+ opacity: 0
+ }
+
+ to {
+ transform: translate(-50%,-.25rem);
+ opacity: 1
+ }
+}
+
+@keyframes tooltip-caret-slide-top {
+ from {
+ opacity: 0
+ }
+
+ 50% {
+ transform: translate(-50%,-.25rem);
+ opacity: 0
+ }
+
+ to {
+ transform: translate(-50%,0);
+ opacity: 1
+ }
+}
+
+@keyframes tooltip-slide-bottom {
+ from {
+ transform: translate(-50%,-.75rem);
+ opacity: 0
+ }
+
+ to {
+ transform: translate(-50%,.25rem);
+ opacity: 1
+ }
+}
+
+@keyframes tooltip-caret-slide-bottom {
+ from {
+ opacity: 0
+ }
+
+ 50% {
+ transform: translate(-50%,-.5rem);
+ opacity: 0
+ }
+
+ to {
+ transform: translate(-50%,-.3rem);
+ opacity: 1
+ }
+}
+
+@keyframes tooltip-slide-left {
+ from {
+ transform: translate(.75rem,-50%);
+ opacity: 0
+ }
+
+ to {
+ transform: translate(-.25rem,-50%);
+ opacity: 1
+ }
+}
+
+@keyframes tooltip-caret-slide-left {
+ from {
+ opacity: 0
+ }
+
+ 50% {
+ transform: translate(.05rem,-50%);
+ opacity: 0
+ }
+
+ to {
+ transform: translate(.3rem,-50%);
+ opacity: 1
+ }
+}
+
+@keyframes tooltip-slide-right {
+ from {
+ transform: translate(-.75rem,-50%);
+ opacity: 0
+ }
+
+ to {
+ transform: translate(.25rem,-50%);
+ opacity: 1
+ }
+}
+
+@keyframes tooltip-caret-slide-right {
+ from {
+ opacity: 0
+ }
+
+ 50% {
+ transform: translate(-.05rem,-50%);
+ opacity: 0
+ }
+
+ to {
+ transform: translate(-.3rem,-50%);
+ opacity: 1
+ }
+}
+
+[aria-controls] {
+ cursor: pointer
+}
+
+[aria-disabled=true], [disabled] {
+ cursor: not-allowed
+}
+
+[aria-hidden=false][hidden] {
+ display: initial
+}
+
+ [aria-hidden=false][hidden]:not(:focus) {
+ clip: rect(0,0,0,0);
+ position: absolute
+ }
+
+[tabindex], a, area, button, input, label, select, summary, textarea {
+ -ms-touch-action: manipulation
+}
+
+[dir=rtl] {
+ direction: rtl
+}
+
+@media (prefers-reduced-motion:reduce) {
+ :not([aria-busy=true]), :not([aria-busy=true])::after, :not([aria-busy=true])::before {
+ background-attachment: initial !important;
+ animation-duration: 1ms !important;
+ animation-delay: -1ms !important;
+ animation-iteration-count: 1 !important;
+ scroll-behavior: auto !important;
+ transition-delay: 0s !important;
+ transition-duration: 0s !important
+ }
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/remoteview.html b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/remoteview.html
new file mode 100644
index 0000000..30a61c2
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/remoteview.html
@@ -0,0 +1 @@
+PrometheOS
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/remoteview.js b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/remoteview.js
new file mode 100644
index 0000000..d556f13
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/remoteview.js
@@ -0,0 +1 @@
+async function screenshot(){await fetch("http://192.168.1.66/api/screenshot").catch(()=>{content.innerHTML="Failed to connect."}).then(n=>n.blob()).then(n=>{var r=window.URL.createObjectURL(n),t=document.createElement("img");t.src=r;t.alt="Screenshot";t.style="max-width: 100%; height: auto";const i=document.getElementById("content");i.innerHTML="";i.appendChild(t)})}window.onload=function(){screenshot()};
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/remove.html b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/remove.html
new file mode 100644
index 0000000..0329b9f
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/remove.html
@@ -0,0 +1 @@
+PrometheOS
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/remove.js b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/remove.js
new file mode 100644
index 0000000..982da2a
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSPacker/bundle/remove.js
@@ -0,0 +1,35 @@
+window.onload = function () {
+ getBankInfo();
+};
+
+async function getBankInfo()
+{
+ await fetch("http://192.168.1.66/api/bankinfo.json").then(async response => {
+
+ const json = await response.json();
+
+ let contentBody = "";
+ for (let i = 0; i < json.length; i++) {
+ if (json[i].slots > 0) {
+ contentBody += "
";
+ }
+ }
+ let content = document.getElementById("content");
+ content.innerHTML = contentBody == "" ? "No items found." : contentBody;
+
+ }).catch(error => {
+
+ let content = document.getElementById("content");
+ content.innerHTML = "Failed to connect."
+
+ });
+}
+
+async function removeBank(id)
+{
+ await fetch("http://192.168.1.66/api/removebank?" + id).then(() => {
+ getBankInfo();
+ }).catch(error => {
+ content.innerHTML = "Failed to connect."
+ });
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSUtility.sln b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSUtility.sln
new file mode 100644
index 0000000..3802ec4
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSUtility.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.7.34031.279
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PrometheOSWeb", "PrometheOSWeb\PrometheOSWeb.csproj", "{9349C526-499C-451B-B23C-A7F69E0AD300}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PrometheOSPacker", "PrometheOSPacker\PrometheOSPacker.csproj", "{D7989A53-A931-4EB4-9E07-93152E01E701}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {9349C526-499C-451B-B23C-A7F69E0AD300}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9349C526-499C-451B-B23C-A7F69E0AD300}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9349C526-499C-451B-B23C-A7F69E0AD300}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9349C526-499C-451B-B23C-A7F69E0AD300}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D7989A53-A931-4EB4-9E07-93152E01E701}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D7989A53-A931-4EB4-9E07-93152E01E701}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D7989A53-A931-4EB4-9E07-93152E01E701}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D7989A53-A931-4EB4-9E07-93152E01E701}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {C911CF43-768E-487C-81BB-34D4FAF94C2B}
+ EndGlobalSection
+EndGlobal
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/Program.cs b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/Program.cs
new file mode 100644
index 0000000..a228ed5
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/Program.cs
@@ -0,0 +1,30 @@
+namespace PrometheOSWeb
+{
+ internal class Program
+ {
+ static void Main(string[] args)
+ {
+ var builder = WebApplication.CreateBuilder(args);
+
+ // Add services to the container.
+ builder.Services.AddRazorPages();
+
+ var app = builder.Build();
+
+ // Configure the HTTP request pipeline.
+ if (!app.Environment.IsDevelopment())
+ {
+ app.UseExceptionHandler("/Error");
+ }
+ app.UseStaticFiles();
+
+ app.UseRouting();
+
+ app.UseAuthorization();
+
+ app.MapRazorPages();
+
+ app.Run();
+ }
+ }
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/PrometheOSWeb.csproj b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/PrometheOSWeb.csproj
new file mode 100644
index 0000000..c78c9c7
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/PrometheOSWeb.csproj
@@ -0,0 +1,9 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/Properties/launchSettings.json b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/Properties/launchSettings.json
new file mode 100644
index 0000000..3008e73
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/Properties/launchSettings.json
@@ -0,0 +1,30 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:38829",
+ "launchUrl": "index.html",
+ "sslPort": 0
+ }
+ },
+ "profiles": {
+ "PrometheOSWeb": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "http://localhost:5190",
+ "launchUrl": "index.html",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/appsettings.Development.json b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/appsettings.Development.json
new file mode 100644
index 0000000..770d3e9
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "DetailedErrors": true,
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/appsettings.json b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/appsettings.json
new file mode 100644
index 0000000..10f68b8
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/appsettings.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/cerbiosini.html b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/cerbiosini.html
new file mode 100644
index 0000000..79e0c6a
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/cerbiosini.html
@@ -0,0 +1,30 @@
+
+
+
+
+
+ PrometheOS
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/cerbiosini.js b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/cerbiosini.js
new file mode 100644
index 0000000..16e1f0a
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/cerbiosini.js
@@ -0,0 +1,61 @@
+window.onload = function () {
+ getCerbiosIni();
+};
+
+async function getCerbiosIni()
+{
+ await fetch("http://192.168.1.66/api/cerbiosini").then(async response => {
+
+ const reader = response.body.getReader();
+ const decoder = new TextDecoder("utf-8");
+
+ let body = '';
+
+ while (true)
+ {
+ const { done, value } = await reader.read();
+ if (done)
+ {
+ break;
+ }
+ const chunk = decoder.decode(value, { stream: true });
+ body += chunk;
+ }
+
+ let contentBody = "";
+ contentBody += "
";
+ let content = document.getElementById("content");
+ content.innerHTML = contentBody;
+
+ }).catch(error => {
+
+ let content = document.getElementById("content");
+ content.innerHTML = "Failed to connect."
+
+ });
+}
+
+async function setCerbiosIni()
+{
+ let content = document.getElementById("cerbiosini");
+
+ var data = new FormData();
+ data.append('body', content.innerText);
+ await fetch("http://192.168.1.66/api/cerbiosini", {
+ method: 'POST',
+ body: data
+ }).then(response => {
+ if (response.status == 200) {
+ window.location.href = "/index.html";
+ } else {
+ uploadFailure();
+ }
+ }).catch(() => {
+ uploadFailure()
+ }
+ );
+}
+
+function uploadFailure() {
+ alert("Upload failed.");
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/download.html b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/download.html
new file mode 100644
index 0000000..f482098
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/download.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+ PrometheOS
+
+
+
+
+
+
+
+
+
+
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/download.js b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/download.js
new file mode 100644
index 0000000..4698180
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/download.js
@@ -0,0 +1,37 @@
+window.onload = function () {
+ getBankInfo();
+};
+
+async function getBankInfo() {
+ await fetch("http://192.168.1.66/api/bankinfo.json").then(async response => {
+
+ const json = await response.json();
+
+ let contentBody = "";
+ for (let i = 0; i < json.length; i++) {
+ if (json[i].slots > 0) {
+ contentBody += "
";
+ }
+ }
+ let content = document.getElementById("content");
+ content.innerHTML = contentBody == "" ? "No items found." : contentBody;
+ }).catch(error => {
+ let content = document.getElementById("content");
+ content.innerHTML = "Failed to connect."
+ });
+}
+
+async function downloadBank(id, name)
+{
+ await fetch("http://192.168.1.66/api/downloadbank?" + id).catch(error => {
+ content.innerHTML = "Failed to connect."
+ }).then(response => response.blob()).then(blob => {
+ var url = window.URL.createObjectURL(blob);
+ var a = document.createElement('a');
+ a.href = url;
+ a.download = name;
+ document.body.appendChild(a);
+ a.click();
+ a.remove();
+ });
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/downloads.html b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/downloads.html
new file mode 100644
index 0000000..a1dd08e
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/downloads.html
@@ -0,0 +1,37 @@
+
+
+
+
+
+ PrometheOS
+
+
+
+
+
+
+
+
+
+
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/downloads.js b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/downloads.js
new file mode 100644
index 0000000..ffefdfa
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/downloads.js
@@ -0,0 +1,27 @@
+async function downloadEeprom() {
+ await fetch("http://192.168.1.66/api/downloadeeprom").catch(error => {
+ content.innerHTML = "Failed to connect."
+ }).then(response => response.blob()).then(blob => {
+ var url = window.URL.createObjectURL(blob);
+ var a = document.createElement('a');
+ a.href = url;
+ a.download = "EEPROM.bin";
+ document.body.appendChild(a);
+ a.click();
+ a.remove();
+ });
+}
+
+async function downloadPrometheOS(id, name) {
+ await fetch("http://192.168.1.66/api/downloadprom").catch(error => {
+ content.innerHTML = "Failed to connect."
+ }).then(response => response.blob()).then(blob => {
+ var url = window.URL.createObjectURL(blob);
+ var a = document.createElement('a');
+ a.href = url;
+ a.download = "PrometheOS.bin";
+ document.body.appendChild(a);
+ a.click();
+ a.remove();
+ });
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/favicon.ico b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/favicon.ico
new file mode 100644
index 0000000..f4fd3c8
Binary files /dev/null and b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/favicon.ico differ
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/flash.html b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/flash.html
new file mode 100644
index 0000000..393fd96
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/flash.html
@@ -0,0 +1,56 @@
+
+
+
+
+
+ PrometheOS
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/flash.js b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/flash.js
new file mode 100644
index 0000000..ead4386
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/flash.js
@@ -0,0 +1,129 @@
+let ledColorState = 0;
+
+window.onload = function () {
+ refreshFileInfo();
+};
+
+function getFileSize()
+{
+ const file = document.getElementById("file");
+ if (file.value == "") {
+ return -1;
+ }
+ const fileSize = file.files[0].size;
+ if (fileSize == 0) {
+ return -1;
+ } else if (fileSize % (256 * 1024) != 0) {
+ return -1;
+ } else if (fileSize > (1024 * 1024)) {
+ return -1;
+ }
+ return fileSize;
+}
+
+async function refreshFileInfo()
+{
+ const file = document.getElementById("file");
+ if (file.value != "") {
+ const name = document.getElementById("name");
+ name.value = file.files[0].name.substring(0, 40);
+ }
+
+ await fetch("http://192.168.1.66/api/freeslots.json").then(async response => {
+
+ const json = await response.json();
+ const freeSlots = document.getElementById("freeSlots");
+ freeSlots.textContent = json["freeslots"];
+
+ const upload = document.getElementById("upload");
+ const slotsNeeeded = document.getElementById("slotsNeeded");
+ const fileSize = getFileSize();
+
+ if (fileSize < 0) {
+ upload.setAttribute("disabled", "disabled");
+ slotsNeeeded.textContent = "NA";
+ }
+ else
+ {
+ const slotsNeededValue = fileSize / (256 * 1024);
+ slotsNeeeded.textContent = slotsNeededValue;
+ if (slotsNeededValue > json["freeslots"]) {
+ upload.setAttribute("disabled", "disabled");
+ } else {
+ upload.removeAttribute("disabled");
+ }
+ }
+
+ }).catch(error => {
+ //
+ });
+}
+
+function setLedColor(ledColor)
+{
+ ledColorState = ledColor;
+
+ let ledColorText = document.getElementById("ledColor");
+ switch (ledColor) {
+ case 1:
+ ledColorText.textContent = "Red";
+ break;
+ case 2:
+ ledColorText.textContent = "Green";
+ break;
+ case 3:
+ ledColorText.textContent = "Yellow";
+ break;
+ case 4:
+ ledColorText.textContent = "Blue";
+ break;
+ case 5:
+ ledColorText.textContent = "Purple";
+ break;
+ case 6:
+ ledColorText.textContent = "Turquoise";
+ break;
+ case 7:
+ ledColorText.textContent = "White";
+ break;
+ default:
+ ledColorText.textContent = "Off";
+ }
+}
+
+async function upload()
+{
+ const upload = document.getElementById("upload");
+ upload.setAttribute("disabled", "disabled");
+ const file = document.getElementById("file");
+ file.setAttribute("disabled", "disabled");
+
+ const name = document.getElementById("name");
+
+ var data = new FormData();
+ data.append('file', file.files[0]);
+ data.append('body', "{\"ledColor\":" + ledColorState + ",\"bankName\":\"" + name.value + "\"}");
+ await fetch("http://192.168.1.66/api/upload", {
+ method: 'POST',
+ body: data
+ }).then(response => {
+ if (response.status == 200) {
+ window.location.href = "/index.html";
+ } else {
+ uploadFailure();
+ }
+ }).catch(() => {
+ uploadFailure()
+ }
+ );
+
+}
+
+function uploadFailure()
+{
+ alert("Upload failed.");
+ let upload = document.getElementById("upload");
+ upload.removeAttribute("disabled");
+ let file = document.getElementById("file");
+ file.removeAttribute("disabled");
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/index.html b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/index.html
new file mode 100644
index 0000000..12a0743
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/index.html
@@ -0,0 +1,57 @@
+
+
+
+
+
+ PrometheOS
+
+
+
+
+
+
+
+
+
+
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/index.js b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/index.js
new file mode 100644
index 0000000..1cdb6fa
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/index.js
@@ -0,0 +1,19 @@
+async function screenshot() {
+ await fetch("http://192.168.1.66/api/screenshot").catch(error => {
+ content.innerHTML = "Failed to connect."
+ }).then(response => response.blob()).then(blob => {
+ var url = window.URL.createObjectURL(blob);
+ var a = document.createElement('a');
+ a.href = url;
+ a.download = "screenshot.png";
+ document.body.appendChild(a);
+ a.click();
+ a.remove();
+ });
+}
+async function reboot() {
+ await fetch("http://192.168.1.66/api/reboot");
+}
+async function shutdown() {
+ await fetch("http://192.168.1.66/api/shutdown");
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/launch.html b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/launch.html
new file mode 100644
index 0000000..3cd7274
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/launch.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+ PrometheOS
+
+
+
+
+
+
+
+
+
+
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/launch.js b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/launch.js
new file mode 100644
index 0000000..3e85e9a
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/launch.js
@@ -0,0 +1,53 @@
+window.onload = function () {
+ getBankInfo();
+};
+
+async function getBankInfo() {
+ await fetch("http://192.168.1.66/api/bankinfo.json").then(async response => {
+
+ const json = await response.json();
+
+ let contentBody = "";
+ for (let i = 0; i < json.length; i++) {
+ if (json[i].slots > 0) {
+ contentBody += "
";
+ }
+ }
+ contentBody += "
";
+
+ let content = document.getElementById("content");
+ content.innerHTML = contentBody;
+ }).catch(error => {
+ let content = document.getElementById("content");
+ content.innerHTML = "Failed to connect."
+ });
+}
+
+async function launchBank(id)
+{
+ await fetch("http://192.168.1.66/api/launchbank?" + id).catch(error => {
+ content.innerHTML = "Failed to connect."
+ }).then(response => {
+ if (response.status == 200) {
+ let content = document.getElementById("content");
+ content.innerHTML = "Launching..."
+ } else {
+ let content = document.getElementById("content");
+ content.innerHTML = "Failed to launch."
+ }
+ });
+}
+
+async function launchTsop() {
+ await fetch("http://192.168.1.66/api/launchtsop").catch(error => {
+ content.innerHTML = "Failed to connect."
+ }).then(response => {
+ if (response.status == 200) {
+ let content = document.getElementById("content");
+ content.innerHTML = "Launching..."
+ } else {
+ let content = document.getElementById("content");
+ content.innerHTML = "Failed to launch."
+ }
+ });
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/main.css b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/main.css
new file mode 100644
index 0000000..d7c4faf
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/main.css
@@ -0,0 +1,119 @@
+.btn-ledoff {
+ color: #ffffff;
+ background-color: #404040;
+ border-color: #000000;
+}
+
+.btn-ledoff:hover,
+.btn-ledoff:focus,
+.btn-ledoff:active,
+.btn-ledoff.active {
+ color: #ffffff;
+ background-color: #202020;
+ border-color: #000000;
+}
+
+.btn-ledred {
+ color: #000000;
+ background-color: #aa0a00;
+ border-color: #000000;
+}
+
+.btn-ledred:hover,
+.btn-ledred:focus,
+.btn-ledred:active,
+.btn-ledred.active {
+ color: #000000;
+ background-color: #d40c00;
+ border-color: #000000;
+}
+
+.btn-ledgreen {
+ color: #000000;
+ background-color: #289a23;
+ border-color: #000000;
+}
+
+.btn-ledgreen:hover,
+.btn-ledgreen:focus,
+.btn-ledgreen:active,
+.btn-ledgreen.active {
+ color: #000000;
+ background-color: #32c12c;
+ border-color: #000000;
+}
+
+.btn-ledyellow {
+ color: #000000;
+ background-color: #cca400;
+ border-color: #000000;
+}
+
+.btn-ledyellow:hover,
+.btn-ledyellow:focus,
+.btn-ledyellow:active,
+.btn-ledyellow.active {
+ color: #000000;
+ background-color: #ffcd00;
+ border-color: #000000;
+}
+
+.btn-ledblue {
+ color: #000000;
+ background-color: #4358cc;
+ border-color: #000000;
+}
+
+.btn-ledblue:hover,
+.btn-ledblue:focus,
+.btn-ledblue:active,
+.btn-ledblue.active {
+ color: #ffffff;
+ background-color: #526eff;
+ border-color: #000000;
+}
+
+.btn-ledpurple {
+ color: #000000;
+ background-color: #663fa1;
+ border-color: #000000;
+}
+
+.btn-ledpurple:hover,
+.btn-ledpurple:focus,
+.btn-ledpurple:active,
+.btn-ledpurple.active {
+ color: #000000;
+ background-color: #7f4fc9;
+ border-color: #000000;
+}
+
+.btn-ledturquoise {
+ color: #000000;
+ background-color: #0096ae;
+ border-color: #000000;
+}
+
+.btn-ledturquoise:hover,
+.btn-ledturquoise:focus,
+.btn-ledturquoise:active,
+.btn-ledturquoise.active {
+ color: #000000;
+ background-color: #00bcd9;
+ border-color: #000000;
+}
+
+.btn-ledwhite {
+ color: #000000;
+ background-color: #c0c0c0;
+ border-color: #000000;
+}
+
+.btn-ledwhite:hover,
+.btn-ledwhite:focus,
+.btn-ledwhite:active,
+.btn-ledwhite.active {
+ color: #000000;
+ background-color: #f0f0f0;
+ border-color: #000000;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/pico.css b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/pico.css
new file mode 100644
index 0000000..52205b2
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/pico.css
@@ -0,0 +1,2576 @@
+:root {
+ --font-family: system-ui,-apple-system,"Segoe UI","Roboto","Ubuntu","Cantarell","Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";
+ --line-height: 1.5;
+ --font-weight: 400;
+ --font-size: 16px;
+ --border-radius: 0.25rem;
+ --border-width: 1px;
+ --outline-width: 3px;
+ --spacing: 1rem;
+ --typography-spacing-vertical: 1.5rem;
+ --block-spacing-vertical: calc(var(--spacing) * 2);
+ --block-spacing-horizontal: var(--spacing);
+ --grid-spacing-vertical: 0;
+ --grid-spacing-horizontal: var(--spacing);
+ --form-element-spacing-vertical: 0.75rem;
+ --form-element-spacing-horizontal: 1rem;
+ --nav-element-spacing-vertical: 1rem;
+ --nav-element-spacing-horizontal: 0.5rem;
+ --nav-link-spacing-vertical: 0.5rem;
+ --nav-link-spacing-horizontal: 0.5rem;
+ --form-label-font-weight: var(--font-weight);
+ --transition: 0.2s ease-in-out;
+ --modal-overlay-backdrop-filter: blur(0.25rem)
+}
+
+@media (min-width:576px) {
+ :root {
+ --font-size: 17px
+ }
+}
+
+@media (min-width:768px) {
+ :root {
+ --font-size: 18px
+ }
+}
+
+@media (min-width:992px) {
+ :root {
+ --font-size: 19px
+ }
+}
+
+@media (min-width:1200px) {
+ :root {
+ --font-size: 20px
+ }
+}
+
+@media (min-width:576px) {
+ body > footer, body > header, body > main, section {
+ --block-spacing-vertical: calc(var(--spacing) * 2.5)
+ }
+}
+
+@media (min-width:768px) {
+ body > footer, body > header, body > main, section {
+ --block-spacing-vertical: calc(var(--spacing) * 3)
+ }
+}
+
+@media (min-width:992px) {
+ body > footer, body > header, body > main, section {
+ --block-spacing-vertical: calc(var(--spacing) * 3.5)
+ }
+}
+
+@media (min-width:1200px) {
+ body > footer, body > header, body > main, section {
+ --block-spacing-vertical: calc(var(--spacing) * 4)
+ }
+}
+
+@media (min-width:576px) {
+ article {
+ --block-spacing-horizontal: calc(var(--spacing) * 1.25)
+ }
+}
+
+@media (min-width:768px) {
+ article {
+ --block-spacing-horizontal: calc(var(--spacing) * 1.5)
+ }
+}
+
+@media (min-width:992px) {
+ article {
+ --block-spacing-horizontal: calc(var(--spacing) * 1.75)
+ }
+}
+
+@media (min-width:1200px) {
+ article {
+ --block-spacing-horizontal: calc(var(--spacing) * 2)
+ }
+}
+
+dialog > article {
+ --block-spacing-vertical: calc(var(--spacing) * 2);
+ --block-spacing-horizontal: var(--spacing)
+}
+
+@media (min-width:576px) {
+ dialog > article {
+ --block-spacing-vertical: calc(var(--spacing) * 2.5);
+ --block-spacing-horizontal: calc(var(--spacing) * 1.25)
+ }
+}
+
+@media (min-width:768px) {
+ dialog > article {
+ --block-spacing-vertical: calc(var(--spacing) * 3);
+ --block-spacing-horizontal: calc(var(--spacing) * 1.5)
+ }
+}
+
+a {
+ --text-decoration: none
+}
+
+ a.contrast, a.secondary {
+ --text-decoration: underline
+ }
+
+small {
+ --font-size: 0.875em
+}
+
+h1, h2, h3, h4, h5, h6 {
+ --font-weight: 700
+}
+
+h1 {
+ --font-size: 2rem;
+ --typography-spacing-vertical: 3rem
+}
+
+h2 {
+ --font-size: 1.75rem;
+ --typography-spacing-vertical: 2.625rem
+}
+
+h3 {
+ --font-size: 1.5rem;
+ --typography-spacing-vertical: 2.25rem
+}
+
+h4 {
+ --font-size: 1.25rem;
+ --typography-spacing-vertical: 1.874rem
+}
+
+h5 {
+ --font-size: 1.125rem;
+ --typography-spacing-vertical: 1.6875rem
+}
+
+[type=checkbox], [type=radio] {
+ --border-width: 2px
+}
+
+ [type=checkbox][role=switch] {
+ --border-width: 3px
+ }
+
+tfoot td, tfoot th, thead td, thead th {
+ --border-width: 3px
+}
+
+:not(thead,tfoot) > * > td {
+ --font-size: 0.875em
+}
+
+code, kbd, pre, samp {
+ --font-family: "Menlo","Consolas","Roboto Mono","Ubuntu Monospace","Noto Mono","Oxygen Mono","Liberation Mono",monospace,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"
+}
+
+kbd {
+ --font-weight: bolder
+}
+
+:root:not([data-theme=dark]), [data-theme=light] {
+ --background-color: #fff;
+ --color: hsl(205, 20%, 32%);
+ --h1-color: hsl(205, 30%, 15%);
+ --h2-color: #24333e;
+ --h3-color: hsl(205, 25%, 23%);
+ --h4-color: #374956;
+ --h5-color: hsl(205, 20%, 32%);
+ --h6-color: #4d606d;
+ --muted-color: hsl(205, 10%, 50%);
+ --muted-border-color: hsl(205, 20%, 94%);
+ --primary: hsl(195, 85%, 41%);
+ --primary-hover: hsl(195, 90%, 32%);
+ --primary-focus: rgba(16, 149, 193, 0.125);
+ --primary-inverse: #fff;
+ --secondary: hsl(205, 15%, 41%);
+ --secondary-hover: hsl(205, 20%, 32%);
+ --secondary-focus: rgba(89, 107, 120, 0.125);
+ --secondary-inverse: #fff;
+ --contrast: hsl(205, 30%, 15%);
+ --contrast-hover: #000;
+ --contrast-focus: rgba(89, 107, 120, 0.125);
+ --contrast-inverse: #fff;
+ --mark-background-color: #fff2ca;
+ --mark-color: #543a26;
+ --ins-color: #388e3c;
+ --del-color: #c62828;
+ --blockquote-border-color: var(--muted-border-color);
+ --blockquote-footer-color: var(--muted-color);
+ --button-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+ --button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+ --form-element-background-color: transparent;
+ --form-element-border-color: hsl(205, 14%, 68%);
+ --form-element-color: var(--color);
+ --form-element-placeholder-color: var(--muted-color);
+ --form-element-active-background-color: transparent;
+ --form-element-active-border-color: var(--primary);
+ --form-element-focus-color: var(--primary-focus);
+ --form-element-disabled-background-color: hsl(205, 18%, 86%);
+ --form-element-disabled-border-color: hsl(205, 14%, 68%);
+ --form-element-disabled-opacity: 0.5;
+ --form-element-invalid-border-color: #c62828;
+ --form-element-invalid-active-border-color: #d32f2f;
+ --form-element-invalid-focus-color: rgba(211, 47, 47, 0.125);
+ --form-element-valid-border-color: #388e3c;
+ --form-element-valid-active-border-color: #43a047;
+ --form-element-valid-focus-color: rgba(67, 160, 71, 0.125);
+ --switch-background-color: hsl(205, 16%, 77%);
+ --switch-color: var(--primary-inverse);
+ --switch-checked-background-color: var(--primary);
+ --range-border-color: hsl(205, 18%, 86%);
+ --range-active-border-color: hsl(205, 16%, 77%);
+ --range-thumb-border-color: var(--background-color);
+ --range-thumb-color: var(--secondary);
+ --range-thumb-hover-color: var(--secondary-hover);
+ --range-thumb-active-color: var(--primary);
+ --table-border-color: var(--muted-border-color);
+ --table-row-stripped-background-color: #f6f8f9;
+ --code-background-color: hsl(205, 20%, 94%);
+ --code-color: var(--muted-color);
+ --code-kbd-background-color: var(--contrast);
+ --code-kbd-color: var(--contrast-inverse);
+ --code-tag-color: hsl(330, 40%, 50%);
+ --code-property-color: hsl(185, 40%, 40%);
+ --code-value-color: hsl(40, 20%, 50%);
+ --code-comment-color: hsl(205, 14%, 68%);
+ --accordion-border-color: var(--muted-border-color);
+ --accordion-close-summary-color: var(--color);
+ --accordion-open-summary-color: var(--muted-color);
+ --card-background-color: var(--background-color);
+ --card-border-color: var(--muted-border-color);
+ --card-box-shadow: 0.0145rem 0.029rem 0.174rem rgba(27, 40, 50, 0.01698),0.0335rem 0.067rem 0.402rem rgba(27, 40, 50, 0.024),0.0625rem 0.125rem 0.75rem rgba(27, 40, 50, 0.03),0.1125rem 0.225rem 1.35rem rgba(27, 40, 50, 0.036),0.2085rem 0.417rem 2.502rem rgba(27, 40, 50, 0.04302),0.5rem 1rem 6rem rgba(27, 40, 50, 0.06),0 0 0 0.0625rem rgba(27, 40, 50, 0.015);
+ --card-sectionning-background-color: #fbfbfc;
+ --dropdown-background-color: #fbfbfc;
+ --dropdown-border-color: #e1e6eb;
+ --dropdown-box-shadow: var(--card-box-shadow);
+ --dropdown-color: var(--color);
+ --dropdown-hover-background-color: hsl(205, 20%, 94%);
+ --modal-overlay-background-color: rgba(213, 220, 226, 0.7);
+ --progress-background-color: hsl(205, 18%, 86%);
+ --progress-color: var(--primary);
+ --loading-spinner-opacity: 0.5;
+ --tooltip-background-color: var(--contrast);
+ --tooltip-color: var(--contrast-inverse);
+ --icon-checkbox: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(65, 84, 98)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-chevron-button: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-chevron-button-inverse: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-close: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(115, 130, 140)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");
+ --icon-date: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(65, 84, 98)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");
+ --icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(198, 40, 40)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");
+ --icon-minus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E");
+ --icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(65, 84, 98)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");
+ --icon-time: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(65, 84, 98)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(56, 142, 60)' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
+ color-scheme: light
+}
+
+@media only screen and (prefers-color-scheme:dark) {
+ :root:not([data-theme]) {
+ --background-color: #11191f;
+ --color: hsl(205, 16%, 77%);
+ --h1-color: hsl(205, 20%, 94%);
+ --h2-color: #e1e6eb;
+ --h3-color: hsl(205, 18%, 86%);
+ --h4-color: #c8d1d8;
+ --h5-color: hsl(205, 16%, 77%);
+ --h6-color: #afbbc4;
+ --muted-color: hsl(205, 10%, 50%);
+ --muted-border-color: #1f2d38;
+ --primary: hsl(195, 85%, 41%);
+ --primary-hover: hsl(195, 80%, 50%);
+ --primary-focus: rgba(16, 149, 193, 0.25);
+ --primary-inverse: #fff;
+ --secondary: hsl(205, 15%, 41%);
+ --secondary-hover: hsl(205, 10%, 50%);
+ --secondary-focus: rgba(115, 130, 140, 0.25);
+ --secondary-inverse: #fff;
+ --contrast: hsl(205, 20%, 94%);
+ --contrast-hover: #fff;
+ --contrast-focus: rgba(115, 130, 140, 0.25);
+ --contrast-inverse: #000;
+ --mark-background-color: #d1c284;
+ --mark-color: #11191f;
+ --ins-color: #388e3c;
+ --del-color: #c62828;
+ --blockquote-border-color: var(--muted-border-color);
+ --blockquote-footer-color: var(--muted-color);
+ --button-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+ --button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+ --form-element-background-color: #11191f;
+ --form-element-border-color: #374956;
+ --form-element-color: var(--color);
+ --form-element-placeholder-color: var(--muted-color);
+ --form-element-active-background-color: var(--form-element-background-color);
+ --form-element-active-border-color: var(--primary);
+ --form-element-focus-color: var(--primary-focus);
+ --form-element-disabled-background-color: hsl(205, 25%, 23%);
+ --form-element-disabled-border-color: hsl(205, 20%, 32%);
+ --form-element-disabled-opacity: 0.5;
+ --form-element-invalid-border-color: #b71c1c;
+ --form-element-invalid-active-border-color: #c62828;
+ --form-element-invalid-focus-color: rgba(198, 40, 40, 0.25);
+ --form-element-valid-border-color: #2e7d32;
+ --form-element-valid-active-border-color: #388e3c;
+ --form-element-valid-focus-color: rgba(56, 142, 60, 0.25);
+ --switch-background-color: #374956;
+ --switch-color: var(--primary-inverse);
+ --switch-checked-background-color: var(--primary);
+ --range-border-color: #24333e;
+ --range-active-border-color: hsl(205, 25%, 23%);
+ --range-thumb-border-color: var(--background-color);
+ --range-thumb-color: var(--secondary);
+ --range-thumb-hover-color: var(--secondary-hover);
+ --range-thumb-active-color: var(--primary);
+ --table-border-color: var(--muted-border-color);
+ --table-row-stripped-background-color: rgba(115, 130, 140, 0.05);
+ --code-background-color: #18232c;
+ --code-color: var(--muted-color);
+ --code-kbd-background-color: var(--contrast);
+ --code-kbd-color: var(--contrast-inverse);
+ --code-tag-color: hsl(330, 30%, 50%);
+ --code-property-color: hsl(185, 30%, 50%);
+ --code-value-color: hsl(40, 10%, 50%);
+ --code-comment-color: #4d606d;
+ --accordion-border-color: var(--muted-border-color);
+ --accordion-active-summary-color: var(--primary);
+ --accordion-close-summary-color: var(--color);
+ --accordion-open-summary-color: var(--muted-color);
+ --card-background-color: #141e26;
+ --card-border-color: var(--card-background-color);
+ --card-box-shadow: 0.0145rem 0.029rem 0.174rem rgba(0, 0, 0, 0.01698),0.0335rem 0.067rem 0.402rem rgba(0, 0, 0, 0.024),0.0625rem 0.125rem 0.75rem rgba(0, 0, 0, 0.03),0.1125rem 0.225rem 1.35rem rgba(0, 0, 0, 0.036),0.2085rem 0.417rem 2.502rem rgba(0, 0, 0, 0.04302),0.5rem 1rem 6rem rgba(0, 0, 0, 0.06),0 0 0 0.0625rem rgba(0, 0, 0, 0.015);
+ --card-sectionning-background-color: #18232c;
+ --dropdown-background-color: hsl(205, 30%, 15%);
+ --dropdown-border-color: #24333e;
+ --dropdown-box-shadow: var(--card-box-shadow);
+ --dropdown-color: var(--color);
+ --dropdown-hover-background-color: rgba(36, 51, 62, 0.75);
+ --modal-overlay-background-color: rgba(36, 51, 62, 0.8);
+ --progress-background-color: #24333e;
+ --progress-color: var(--primary);
+ --loading-spinner-opacity: 0.5;
+ --tooltip-background-color: var(--contrast);
+ --tooltip-color: var(--contrast-inverse);
+ --icon-checkbox: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-chevron-button: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-chevron-button-inverse: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(0, 0, 0)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-close: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(115, 130, 140)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");
+ --icon-date: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");
+ --icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(183, 28, 28)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");
+ --icon-minus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E");
+ --icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");
+ --icon-time: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(46, 125, 50)' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
+ color-scheme: dark
+ }
+}
+
+[data-theme=dark] {
+ --background-color: #11191f;
+ --color: hsl(205, 16%, 77%);
+ --h1-color: hsl(205, 20%, 94%);
+ --h2-color: #e1e6eb;
+ --h3-color: hsl(205, 18%, 86%);
+ --h4-color: #c8d1d8;
+ --h5-color: hsl(205, 16%, 77%);
+ --h6-color: #afbbc4;
+ --muted-color: hsl(205, 10%, 50%);
+ --muted-border-color: #1f2d38;
+ --primary: hsl(204, 70%, 30%);
+ --primary-hover: hsl(195, 85%, 41%);
+ --primary-focus: rgba(16, 149, 193, 0.25);
+ --primary-inverse: #fff;
+ --secondary: hsl(205, 15%, 41%);
+ --secondary-hover: hsl(205, 10%, 50%);
+ --secondary-focus: rgba(115, 130, 140, 0.25);
+ --secondary-inverse: #fff;
+ --contrast: hsl(205, 20%, 94%);
+ --contrast-hover: #fff;
+ --contrast-focus: rgba(115, 130, 140, 0.25);
+ --contrast-inverse: #000;
+ --mark-background-color: #d1c284;
+ --mark-color: #11191f;
+ --ins-color: #388e3c;
+ --del-color: #c62828;
+ --blockquote-border-color: var(--muted-border-color);
+ --blockquote-footer-color: var(--muted-color);
+ --button-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+ --button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+ --form-element-background-color: #11191f;
+ --form-element-border-color: #374956;
+ --form-element-color: var(--color);
+ --form-element-placeholder-color: var(--muted-color);
+ --form-element-active-background-color: var(--form-element-background-color);
+ --form-element-active-border-color: var(--primary);
+ --form-element-focus-color: var(--primary-focus);
+ --form-element-disabled-background-color: hsl(205, 25%, 23%);
+ --form-element-disabled-border-color: hsl(205, 20%, 32%);
+ --form-element-disabled-opacity: 0.5;
+ --form-element-invalid-border-color: #b71c1c;
+ --form-element-invalid-active-border-color: #c62828;
+ --form-element-invalid-focus-color: rgba(198, 40, 40, 0.25);
+ --form-element-valid-border-color: #2e7d32;
+ --form-element-valid-active-border-color: #388e3c;
+ --form-element-valid-focus-color: rgba(56, 142, 60, 0.25);
+ --switch-background-color: #374956;
+ --switch-color: var(--primary-inverse);
+ --switch-checked-background-color: var(--primary);
+ --range-border-color: #24333e;
+ --range-active-border-color: hsl(205, 25%, 23%);
+ --range-thumb-border-color: var(--background-color);
+ --range-thumb-color: var(--secondary);
+ --range-thumb-hover-color: var(--secondary-hover);
+ --range-thumb-active-color: var(--primary);
+ --table-border-color: var(--muted-border-color);
+ --table-row-stripped-background-color: rgba(115, 130, 140, 0.05);
+ --code-background-color: #18232c;
+ --code-color: var(--muted-color);
+ --code-kbd-background-color: var(--contrast);
+ --code-kbd-color: var(--contrast-inverse);
+ --code-tag-color: hsl(330, 30%, 50%);
+ --code-property-color: hsl(185, 30%, 50%);
+ --code-value-color: hsl(40, 10%, 50%);
+ --code-comment-color: #4d606d;
+ --accordion-border-color: var(--muted-border-color);
+ --accordion-active-summary-color: var(--primary);
+ --accordion-close-summary-color: var(--color);
+ --accordion-open-summary-color: var(--muted-color);
+ --card-background-color: #141e26;
+ --card-border-color: var(--card-background-color);
+ --card-box-shadow: 0.0145rem 0.029rem 0.174rem rgba(0, 0, 0, 0.01698),0.0335rem 0.067rem 0.402rem rgba(0, 0, 0, 0.024),0.0625rem 0.125rem 0.75rem rgba(0, 0, 0, 0.03),0.1125rem 0.225rem 1.35rem rgba(0, 0, 0, 0.036),0.2085rem 0.417rem 2.502rem rgba(0, 0, 0, 0.04302),0.5rem 1rem 6rem rgba(0, 0, 0, 0.06),0 0 0 0.0625rem rgba(0, 0, 0, 0.015);
+ --card-sectionning-background-color: #18232c;
+ --dropdown-background-color: hsl(205, 30%, 15%);
+ --dropdown-border-color: #24333e;
+ --dropdown-box-shadow: var(--card-box-shadow);
+ --dropdown-color: var(--color);
+ --dropdown-hover-background-color: rgba(36, 51, 62, 0.75);
+ --modal-overlay-background-color: rgba(36, 51, 62, 0.8);
+ --progress-background-color: #24333e;
+ --progress-color: var(--primary);
+ --loading-spinner-opacity: 0.5;
+ --tooltip-background-color: var(--contrast);
+ --tooltip-color: var(--contrast-inverse);
+ --icon-checkbox: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-chevron-button: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-chevron-button-inverse: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(0, 0, 0)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-close: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(115, 130, 140)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");
+ --icon-date: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");
+ --icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(183, 28, 28)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");
+ --icon-minus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E");
+ --icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");
+ --icon-time: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");
+ --icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(46, 125, 50)' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
+ color-scheme: dark
+}
+
+[type=checkbox], [type=radio], [type=range], progress {
+ accent-color: var(--primary)
+}
+
+*, ::after, ::before {
+ box-sizing: border-box;
+ background-repeat: no-repeat
+}
+
+::after, ::before {
+ text-decoration: inherit;
+ vertical-align: inherit
+}
+
+:where(:root) {
+ -webkit-tap-highlight-color: transparent;
+ -webkit-text-size-adjust: 100%;
+ -moz-text-size-adjust: 100%;
+ text-size-adjust: 100%;
+ background-color: var(--background-color);
+ color: var(--color);
+ font-weight: var(--font-weight);
+ font-size: var(--font-size);
+ line-height: var(--line-height);
+ font-family: var(--font-family);
+ text-rendering: optimizeLegibility;
+ overflow-wrap: break-word;
+ cursor: default;
+ -moz-tab-size: 4;
+ -o-tab-size: 4;
+ tab-size: 4
+}
+
+main {
+ display: block
+}
+
+body {
+ width: 100%;
+ margin: 0
+}
+
+ body > footer, body > header, body > main {
+ width: 100%;
+ margin-right: auto;
+ margin-left: auto;
+ padding: var(--block-spacing-vertical) 0
+ }
+
+.container, .container-fluid {
+ width: 100%;
+ margin-right: auto;
+ margin-left: auto;
+ padding-right: var(--spacing);
+ padding-left: var(--spacing)
+}
+
+@media (min-width:576px) {
+ .container {
+ max-width: 510px;
+ padding-right: 0;
+ padding-left: 0
+ }
+}
+
+@media (min-width:768px) {
+ .container {
+ max-width: 700px
+ }
+}
+
+@media (min-width:992px) {
+ .container {
+ max-width: 920px
+ }
+}
+
+@media (min-width:1200px) {
+ .container {
+ max-width: 1130px
+ }
+}
+
+section {
+ margin-bottom: var(--block-spacing-vertical)
+}
+
+.grid {
+ grid-column-gap: var(--grid-spacing-horizontal);
+ grid-row-gap: var(--grid-spacing-vertical);
+ display: grid;
+ grid-template-columns: 1fr;
+ margin: 0
+}
+
+@media (min-width:992px) {
+ .grid {
+ grid-template-columns: repeat(auto-fit,minmax(0%,1fr))
+ }
+}
+
+.grid > * {
+ min-width: 0
+}
+
+figure {
+ display: block;
+ margin: 0;
+ padding: 0;
+ overflow-x: auto
+}
+
+ figure figcaption {
+ padding: calc(var(--spacing) * .5) 0;
+ color: var(--muted-color)
+ }
+
+b, strong {
+ font-weight: bolder
+}
+
+sub, sup {
+ position: relative;
+ font-size: .75em;
+ line-height: 0;
+ vertical-align: baseline
+}
+
+sub {
+ bottom: -.25em
+}
+
+sup {
+ top: -.5em
+}
+
+address, blockquote, dl, figure, form, ol, p, pre, table, ul {
+ margin-top: 0;
+ margin-bottom: var(--typography-spacing-vertical);
+ color: var(--color);
+ font-style: normal;
+ font-weight: var(--font-weight);
+ font-size: var(--font-size)
+}
+
+[role=link], a {
+ --color: var(--primary);
+ --background-color: transparent;
+ outline: 0;
+ background-color: var(--background-color);
+ color: var(--color);
+ -webkit-text-decoration: var(--text-decoration);
+ text-decoration: var(--text-decoration);
+ transition: background-color var(--transition),color var(--transition),box-shadow var(--transition),-webkit-text-decoration var(--transition);
+ transition: background-color var(--transition),color var(--transition),text-decoration var(--transition),box-shadow var(--transition);
+ transition: background-color var(--transition),color var(--transition),text-decoration var(--transition),box-shadow var(--transition),-webkit-text-decoration var(--transition)
+}
+
+ [role=link]:is([aria-current],:hover,:active,:focus), a:is([aria-current],:hover,:active,:focus) {
+ --color: var(--primary-hover);
+ --text-decoration: underline
+ }
+
+ [role=link]:focus, a:focus {
+ --background-color: var(--primary-focus)
+ }
+
+ [role=link].secondary, a.secondary {
+ --color: var(--secondary)
+ }
+
+ [role=link].secondary:is([aria-current],:hover,:active,:focus), a.secondary:is([aria-current],:hover,:active,:focus) {
+ --color: var(--secondary-hover)
+ }
+
+ [role=link].secondary:focus, a.secondary:focus {
+ --background-color: var(--secondary-focus)
+ }
+
+ [role=link].contrast, a.contrast {
+ --color: var(--contrast)
+ }
+
+ [role=link].contrast:is([aria-current],:hover,:active,:focus), a.contrast:is([aria-current],:hover,:active,:focus) {
+ --color: var(--contrast-hover)
+ }
+
+ [role=link].contrast:focus, a.contrast:focus {
+ --background-color: var(--contrast-focus)
+ }
+
+h1, h2, h3, h4, h5, h6 {
+ margin-top: 0;
+ margin-bottom: var(--typography-spacing-vertical);
+ color: var(--color);
+ font-weight: var(--font-weight);
+ font-size: var(--font-size);
+ font-family: var(--font-family)
+}
+
+h1 {
+ --color: var(--h1-color)
+}
+
+h2 {
+ --color: var(--h2-color)
+}
+
+h3 {
+ --color: var(--h3-color)
+}
+
+h4 {
+ --color: var(--h4-color)
+}
+
+h5 {
+ --color: var(--h5-color)
+}
+
+h6 {
+ --color: var(--h6-color)
+}
+
+:where(address,blockquote,dl,figure,form,ol,p,pre,table,ul) ~ :is(h1,h2,h3,h4,h5,h6) {
+ margin-top: var(--typography-spacing-vertical)
+}
+
+.headings, hgroup {
+ margin-bottom: var(--typography-spacing-vertical)
+}
+
+ .headings > *, hgroup > * {
+ margin-bottom: 0
+ }
+
+ .headings > :last-child, hgroup > :last-child {
+ --color: var(--muted-color);
+ --font-weight: unset;
+ font-size: 1rem;
+ font-family: unset
+ }
+
+p {
+ margin-bottom: var(--typography-spacing-vertical)
+}
+
+small {
+ font-size: var(--font-size)
+}
+
+:where(dl,ol,ul) {
+ padding-right: 0;
+ padding-left: var(--spacing);
+ -webkit-padding-start: var(--spacing);
+ padding-inline-start: var(--spacing);
+ -webkit-padding-end: 0;
+ padding-inline-end: 0
+}
+
+ :where(dl,ol,ul) li {
+ margin-bottom: calc(var(--typography-spacing-vertical) * .25)
+ }
+
+ :where(dl,ol,ul) :is(dl,ol,ul) {
+ margin: 0;
+ margin-top: calc(var(--typography-spacing-vertical) * .25)
+ }
+
+ul li {
+ list-style: square
+}
+
+mark {
+ padding: .125rem .25rem;
+ background-color: var(--mark-background-color);
+ color: var(--mark-color);
+ vertical-align: baseline
+}
+
+blockquote {
+ display: block;
+ margin: var(--typography-spacing-vertical) 0;
+ padding: var(--spacing);
+ border-right: none;
+ border-left: .25rem solid var(--blockquote-border-color);
+ -webkit-border-start: 0.25rem solid var(--blockquote-border-color);
+ border-inline-start: 0.25rem solid var(--blockquote-border-color);
+ -webkit-border-end: none;
+ border-inline-end: none
+}
+
+ blockquote footer {
+ margin-top: calc(var(--typography-spacing-vertical) * .5);
+ color: var(--blockquote-footer-color)
+ }
+
+abbr[title] {
+ border-bottom: 1px dotted;
+ text-decoration: none;
+ cursor: help
+}
+
+ins {
+ color: var(--ins-color);
+ text-decoration: none
+}
+
+del {
+ color: var(--del-color)
+}
+
+::-moz-selection {
+ background-color: var(--primary-focus)
+}
+
+::selection {
+ background-color: var(--primary-focus)
+}
+
+:where(audio,canvas,iframe,img,svg,video) {
+ vertical-align: middle
+}
+
+audio, video {
+ display: inline-block
+}
+
+ audio:not([controls]) {
+ display: none;
+ height: 0
+ }
+
+:where(iframe) {
+ border-style: none
+}
+
+img {
+ max-width: 100%;
+ height: auto;
+ border-style: none
+}
+
+:where(svg:not([fill])) {
+ fill: currentColor
+}
+
+svg:not(:root) {
+ overflow: hidden
+}
+
+button {
+ margin: 0;
+ overflow: visible;
+ font-family: inherit;
+ text-transform: none
+}
+
+[type=button], [type=reset], [type=submit], button {
+ -webkit-appearance: button
+}
+
+button {
+ display: block;
+ width: 100%;
+ margin-bottom: var(--spacing)
+}
+
+[role=button] {
+ display: inline-block;
+ text-decoration: none
+}
+
+[role=button], button, input[type=button], input[type=reset], input[type=submit] {
+ --background-color: var(--primary);
+ --border-color: var(--primary);
+ --color: var(--primary-inverse);
+ --box-shadow: var(--button-box-shadow, 0 0 0 rgba(0, 0, 0, 0));
+ padding: var(--form-element-spacing-vertical) var(--form-element-spacing-horizontal);
+ border: var(--border-width) solid var(--border-color);
+ border-radius: var(--border-radius);
+ outline: 0;
+ background-color: var(--background-color);
+ box-shadow: var(--box-shadow);
+ color: var(--color);
+ font-weight: var(--font-weight);
+ font-size: 1rem;
+ line-height: var(--line-height);
+ text-align: center;
+ cursor: pointer;
+ transition: background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)
+}
+
+ [role=button]:is([aria-current],:hover,:active,:focus), button:is([aria-current],:hover,:active,:focus), input[type=button]:is([aria-current],:hover,:active,:focus), input[type=reset]:is([aria-current],:hover,:active,:focus), input[type=submit]:is([aria-current],:hover,:active,:focus) {
+ --background-color: var(--primary-hover);
+ --border-color: var(--primary-hover);
+ --box-shadow: var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0));
+ --color: var(--primary-inverse)
+ }
+
+ [role=button]:focus, button:focus, input[type=button]:focus, input[type=reset]:focus, input[type=submit]:focus {
+ --box-shadow: var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)),0 0 0 var(--outline-width) var(--primary-focus)
+ }
+
+:is(button,input[type=submit],input[type=button],[role=button]).secondary, input[type=reset] {
+ --background-color: var(--secondary);
+ --border-color: var(--secondary);
+ --color: var(--secondary-inverse);
+ cursor: pointer
+}
+
+ :is(button,input[type=submit],input[type=button],[role=button]).secondary:is([aria-current],:hover,:active,:focus), input[type=reset]:is([aria-current],:hover,:active,:focus) {
+ --background-color: var(--secondary-hover);
+ --border-color: var(--secondary-hover);
+ --color: var(--secondary-inverse)
+ }
+
+ :is(button,input[type=submit],input[type=button],[role=button]).secondary:focus, input[type=reset]:focus {
+ --box-shadow: var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)),0 0 0 var(--outline-width) var(--secondary-focus)
+ }
+
+:is(button,input[type=submit],input[type=button],[role=button]).contrast {
+ --background-color: var(--contrast);
+ --border-color: var(--contrast);
+ --color: var(--contrast-inverse)
+}
+
+ :is(button,input[type=submit],input[type=button],[role=button]).contrast:is([aria-current],:hover,:active,:focus) {
+ --background-color: var(--contrast-hover);
+ --border-color: var(--contrast-hover);
+ --color: var(--contrast-inverse)
+ }
+
+ :is(button,input[type=submit],input[type=button],[role=button]).contrast:focus {
+ --box-shadow: var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)),0 0 0 var(--outline-width) var(--contrast-focus)
+ }
+
+:is(button,input[type=submit],input[type=button],[role=button]).outline, input[type=reset].outline {
+ --background-color: transparent;
+ --color: var(--primary)
+}
+
+ :is(button,input[type=submit],input[type=button],[role=button]).outline:is([aria-current],:hover,:active,:focus), input[type=reset].outline:is([aria-current],:hover,:active,:focus) {
+ --background-color: transparent;
+ --color: var(--primary-hover)
+ }
+
+ :is(button,input[type=submit],input[type=button],[role=button]).outline.secondary, input[type=reset].outline {
+ --color: var(--secondary)
+ }
+
+ :is(button,input[type=submit],input[type=button],[role=button]).outline.secondary:is([aria-current],:hover,:active,:focus), input[type=reset].outline:is([aria-current],:hover,:active,:focus) {
+ --color: var(--secondary-hover)
+ }
+
+ :is(button,input[type=submit],input[type=button],[role=button]).outline.contrast {
+ --color: var(--contrast)
+ }
+
+ :is(button,input[type=submit],input[type=button],[role=button]).outline.contrast:is([aria-current],:hover,:active,:focus) {
+ --color: var(--contrast-hover)
+ }
+
+:where(button,[type=submit],[type=button],[type=reset],[role=button])[disabled], :where(fieldset[disabled]) :is(button,[type=submit],[type=button],[type=reset],[role=button]), a[role=button]:not([href]) {
+ opacity: .5;
+ pointer-events: none
+}
+
+input, optgroup, select, textarea {
+ margin: 0;
+ font-size: 1rem;
+ line-height: var(--line-height);
+ font-family: inherit;
+ letter-spacing: inherit
+}
+
+input {
+ overflow: visible
+}
+
+select {
+ text-transform: none
+}
+
+legend {
+ max-width: 100%;
+ padding: 0;
+ color: inherit;
+ white-space: normal
+}
+
+textarea {
+ overflow: auto
+}
+
+[type=checkbox], [type=radio] {
+ padding: 0
+}
+
+::-webkit-inner-spin-button, ::-webkit-outer-spin-button {
+ height: auto
+}
+
+[type=search] {
+ -webkit-appearance: textfield;
+ outline-offset: -2px
+}
+
+ [type=search]::-webkit-search-decoration {
+ -webkit-appearance: none
+ }
+
+::-webkit-file-upload-button {
+ -webkit-appearance: button;
+ font: inherit
+}
+
+::-moz-focus-inner {
+ padding: 0;
+ border-style: none
+}
+
+:-moz-focusring {
+ outline: 0
+}
+
+:-moz-ui-invalid {
+ box-shadow: none
+}
+
+::-ms-expand {
+ display: none
+}
+
+[type=file], [type=range] {
+ padding: 0;
+ border-width: 0
+}
+
+input:not([type=checkbox],[type=radio],[type=range]) {
+ height: calc(1rem * var(--line-height) + var(--form-element-spacing-vertical) * 2 + var(--border-width) * 2)
+}
+
+fieldset {
+ margin: 0;
+ margin-bottom: var(--spacing);
+ padding: 0;
+ border: 0
+}
+
+ fieldset legend, label {
+ display: block;
+ margin-bottom: calc(var(--spacing) * .25);
+ font-weight: var(--form-label-font-weight,var(--font-weight))
+ }
+
+input:not([type=checkbox],[type=radio]), select, textarea {
+ width: 100%
+}
+
+input:not([type=checkbox],[type=radio],[type=range],[type=file]), select, textarea {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ padding: var(--form-element-spacing-vertical) var(--form-element-spacing-horizontal)
+}
+
+input, select, textarea {
+ --background-color: var(--form-element-background-color);
+ --border-color: var(--form-element-border-color);
+ --color: var(--form-element-color);
+ --box-shadow: none;
+ border: var(--border-width) solid var(--border-color);
+ border-radius: var(--border-radius);
+ outline: 0;
+ background-color: var(--background-color);
+ box-shadow: var(--box-shadow);
+ color: var(--color);
+ font-weight: var(--font-weight);
+ transition: background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)
+}
+
+ :where(select,textarea):is(:active,:focus), input:not([type=submit],[type=button],[type=reset],[type=checkbox],[type=radio],[readonly]):is(:active,:focus) {
+ --background-color: var(--form-element-active-background-color)
+ }
+
+ :where(select,textarea):is(:active,:focus), input:not([type=submit],[type=button],[type=reset],[role=switch],[readonly]):is(:active,:focus) {
+ --border-color: var(--form-element-active-border-color)
+ }
+
+ input:not([type=submit],[type=button],[type=reset],[type=range],[type=file],[readonly]):focus, select:focus, textarea:focus {
+ --box-shadow: 0 0 0 var(--outline-width) var(--form-element-focus-color)
+ }
+
+ :where(fieldset[disabled]) :is(input:not([type=submit],[type=button],[type=reset]),select,textarea), input:not([type=submit],[type=button],[type=reset])[disabled], select[disabled], textarea[disabled] {
+ --background-color: var(--form-element-disabled-background-color);
+ --border-color: var(--form-element-disabled-border-color);
+ opacity: var(--form-element-disabled-opacity);
+ pointer-events: none
+ }
+
+:where(input,select,textarea):not([type=checkbox],[type=radio],[type=date],[type=datetime-local],[type=month],[type=time],[type=week])[aria-invalid] {
+ padding-right: calc(var(--form-element-spacing-horizontal) + 1.5rem) !important;
+ padding-left: var(--form-element-spacing-horizontal);
+ -webkit-padding-start: var(--form-element-spacing-horizontal) !important;
+ padding-inline-start: var(--form-element-spacing-horizontal) !important;
+ -webkit-padding-end: calc(var(--form-element-spacing-horizontal) + 1.5rem) !important;
+ padding-inline-end: calc(var(--form-element-spacing-horizontal) + 1.5rem) !important;
+ background-position: center right .75rem;
+ background-size: 1rem auto;
+ background-repeat: no-repeat
+}
+
+:where(input,select,textarea):not([type=checkbox],[type=radio],[type=date],[type=datetime-local],[type=month],[type=time],[type=week])[aria-invalid=false] {
+ background-image: var(--icon-valid)
+}
+
+:where(input,select,textarea):not([type=checkbox],[type=radio],[type=date],[type=datetime-local],[type=month],[type=time],[type=week])[aria-invalid=true] {
+ background-image: var(--icon-invalid)
+}
+
+:where(input,select,textarea)[aria-invalid=false] {
+ --border-color: var(--form-element-valid-border-color)
+}
+
+ :where(input,select,textarea)[aria-invalid=false]:is(:active,:focus) {
+ --border-color: var(--form-element-valid-active-border-color) !important;
+ --box-shadow: 0 0 0 var(--outline-width) var(--form-element-valid-focus-color) !important
+ }
+
+:where(input,select,textarea)[aria-invalid=true] {
+ --border-color: var(--form-element-invalid-border-color)
+}
+
+ :where(input,select,textarea)[aria-invalid=true]:is(:active,:focus) {
+ --border-color: var(--form-element-invalid-active-border-color) !important;
+ --box-shadow: 0 0 0 var(--outline-width) var(--form-element-invalid-focus-color) !important
+ }
+
+[dir=rtl] :where(input,select,textarea):not([type=checkbox],[type=radio]):is([aria-invalid],[aria-invalid=true],[aria-invalid=false]) {
+ background-position: center left .75rem
+}
+
+input::-webkit-input-placeholder, input::placeholder, select:invalid, textarea::-webkit-input-placeholder, textarea::placeholder {
+ color: var(--form-element-placeholder-color);
+ opacity: 1
+}
+
+input:not([type=checkbox],[type=radio]), select, textarea {
+ margin-bottom: var(--spacing)
+}
+
+ select::-ms-expand {
+ border: 0;
+ background-color: transparent
+ }
+
+ select:not([multiple],[size]) {
+ padding-right: calc(var(--form-element-spacing-horizontal) + 1.5rem);
+ padding-left: var(--form-element-spacing-horizontal);
+ -webkit-padding-start: var(--form-element-spacing-horizontal);
+ padding-inline-start: var(--form-element-spacing-horizontal);
+ -webkit-padding-end: calc(var(--form-element-spacing-horizontal) + 1.5rem);
+ padding-inline-end: calc(var(--form-element-spacing-horizontal) + 1.5rem);
+ background-image: var(--icon-chevron);
+ background-position: center right .75rem;
+ background-size: 1rem auto;
+ background-repeat: no-repeat
+ }
+
+[dir=rtl] select:not([multiple],[size]) {
+ background-position: center left .75rem
+}
+
+:where(input,select,textarea,.grid) + small {
+ display: block;
+ width: 100%;
+ margin-top: calc(var(--spacing) * -.75);
+ margin-bottom: var(--spacing);
+ color: var(--muted-color)
+}
+
+label > :where(input,select,textarea) {
+ margin-top: calc(var(--spacing) * .25)
+}
+
+[type=checkbox], [type=radio] {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ width: 1.25em;
+ height: 1.25em;
+ margin-top: -.125em;
+ margin-right: .375em;
+ margin-left: 0;
+ -webkit-margin-start: 0;
+ margin-inline-start: 0;
+ -webkit-margin-end: .375em;
+ margin-inline-end: .375em;
+ border-width: var(--border-width);
+ font-size: inherit;
+ vertical-align: middle;
+ cursor: pointer
+}
+
+ [type=checkbox]::-ms-check, [type=radio]::-ms-check {
+ display: none
+ }
+
+ [type=checkbox]:checked, [type=checkbox]:checked:active, [type=checkbox]:checked:focus, [type=radio]:checked, [type=radio]:checked:active, [type=radio]:checked:focus {
+ --background-color: var(--primary);
+ --border-color: var(--primary);
+ background-image: var(--icon-checkbox);
+ background-position: center;
+ background-size: .75em auto;
+ background-repeat: no-repeat
+ }
+
+ [type=checkbox] ~ label, [type=radio] ~ label {
+ display: inline-block;
+ margin-right: .375em;
+ margin-bottom: 0;
+ cursor: pointer
+ }
+
+ [type=checkbox]:indeterminate {
+ --background-color: var(--primary);
+ --border-color: var(--primary);
+ background-image: var(--icon-minus);
+ background-position: center;
+ background-size: .75em auto;
+ background-repeat: no-repeat
+ }
+
+[type=radio] {
+ border-radius: 50%
+}
+
+ [type=radio]:checked, [type=radio]:checked:active, [type=radio]:checked:focus {
+ --background-color: var(--primary-inverse);
+ border-width: .35em;
+ background-image: none
+ }
+
+[type=checkbox][role=switch] {
+ --background-color: var(--switch-background-color);
+ --border-color: var(--switch-background-color);
+ --color: var(--switch-color);
+ width: 2.25em;
+ height: 1.25em;
+ border: var(--border-width) solid var(--border-color);
+ border-radius: 1.25em;
+ background-color: var(--background-color);
+ line-height: 1.25em
+}
+
+ [type=checkbox][role=switch]:focus {
+ --background-color: var(--switch-background-color);
+ --border-color: var(--switch-background-color)
+ }
+
+ [type=checkbox][role=switch]:checked {
+ --background-color: var(--switch-checked-background-color);
+ --border-color: var(--switch-checked-background-color)
+ }
+
+ [type=checkbox][role=switch]:before {
+ display: block;
+ width: calc(1.25em - (var(--border-width) * 2));
+ height: 100%;
+ border-radius: 50%;
+ background-color: var(--color);
+ content: "";
+ transition: margin .1s ease-in-out
+ }
+
+ [type=checkbox][role=switch]:checked {
+ background-image: none
+ }
+
+ [type=checkbox][role=switch]:checked::before {
+ margin-left: calc(1.125em - var(--border-width));
+ -webkit-margin-start: calc(1.125em - var(--border-width));
+ margin-inline-start: calc(1.125em - var(--border-width))
+ }
+
+ [type=checkbox]:checked[aria-invalid=false], [type=checkbox][aria-invalid=false], [type=checkbox][role=switch]:checked[aria-invalid=false], [type=checkbox][role=switch][aria-invalid=false], [type=radio]:checked[aria-invalid=false], [type=radio][aria-invalid=false] {
+ --border-color: var(--form-element-valid-border-color)
+ }
+
+ [type=checkbox]:checked[aria-invalid=true], [type=checkbox][aria-invalid=true], [type=checkbox][role=switch]:checked[aria-invalid=true], [type=checkbox][role=switch][aria-invalid=true], [type=radio]:checked[aria-invalid=true], [type=radio][aria-invalid=true] {
+ --border-color: var(--form-element-invalid-border-color)
+ }
+
+[type=color]::-webkit-color-swatch-wrapper {
+ padding: 0
+}
+
+[type=color]::-moz-focus-inner {
+ padding: 0
+}
+
+[type=color]::-webkit-color-swatch {
+ border: 0;
+ border-radius: calc(var(--border-radius) * .5)
+}
+
+[type=color]::-moz-color-swatch {
+ border: 0;
+ border-radius: calc(var(--border-radius) * .5)
+}
+
+input:not([type=checkbox],[type=radio],[type=range],[type=file]):is([type=date],[type=datetime-local],[type=month],[type=time],[type=week]) {
+ --icon-position: 0.75rem;
+ --icon-width: 1rem;
+ padding-right: calc(var(--icon-width) + var(--icon-position));
+ background-image: var(--icon-date);
+ background-position: center right var(--icon-position);
+ background-size: var(--icon-width) auto;
+ background-repeat: no-repeat
+}
+
+input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=time] {
+ background-image: var(--icon-time)
+}
+
+[type=date]::-webkit-calendar-picker-indicator, [type=datetime-local]::-webkit-calendar-picker-indicator, [type=month]::-webkit-calendar-picker-indicator, [type=time]::-webkit-calendar-picker-indicator, [type=week]::-webkit-calendar-picker-indicator {
+ width: var(--icon-width);
+ margin-right: calc(var(--icon-width) * -1);
+ margin-left: var(--icon-position);
+ opacity: 0
+}
+
+[dir=rtl] :is([type=date],[type=datetime-local],[type=month],[type=time],[type=week]) {
+ text-align: right
+}
+
+@-moz-document url-prefix() {
+ [type=date], [type=datetime-local], [type=month], [type=time], [type=week] {
+ padding-right: var(--form-element-spacing-horizontal) !important;
+ background-image: none !important
+ }
+}
+
+[type=file] {
+ --color: var(--muted-color);
+ padding: calc(var(--form-element-spacing-vertical) * .5) 0;
+ border: 0;
+ border-radius: 0;
+ background: 0 0
+}
+
+ [type=file]::file-selector-button {
+ --background-color: var(--secondary);
+ --border-color: var(--secondary);
+ --color: var(--secondary-inverse);
+ margin-right: calc(var(--spacing)/ 2);
+ margin-left: 0;
+ -webkit-margin-start: 0;
+ margin-inline-start: 0;
+ -webkit-margin-end: calc(var(--spacing)/ 2);
+ margin-inline-end: calc(var(--spacing)/ 2);
+ padding: calc(var(--form-element-spacing-vertical) * .5) calc(var(--form-element-spacing-horizontal) * .5);
+ border: var(--border-width) solid var(--border-color);
+ border-radius: var(--border-radius);
+ outline: 0;
+ background-color: var(--background-color);
+ box-shadow: var(--box-shadow);
+ color: var(--color);
+ font-weight: var(--font-weight);
+ font-size: 1rem;
+ line-height: var(--line-height);
+ text-align: center;
+ cursor: pointer;
+ transition: background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)
+ }
+
+ [type=file]::file-selector-button:is(:hover,:active,:focus) {
+ --background-color: var(--secondary-hover);
+ --border-color: var(--secondary-hover)
+ }
+
+ [type=file]::-webkit-file-upload-button {
+ --background-color: var(--secondary);
+ --border-color: var(--secondary);
+ --color: var(--secondary-inverse);
+ margin-right: calc(var(--spacing)/ 2);
+ margin-left: 0;
+ -webkit-margin-start: 0;
+ margin-inline-start: 0;
+ -webkit-margin-end: calc(var(--spacing)/ 2);
+ margin-inline-end: calc(var(--spacing)/ 2);
+ padding: calc(var(--form-element-spacing-vertical) * .5) calc(var(--form-element-spacing-horizontal) * .5);
+ border: var(--border-width) solid var(--border-color);
+ border-radius: var(--border-radius);
+ outline: 0;
+ background-color: var(--background-color);
+ box-shadow: var(--box-shadow);
+ color: var(--color);
+ font-weight: var(--font-weight);
+ font-size: 1rem;
+ line-height: var(--line-height);
+ text-align: center;
+ cursor: pointer;
+ -webkit-transition: background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition);
+ transition: background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)
+ }
+
+ [type=file]::-webkit-file-upload-button:is(:hover,:active,:focus) {
+ --background-color: var(--secondary-hover);
+ --border-color: var(--secondary-hover)
+ }
+
+ [type=file]::-ms-browse {
+ --background-color: var(--secondary);
+ --border-color: var(--secondary);
+ --color: var(--secondary-inverse);
+ margin-right: calc(var(--spacing)/ 2);
+ margin-left: 0;
+ margin-inline-start: 0;
+ margin-inline-end: calc(var(--spacing)/ 2);
+ padding: calc(var(--form-element-spacing-vertical) * .5) calc(var(--form-element-spacing-horizontal) * .5);
+ border: var(--border-width) solid var(--border-color);
+ border-radius: var(--border-radius);
+ outline: 0;
+ background-color: var(--background-color);
+ box-shadow: var(--box-shadow);
+ color: var(--color);
+ font-weight: var(--font-weight);
+ font-size: 1rem;
+ line-height: var(--line-height);
+ text-align: center;
+ cursor: pointer;
+ -ms-transition: background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition);
+ transition: background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)
+ }
+
+ [type=file]::-ms-browse:is(:hover,:active,:focus) {
+ --background-color: var(--secondary-hover);
+ --border-color: var(--secondary-hover)
+ }
+
+[type=range] {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ width: 100%;
+ height: 1.25rem;
+ background: 0 0
+}
+
+ [type=range]::-webkit-slider-runnable-track {
+ width: 100%;
+ height: .25rem;
+ border-radius: var(--border-radius);
+ background-color: var(--range-border-color);
+ -webkit-transition: background-color var(--transition),box-shadow var(--transition);
+ transition: background-color var(--transition),box-shadow var(--transition)
+ }
+
+ [type=range]::-moz-range-track {
+ width: 100%;
+ height: .25rem;
+ border-radius: var(--border-radius);
+ background-color: var(--range-border-color);
+ -moz-transition: background-color var(--transition),box-shadow var(--transition);
+ transition: background-color var(--transition),box-shadow var(--transition)
+ }
+
+ [type=range]::-ms-track {
+ width: 100%;
+ height: .25rem;
+ border-radius: var(--border-radius);
+ background-color: var(--range-border-color);
+ -ms-transition: background-color var(--transition),box-shadow var(--transition);
+ transition: background-color var(--transition),box-shadow var(--transition)
+ }
+
+ [type=range]::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ width: 1.25rem;
+ height: 1.25rem;
+ margin-top: -.5rem;
+ border: 2px solid var(--range-thumb-border-color);
+ border-radius: 50%;
+ background-color: var(--range-thumb-color);
+ cursor: pointer;
+ -webkit-transition: background-color var(--transition),transform var(--transition);
+ transition: background-color var(--transition),transform var(--transition)
+ }
+
+ [type=range]::-moz-range-thumb {
+ -webkit-appearance: none;
+ width: 1.25rem;
+ height: 1.25rem;
+ margin-top: -.5rem;
+ border: 2px solid var(--range-thumb-border-color);
+ border-radius: 50%;
+ background-color: var(--range-thumb-color);
+ cursor: pointer;
+ -moz-transition: background-color var(--transition),transform var(--transition);
+ transition: background-color var(--transition),transform var(--transition)
+ }
+
+ [type=range]::-ms-thumb {
+ -webkit-appearance: none;
+ width: 1.25rem;
+ height: 1.25rem;
+ margin-top: -.5rem;
+ border: 2px solid var(--range-thumb-border-color);
+ border-radius: 50%;
+ background-color: var(--range-thumb-color);
+ cursor: pointer;
+ -ms-transition: background-color var(--transition),transform var(--transition);
+ transition: background-color var(--transition),transform var(--transition)
+ }
+
+ [type=range]:focus, [type=range]:hover {
+ --range-border-color: var(--range-active-border-color);
+ --range-thumb-color: var(--range-thumb-hover-color)
+ }
+
+ [type=range]:active {
+ --range-thumb-color: var(--range-thumb-active-color)
+ }
+
+ [type=range]:active::-webkit-slider-thumb {
+ transform: scale(1.25)
+ }
+
+ [type=range]:active::-moz-range-thumb {
+ transform: scale(1.25)
+ }
+
+ [type=range]:active::-ms-thumb {
+ transform: scale(1.25)
+ }
+
+input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search] {
+ -webkit-padding-start: calc(var(--form-element-spacing-horizontal) + 1.75rem);
+ padding-inline-start: calc(var(--form-element-spacing-horizontal) + 1.75rem);
+ border-radius: 5rem;
+ background-image: var(--icon-search);
+ background-position: center left 1.125rem;
+ background-size: 1rem auto;
+ background-repeat: no-repeat
+}
+
+ input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid] {
+ -webkit-padding-start: calc(var(--form-element-spacing-horizontal) + 1.75rem) !important;
+ padding-inline-start: calc(var(--form-element-spacing-horizontal) + 1.75rem) !important;
+ background-position: center left 1.125rem,center right .75rem
+ }
+
+ input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid=false] {
+ background-image: var(--icon-search),var(--icon-valid)
+ }
+
+ input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid=true] {
+ background-image: var(--icon-search),var(--icon-invalid)
+ }
+
+[type=search]::-webkit-search-cancel-button {
+ -webkit-appearance: none;
+ display: none
+}
+
+[dir=rtl] :where(input):not([type=checkbox],[type=radio],[type=range],[type=file])[type=search] {
+ background-position: center right 1.125rem
+}
+
+ [dir=rtl] :where(input):not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid] {
+ background-position: center right 1.125rem,center left .75rem
+ }
+
+:where(table) {
+ width: 100%;
+ border-collapse: collapse;
+ border-spacing: 0;
+ text-indent: 0
+}
+
+td, th {
+ padding: calc(var(--spacing)/ 2) var(--spacing);
+ border-bottom: var(--border-width) solid var(--table-border-color);
+ color: var(--color);
+ font-weight: var(--font-weight);
+ font-size: var(--font-size);
+ text-align: left;
+ text-align: start
+}
+
+tfoot td, tfoot th {
+ border-top: var(--border-width) solid var(--table-border-color);
+ border-bottom: 0
+}
+
+table[role=grid] tbody tr:nth-child(odd) {
+ background-color: var(--table-row-stripped-background-color)
+}
+
+code, kbd, pre, samp {
+ font-size: .875em;
+ font-family: var(--font-family)
+}
+
+pre {
+ -ms-overflow-style: scrollbar;
+ overflow: auto
+}
+
+code, kbd, pre {
+ border-radius: var(--border-radius);
+ background: var(--code-background-color);
+ color: var(--code-color);
+ font-weight: var(--font-weight);
+ line-height: initial
+}
+
+code, kbd {
+ display: inline-block;
+ padding: .375rem .5rem
+}
+
+pre {
+ display: block;
+ margin-bottom: var(--spacing);
+ overflow-x: auto
+}
+
+ pre > code {
+ display: block;
+ padding: var(--spacing);
+ background: 0 0;
+ font-size: 14px;
+ line-height: var(--line-height)
+ }
+
+code b {
+ color: var(--code-tag-color);
+ font-weight: var(--font-weight)
+}
+
+code i {
+ color: var(--code-property-color);
+ font-style: normal
+}
+
+code u {
+ color: var(--code-value-color);
+ text-decoration: none
+}
+
+code em {
+ color: var(--code-comment-color);
+ font-style: normal
+}
+
+kbd {
+ background-color: var(--code-kbd-background-color);
+ color: var(--code-kbd-color);
+ vertical-align: baseline
+}
+
+hr {
+ height: 0;
+ border: 0;
+ border-top: 1px solid var(--muted-border-color);
+ color: inherit
+}
+
+[hidden], template {
+ display: none !important
+}
+
+canvas {
+ display: inline-block
+}
+
+details {
+ display: block;
+ margin-bottom: var(--spacing);
+ padding-bottom: var(--spacing);
+ border-bottom: var(--border-width) solid var(--accordion-border-color)
+}
+
+ details summary {
+ line-height: 1rem;
+ list-style-type: none;
+ cursor: pointer;
+ transition: color var(--transition)
+ }
+
+ details summary:not([role]) {
+ color: var(--accordion-close-summary-color)
+ }
+
+ details summary::-webkit-details-marker {
+ display: none
+ }
+
+ details summary::marker {
+ display: none
+ }
+
+ details summary::-moz-list-bullet {
+ list-style-type: none
+ }
+
+ details summary::after {
+ display: block;
+ width: 1rem;
+ height: 1rem;
+ -webkit-margin-start: calc(var(--spacing,1rem) * 0.5);
+ margin-inline-start: calc(var(--spacing,1rem) * .5);
+ float: right;
+ transform: rotate(-90deg);
+ background-image: var(--icon-chevron);
+ background-position: right center;
+ background-size: 1rem auto;
+ background-repeat: no-repeat;
+ content: "";
+ transition: transform var(--transition)
+ }
+
+ details summary:focus {
+ outline: 0
+ }
+
+ details summary:focus:not([role=button]) {
+ color: var(--accordion-active-summary-color)
+ }
+
+ details summary[role=button] {
+ width: 100%;
+ text-align: left
+ }
+
+ details summary[role=button]::after {
+ height: calc(1rem * var(--line-height,1.5));
+ background-image: var(--icon-chevron-button)
+ }
+
+ details summary[role=button]:not(.outline).contrast::after {
+ background-image: var(--icon-chevron-button-inverse)
+ }
+
+ details[open] > summary {
+ margin-bottom: calc(var(--spacing))
+ }
+
+ details[open] > summary:not([role]):not(:focus) {
+ color: var(--accordion-open-summary-color)
+ }
+
+ details[open] > summary::after {
+ transform: rotate(0)
+ }
+
+[dir=rtl] details summary {
+ text-align: right
+}
+
+ [dir=rtl] details summary::after {
+ float: left;
+ background-position: left center
+ }
+
+article {
+ margin: var(--block-spacing-vertical) 0;
+ padding: var(--block-spacing-vertical) var(--block-spacing-horizontal);
+ border-radius: var(--border-radius);
+ background: var(--card-background-color);
+ box-shadow: var(--card-box-shadow)
+}
+
+ article > footer, article > header {
+ margin-right: calc(var(--block-spacing-horizontal) * -1);
+ margin-left: calc(var(--block-spacing-horizontal) * -1);
+ padding: calc(var(--block-spacing-vertical) * .66) var(--block-spacing-horizontal);
+ background-color: var(--card-sectionning-background-color)
+ }
+
+ article > header {
+ margin-top: calc(var(--block-spacing-vertical) * -1);
+ margin-bottom: var(--block-spacing-vertical);
+ border-bottom: var(--border-width) solid var(--card-border-color);
+ border-top-right-radius: var(--border-radius);
+ border-top-left-radius: var(--border-radius)
+ }
+
+ article > footer {
+ margin-top: var(--block-spacing-vertical);
+ margin-bottom: calc(var(--block-spacing-vertical) * -1);
+ border-top: var(--border-width) solid var(--card-border-color);
+ border-bottom-right-radius: var(--border-radius);
+ border-bottom-left-radius: var(--border-radius)
+ }
+
+:root {
+ --scrollbar-width: 0px
+}
+
+dialog {
+ display: flex;
+ z-index: 999;
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ align-items: center;
+ justify-content: center;
+ width: inherit;
+ min-width: 100%;
+ height: inherit;
+ min-height: 100%;
+ padding: var(--spacing);
+ border: 0;
+ -webkit-backdrop-filter: var(--modal-overlay-backdrop-filter);
+ backdrop-filter: var(--modal-overlay-backdrop-filter);
+ background-color: var(--modal-overlay-background-color);
+ color: var(--color)
+}
+
+ dialog article {
+ max-height: calc(100vh - var(--spacing) * 2);
+ overflow: auto
+ }
+
+@media (min-width:576px) {
+ dialog article {
+ max-width: 510px
+ }
+}
+
+@media (min-width:768px) {
+ dialog article {
+ max-width: 700px
+ }
+}
+
+dialog article > footer, dialog article > header {
+ padding: calc(var(--block-spacing-vertical) * .5) var(--block-spacing-horizontal)
+}
+
+ dialog article > header .close {
+ margin: 0;
+ margin-left: var(--spacing);
+ float: right
+ }
+
+dialog article > footer {
+ text-align: right
+}
+
+ dialog article > footer [role=button] {
+ margin-bottom: 0
+ }
+
+ dialog article > footer [role=button]:not(:first-of-type) {
+ margin-left: calc(var(--spacing) * .5)
+ }
+
+dialog article p:last-of-type {
+ margin: 0
+}
+
+dialog article .close {
+ display: block;
+ width: 1rem;
+ height: 1rem;
+ margin-top: calc(var(--block-spacing-vertical) * -.5);
+ margin-bottom: var(--typography-spacing-vertical);
+ margin-left: auto;
+ background-image: var(--icon-close);
+ background-position: center;
+ background-size: auto 1rem;
+ background-repeat: no-repeat;
+ opacity: .5;
+ transition: opacity var(--transition)
+}
+
+ dialog article .close:is([aria-current],:hover,:active,:focus) {
+ opacity: 1
+ }
+
+dialog:not([open]), dialog[open=false] {
+ display: none
+}
+
+.modal-is-open {
+ padding-right: var(--scrollbar-width,0);
+ overflow: hidden;
+ pointer-events: none;
+ touch-action: none
+}
+
+ .modal-is-open dialog {
+ pointer-events: auto
+ }
+
+:where(.modal-is-opening,.modal-is-closing) dialog, :where(.modal-is-opening,.modal-is-closing) dialog > article {
+ animation-duration: .2s;
+ animation-timing-function: ease-in-out;
+ animation-fill-mode: both
+}
+
+:where(.modal-is-opening,.modal-is-closing) dialog {
+ animation-duration: .8s;
+ animation-name: modal-overlay
+}
+
+ :where(.modal-is-opening,.modal-is-closing) dialog > article {
+ animation-delay: .2s;
+ animation-name: modal
+ }
+
+.modal-is-closing dialog, .modal-is-closing dialog > article {
+ animation-delay: 0s;
+ animation-direction: reverse
+}
+
+@keyframes modal-overlay {
+ from {
+ -webkit-backdrop-filter: none;
+ backdrop-filter: none;
+ background-color: transparent
+ }
+}
+
+@keyframes modal {
+ from {
+ transform: translateY(-100%);
+ opacity: 0
+ }
+}
+
+:where(nav li)::before {
+ float: left;
+ content: ""
+}
+
+nav, nav ul {
+ display: flex
+}
+
+nav {
+ justify-content: space-between
+}
+
+ nav ol, nav ul {
+ align-items: center;
+ margin-bottom: 0;
+ padding: 0;
+ list-style: none
+ }
+
+ nav ol:first-of-type, nav ul:first-of-type {
+ margin-left: calc(var(--nav-element-spacing-horizontal) * -1)
+ }
+
+ nav ol:last-of-type, nav ul:last-of-type {
+ margin-right: calc(var(--nav-element-spacing-horizontal) * -1)
+ }
+
+ nav li {
+ display: inline-block;
+ margin: 0;
+ padding: var(--nav-element-spacing-vertical) var(--nav-element-spacing-horizontal)
+ }
+
+ nav li > * {
+ --spacing: 0
+ }
+
+ nav :where(a,[role=link]) {
+ display: inline-block;
+ margin: calc(var(--nav-link-spacing-vertical) * -1) calc(var(--nav-link-spacing-horizontal) * -1);
+ padding: var(--nav-link-spacing-vertical) var(--nav-link-spacing-horizontal);
+ border-radius: var(--border-radius);
+ text-decoration: none
+ }
+
+ nav :where(a,[role=link]):is([aria-current],:hover,:active,:focus) {
+ text-decoration: none
+ }
+
+ nav[aria-label=breadcrumb] {
+ align-items: center;
+ justify-content: start
+ }
+
+ nav[aria-label=breadcrumb] ul li:not(:first-child) {
+ -webkit-margin-start: var(--nav-link-spacing-horizontal);
+ margin-inline-start: var(--nav-link-spacing-horizontal)
+ }
+
+ nav[aria-label=breadcrumb] ul li:not(:last-child) ::after {
+ position: absolute;
+ width: calc(var(--nav-link-spacing-horizontal) * 2);
+ -webkit-margin-start: calc(var(--nav-link-spacing-horizontal)/ 2);
+ margin-inline-start: calc(var(--nav-link-spacing-horizontal)/ 2);
+ content: "/";
+ color: var(--muted-color);
+ text-align: center
+ }
+
+ nav[aria-label=breadcrumb] a[aria-current] {
+ background-color: transparent;
+ color: inherit;
+ text-decoration: none;
+ pointer-events: none
+ }
+
+ nav [role=button] {
+ margin-right: inherit;
+ margin-left: inherit;
+ padding: var(--nav-link-spacing-vertical) var(--nav-link-spacing-horizontal)
+ }
+
+aside li, aside nav, aside ol, aside ul {
+ display: block
+}
+
+aside li {
+ padding: calc(var(--nav-element-spacing-vertical) * .5) var(--nav-element-spacing-horizontal)
+}
+
+ aside li a {
+ display: block
+ }
+
+ aside li [role=button] {
+ margin: inherit
+ }
+
+[dir=rtl] nav[aria-label=breadcrumb] ul li:not(:last-child) ::after {
+ content: "\\"
+}
+
+progress {
+ display: inline-block;
+ vertical-align: baseline
+}
+
+progress {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ display: inline-block;
+ appearance: none;
+ width: 100%;
+ height: .5rem;
+ margin-bottom: calc(var(--spacing) * .5);
+ overflow: hidden;
+ border: 0;
+ border-radius: var(--border-radius);
+ background-color: var(--progress-background-color);
+ color: var(--progress-color)
+}
+
+ progress::-webkit-progress-bar {
+ border-radius: var(--border-radius);
+ background: 0 0
+ }
+
+ progress[value]::-webkit-progress-value {
+ background-color: var(--progress-color)
+ }
+
+ progress::-moz-progress-bar {
+ background-color: var(--progress-color)
+ }
+
+@media (prefers-reduced-motion:no-preference) {
+ progress:indeterminate {
+ background: var(--progress-background-color) linear-gradient(to right,var(--progress-color) 30%,var(--progress-background-color) 30%) top left/150% 150% no-repeat;
+ animation: progress-indeterminate 1s linear infinite
+ }
+
+ progress:indeterminate[value]::-webkit-progress-value {
+ background-color: transparent
+ }
+
+ progress:indeterminate::-moz-progress-bar {
+ background-color: transparent
+ }
+}
+
+@media (prefers-reduced-motion:no-preference) {
+ [dir=rtl] progress:indeterminate {
+ animation-direction: reverse
+ }
+}
+
+@keyframes progress-indeterminate {
+ 0% {
+ background-position: 200% 0
+ }
+
+ 100% {
+ background-position: -200% 0
+ }
+}
+
+details[role=list], li[role=list] {
+ position: relative
+}
+
+ details[role=list] summary + ul, li[role=list] > ul {
+ display: flex;
+ z-index: 99;
+ position: absolute;
+ top: auto;
+ right: 0;
+ left: 0;
+ flex-direction: column;
+ margin: 0;
+ padding: 0;
+ border: var(--border-width) solid var(--dropdown-border-color);
+ border-radius: var(--border-radius);
+ border-top-right-radius: 0;
+ border-top-left-radius: 0;
+ background-color: var(--dropdown-background-color);
+ box-shadow: var(--card-box-shadow);
+ color: var(--dropdown-color);
+ white-space: nowrap
+ }
+
+ details[role=list] summary + ul li, li[role=list] > ul li {
+ width: 100%;
+ margin-bottom: 0;
+ padding: calc(var(--form-element-spacing-vertical) * .5) var(--form-element-spacing-horizontal);
+ list-style: none
+ }
+
+ details[role=list] summary + ul li:first-of-type, li[role=list] > ul li:first-of-type {
+ margin-top: calc(var(--form-element-spacing-vertical) * .5)
+ }
+
+ details[role=list] summary + ul li:last-of-type, li[role=list] > ul li:last-of-type {
+ margin-bottom: calc(var(--form-element-spacing-vertical) * .5)
+ }
+
+ details[role=list] summary + ul li a, li[role=list] > ul li a {
+ display: block;
+ margin: calc(var(--form-element-spacing-vertical) * -.5) calc(var(--form-element-spacing-horizontal) * -1);
+ padding: calc(var(--form-element-spacing-vertical) * .5) var(--form-element-spacing-horizontal);
+ overflow: hidden;
+ color: var(--dropdown-color);
+ text-decoration: none;
+ text-overflow: ellipsis
+ }
+
+ details[role=list] summary + ul li a:hover, li[role=list] > ul li a:hover {
+ background-color: var(--dropdown-hover-background-color)
+ }
+
+ details[role=list] summary::after, li[role=list] > a::after {
+ display: block;
+ width: 1rem;
+ height: calc(1rem * var(--line-height,1.5));
+ -webkit-margin-start: 0.5rem;
+ margin-inline-start: .5rem;
+ float: right;
+ transform: rotate(0);
+ background-position: right center;
+ background-size: 1rem auto;
+ background-repeat: no-repeat;
+ content: ""
+ }
+
+details[role=list] {
+ padding: 0;
+ border-bottom: none
+}
+
+ details[role=list] summary {
+ margin-bottom: 0
+ }
+
+ details[role=list] summary:not([role]) {
+ height: calc(1rem * var(--line-height) + var(--form-element-spacing-vertical) * 2 + var(--border-width) * 2);
+ padding: var(--form-element-spacing-vertical) var(--form-element-spacing-horizontal);
+ border: var(--border-width) solid var(--form-element-border-color);
+ border-radius: var(--border-radius);
+ background-color: var(--form-element-background-color);
+ color: var(--form-element-placeholder-color);
+ line-height: inherit;
+ cursor: pointer;
+ transition: background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)
+ }
+
+ details[role=list] summary:not([role]):active, details[role=list] summary:not([role]):focus {
+ border-color: var(--form-element-active-border-color);
+ background-color: var(--form-element-active-background-color)
+ }
+
+ details[role=list] summary:not([role]):focus {
+ box-shadow: 0 0 0 var(--outline-width) var(--form-element-focus-color)
+ }
+
+ details[role=list][open] summary {
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0
+ }
+
+ details[role=list][open] summary::before {
+ display: block;
+ z-index: 1;
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ background: 0 0;
+ content: "";
+ cursor: default
+ }
+
+nav details[role=list] summary, nav li[role=list] a {
+ display: flex;
+ direction: ltr
+}
+
+ nav details[role=list] summary + ul, nav li[role=list] > ul {
+ min-width: -moz-fit-content;
+ min-width: fit-content;
+ border-radius: var(--border-radius)
+ }
+
+ nav details[role=list] summary + ul li a, nav li[role=list] > ul li a {
+ border-radius: 0
+ }
+
+ nav details[role=list] summary, nav details[role=list] summary:not([role]) {
+ height: auto;
+ padding: var(--nav-link-spacing-vertical) var(--nav-link-spacing-horizontal)
+ }
+
+nav details[role=list][open] summary {
+ border-radius: var(--border-radius)
+}
+
+nav details[role=list] summary + ul {
+ margin-top: var(--outline-width);
+ -webkit-margin-start: 0;
+ margin-inline-start: 0
+}
+
+nav details[role=list] summary[role=link] {
+ margin-bottom: calc(var(--nav-link-spacing-vertical) * -1);
+ line-height: var(--line-height)
+}
+
+ nav details[role=list] summary[role=link] + ul {
+ margin-top: calc(var(--nav-link-spacing-vertical) + var(--outline-width));
+ -webkit-margin-start: calc(var(--nav-link-spacing-horizontal) * -1);
+ margin-inline-start: calc(var(--nav-link-spacing-horizontal) * -1)
+ }
+
+li[role=list] a:active ~ ul, li[role=list] a:focus ~ ul, li[role=list]:hover > ul {
+ display: flex
+}
+
+li[role=list] > ul {
+ display: none;
+ margin-top: calc(var(--nav-link-spacing-vertical) + var(--outline-width));
+ -webkit-margin-start: calc(var(--nav-element-spacing-horizontal) - var(--nav-link-spacing-horizontal));
+ margin-inline-start: calc(var(--nav-element-spacing-horizontal) - var(--nav-link-spacing-horizontal))
+}
+
+li[role=list] > a::after {
+ background-image: var(--icon-chevron)
+}
+
+label > details[role=list] {
+ margin-top: calc(var(--spacing) * .25);
+ margin-bottom: var(--spacing)
+}
+
+[aria-busy=true] {
+ cursor: progress
+}
+
+ [aria-busy=true]:not(input,select,textarea,html)::before {
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+ border: .1875em solid currentColor;
+ border-radius: 1em;
+ border-right-color: transparent;
+ content: "";
+ vertical-align: text-bottom;
+ vertical-align: -.125em;
+ animation: spinner .75s linear infinite;
+ opacity: var(--loading-spinner-opacity)
+ }
+
+ [aria-busy=true]:not(input,select,textarea,html):not(:empty)::before {
+ margin-right: calc(var(--spacing) * .5);
+ margin-left: 0;
+ -webkit-margin-start: 0;
+ margin-inline-start: 0;
+ -webkit-margin-end: calc(var(--spacing) * .5);
+ margin-inline-end: calc(var(--spacing) * .5)
+ }
+
+ [aria-busy=true]:not(input,select,textarea,html):empty {
+ text-align: center
+ }
+
+a[aria-busy=true], button[aria-busy=true], input[type=button][aria-busy=true], input[type=reset][aria-busy=true], input[type=submit][aria-busy=true] {
+ pointer-events: none
+}
+
+@keyframes spinner {
+ to {
+ transform: rotate(360deg)
+ }
+}
+
+[data-tooltip] {
+ position: relative
+}
+
+ [data-tooltip]:not(a,button,input) {
+ border-bottom: 1px dotted;
+ text-decoration: none;
+ cursor: help
+ }
+
+ [data-tooltip]::after, [data-tooltip]::before, [data-tooltip][data-placement=top]::after, [data-tooltip][data-placement=top]::before {
+ display: block;
+ z-index: 99;
+ position: absolute;
+ bottom: 100%;
+ left: 50%;
+ padding: .25rem .5rem;
+ overflow: hidden;
+ transform: translate(-50%,-.25rem);
+ border-radius: var(--border-radius);
+ background: var(--tooltip-background-color);
+ content: attr(data-tooltip);
+ color: var(--tooltip-color);
+ font-style: normal;
+ font-weight: var(--font-weight);
+ font-size: .875rem;
+ text-decoration: none;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ opacity: 0;
+ pointer-events: none
+ }
+
+ [data-tooltip]::after, [data-tooltip][data-placement=top]::after {
+ padding: 0;
+ transform: translate(-50%,0);
+ border-top: .3rem solid;
+ border-right: .3rem solid transparent;
+ border-left: .3rem solid transparent;
+ border-radius: 0;
+ background-color: transparent;
+ content: "";
+ color: var(--tooltip-background-color)
+ }
+
+ [data-tooltip][data-placement=bottom]::after, [data-tooltip][data-placement=bottom]::before {
+ top: 100%;
+ bottom: auto;
+ transform: translate(-50%,.25rem)
+ }
+
+ [data-tooltip][data-placement=bottom]:after {
+ transform: translate(-50%,-.3rem);
+ border: .3rem solid transparent;
+ border-bottom: .3rem solid
+ }
+
+ [data-tooltip][data-placement=left]::after, [data-tooltip][data-placement=left]::before {
+ top: 50%;
+ right: 100%;
+ bottom: auto;
+ left: auto;
+ transform: translate(-.25rem,-50%)
+ }
+
+ [data-tooltip][data-placement=left]:after {
+ transform: translate(.3rem,-50%);
+ border: .3rem solid transparent;
+ border-left: .3rem solid
+ }
+
+ [data-tooltip][data-placement=right]::after, [data-tooltip][data-placement=right]::before {
+ top: 50%;
+ right: auto;
+ bottom: auto;
+ left: 100%;
+ transform: translate(.25rem,-50%)
+ }
+
+ [data-tooltip][data-placement=right]:after {
+ transform: translate(-.3rem,-50%);
+ border: .3rem solid transparent;
+ border-right: .3rem solid
+ }
+
+ [data-tooltip]:focus::after, [data-tooltip]:focus::before, [data-tooltip]:hover::after, [data-tooltip]:hover::before {
+ opacity: 1
+ }
+
+@media (hover:hover) and (pointer:fine) {
+ [data-tooltip]:hover::after, [data-tooltip]:hover::before, [data-tooltip][data-placement=bottom]:focus::after, [data-tooltip][data-placement=bottom]:focus::before, [data-tooltip][data-placement=bottom]:hover [data-tooltip]:focus::after, [data-tooltip][data-placement=bottom]:hover [data-tooltip]:focus::before {
+ animation-duration: .2s;
+ animation-name: tooltip-slide-top
+ }
+
+ [data-tooltip]:hover::after, [data-tooltip][data-placement=bottom]:focus::after, [data-tooltip][data-placement=bottom]:hover [data-tooltip]:focus::after {
+ animation-name: tooltip-caret-slide-top
+ }
+
+ [data-tooltip][data-placement=bottom]:focus::after, [data-tooltip][data-placement=bottom]:focus::before, [data-tooltip][data-placement=bottom]:hover::after, [data-tooltip][data-placement=bottom]:hover::before {
+ animation-duration: .2s;
+ animation-name: tooltip-slide-bottom
+ }
+
+ [data-tooltip][data-placement=bottom]:focus::after, [data-tooltip][data-placement=bottom]:hover::after {
+ animation-name: tooltip-caret-slide-bottom
+ }
+
+ [data-tooltip][data-placement=left]:focus::after, [data-tooltip][data-placement=left]:focus::before, [data-tooltip][data-placement=left]:hover::after, [data-tooltip][data-placement=left]:hover::before {
+ animation-duration: .2s;
+ animation-name: tooltip-slide-left
+ }
+
+ [data-tooltip][data-placement=left]:focus::after, [data-tooltip][data-placement=left]:hover::after {
+ animation-name: tooltip-caret-slide-left
+ }
+
+ [data-tooltip][data-placement=right]:focus::after, [data-tooltip][data-placement=right]:focus::before, [data-tooltip][data-placement=right]:hover::after, [data-tooltip][data-placement=right]:hover::before {
+ animation-duration: .2s;
+ animation-name: tooltip-slide-right
+ }
+
+ [data-tooltip][data-placement=right]:focus::after, [data-tooltip][data-placement=right]:hover::after {
+ animation-name: tooltip-caret-slide-right
+ }
+}
+
+@keyframes tooltip-slide-top {
+ from {
+ transform: translate(-50%,.75rem);
+ opacity: 0
+ }
+
+ to {
+ transform: translate(-50%,-.25rem);
+ opacity: 1
+ }
+}
+
+@keyframes tooltip-caret-slide-top {
+ from {
+ opacity: 0
+ }
+
+ 50% {
+ transform: translate(-50%,-.25rem);
+ opacity: 0
+ }
+
+ to {
+ transform: translate(-50%,0);
+ opacity: 1
+ }
+}
+
+@keyframes tooltip-slide-bottom {
+ from {
+ transform: translate(-50%,-.75rem);
+ opacity: 0
+ }
+
+ to {
+ transform: translate(-50%,.25rem);
+ opacity: 1
+ }
+}
+
+@keyframes tooltip-caret-slide-bottom {
+ from {
+ opacity: 0
+ }
+
+ 50% {
+ transform: translate(-50%,-.5rem);
+ opacity: 0
+ }
+
+ to {
+ transform: translate(-50%,-.3rem);
+ opacity: 1
+ }
+}
+
+@keyframes tooltip-slide-left {
+ from {
+ transform: translate(.75rem,-50%);
+ opacity: 0
+ }
+
+ to {
+ transform: translate(-.25rem,-50%);
+ opacity: 1
+ }
+}
+
+@keyframes tooltip-caret-slide-left {
+ from {
+ opacity: 0
+ }
+
+ 50% {
+ transform: translate(.05rem,-50%);
+ opacity: 0
+ }
+
+ to {
+ transform: translate(.3rem,-50%);
+ opacity: 1
+ }
+}
+
+@keyframes tooltip-slide-right {
+ from {
+ transform: translate(-.75rem,-50%);
+ opacity: 0
+ }
+
+ to {
+ transform: translate(.25rem,-50%);
+ opacity: 1
+ }
+}
+
+@keyframes tooltip-caret-slide-right {
+ from {
+ opacity: 0
+ }
+
+ 50% {
+ transform: translate(-.05rem,-50%);
+ opacity: 0
+ }
+
+ to {
+ transform: translate(-.3rem,-50%);
+ opacity: 1
+ }
+}
+
+[aria-controls] {
+ cursor: pointer
+}
+
+[aria-disabled=true], [disabled] {
+ cursor: not-allowed
+}
+
+[aria-hidden=false][hidden] {
+ display: initial
+}
+
+ [aria-hidden=false][hidden]:not(:focus) {
+ clip: rect(0,0,0,0);
+ position: absolute
+ }
+
+[tabindex], a, area, button, input, label, select, summary, textarea {
+ -ms-touch-action: manipulation
+}
+
+[dir=rtl] {
+ direction: rtl
+}
+
+@media (prefers-reduced-motion:reduce) {
+ :not([aria-busy=true]), :not([aria-busy=true])::after, :not([aria-busy=true])::before {
+ background-attachment: initial !important;
+ animation-duration: 1ms !important;
+ animation-delay: -1ms !important;
+ animation-iteration-count: 1 !important;
+ scroll-behavior: auto !important;
+ transition-delay: 0s !important;
+ transition-duration: 0s !important
+ }
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/remoteview.html b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/remoteview.html
new file mode 100644
index 0000000..7f73739
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/remoteview.html
@@ -0,0 +1,33 @@
+
+
+
+
+
+ PrometheOS
+
+
+
+
+
+
+
+
+
+
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/remoteview.js b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/remoteview.js
new file mode 100644
index 0000000..385e405
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/remoteview.js
@@ -0,0 +1,19 @@
+window.onload = function () {
+ screenshot();
+};
+async function screenshot() {
+ await fetch("http://192.168.1.66/api/screenshot").catch(error => {
+ content.innerHTML = "Failed to connect."
+ }).then(response => response.blob()).then(blob => {
+ var url = window.URL.createObjectURL(blob);
+
+ var img = document.createElement('img');
+ img.src = url;
+ img.alt = "Screenshot";
+ img.style = "max-width: 100%; height: auto";
+
+ const content = document.getElementById('content');
+ content.innerHTML = "";
+ content.appendChild(img);
+ });
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/remove.html b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/remove.html
new file mode 100644
index 0000000..f857c0f
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/remove.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+ PrometheOS
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/remove.js b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/remove.js
new file mode 100644
index 0000000..42c6c14
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSUtility/PrometheOSWeb/wwwroot/remove.js
@@ -0,0 +1,35 @@
+window.onload = function () {
+ getBankInfo();
+};
+
+async function getBankInfo()
+{
+ await fetch("http://192.168.1.66/api/bankinfo.json").then(async response => {
+
+ const json = await response.json();
+
+ let contentBody = "";
+ for (let i = 0; i < json.length; i++) {
+ if (json[i].slots > 0) {
+ contentBody += "
";
+ }
+ }
+ let content = document.getElementById("content");
+ content.innerHTML = contentBody == "" ? "No items found." : contentBody;
+
+ }).catch(error => {
+
+ let content = document.getElementById("content");
+ content.innerHTML = "Failed to connect."
+
+ });
+}
+
+async function removeBank(id)
+{
+ await fetch("http://192.168.1.66/api/removebank?" + id).then(() => {
+ getBankInfo();
+ }).catch(error => {
+ content.innerHTML = "Failed to connect."
+ });
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/.gitignore b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/.gitignore
new file mode 100644
index 0000000..d253d59
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/.gitignore
@@ -0,0 +1,29 @@
+*.suo
+*.user
+*.ncb
+
+[Dd]ebug/
+[Dd]ebug-Tools/
+[Dd]ebug-Xenium/
+[Dd]ebug-Xtremium/
+[Dd]ebug-Xecuter/
+[Dd]ebug-Xchanger/
+[Dd]ebug-Smartxx/
+[Dd]ebug-Modxo/
+[Dd]ebug-Aladdin1mb/
+[Dd]ebug-Aladdin2mb/
+[Dd]ebug-Dummy/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]elease-Tools/
+[Rr]elease-Xenium/
+[Rr]elease-Xtremium/
+[Rr]elease-Xecuter/
+[Rr]elease-Xchanger/
+[Rr]elease-Smartxx/
+[Rr]elease-Modxo/
+[Rr]elease-Aladdin1mb/
+[Rr]elease-Aladdin2mb/
+[Rr]elease-Dummy/
+[Rr]eleases/
+
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/Bundler.exe b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/Bundler.exe
new file mode 100644
index 0000000..ee7b791
Binary files /dev/null and b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/Bundler.exe differ
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/Icon.png b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/Icon.png
new file mode 100644
index 0000000..fd98610
Binary files /dev/null and b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/Icon.png differ
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/Icon.psd b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/Icon.psd
new file mode 100644
index 0000000..469aaa3
Binary files /dev/null and b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/Icon.psd differ
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/runme.bat b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/runme.bat
new file mode 100644
index 0000000..0b9eab5
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/runme.bat
@@ -0,0 +1 @@
+bundler titleimage.rdf
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/titleimage.bmp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/titleimage.bmp
new file mode 100644
index 0000000..d7b46fb
Binary files /dev/null and b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/titleimage.bmp differ
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/titleimage.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/titleimage.h
new file mode 100644
index 0000000..78d5c8f
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/titleimage.h
@@ -0,0 +1,5 @@
+// Automatically generated by the bundler tool from titleimage.rdf
+
+#define titleimage_NUM_RESOURCES 1UL
+
+#define titleimage_titleimage_OFFSET 0UL
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/titleimage.rdf b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/titleimage.rdf
new file mode 100644
index 0000000..6a467e2
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/titleimage.rdf
@@ -0,0 +1,7 @@
+Texture titleimage
+{
+ Source titleimage.bmp
+ Format D3DFMT_DXT1
+ Width 128
+ Height 128
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/titleimage.xpr b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/titleimage.xpr
new file mode 100644
index 0000000..b1de6b6
Binary files /dev/null and b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Artwork/Icon/titleimage.xpr differ
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Assets/ArialBold.sfd b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Assets/ArialBold.sfd
new file mode 100644
index 0000000..0813277
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Assets/ArialBold.sfd
@@ -0,0 +1,17466 @@
+SplineFontDB: 3.2
+FontName: ArialRoundedMTBold
+FullName: Arial Rounded MT Bold
+FamilyName: Arial Rounded MT Bold
+Weight: Book
+Copyright: Copyright (c) 1993 , Monotype Typography ltd.
+Version: 1.51
+ItalicAngle: 0
+UnderlinePosition: -256
+UnderlineWidth: 102
+Ascent: 1638
+Descent: 410
+InvalidEm: 0
+sfntRevision: 0x0001828f
+LayerCount: 2
+Layer: 0 1 "Back" 1
+Layer: 1 1 "Fore" 0
+XUID: [1021 280 -22418016 15243]
+StyleMap: 0x0040
+FSType: 8
+OS2Version: 1
+OS2_WeightWidthSlopeOnly: 0
+OS2_UseTypoMetrics: 0
+CreationTime: 806935405
+ModificationTime: 1699256171
+PfmFamily: 17
+TTFWeight: 400
+TTFWidth: 5
+LineGap: 0
+VLineGap: 0
+Panose: 2 15 7 4 3 5 4 3 2 4
+OS2TypoAscent: 1491
+OS2TypoAOffset: 0
+OS2TypoDescent: -430
+OS2TypoDOffset: 0
+OS2TypoLinegap: 270
+OS2WinAscent: 1938
+OS2WinAOffset: 0
+OS2WinDescent: 432
+OS2WinDOffset: 0
+HheadAscent: 1938
+HheadAOffset: 0
+HheadDescent: -432
+HheadDOffset: 0
+OS2SubXSize: 1434
+OS2SubYSize: 1331
+OS2SubXOff: 0
+OS2SubYOff: 129
+OS2SupXSize: 1434
+OS2SupYSize: 1331
+OS2SupXOff: 0
+OS2SupYOff: 447
+OS2StrikeYSize: 102
+OS2StrikeYPos: 530
+OS2FamilyClass: 2053
+OS2Vendor: 'MONO'
+OS2CodePages: 20000001.00000000
+OS2UnicodeRanges: 00000003.00000000.00000000.00000000
+Lookup: 258 0 0 "'kern' Horizontal Kerning in Latin lookup 0" { "'kern' Horizontal Kerning in Latin lookup 0 subtable" } ['kern' ('DFLT' <'dflt' > 'latn' <'dflt' > ) ]
+DEI: 91125
+TtTable: prep
+NPUSHB
+ 81
+ 64
+ 86
+ 58
+ 5
+ 57
+ 54
+ 54
+ 4
+ 53
+ 52
+ 52
+ 4
+ 51
+ 48
+ 48
+ 4
+ 47
+ 45
+ 46
+ 4
+ 44
+ 32
+ 41
+ 4
+ 31
+ 32
+ 5
+ 31
+ 14
+ 31
+ 4
+ 13
+ 14
+ 5
+ 0
+ 52
+ 176
+ 160
+ 5
+ 159
+ 146
+ 157
+ 4
+ 145
+ 146
+ 5
+ 145
+ 139
+ 141
+ 4
+ 138
+ 131
+ 136
+ 4
+ 130
+ 131
+ 5
+ 130
+ 87
+ 128
+ 4
+ 86
+ 87
+ 5
+ 0
+ 136
+ 0
+ 13
+ 12
+ 11
+ 10
+ 9
+ 8
+ 7
+ 6
+ 8
+ 6
+ 73
+ 0
+ 48
+ 0
+SCANTYPE
+PUSHW_1
+ 868
+SCANCTRL
+SCVTCI
+SZPS
+SVTCA[y-axis]
+SROUND
+LOOPCALL
+SMD
+RTG
+MIAP[rnd]
+CALL
+CALL
+CALL
+CALL
+CALL
+CALL
+CALL
+CALL
+RTG
+MIAP[rnd]
+CALL
+CALL
+CALL
+CALL
+CALL
+CALL
+CALL
+CALL
+CALL
+SMD
+RTG
+EndTTInstrs
+TtTable: fpgm
+PUSHB_5
+ 15
+ 14
+ 13
+ 12
+ 11
+PUSHB_5
+ 10
+ 9
+ 8
+ 7
+ 6
+PUSHB_5
+ 5
+ 4
+ 3
+ 2
+ 1
+PUSHB_1
+ 0
+FDEF
+PUSHB_2
+ 1
+ 3
+CINDEX
+WS
+DUP
+GC[cur]
+DUP
+ROUND[Grey]
+SUB
+ABS
+PUSHB_1
+ 3
+CINDEX
+GC[cur]
+DUP
+ROUND[Grey]
+SUB
+ABS
+GTEQ
+IF
+SWAP
+MDAP[rnd]
+SWAP
+MIRP[rp0,min,rnd,black]
+ELSE
+MDAP[rnd]
+SWAP
+MIRP[min,rnd,black]
+EIF
+SLOOP
+IP
+SLOOP
+ALIGNRP
+DUP
+PUSHB_1
+ 0
+NEQ
+IF
+PUSHB_1
+ 3
+LOOPCALL
+ELSE
+POP
+EIF
+PUSHB_1
+ 1
+RS
+SRP0
+SLOOP
+ALIGNRP
+DUP
+PUSHB_1
+ 0
+NEQ
+IF
+PUSHB_1
+ 3
+LOOPCALL
+ELSE
+POP
+EIF
+ENDF
+FDEF
+SRP1
+SRP2
+SLOOP
+IP
+ENDF
+FDEF
+SRP0
+SLOOP
+ALIGNRP
+ENDF
+FDEF
+MDRP[black]
+ENDF
+FDEF
+PUSHB_1
+ 69
+SROUND
+PUSHB_1
+ 1
+SWAP
+MIAP[no-rnd]
+PUSHB_1
+ 0
+SRP0
+PUSHB_1
+ 1
+MDRP[rp0,rnd,grey]
+PUSHB_1
+ 0
+SWAP
+WS
+PUSHB_1
+ 1
+SWAP
+WS
+PUSHB_1
+ 73
+SROUND
+PUSHB_1
+ 2
+DUP
+DUP
+PUSHB_1
+ 0
+RS
+MIAP[no-rnd]
+PUSHB_1
+ 1
+SRP0
+MDRP[rnd,grey]
+GC[cur]
+PUSHB_1
+ 0
+RS
+SWAP
+WCVTP
+PUSHB_1
+ 1
+RS
+PUSHB_1
+ 0
+RS
+PUSHB_1
+ 1
+ADD
+DUP
+PUSHB_1
+ 0
+SWAP
+WS
+GTEQ
+PUSHB_1
+ 37
+NEG
+SWAP
+JROT
+ENDF
+FDEF
+PUSHB_1
+ 69
+SROUND
+PUSHB_1
+ 0
+SWAP
+WS
+PUSHB_1
+ 1
+SWAP
+WS
+PUSHB_1
+ 2
+DUP
+DUP
+PUSHB_1
+ 0
+RS
+MIAP[no-rnd]
+PUSHB_1
+ 0
+SRP0
+MDRP[rnd,grey]
+GC[cur]
+PUSHB_1
+ 0
+RS
+SWAP
+WCVTP
+PUSHB_1
+ 1
+RS
+PUSHB_1
+ 0
+RS
+PUSHB_1
+ 1
+ADD
+DUP
+PUSHB_1
+ 0
+SWAP
+WS
+GTEQ
+PUSHB_1
+ 37
+NEG
+SWAP
+JROT
+ENDF
+FDEF
+DUP
+RCVT
+ROUND[Grey]
+WCVTP
+ENDF
+FDEF
+CALL
+ENDF
+FDEF
+PUSHB_2
+ 1
+ 5
+CINDEX
+WS
+MIAP[rnd]
+MIRP[min,rnd,black]
+SLOOP
+IP
+SLOOP
+ALIGNRP
+DUP
+PUSHB_1
+ 0
+NEQ
+IF
+PUSHB_1
+ 3
+LOOPCALL
+ELSE
+POP
+EIF
+PUSHB_1
+ 1
+RS
+SRP0
+SLOOP
+ALIGNRP
+DUP
+PUSHB_1
+ 0
+NEQ
+IF
+PUSHB_1
+ 3
+LOOPCALL
+ELSE
+POP
+EIF
+ENDF
+FDEF
+PUSHB_2
+ 1
+ 3
+CINDEX
+WS
+MIAP[rnd]
+MIRP[rp0,min,rnd,black]
+SLOOP
+IP
+SLOOP
+ALIGNRP
+DUP
+PUSHB_1
+ 0
+NEQ
+IF
+PUSHB_1
+ 3
+LOOPCALL
+ELSE
+POP
+EIF
+PUSHB_1
+ 1
+RS
+SRP0
+SLOOP
+ALIGNRP
+DUP
+PUSHB_1
+ 0
+NEQ
+IF
+PUSHB_1
+ 3
+LOOPCALL
+ELSE
+POP
+EIF
+ENDF
+FDEF
+DUP
+GC[cur]
+DUP
+ROUND[Grey]
+SUB
+ABS
+PUSHB_1
+ 3
+CINDEX
+GC[cur]
+DUP
+ROUND[Grey]
+SUB
+ABS
+GTEQ
+IF
+SWAP
+EIF
+MDAP[rnd]
+SWAP
+MIRP[min,rnd,black]
+ENDF
+FDEF
+MIAP[rnd]
+MIRP[min,rnd,black]
+ENDF
+FDEF
+MIAP[rnd]
+MIRP[rp0,min,rnd,black]
+ENDF
+FDEF
+DUP
+GC[cur]
+DUP
+ROUND[Grey]
+SUB
+ABS
+PUSHB_1
+ 3
+CINDEX
+GC[cur]
+DUP
+ROUND[Grey]
+SUB
+ABS
+GTEQ
+IF
+SWAP
+EIF
+MDAP[rnd]
+SWAP
+MIRP[min,rnd,black]
+SLOOP
+IP
+ENDF
+FDEF
+DUP
+GC[cur]
+DUP
+ROUND[Grey]
+SUB
+ABS
+PUSHB_1
+ 3
+CINDEX
+GC[cur]
+DUP
+ROUND[Grey]
+SUB
+ABS
+GTEQ
+IF
+SWAP
+MDAP[rnd]
+SWAP
+MIRP[rp0,min,rnd,black]
+ELSE
+MDAP[rnd]
+SWAP
+MIRP[min,rnd,black]
+EIF
+SLOOP
+ALIGNRP
+DUP
+PUSHB_1
+ 0
+NEQ
+IF
+PUSHB_1
+ 3
+LOOPCALL
+ELSE
+POP
+EIF
+ENDF
+FDEF
+DUP
+GC[cur]
+DUP
+ROUND[Grey]
+SUB
+ABS
+PUSHB_1
+ 3
+CINDEX
+GC[cur]
+DUP
+ROUND[Grey]
+SUB
+ABS
+GTEQ
+IF
+SWAP
+MDAP[rnd]
+SWAP
+MIRP[min,rnd,black]
+ELSE
+MDAP[rnd]
+SWAP
+MIRP[rp0,min,rnd,black]
+EIF
+SLOOP
+ALIGNRP
+DUP
+PUSHB_1
+ 0
+NEQ
+IF
+PUSHB_1
+ 3
+LOOPCALL
+ELSE
+POP
+EIF
+ENDF
+EndTTInstrs
+ShortTable: cvt 177
+ 6
+ 8
+ 14
+ 73
+ 87
+ 90
+ -450
+ -400
+ -50
+ 0
+ 1055
+ 1105
+ 1450
+ 1500
+ 1526
+ 1122
+ 1114
+ 1112
+ 1069
+ 973
+ 920
+ 799
+ 680
+ 600
+ 598
+ 592
+ 487
+ 420
+ 393
+ 352
+ 301
+ 299
+ 289
+ 283
+ 281
+ 266
+ 262
+ 252
+ 246
+ 244
+ 242
+ 236
+ 233
+ 229
+ 227
+ 225
+ 223
+ 217
+ 213
+ 211
+ 207
+ 205
+ 203
+ 197
+ 190
+ 188
+ 186
+ 184
+ 180
+ 178
+ 176
+ 174
+ 166
+ 164
+ 158
+ 156
+ 150
+ 145
+ 143
+ 141
+ 139
+ 137
+ 135
+ 131
+ 129
+ 125
+ 117
+ 113
+ 109
+ 106
+ 104
+ 102
+ 100
+ 92
+ 80
+ 66
+ 47
+ 2073
+ 1849
+ 1571
+ 1395
+ 1380
+ 1360
+ 1356
+ 1284
+ 1233
+ 1161
+ 1098
+ 1075
+ 1063
+ 1051
+ 1049
+ 1034
+ 1026
+ 1018
+ 1016
+ 1006
+ 1001
+ 999
+ 973
+ 965
+ 956
+ 918
+ 770
+ 725
+ 696
+ 678
+ 668
+ 625
+ 610
+ 604
+ 592
+ 522
+ 434
+ 432
+ 414
+ 328
+ 307
+ 301
+ 297
+ 293
+ 287
+ 285
+ 283
+ 281
+ 279
+ 274
+ 272
+ 266
+ 264
+ 260
+ 258
+ 256
+ 254
+ 252
+ 250
+ 248
+ 246
+ 242
+ 240
+ 236
+ 231
+ 225
+ 223
+ 201
+ 197
+ 193
+ 186
+ 180
+ 178
+ 176
+ 174
+ 172
+ 170
+ 168
+ 166
+ 158
+ 156
+ 152
+ 150
+ 143
+ 127
+ 125
+ 104
+ 102
+ 43
+ 35
+EndShort
+ShortTable: maxp 16
+ 1
+ 0
+ 243
+ 114
+ 7
+ 92
+ 4
+ 2
+ 12
+ 6
+ 20
+ 0
+ 748
+ 117
+ 2
+ 1
+EndShort
+LangName: 1033 "Copyright +AKkA 1993 , Monotype Typography ltd." "" "Regular" "Arial Rounded MT Bold" "" "Version 1.51" "" "Arial +AK4A Trademark of Monotype Typography ltd registered in the US Pat & TM.and elsewhere."
+LangName: 1027 "" "" "Normal"
+LangName: 1029 "" "" "oby+AQ0A-ejn+AOkA"
+LangName: 1030 "" "" "normal"
+LangName: 1031 "" "" "Standard"
+LangName: 1032 "" "" "+A5oDsQO9A78DvQO5A7oDrAAA"
+LangName: 1034 "" "" "Normal"
+LangName: 1035 "" "" "Normaali"
+LangName: 1036 "" "" "Normal"
+LangName: 1038 "" "" "Norm+AOEA-l"
+LangName: 1040 "" "" "Normale"
+LangName: 1043 "" "" "Standaard"
+LangName: 1044 "" "" "Normal"
+LangName: 1045 "" "" "Normalny"
+LangName: 1046 "" "" "Normal"
+LangName: 1049 "" "" "+BB4EMQRLBEcEPQRLBDkA"
+LangName: 1051 "" "" "Norm+AOEA-lne"
+LangName: 1053 "" "" "Normal"
+LangName: 1055 "" "" "Normal"
+LangName: 1060 "" "" "Navadno"
+LangName: 1069 "" "" "Arrunta"
+LangName: 2058 "" "" "Normal"
+LangName: 2070 "" "" "Normal"
+LangName: 3082 "" "" "Normal"
+LangName: 3084 "" "" "Normal"
+Encoding: UnicodeBmp
+UnicodeInterp: none
+NameList: AGL For New Fonts
+DisplaySize: -48
+AntiAlias: 1
+FitToEm: 0
+WinInfo: 0 77 26
+BeginChars: 65539 243
+
+StartChar: .notdef
+Encoding: 65536 -1 0
+Width: 1024
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+82 1365 m 1,0,-1
+ 942 1365 l 1,1,-1
+ 942 0 l 1,2,-1
+ 82 0 l 1,3,-1
+ 82 1365 l 1,0,-1
+123 1324 m 1,4,-1
+ 123 41 l 1,5,-1
+ 901 41 l 1,6,-1
+ 901 1324 l 1,7,-1
+ 123 1324 l 1,4,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: .null
+Encoding: 65537 -1 1
+Width: 0
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Validated: 1
+EndChar
+
+StartChar: nonmarkingreturn
+Encoding: 65538 -1 2
+Width: 512
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Validated: 1
+EndChar
+
+StartChar: space
+Encoding: 32 32 3
+Width: 512
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Validated: 1
+EndChar
+
+StartChar: exclam
+Encoding: 33 33 4
+Width: 682
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 26
+ 15
+ 1
+ 0
+ 0
+ 0
+ 0
+ 24
+ 31
+ 18
+ 9
+ 8
+ 7
+ 6
+ 12
+ 0
+ 27
+ 1
+ 0
+ 21
+ 1
+ 0
+ 128
+ 9
+ 3
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+231 635 m 2,0,-1
+ 199 1114 l 2,1,2
+ 190 1254 190 1254 190 1315 c 0,3,4
+ 190 1398 190 1398 233.5 1444.5 c 128,-1,5
+ 277 1491 277 1491 348 1491 c 0,6,7
+ 434 1491 434 1491 463 1431.5 c 128,-1,8
+ 492 1372 492 1372 492 1260 c 0,9,10
+ 492 1194 492 1194 485 1126 c 2,11,-1
+ 442 633 l 2,12,13
+ 435 545 435 545 412 498 c 128,-1,14
+ 389 451 389 451 336 451 c 0,15,16
+ 282 451 282 451 261 496.5 c 128,-1,17
+ 240 542 240 542 231 635 c 2,0,-1
+342 -23 m 0,18,19
+ 281 -23 281 -23 235.5 16.5 c 128,-1,20
+ 190 56 190 56 190 127 c 0,21,22
+ 190 189 190 189 233.5 232.5 c 128,-1,23
+ 277 276 277 276 340 276 c 256,24,25
+ 403 276 403 276 447.5 232.5 c 128,-1,26
+ 492 189 492 189 492 127 c 0,27,28
+ 492 57 492 57 447 17 c 128,-1,29
+ 402 -23 402 -23 342 -23 c 0,18,19
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: quotedbl
+Encoding: 34 34 5
+Width: 981
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 16
+ 10
+ 12
+ 7
+ 4
+ 12
+ 1
+ 127
+ 11
+ 9
+ 10
+ 127
+ 5
+ 3
+ 10
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MIAP[rnd]
+MDAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+373 944 m 1,0,-1
+ 166 944 l 1,1,-1
+ 113 1219 l 1,2,-1
+ 113 1466 l 1,3,-1
+ 420 1466 l 1,4,-1
+ 420 1219 l 1,5,-1
+ 373 944 l 1,0,-1
+823 944 m 1,6,-1
+ 616 944 l 1,7,-1
+ 563 1219 l 1,8,-1
+ 563 1466 l 1,9,-1
+ 870 1466 l 1,10,-1
+ 870 1219 l 1,11,-1
+ 823 944 l 1,6,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: numbersign
+Encoding: 35 35 6
+Width: 1130
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 77
+ 0
+ 28
+ 1
+ 0
+ 79
+ 46
+ 2
+ 0
+ 8
+ 46
+ 15
+ 10
+ 9
+ 0
+ 81
+ 48
+ 2
+ 0
+ 68
+ 55
+ 2
+ 0
+ 46
+ 6
+ 1
+ 0
+ 2
+ 7
+ 72
+ 9
+ 61
+ 9
+ 41
+ 10
+ 33
+ 12
+ 21
+ 12
+ 0
+ 52
+ 1
+ 0
+ 3
+ 1
+ 81
+ 80
+ 79
+ 78
+ 75
+ 69
+ 68
+ 67
+ 66
+ 64
+ 56
+ 48
+ 47
+ 41
+ 40
+ 36
+ 29
+ 28
+ 27
+ 26
+ 24
+ 17
+ 16
+ 8
+ 7
+ 1
+ 0
+ 27
+ 97
+ 43
+ 12
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+117 178 m 2,0,-1
+ 154 365 l 1,1,2
+ 16 368 16 368 16 475 c 0,3,4
+ 16 525 16 525 50.5 556.5 c 128,-1,5
+ 85 588 85 588 152 588 c 2,6,-1
+ 199 588 l 1,7,-1
+ 256 879 l 1,8,-1
+ 152 879 l 2,9,10
+ 87 879 87 879 51.5 911.5 c 128,-1,11
+ 16 944 16 944 16 991 c 0,12,13
+ 16 1041 16 1041 50.5 1071.5 c 128,-1,14
+ 85 1102 85 1102 152 1102 c 2,15,-1
+ 301 1102 l 1,16,-1
+ 348 1331 l 2,17,18
+ 359 1389 359 1389 372.5 1422 c 128,-1,19
+ 386 1455 386 1455 409.5 1472 c 128,-1,20
+ 433 1489 433 1489 471 1489 c 0,21,22
+ 524 1489 524 1489 552 1461 c 128,-1,23
+ 580 1433 580 1433 580 1389 c 0,24,25
+ 580 1379 580 1379 563 1288 c 2,26,-1
+ 526 1102 l 1,27,-1
+ 745 1102 l 1,28,-1
+ 793 1331 l 2,29,30
+ 803 1383 803 1383 812 1415 c 128,-1,31
+ 821 1447 821 1447 844.5 1469 c 128,-1,32
+ 868 1491 868 1491 913 1491 c 0,33,34
+ 965 1491 965 1491 993.5 1464 c 128,-1,35
+ 1022 1437 1022 1437 1022 1391 c 0,36,37
+ 1022 1370 1022 1370 1019.5 1350 c 128,-1,38
+ 1017 1330 1017 1330 1013 1311.5 c 128,-1,39
+ 1009 1293 1009 1293 1008 1288 c 2,40,-1
+ 971 1100 l 1,41,42
+ 1114 1097 1114 1097 1114 989 c 0,43,44
+ 1114 939 1114 939 1080 909 c 128,-1,45
+ 1046 879 1046 879 979 879 c 2,46,-1
+ 928 879 l 1,47,-1
+ 868 588 l 1,48,-1
+ 979 588 l 2,49,50
+ 1046 588 1046 588 1080 556 c 128,-1,51
+ 1114 524 1114 524 1114 475 c 256,52,53
+ 1114 426 1114 426 1080.5 395.5 c 128,-1,54
+ 1047 365 1047 365 979 365 c 2,55,-1
+ 825 365 l 1,56,-1
+ 778 135 l 2,57,58
+ 767 80 767 80 758.5 50 c 128,-1,59
+ 750 20 750 20 726 -2.5 c 128,-1,60
+ 702 -25 702 -25 657 -25 c 0,61,62
+ 607 -25 607 -25 578 3 c 128,-1,63
+ 549 31 549 31 549 76 c 0,64,65
+ 549 117 549 117 563 178 c 2,66,-1
+ 600 365 l 1,67,-1
+ 379 365 l 1,68,-1
+ 332 135 l 2,69,70
+ 314 50 314 50 294.5 12.5 c 128,-1,71
+ 275 -25 275 -25 211 -25 c 0,72,73
+ 160 -25 160 -25 131 3 c 128,-1,74
+ 102 31 102 31 102 76 c 0,75,76
+ 102 99 102 99 107.5 127.5 c 128,-1,77
+ 113 156 113 156 117 178 c 2,0,-1
+702 879 m 1,78,-1
+ 481 879 l 1,79,-1
+ 422 588 l 1,80,-1
+ 645 588 l 1,81,-1
+ 702 879 l 1,78,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: dollar
+Encoding: 36 36 7
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 51
+ 69
+ 68
+ 62
+ 61
+ 59
+ 48
+ 41
+ 29
+ 14
+ 10
+ 12
+ 1
+ 72
+ 25
+ 1
+ 18
+ 7
+ 4
+ 3
+ 146
+ 21
+ 72
+ 13
+ 0
+ 69
+ 15
+ 0
+ 3
+ 0
+ 62
+ 56
+ 49
+ 3
+ 0
+ 171
+ 25
+ 32
+ 0
+ 0
+ 0
+ 38
+ 1
+ 0
+ 44
+ 1
+ 146
+ 65
+ 53
+ 0
+ 3
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+670 1593 m 2,0,-1
+ 670 1485 l 1,1,2
+ 777 1474 777 1474 853.5 1441 c 128,-1,3
+ 930 1408 930 1408 987 1341 c 0,4,5
+ 1032 1290 1032 1290 1056.5 1236 c 128,-1,6
+ 1081 1182 1081 1182 1081 1137 c 0,7,8
+ 1081 1087 1081 1087 1044.5 1050.5 c 128,-1,9
+ 1008 1014 1008 1014 956 1014 c 0,10,11
+ 858 1014 858 1014 829 1120 c 0,12,13
+ 796 1245 796 1245 670 1286 c 1,14,-1
+ 670 870 l 1,15,16
+ 794 836 794 836 867.5 808 c 128,-1,17
+ 941 780 941 780 999 727 c 0,18,19
+ 1061 672 1061 672 1094.5 595.5 c 128,-1,20
+ 1128 519 1128 519 1128 428 c 0,21,22
+ 1128 314 1128 314 1074.5 214.5 c 128,-1,23
+ 1021 115 1021 115 917 52 c 128,-1,24
+ 813 -11 813 -11 670 -23 c 1,25,-1
+ 670 -272 l 2,26,27
+ 670 -331 670 -331 658.5 -358 c 128,-1,28
+ 647 -385 647 -385 608 -385 c 0,29,30
+ 572 -385 572 -385 557.5 -363 c 128,-1,31
+ 543 -341 543 -341 543 -295 c 2,32,-1
+ 543 -25 l 1,33,34
+ 426 -12 426 -12 338.5 30 c 128,-1,35
+ 251 72 251 72 192.5 134.5 c 128,-1,36
+ 134 197 134 197 106 264.5 c 128,-1,37
+ 78 332 78 332 78 397 c 0,38,39
+ 78 445 78 445 115.5 483.5 c 128,-1,40
+ 153 522 153 522 209 522 c 0,41,42
+ 254 522 254 522 285 501 c 128,-1,43
+ 316 480 316 480 328 442 c 0,44,45
+ 355 360 355 360 375 316.5 c 128,-1,46
+ 395 273 395 273 435.5 237 c 128,-1,47
+ 476 201 476 201 543 182 c 1,48,-1
+ 543 647 l 1,49,50
+ 409 684 409 684 319 729.5 c 128,-1,51
+ 229 775 229 775 173 859 c 128,-1,52
+ 117 943 117 943 117 1075 c 0,53,54
+ 117 1247 117 1247 226.5 1357 c 128,-1,55
+ 336 1467 336 1467 543 1485 c 1,56,-1
+ 543 1591 l 2,57,58
+ 543 1675 543 1675 606 1675 c 0,59,60
+ 670 1675 670 1675 670 1593 c 2,0,-1
+543 907 m 1,61,-1
+ 543 1290 l 1,62,63
+ 459 1265 459 1265 412 1224 c 128,-1,64
+ 365 1183 365 1183 365 1100 c 0,65,66
+ 365 1021 365 1021 409 980.5 c 128,-1,67
+ 453 940 453 940 543 907 c 1,61,-1
+670 610 m 1,68,-1
+ 670 172 l 1,69,70
+ 771 192 771 192 826 253 c 128,-1,71
+ 881 314 881 314 881 395 c 0,72,73
+ 881 482 881 482 827.5 529.5 c 128,-1,74
+ 774 577 774 577 670 610 c 1,68,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: percent
+Encoding: 37 37 8
+Width: 1749
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 81
+ 58
+ 1
+ 19
+ 27
+ 30
+ 1
+ 48
+ 55
+ 2
+ 1
+ 70
+ 1
+ 0
+ 0
+ 0
+ 67
+ 1
+ 19
+ 75
+ 11
+ 12
+ 9
+ 40
+ 3
+ 2
+ 48
+ 27
+ 48
+ 13
+ 0
+ 0
+ 61
+ 1
+ 0
+ 66
+ 1
+ 55
+ 75
+ 33
+ 9
+ 8
+ 3
+ 7
+ 59
+ 9
+ 0
+ 10
+ 73
+ 58
+ 2
+ 45
+ 52
+ 66
+ 64
+ 2
+ 16
+ 23
+ 2
+ 1
+ 157
+ 30
+ 45
+ 10
+ 67
+ 1
+ 157
+ 52
+ 37
+ 13
+ 59
+ 1
+ 157
+ 0
+ 16
+ 13
+ 157
+ 23
+ 7
+ 10
+ 4
+ 7
+LOOPCALL
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+LOOPCALL
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+676 1090 m 0,0,1
+ 676 899 676 899 592 806 c 128,-1,2
+ 508 713 508 713 362 713 c 0,3,4
+ 272 713 272 713 200.5 752.5 c 128,-1,5
+ 129 792 129 792 89 876 c 128,-1,6
+ 49 960 49 960 49 1081 c 0,7,8
+ 49 1211 49 1211 80 1298 c 128,-1,9
+ 111 1385 111 1385 180.5 1430 c 128,-1,10
+ 250 1475 250 1475 358 1475 c 0,11,12
+ 436 1475 436 1475 495 1451 c 128,-1,13
+ 554 1427 554 1427 595 1377.5 c 128,-1,14
+ 636 1328 636 1328 656 1257 c 128,-1,15
+ 676 1186 676 1186 676 1090 c 0,0,1
+489 1100 m 0,16,17
+ 489 1231 489 1231 461 1290.5 c 128,-1,18
+ 433 1350 433 1350 362 1350 c 0,19,20
+ 314 1350 314 1350 285.5 1321.5 c 128,-1,21
+ 257 1293 257 1293 246.5 1237.5 c 128,-1,22
+ 236 1182 236 1182 236 1096 c 0,23,24
+ 236 1007 236 1007 246.5 951 c 128,-1,25
+ 257 895 257 895 285 866.5 c 128,-1,26
+ 313 838 313 838 362 838 c 0,27,28
+ 436 838 436 838 462.5 901 c 128,-1,29
+ 489 964 489 964 489 1100 c 0,16,17
+1700 367 m 0,30,31
+ 1700 176 1700 176 1616 83 c 128,-1,32
+ 1532 -10 1532 -10 1386 -10 c 0,33,34
+ 1295 -10 1295 -10 1223.5 30 c 128,-1,35
+ 1152 70 1152 70 1111.5 153 c 128,-1,36
+ 1071 236 1071 236 1071 358 c 0,37,38
+ 1071 553 1071 553 1145.5 651.5 c 128,-1,39
+ 1220 750 1220 750 1382 750 c 0,40,41
+ 1460 750 1460 750 1518.5 726 c 128,-1,42
+ 1577 702 1577 702 1618.5 654 c 128,-1,43
+ 1660 606 1660 606 1680 534.5 c 128,-1,44
+ 1700 463 1700 463 1700 367 c 0,30,31
+1513 377 m 0,45,46
+ 1513 506 1513 506 1485 565.5 c 128,-1,47
+ 1457 625 1457 625 1386 625 c 0,48,49
+ 1336 625 1336 625 1308 597 c 128,-1,50
+ 1280 569 1280 569 1268.5 514.5 c 128,-1,51
+ 1257 460 1257 460 1257 373 c 0,52,53
+ 1257 239 1257 239 1285.5 177 c 128,-1,54
+ 1314 115 1314 115 1386 115 c 0,55,56
+ 1459 115 1459 115 1486 178.5 c 128,-1,57
+ 1513 242 1513 242 1513 377 c 0,45,46
+1343 1343 m 2,58,-1
+ 510 0 l 2,59,60
+ 478 -55 478 -55 438 -55 c 0,61,62
+ 415 -55 415 -55 392 -37.5 c 128,-1,63
+ 369 -20 369 -20 369 8 c 0,64,65
+ 369 29 369 29 389 59 c 2,66,-1
+ 1227 1413 l 2,67,68
+ 1249 1450 1249 1450 1265.5 1468.5 c 128,-1,69
+ 1282 1487 1282 1487 1313 1487 c 0,70,71
+ 1343 1487 1343 1487 1361.5 1469.5 c 128,-1,72
+ 1380 1452 1380 1452 1380 1423 c 0,73,74
+ 1380 1402 1380 1402 1343 1343 c 2,58,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: ampersand
+Encoding: 38 38 9
+Width: 1556
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 66
+ 67
+ 64
+ 52
+ 49
+ 25
+ 19
+ 15
+ 11
+ 0
+ 9
+ 73
+ 60
+ 1
+ 73
+ 59
+ 4
+ 12
+ 12
+ 0
+ 0
+ 0
+ 32
+ 1
+ 35
+ 1
+ 60
+ 52
+ 39
+ 9
+ 8
+ 2
+ 7
+ 67
+ 52
+ 2
+ 70
+ 55
+ 1
+ 25
+ 1
+ 0
+ 11
+ 1
+ 0
+ 64
+ 35
+ 15
+ 3
+ 150
+ 8
+ 70
+ 0
+ 76
+ 49
+ 2
+ 0
+ 0
+ 0
+ 0
+ 1
+ 136
+ 55
+ 44
+ 0
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+317 1155 m 0,0,1
+ 317 1248 317 1248 365.5 1324.5 c 128,-1,2
+ 414 1401 414 1401 508 1446 c 128,-1,3
+ 602 1491 602 1491 729 1491 c 0,4,5
+ 855 1491 855 1491 947 1444 c 128,-1,6
+ 1039 1397 1039 1397 1084.5 1321 c 128,-1,7
+ 1130 1245 1130 1245 1130 1163 c 0,8,9
+ 1130 1051 1130 1051 1056 968 c 128,-1,10
+ 982 885 982 885 838 799 c 1,11,12
+ 888 740 888 740 931 688 c 128,-1,13
+ 974 636 974 636 1014 591 c 128,-1,14
+ 1054 546 1054 546 1087 514 c 1,15,16
+ 1102 542 1102 542 1133.5 619 c 128,-1,17
+ 1165 696 1165 696 1192.5 730 c 128,-1,18
+ 1220 764 1220 764 1270 764 c 0,19,20
+ 1317 764 1317 764 1353 730.5 c 128,-1,21
+ 1389 697 1389 697 1389 649 c 0,22,23
+ 1389 605 1389 605 1358 524.5 c 128,-1,24
+ 1327 444 1327 444 1268 346 c 1,25,26
+ 1305 314 1305 314 1385.5 249 c 128,-1,27
+ 1466 184 1466 184 1484.5 160.5 c 128,-1,28
+ 1503 137 1503 137 1503 98 c 0,29,30
+ 1503 46 1503 46 1465.5 10.5 c 128,-1,31
+ 1428 -25 1428 -25 1382 -25 c 0,32,33
+ 1335 -25 1335 -25 1291 5 c 128,-1,34
+ 1247 35 1247 35 1104 152 c 1,35,36
+ 1039 91 1039 91 969.5 52 c 128,-1,37
+ 900 13 900 13 820.5 -6 c 128,-1,38
+ 741 -25 741 -25 643 -25 c 0,39,40
+ 518 -25 518 -25 418.5 11.5 c 128,-1,41
+ 319 48 319 48 253 110 c 128,-1,42
+ 187 172 187 172 155 247.5 c 128,-1,43
+ 123 323 123 323 123 401 c 0,44,45
+ 123 476 123 476 147 538.5 c 128,-1,46
+ 171 601 171 601 214.5 651.5 c 128,-1,47
+ 258 702 258 702 321.5 747.5 c 128,-1,48
+ 385 793 385 793 469 836 c 1,49,50
+ 394 930 394 930 355.5 1003.5 c 128,-1,51
+ 317 1077 317 1077 317 1155 c 0,0,1
+600 676 m 1,52,53
+ 498 617 498 617 447.5 558 c 128,-1,54
+ 397 499 397 499 397 418 c 0,55,56
+ 397 372 397 372 415.5 330 c 128,-1,57
+ 434 288 434 288 469.5 252 c 128,-1,58
+ 505 216 505 216 552 197 c 128,-1,59
+ 599 178 599 178 651 178 c 0,60,61
+ 702 178 702 178 750 194 c 128,-1,62
+ 798 210 798 210 841 239.5 c 128,-1,63
+ 884 269 884 269 930 313 c 1,64,65
+ 841 395 841 395 770 475.5 c 128,-1,66
+ 699 556 699 556 600 676 c 1,52,53
+702 950 m 1,67,68
+ 804 1015 804 1015 849.5 1059.5 c 128,-1,69
+ 895 1104 895 1104 895 1167 c 0,70,71
+ 895 1229 895 1229 849.5 1271 c 128,-1,72
+ 804 1313 804 1313 735 1313 c 256,73,74
+ 666 1313 666 1313 619.5 1270 c 128,-1,75
+ 573 1227 573 1227 573 1169 c 0,76,77
+ 573 1139 573 1139 590.5 1104.5 c 128,-1,78
+ 608 1070 608 1070 634 1036 c 128,-1,79
+ 660 1002 660 1002 702 950 c 1,67,68
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: quotesingle
+Encoding: 39 39 10
+Width: 492
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 8
+ 4
+ 12
+ 1
+ 127
+ 5
+ 3
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+352 944 m 1,0,-1
+ 145 944 l 1,1,-1
+ 92 1219 l 1,2,-1
+ 92 1466 l 1,3,-1
+ 399 1466 l 1,4,-1
+ 399 1219 l 1,5,-1
+ 352 944 l 1,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: parenleft
+Encoding: 40 40 11
+Width: 725
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 12
+ 22
+ 7
+ 8
+ 12
+ 26
+ 4
+ 2
+ 142
+ 15
+ 0
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+129 530 m 0,0,1
+ 129 681 129 681 155 812.5 c 128,-1,2
+ 181 944 181 944 234 1071.5 c 128,-1,3
+ 287 1199 287 1199 365 1327 c 0,4,5
+ 412 1405 412 1405 444 1439.5 c 128,-1,6
+ 476 1474 476 1474 504.5 1482.5 c 128,-1,7
+ 533 1491 533 1491 578 1491 c 0,8,9
+ 627 1491 627 1491 627 1464 c 0,10,11
+ 627 1455 627 1455 581 1355.5 c 128,-1,12
+ 535 1256 535 1256 494.5 1147 c 128,-1,13
+ 454 1038 454 1038 419.5 875 c 128,-1,14
+ 385 712 385 712 385 530 c 0,15,16
+ 385 350 385 350 419 189 c 128,-1,17
+ 453 28 453 28 496.5 -90 c 128,-1,18
+ 540 -208 540 -208 583.5 -301.5 c 128,-1,19
+ 627 -395 627 -395 627 -403 c 0,20,21
+ 627 -430 627 -430 578 -430 c 0,22,23
+ 532 -430 532 -430 503.5 -420.5 c 128,-1,24
+ 475 -411 475 -411 444 -376 c 128,-1,25
+ 413 -341 413 -341 365 -264 c 0,26,27
+ 286 -132 286 -132 234.5 -9.5 c 128,-1,28
+ 183 113 183 113 156 245 c 128,-1,29
+ 129 377 129 377 129 530 c 0,0,1
+EndSplineSet
+Validated: 1
+Kerns2: 77 178 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 74 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 45 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: parenright
+Encoding: 41 41 12
+Width: 725
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 11
+ 20
+ 12
+ 6
+ 7
+ 23
+ 1
+ 142
+ 0
+ 13
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+598 530 m 0,0,1
+ 598 310 598 310 539.5 121 c 128,-1,2
+ 481 -68 481 -68 362 -264 c 0,3,4
+ 295 -374 295 -374 256 -402 c 128,-1,5
+ 217 -430 217 -430 150 -430 c 0,6,7
+ 100 -430 100 -430 100 -403 c 0,8,9
+ 100 -394 100 -394 142 -306.5 c 128,-1,10
+ 184 -219 184 -219 229.5 -98 c 128,-1,11
+ 275 23 275 23 308.5 186.5 c 128,-1,12
+ 342 350 342 350 342 530 c 0,13,14
+ 342 711 342 711 308 875 c 128,-1,15
+ 274 1039 274 1039 229 1159 c 128,-1,16
+ 184 1279 184 1279 142 1367.5 c 128,-1,17
+ 100 1456 100 1456 100 1464 c 0,18,19
+ 100 1491 100 1491 150 1491 c 0,20,21
+ 220 1491 220 1491 258 1464.5 c 128,-1,22
+ 296 1438 296 1438 362 1327 c 0,23,24
+ 421 1229 421 1229 465 1134 c 128,-1,25
+ 509 1039 509 1039 538.5 944 c 128,-1,26
+ 568 849 568 849 583 746 c 128,-1,27
+ 598 643 598 643 598 530 c 0,0,1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: asterisk
+Encoding: 42 42 13
+Width: 897
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 35
+ 45
+ 4
+ 2
+ 49
+ 1
+ 0
+ 0
+ 39
+ 36
+ 12
+ 10
+ 4
+ 61
+ 0
+ 25
+ 0
+ 7
+ 55
+ 29
+ 22
+ 12
+ 1
+ 0
+ 36
+ 1
+ 0
+ 49
+ 25
+ 0
+ 3
+ 164
+ 58
+ 52
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+504 1221 m 1,0,1
+ 569 1251 569 1251 628 1281 c 128,-1,2
+ 687 1311 687 1311 722 1325 c 128,-1,3
+ 757 1339 757 1339 778 1339 c 0,4,5
+ 813 1339 813 1339 838.5 1315.5 c 128,-1,6
+ 864 1292 864 1292 864 1257 c 0,7,8
+ 864 1237 864 1237 851.5 1215.5 c 128,-1,9
+ 839 1194 839 1194 825 1188 c 0,10,11
+ 696 1137 696 1137 541 1114 c 1,12,13
+ 569 1088 569 1088 610 1045 c 128,-1,14
+ 651 1002 651 1002 653 999 c 0,15,16
+ 668 978 668 978 695 947 c 128,-1,17
+ 722 916 722 916 732.5 898.5 c 128,-1,18
+ 743 881 743 881 743 856 c 0,19,20
+ 743 824 743 824 719 800 c 128,-1,21
+ 695 776 695 776 657 776 c 256,22,23
+ 619 776 619 776 571.5 835 c 128,-1,24
+ 524 894 524 894 449 1047 c 1,25,26
+ 373 909 373 909 347 865 c 128,-1,27
+ 321 821 321 821 297 798.5 c 128,-1,28
+ 273 776 273 776 242 776 c 0,29,30
+ 205 776 205 776 180.5 801.5 c 128,-1,31
+ 156 827 156 827 156 856 c 0,32,33
+ 156 883 156 883 166 897 c 0,34,35
+ 258 1022 258 1022 358 1114 c 1,36,37
+ 274 1127 274 1127 208 1143 c 128,-1,38
+ 142 1159 142 1159 68 1190 c 0,39,40
+ 56 1196 56 1196 44.5 1217.5 c 128,-1,41
+ 33 1239 33 1239 33 1257 c 0,42,43
+ 33 1292 33 1292 58.5 1315.5 c 128,-1,44
+ 84 1339 84 1339 117 1339 c 0,45,46
+ 141 1339 141 1339 177 1324.5 c 128,-1,47
+ 213 1310 213 1310 268.5 1282.5 c 128,-1,48
+ 324 1255 324 1255 395 1221 c 1,49,50
+ 382 1284 382 1284 373.5 1365.5 c 128,-1,51
+ 365 1447 365 1447 365 1477 c 0,52,53
+ 365 1514 365 1514 388.5 1540.5 c 128,-1,54
+ 412 1567 412 1567 449 1567 c 0,55,56
+ 485 1567 485 1567 508.5 1540.5 c 128,-1,57
+ 532 1514 532 1514 532 1470 c 0,58,59
+ 532 1458 532 1458 528.5 1422.5 c 128,-1,60
+ 525 1387 525 1387 518.5 1336.5 c 128,-1,61
+ 512 1286 512 1286 504 1221 c 1,0,1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: plus
+Encoding: 43 43 14
+Width: 1194
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 26
+ 0
+ 8
+ 1
+ 0
+ 10
+ 1
+ 0
+ 36
+ 4
+ 2
+ 0
+ 7
+ 7
+ 1
+ 0
+ 11
+ 1
+ 0
+ 1
+ 1
+ 0
+ 141
+ 7
+ 5
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MDAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+725 211 m 1,0,-1
+ 467 211 l 1,1,-1
+ 467 592 l 1,2,-1
+ 84 592 l 1,3,-1
+ 84 854 l 1,4,-1
+ 467 854 l 1,5,-1
+ 467 1237 l 1,6,-1
+ 725 1237 l 1,7,-1
+ 725 854 l 1,8,-1
+ 1110 854 l 1,9,-1
+ 1110 592 l 1,10,-1
+ 725 592 l 1,11,-1
+ 725 211 l 1,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: comma
+Encoding: 44 44 15
+Width: 641
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 14
+ 23
+ 6
+ 14
+ 10
+ 7
+ 19
+ 17
+ 0
+ 3
+ 126
+ 10
+ 3
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+326 -27 m 1,0,1
+ 260 -27 260 -27 212 13.5 c 128,-1,2
+ 164 54 164 54 164 127 c 0,3,4
+ 164 190 164 190 211 233 c 128,-1,5
+ 258 276 258 276 322 276 c 0,6,7
+ 370 276 370 276 409 250 c 128,-1,8
+ 448 224 448 224 470 173.5 c 128,-1,9
+ 492 123 492 123 492 49 c 0,10,11
+ 492 -50 492 -50 450 -136.5 c 128,-1,12
+ 408 -223 408 -223 347.5 -273.5 c 128,-1,13
+ 287 -324 287 -324 238 -324 c 0,14,15
+ 207 -324 207 -324 187.5 -303.5 c 128,-1,16
+ 168 -283 168 -283 168 -256 c 0,17,18
+ 168 -215 168 -215 209 -190 c 0,19,20
+ 326 -125 326 -125 326 -27 c 1,0,1
+EndSplineSet
+Validated: 1
+Kerns2: 183 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: hyphen
+Encoding: 45 45 16
+AltUni2: 0000ad.ffffffff.0 0000ad.ffffffff.0
+Width: 682
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 10
+ 40
+ 8
+ 1
+ 10
+ 7
+ 119
+ 11
+ 4
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+500 412 m 2,0,-1
+ 184 412 l 2,1,2
+ 112 412 112 412 74.5 445.5 c 128,-1,3
+ 37 479 37 479 37 532 c 0,4,5
+ 37 586 37 586 73.5 619.5 c 128,-1,6
+ 110 653 110 653 184 653 c 2,7,-1
+ 500 653 l 2,8,9
+ 574 653 574 653 610.5 619.5 c 128,-1,10
+ 647 586 647 586 647 532 c 0,11,12
+ 647 479 647 479 611 445.5 c 128,-1,13
+ 575 412 575 412 500 412 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: period
+Encoding: 46 46 17
+Width: 641
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 11
+ 6
+ 30
+ 0
+ 9
+ 11
+ 7
+ 128
+ 9
+ 3
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+322 -25 m 0,0,1
+ 260 -25 260 -25 215 15 c 128,-1,2
+ 170 55 170 55 170 127 c 0,3,4
+ 170 188 170 188 213 232 c 128,-1,5
+ 256 276 256 276 319 276 c 256,6,7
+ 382 276 382 276 426.5 232.5 c 128,-1,8
+ 471 189 471 189 471 127 c 0,9,10
+ 471 56 471 56 426.5 15.5 c 128,-1,11
+ 382 -25 382 -25 322 -25 c 0,0,1
+EndSplineSet
+Validated: 1
+Kerns2: 183 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: slash
+Encoding: 47 47 18
+Width: 575
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 9
+ 13
+ 12
+ 5
+ 9
+ 122
+ 16
+ 7
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+528 1288 m 2,0,-1
+ 248 135 l 2,1,2
+ 234 78 234 78 223.5 45 c 128,-1,3
+ 213 12 213 12 191.5 -6.5 c 128,-1,4
+ 170 -25 170 -25 129 -25 c 0,5,6
+ 27 -25 27 -25 27 63 c 0,7,8
+ 27 86 27 86 47 178 c 2,9,-1
+ 326 1331 l 2,10,11
+ 348 1423 348 1423 368 1457 c 128,-1,12
+ 388 1491 388 1491 446 1491 c 0,13,14
+ 496 1491 496 1491 522.5 1467 c 128,-1,15
+ 549 1443 549 1443 549 1401 c 0,16,17
+ 549 1370 549 1370 528 1288 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: zero
+Encoding: 48 48 19
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 35
+ 15
+ 9
+ 3
+ 0
+ 4
+ 28
+ 35
+ 1
+ 28
+ 52
+ 18
+ 12
+ 12
+ 35
+ 52
+ 6
+ 9
+ 11
+ 2
+ 7
+ 3
+ 1
+ 136
+ 0
+ 24
+ 13
+ 15
+ 9
+ 2
+ 136
+ 31
+ 12
+ 13
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1120 719 m 0,0,1
+ 1120 555 1120 555 1100 437 c 128,-1,2
+ 1080 319 1080 319 1026 223 c 0,3,4
+ 958 105 958 105 850 41 c 128,-1,5
+ 742 -23 742 -23 610 -23 c 0,6,7
+ 458 -23 458 -23 337.5 63 c 128,-1,8
+ 217 149 217 149 156 301 c 0,9,10
+ 125 384 125 384 110.5 484.5 c 128,-1,11
+ 96 585 96 585 96 702 c 0,12,13
+ 96 853 96 853 112 974 c 128,-1,14
+ 128 1095 128 1095 162 1182 c 0,15,16
+ 221 1326 221 1326 333.5 1401.5 c 128,-1,17
+ 446 1477 446 1477 602 1477 c 0,18,19
+ 705 1477 705 1477 789 1443.5 c 128,-1,20
+ 873 1410 873 1410 936.5 1345.5 c 128,-1,21
+ 1000 1281 1000 1281 1044 1186 c 0,22,23
+ 1120 1021 1120 1021 1120 719 c 0,0,1
+846 739 m 0,24,25
+ 846 922 846 922 824 1038.5 c 128,-1,26
+ 802 1155 802 1155 750 1214.5 c 128,-1,27
+ 698 1274 698 1274 606 1274 c 0,28,29
+ 474 1274 474 1274 422.5 1141 c 128,-1,30
+ 371 1008 371 1008 371 731 c 0,31,32
+ 371 543 371 543 393 423 c 128,-1,33
+ 415 303 415 303 467 241.5 c 128,-1,34
+ 519 180 519 180 608 180 c 0,35,36
+ 700 180 700 180 752 244 c 128,-1,37
+ 804 308 804 308 825 427 c 128,-1,38
+ 846 546 846 546 846 739 c 0,24,25
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: one
+Encoding: 49 49 20
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 11
+ 20
+ 9
+ 14
+ 12
+ 3
+ 1
+ 137
+ 18
+ 0
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MDAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+578 137 m 2,0,-1
+ 578 1047 l 1,1,2
+ 324 852 324 852 236 852 c 0,3,4
+ 194 852 194 852 161.5 885.5 c 128,-1,5
+ 129 919 129 919 129 963 c 0,6,7
+ 129 1014 129 1014 161 1038 c 128,-1,8
+ 193 1062 193 1062 274 1100 c 0,9,10
+ 395 1157 395 1157 467.5 1220 c 128,-1,11
+ 540 1283 540 1283 596 1361 c 128,-1,12
+ 652 1439 652 1439 669 1457 c 128,-1,13
+ 686 1475 686 1475 733 1475 c 0,14,15
+ 786 1475 786 1475 818 1434 c 128,-1,16
+ 850 1393 850 1393 850 1321 c 2,17,-1
+ 850 176 l 2,18,19
+ 850 -25 850 -25 713 -25 c 0,20,21
+ 652 -25 652 -25 615 16 c 128,-1,22
+ 578 57 578 57 578 137 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: two
+Encoding: 50 50 21
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 38
+ 50
+ 31
+ 17
+ 14
+ 4
+ 25
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 41
+ 1
+ 25
+ 52
+ 39
+ 12
+ 9
+ 0
+ 41
+ 8
+ 9
+ 11
+ 2
+ 7
+ 4
+ 1
+ 0
+ 0
+ 0
+ 41
+ 1
+ 136
+ 45
+ 21
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+457 236 m 1,0,-1
+ 979 236 l 2,1,2
+ 1057 236 1057 236 1098 204 c 128,-1,3
+ 1139 172 1139 172 1139 117 c 0,4,5
+ 1139 68 1139 68 1106.5 34 c 128,-1,6
+ 1074 0 1074 0 1008 0 c 2,7,-1
+ 272 0 l 2,8,9
+ 197 0 197 0 155 41.5 c 128,-1,10
+ 113 83 113 83 113 139 c 0,11,12
+ 113 175 113 175 140 234.5 c 128,-1,13
+ 167 294 167 294 199 328 c 0,14,15
+ 332 466 332 466 439 564.5 c 128,-1,16
+ 546 663 546 663 592 694 c 0,17,18
+ 674 752 674 752 728.5 810.5 c 128,-1,19
+ 783 869 783 869 811.5 930.5 c 128,-1,20
+ 840 992 840 992 840 1051 c 0,21,22
+ 840 1115 840 1115 809.5 1165.5 c 128,-1,23
+ 779 1216 779 1216 726.5 1244 c 128,-1,24
+ 674 1272 674 1272 612 1272 c 0,25,26
+ 481 1272 481 1272 406 1157 c 0,27,28
+ 396 1142 396 1142 372.5 1075 c 128,-1,29
+ 349 1008 349 1008 319.5 972 c 128,-1,30
+ 290 936 290 936 233 936 c 0,31,32
+ 183 936 183 936 150 969 c 128,-1,33
+ 117 1002 117 1002 117 1059 c 0,34,35
+ 117 1128 117 1128 148 1203 c 128,-1,36
+ 179 1278 179 1278 240.5 1339 c 128,-1,37
+ 302 1400 302 1400 396.5 1437.5 c 128,-1,38
+ 491 1475 491 1475 618 1475 c 0,39,40
+ 771 1475 771 1475 879 1427 c 0,41,42
+ 949 1395 949 1395 1002 1339 c 128,-1,43
+ 1055 1283 1055 1283 1084.5 1209.5 c 128,-1,44
+ 1114 1136 1114 1136 1114 1057 c 0,45,46
+ 1114 933 1114 933 1052.5 831.5 c 128,-1,47
+ 991 730 991 730 927 672.5 c 128,-1,48
+ 863 615 863 615 712.5 492 c 128,-1,49
+ 562 369 562 369 506 301 c 0,50,51
+ 482 274 482 274 457 236 c 1,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: three
+Encoding: 51 51 22
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 45
+ 50
+ 1
+ 60
+ 53
+ 1
+ 6
+ 54
+ 22
+ 12
+ 12
+ 14
+ 1
+ 0
+ 63
+ 47
+ 2
+ 0
+ 30
+ 1
+ 52
+ 69
+ 60
+ 0
+ 53
+ 53
+ 39
+ 9
+ 11
+ 3
+ 7
+ 11
+ 10
+ 0
+ 0
+ 3
+ 1
+ 0
+ 30
+ 27
+ 2
+ 136
+ 34
+ 57
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+561 885 m 2,0,1
+ 653 885 653 885 719.5 939 c 128,-1,2
+ 786 993 786 993 786 1094 c 0,3,4
+ 786 1171 786 1171 733 1226.5 c 128,-1,5
+ 680 1282 680 1282 590 1282 c 0,6,7
+ 529 1282 529 1282 489.5 1265 c 128,-1,8
+ 450 1248 450 1248 427 1220 c 128,-1,9
+ 404 1192 404 1192 383.5 1148 c 128,-1,10
+ 363 1104 363 1104 346 1065 c 0,11,12
+ 336 1044 336 1044 310 1032 c 128,-1,13
+ 284 1020 284 1020 250 1020 c 0,14,15
+ 210 1020 210 1020 176.5 1052.5 c 128,-1,16
+ 143 1085 143 1085 143 1139 c 0,17,18
+ 143 1191 143 1191 174.5 1248.5 c 128,-1,19
+ 206 1306 206 1306 266.5 1358 c 128,-1,20
+ 327 1410 327 1410 417 1441.5 c 128,-1,21
+ 507 1473 507 1473 618 1473 c 0,22,23
+ 715 1473 715 1473 795 1446.5 c 128,-1,24
+ 875 1420 875 1420 934 1370 c 128,-1,25
+ 993 1320 993 1320 1023 1254 c 128,-1,26
+ 1053 1188 1053 1188 1053 1112 c 0,27,28
+ 1053 1012 1053 1012 1009.5 940.5 c 128,-1,29
+ 966 869 966 869 885 801 c 1,30,31
+ 963 759 963 759 1016.5 705 c 128,-1,32
+ 1070 651 1070 651 1097 585.5 c 128,-1,33
+ 1124 520 1124 520 1124 444 c 0,34,35
+ 1124 353 1124 353 1087.5 268 c 128,-1,36
+ 1051 183 1051 183 980 116.5 c 128,-1,37
+ 909 50 909 50 811.5 12.5 c 128,-1,38
+ 714 -25 714 -25 596 -25 c 0,39,40
+ 476 -25 476 -25 381 18 c 128,-1,41
+ 286 61 286 61 224.5 125.5 c 128,-1,42
+ 163 190 163 190 131.5 259 c 128,-1,43
+ 100 328 100 328 100 373 c 0,44,45
+ 100 431 100 431 137.5 466.5 c 128,-1,46
+ 175 502 175 502 231 502 c 0,47,48
+ 259 502 259 502 285 485.5 c 128,-1,49
+ 311 469 311 469 319 446 c 0,50,51
+ 371 307 371 307 430.5 239.5 c 128,-1,52
+ 490 172 490 172 598 172 c 0,53,54
+ 660 172 660 172 717.5 202.5 c 128,-1,55
+ 775 233 775 233 812.5 293 c 128,-1,56
+ 850 353 850 353 850 432 c 0,57,58
+ 850 549 850 549 786 615.5 c 128,-1,59
+ 722 682 722 682 608 682 c 0,60,61
+ 588 682 588 682 546 678 c 128,-1,62
+ 504 674 504 674 492 674 c 0,63,64
+ 437 674 437 674 407 701.5 c 128,-1,65
+ 377 729 377 729 377 778 c 0,66,67
+ 377 826 377 826 413 855.5 c 128,-1,68
+ 449 885 449 885 520 885 c 2,69,-1
+ 561 885 l 2,0,1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: four
+Encoding: 52 52 23
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 29
+ 0
+ 33
+ 1
+ 0
+ 24
+ 1
+ 0
+ 46
+ 17
+ 1
+ 0
+ 7
+ 34
+ 29
+ 9
+ 14
+ 12
+ 0
+ 25
+ 1
+ 0
+ 34
+ 1
+ 0
+ 145
+ 16
+ 0
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+MDAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+717 127 m 2,0,-1
+ 717 313 l 1,1,-1
+ 215 313 l 2,2,3
+ 120 313 120 313 72.5 356 c 128,-1,4
+ 25 399 25 399 25 473 c 0,5,6
+ 25 492 25 492 32 511.5 c 128,-1,7
+ 39 531 39 531 53 552.5 c 128,-1,8
+ 67 574 67 574 82 594 c 128,-1,9
+ 97 614 97 614 119 643 c 2,10,-1
+ 649 1352 l 2,11,12
+ 701 1422 701 1422 734.5 1453.5 c 128,-1,13
+ 768 1485 768 1485 815 1485 c 0,14,15
+ 967 1485 967 1485 967 1311 c 2,16,-1
+ 967 537 l 1,17,-1
+ 1010 537 l 2,18,19
+ 1087 537 1087 537 1133.5 516 c 128,-1,20
+ 1180 495 1180 495 1180 424 c 0,21,22
+ 1180 366 1180 366 1142 339.5 c 128,-1,23
+ 1104 313 1104 313 1028 313 c 2,24,-1
+ 967 313 l 1,25,-1
+ 967 127 l 2,26,27
+ 967 50 967 50 933 12.5 c 128,-1,28
+ 899 -25 899 -25 842 -25 c 0,29,30
+ 786 -25 786 -25 751.5 13.5 c 128,-1,31
+ 717 52 717 52 717 127 c 2,0,-1
+287 537 m 1,32,-1
+ 717 537 l 1,33,-1
+ 717 1118 l 1,34,-1
+ 287 537 l 1,32,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: five
+Encoding: 53 53 24
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 43
+ 22
+ 20
+ 2
+ 33
+ 25
+ 1
+ 0
+ 0
+ 0
+ 0
+ 43
+ 1
+ 0
+ 41
+ 47
+ 12
+ 9
+ 0
+ 0
+ 37
+ 1
+ 0
+ 2
+ 1
+ 53
+ 4
+ 33
+ 0
+ 25
+ 54
+ 13
+ 9
+ 11
+ 3
+ 7
+ 49
+ 0
+ 2
+ 136
+ 9
+ 29
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+948 1219 m 2,0,-1
+ 473 1219 l 1,1,-1
+ 416 895 l 1,2,3
+ 558 971 558 971 678 971 c 0,4,5
+ 774 971 774 971 857.5 935 c 128,-1,6
+ 941 899 941 899 1004 835.5 c 128,-1,7
+ 1067 772 1067 772 1103 685 c 128,-1,8
+ 1139 598 1139 598 1139 498 c 0,9,10
+ 1139 353 1139 353 1074 234 c 128,-1,11
+ 1009 115 1009 115 886.5 45 c 128,-1,12
+ 764 -25 764 -25 604 -25 c 0,13,14
+ 425 -25 425 -25 313.5 41 c 128,-1,15
+ 202 107 202 107 155.5 192.5 c 128,-1,16
+ 109 278 109 278 109 342 c 0,17,18
+ 109 381 109 381 141.5 416 c 128,-1,19
+ 174 451 174 451 223 451 c 0,20,21
+ 307 451 307 451 348 354 c 0,22,23
+ 388 265 388 265 456 215.5 c 128,-1,24
+ 524 166 524 166 608 166 c 0,25,26
+ 685 166 685 166 743 206 c 128,-1,27
+ 801 246 801 246 832.5 316 c 128,-1,28
+ 864 386 864 386 864 475 c 0,29,30
+ 864 571 864 571 830 639 c 128,-1,31
+ 796 707 796 707 739 740.5 c 128,-1,32
+ 682 774 682 774 612 774 c 0,33,34
+ 526 774 526 774 489 753 c 128,-1,35
+ 452 732 452 732 382.5 679.5 c 128,-1,36
+ 313 627 313 627 268 627 c 0,37,38
+ 219 627 219 627 181 662.5 c 128,-1,39
+ 143 698 143 698 143 743 c 0,40,41
+ 143 748 143 748 154 811 c 2,42,-1
+ 238 1290 l 2,43,44
+ 252 1376 252 1376 290 1415 c 128,-1,45
+ 328 1454 328 1454 414 1454 c 2,46,-1
+ 942 1454 l 2,47,48
+ 1098 1454 1098 1454 1098 1335 c 0,49,50
+ 1098 1283 1098 1283 1060 1251 c 128,-1,51
+ 1022 1219 1022 1219 948 1219 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: six
+Encoding: 54 54 25
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 47
+ 31
+ 1
+ 34
+ 3
+ 1
+ 34
+ 54
+ 21
+ 12
+ 12
+ 28
+ 1
+ 0
+ 0
+ 0
+ 0
+ 1
+ 54
+ 3
+ 46
+ 0
+ 39
+ 53
+ 12
+ 9
+ 11
+ 3
+ 7
+ 31
+ 1
+ 42
+ 50
+ 1
+ 25
+ 1
+ 138
+ 8
+ 42
+ 13
+ 0
+ 1
+ 128
+ 50
+ 16
+ 13
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+371 793 m 1,0,1
+ 439 874 439 874 519 913 c 128,-1,2
+ 599 952 599 952 698 952 c 0,3,4
+ 793 952 793 952 873.5 916.5 c 128,-1,5
+ 954 881 954 881 1014.5 815.5 c 128,-1,6
+ 1075 750 1075 750 1108 661 c 128,-1,7
+ 1141 572 1141 572 1141 475 c 0,8,9
+ 1141 334 1141 334 1076.5 219 c 128,-1,10
+ 1012 104 1012 104 896.5 39.5 c 128,-1,11
+ 781 -25 781 -25 635 -25 c 0,12,13
+ 467 -25 467 -25 345 57 c 128,-1,14
+ 223 139 223 139 158.5 299.5 c 128,-1,15
+ 94 460 94 460 94 692 c 0,16,17
+ 94 881 94 881 133 1030 c 128,-1,18
+ 172 1179 172 1179 245 1277 c 128,-1,19
+ 318 1375 318 1375 422 1425 c 128,-1,20
+ 526 1475 526 1475 659 1475 c 0,21,22
+ 787 1475 787 1475 884.5 1425 c 128,-1,23
+ 982 1375 982 1375 1031.5 1301 c 128,-1,24
+ 1081 1227 1081 1227 1081 1159 c 0,25,26
+ 1081 1118 1081 1118 1050 1084.5 c 128,-1,27
+ 1019 1051 1019 1051 971 1051 c 0,28,29
+ 929 1051 929 1051 893 1077.5 c 128,-1,30
+ 857 1104 857 1104 840 1151 c 0,31,32
+ 817 1211 817 1211 767 1247.5 c 128,-1,33
+ 717 1284 717 1284 651 1284 c 0,34,35
+ 598 1284 598 1284 545.5 1253.5 c 128,-1,36
+ 493 1223 493 1223 457 1171 c 0,37,38
+ 384 1065 384 1065 371 793 c 1,0,1
+641 172 m 0,39,40
+ 742 172 742 172 808 254.5 c 128,-1,41
+ 874 337 874 337 874 471 c 0,42,43
+ 874 562 874 562 843 627.5 c 128,-1,44
+ 812 693 812 693 758 727.5 c 128,-1,45
+ 704 762 704 762 639 762 c 0,46,47
+ 577 762 577 762 520.5 729 c 128,-1,48
+ 464 696 464 696 429.5 633.5 c 128,-1,49
+ 395 571 395 571 395 487 c 0,50,51
+ 395 352 395 352 465 262 c 128,-1,52
+ 535 172 535 172 641 172 c 0,39,40
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: seven
+Encoding: 55 55 26
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 17
+ 24
+ 41
+ 1
+ 12
+ 12
+ 7
+ 16
+ 9
+ 24
+ 19
+ 9
+ 3
+ 105
+ 4
+ 28
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+319 1452 m 2,0,-1
+ 985 1452 l 2,1,2
+ 1081 1452 1081 1452 1124 1422 c 128,-1,3
+ 1167 1392 1167 1392 1167 1323 c 0,4,5
+ 1167 1281 1167 1281 1116.5 1212 c 128,-1,6
+ 1066 1143 1066 1143 1001.5 1059.5 c 128,-1,7
+ 937 976 937 976 868.5 852 c 128,-1,8
+ 800 728 800 728 743 549 c 0,9,10
+ 719 470 719 470 709 418 c 128,-1,11
+ 699 366 699 366 687 283 c 128,-1,12
+ 675 200 675 200 666 156 c 0,13,14
+ 645 54 645 54 606.5 14.5 c 128,-1,15
+ 568 -25 568 -25 504 -25 c 0,16,17
+ 443 -25 443 -25 406 17.5 c 128,-1,18
+ 369 60 369 60 369 143 c 0,19,20
+ 369 207 369 207 396 317 c 128,-1,21
+ 423 427 423 427 484 580.5 c 128,-1,22
+ 545 734 545 734 636.5 895.5 c 128,-1,23
+ 728 1057 728 1057 854 1217 c 1,24,-1
+ 319 1217 l 2,25,26
+ 235 1217 235 1217 193.5 1247.5 c 128,-1,27
+ 152 1278 152 1278 152 1343 c 0,28,29
+ 152 1412 152 1412 196 1432 c 128,-1,30
+ 240 1452 240 1452 319 1452 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: eight
+Encoding: 56 56 27
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 52
+ 43
+ 54
+ 4
+ 12
+ 12
+ 26
+ 12
+ 2
+ 54
+ 49
+ 32
+ 13
+ 39
+ 54
+ 20
+ 9
+ 11
+ 3
+ 7
+ 0
+ 10
+ 43
+ 1
+ 28
+ 35
+ 1
+ 0
+ 0
+ 54
+ 1
+ 0
+ 12
+ 9
+ 2
+ 136
+ 16
+ 28
+ 0
+ 46
+ 1
+ 0
+ 0
+ 0
+ 26
+ 0
+ 2
+ 136
+ 35
+ 24
+ 0
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+137 1094 m 0,0,1
+ 137 1194 137 1194 191.5 1282.5 c 128,-1,2
+ 246 1371 246 1371 351.5 1424 c 128,-1,3
+ 457 1477 457 1477 598 1477 c 0,4,5
+ 717 1477 717 1477 807 1446 c 128,-1,6
+ 897 1415 897 1415 957 1360.5 c 128,-1,7
+ 1017 1306 1017 1306 1046 1237.5 c 128,-1,8
+ 1075 1169 1075 1169 1075 1092 c 0,9,10
+ 1075 994 1075 994 1024.5 917 c 128,-1,11
+ 974 840 974 840 874 791 c 1,12,13
+ 959 758 959 758 1015 704.5 c 128,-1,14
+ 1071 651 1071 651 1099.5 580.5 c 128,-1,15
+ 1128 510 1128 510 1128 424 c 0,16,17
+ 1128 298 1128 298 1067 195.5 c 128,-1,18
+ 1006 93 1006 93 888 35 c 128,-1,19
+ 770 -23 770 -23 610 -23 c 0,20,21
+ 444 -23 444 -23 326 35 c 128,-1,22
+ 208 93 208 93 148 194.5 c 128,-1,23
+ 88 296 88 296 88 422 c 0,24,25
+ 88 691 88 691 342 791 c 1,26,27
+ 137 887 137 887 137 1094 c 0,0,1
+854 432 m 256,28,29
+ 854 510 854 510 822 568 c 128,-1,30
+ 790 626 790 626 732 657 c 128,-1,31
+ 674 688 674 688 602 688 c 0,32,33
+ 500 688 500 688 431 620 c 128,-1,34
+ 362 552 362 552 362 430 c 0,35,36
+ 362 352 362 352 394.5 292.5 c 128,-1,37
+ 427 233 427 233 483 200.5 c 128,-1,38
+ 539 168 539 168 608 168 c 0,39,40
+ 678 168 678 168 734 201 c 128,-1,41
+ 790 234 790 234 822 294 c 128,-1,42
+ 854 354 854 354 854 432 c 256,28,29
+604 1286 m 0,43,44
+ 510 1286 510 1286 452.5 1227.5 c 128,-1,45
+ 395 1169 395 1169 395 1077 c 0,46,47
+ 395 992 395 992 454 935.5 c 128,-1,48
+ 513 879 513 879 606 879 c 0,49,50
+ 653 879 653 879 691.5 894 c 128,-1,51
+ 730 909 730 909 757.5 935.5 c 128,-1,52
+ 785 962 785 962 800 998.5 c 128,-1,53
+ 815 1035 815 1035 815 1079 c 0,54,55
+ 815 1138 815 1138 788.5 1185 c 128,-1,56
+ 762 1232 762 1232 714 1259 c 128,-1,57
+ 666 1286 666 1286 604 1286 c 0,43,44
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: nine
+Encoding: 57 57 28
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 47
+ 39
+ 1
+ 3
+ 36
+ 1
+ 46
+ 53
+ 13
+ 12
+ 12
+ 0
+ 0
+ 30
+ 1
+ 0
+ 0
+ 1
+ 54
+ 52
+ 3
+ 0
+ 36
+ 54
+ 23
+ 9
+ 11
+ 3
+ 7
+ 39
+ 1
+ 41
+ 49
+ 1
+ 0
+ 1
+ 128
+ 18
+ 41
+ 13
+ 27
+ 1
+ 138
+ 49
+ 8
+ 13
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+834 657 m 1,0,1
+ 768 579 768 579 686.5 539.5 c 128,-1,2
+ 605 500 605 500 506 500 c 0,3,4
+ 412 500 412 500 330.5 536.5 c 128,-1,5
+ 249 573 249 573 189.5 638.5 c 128,-1,6
+ 130 704 130 704 98 791.5 c 128,-1,7
+ 66 879 66 879 66 975 c 0,8,9
+ 66 1078 66 1078 102 1170.5 c 128,-1,10
+ 138 1263 138 1263 205 1331 c 128,-1,11
+ 272 1399 272 1399 364.5 1437 c 128,-1,12
+ 457 1475 457 1475 569 1475 c 0,13,14
+ 698 1475 698 1475 799 1428 c 128,-1,15
+ 900 1381 900 1381 969 1291.5 c 128,-1,16
+ 1038 1202 1038 1202 1075 1066 c 128,-1,17
+ 1112 930 1112 930 1112 758 c 0,18,19
+ 1112 566 1112 566 1073 419.5 c 128,-1,20
+ 1034 273 1034 273 959.5 173.5 c 128,-1,21
+ 885 74 885 74 781 25.5 c 128,-1,22
+ 677 -23 677 -23 545 -23 c 0,23,24
+ 415 -23 415 -23 319 26.5 c 128,-1,25
+ 223 76 223 76 173 149.5 c 128,-1,26
+ 123 223 123 223 123 291 c 0,27,28
+ 123 333 123 333 154 366 c 128,-1,29
+ 185 399 185 399 233 399 c 0,30,31
+ 277 399 277 399 312 374.5 c 128,-1,32
+ 347 350 347 350 365 301 c 0,33,34
+ 387 241 387 241 438 204.5 c 128,-1,35
+ 489 168 489 168 553 168 c 0,36,37
+ 610 168 610 168 661 197 c 128,-1,38
+ 712 226 712 226 748 279 c 0,39,40
+ 820 386 820 386 834 657 c 1,0,1
+811 963 m 0,41,42
+ 811 1031 811 1031 792.5 1088.5 c 128,-1,43
+ 774 1146 774 1146 740.5 1188 c 128,-1,44
+ 707 1230 707 1230 660.5 1254 c 128,-1,45
+ 614 1278 614 1278 559 1278 c 0,46,47
+ 464 1278 464 1278 398 1196.5 c 128,-1,48
+ 332 1115 332 1115 332 981 c 0,49,50
+ 332 848 332 848 398 769 c 128,-1,51
+ 464 690 464 690 565 690 c 0,52,53
+ 627 690 627 690 683.5 722.5 c 128,-1,54
+ 740 755 740 755 775.5 817 c 128,-1,55
+ 811 879 811 879 811 963 c 0,41,42
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: colon
+Encoding: 58 58 29
+Width: 641
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 24
+ 21
+ 31
+ 15
+ 10
+ 12
+ 6
+ 30
+ 0
+ 9
+ 11
+ 2
+ 7
+ 0
+ 18
+ 1
+ 0
+ 12
+ 1
+ 0
+ 128
+ 9
+ 3
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+322 -25 m 0,0,1
+ 260 -25 260 -25 215 15 c 128,-1,2
+ 170 55 170 55 170 127 c 0,3,4
+ 170 188 170 188 213 232 c 128,-1,5
+ 256 276 256 276 319 276 c 256,6,7
+ 382 276 382 276 426.5 232.5 c 128,-1,8
+ 471 189 471 189 471 127 c 0,9,10
+ 471 56 471 56 426.5 15.5 c 128,-1,11
+ 382 -25 382 -25 322 -25 c 0,0,1
+170 936 m 0,12,13
+ 170 1007 170 1007 214.5 1046 c 128,-1,14
+ 259 1085 259 1085 322 1085 c 0,15,16
+ 383 1085 383 1085 427 1045.5 c 128,-1,17
+ 471 1006 471 1006 471 936 c 0,18,19
+ 471 880 471 880 423 833 c 128,-1,20
+ 375 786 375 786 319 786 c 0,21,22
+ 258 786 258 786 214 831 c 128,-1,23
+ 170 876 170 876 170 936 c 0,12,13
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: semicolon
+Encoding: 59 59 30
+Width: 641
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 26
+ 30
+ 31
+ 24
+ 10
+ 12
+ 23
+ 6
+ 14
+ 10
+ 2
+ 7
+ 10
+ 1
+ 0
+ 17
+ 3
+ 2
+ 0
+ 19
+ 0
+ 2
+ 128
+ 27
+ 21
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+307 -27 m 1,0,1
+ 241 -27 241 -27 193 13.5 c 128,-1,2
+ 145 54 145 54 145 127 c 0,3,4
+ 145 190 145 190 192 233 c 128,-1,5
+ 239 276 239 276 303 276 c 0,6,7
+ 351 276 351 276 390 250 c 128,-1,8
+ 429 224 429 224 451 173.5 c 128,-1,9
+ 473 123 473 123 473 49 c 0,10,11
+ 473 -50 473 -50 431 -136.5 c 128,-1,12
+ 389 -223 389 -223 328.5 -273.5 c 128,-1,13
+ 268 -324 268 -324 219 -324 c 0,14,15
+ 188 -324 188 -324 169 -303.5 c 128,-1,16
+ 150 -283 150 -283 150 -256 c 0,17,18
+ 150 -215 150 -215 190 -190 c 0,19,20
+ 307 -126 307 -126 307 -27 c 1,0,1
+170 936 m 0,21,22
+ 170 1007 170 1007 214.5 1046 c 128,-1,23
+ 259 1085 259 1085 322 1085 c 0,24,25
+ 383 1085 383 1085 427 1045.5 c 128,-1,26
+ 471 1006 471 1006 471 936 c 0,27,28
+ 471 879 471 879 424.5 832.5 c 128,-1,29
+ 378 786 378 786 322 786 c 0,30,31
+ 280 786 280 786 245.5 806 c 128,-1,32
+ 211 826 211 826 190.5 859.5 c 128,-1,33
+ 170 893 170 893 170 936 c 0,21,22
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: less
+Encoding: 60 60 31
+Width: 1194
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 14
+ 4
+ 1
+ 0
+ 5
+ 1
+ 0
+ 0
+ 6
+ 1
+ 106
+ 1
+ 3
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MDAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1100 451 m 1,0,-1
+ 1100 168 l 1,1,-1
+ 94 604 l 1,2,-1
+ 94 846 l 1,3,-1
+ 1100 1282 l 1,4,-1
+ 1100 997 l 1,5,-1
+ 399 727 l 1,6,-1
+ 1100 451 l 1,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: equal
+Encoding: 61 61 32
+Width: 1194
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 23
+ 5
+ 36
+ 7
+ 10
+ 12
+ 36
+ 3
+ 1
+ 10
+ 2
+ 7
+ 0
+ 4
+ 1
+ 0
+ 6
+ 1
+ 0
+ 103
+ 0
+ 2
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1110 371 m 1,0,-1
+ 84 371 l 1,1,-1
+ 84 633 l 1,2,-1
+ 1110 633 l 1,3,-1
+ 1110 371 l 1,0,-1
+1110 815 m 1,4,-1
+ 84 815 l 1,5,-1
+ 84 1077 l 1,6,-1
+ 1110 1077 l 1,7,-1
+ 1110 815 l 1,4,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: greater
+Encoding: 62 62 33
+Width: 1194
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 14
+ 5
+ 1
+ 0
+ 0
+ 0
+ 5
+ 1
+ 3
+ 1
+ 106
+ 0
+ 2
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MDAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1100 604 m 1,0,-1
+ 94 166 l 1,1,-1
+ 94 449 l 1,2,-1
+ 797 725 l 1,3,-1
+ 94 997 l 1,4,-1
+ 94 1278 l 1,5,-1
+ 1100 844 l 1,6,-1
+ 1100 604 l 1,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: question
+Encoding: 63 63 34
+Width: 1174
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 47
+ 38
+ 17
+ 12
+ 3
+ 33
+ 47
+ 1
+ 33
+ 49
+ 4
+ 12
+ 12
+ 19
+ 1
+ 0
+ 0
+ 0
+ 0
+ 47
+ 31
+ 41
+ 9
+ 8
+ 2
+ 7
+ 36
+ 10
+ 0
+ 10
+ 12
+ 1
+ 30
+ 50
+ 1
+ 136
+ 8
+ 30
+ 10
+ 22
+ 17
+ 2
+ 128
+ 50
+ 44
+ 13
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+90 1073 m 0,0,1
+ 90 1168 90 1168 151 1265.5 c 128,-1,2
+ 212 1363 212 1363 329 1427 c 128,-1,3
+ 446 1491 446 1491 602 1491 c 0,4,5
+ 747 1491 747 1491 858 1437.5 c 128,-1,6
+ 969 1384 969 1384 1029.5 1292 c 128,-1,7
+ 1090 1200 1090 1200 1090 1092 c 0,8,9
+ 1090 1007 1090 1007 1055.5 943 c 128,-1,10
+ 1021 879 1021 879 973.5 832.5 c 128,-1,11
+ 926 786 926 786 803 676 c 0,12,13
+ 769 645 769 645 748.5 621.5 c 128,-1,14
+ 728 598 728 598 718 578.5 c 128,-1,15
+ 708 559 708 559 702.5 539.5 c 128,-1,16
+ 697 520 697 520 686 471 c 0,17,18
+ 667 367 667 367 567 367 c 0,19,20
+ 515 367 515 367 479.5 401 c 128,-1,21
+ 444 435 444 435 444 502 c 0,22,23
+ 444 586 444 586 470 647.5 c 128,-1,24
+ 496 709 496 709 539 755.5 c 128,-1,25
+ 582 802 582 802 655 866 c 0,26,27
+ 719 922 719 922 747.5 950.5 c 128,-1,28
+ 776 979 776 979 795.5 1014 c 128,-1,29
+ 815 1049 815 1049 815 1090 c 0,30,31
+ 815 1170 815 1170 755.5 1225 c 128,-1,32
+ 696 1280 696 1280 602 1280 c 0,33,34
+ 492 1280 492 1280 440 1224.5 c 128,-1,35
+ 388 1169 388 1169 352 1061 c 0,36,37
+ 318 948 318 948 223 948 c 0,38,39
+ 167 948 167 948 128.5 987.5 c 128,-1,40
+ 90 1027 90 1027 90 1073 c 0,0,1
+578 -23 m 0,41,42
+ 517 -23 517 -23 471.5 16.5 c 128,-1,43
+ 426 56 426 56 426 127 c 0,44,45
+ 426 190 426 190 470 233 c 128,-1,46
+ 514 276 514 276 578 276 c 0,47,48
+ 641 276 641 276 684 233 c 128,-1,49
+ 727 190 727 190 727 127 c 0,50,51
+ 727 57 727 57 682 17 c 128,-1,52
+ 637 -23 637 -23 578 -23 c 0,41,42
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: at
+Encoding: 64 64 35
+Width: 2005
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 79
+ 72
+ 1
+ 84
+ 8
+ 1
+ 17
+ 57
+ 48
+ 12
+ 12
+ 0
+ 0
+ 0
+ 0
+ 21
+ 0
+ 2
+ 84
+ 58
+ 70
+ 10
+ 9
+ 0
+ 0
+ 0
+ 0
+ 75
+ 61
+ 33
+ 3
+ 8
+ 52
+ 58
+ 9
+ 8
+ 3
+ 7
+ 38
+ 7
+ 29
+ 2
+ 10
+ 79
+ 61
+ 29
+ 5
+ 2
+ 1
+ 0
+ 7
+ 12
+ 72
+ 21
+ 1
+ 66
+ 24
+ 2
+ 1
+ 33
+ 1
+ 0
+ 0
+ 0
+ 32
+ 1
+ 158
+ 53
+ 12
+ 0
+ 141
+ 72
+ 66
+ 10
+ 157
+ 24
+ 43
+ 10
+ 3
+ 7
+LOOPCALL
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MDAP[rnd]
+MIAP[rnd]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1243 948 m 1,0,-1
+ 1268 1059 l 1,1,-1
+ 1532 1059 l 1,2,-1
+ 1380 342 l 2,3,4
+ 1366 274 1366 274 1366 252 c 0,5,6
+ 1366 229 1366 229 1377.5 216 c 128,-1,7
+ 1389 203 1389 203 1405 203 c 0,8,9
+ 1459 203 1459 203 1544.5 273.5 c 128,-1,10
+ 1630 344 1630 344 1693.5 465.5 c 128,-1,11
+ 1757 587 1757 587 1757 731 c 0,12,13
+ 1757 851 1757 851 1711.5 957 c 128,-1,14
+ 1666 1063 1666 1063 1580 1141 c 128,-1,15
+ 1494 1219 1494 1219 1367.5 1263 c 128,-1,16
+ 1241 1307 1241 1307 1081 1307 c 0,17,18
+ 918 1307 918 1307 782 1264.5 c 128,-1,19
+ 646 1222 646 1222 543 1142.5 c 128,-1,20
+ 440 1063 440 1063 371 946 c 0,21,22
+ 310 844 310 844 278 720 c 128,-1,23
+ 246 596 246 596 246 467 c 0,24,25
+ 246 295 246 295 314.5 152.5 c 128,-1,26
+ 383 10 383 10 513.5 -86.5 c 128,-1,27
+ 644 -183 644 -183 829 -223.5 c 128,-1,28
+ 1014 -264 1014 -264 1247 -240 c 0,29,30
+ 1432 -218 1432 -218 1560.5 -156 c 128,-1,31
+ 1689 -94 1689 -94 1778 18 c 1,32,-1
+ 1991 18 l 1,33,34
+ 1939 -89 1939 -89 1855.5 -173 c 128,-1,35
+ 1772 -257 1772 -257 1660 -314.5 c 128,-1,36
+ 1548 -372 1548 -372 1409 -402 c 128,-1,37
+ 1270 -432 1270 -432 1106 -432 c 0,38,39
+ 860 -432 860 -432 663 -367.5 c 128,-1,40
+ 466 -303 466 -303 331.5 -181.5 c 128,-1,41
+ 197 -60 197 -60 128 108.5 c 128,-1,42
+ 59 277 59 277 59 481 c 0,43,44
+ 59 694 59 694 130 879 c 128,-1,45
+ 201 1064 201 1064 334.5 1200.5 c 128,-1,46
+ 468 1337 468 1337 660.5 1414 c 128,-1,47
+ 853 1491 853 1491 1085 1491 c 0,48,49
+ 1275 1491 1275 1491 1433.5 1435.5 c 128,-1,50
+ 1592 1380 1592 1380 1705 1276 c 128,-1,51
+ 1818 1172 1818 1172 1877.5 1029.5 c 128,-1,52
+ 1937 887 1937 887 1937 715 c 0,53,54
+ 1937 581 1937 581 1889 452.5 c 128,-1,55
+ 1841 324 1841 324 1751.5 221.5 c 128,-1,56
+ 1662 119 1662 119 1541 59.5 c 128,-1,57
+ 1420 0 1420 0 1280 0 c 0,58,59
+ 1199 0 1199 0 1154 27.5 c 128,-1,60
+ 1109 55 1109 55 1094 115 c 1,61,62
+ 1007 29 1007 29 894 6.5 c 128,-1,63
+ 781 -16 781 -16 675 27.5 c 128,-1,64
+ 569 71 569 71 503.5 174 c 128,-1,65
+ 438 277 438 277 438 428 c 0,66,67
+ 438 585 438 585 505.5 737 c 128,-1,68
+ 573 889 573 889 697.5 986 c 128,-1,69
+ 822 1083 822 1083 979 1083 c 0,70,71
+ 1159 1083 1159 1083 1243 948 c 1,0,-1
+696 430 m 0,72,73
+ 696 310 696 310 746 246 c 128,-1,74
+ 796 182 796 182 877 182 c 0,75,76
+ 971 182 971 182 1042.5 257 c 128,-1,77
+ 1114 332 1114 332 1151 446.5 c 128,-1,78
+ 1188 561 1188 561 1188 668 c 0,79,80
+ 1188 721 1188 721 1175.5 763.5 c 128,-1,81
+ 1163 806 1163 806 1138.5 838 c 128,-1,82
+ 1114 870 1114 870 1079.5 886.5 c 128,-1,83
+ 1045 903 1045 903 1001 903 c 0,84,85
+ 913 903 913 903 842.5 834.5 c 128,-1,86
+ 772 766 772 766 734 656.5 c 128,-1,87
+ 696 547 696 547 696 430 c 0,72,73
+EndSplineSet
+Validated: 33
+EndChar
+
+StartChar: A
+Encoding: 65 65 36
+Width: 1473
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 21
+ 46
+ 35
+ 2
+ 10
+ 7
+ 36
+ 29
+ 9
+ 18
+ 12
+ 6
+ 9
+ 36
+ 35
+ 34
+ 3
+ 92
+ 26
+ 9
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+MDAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1098 166 m 2,0,-1
+ 1028 350 l 1,1,-1
+ 432 350 l 1,2,-1
+ 362 162 l 2,3,4
+ 321 52 321 52 292 13.5 c 128,-1,5
+ 263 -25 263 -25 197 -25 c 0,6,7
+ 141 -25 141 -25 98 16 c 128,-1,8
+ 55 57 55 57 55 109 c 0,9,10
+ 55 139 55 139 65 171 c 128,-1,11
+ 75 203 75 203 98 260 c 2,12,-1
+ 473 1212 l 2,13,14
+ 489 1253 489 1253 511.5 1310.5 c 128,-1,15
+ 534 1368 534 1368 559.5 1406 c 128,-1,16
+ 585 1444 585 1444 626.5 1467.5 c 128,-1,17
+ 668 1491 668 1491 729 1491 c 0,18,19
+ 791 1491 791 1491 832.5 1467.5 c 128,-1,20
+ 874 1444 874 1444 899.5 1407 c 128,-1,21
+ 925 1370 925 1370 942.5 1327.5 c 128,-1,22
+ 960 1285 960 1285 987 1214 c 2,23,-1
+ 1370 268 l 2,24,25
+ 1415 160 1415 160 1415 111 c 0,26,27
+ 1415 60 1415 60 1372.5 17.5 c 128,-1,28
+ 1330 -25 1330 -25 1270 -25 c 0,29,30
+ 1235 -25 1235 -25 1210 -12.5 c 128,-1,31
+ 1185 0 1185 0 1168 21.5 c 128,-1,32
+ 1151 43 1151 43 1131.5 87.5 c 128,-1,33
+ 1112 132 1112 132 1098 166 c 2,0,-1
+510 573 m 1,34,-1
+ 948 573 l 1,35,-1
+ 727 1178 l 1,36,-1
+ 510 573 l 1,34,-1
+EndSplineSet
+Validated: 1
+Kerns2: 183 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 181 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 90 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 89 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 60 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 57 -104 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 56 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 55 -180 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 52 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 50 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 42 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 38 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: B
+Encoding: 66 66 37
+Width: 1473
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 58
+ 0
+ 0
+ 0
+ 0
+ 12
+ 1
+ 34
+ 46
+ 9
+ 12
+ 9
+ 18
+ 1
+ 48
+ 36
+ 27
+ 13
+ 0
+ 0
+ 0
+ 0
+ 23
+ 1
+ 29
+ 46
+ 1
+ 9
+ 8
+ 3
+ 7
+ 39
+ 1
+ 31
+ 28
+ 1
+ 0
+ 0
+ 41
+ 1
+ 0
+ 23
+ 18
+ 16
+ 12
+ 4
+ 128
+ 20
+ 31
+ 0
+ 0
+ 35
+ 1
+ 129
+ 28
+ 5
+ 15
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+786 0 m 2,0,-1
+ 338 0 l 2,1,2
+ 241 0 241 0 199.5 43.5 c 128,-1,3
+ 158 87 158 87 158 182 c 2,4,-1
+ 158 1284 l 2,5,6
+ 158 1381 158 1381 200.5 1423.5 c 128,-1,7
+ 243 1466 243 1466 338 1466 c 2,8,-1
+ 813 1466 l 2,9,10
+ 918 1466 918 1466 995 1453 c 128,-1,11
+ 1072 1440 1072 1440 1133 1403 c 0,12,13
+ 1185 1372 1185 1372 1225 1324.5 c 128,-1,14
+ 1265 1277 1265 1277 1286 1219.5 c 128,-1,15
+ 1307 1162 1307 1162 1307 1098 c 0,16,17
+ 1307 878 1307 878 1087 776 c 1,18,19
+ 1376 684 1376 684 1376 418 c 0,20,21
+ 1376 295 1376 295 1313 196.5 c 128,-1,22
+ 1250 98 1250 98 1143 51 c 0,23,24
+ 1076 23 1076 23 989 11.5 c 128,-1,25
+ 902 0 902 0 786 0 c 2,0,-1
+764 651 m 2,26,-1
+ 455 651 l 1,27,-1
+ 455 223 l 1,28,-1
+ 774 223 l 2,29,30
+ 1075 223 1075 223 1075 440 c 0,31,32
+ 1075 551 1075 551 997 601 c 128,-1,33
+ 919 651 919 651 764 651 c 2,26,-1
+455 1243 m 1,34,-1
+ 455 864 l 1,35,-1
+ 727 864 l 2,36,37
+ 838 864 838 864 898.5 885 c 128,-1,38
+ 959 906 959 906 991 965 c 0,39,40
+ 1016 1007 1016 1007 1016 1059 c 0,41,42
+ 1016 1170 1016 1170 937 1206.5 c 128,-1,43
+ 858 1243 858 1243 696 1243 c 2,44,-1
+ 455 1243 l 1,34,-1
+EndSplineSet
+Validated: 1
+Kerns2: 104 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 99 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 98 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 56 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 36 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -104 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: C
+Encoding: 67 67 38
+Width: 1516
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 33
+ 44
+ 41
+ 25
+ 0
+ 4
+ 31
+ 38
+ 1
+ 31
+ 41
+ 18
+ 12
+ 12
+ 0
+ 0
+ 0
+ 0
+ 9
+ 1
+ 38
+ 41
+ 5
+ 9
+ 8
+ 2
+ 7
+ 9
+ 1
+ 128
+ 34
+ 13
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1409 463 m 0,0,1
+ 1409 393 1409 393 1374.5 311.5 c 128,-1,2
+ 1340 230 1340 230 1266 151.5 c 128,-1,3
+ 1192 73 1192 73 1077 24 c 128,-1,4
+ 962 -25 962 -25 809 -25 c 0,5,6
+ 693 -25 693 -25 598 -3 c 128,-1,7
+ 503 19 503 19 425.5 65.5 c 128,-1,8
+ 348 112 348 112 283 188 c 0,9,10
+ 225 257 225 257 184 342.5 c 128,-1,11
+ 143 428 143 428 122.5 525 c 128,-1,12
+ 102 622 102 622 102 731 c 0,13,14
+ 102 908 102 908 153.5 1048 c 128,-1,15
+ 205 1188 205 1188 301 1287.5 c 128,-1,16
+ 397 1387 397 1387 526 1439 c 128,-1,17
+ 655 1491 655 1491 801 1491 c 0,18,19
+ 979 1491 979 1491 1118 1420 c 128,-1,20
+ 1257 1349 1257 1349 1331 1244.5 c 128,-1,21
+ 1405 1140 1405 1140 1405 1047 c 0,22,23
+ 1405 996 1405 996 1369 957 c 128,-1,24
+ 1333 918 1333 918 1282 918 c 0,25,26
+ 1225 918 1225 918 1196.5 945 c 128,-1,27
+ 1168 972 1168 972 1133 1038 c 0,28,29
+ 1075 1147 1075 1147 996.5 1201 c 128,-1,30
+ 918 1255 918 1255 803 1255 c 0,31,32
+ 620 1255 620 1255 511.5 1116 c 128,-1,33
+ 403 977 403 977 403 721 c 0,34,35
+ 403 550 403 550 451 436.5 c 128,-1,36
+ 499 323 499 323 587 267 c 128,-1,37
+ 675 211 675 211 793 211 c 0,38,39
+ 921 211 921 211 1009.5 274.5 c 128,-1,40
+ 1098 338 1098 338 1143 461 c 0,41,42
+ 1162 519 1162 519 1190 555.5 c 128,-1,43
+ 1218 592 1218 592 1280 592 c 0,44,45
+ 1333 592 1333 592 1371 555 c 128,-1,46
+ 1409 518 1409 518 1409 463 c 0,0,1
+EndSplineSet
+Validated: 1
+Kerns2: 17 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: D
+Encoding: 68 68 39
+Width: 1516
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 39
+ 0
+ 0
+ 0
+ 0
+ 4
+ 1
+ 23
+ 41
+ 1
+ 12
+ 9
+ 0
+ 0
+ 0
+ 0
+ 10
+ 1
+ 25
+ 41
+ 15
+ 9
+ 8
+ 2
+ 7
+ 10
+ 4
+ 2
+ 128
+ 6
+ 31
+ 13
+ 0
+ 1
+ 129
+ 24
+ 20
+ 13
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+344 1466 m 2,0,-1
+ 731 1466 l 2,1,2
+ 882 1466 882 1466 990 1438 c 128,-1,3
+ 1098 1410 1098 1410 1186 1333 c 0,4,5
+ 1415 1137 1415 1137 1415 737 c 0,6,7
+ 1415 605 1415 605 1392 496 c 128,-1,8
+ 1369 387 1369 387 1321 299.5 c 128,-1,9
+ 1273 212 1273 212 1198 143 c 0,10,11
+ 1139 90 1139 90 1069 58 c 128,-1,12
+ 999 26 999 26 918.5 13 c 128,-1,13
+ 838 0 838 0 737 0 c 2,14,-1
+ 350 0 l 2,15,16
+ 269 0 269 0 228 24.5 c 128,-1,17
+ 187 49 187 49 174.5 93.5 c 128,-1,18
+ 162 138 162 138 162 209 c 2,19,-1
+ 162 1284 l 2,20,21
+ 162 1380 162 1380 205 1423 c 128,-1,22
+ 248 1466 248 1466 344 1466 c 2,0,-1
+459 1231 m 1,23,-1
+ 459 236 l 1,24,-1
+ 684 236 l 2,25,26
+ 758 236 758 236 800 240 c 128,-1,27
+ 842 244 842 244 887 260 c 128,-1,28
+ 932 276 932 276 965 305 c 0,29,30
+ 1114 431 1114 431 1114 739 c 0,31,32
+ 1114 956 1114 956 1048.5 1064 c 128,-1,33
+ 983 1172 983 1172 887 1201.5 c 128,-1,34
+ 791 1231 791 1231 655 1231 c 2,35,-1
+ 459 1231 l 1,23,-1
+EndSplineSet
+Validated: 1
+Kerns2: 99 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 98 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 60 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 58 51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 57 -53 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 36 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -154 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: E
+Encoding: 69 69 40
+Width: 1366
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 24
+ 0
+ 43
+ 28
+ 12
+ 12
+ 46
+ 2
+ 9
+ 10
+ 11
+ 41
+ 19
+ 9
+ 11
+ 3
+ 7
+ 0
+ 2
+ 1
+ 129
+ 11
+ 23
+ 15
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1126 1237 m 2,0,-1
+ 457 1237 l 1,1,-1
+ 457 877 l 1,2,-1
+ 1073 877 l 2,3,4
+ 1141 877 1141 877 1174.5 846.5 c 128,-1,5
+ 1208 816 1208 816 1208 766 c 256,6,7
+ 1208 716 1208 716 1175 684.5 c 128,-1,8
+ 1142 653 1142 653 1073 653 c 2,9,-1
+ 457 653 l 1,10,-1
+ 457 236 l 1,11,-1
+ 1149 236 l 2,12,13
+ 1219 236 1219 236 1254.5 203.5 c 128,-1,14
+ 1290 171 1290 171 1290 117 c 0,15,16
+ 1290 65 1290 65 1254.5 32.5 c 128,-1,17
+ 1219 0 1219 0 1149 0 c 2,18,-1
+ 342 0 l 2,19,20
+ 245 0 245 0 202.5 43 c 128,-1,21
+ 160 86 160 86 160 182 c 2,22,-1
+ 160 1284 l 2,23,24
+ 160 1348 160 1348 179 1388.5 c 128,-1,25
+ 198 1429 198 1429 238.5 1447.5 c 128,-1,26
+ 279 1466 279 1466 342 1466 c 2,27,-1
+ 1126 1466 l 2,28,29
+ 1197 1466 1197 1466 1231.5 1434.5 c 128,-1,30
+ 1266 1403 1266 1403 1266 1352 c 0,31,32
+ 1266 1300 1266 1300 1231.5 1268.5 c 128,-1,33
+ 1197 1237 1197 1237 1126 1237 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: F
+Encoding: 70 70 41
+Width: 1237
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 21
+ 0
+ 43
+ 23
+ 12
+ 12
+ 46
+ 2
+ 9
+ 10
+ 2
+ 7
+ 14
+ 9
+ 0
+ 2
+ 1
+ 129
+ 10
+ 18
+ 15
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1036 1237 m 2,0,-1
+ 451 1237 l 1,1,-1
+ 451 862 l 1,2,-1
+ 940 862 l 2,3,4
+ 1008 862 1008 862 1041.5 831.5 c 128,-1,5
+ 1075 801 1075 801 1075 750 c 256,6,7
+ 1075 699 1075 699 1041 669 c 128,-1,8
+ 1007 639 1007 639 940 639 c 2,9,-1
+ 451 639 l 1,10,-1
+ 451 156 l 2,11,12
+ 451 64 451 64 409.5 19.5 c 128,-1,13
+ 368 -25 368 -25 303 -25 c 0,14,15
+ 237 -25 237 -25 195.5 20 c 128,-1,16
+ 154 65 154 65 154 156 c 2,17,-1
+ 154 1284 l 2,18,19
+ 154 1348 154 1348 173 1388.5 c 128,-1,20
+ 192 1429 192 1429 232.5 1447.5 c 128,-1,21
+ 273 1466 273 1466 336 1466 c 2,22,-1
+ 1036 1466 l 2,23,24
+ 1107 1466 1107 1466 1141.5 1434.5 c 128,-1,25
+ 1176 1403 1176 1403 1176 1352 c 0,26,27
+ 1176 1300 1176 1300 1141.5 1268.5 c 128,-1,28
+ 1107 1237 1107 1237 1036 1237 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 124 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 110 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 108 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 99 -154 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 98 -154 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 85 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 82 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 79 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 76 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 72 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 68 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 36 -154 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -256 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -231 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: G
+Encoding: 71 71 42
+Width: 1622
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 53
+ 29
+ 1
+ 33
+ 53
+ 1
+ 33
+ 43
+ 18
+ 12
+ 12
+ 26
+ 1
+ 0
+ 0
+ 0
+ 0
+ 1
+ 46
+ 53
+ 45
+ 0
+ 0
+ 0
+ 0
+ 0
+ 5
+ 1
+ 41
+ 43
+ 8
+ 9
+ 8
+ 3
+ 7
+ 49
+ 29
+ 2
+ 45
+ 38
+ 1
+ 23
+ 5
+ 2
+ 137
+ 1
+ 45
+ 13
+ 128
+ 38
+ 13
+ 10
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1499 596 m 2,0,-1
+ 1499 315 l 2,1,2
+ 1499 259 1499 259 1488 225.5 c 128,-1,3
+ 1477 192 1477 192 1447.5 165 c 128,-1,4
+ 1418 138 1418 138 1372 113 c 0,5,6
+ 1239 41 1239 41 1116 8 c 128,-1,7
+ 993 -25 993 -25 848 -25 c 0,8,9
+ 679 -25 679 -25 540 27 c 128,-1,10
+ 401 79 401 79 303 178 c 128,-1,11
+ 205 277 205 277 152.5 418 c 128,-1,12
+ 100 559 100 559 100 733 c 0,13,14
+ 100 904 100 904 151 1046 c 128,-1,15
+ 202 1188 202 1188 301 1287 c 128,-1,16
+ 400 1386 400 1386 542 1438.5 c 128,-1,17
+ 684 1491 684 1491 864 1491 c 0,18,19
+ 1012 1491 1012 1491 1126 1451.5 c 128,-1,20
+ 1240 1412 1240 1412 1311 1352 c 128,-1,21
+ 1382 1292 1382 1292 1418 1225 c 128,-1,22
+ 1454 1158 1454 1158 1454 1106 c 0,23,24
+ 1454 1050 1454 1050 1412.5 1010.5 c 128,-1,25
+ 1371 971 1371 971 1313 971 c 0,26,27
+ 1281 971 1281 971 1251.5 986 c 128,-1,28
+ 1222 1001 1222 1001 1202 1028 c 0,29,30
+ 1147 1114 1147 1114 1109 1158 c 128,-1,31
+ 1071 1202 1071 1202 1006.5 1232 c 128,-1,32
+ 942 1262 942 1262 842 1262 c 0,33,34
+ 739 1262 739 1262 658 1226.5 c 128,-1,35
+ 577 1191 577 1191 519.5 1123.5 c 128,-1,36
+ 462 1056 462 1056 431.5 958 c 128,-1,37
+ 401 860 401 860 401 741 c 0,38,39
+ 401 483 401 483 519.5 344 c 128,-1,40
+ 638 205 638 205 850 205 c 0,41,42
+ 953 205 953 205 1043.5 232 c 128,-1,43
+ 1134 259 1134 259 1227 309 c 1,44,-1
+ 1227 547 l 1,45,-1
+ 997 547 l 2,46,47
+ 914 547 914 547 871.5 572 c 128,-1,48
+ 829 597 829 597 829 657 c 0,49,50
+ 829 706 829 706 864.5 738 c 128,-1,51
+ 900 770 900 770 961 770 c 2,52,-1
+ 1298 770 l 2,53,54
+ 1360 770 1360 770 1403 759 c 128,-1,55
+ 1446 748 1446 748 1472.5 710 c 128,-1,56
+ 1499 672 1499 672 1499 596 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 42 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 36 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: H
+Encoding: 72 72 43
+Width: 1556
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 29
+ 40
+ 2
+ 18
+ 10
+ 7
+ 29
+ 12
+ 22
+ 9
+ 13
+ 9
+ 6
+ 12
+ 0
+ 16
+ 1
+ 129
+ 10
+ 2
+ 14
+ 0
+ 0
+ 1
+ 129
+ 18
+ 26
+ 15
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+459 1311 m 2,0,-1
+ 459 891 l 1,1,-1
+ 1100 891 l 1,2,-1
+ 1100 1311 l 2,3,4
+ 1100 1401 1100 1401 1140.5 1446 c 128,-1,5
+ 1181 1491 1181 1491 1247 1491 c 0,6,7
+ 1314 1491 1314 1491 1355.5 1446.5 c 128,-1,8
+ 1397 1402 1397 1402 1397 1311 c 2,9,-1
+ 1397 156 l 2,10,11
+ 1397 65 1397 65 1355 20 c 128,-1,12
+ 1313 -25 1313 -25 1247 -25 c 0,13,14
+ 1180 -25 1180 -25 1140 20.5 c 128,-1,15
+ 1100 66 1100 66 1100 156 c 2,16,-1
+ 1100 649 l 1,17,-1
+ 459 649 l 1,18,-1
+ 459 156 l 2,19,20
+ 459 65 459 65 417 20 c 128,-1,21
+ 375 -25 375 -25 309 -25 c 0,22,23
+ 242 -25 242 -25 202 20.5 c 128,-1,24
+ 162 66 162 66 162 156 c 2,25,-1
+ 162 1311 l 2,26,27
+ 162 1401 162 1401 201.5 1446 c 128,-1,28
+ 241 1491 241 1491 309 1491 c 0,29,30
+ 376 1491 376 1491 417.5 1446.5 c 128,-1,31
+ 459 1402 459 1402 459 1311 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: I
+Encoding: 73 73 44
+Width: 641
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 9
+ 11
+ 9
+ 4
+ 12
+ 129
+ 8
+ 1
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+172 156 m 2,0,-1
+ 172 1311 l 2,1,2
+ 172 1401 172 1401 213 1446 c 128,-1,3
+ 254 1491 254 1491 319 1491 c 0,4,5
+ 386 1491 386 1491 427.5 1446.5 c 128,-1,6
+ 469 1402 469 1402 469 1311 c 2,7,-1
+ 469 156 l 2,8,9
+ 469 65 469 65 427.5 20 c 128,-1,10
+ 386 -25 386 -25 319 -25 c 0,11,12
+ 255 -25 255 -25 213.5 20.5 c 128,-1,13
+ 172 66 172 66 172 156 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: J
+Encoding: 74 74 45
+Width: 1174
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 20
+ 0
+ 0
+ 0
+ 0
+ 10
+ 1
+ 23
+ 41
+ 7
+ 9
+ 8
+ 7
+ 29
+ 12
+ 16
+ 129
+ 1
+ 25
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MIAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1012 1311 m 2,0,-1
+ 1012 543 l 2,1,2
+ 1012 443 1012 443 1003.5 373 c 128,-1,3
+ 995 303 995 303 965 231 c 0,4,5
+ 915 110 915 110 800 42.5 c 128,-1,6
+ 685 -25 685 -25 520 -25 c 0,7,8
+ 371 -25 371 -25 271.5 22 c 128,-1,9
+ 172 69 172 69 111 174 c 0,10,11
+ 79 230 79 230 59 303 c 128,-1,12
+ 39 376 39 376 39 442 c 0,13,14
+ 39 512 39 512 78 549 c 128,-1,15
+ 117 586 117 586 178 586 c 0,16,17
+ 237 586 237 586 267 552 c 128,-1,18
+ 297 518 297 518 313 446 c 0,19,20
+ 330 369 330 369 347 323 c 128,-1,21
+ 364 277 364 277 404 244 c 128,-1,22
+ 444 211 444 211 518 211 c 0,23,24
+ 715 211 715 211 715 500 c 2,25,-1
+ 715 1311 l 2,26,27
+ 715 1401 715 1401 754.5 1446 c 128,-1,28
+ 794 1491 794 1491 862 1491 c 0,29,30
+ 931 1491 931 1491 971.5 1446 c 128,-1,31
+ 1012 1401 1012 1401 1012 1311 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 99 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 98 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 36 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 30 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 29 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -154 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: K
+Encoding: 75 75 46
+Width: 1516
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 18
+ 38
+ 12
+ 28
+ 9
+ 23
+ 18
+ 9
+ 5
+ 12
+ 1
+ 0
+ 0
+ 1
+ 129
+ 24
+ 35
+ 15
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+MDAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+459 1311 m 2,0,-1
+ 459 797 l 1,1,-1
+ 1042 1405 l 2,2,3
+ 1084 1449 1084 1449 1113.5 1470 c 128,-1,4
+ 1143 1491 1143 1491 1192 1491 c 0,5,6
+ 1256 1491 1256 1491 1295.5 1453.5 c 128,-1,7
+ 1335 1416 1335 1416 1335 1362 c 0,8,9
+ 1335 1297 1335 1297 1268 1233 c 2,10,-1
+ 907 891 l 1,11,-1
+ 1323 295 l 2,12,13
+ 1367 233 1367 233 1389 186.5 c 128,-1,14
+ 1411 140 1411 140 1411 96 c 0,15,16
+ 1411 47 1411 47 1372.5 11 c 128,-1,17
+ 1334 -25 1334 -25 1268 -25 c 0,18,19
+ 1206 -25 1206 -25 1167 1.5 c 128,-1,20
+ 1128 28 1128 28 1101 72 c 128,-1,21
+ 1074 116 1074 116 1053 152 c 2,22,-1
+ 702 692 l 1,23,-1
+ 459 459 l 1,24,-1
+ 459 156 l 2,25,26
+ 459 64 459 64 417 19.5 c 128,-1,27
+ 375 -25 375 -25 309 -25 c 0,28,29
+ 271 -25 271 -25 236 -5 c 128,-1,30
+ 201 15 201 15 182 49 c 0,31,32
+ 168 77 168 77 165 114 c 128,-1,33
+ 162 151 162 151 162 221 c 2,34,-1
+ 162 1311 l 2,35,36
+ 162 1401 162 1401 201.5 1446 c 128,-1,37
+ 241 1491 241 1491 309 1491 c 0,38,39
+ 376 1491 376 1491 417.5 1446.5 c 128,-1,40
+ 459 1402 459 1402 459 1311 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 129 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 124 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 110 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 108 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 103 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 92 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 90 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 89 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 88 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 82 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 72 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 68 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 50 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 42 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 38 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 12 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: L
+Encoding: 76 76 47
+Width: 1237
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 13
+ 1
+ 39
+ 9
+ 9
+ 11
+ 7
+ 16
+ 12
+ 129
+ 0
+ 13
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+451 1311 m 2,0,-1
+ 451 244 l 1,1,-1
+ 1053 244 l 2,2,3
+ 1125 244 1125 244 1163.5 209 c 128,-1,4
+ 1202 174 1202 174 1202 121 c 0,5,6
+ 1202 67 1202 67 1164 33.5 c 128,-1,7
+ 1126 0 1126 0 1053 0 c 2,8,-1
+ 336 0 l 2,9,10
+ 239 0 239 0 196.5 43 c 128,-1,11
+ 154 86 154 86 154 182 c 2,12,-1
+ 154 1311 l 2,13,14
+ 154 1401 154 1401 194.5 1446 c 128,-1,15
+ 235 1491 235 1491 301 1491 c 0,16,17
+ 368 1491 368 1491 409.5 1446.5 c 128,-1,18
+ 451 1402 451 1402 451 1311 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 183 -205 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 181 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 104 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 103 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 92 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 90 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 60 -258 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 58 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 57 -231 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 56 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 55 -256 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 54 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 50 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 42 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 38 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 36 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: M
+Encoding: 77 77 48
+Width: 1706
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 29
+ 40
+ 9
+ 35
+ 31
+ 9
+ 24
+ 12
+ 18
+ 13
+ 12
+ 5
+ 9
+ 1
+ 18
+ 17
+ 2
+ 34
+ 1
+ 1
+ 137
+ 28
+ 34
+ 10
+ 137
+ 1
+ 9
+ 10
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+MDAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+MDAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+655 221 m 2,0,-1
+ 420 1155 l 1,1,-1
+ 420 143 l 2,2,3
+ 420 59 420 59 382.5 17 c 128,-1,4
+ 345 -25 345 -25 283 -25 c 0,5,6
+ 223 -25 223 -25 185 16.5 c 128,-1,7
+ 147 58 147 58 147 143 c 2,8,-1
+ 147 1303 l 2,9,10
+ 147 1399 147 1399 197 1432.5 c 128,-1,11
+ 247 1466 247 1466 332 1466 c 2,12,-1
+ 424 1466 l 2,13,14
+ 507 1466 507 1466 544.5 1451 c 128,-1,15
+ 582 1436 582 1436 600 1397 c 128,-1,16
+ 618 1358 618 1358 641 1270 c 2,17,-1
+ 854 467 l 1,18,-1
+ 1067 1270 l 2,19,20
+ 1090 1358 1090 1358 1108 1397 c 128,-1,21
+ 1126 1436 1126 1436 1163.5 1451 c 128,-1,22
+ 1201 1466 1201 1466 1284 1466 c 2,23,-1
+ 1376 1466 l 2,24,25
+ 1461 1466 1461 1466 1511 1432.5 c 128,-1,26
+ 1561 1399 1561 1399 1561 1303 c 2,27,-1
+ 1561 143 l 2,28,29
+ 1561 59 1561 59 1523.5 17 c 128,-1,30
+ 1486 -25 1486 -25 1423 -25 c 0,31,32
+ 1364 -25 1364 -25 1326 17 c 128,-1,33
+ 1288 59 1288 59 1288 143 c 2,34,-1
+ 1288 1155 l 1,35,-1
+ 1053 221 l 2,36,37
+ 1030 130 1030 130 1015.5 87.5 c 128,-1,38
+ 1001 45 1001 45 962 10 c 128,-1,39
+ 923 -25 923 -25 854 -25 c 0,40,41
+ 802 -25 802 -25 766 -2.5 c 128,-1,42
+ 730 20 730 20 710 55 c 128,-1,43
+ 690 90 690 90 678.5 132.5 c 128,-1,44
+ 667 175 667 175 655 221 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: N
+Encoding: 78 78 49
+Width: 1556
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 28
+ 30
+ 12
+ 21
+ 9
+ 17
+ 11
+ 9
+ 5
+ 12
+ 1
+ 16
+ 0
+ 2
+ 1
+ 17
+ 1
+ 137
+ 9
+ 1
+ 10
+ 27
+ 1
+ 135
+ 17
+ 25
+ 13
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+MDAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+547 1313 m 2,0,-1
+ 1118 449 l 1,1,-1
+ 1118 1321 l 2,2,3
+ 1118 1406 1118 1406 1154.5 1448.5 c 128,-1,4
+ 1191 1491 1191 1491 1253 1491 c 0,5,6
+ 1317 1491 1317 1491 1354 1448.5 c 128,-1,7
+ 1391 1406 1391 1406 1391 1321 c 2,8,-1
+ 1391 168 l 2,9,10
+ 1391 -25 1391 -25 1231 -25 c 0,11,12
+ 1191 -25 1191 -25 1159 -13.5 c 128,-1,13
+ 1127 -2 1127 -2 1099 23 c 128,-1,14
+ 1071 48 1071 48 1047 81.5 c 128,-1,15
+ 1023 115 1023 115 999 150 c 2,16,-1
+ 442 1004 l 1,17,-1
+ 442 145 l 2,18,19
+ 442 61 442 61 403 18 c 128,-1,20
+ 364 -25 364 -25 303 -25 c 0,21,22
+ 240 -25 240 -25 202 18.5 c 128,-1,23
+ 164 62 164 62 164 145 c 2,24,-1
+ 164 1276 l 2,25,26
+ 164 1348 164 1348 180 1389 c 0,27,28
+ 199 1434 199 1434 243 1462.5 c 128,-1,29
+ 287 1491 287 1491 338 1491 c 0,30,31
+ 378 1491 378 1491 406.5 1478 c 128,-1,32
+ 435 1465 435 1465 456.5 1443 c 128,-1,33
+ 478 1421 478 1421 500.5 1386 c 128,-1,34
+ 523 1351 523 1351 547 1313 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 99 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 98 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 36 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: O
+Encoding: 79 79 50
+Width: 1622
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 27
+ 23
+ 41
+ 0
+ 12
+ 12
+ 33
+ 41
+ 9
+ 9
+ 11
+ 2
+ 7
+ 0
+ 1
+ 19
+ 28
+ 1
+ 128
+ 4
+ 19
+ 10
+ 128
+ 28
+ 14
+ 10
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+805 1491 m 0,0,1
+ 1033 1491 1033 1491 1196.5 1398.5 c 128,-1,2
+ 1360 1306 1360 1306 1444 1135.5 c 128,-1,3
+ 1528 965 1528 965 1528 735 c 0,4,5
+ 1528 565 1528 565 1482 426 c 128,-1,6
+ 1436 287 1436 287 1344 185 c 128,-1,7
+ 1252 83 1252 83 1118 29 c 128,-1,8
+ 984 -25 984 -25 811 -25 c 0,9,10
+ 639 -25 639 -25 503 30.5 c 128,-1,11
+ 367 86 367 86 276 187 c 128,-1,12
+ 185 288 185 288 138.5 430 c 128,-1,13
+ 92 572 92 572 92 737 c 0,14,15
+ 92 906 92 906 140.5 1047 c 128,-1,16
+ 189 1188 189 1188 281 1287 c 128,-1,17
+ 373 1386 373 1386 505 1438.5 c 128,-1,18
+ 637 1491 637 1491 805 1491 c 0,0,1
+1227 737 m 0,19,20
+ 1227 898 1227 898 1175 1016 c 128,-1,21
+ 1123 1134 1123 1134 1026.5 1194.5 c 128,-1,22
+ 930 1255 930 1255 805 1255 c 0,23,24
+ 716 1255 716 1255 640.5 1221.5 c 128,-1,25
+ 565 1188 565 1188 510.5 1124 c 128,-1,26
+ 456 1060 456 1060 424.5 960.5 c 128,-1,27
+ 393 861 393 861 393 737 c 0,28,29
+ 393 612 393 612 424.5 511 c 128,-1,30
+ 456 410 456 410 513.5 343.5 c 128,-1,31
+ 571 277 571 277 645.5 244 c 128,-1,32
+ 720 211 720 211 809 211 c 0,33,34
+ 923 211 923 211 1018.5 268 c 128,-1,35
+ 1114 325 1114 325 1170.5 444 c 128,-1,36
+ 1227 563 1227 563 1227 737 c 0,19,20
+EndSplineSet
+Validated: 1
+Kerns2: 99 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 98 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 60 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 59 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 58 25 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 57 -53 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 55 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 36 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -104 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: P
+Encoding: 80 80 51
+Width: 1366
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 39
+ 0
+ 0
+ 0
+ 0
+ 15
+ 1
+ 23
+ 46
+ 13
+ 12
+ 9
+ 46
+ 25
+ 0
+ 10
+ 2
+ 7
+ 5
+ 9
+ 0
+ 1
+ 29
+ 1
+ 1
+ 15
+ 1
+ 128
+ 19
+ 29
+ 13
+ 0
+ 24
+ 1
+ 129
+ 1
+ 9
+ 15
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+729 571 m 2,0,-1
+ 457 571 l 1,1,-1
+ 457 156 l 2,2,3
+ 457 67 457 67 415 21 c 128,-1,4
+ 373 -25 373 -25 309 -25 c 0,5,6
+ 242 -25 242 -25 201 20.5 c 128,-1,7
+ 160 66 160 66 160 154 c 2,8,-1
+ 160 1284 l 2,9,10
+ 160 1382 160 1382 205 1424 c 128,-1,11
+ 250 1466 250 1466 348 1466 c 2,12,-1
+ 729 1466 l 2,13,14
+ 898 1466 898 1466 989 1440 c 0,15,16
+ 1079 1415 1079 1415 1144.5 1357 c 128,-1,17
+ 1210 1299 1210 1299 1244 1215 c 128,-1,18
+ 1278 1131 1278 1131 1278 1026 c 0,19,20
+ 1278 802 1278 802 1140 686.5 c 128,-1,21
+ 1002 571 1002 571 729 571 c 2,0,-1
+657 1243 m 2,22,-1
+ 457 1243 l 1,23,-1
+ 457 795 l 1,24,-1
+ 657 795 l 2,25,26
+ 762 795 762 795 832.5 817 c 128,-1,27
+ 903 839 903 839 940 889 c 128,-1,28
+ 977 939 977 939 977 1020 c 0,29,30
+ 977 1117 977 1117 920 1178 c 0,31,32
+ 856 1243 856 1243 657 1243 c 2,22,-1
+EndSplineSet
+Validated: 1
+Kerns2: 110 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 99 -180 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 98 -180 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 82 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 72 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 68 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 36 -180 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -307 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -283 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: Q
+Encoding: 81 81 52
+Width: 1622
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 52
+ 53
+ 46
+ 2
+ 36
+ 44
+ 1
+ 36
+ 41
+ 23
+ 12
+ 12
+ 29
+ 1
+ 0
+ 7
+ 1
+ 0
+ 11
+ 0
+ 2
+ 44
+ 41
+ 13
+ 9
+ 8
+ 2
+ 7
+ 50
+ 46
+ 29
+ 11
+ 4
+ 32
+ 41
+ 1
+ 4
+ 1
+ 0
+ 0
+ 0
+ 0
+ 1
+ 128
+ 27
+ 32
+ 0
+ 128
+ 41
+ 18
+ 10
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1339 182 m 1,0,1
+ 1404 138 1404 138 1481 96.5 c 128,-1,2
+ 1558 55 1558 55 1583 30.5 c 128,-1,3
+ 1608 6 1608 6 1608 -39 c 0,4,5
+ 1608 -71 1608 -71 1578.5 -103 c 128,-1,6
+ 1549 -135 1549 -135 1507 -135 c 0,7,8
+ 1473 -135 1473 -135 1424.5 -113 c 128,-1,9
+ 1376 -91 1376 -91 1310.5 -49 c 128,-1,10
+ 1245 -7 1245 -7 1167 49 c 1,11,12
+ 1022 -25 1022 -25 811 -25 c 0,13,14
+ 640 -25 640 -25 504.5 29.5 c 128,-1,15
+ 369 84 369 84 277 186.5 c 128,-1,16
+ 185 289 185 289 138.5 430 c 128,-1,17
+ 92 571 92 571 92 737 c 0,18,19
+ 92 906 92 906 140.5 1047 c 128,-1,20
+ 189 1188 189 1188 281 1287 c 128,-1,21
+ 373 1386 373 1386 505 1438.5 c 128,-1,22
+ 637 1491 637 1491 805 1491 c 0,23,24
+ 1033 1491 1033 1491 1196.5 1398.5 c 128,-1,25
+ 1360 1306 1360 1306 1444 1135.5 c 128,-1,26
+ 1528 965 1528 965 1528 735 c 0,27,28
+ 1528 386 1528 386 1339 182 c 1,0,1
+1106 344 m 1,29,30
+ 1168 415 1168 415 1197.5 512 c 128,-1,31
+ 1227 609 1227 609 1227 737 c 0,32,33
+ 1227 898 1227 898 1175 1016 c 128,-1,34
+ 1123 1134 1123 1134 1026.5 1194.5 c 128,-1,35
+ 930 1255 930 1255 805 1255 c 0,36,37
+ 716 1255 716 1255 640.5 1221.5 c 128,-1,38
+ 565 1188 565 1188 510.5 1124 c 128,-1,39
+ 456 1060 456 1060 424.5 960.5 c 128,-1,40
+ 393 861 393 861 393 737 c 0,41,42
+ 393 484 393 484 511 347.5 c 128,-1,43
+ 629 211 629 211 809 211 c 0,44,45
+ 883 211 883 211 961 242 c 1,46,47
+ 914 277 914 277 843.5 312 c 128,-1,48
+ 773 347 773 347 747 366 c 128,-1,49
+ 721 385 721 385 721 420 c 0,50,51
+ 721 450 721 450 746 473 c 128,-1,52
+ 771 496 771 496 801 496 c 0,53,54
+ 892 496 892 496 1106 344 c 1,29,30
+EndSplineSet
+Validated: 1
+Kerns2: 92 25 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 83 51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 77 127 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 74 51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 73 76 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 60 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 58 51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 57 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 55 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: R
+Encoding: 82 82 53
+Width: 1473
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 50
+ 0
+ 0
+ 0
+ 0
+ 16
+ 1
+ 42
+ 46
+ 13
+ 12
+ 9
+ 23
+ 1
+ 48
+ 44
+ 1
+ 13
+ 2
+ 7
+ 32
+ 9
+ 5
+ 9
+ 37
+ 0
+ 2
+ 48
+ 1
+ 1
+ 28
+ 1
+ 0
+ 23
+ 1
+ 0
+ 16
+ 1
+ 128
+ 20
+ 48
+ 0
+ 0
+ 43
+ 1
+ 129
+ 1
+ 9
+ 15
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+559 627 m 2,0,-1
+ 455 627 l 1,1,-1
+ 455 156 l 2,2,3
+ 455 63 455 63 414 19 c 128,-1,4
+ 373 -25 373 -25 307 -25 c 0,5,6
+ 236 -25 236 -25 197 21 c 128,-1,7
+ 158 67 158 67 158 156 c 2,8,-1
+ 158 1284 l 2,9,10
+ 158 1380 158 1380 201 1423 c 128,-1,11
+ 244 1466 244 1466 340 1466 c 2,12,-1
+ 823 1466 l 2,13,14
+ 923 1466 923 1466 994 1457.5 c 128,-1,15
+ 1065 1449 1065 1449 1122 1423 c 0,16,17
+ 1191 1394 1191 1394 1244 1340 c 128,-1,18
+ 1297 1286 1297 1286 1324.5 1214.5 c 128,-1,19
+ 1352 1143 1352 1143 1352 1063 c 0,20,21
+ 1352 899 1352 899 1259.5 801 c 128,-1,22
+ 1167 703 1167 703 979 662 c 1,23,24
+ 1058 620 1058 620 1130 538 c 128,-1,25
+ 1202 456 1202 456 1258.5 363.5 c 128,-1,26
+ 1315 271 1315 271 1346.5 196.5 c 128,-1,27
+ 1378 122 1378 122 1378 94 c 0,28,29
+ 1378 65 1378 65 1359.5 36.5 c 128,-1,30
+ 1341 8 1341 8 1309 -8.5 c 128,-1,31
+ 1277 -25 1277 -25 1235 -25 c 0,32,33
+ 1185 -25 1185 -25 1151 -1.5 c 128,-1,34
+ 1117 22 1117 22 1092.5 58 c 128,-1,35
+ 1068 94 1068 94 1026 164 c 2,36,-1
+ 907 362 l 2,37,38
+ 843 471 843 471 792.5 528 c 128,-1,39
+ 742 585 742 585 690 606 c 128,-1,40
+ 638 627 638 627 559 627 c 2,0,-1
+729 1243 m 2,41,-1
+ 455 1243 l 1,42,-1
+ 455 840 l 1,43,-1
+ 721 840 l 2,44,45
+ 828 840 828 840 901 858.5 c 128,-1,46
+ 974 877 974 877 1012.5 921.5 c 128,-1,47
+ 1051 966 1051 966 1051 1044 c 0,48,49
+ 1051 1105 1051 1105 1020 1151.5 c 128,-1,50
+ 989 1198 989 1198 934 1221 c 0,51,52
+ 882 1243 882 1243 729 1243 c 2,41,-1
+EndSplineSet
+Validated: 1
+Kerns2: 129 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 124 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 110 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 108 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 104 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 92 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 90 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 89 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 88 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 82 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 72 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 68 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 60 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 57 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 56 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 55 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 42 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 38 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 12 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: S
+Encoding: 83 83 54
+Width: 1366
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 57
+ 56
+ 42
+ 26
+ 15
+ 12
+ 0
+ 6
+ 48
+ 19
+ 1
+ 48
+ 49
+ 34
+ 12
+ 12
+ 0
+ 0
+ 0
+ 0
+ 6
+ 1
+ 19
+ 47
+ 4
+ 9
+ 8
+ 2
+ 7
+ 45
+ 10
+ 56
+ 45
+ 26
+ 3
+ 22
+ 51
+ 1
+ 39
+ 1
+ 130
+ 0
+ 22
+ 13
+ 0
+ 0
+ 9
+ 1
+ 0
+ 15
+ 6
+ 2
+ 136
+ 51
+ 30
+ 0
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1274 440 m 0,0,1
+ 1274 307 1274 307 1205.5 201 c 128,-1,2
+ 1137 95 1137 95 1005 35 c 128,-1,3
+ 873 -25 873 -25 692 -25 c 0,4,5
+ 475 -25 475 -25 334 57 c 0,6,7
+ 234 116 234 116 171.5 214.5 c 128,-1,8
+ 109 313 109 313 109 406 c 0,9,10
+ 109 460 109 460 146.5 498.5 c 128,-1,11
+ 184 537 184 537 242 537 c 0,12,13
+ 289 537 289 537 321.5 507 c 128,-1,14
+ 354 477 354 477 377 418 c 0,15,16
+ 405 348 405 348 437.5 301 c 128,-1,17
+ 470 254 470 254 529 223.5 c 128,-1,18
+ 588 193 588 193 684 193 c 0,19,20
+ 816 193 816 193 898.5 254.5 c 128,-1,21
+ 981 316 981 316 981 408 c 0,22,23
+ 981 481 981 481 936.5 526.5 c 128,-1,24
+ 892 572 892 572 821.5 596 c 128,-1,25
+ 751 620 751 620 633 647 c 0,26,27
+ 475 684 475 684 368.5 733.5 c 128,-1,28
+ 262 783 262 783 199.5 868.5 c 128,-1,29
+ 137 954 137 954 137 1081 c 0,30,31
+ 137 1202 137 1202 203 1296 c 128,-1,32
+ 269 1390 269 1390 394 1440.5 c 128,-1,33
+ 519 1491 519 1491 688 1491 c 0,34,35
+ 823 1491 823 1491 921.5 1457.5 c 128,-1,36
+ 1020 1424 1020 1424 1085 1368.5 c 128,-1,37
+ 1150 1313 1150 1313 1180 1252 c 128,-1,38
+ 1210 1191 1210 1191 1210 1133 c 0,39,40
+ 1210 1080 1210 1080 1172.5 1037.5 c 128,-1,41
+ 1135 995 1135 995 1079 995 c 0,42,43
+ 1028 995 1028 995 1001.5 1020.5 c 128,-1,44
+ 975 1046 975 1046 944 1104 c 0,45,46
+ 904 1187 904 1187 848 1233.5 c 128,-1,47
+ 792 1280 792 1280 668 1280 c 0,48,49
+ 553 1280 553 1280 482.5 1229.5 c 128,-1,50
+ 412 1179 412 1179 412 1108 c 0,51,52
+ 412 1064 412 1064 436 1032 c 128,-1,53
+ 460 1000 460 1000 502 977 c 128,-1,54
+ 544 954 544 954 587 941 c 128,-1,55
+ 630 928 630 928 729 903 c 0,56,57
+ 853 874 853 874 953.5 839 c 128,-1,58
+ 1054 804 1054 804 1124.5 754 c 128,-1,59
+ 1195 704 1195 704 1234.5 627.5 c 128,-1,60
+ 1274 551 1274 551 1274 440 c 0,0,1
+EndSplineSet
+Validated: 1
+Kerns2: 17 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: T
+Encoding: 84 84 55
+Width: 1280
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 19
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+ 9
+ 38
+ 17
+ 12
+ 9
+ 7
+ 5
+ 9
+ 129
+ 1
+ 8
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1112 1221 m 2,0,-1
+ 788 1221 l 1,1,-1
+ 788 156 l 2,2,3
+ 788 64 788 64 747 19.5 c 128,-1,4
+ 706 -25 706 -25 641 -25 c 0,5,6
+ 575 -25 575 -25 533.5 20 c 128,-1,7
+ 492 65 492 65 492 156 c 2,8,-1
+ 492 1221 l 1,9,-1
+ 168 1221 l 2,10,11
+ 92 1221 92 1221 55 1254.5 c 128,-1,12
+ 18 1288 18 1288 18 1343 c 0,13,14
+ 18 1400 18 1400 56.5 1433 c 128,-1,15
+ 95 1466 95 1466 168 1466 c 2,16,-1
+ 1112 1466 l 2,17,18
+ 1189 1466 1189 1466 1226.5 1432 c 128,-1,19
+ 1264 1398 1264 1398 1264 1343 c 256,20,21
+ 1264 1288 1264 1288 1226 1254.5 c 128,-1,22
+ 1188 1221 1188 1221 1112 1221 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 110 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 103 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 99 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 98 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 93 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 92 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 90 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 88 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 86 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 85 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 82 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 80 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 76 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 75 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 72 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 70 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 68 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 52 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 50 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 42 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 38 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 36 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 30 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 29 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -256 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 16 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -231 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: U
+Encoding: 85 85 56
+Width: 1556
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 28
+ 0
+ 0
+ 0
+ 0
+ 26
+ 1
+ 12
+ 41
+ 29
+ 9
+ 8
+ 7
+ 19
+ 12
+ 4
+ 12
+ 26
+ 1
+ 129
+ 23
+ 15
+ 13
+ 129
+ 7
+ 1
+ 10
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+162 606 m 2,0,-1
+ 162 1311 l 2,1,2
+ 162 1401 162 1401 202.5 1446 c 128,-1,3
+ 243 1491 243 1491 309 1491 c 0,4,5
+ 378 1491 378 1491 418.5 1446 c 128,-1,6
+ 459 1401 459 1401 459 1311 c 2,7,-1
+ 459 590 l 2,8,9
+ 459 467 459 467 486.5 384.5 c 128,-1,10
+ 514 302 514 302 584 256.5 c 128,-1,11
+ 654 211 654 211 780 211 c 0,12,13
+ 954 211 954 211 1026 303.5 c 128,-1,14
+ 1098 396 1098 396 1098 584 c 2,15,-1
+ 1098 1311 l 2,16,17
+ 1098 1402 1098 1402 1138 1446.5 c 128,-1,18
+ 1178 1491 1178 1491 1245 1491 c 256,19,20
+ 1312 1491 1312 1491 1353.5 1446.5 c 128,-1,21
+ 1395 1402 1395 1402 1395 1311 c 2,22,-1
+ 1395 606 l 2,23,24
+ 1395 434 1395 434 1361.5 319 c 128,-1,25
+ 1328 204 1328 204 1235 117 c 0,26,27
+ 1155 43 1155 43 1049 9 c 128,-1,28
+ 943 -25 943 -25 801 -25 c 0,29,30
+ 632 -25 632 -25 510 11.5 c 128,-1,31
+ 388 48 388 48 311 124.5 c 128,-1,32
+ 234 201 234 201 198 320.5 c 128,-1,33
+ 162 440 162 440 162 606 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 99 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 98 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 36 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: V
+Encoding: 86 86 57
+Width: 1409
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 12
+ 33
+ 12
+ 20
+ 9
+ 6
+ 12
+ 1
+ 94
+ 10
+ 30
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+377 1296 m 2,0,-1
+ 709 313 l 1,1,-1
+ 1042 1303 l 2,2,3
+ 1068 1381 1068 1381 1081 1411.5 c 128,-1,4
+ 1094 1442 1094 1442 1124 1466.5 c 128,-1,5
+ 1154 1491 1154 1491 1206 1491 c 0,6,7
+ 1244 1491 1244 1491 1276.5 1472 c 128,-1,8
+ 1309 1453 1309 1453 1327.5 1421.5 c 128,-1,9
+ 1346 1390 1346 1390 1346 1358 c 0,10,11
+ 1346 1336 1346 1336 1340 1310.5 c 128,-1,12
+ 1334 1285 1334 1285 1325 1260.5 c 128,-1,13
+ 1316 1236 1316 1236 1307 1210 c 2,14,-1
+ 952 252 l 2,15,16
+ 933 197 933 197 914 147.5 c 128,-1,17
+ 895 98 895 98 870 60.5 c 128,-1,18
+ 845 23 845 23 803.5 -1 c 128,-1,19
+ 762 -25 762 -25 702 -25 c 256,20,21
+ 642 -25 642 -25 600.5 -1.5 c 128,-1,22
+ 559 22 559 22 533.5 60.5 c 128,-1,23
+ 508 99 508 99 489 148 c 128,-1,24
+ 470 197 470 197 451 252 c 2,25,-1
+ 102 1202 l 2,26,27
+ 93 1228 93 1228 83.5 1253 c 128,-1,28
+ 74 1278 74 1278 67.5 1307 c 128,-1,29
+ 61 1336 61 1336 61 1356 c 0,30,31
+ 61 1407 61 1407 102 1449 c 128,-1,32
+ 143 1491 143 1491 205 1491 c 0,33,34
+ 281 1491 281 1491 312.5 1444.5 c 128,-1,35
+ 344 1398 344 1398 377 1296 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 110 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 103 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 99 -104 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 98 -104 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 92 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 88 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 85 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 82 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 76 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 72 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 68 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 52 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 50 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 42 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 38 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 36 -104 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 30 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 29 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -256 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 16 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -231 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: W
+Encoding: 87 87 58
+Width: 1921
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 18
+ 46
+ 9
+ 36
+ 12
+ 31
+ 26
+ 12
+ 21
+ 17
+ 12
+ 6
+ 9
+ 1
+ 88
+ 39
+ 14
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+MDAP[rnd]
+MIAP[rnd]
+MDAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1198 231 m 2,0,-1
+ 961 1110 l 1,1,-1
+ 721 231 l 2,2,3
+ 693 131 693 131 676.5 87.5 c 128,-1,4
+ 660 44 660 44 619 9.5 c 128,-1,5
+ 578 -25 578 -25 510 -25 c 0,6,7
+ 455 -25 455 -25 419.5 -4.5 c 128,-1,8
+ 384 16 384 16 362 53.5 c 128,-1,9
+ 340 91 340 91 326 142.5 c 128,-1,10
+ 312 194 312 194 301 238 c 2,11,-1
+ 57 1225 l 2,12,13
+ 35 1311 35 1311 35 1356 c 0,14,15
+ 35 1413 35 1413 75 1452 c 128,-1,16
+ 115 1491 115 1491 174 1491 c 0,17,18
+ 255 1491 255 1491 283 1439 c 128,-1,19
+ 311 1387 311 1387 332 1288 c 2,20,-1
+ 524 432 l 1,21,-1
+ 739 1233 l 2,22,23
+ 763 1325 763 1325 782 1373 c 128,-1,24
+ 801 1421 801 1421 844 1456 c 128,-1,25
+ 887 1491 887 1491 961 1491 c 0,26,27
+ 1036 1491 1036 1491 1077.5 1454.5 c 128,-1,28
+ 1119 1418 1119 1418 1135 1375 c 128,-1,29
+ 1151 1332 1151 1332 1178 1233 c 2,30,-1
+ 1395 432 l 1,31,-1
+ 1587 1288 l 2,32,33
+ 1601 1355 1601 1355 1613.5 1393 c 128,-1,34
+ 1626 1431 1626 1431 1656.5 1461 c 128,-1,35
+ 1687 1491 1687 1491 1745 1491 c 256,36,37
+ 1803 1491 1803 1491 1843.5 1452.5 c 128,-1,38
+ 1884 1414 1884 1414 1884 1356 c 0,39,40
+ 1884 1315 1884 1315 1862 1225 c 2,41,-1
+ 1618 238 l 2,42,43
+ 1593 138 1593 138 1576.5 91.5 c 128,-1,44
+ 1560 45 1560 45 1520.5 10 c 128,-1,45
+ 1481 -25 1481 -25 1409 -25 c 0,46,47
+ 1341 -25 1341 -25 1300 9 c 128,-1,48
+ 1259 43 1259 43 1243 85.5 c 128,-1,49
+ 1227 128 1227 128 1198 231 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 110 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 103 25 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 92 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 88 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 85 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 82 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 72 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 71 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 68 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 50 25 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 30 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 29 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 16 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: X
+Encoding: 88 88 59
+Width: 1237
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 32
+ 24
+ 1
+ 2
+ 27
+ 12
+ 37
+ 13
+ 7
+ 43
+ 9
+ 32
+ 9
+ 18
+ 12
+ 8
+ 12
+ 25
+ 24
+ 21
+ 13
+ 12
+ 11
+ 5
+ 2
+ 1
+ 0
+ 10
+ 96
+ 28
+ 46
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+106 285 m 2,0,-1
+ 434 764 l 1,1,-1
+ 158 1190 l 2,2,3
+ 119 1252 119 1252 99.5 1296.5 c 128,-1,4
+ 80 1341 80 1341 80 1382 c 0,5,6
+ 80 1424 80 1424 117.5 1457.5 c 128,-1,7
+ 155 1491 155 1491 209 1491 c 0,8,9
+ 271 1491 271 1491 305.5 1454.5 c 128,-1,10
+ 340 1418 340 1418 401 1319 c 2,11,-1
+ 621 963 l 1,12,-1
+ 856 1319 l 2,13,14
+ 885 1364 885 1364 905.5 1396 c 128,-1,15
+ 926 1428 926 1428 945 1449 c 128,-1,16
+ 964 1470 964 1470 987.5 1480.5 c 128,-1,17
+ 1011 1491 1011 1491 1042 1491 c 0,18,19
+ 1098 1491 1098 1491 1133.5 1457.5 c 128,-1,20
+ 1169 1424 1169 1424 1169 1378 c 0,21,22
+ 1169 1311 1169 1311 1092 1196 c 2,23,-1
+ 803 764 l 1,24,-1
+ 1114 285 l 2,25,26
+ 1156 222 1156 222 1175 180.5 c 128,-1,27
+ 1194 139 1194 139 1194 102 c 0,28,29
+ 1194 67 1194 67 1177 38 c 128,-1,30
+ 1160 9 1160 9 1129 -8 c 128,-1,31
+ 1098 -25 1098 -25 1059 -25 c 0,32,33
+ 1017 -25 1017 -25 988 -7.5 c 128,-1,34
+ 959 10 959 10 941 36 c 128,-1,35
+ 923 62 923 62 874 137 c 2,36,-1
+ 616 543 l 1,37,-1
+ 342 125 l 2,38,39
+ 310 75 310 75 296.5 55 c 128,-1,40
+ 283 35 283 35 264 16 c 128,-1,41
+ 245 -3 245 -3 219 -14 c 128,-1,42
+ 193 -25 193 -25 158 -25 c 0,43,44
+ 104 -25 104 -25 68.5 8 c 128,-1,45
+ 33 41 33 41 33 104 c 0,46,47
+ 33 178 33 178 106 285 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 103 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 50 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 42 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 38 -53 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: Y
+Encoding: 89 89 60
+Width: 1280
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 14
+ 29
+ 9
+ 18
+ 12
+ 12
+ 8
+ 12
+ 12
+ 1
+ 129
+ 25
+ 0
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MDAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+487 156 m 2,0,-1
+ 487 621 l 1,1,-1
+ 129 1176 l 2,2,3
+ 82 1251 82 1251 62.5 1293 c 128,-1,4
+ 43 1335 43 1335 43 1366 c 0,5,6
+ 43 1417 43 1417 82.5 1454 c 128,-1,7
+ 122 1491 122 1491 180 1491 c 0,8,9
+ 241 1491 241 1491 272.5 1456.5 c 128,-1,10
+ 304 1422 304 1422 367 1319 c 2,11,-1
+ 641 874 l 1,12,-1
+ 918 1319 l 2,13,14
+ 943 1360 943 1360 960 1388 c 128,-1,15
+ 977 1416 977 1416 997.5 1440.5 c 128,-1,16
+ 1018 1465 1018 1465 1043 1478 c 128,-1,17
+ 1068 1491 1068 1491 1104 1491 c 0,18,19
+ 1160 1491 1160 1491 1197.5 1454.5 c 128,-1,20
+ 1235 1418 1235 1418 1235 1370 c 0,21,22
+ 1235 1331 1235 1331 1216 1292 c 128,-1,23
+ 1197 1253 1197 1253 1151 1184 c 2,24,-1
+ 784 621 l 1,25,-1
+ 784 156 l 2,26,27
+ 784 65 784 65 742 20 c 128,-1,28
+ 700 -25 700 -25 635 -25 c 0,29,30
+ 569 -25 569 -25 528 19.5 c 128,-1,31
+ 487 64 487 64 487 156 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 110 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 103 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 99 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 98 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 89 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 88 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 84 -154 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 83 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 82 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 76 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 72 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 71 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 68 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 54 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 50 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 42 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 38 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 36 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 30 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 29 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -231 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 16 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -205 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: Z
+Encoding: 90 90 61
+Width: 1323
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 31
+ 0
+ 1
+ 1
+ 15
+ 1
+ 1
+ 46
+ 9
+ 12
+ 12
+ 15
+ 46
+ 23
+ 9
+ 11
+ 2
+ 7
+ 14
+ 10
+ 15
+ 14
+ 11
+ 5
+ 1
+ 0
+ 6
+ 94
+ 19
+ 26
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+121 342 m 2,0,-1
+ 874 1243 l 1,1,-1
+ 227 1243 l 2,2,3
+ 159 1243 159 1243 124.5 1273 c 128,-1,4
+ 90 1303 90 1303 90 1352 c 0,5,6
+ 90 1403 90 1403 124.5 1434.5 c 128,-1,7
+ 159 1466 159 1466 227 1466 c 2,8,-1
+ 1061 1466 l 2,9,10
+ 1223 1466 1223 1466 1223 1315 c 0,11,12
+ 1223 1243 1223 1243 1196 1200 c 128,-1,13
+ 1169 1157 1169 1157 1087 1061 c 2,14,-1
+ 383 223 l 1,15,-1
+ 1159 223 l 2,16,17
+ 1228 223 1228 223 1262 194.5 c 128,-1,18
+ 1296 166 1296 166 1296 115 c 0,19,20
+ 1296 62 1296 62 1262 31 c 128,-1,21
+ 1228 0 1228 0 1159 0 c 2,22,-1
+ 207 0 l 2,23,24
+ 110 0 110 0 61 43.5 c 128,-1,25
+ 12 87 12 87 12 160 c 0,26,27
+ 12 185 12 185 20 206 c 128,-1,28
+ 28 227 28 227 41.5 245.5 c 128,-1,29
+ 55 264 55 264 79 292.5 c 128,-1,30
+ 103 321 103 321 121 342 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: bracketleft
+Encoding: 91 91 62
+Width: 725
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 16
+ 0
+ 48
+ 17
+ 12
+ 12
+ 48
+ 2
+ 8
+ 10
+ 2
+ 7
+ 141
+ 2
+ 13
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+573 1278 m 2,0,-1
+ 406 1278 l 1,1,-1
+ 406 -172 l 1,2,-1
+ 573 -172 l 2,3,4
+ 702 -172 702 -172 702 -279 c 0,5,6
+ 702 -385 702 -385 573 -385 c 2,7,-1
+ 324 -385 l 2,8,9
+ 263 -385 263 -385 223.5 -365 c 128,-1,10
+ 184 -345 184 -345 165.5 -304.5 c 128,-1,11
+ 147 -264 147 -264 147 -203 c 2,12,-1
+ 147 1309 l 2,13,14
+ 147 1403 147 1403 189 1447 c 128,-1,15
+ 231 1491 231 1491 324 1491 c 2,16,-1
+ 573 1491 l 2,17,18
+ 638 1491 638 1491 670 1462 c 128,-1,19
+ 702 1433 702 1433 702 1384 c 0,20,21
+ 702 1278 702 1278 573 1278 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: backslash
+Encoding: 92 92 63
+Width: 575
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 4
+ 15
+ 12
+ 5
+ 9
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+248 1331 m 2,0,-1
+ 528 178 l 2,1,2
+ 549 96 549 96 549 63 c 0,3,4
+ 549 -25 549 -25 446 -25 c 0,5,6
+ 404 -25 404 -25 382.5 -6.5 c 128,-1,7
+ 361 12 361 12 352 38.5 c 128,-1,8
+ 343 65 343 65 326 135 c 2,9,-1
+ 47 1288 l 2,10,11
+ 27 1374 27 1374 27 1401 c 0,12,13
+ 27 1443 27 1443 53.5 1467 c 128,-1,14
+ 80 1491 80 1491 129 1491 c 0,15,16
+ 188 1491 188 1491 207 1457 c 128,-1,17
+ 226 1423 226 1423 248 1331 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: bracketright
+Encoding: 93 93 64
+Width: 725
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 16
+ 1
+ 48
+ 9
+ 12
+ 12
+ 48
+ 23
+ 17
+ 10
+ 2
+ 7
+ 141
+ 13
+ 1
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+319 -172 m 1,0,-1
+ 319 1278 l 1,1,-1
+ 154 1278 l 2,2,3
+ 90 1278 90 1278 56.5 1307.5 c 128,-1,4
+ 23 1337 23 1337 23 1384 c 0,5,6
+ 23 1432 23 1432 56.5 1461.5 c 128,-1,7
+ 90 1491 90 1491 154 1491 c 2,8,-1
+ 401 1491 l 2,9,10
+ 493 1491 493 1491 535.5 1447 c 128,-1,11
+ 578 1403 578 1403 578 1309 c 2,12,-1
+ 578 -203 l 2,13,14
+ 578 -296 578 -296 536 -340.5 c 128,-1,15
+ 494 -385 494 -385 401 -385 c 2,16,-1
+ 154 -385 l 2,17,18
+ 90 -385 90 -385 56.5 -355.5 c 128,-1,19
+ 23 -326 23 -326 23 -279 c 0,20,21
+ 23 -231 23 -231 56.5 -201.5 c 128,-1,22
+ 90 -172 90 -172 154 -172 c 2,23,-1
+ 319 -172 l 1,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: asciicircum
+Encoding: 94 94 65
+Width: 1194
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 13
+ 0
+ 0
+ 0
+ 5
+ 1
+ 6
+ 1
+ 1
+ 21
+ 3
+ 12
+ 9
+ 7
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+401 692 m 1,0,-1
+ 115 692 l 1,1,-1
+ 492 1491 l 1,2,-1
+ 713 1491 l 1,3,-1
+ 1079 692 l 1,4,-1
+ 797 692 l 1,5,-1
+ 598 1182 l 1,6,-1
+ 401 692 l 1,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: underscore
+Encoding: 95 95 66
+Width: 1024
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 5
+ 81
+ 2
+ 0
+ 10
+ 7
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+-12 -256 m 1,0,-1
+ -12 -154 l 1,1,-1
+ 1036 -154 l 1,2,-1
+ 1036 -256 l 1,3,-1
+ -12 -256 l 1,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: grave
+Encoding: 96 96 67
+Width: 682
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 6
+ 5
+ 34
+ 13
+ 12
+ 12
+ 7
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+424 1364 m 2,0,-1
+ 469 1280 l 2,1,2
+ 496 1237 496 1237 496 1221 c 0,3,4
+ 496 1196 496 1196 453 1196 c 0,5,6
+ 387 1196 387 1196 330 1225 c 0,7,8
+ 302 1239 302 1239 192 1344 c 128,-1,9
+ 82 1449 82 1449 82 1462 c 0,10,11
+ 82 1477 82 1477 133 1477 c 2,12,-1
+ 268 1477 l 2,13,14
+ 327 1477 327 1477 357 1456 c 128,-1,15
+ 387 1435 387 1435 424 1364 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: a
+Encoding: 97 97 68
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 53
+ 36
+ 1
+ 45
+ 53
+ 1
+ 17
+ 54
+ 29
+ 10
+ 12
+ 22
+ 10
+ 2
+ 63
+ 14
+ 45
+ 13
+ 0
+ 0
+ 0
+ 3
+ 1
+ 0
+ 1
+ 53
+ 59
+ 42
+ 9
+ 8
+ 3
+ 7
+ 39
+ 33
+ 2
+ 0
+ 0
+ 45
+ 1
+ 0
+ 1
+ 138
+ 36
+ 14
+ 0
+ 25
+ 10
+ 2
+ 136
+ 50
+ 7
+ 13
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+831 129 m 1,0,1
+ 732 52 732 52 639.5 13.5 c 128,-1,2
+ 547 -25 547 -25 432 -25 c 0,3,4
+ 327 -25 327 -25 247.5 16.5 c 128,-1,5
+ 168 58 168 58 125 129 c 128,-1,6
+ 82 200 82 200 82 283 c 0,7,8
+ 82 395 82 395 153 474 c 128,-1,9
+ 224 553 224 553 348 580 c 0,10,11
+ 374 586 374 586 477 607 c 128,-1,12
+ 580 628 580 628 653.5 645.5 c 128,-1,13
+ 727 663 727 663 813 688 c 1,14,15
+ 808 796 808 796 769.5 846.5 c 128,-1,16
+ 731 897 731 897 610 897 c 0,17,18
+ 506 897 506 897 453.5 868 c 128,-1,19
+ 401 839 401 839 363.5 781 c 128,-1,20
+ 326 723 326 723 310.5 704.5 c 128,-1,21
+ 295 686 295 686 244 686 c 0,22,23
+ 198 686 198 686 164.5 715.5 c 128,-1,24
+ 131 745 131 745 131 791 c 0,25,26
+ 131 863 131 863 182 931 c 128,-1,27
+ 233 999 233 999 341 1043 c 128,-1,28
+ 449 1087 449 1087 610 1087 c 0,29,30
+ 790 1087 790 1087 893 1044.5 c 128,-1,31
+ 996 1002 996 1002 1038.5 910 c 128,-1,32
+ 1081 818 1081 818 1081 666 c 0,33,34
+ 1081 570 1081 570 1080.5 503 c 128,-1,35
+ 1080 436 1080 436 1079 354 c 0,36,37
+ 1079 277 1079 277 1104.5 193.5 c 128,-1,38
+ 1130 110 1130 110 1130 86 c 0,39,40
+ 1130 44 1130 44 1090.5 9.5 c 128,-1,41
+ 1051 -25 1051 -25 1001 -25 c 0,42,43
+ 959 -25 959 -25 918 14.5 c 128,-1,44
+ 877 54 877 54 831 129 c 1,0,1
+813 524 m 1,45,46
+ 753 502 753 502 638.5 477.5 c 128,-1,47
+ 524 453 524 453 480 441.5 c 128,-1,48
+ 436 430 436 430 396 396.5 c 128,-1,49
+ 356 363 356 363 356 303 c 0,50,51
+ 356 241 356 241 403 197.5 c 128,-1,52
+ 450 154 450 154 526 154 c 0,53,54
+ 607 154 607 154 675.5 189.5 c 128,-1,55
+ 744 225 744 225 776 281 c 0,56,57
+ 813 343 813 343 813 485 c 2,58,-1
+ 813 524 l 1,45,46
+EndSplineSet
+Validated: 1
+Kerns2: 92 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 90 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 89 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 87 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 83 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 74 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 69 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: b
+Encoding: 98 98 69
+Width: 1280
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 41
+ 0
+ 0
+ 0
+ 0
+ 1
+ 1
+ 42
+ 52
+ 4
+ 10
+ 9
+ 0
+ 0
+ 0
+ 13
+ 1
+ 18
+ 1
+ 35
+ 49
+ 22
+ 9
+ 8
+ 2
+ 7
+ 29
+ 12
+ 136
+ 8
+ 38
+ 10
+ 32
+ 1
+ 0
+ 1
+ 141
+ 18
+ 26
+ 15
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+393 1335 m 2,0,-1
+ 393 918 l 1,1,2
+ 470 998 470 998 550 1040.5 c 128,-1,3
+ 630 1083 630 1083 748 1083 c 0,4,5
+ 884 1083 884 1083 986.5 1018.5 c 128,-1,6
+ 1089 954 1089 954 1145.5 831.5 c 128,-1,7
+ 1202 709 1202 709 1202 541 c 0,8,9
+ 1202 417 1202 417 1170.5 313.5 c 128,-1,10
+ 1139 210 1139 210 1079 134 c 128,-1,11
+ 1019 58 1019 58 933.5 16.5 c 128,-1,12
+ 848 -25 848 -25 745 -25 c 0,13,14
+ 682 -25 682 -25 626.5 -10 c 128,-1,15
+ 571 5 571 5 532 29.5 c 128,-1,16
+ 493 54 493 54 465.5 80 c 128,-1,17
+ 438 106 438 106 393 158 c 1,18,-1
+ 393 131 l 2,19,20
+ 393 54 393 54 356 14.5 c 128,-1,21
+ 319 -25 319 -25 262 -25 c 0,22,23
+ 204 -25 204 -25 169.5 14.5 c 128,-1,24
+ 135 54 135 54 135 131 c 2,25,-1
+ 135 1323 l 2,26,27
+ 135 1406 135 1406 168.5 1448.5 c 128,-1,28
+ 202 1491 202 1491 262 1491 c 0,29,30
+ 325 1491 325 1491 359 1450.5 c 128,-1,31
+ 393 1410 393 1410 393 1335 c 2,0,-1
+406 524 m 0,32,33
+ 406 361 406 361 480.5 273.5 c 128,-1,34
+ 555 186 555 186 676 186 c 0,35,36
+ 779 186 779 186 853.5 275.5 c 128,-1,37
+ 928 365 928 365 928 532 c 0,38,39
+ 928 640 928 640 897 718 c 128,-1,40
+ 866 796 866 796 809 838.5 c 128,-1,41
+ 752 881 752 881 676 881 c 0,42,43
+ 598 881 598 881 537 838.5 c 128,-1,44
+ 476 796 476 796 441 715.5 c 128,-1,45
+ 406 635 406 635 406 524 c 0,32,33
+EndSplineSet
+Validated: 1
+Kerns2: 129 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 92 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 90 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 89 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 88 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 79 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 69 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: c
+Encoding: 99 99 70
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 26
+ 40
+ 37
+ 23
+ 20
+ 0
+ 5
+ 26
+ 34
+ 1
+ 26
+ 49
+ 12
+ 10
+ 12
+ 34
+ 52
+ 5
+ 9
+ 11
+ 2
+ 7
+ 136
+ 29
+ 8
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1120 313 m 0,0,1
+ 1120 262 1120 262 1089.5 204 c 128,-1,2
+ 1059 146 1059 146 996.5 93.5 c 128,-1,3
+ 934 41 934 41 839 9 c 128,-1,4
+ 744 -23 744 -23 625 -23 c 0,5,6
+ 372 -23 372 -23 230 124.5 c 128,-1,7
+ 88 272 88 272 88 520 c 0,8,9
+ 88 688 88 688 153 817 c 128,-1,10
+ 218 946 218 946 341 1016.5 c 128,-1,11
+ 464 1087 464 1087 635 1087 c 0,12,13
+ 741 1087 741 1087 829.5 1056 c 128,-1,14
+ 918 1025 918 1025 979.5 976 c 128,-1,15
+ 1041 927 1041 927 1073.5 871.5 c 128,-1,16
+ 1106 816 1106 816 1106 768 c 0,17,18
+ 1106 719 1106 719 1069.5 685 c 128,-1,19
+ 1033 651 1033 651 981 651 c 0,20,21
+ 947 651 947 651 924.5 668.5 c 128,-1,22
+ 902 686 902 686 874 725 c 0,23,24
+ 824 801 824 801 769.5 839 c 128,-1,25
+ 715 877 715 877 631 877 c 0,26,27
+ 510 877 510 877 436 782.5 c 128,-1,28
+ 362 688 362 688 362 524 c 0,29,30
+ 362 447 362 447 381 382.5 c 128,-1,31
+ 400 318 400 318 436 272.5 c 128,-1,32
+ 472 227 472 227 523 203.5 c 128,-1,33
+ 574 180 574 180 635 180 c 0,34,35
+ 717 180 717 180 775.5 218 c 128,-1,36
+ 834 256 834 256 879 334 c 0,37,38
+ 904 380 904 380 933 406 c 128,-1,39
+ 962 432 962 432 1004 432 c 0,40,41
+ 1054 432 1054 432 1087 394 c 128,-1,42
+ 1120 356 1120 356 1120 313 c 0,0,1
+EndSplineSet
+Validated: 1
+Kerns2: 92 -53 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 79 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 78 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 75 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: d
+Encoding: 100 100 71
+Width: 1280
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 42
+ 0
+ 0
+ 0
+ 0
+ 16
+ 1
+ 42
+ 52
+ 13
+ 10
+ 9
+ 0
+ 0
+ 0
+ 5
+ 1
+ 1
+ 0
+ 2
+ 34
+ 49
+ 27
+ 9
+ 8
+ 2
+ 7
+ 20
+ 12
+ 38
+ 1
+ 0
+ 1
+ 141
+ 24
+ 16
+ 14
+ 136
+ 30
+ 10
+ 10
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+889 131 m 2,0,-1
+ 889 158 l 1,1,2
+ 834 95 834 95 780.5 55.5 c 128,-1,3
+ 727 16 727 16 664.5 -4.5 c 128,-1,4
+ 602 -25 602 -25 528 -25 c 0,5,6
+ 430 -25 430 -25 346.5 16.5 c 128,-1,7
+ 263 58 263 58 202 135 c 128,-1,8
+ 141 212 141 212 109.5 316 c 128,-1,9
+ 78 420 78 420 78 541 c 0,10,11
+ 78 797 78 797 203 940 c 128,-1,12
+ 328 1083 328 1083 532 1083 c 0,13,14
+ 650 1083 650 1083 731 1042.5 c 128,-1,15
+ 812 1002 812 1002 889 918 c 1,16,-1
+ 889 1321 l 2,17,18
+ 889 1405 889 1405 922.5 1448 c 128,-1,19
+ 956 1491 956 1491 1018 1491 c 256,20,21
+ 1080 1491 1080 1491 1113.5 1451.5 c 128,-1,22
+ 1147 1412 1147 1412 1147 1335 c 2,23,-1
+ 1147 131 l 2,24,25
+ 1147 53 1147 53 1111 14 c 128,-1,26
+ 1075 -25 1075 -25 1018 -25 c 0,27,28
+ 962 -25 962 -25 925.5 15.5 c 128,-1,29
+ 889 56 889 56 889 131 c 2,0,-1
+352 532 m 0,30,31
+ 352 421 352 421 386.5 343 c 128,-1,32
+ 421 265 421 265 481 225.5 c 128,-1,33
+ 541 186 541 186 612 186 c 0,34,35
+ 684 186 684 186 743.5 223.5 c 128,-1,36
+ 803 261 803 261 838.5 338.5 c 128,-1,37
+ 874 416 874 416 874 532 c 0,38,39
+ 874 641 874 641 838.5 719.5 c 128,-1,40
+ 803 798 803 798 742.5 839.5 c 128,-1,41
+ 682 881 682 881 610 881 c 0,42,43
+ 535 881 535 881 476 838.5 c 128,-1,44
+ 417 796 417 796 384.5 716.5 c 128,-1,45
+ 352 637 352 637 352 532 c 0,30,31
+EndSplineSet
+Validated: 1
+Kerns2: 183 25 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 89 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: e
+Encoding: 101 101 72
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 30
+ 12
+ 10
+ 2
+ 0
+ 5
+ 1
+ 39
+ 54
+ 28
+ 10
+ 12
+ 65
+ 36
+ 0
+ 10
+ 5
+ 58
+ 20
+ 9
+ 11
+ 3
+ 7
+ 0
+ 35
+ 1
+ 135
+ 1
+ 23
+ 15
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+903 463 m 2,0,-1
+ 369 463 l 1,1,2
+ 370 370 370 370 406.5 299 c 128,-1,3
+ 443 228 443 228 503.5 192 c 128,-1,4
+ 564 156 564 156 637 156 c 0,5,6
+ 686 156 686 156 726.5 167.5 c 128,-1,7
+ 767 179 767 179 805 203.5 c 128,-1,8
+ 843 228 843 228 875 256 c 128,-1,9
+ 907 284 907 284 958 332 c 0,10,11
+ 979 350 979 350 1018 350 c 0,12,13
+ 1060 350 1060 350 1086 327 c 128,-1,14
+ 1112 304 1112 304 1112 262 c 0,15,16
+ 1112 225 1112 225 1083 175.5 c 128,-1,17
+ 1054 126 1054 126 995.5 80.5 c 128,-1,18
+ 937 35 937 35 848.5 5 c 128,-1,19
+ 760 -25 760 -25 645 -25 c 0,20,21
+ 382 -25 382 -25 236 125 c 128,-1,22
+ 90 275 90 275 90 532 c 0,23,24
+ 90 653 90 653 126 756.5 c 128,-1,25
+ 162 860 162 860 231 934 c 128,-1,26
+ 300 1008 300 1008 401 1047.5 c 128,-1,27
+ 502 1087 502 1087 625 1087 c 0,28,29
+ 785 1087 785 1087 899.5 1019.5 c 128,-1,30
+ 1014 952 1014 952 1071 845 c 128,-1,31
+ 1128 738 1128 738 1128 627 c 0,32,33
+ 1128 524 1128 524 1069 493.5 c 128,-1,34
+ 1010 463 1010 463 903 463 c 2,0,-1
+369 618 m 1,35,-1
+ 864 618 l 1,36,37
+ 854 758 854 758 788.5 827.5 c 128,-1,38
+ 723 897 723 897 616 897 c 0,39,40
+ 514 897 514 897 448.5 826.5 c 128,-1,41
+ 383 756 383 756 369 618 c 1,35,-1
+EndSplineSet
+Validated: 1
+Kerns2: 93 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 92 -53 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 91 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 90 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 89 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 83 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 74 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 69 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: f
+Encoding: 102 102 73
+Width: 682
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 40
+ 0
+ 0
+ 11
+ 1
+ 0
+ 0
+ 14
+ 53
+ 6
+ 12
+ 9
+ 0
+ 0
+ 1
+ 0
+ 33
+ 1
+ 0
+ 24
+ 53
+ 18
+ 10
+ 9
+ 2
+ 7
+ 29
+ 9
+ 0
+ 25
+ 1
+ 37
+ 1
+ 32
+ 1
+ 0
+ 137
+ 18
+ 1
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+119 1061 m 2,0,-1
+ 184 1061 l 1,1,-1
+ 184 1143 l 2,2,3
+ 184 1271 184 1271 216.5 1346.5 c 128,-1,4
+ 249 1422 249 1422 326.5 1456.5 c 128,-1,5
+ 404 1491 404 1491 539 1491 c 0,6,7
+ 778 1491 778 1491 778 1374 c 0,8,9
+ 778 1336 778 1336 753 1309 c 128,-1,10
+ 728 1282 728 1282 694 1282 c 0,11,12
+ 678 1282 678 1282 639 1288 c 128,-1,13
+ 600 1294 600 1294 573 1294 c 0,14,15
+ 499 1294 499 1294 478 1250.5 c 128,-1,16
+ 457 1207 457 1207 457 1126 c 2,17,-1
+ 457 1061 l 1,18,-1
+ 524 1061 l 2,19,20
+ 680 1061 680 1061 680 967 c 0,21,22
+ 680 900 680 900 638.5 882 c 128,-1,23
+ 597 864 597 864 524 864 c 2,24,-1
+ 457 864 l 1,25,-1
+ 457 141 l 2,26,27
+ 457 60 457 60 418.5 17.5 c 128,-1,28
+ 380 -25 380 -25 319 -25 c 0,29,30
+ 261 -25 261 -25 222.5 17.5 c 128,-1,31
+ 184 60 184 60 184 141 c 2,32,-1
+ 184 864 l 1,33,-1
+ 109 864 l 2,34,35
+ 48 864 48 864 15 891.5 c 128,-1,36
+ -18 919 -18 919 -18 963 c 0,37,38
+ -18 1061 -18 1061 119 1061 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 183 76 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 181 102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 124 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 119 205 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 115 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 110 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 108 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 82 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 79 25 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 76 25 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 73 76 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 72 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 68 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 34 102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 12 76 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 4 76 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 3 229 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: g
+Encoding: 103 103 74
+Width: 1280
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 58
+ 15
+ 1
+ 28
+ 20
+ 1
+ 44
+ 1
+ 0
+ 0
+ 0
+ 40
+ 0
+ 2
+ 57
+ 52
+ 37
+ 10
+ 9
+ 0
+ 0
+ 0
+ 0
+ 25
+ 1
+ 50
+ 52
+ 28
+ 9
+ 8
+ 20
+ 54
+ 6
+ 7
+ 11
+ 3
+ 7
+ 13
+ 9
+ 0
+ 0
+ 25
+ 1
+ 0
+ 40
+ 1
+ 138
+ 1
+ 54
+ 0
+ 15
+ 10
+ 2
+ 136
+ 47
+ 32
+ 13
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1145 885 m 2,0,-1
+ 1145 92 l 2,1,2
+ 1145 -44 1145 -44 1116 -142 c 128,-1,3
+ 1087 -240 1087 -240 1023 -304 c 128,-1,4
+ 959 -368 959 -368 855.5 -399 c 128,-1,5
+ 752 -430 752 -430 598 -430 c 0,6,7
+ 457 -430 457 -430 346 -390.5 c 128,-1,8
+ 235 -351 235 -351 175 -288.5 c 128,-1,9
+ 115 -226 115 -226 115 -160 c 0,10,11
+ 115 -110 115 -110 149 -78.5 c 128,-1,12
+ 183 -47 183 -47 231 -47 c 0,13,14
+ 291 -47 291 -47 336 -100 c 0,15,16
+ 358 -127 358 -127 381.5 -154.5 c 128,-1,17
+ 405 -182 405 -182 433.5 -201.5 c 128,-1,18
+ 462 -221 462 -221 502 -230.5 c 128,-1,19
+ 542 -240 542 -240 594 -240 c 0,20,21
+ 700 -240 700 -240 758.5 -210.5 c 128,-1,22
+ 817 -181 817 -181 840.5 -128 c 128,-1,23
+ 864 -75 864 -75 868 -14.5 c 128,-1,24
+ 872 46 872 46 874 180 c 1,25,26
+ 811 92 811 92 728.5 46 c 128,-1,27
+ 646 0 646 0 532 0 c 0,28,29
+ 395 0 395 0 292.5 70 c 128,-1,30
+ 190 140 190 140 135 266 c 128,-1,31
+ 80 392 80 392 80 557 c 0,32,33
+ 80 680 80 680 113.5 779 c 128,-1,34
+ 147 878 147 878 209 946 c 128,-1,35
+ 271 1014 271 1014 352 1048.5 c 128,-1,36
+ 433 1083 433 1083 530 1083 c 0,37,38
+ 646 1083 646 1083 731 1038.5 c 128,-1,39
+ 816 994 816 994 889 899 c 1,40,-1
+ 889 936 l 2,41,42
+ 889 1007 889 1007 924 1046 c 128,-1,43
+ 959 1085 959 1085 1014 1085 c 0,44,45
+ 1093 1085 1093 1085 1119 1033.5 c 128,-1,46
+ 1145 982 1145 982 1145 885 c 2,0,-1
+354 539 m 0,47,48
+ 354 373 354 373 426.5 288 c 128,-1,49
+ 499 203 499 203 614 203 c 0,50,51
+ 682 203 682 203 742.5 239.5 c 128,-1,52
+ 803 276 803 276 841 349.5 c 128,-1,53
+ 879 423 879 423 879 528 c 0,54,55
+ 879 695 879 695 805.5 788 c 128,-1,56
+ 732 881 732 881 612 881 c 0,57,58
+ 495 881 495 881 424.5 792 c 128,-1,59
+ 354 703 354 703 354 539 c 0,47,48
+EndSplineSet
+Validated: 1
+Kerns2: 124 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 110 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 108 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 85 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 83 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 82 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 79 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 74 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 72 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 68 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: h
+Encoding: 104 104 75
+Width: 1237
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 34
+ 0
+ 0
+ 0
+ 0
+ 8
+ 1
+ 2
+ 21
+ 49
+ 5
+ 10
+ 9
+ 7
+ 36
+ 12
+ 30
+ 9
+ 15
+ 9
+ 8
+ 1
+ 137
+ 12
+ 17
+ 13
+ 0
+ 0
+ 1
+ 137
+ 26
+ 33
+ 15
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+408 1325 m 2,0,-1
+ 408 920 l 1,1,2
+ 460 980 460 980 509.5 1015 c 128,-1,3
+ 559 1050 559 1050 619 1067.5 c 128,-1,4
+ 679 1085 679 1085 748 1085 c 0,5,6
+ 852 1085 852 1085 932.5 1041 c 128,-1,7
+ 1013 997 1013 997 1059 913 c 0,8,9
+ 1088 864 1088 864 1098 803.5 c 128,-1,10
+ 1108 743 1108 743 1108 664 c 2,11,-1
+ 1108 141 l 2,12,13
+ 1108 59 1108 59 1070.5 17 c 128,-1,14
+ 1033 -25 1033 -25 971 -25 c 0,15,16
+ 836 -25 836 -25 836 141 c 2,17,-1
+ 836 602 l 2,18,19
+ 836 733 836 733 797 803.5 c 128,-1,20
+ 758 874 758 874 649 874 c 0,21,22
+ 576 874 576 874 517.5 832.5 c 128,-1,23
+ 459 791 459 791 430 719 c 0,24,25
+ 408 658 408 658 408 502 c 2,26,-1
+ 408 141 l 2,27,28
+ 408 60 408 60 371.5 17.5 c 128,-1,29
+ 335 -25 335 -25 270 -25 c 0,30,31
+ 135 -25 135 -25 135 141 c 2,32,-1
+ 135 1325 l 2,33,34
+ 135 1408 135 1408 170.5 1449.5 c 128,-1,35
+ 206 1491 206 1491 270 1491 c 0,36,37
+ 335 1491 335 1491 371.5 1449 c 128,-1,38
+ 408 1407 408 1407 408 1325 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: i
+Encoding: 105 105 76
+Width: 555
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 22
+ 14
+ 35
+ 20
+ 12
+ 12
+ 7
+ 11
+ 10
+ 4
+ 9
+ 0
+ 23
+ 1
+ 0
+ 17
+ 1
+ 0
+ 137
+ 1
+ 8
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+414 930 m 2,0,-1
+ 414 141 l 2,1,2
+ 414 59 414 59 375 17 c 128,-1,3
+ 336 -25 336 -25 276 -25 c 256,4,5
+ 216 -25 216 -25 178.5 18 c 128,-1,6
+ 141 61 141 61 141 141 c 2,7,-1
+ 141 922 l 2,8,9
+ 141 1003 141 1003 178.5 1044 c 128,-1,10
+ 216 1085 216 1085 276 1085 c 256,11,12
+ 336 1085 336 1085 375 1044 c 128,-1,13
+ 414 1003 414 1003 414 930 c 2,0,-1
+279 1212 m 0,14,15
+ 222 1212 222 1212 181.5 1247 c 128,-1,16
+ 141 1282 141 1282 141 1346 c 0,17,18
+ 141 1404 141 1404 182.5 1441.5 c 128,-1,19
+ 224 1479 224 1479 279 1479 c 0,20,21
+ 332 1479 332 1479 373 1445 c 128,-1,22
+ 414 1411 414 1411 414 1346 c 0,23,24
+ 414 1283 414 1283 374 1247.5 c 128,-1,25
+ 334 1212 334 1212 279 1212 c 0,14,15
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: j
+Encoding: 106 106 77
+Width: 555
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 39
+ 0
+ 1
+ 26
+ 16
+ 1
+ 26
+ 35
+ 32
+ 12
+ 12
+ 12
+ 1
+ 0
+ 0
+ 0
+ 4
+ 1
+ 16
+ 41
+ 6
+ 7
+ 8
+ 2
+ 7
+ 23
+ 10
+ 0
+ 35
+ 1
+ 0
+ 29
+ 1
+ 4
+ 1
+ 137
+ 1
+ 19
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+416 922 m 2,0,-1
+ 416 -4 l 2,1,2
+ 416 -103 416 -103 409.5 -165.5 c 128,-1,3
+ 403 -228 403 -228 391 -256 c 0,4,5
+ 323 -430 323 -430 102 -430 c 0,6,7
+ -22 -430 -22 -430 -86 -396 c 128,-1,8
+ -150 -362 -150 -362 -150 -297 c 0,9,10
+ -150 -249 -150 -249 -121 -218.5 c 128,-1,11
+ -92 -188 -92 -188 -45 -188 c 0,12,13
+ -39 -188 -39 -188 -25.5 -189.5 c 128,-1,14
+ -12 -191 -12 -191 14.5 -193 c 128,-1,15
+ 41 -195 41 -195 51 -195 c 0,16,17
+ 106 -195 106 -195 124.5 -152 c 128,-1,18
+ 143 -109 143 -109 143 2 c 2,19,-1
+ 143 922 l 2,20,21
+ 143 1003 143 1003 181 1044 c 128,-1,22
+ 219 1085 219 1085 281 1085 c 0,23,24
+ 341 1085 341 1085 378.5 1044.5 c 128,-1,25
+ 416 1004 416 1004 416 922 c 2,0,-1
+281 1212 m 0,26,27
+ 224 1212 224 1212 183.5 1247 c 128,-1,28
+ 143 1282 143 1282 143 1346 c 0,29,30
+ 143 1404 143 1404 184.5 1441.5 c 128,-1,31
+ 226 1479 226 1479 281 1479 c 0,32,33
+ 334 1479 334 1479 375 1445 c 128,-1,34
+ 416 1411 416 1411 416 1346 c 0,35,36
+ 416 1283 416 1283 376 1247.5 c 128,-1,37
+ 336 1212 336 1212 281 1212 c 0,26,27
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: k
+Encoding: 107 107 78
+Width: 1174
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 18
+ 34
+ 9
+ 21
+ 10
+ 17
+ 13
+ 12
+ 6
+ 9
+ 1
+ 0
+ 16
+ 1
+ 137
+ 2
+ 10
+ 15
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+MDAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+821 100 m 2,0,-1
+ 580 496 l 1,1,-1
+ 432 356 l 1,2,-1
+ 432 139 l 2,3,4
+ 432 60 432 60 390.5 17.5 c 128,-1,5
+ 349 -25 349 -25 295 -25 c 0,6,7
+ 232 -25 232 -25 196 17 c 128,-1,8
+ 160 59 160 59 160 141 c 2,9,-1
+ 160 1305 l 2,10,11
+ 160 1396 160 1396 195 1443.5 c 128,-1,12
+ 230 1491 230 1491 295 1491 c 0,13,14
+ 358 1491 358 1491 395 1448 c 128,-1,15
+ 432 1405 432 1405 432 1321 c 2,16,-1
+ 432 659 l 1,17,-1
+ 739 981 l 2,18,19
+ 796 1041 796 1041 826 1063 c 128,-1,20
+ 856 1085 856 1085 899 1085 c 0,21,22
+ 950 1085 950 1085 984 1052.5 c 128,-1,23
+ 1018 1020 1018 1020 1018 971 c 0,24,25
+ 1018 911 1018 911 907 811 c 2,26,-1
+ 762 678 l 1,27,-1
+ 1042 238 l 2,28,29
+ 1073 189 1073 189 1086.5 163.5 c 128,-1,30
+ 1100 138 1100 138 1100 115 c 0,31,32
+ 1100 50 1100 50 1064.5 12.5 c 128,-1,33
+ 1029 -25 1029 -25 971 -25 c 0,34,35
+ 921 -25 921 -25 894 2 c 128,-1,36
+ 867 29 867 29 821 100 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 129 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 124 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 108 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 92 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 88 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 86 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 84 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 83 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 82 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 79 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 76 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 74 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 72 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 71 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 70 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 68 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: l
+Encoding: 108 108 79
+Width: 555
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 9
+ 11
+ 9
+ 4
+ 12
+ 137
+ 8
+ 1
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+141 141 m 2,0,-1
+ 141 1325 l 2,1,2
+ 141 1407 141 1407 177.5 1449 c 128,-1,3
+ 214 1491 214 1491 276 1491 c 256,4,5
+ 338 1491 338 1491 376 1449.5 c 128,-1,6
+ 414 1408 414 1408 414 1325 c 2,7,-1
+ 414 141 l 2,8,9
+ 414 58 414 58 375.5 16.5 c 128,-1,10
+ 337 -25 337 -25 276 -25 c 0,11,12
+ 216 -25 216 -25 178.5 18 c 128,-1,13
+ 141 61 141 61 141 141 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 90 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: m
+Encoding: 109 109 80
+Width: 1812
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 43
+ 26
+ 1
+ 39
+ 1
+ 0
+ 56
+ 1
+ 42
+ 36
+ 30
+ 3
+ 12
+ 49
+ 33
+ 10
+ 9
+ 7
+ 48
+ 9
+ 19
+ 9
+ 4
+ 9
+ 42
+ 1
+ 133
+ 45
+ 51
+ 13
+ 36
+ 1
+ 134
+ 0
+ 7
+ 13
+ 30
+ 1
+ 134
+ 15
+ 23
+ 13
+ 3
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1049 510 m 2,0,-1
+ 1049 147 l 2,1,2
+ 1049 61 1049 61 1010 18 c 128,-1,3
+ 971 -25 971 -25 907 -25 c 0,4,5
+ 845 -25 845 -25 806.5 18 c 128,-1,6
+ 768 61 768 61 768 147 c 2,7,-1
+ 768 582 l 2,8,9
+ 768 685 768 685 761 742 c 128,-1,10
+ 754 799 754 799 723 835.5 c 128,-1,11
+ 692 872 692 872 625 872 c 0,12,13
+ 491 872 491 872 448.5 780 c 128,-1,14
+ 406 688 406 688 406 516 c 2,15,-1
+ 406 147 l 2,16,17
+ 406 62 406 62 367.5 18.5 c 128,-1,18
+ 329 -25 329 -25 266 -25 c 0,19,20
+ 204 -25 204 -25 164.5 18.5 c 128,-1,21
+ 125 62 125 62 125 147 c 2,22,-1
+ 125 928 l 2,23,24
+ 125 1005 125 1005 160.5 1045 c 128,-1,25
+ 196 1085 196 1085 254 1085 c 0,26,27
+ 310 1085 310 1085 347.5 1047.5 c 128,-1,28
+ 385 1010 385 1010 385 944 c 2,29,-1
+ 385 918 l 1,30,31
+ 456 1003 456 1003 537 1043 c 128,-1,32
+ 618 1083 618 1083 717 1083 c 0,33,34
+ 820 1083 820 1083 894 1042 c 128,-1,35
+ 968 1001 968 1001 1016 918 c 1,36,37
+ 1085 1002 1085 1002 1164 1042.5 c 128,-1,38
+ 1243 1083 1243 1083 1339 1083 c 0,39,40
+ 1451 1083 1451 1083 1532 1039 c 128,-1,41
+ 1613 995 1613 995 1653 913 c 0,42,43
+ 1688 839 1688 839 1688 680 c 2,44,-1
+ 1688 147 l 2,45,46
+ 1688 61 1688 61 1649 18 c 128,-1,47
+ 1610 -25 1610 -25 1546 -25 c 0,48,49
+ 1484 -25 1484 -25 1444.5 18.5 c 128,-1,50
+ 1405 62 1405 62 1405 147 c 2,51,-1
+ 1405 606 l 2,52,53
+ 1405 694 1405 694 1397.5 747 c 128,-1,54
+ 1390 800 1390 800 1357 836 c 128,-1,55
+ 1324 872 1324 872 1257 872 c 0,56,57
+ 1203 872 1203 872 1154.5 840 c 128,-1,58
+ 1106 808 1106 808 1079 754 c 0,59,60
+ 1049 685 1049 685 1049 510 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 129 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 88 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: n
+Encoding: 110 110 81
+Width: 1237
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 33
+ 0
+ 37
+ 1
+ 0
+ 0
+ 7
+ 1
+ 0
+ 3
+ 21
+ 49
+ 4
+ 10
+ 9
+ 7
+ 30
+ 9
+ 14
+ 9
+ 7
+ 1
+ 137
+ 11
+ 17
+ 13
+ 0
+ 1
+ 137
+ 26
+ 34
+ 13
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+389 934 m 2,0,-1
+ 389 901 l 1,1,2
+ 461 996 461 996 546.5 1040.5 c 128,-1,3
+ 632 1085 632 1085 743 1085 c 0,4,5
+ 851 1085 851 1085 936 1038 c 128,-1,6
+ 1021 991 1021 991 1063 905 c 0,7,8
+ 1090 855 1090 855 1098 797 c 128,-1,9
+ 1106 739 1106 739 1106 649 c 2,10,-1
+ 1106 141 l 2,11,12
+ 1106 59 1106 59 1068.5 17 c 128,-1,13
+ 1031 -25 1031 -25 971 -25 c 0,14,15
+ 910 -25 910 -25 872 18 c 128,-1,16
+ 834 61 834 61 834 141 c 2,17,-1
+ 834 596 l 2,18,19
+ 834 731 834 731 796.5 802.5 c 128,-1,20
+ 759 874 759 874 647 874 c 0,21,22
+ 574 874 574 874 514 830.5 c 128,-1,23
+ 454 787 454 787 426 711 c 0,24,25
+ 406 650 406 650 406 483 c 2,26,-1
+ 406 141 l 2,27,28
+ 406 58 406 58 367.5 16.5 c 128,-1,29
+ 329 -25 329 -25 268 -25 c 0,30,31
+ 209 -25 209 -25 171 18 c 128,-1,32
+ 133 61 133 61 133 141 c 2,33,-1
+ 133 930 l 2,34,35
+ 133 1008 133 1008 167 1046.5 c 128,-1,36
+ 201 1085 201 1085 260 1085 c 0,37,38
+ 296 1085 296 1085 325 1068 c 128,-1,39
+ 354 1051 354 1051 371.5 1017 c 128,-1,40
+ 389 983 389 983 389 934 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 129 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 89 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 88 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: o
+Encoding: 111 111 82
+Width: 1237
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 27
+ 0
+ 1
+ 23
+ 31
+ 1
+ 23
+ 52
+ 15
+ 10
+ 12
+ 31
+ 52
+ 5
+ 9
+ 11
+ 2
+ 7
+ 136
+ 0
+ 20
+ 10
+ 136
+ 27
+ 10
+ 10
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1163 530 m 0,0,1
+ 1163 408 1163 408 1125 305 c 128,-1,2
+ 1087 202 1087 202 1015 128 c 128,-1,3
+ 943 54 943 54 843 14.5 c 128,-1,4
+ 743 -25 743 -25 618 -25 c 0,5,6
+ 494 -25 494 -25 395 15 c 128,-1,7
+ 296 55 296 55 223.5 129.5 c 128,-1,8
+ 151 204 151 204 113.5 305.5 c 128,-1,9
+ 76 407 76 407 76 530 c 0,10,11
+ 76 654 76 654 114 757 c 128,-1,12
+ 152 860 152 860 223 933 c 128,-1,13
+ 294 1006 294 1006 395 1045.5 c 128,-1,14
+ 496 1085 496 1085 618 1085 c 0,15,16
+ 742 1085 742 1085 843 1045 c 128,-1,17
+ 944 1005 944 1005 1016 931 c 128,-1,18
+ 1088 857 1088 857 1125.5 755 c 128,-1,19
+ 1163 653 1163 653 1163 530 c 0,0,1
+889 530 m 0,20,21
+ 889 697 889 697 815.5 790 c 128,-1,22
+ 742 883 742 883 618 883 c 0,23,24
+ 538 883 538 883 477 841.5 c 128,-1,25
+ 416 800 416 800 383 719 c 128,-1,26
+ 350 638 350 638 350 530 c 0,27,28
+ 350 423 350 423 382.5 343 c 128,-1,29
+ 415 263 415 263 475.5 220.5 c 128,-1,30
+ 536 178 536 178 618 178 c 0,31,32
+ 742 178 742 178 815.5 271.5 c 128,-1,33
+ 889 365 889 365 889 530 c 0,20,21
+EndSplineSet
+Validated: 1
+Kerns2: 92 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 91 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 89 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: p
+Encoding: 112 112 83
+Width: 1280
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 42
+ 26
+ 1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 2
+ 33
+ 52
+ 4
+ 10
+ 9
+ 0
+ 0
+ 0
+ 0
+ 16
+ 1
+ 39
+ 49
+ 13
+ 9
+ 8
+ 2
+ 7
+ 19
+ 7
+ 136
+ 8
+ 29
+ 10
+ 36
+ 1
+ 0
+ 1
+ 141
+ 16
+ 23
+ 15
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+393 932 m 2,0,-1
+ 393 899 l 1,1,2
+ 470 994 470 994 553 1038.5 c 128,-1,3
+ 636 1083 636 1083 741 1083 c 0,4,5
+ 867 1083 867 1083 973 1018 c 128,-1,6
+ 1079 953 1079 953 1140.5 828 c 128,-1,7
+ 1202 703 1202 703 1202 532 c 0,8,9
+ 1202 406 1202 406 1166.5 300.5 c 128,-1,10
+ 1131 195 1131 195 1069 123.5 c 128,-1,11
+ 1007 52 1007 52 922.5 13.5 c 128,-1,12
+ 838 -25 838 -25 741 -25 c 0,13,14
+ 624 -25 624 -25 544.5 22 c 128,-1,15
+ 465 69 465 69 393 160 c 1,16,-1
+ 393 -250 l 2,17,18
+ 393 -430 393 -430 262 -430 c 0,19,20
+ 185 -430 185 -430 160 -383.5 c 128,-1,21
+ 135 -337 135 -337 135 -248 c 2,22,-1
+ 135 930 l 2,23,24
+ 135 1008 135 1008 169 1046.5 c 128,-1,25
+ 203 1085 203 1085 262 1085 c 0,26,27
+ 320 1085 320 1085 356.5 1045.5 c 128,-1,28
+ 393 1006 393 1006 393 932 c 2,0,-1
+928 535 m 0,29,30
+ 928 643 928 643 895 720.5 c 128,-1,31
+ 862 798 862 798 803.5 839.5 c 128,-1,32
+ 745 881 745 881 674 881 c 0,33,34
+ 561 881 561 881 483.5 792 c 128,-1,35
+ 406 703 406 703 406 530 c 0,36,37
+ 406 367 406 367 483 276.5 c 128,-1,38
+ 560 186 560 186 674 186 c 0,39,40
+ 742 186 742 186 800 225.5 c 128,-1,41
+ 858 265 858 265 893 344 c 128,-1,42
+ 928 423 928 423 928 535 c 0,29,30
+EndSplineSet
+Validated: 1
+Kerns2: 93 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 92 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 90 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: q
+Encoding: 113 113 84
+Width: 1280
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 41
+ 19
+ 1
+ 0
+ 0
+ 0
+ 15
+ 1
+ 41
+ 52
+ 12
+ 10
+ 9
+ 0
+ 0
+ 0
+ 0
+ 1
+ 1
+ 32
+ 49
+ 4
+ 9
+ 8
+ 2
+ 7
+ 25
+ 7
+ 36
+ 1
+ 0
+ 1
+ 141
+ 23
+ 15
+ 14
+ 136
+ 28
+ 8
+ 10
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+889 -248 m 2,0,-1
+ 889 137 l 1,1,2
+ 810 58 810 58 724.5 16.5 c 128,-1,3
+ 639 -25 639 -25 535 -25 c 0,4,5
+ 408 -25 408 -25 303.5 42 c 128,-1,6
+ 199 109 199 109 139.5 234.5 c 128,-1,7
+ 80 360 80 360 80 530 c 0,8,9
+ 80 704 80 704 140 828.5 c 128,-1,10
+ 200 953 200 953 306.5 1018 c 128,-1,11
+ 413 1083 413 1083 543 1083 c 0,12,13
+ 653 1083 653 1083 740 1037.5 c 128,-1,14
+ 827 992 827 992 889 899 c 1,15,-1
+ 889 932 l 2,16,17
+ 889 1007 889 1007 925 1046 c 128,-1,18
+ 961 1085 961 1085 1018 1085 c 256,19,20
+ 1075 1085 1075 1085 1111 1046.5 c 128,-1,21
+ 1147 1008 1147 1008 1147 932 c 2,22,-1
+ 1147 -248 l 2,23,24
+ 1147 -430 1147 -430 1018 -430 c 0,25,26
+ 938 -430 938 -430 913.5 -381 c 128,-1,27
+ 889 -332 889 -332 889 -248 c 2,0,-1
+354 532 m 0,28,29
+ 354 422 354 422 389.5 342.5 c 128,-1,30
+ 425 263 425 263 483 224.5 c 128,-1,31
+ 541 186 541 186 608 186 c 0,32,33
+ 681 186 681 186 742 224.5 c 128,-1,34
+ 803 263 803 263 840 342 c 128,-1,35
+ 877 421 877 421 877 537 c 0,36,37
+ 877 619 877 619 855.5 685 c 128,-1,38
+ 834 751 834 751 797 794.5 c 128,-1,39
+ 760 838 760 838 712 859.5 c 128,-1,40
+ 664 881 664 881 610 881 c 0,41,42
+ 500 881 500 881 427 790 c 128,-1,43
+ 354 699 354 699 354 532 c 0,28,29
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: r
+Encoding: 114 114 85
+Width: 897
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 23
+ 0
+ 10
+ 1
+ 22
+ 1
+ 0
+ 13
+ 1
+ 25
+ 41
+ 16
+ 10
+ 9
+ 7
+ 4
+ 9
+ 13
+ 1
+ 137
+ 0
+ 8
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+412 369 m 2,0,-1
+ 412 141 l 2,1,2
+ 412 58 412 58 373 16.5 c 128,-1,3
+ 334 -25 334 -25 274 -25 c 0,4,5
+ 215 -25 215 -25 177 17 c 128,-1,6
+ 139 59 139 59 139 141 c 2,7,-1
+ 139 901 l 2,8,9
+ 139 1085 139 1085 272 1085 c 0,10,11
+ 340 1085 340 1085 370 1042 c 128,-1,12
+ 400 999 400 999 403 915 c 1,13,14
+ 452 999 452 999 503.5 1042 c 128,-1,15
+ 555 1085 555 1085 641 1085 c 256,16,17
+ 727 1085 727 1085 808 1042 c 128,-1,18
+ 889 999 889 999 889 928 c 0,19,20
+ 889 878 889 878 854.5 845.5 c 128,-1,21
+ 820 813 820 813 780 813 c 0,22,23
+ 765 813 765 813 707.5 831.5 c 128,-1,24
+ 650 850 650 850 606 850 c 0,25,26
+ 546 850 546 850 508 818.5 c 128,-1,27
+ 470 787 470 787 449 725 c 128,-1,28
+ 428 663 428 663 420 577.5 c 128,-1,29
+ 412 492 412 492 412 369 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 129 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 124 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 110 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 108 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 89 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 88 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 87 25 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 86 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 85 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 84 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 83 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 82 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 79 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 78 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 77 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 74 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 72 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 71 -53 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 70 -53 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 68 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 30 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 29 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -256 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 16 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -231 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: s
+Encoding: 115 115 86
+Width: 1110
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 54
+ 52
+ 42
+ 23
+ 14
+ 11
+ 0
+ 6
+ 45
+ 17
+ 1
+ 0
+ 0
+ 39
+ 1
+ 0
+ 0
+ 45
+ 61
+ 31
+ 10
+ 9
+ 17
+ 60
+ 4
+ 9
+ 11
+ 2
+ 7
+ 52
+ 42
+ 23
+ 3
+ 20
+ 48
+ 1
+ 36
+ 1
+ 138
+ 0
+ 20
+ 13
+ 0
+ 0
+ 8
+ 1
+ 0
+ 14
+ 1
+ 144
+ 48
+ 27
+ 0
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1020 332 m 0,0,1
+ 1020 219 1020 219 965 138.5 c 128,-1,2
+ 910 58 910 58 802.5 16.5 c 128,-1,3
+ 695 -25 695 -25 541 -25 c 0,4,5
+ 394 -25 394 -25 289 20 c 128,-1,6
+ 184 65 184 65 134 132.5 c 128,-1,7
+ 84 200 84 200 84 268 c 0,8,9
+ 84 313 84 313 116 345 c 128,-1,10
+ 148 377 148 377 197 377 c 0,11,12
+ 240 377 240 377 263 356 c 128,-1,13
+ 286 335 286 335 307 297 c 0,14,15
+ 349 224 349 224 407.5 188 c 128,-1,16
+ 466 152 466 152 567 152 c 0,17,18
+ 649 152 649 152 701.5 188.5 c 128,-1,19
+ 754 225 754 225 754 272 c 0,20,21
+ 754 344 754 344 699.5 377 c 128,-1,22
+ 645 410 645 410 520 440 c 0,23,24
+ 379 475 379 475 290.5 513.5 c 128,-1,25
+ 202 552 202 552 149 615 c 128,-1,26
+ 96 678 96 678 96 770 c 0,27,28
+ 96 852 96 852 145 925 c 128,-1,29
+ 194 998 194 998 289.5 1041.5 c 128,-1,30
+ 385 1085 385 1085 520 1085 c 0,31,32
+ 626 1085 626 1085 710.5 1063 c 128,-1,33
+ 795 1041 795 1041 851.5 1004 c 128,-1,34
+ 908 967 908 967 937.5 922 c 128,-1,35
+ 967 877 967 877 967 834 c 0,36,37
+ 967 787 967 787 935.5 757 c 128,-1,38
+ 904 727 904 727 846 727 c 0,39,40
+ 804 727 804 727 774.5 751 c 128,-1,41
+ 745 775 745 775 707 823 c 0,42,43
+ 676 863 676 863 634 887 c 128,-1,44
+ 592 911 592 911 520 911 c 0,45,46
+ 446 911 446 911 397 879.5 c 128,-1,47
+ 348 848 348 848 348 801 c 0,48,49
+ 348 758 348 758 384 730.5 c 128,-1,50
+ 420 703 420 703 481 685 c 128,-1,51
+ 542 667 542 667 649 641 c 0,52,53
+ 776 610 776 610 856.5 567 c 128,-1,54
+ 937 524 937 524 978.5 465.5 c 128,-1,55
+ 1020 407 1020 407 1020 332 c 0,0,1
+EndSplineSet
+Validated: 1
+Kerns2: 90 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: t
+Encoding: 116 116 87
+Width: 725
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 40
+ 0
+ 0
+ 1
+ 0
+ 41
+ 1
+ 0
+ 21
+ 53
+ 14
+ 10
+ 9
+ 30
+ 1
+ 0
+ 0
+ 0
+ 0
+ 27
+ 49
+ 36
+ 9
+ 8
+ 2
+ 7
+ 8
+ 12
+ 0
+ 23
+ 1
+ 45
+ 1
+ 40
+ 1
+ 0
+ 137
+ 13
+ 1
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+156 1061 m 2,0,-1
+ 186 1061 l 1,1,-1
+ 186 1225 l 2,2,3
+ 186 1291 186 1291 189.5 1328.5 c 128,-1,4
+ 193 1366 193 1366 209 1393 c 0,5,6
+ 225 1421 225 1421 255 1438.5 c 128,-1,7
+ 285 1456 285 1456 322 1456 c 0,8,9
+ 374 1456 374 1456 416 1417 c 0,10,11
+ 444 1391 444 1391 451.5 1353.5 c 128,-1,12
+ 459 1316 459 1316 459 1247 c 2,13,-1
+ 459 1061 l 1,14,-1
+ 559 1061 l 2,15,16
+ 617 1061 617 1061 647.5 1033.5 c 128,-1,17
+ 678 1006 678 1006 678 963 c 0,18,19
+ 678 908 678 908 634.5 886 c 128,-1,20
+ 591 864 591 864 510 864 c 2,21,-1
+ 459 864 l 1,22,-1
+ 459 362 l 2,23,24
+ 459 298 459 298 463.5 263.5 c 128,-1,25
+ 468 229 468 229 487.5 207.5 c 128,-1,26
+ 507 186 507 186 551 186 c 0,27,28
+ 575 186 575 186 616 194.5 c 128,-1,29
+ 657 203 657 203 680 203 c 0,30,31
+ 713 203 713 203 739.5 176.5 c 128,-1,32
+ 766 150 766 150 766 111 c 0,33,34
+ 766 45 766 45 694 10 c 128,-1,35
+ 622 -25 622 -25 487 -25 c 0,36,37
+ 359 -25 359 -25 293 18 c 128,-1,38
+ 227 61 227 61 206.5 137 c 128,-1,39
+ 186 213 186 213 186 340 c 2,40,-1
+ 186 864 l 1,41,-1
+ 150 864 l 2,42,43
+ 91 864 91 864 60 892 c 128,-1,44
+ 29 920 29 920 29 963 c 256,45,46
+ 29 1006 29 1006 61.5 1033.5 c 128,-1,47
+ 94 1061 94 1061 156 1061 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 183 51 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: u
+Encoding: 117 117 88
+Width: 1237
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 33
+ 0
+ 0
+ 38
+ 1
+ 0
+ 8
+ 1
+ 0
+ 3
+ 22
+ 49
+ 5
+ 9
+ 8
+ 7
+ 31
+ 10
+ 14
+ 10
+ 0
+ 1
+ 137
+ 35
+ 27
+ 13
+ 8
+ 1
+ 137
+ 17
+ 11
+ 13
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+850 129 m 2,0,-1
+ 850 164 l 1,1,2
+ 801 102 801 102 747 60 c 128,-1,3
+ 693 18 693 18 629 -2.5 c 128,-1,4
+ 565 -23 565 -23 483 -23 c 0,5,6
+ 384 -23 384 -23 305.5 18 c 128,-1,7
+ 227 59 227 59 184 131 c 0,8,9
+ 133 218 133 218 133 381 c 2,10,-1
+ 133 922 l 2,11,12
+ 133 1004 133 1004 170 1044.5 c 128,-1,13
+ 207 1085 207 1085 268 1085 c 0,14,15
+ 330 1085 330 1085 368 1044 c 128,-1,16
+ 406 1003 406 1003 406 922 c 2,17,-1
+ 406 485 l 2,18,19
+ 406 390 406 390 422 325.5 c 128,-1,20
+ 438 261 438 261 479.5 224.5 c 128,-1,21
+ 521 188 521 188 592 188 c 0,22,23
+ 661 188 661 188 722 229 c 128,-1,24
+ 783 270 783 270 811 336 c 0,25,26
+ 834 394 834 394 834 590 c 2,27,-1
+ 834 922 l 2,28,29
+ 834 1003 834 1003 872 1044 c 128,-1,30
+ 910 1085 910 1085 971 1085 c 256,31,32
+ 1032 1085 1032 1085 1069 1044.5 c 128,-1,33
+ 1106 1004 1106 1004 1106 922 c 2,34,-1
+ 1106 131 l 2,35,36
+ 1106 53 1106 53 1070.5 14 c 128,-1,37
+ 1035 -25 1035 -25 979 -25 c 256,38,39
+ 923 -25 923 -25 886.5 15.5 c 128,-1,40
+ 850 56 850 56 850 129 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: v
+Encoding: 118 118 89
+Width: 1110
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 12
+ 31
+ 10
+ 18
+ 9
+ 5
+ 10
+ 1
+ 108
+ 8
+ 27
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+334 915 m 2,0,-1
+ 555 295 l 1,1,-1
+ 793 942 l 2,2,3
+ 821 1020 821 1020 848 1052.5 c 128,-1,4
+ 875 1085 875 1085 930 1085 c 0,5,6
+ 982 1085 982 1085 1018.5 1050 c 128,-1,7
+ 1055 1015 1055 1015 1055 969 c 0,8,9
+ 1055 951 1055 951 1048.5 927 c 128,-1,10
+ 1042 903 1042 903 1033.5 882 c 128,-1,11
+ 1025 861 1025 861 1014 834 c 2,12,-1
+ 752 184 l 2,13,14
+ 741 156 741 156 723.5 113 c 128,-1,15
+ 706 70 706 70 684.5 39.5 c 128,-1,16
+ 663 9 663 9 631.5 -8 c 128,-1,17
+ 600 -25 600 -25 555 -25 c 0,18,19
+ 497 -25 497 -25 462.5 1.5 c 128,-1,20
+ 428 28 428 28 411.5 59.5 c 128,-1,21
+ 395 91 395 91 356 184 c 2,22,-1
+ 96 827 l 2,23,24
+ 87 851 87 851 77.5 875 c 128,-1,25
+ 68 899 68 899 61.5 924 c 128,-1,26
+ 55 949 55 949 55 967 c 0,27,28
+ 55 995 55 995 72 1022.5 c 128,-1,29
+ 89 1050 89 1050 119 1067.5 c 128,-1,30
+ 149 1085 149 1085 184 1085 c 0,31,32
+ 252 1085 252 1085 277.5 1046 c 128,-1,33
+ 303 1007 303 1007 334 915 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 124 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 110 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 108 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 84 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 82 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 72 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 71 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 70 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 68 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -154 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: w
+Encoding: 119 119 90
+Width: 1665
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 18
+ 46
+ 10
+ 35
+ 9
+ 31
+ 26
+ 9
+ 16
+ 10
+ 11
+ 6
+ 10
+ 1
+ 89
+ 19
+ 43
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MIAP[rnd]
+MDAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+MDAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+311 915 m 2,0,-1
+ 489 305 l 1,1,-1
+ 651 872 l 2,2,3
+ 677 961 677 961 689.5 993.5 c 128,-1,4
+ 702 1026 702 1026 736.5 1055.5 c 128,-1,5
+ 771 1085 771 1085 831 1085 c 0,6,7
+ 892 1085 892 1085 926.5 1055.5 c 128,-1,8
+ 961 1026 961 1026 975 991.5 c 128,-1,9
+ 989 957 989 957 1014 872 c 2,10,-1
+ 1176 305 l 1,11,-1
+ 1356 915 l 2,12,13
+ 1374 981 1374 981 1385 1010.5 c 128,-1,14
+ 1396 1040 1396 1040 1422 1062.5 c 128,-1,15
+ 1448 1085 1448 1085 1497 1085 c 256,16,17
+ 1546 1085 1546 1085 1582 1051 c 128,-1,18
+ 1618 1017 1618 1017 1618 971 c 0,19,20
+ 1618 929 1618 929 1587 844 c 2,21,-1
+ 1364 190 l 2,22,23
+ 1335 107 1335 107 1319 70 c 128,-1,24
+ 1303 33 1303 33 1268.5 4 c 128,-1,25
+ 1234 -25 1234 -25 1174 -25 c 0,26,27
+ 1112 -25 1112 -25 1076.5 6 c 128,-1,28
+ 1041 37 1041 37 1024 82 c 128,-1,29
+ 1007 127 1007 127 987 199 c 2,30,-1
+ 831 731 l 1,31,-1
+ 680 199 l 2,32,33
+ 650 88 650 88 615 31.5 c 128,-1,34
+ 580 -25 580 -25 492 -25 c 0,35,36
+ 447 -25 447 -25 415.5 -7.5 c 128,-1,37
+ 384 10 384 10 363 42.5 c 128,-1,38
+ 342 75 342 75 326 119.5 c 128,-1,39
+ 310 164 310 164 301 190 c 2,40,-1
+ 80 844 l 2,41,42
+ 47 936 47 936 47 971 c 0,43,44
+ 47 1015 47 1015 82 1050 c 128,-1,45
+ 117 1085 117 1085 168 1085 c 0,46,47
+ 236 1085 236 1085 260 1046.5 c 128,-1,48
+ 284 1008 284 1008 311 915 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 124 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 110 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 108 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 84 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 82 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 72 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 71 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 70 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 68 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -180 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -154 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: x
+Encoding: 120 120 91
+Width: 1067
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 31
+ 32
+ 11
+ 2
+ 29
+ 21
+ 1
+ 13
+ 7
+ 38
+ 9
+ 25
+ 10
+ 17
+ 10
+ 5
+ 9
+ 32
+ 31
+ 28
+ 21
+ 20
+ 14
+ 12
+ 11
+ 10
+ 9
+ 111
+ 35
+ 8
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+733 88 m 2,0,-1
+ 535 379 l 1,1,-1
+ 332 88 l 2,2,3
+ 288 27 288 27 257.5 1 c 128,-1,4
+ 227 -25 227 -25 180 -25 c 0,5,6
+ 128 -25 128 -25 91.5 7.5 c 128,-1,7
+ 55 40 55 40 55 82 c 0,8,9
+ 55 125 55 125 111 205 c 2,10,-1
+ 358 559 l 1,11,-1
+ 139 854 l 2,12,13
+ 82 927 82 927 82 981 c 0,14,15
+ 82 1023 82 1023 116 1054 c 128,-1,16
+ 150 1085 150 1085 205 1085 c 0,17,18
+ 253 1085 253 1085 284.5 1058 c 128,-1,19
+ 316 1031 316 1031 358 973 c 2,20,-1
+ 535 731 l 1,21,-1
+ 707 973 l 2,22,23
+ 750 1033 750 1033 781.5 1059 c 128,-1,24
+ 813 1085 813 1085 860 1085 c 0,25,26
+ 914 1085 914 1085 949.5 1054.5 c 128,-1,27
+ 985 1024 985 1024 985 981 c 0,28,29
+ 985 950 985 950 970.5 921.5 c 128,-1,30
+ 956 893 956 893 926 854 c 2,31,-1
+ 707 559 l 1,32,-1
+ 954 205 l 2,33,34
+ 1012 122 1012 122 1012 80 c 0,35,36
+ 1012 37 1012 37 976 6 c 128,-1,37
+ 940 -25 940 -25 887 -25 c 0,38,39
+ 840 -25 840 -25 807.5 2 c 128,-1,40
+ 775 29 775 29 733 88 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 124 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 82 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 72 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 71 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 70 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: y
+Encoding: 121 121 92
+Width: 1110
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 34
+ 35
+ 1
+ 0
+ 0
+ 0
+ 0
+ 39
+ 50
+ 29
+ 7
+ 8
+ 7
+ 17
+ 10
+ 12
+ 8
+ 10
+ 0
+ 0
+ 32
+ 1
+ 0
+ 37
+ 25
+ 24
+ 2
+ 1
+ 0
+ 6
+ 107
+ 21
+ 4
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MDAP[rnd]
+MIAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+393 -59 m 2,0,-1
+ 418 2 l 1,1,-1
+ 82 848 l 2,2,3
+ 51 921 51 921 51 954 c 0,4,5
+ 51 989 51 989 69 1019 c 128,-1,6
+ 87 1049 87 1049 118.5 1067 c 128,-1,7
+ 150 1085 150 1085 184 1085 c 0,8,9
+ 243 1085 243 1085 273 1047.5 c 128,-1,10
+ 303 1010 303 1010 326 940 c 2,11,-1
+ 557 268 l 1,12,-1
+ 776 893 l 2,13,14
+ 802 969 802 969 823 1012 c 128,-1,15
+ 844 1055 844 1055 867.5 1070 c 128,-1,16
+ 891 1085 891 1085 934 1085 c 0,17,18
+ 965 1085 965 1085 993.5 1068.5 c 128,-1,19
+ 1022 1052 1022 1052 1037.5 1024 c 128,-1,20
+ 1053 996 1053 996 1053 965 c 1,21,22
+ 1049 946 1049 946 1040 911 c 128,-1,23
+ 1031 876 1031 876 1018 840 c 2,24,-1
+ 662 -92 l 2,25,26
+ 616 -215 616 -215 572 -285 c 128,-1,27
+ 528 -355 528 -355 455.5 -392.5 c 128,-1,28
+ 383 -430 383 -430 260 -430 c 0,29,30
+ 140 -430 140 -430 80 -404 c 128,-1,31
+ 20 -378 20 -378 20 -309 c 0,32,33
+ 20 -262 20 -262 48.5 -236.5 c 128,-1,34
+ 77 -211 77 -211 133 -211 c 0,35,36
+ 155 -211 155 -211 176 -217 c 0,37,38
+ 202 -223 202 -223 221 -223 c 0,39,40
+ 268 -223 268 -223 295 -209 c 128,-1,41
+ 322 -195 322 -195 343.5 -160.5 c 128,-1,42
+ 365 -126 365 -126 393 -59 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 183 25 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 124 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 110 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 108 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 86 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 82 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 74 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 72 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 71 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 70 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 68 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 17 -180 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 15 -154 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: z
+Encoding: 122 122 93
+Width: 1067
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 30
+ 15
+ 0
+ 2
+ 20
+ 1
+ 1
+ 20
+ 53
+ 28
+ 10
+ 12
+ 1
+ 48
+ 9
+ 9
+ 11
+ 2
+ 7
+ 31
+ 24
+ 20
+ 15
+ 1
+ 0
+ 6
+ 103
+ 5
+ 12
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+883 772 m 2,0,-1
+ 383 213 l 1,1,-1
+ 918 213 l 2,2,3
+ 983 213 983 213 1016 182.5 c 128,-1,4
+ 1049 152 1049 152 1049 104 c 0,5,6
+ 1049 58 1049 58 1016.5 29 c 128,-1,7
+ 984 0 984 0 918 0 c 2,8,-1
+ 178 0 l 2,9,10
+ 100 0 100 0 61.5 34 c 128,-1,11
+ 23 68 23 68 23 127 c 0,12,13
+ 23 162 23 162 50 197.5 c 128,-1,14
+ 77 233 77 233 162 328 c 0,15,16
+ 252 428 252 428 325.5 509 c 128,-1,17
+ 399 590 399 590 462 660.5 c 128,-1,18
+ 525 731 525 731 566.5 780 c 128,-1,19
+ 608 829 608 829 633 864 c 1,20,-1
+ 227 864 l 2,21,22
+ 143 864 143 864 100 879 c 128,-1,23
+ 57 894 57 894 57 958 c 0,24,25
+ 57 1005 57 1005 89.5 1033 c 128,-1,26
+ 122 1061 122 1061 182 1061 c 2,27,-1
+ 809 1061 l 2,28,29
+ 896 1061 896 1061 942.5 1035.5 c 128,-1,30
+ 989 1010 989 1010 989 944 c 0,31,32
+ 989 922 989 922 980 898.5 c 128,-1,33
+ 971 875 971 875 960 860 c 128,-1,34
+ 949 845 949 845 930 823.5 c 128,-1,35
+ 911 802 911 802 883 772 c 2,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 124 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 82 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 72 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 71 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 70 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: braceleft
+Encoding: 123 123 94
+Width: 788
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 17
+ 36
+ 12
+ 14
+ 7
+ 0
+ 45
+ 1
+ 0
+ 33
+ 1
+ 0
+ 1
+ 144
+ 4
+ 18
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+352 530 m 1,0,1
+ 423 486 423 486 463 431.5 c 128,-1,2
+ 503 377 503 377 519 292.5 c 128,-1,3
+ 535 208 535 208 535 76 c 0,4,5
+ 535 -23 535 -23 539.5 -70 c 128,-1,6
+ 544 -117 544 -117 557.5 -141.5 c 128,-1,7
+ 571 -166 571 -166 590 -173.5 c 128,-1,8
+ 609 -181 609 -181 655 -188 c 0,9,10
+ 693 -193 693 -193 718 -225 c 128,-1,11
+ 743 -257 743 -257 743 -309 c 0,12,13
+ 743 -430 743 -430 596 -430 c 0,14,15
+ 505 -430 505 -430 433.5 -392 c 128,-1,16
+ 362 -354 362 -354 323 -284.5 c 128,-1,17
+ 284 -215 284 -215 283 -125 c 0,18,19
+ 280 27 280 27 277 119 c 128,-1,20
+ 274 211 274 211 268 238 c 0,21,22
+ 253 305 253 305 223.5 339 c 128,-1,23
+ 194 373 194 373 146.5 402.5 c 128,-1,24
+ 99 432 99 432 79 455.5 c 128,-1,25
+ 59 479 59 479 59 530 c 0,26,27
+ 59 604 59 604 117 641 c 0,28,29
+ 189 686 189 686 219.5 717.5 c 128,-1,30
+ 250 749 250 749 262.5 798.5 c 128,-1,31
+ 275 848 275 848 277 906.5 c 128,-1,32
+ 279 965 279 965 283 1188 c 0,33,34
+ 286 1326 286 1326 370.5 1408.5 c 128,-1,35
+ 455 1491 455 1491 596 1491 c 0,36,37
+ 743 1491 743 1491 743 1372 c 0,38,39
+ 743 1318 743 1318 718.5 1287 c 128,-1,40
+ 694 1256 694 1256 655 1251 c 0,41,42
+ 597 1243 597 1243 574 1227 c 128,-1,43
+ 551 1211 551 1211 544 1165 c 128,-1,44
+ 537 1119 537 1119 535 987 c 0,45,46
+ 533 858 533 858 519.5 775.5 c 128,-1,47
+ 506 693 506 693 466.5 635 c 128,-1,48
+ 427 577 427 577 352 530 c 1,0,1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: bar
+Encoding: 124 124 95
+Width: 575
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 9
+ 11
+ 12
+ 4
+ 7
+ 153
+ 1
+ 8
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+399 1354 m 2,0,-1
+ 399 -293 l 2,1,2
+ 399 -361 399 -361 368.5 -395.5 c 128,-1,3
+ 338 -430 338 -430 289 -430 c 256,4,5
+ 240 -430 240 -430 208 -395 c 128,-1,6
+ 176 -360 176 -360 176 -293 c 2,7,-1
+ 176 1354 l 2,8,9
+ 176 1421 176 1421 208 1456 c 128,-1,10
+ 240 1491 240 1491 289 1491 c 256,11,12
+ 338 1491 338 1491 368.5 1455.5 c 128,-1,13
+ 399 1420 399 1420 399 1354 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: braceright
+Encoding: 125 125 96
+Width: 788
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 17
+ 36
+ 7
+ 15
+ 12
+ 0
+ 33
+ 1
+ 0
+ 48
+ 1
+ 0
+ 1
+ 143
+ 19
+ 5
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+436 530 m 1,0,1
+ 382 564 382 564 348 601 c 128,-1,2
+ 314 638 314 638 292 691 c 128,-1,3
+ 270 744 270 744 261 816.5 c 128,-1,4
+ 252 889 252 889 252 987 c 0,5,6
+ 252 1082 252 1082 248 1132.5 c 128,-1,7
+ 244 1183 244 1183 232 1206 c 128,-1,8
+ 220 1229 220 1229 198.5 1237.5 c 128,-1,9
+ 177 1246 177 1246 133 1251 c 0,10,11
+ 96 1256 96 1256 70.5 1287 c 128,-1,12
+ 45 1318 45 1318 45 1372 c 0,13,14
+ 45 1491 45 1491 190 1491 c 0,15,16
+ 283 1491 283 1491 353.5 1453.5 c 128,-1,17
+ 424 1416 424 1416 464.5 1346.5 c 128,-1,18
+ 505 1277 505 1277 506 1188 c 0,19,20
+ 512 856 512 856 520 823 c 0,21,22
+ 536 757 536 757 567 722.5 c 128,-1,23
+ 598 688 598 688 642 661.5 c 128,-1,24
+ 686 635 686 635 707.5 609 c 128,-1,25
+ 729 583 729 583 729 530 c 0,26,27
+ 729 455 729 455 672 420 c 0,28,29
+ 602 377 602 377 570.5 344.5 c 128,-1,30
+ 539 312 539 312 526.5 263.5 c 128,-1,31
+ 514 215 514 215 511.5 118 c 128,-1,32
+ 509 21 509 21 506 -125 c 0,33,34
+ 503 -263 503 -263 417.5 -346.5 c 128,-1,35
+ 332 -430 332 -430 190 -430 c 0,36,37
+ 120 -430 120 -430 82.5 -399 c 128,-1,38
+ 45 -368 45 -368 45 -309 c 0,39,40
+ 45 -276 45 -276 57 -248.5 c 128,-1,41
+ 69 -221 69 -221 88.5 -206 c 128,-1,42
+ 108 -191 108 -191 133 -188 c 0,43,44
+ 178 -182 178 -182 200 -173 c 128,-1,45
+ 222 -164 222 -164 233.5 -139 c 128,-1,46
+ 245 -114 245 -114 248.5 -65.5 c 128,-1,47
+ 252 -17 252 -17 252 76 c 0,48,49
+ 254 214 254 214 268 292 c 128,-1,50
+ 282 370 282 370 321 426 c 128,-1,51
+ 360 482 360 482 436 530 c 1,0,1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: asciitilde
+Encoding: 126 126 97
+Width: 1194
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 21
+ 14
+ 1
+ 0
+ 2
+ 1
+ 0
+ 15
+ 11
+ 3
+ 0
+ 4
+ 28
+ 6
+ 19
+ 0
+ 7
+ 99
+ 15
+ 3
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+338 657 m 0,0,1
+ 197 657 197 657 66 520 c 1,2,-1
+ 66 778 l 1,3,4
+ 132 852 132 852 204.5 883.5 c 128,-1,5
+ 277 915 277 915 367 915 c 0,6,7
+ 436 915 436 915 498.5 897 c 128,-1,8
+ 561 879 561 879 627 852.5 c 128,-1,9
+ 693 826 693 826 756 803 c 128,-1,10
+ 819 780 819 780 854 780 c 0,11,12
+ 917 780 917 780 989.5 817 c 128,-1,13
+ 1062 854 1062 854 1128 924 c 1,14,-1
+ 1128 655 l 1,15,16
+ 1098 624 1098 624 1049.5 592.5 c 128,-1,17
+ 1001 561 1001 561 950 541.5 c 128,-1,18
+ 899 522 899 522 854 522 c 0,19,20
+ 782 522 782 522 720.5 539 c 128,-1,21
+ 659 556 659 556 580.5 589.5 c 128,-1,22
+ 502 623 502 623 451 640 c 128,-1,23
+ 400 657 400 657 338 657 c 0,0,1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: Adieresis
+Encoding: 196 196 98
+Width: 1473
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 36 65 N 1 0 0 1 0 0 2
+Refer: 142 168 N 1 0 0 1 342 371 2
+Validated: 1
+Kerns2: 183 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 181 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 90 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 89 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 60 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 57 -104 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 56 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 55 -180 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 52 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 50 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 42 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 38 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: Aring
+Encoding: 197 197 99
+Width: 1473
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 36 65 N 1 0 0 1 0 0 2
+Refer: 220 730 N 1 0 0 1 342 371 2
+Validated: 1
+Kerns2: 183 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 181 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 90 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 89 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 60 -129 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 57 -104 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 56 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 55 -180 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 52 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 50 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 42 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 38 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: Ccedilla
+Encoding: 199 199 100
+Width: 1516
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 73
+ 74
+ 58
+ 55
+ 3
+ 62
+ 69
+ 30
+ 27
+ 2
+ 35
+ 22
+ 2
+ 1
+ 62
+ 41
+ 48
+ 12
+ 12
+ 0
+ 0
+ 0
+ 0
+ 1
+ 81
+ 39
+ 2
+ 69
+ 42
+ 35
+ 9
+ 8
+ 17
+ 1
+ 0
+ 0
+ 0
+ 0
+ 22
+ 76
+ 8
+ 7
+ 8
+ 3
+ 7
+ 1
+ 9
+ 0
+ 1
+ 24
+ 65
+ 1
+ 35
+ 1
+ 2
+ 0
+ 157
+ 4
+ 24
+ 14
+ 33
+ 14
+ 2
+ 0
+ 0
+ 0
+ 39
+ 1
+ 128
+ 65
+ 43
+ 0
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+LOOPCALL
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+813 -25 m 1,0,-1
+ 807 -47 l 1,1,2
+ 908 -64 908 -64 963 -105.5 c 128,-1,3
+ 1018 -147 1018 -147 1018 -223 c 0,4,5
+ 1018 -282 1018 -282 980 -328 c 128,-1,6
+ 942 -374 942 -374 865.5 -400 c 128,-1,7
+ 789 -426 789 -426 682 -426 c 0,8,9
+ 629 -426 629 -426 582.5 -420 c 128,-1,10
+ 536 -414 536 -414 485 -399 c 0,11,12
+ 478 -397 478 -397 470.5 -383 c 128,-1,13
+ 463 -369 463 -369 463 -358 c 0,14,15
+ 463 -326 463 -326 487.5 -314.5 c 128,-1,16
+ 512 -303 512 -303 557 -303 c 0,17,18
+ 573 -303 573 -303 582 -303.5 c 128,-1,19
+ 591 -304 591 -304 606.5 -305 c 128,-1,20
+ 622 -306 622 -306 640 -307.5 c 128,-1,21
+ 658 -309 658 -309 670 -309 c 0,22,23
+ 831 -309 831 -309 831 -223 c 0,24,25
+ 831 -189 831 -189 802.5 -167 c 128,-1,26
+ 774 -145 774 -145 727 -145 c 0,27,28
+ 708 -145 708 -145 674 -151.5 c 128,-1,29
+ 640 -158 640 -158 633 -158 c 0,30,31
+ 615 -158 615 -158 600.5 -142 c 128,-1,32
+ 586 -126 586 -126 586 -104 c 0,33,34
+ 586 -41 586 -41 750 -25 c 1,35,36
+ 678 -19 678 -19 604 -3.5 c 128,-1,37
+ 530 12 530 12 469 41 c 128,-1,38
+ 408 70 408 70 354 117 c 0,39,40
+ 278 181 278 181 220 275 c 128,-1,41
+ 162 369 162 369 132 484 c 128,-1,42
+ 102 599 102 599 102 731 c 0,43,44
+ 102 908 102 908 153.5 1048 c 128,-1,45
+ 205 1188 205 1188 301 1287.5 c 128,-1,46
+ 397 1387 397 1387 526 1439 c 128,-1,47
+ 655 1491 655 1491 801 1491 c 0,48,49
+ 979 1491 979 1491 1118 1420 c 128,-1,50
+ 1257 1349 1257 1349 1331 1244.5 c 128,-1,51
+ 1405 1140 1405 1140 1405 1047 c 0,52,53
+ 1405 996 1405 996 1369 957 c 128,-1,54
+ 1333 918 1333 918 1282 918 c 0,55,56
+ 1237 918 1237 918 1207 938.5 c 128,-1,57
+ 1177 959 1177 959 1151 1004 c 0,58,59
+ 1112 1077 1112 1077 1072.5 1130.5 c 128,-1,60
+ 1033 1184 1033 1184 967.5 1219.5 c 128,-1,61
+ 902 1255 902 1255 803 1255 c 0,62,63
+ 620 1255 620 1255 511.5 1116 c 128,-1,64
+ 403 977 403 977 403 721 c 0,65,66
+ 403 550 403 550 451 436 c 128,-1,67
+ 499 322 499 322 586.5 265.5 c 128,-1,68
+ 674 209 674 209 793 209 c 0,69,70
+ 928 209 928 209 1022.5 284.5 c 128,-1,71
+ 1117 360 1117 360 1143 461 c 0,72,73
+ 1177 592 1177 592 1280 592 c 0,74,75
+ 1333 592 1333 592 1371 555 c 128,-1,76
+ 1409 518 1409 518 1409 463 c 256,77,78
+ 1409 408 1409 408 1383 338 c 128,-1,79
+ 1357 268 1357 268 1306 200.5 c 128,-1,80
+ 1255 133 1255 133 1184 82 c 0,81,82
+ 1040 -22 1040 -22 813 -25 c 1,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: Eacute
+Encoding: 201 201 101
+Width: 1366
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 40 69 N 1 0 0 1 0 0 2
+Refer: 141 180 N 1 0 0 1 342 371 2
+Validated: 1
+EndChar
+
+StartChar: Ntilde
+Encoding: 209 209 102
+Width: 1556
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 49 78 N 1 0 0 1 0 0 2
+Refer: 216 732 N 1 0 0 1 397 371 2
+Validated: 1
+EndChar
+
+StartChar: Odieresis
+Encoding: 214 214 103
+Width: 1622
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 50 79 N 1 0 0 1 0 0 2
+Refer: 142 168 N 1 0 0 1 500 371 2
+Validated: 1
+Kerns2: 60 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 59 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 58 25 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 57 -53 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 55 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 36 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: Udieresis
+Encoding: 220 220 104
+Width: 1556
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 56 85 N 1 0 0 1 0 0 2
+Refer: 142 168 N 1 0 0 1 397 371 2
+Validated: 1
+Kerns2: 36 -102 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: aacute
+Encoding: 225 225 105
+Width: 1217
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 68 97 N 1 0 0 1 0 0 2
+Refer: 141 180 N 1 0 0 1 227 0 2
+Validated: 1
+EndChar
+
+StartChar: agrave
+Encoding: 224 224 106
+Width: 1217
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 68 97 N 1 0 0 1 0 0 2
+Refer: 67 96 N 1 0 0 1 227 0 2
+Validated: 1
+EndChar
+
+StartChar: acircumflex
+Encoding: 226 226 107
+Width: 1217
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 68 97 N 1 0 0 1 0 0 2
+Refer: 215 710 N 1 0 0 1 227 0 2
+Validated: 1
+EndChar
+
+StartChar: adieresis
+Encoding: 228 228 108
+Width: 1217
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 68 97 N 1 0 0 1 0 0 2
+Refer: 142 168 N 1 0 0 1 227 0 2
+Validated: 1
+Kerns2: 92 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 90 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 89 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: atilde
+Encoding: 227 227 109
+Width: 1217
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 68 97 N 1 0 0 1 0 0 2
+Refer: 216 732 N 1 0 0 1 227 0 2
+Validated: 1
+EndChar
+
+StartChar: aring
+Encoding: 229 229 110
+Width: 1217
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 68 97 N 1 0 0 1 0 0 2
+Refer: 220 730 N 1 0 0 1 227 0 2
+Validated: 1
+Kerns2: 92 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 90 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 89 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: ccedilla
+Encoding: 231 231 111
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 66
+ 62
+ 46
+ 44
+ 3
+ 49
+ 57
+ 24
+ 21
+ 2
+ 0
+ 16
+ 2
+ 1
+ 49
+ 49
+ 36
+ 10
+ 12
+ 57
+ 51
+ 0
+ 9
+ 11
+ 13
+ 1
+ 0
+ 0
+ 0
+ 0
+ 16
+ 78
+ 8
+ 7
+ 8
+ 3
+ 7
+ 29
+ 9
+ 1
+ 9
+ 0
+ 1
+ 18
+ 52
+ 1
+ 29
+ 1
+ 2
+ 0
+ 161
+ 4
+ 18
+ 14
+ 27
+ 1
+ 0
+ 0
+ 0
+ 10
+ 1
+ 136
+ 52
+ 32
+ 0
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+LOOPCALL
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+655 -25 m 1,0,-1
+ 651 -45 l 1,1,2
+ 757 -54 757 -54 808.5 -98 c 128,-1,3
+ 860 -142 860 -142 860 -213 c 0,4,5
+ 860 -272 860 -272 821.5 -316.5 c 128,-1,6
+ 783 -361 783 -361 708 -385.5 c 128,-1,7
+ 633 -410 633 -410 526 -410 c 0,8,9
+ 342 -410 342 -410 342 -340 c 0,10,11
+ 342 -321 342 -321 356 -307 c 128,-1,12
+ 370 -293 370 -293 389 -293 c 0,13,14
+ 393 -293 393 -293 433 -297 c 128,-1,15
+ 473 -301 473 -301 506 -301 c 0,16,17
+ 686 -301 686 -301 686 -215 c 0,18,19
+ 686 -184 686 -184 658.5 -162.5 c 128,-1,20
+ 631 -141 631 -141 590 -141 c 0,21,22
+ 574 -141 574 -141 544 -145.5 c 128,-1,23
+ 514 -150 514 -150 500 -150 c 0,24,25
+ 475 -150 475 -150 460.5 -131.5 c 128,-1,26
+ 446 -113 446 -113 446 -92 c 0,27,28
+ 446 -44 446 -44 588 -23 c 1,29,30
+ 346 -10 346 -10 217 136.5 c 128,-1,31
+ 88 283 88 283 88 520 c 0,32,33
+ 88 688 88 688 153 817 c 128,-1,34
+ 218 946 218 946 341 1016.5 c 128,-1,35
+ 464 1087 464 1087 635 1087 c 0,36,37
+ 741 1087 741 1087 829.5 1056 c 128,-1,38
+ 918 1025 918 1025 979.5 976 c 128,-1,39
+ 1041 927 1041 927 1073.5 871.5 c 128,-1,40
+ 1106 816 1106 816 1106 768 c 0,41,42
+ 1106 719 1106 719 1069.5 685 c 128,-1,43
+ 1033 651 1033 651 981 651 c 0,44,45
+ 928 651 928 651 891 702 c 0,46,47
+ 829 792 829 792 777 834.5 c 128,-1,48
+ 725 877 725 877 631 877 c 0,49,50
+ 510 877 510 877 436 782.5 c 128,-1,51
+ 362 688 362 688 362 524 c 0,52,53
+ 362 447 362 447 381 382.5 c 128,-1,54
+ 400 318 400 318 436 272.5 c 128,-1,55
+ 472 227 472 227 523 203.5 c 128,-1,56
+ 574 180 574 180 635 180 c 0,57,58
+ 721 180 721 180 770.5 213 c 128,-1,59
+ 820 246 820 246 864.5 313 c 128,-1,60
+ 909 380 909 380 933 406 c 128,-1,61
+ 957 432 957 432 1004 432 c 0,62,63
+ 1053 432 1053 432 1086.5 395 c 128,-1,64
+ 1120 358 1120 358 1120 313 c 0,65,66
+ 1120 246 1120 246 1066.5 169 c 128,-1,67
+ 1013 92 1013 92 907 36.5 c 128,-1,68
+ 801 -19 801 -19 655 -25 c 1,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: eacute
+Encoding: 233 233 112
+Width: 1217
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 72 101 N 1 0 0 1 0 0 2
+Refer: 141 180 N 1 0 0 1 227 0 2
+Validated: 1
+EndChar
+
+StartChar: egrave
+Encoding: 232 232 113
+Width: 1217
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 72 101 N 1 0 0 1 0 0 2
+Refer: 67 96 N 1 0 0 1 227 0 2
+Validated: 1
+EndChar
+
+StartChar: ecircumflex
+Encoding: 234 234 114
+Width: 1217
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 72 101 N 1 0 0 1 0 0 2
+Refer: 215 710 N 1 0 0 1 227 0 2
+Validated: 1
+EndChar
+
+StartChar: edieresis
+Encoding: 235 235 115
+Width: 1217
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 72 101 N 1 0 0 1 0 0 2
+Refer: 142 168 N 1 0 0 1 227 0 2
+Validated: 1
+EndChar
+
+StartChar: iacute
+Encoding: 237 237 116
+Width: 555
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 214 305 N 1 0 0 1 0 0 2
+Refer: 141 180 N 1 0 0 1 -55 0 2
+Validated: 1
+EndChar
+
+StartChar: igrave
+Encoding: 236 236 117
+Width: 555
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 214 305 N 1 0 0 1 0 0 2
+Refer: 67 96 N 1 0 0 1 -55 0 2
+Validated: 1
+EndChar
+
+StartChar: icircumflex
+Encoding: 238 238 118
+Width: 555
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 214 305 N 1 0 0 1 0 0 2
+Refer: 215 710 N 1 0 0 1 -55 0 2
+Validated: 1
+EndChar
+
+StartChar: idieresis
+Encoding: 239 239 119
+Width: 555
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 214 305 N 1 0 0 1 0 0 2
+Refer: 142 168 N 1 0 0 1 -55 0 2
+Validated: 1
+EndChar
+
+StartChar: ntilde
+Encoding: 241 241 120
+Width: 1237
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 81 110 N 1 0 0 1 0 0 2
+Refer: 216 732 N 1 0 0 1 227 0 2
+Validated: 1
+EndChar
+
+StartChar: oacute
+Encoding: 243 243 121
+Width: 1237
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 82 111 N 1 0 0 1 0 0 2
+Refer: 141 180 N 1 0 0 1 227 0 2
+Validated: 1
+EndChar
+
+StartChar: ograve
+Encoding: 242 242 122
+Width: 1237
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 82 111 N 1 0 0 1 0 0 2
+Refer: 67 96 N 1 0 0 1 227 0 2
+Validated: 1
+EndChar
+
+StartChar: ocircumflex
+Encoding: 244 244 123
+Width: 1237
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 82 111 N 1 0 0 1 0 0 2
+Refer: 215 710 N 1 0 0 1 227 0 2
+Validated: 1
+EndChar
+
+StartChar: odieresis
+Encoding: 246 246 124
+Width: 1237
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 82 111 N 1 0 0 1 0 0 2
+Refer: 142 168 N 1 0 0 1 227 0 2
+Validated: 1
+Kerns2: 92 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 91 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 89 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: otilde
+Encoding: 245 245 125
+Width: 1237
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 82 111 N 1 0 0 1 0 0 2
+Refer: 216 732 N 1 0 0 1 227 0 2
+Validated: 1
+EndChar
+
+StartChar: uacute
+Encoding: 250 250 126
+Width: 1237
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 88 117 N 1 0 0 1 0 0 2
+Refer: 141 180 N 1 0 0 1 227 0 2
+Validated: 1
+EndChar
+
+StartChar: ugrave
+Encoding: 249 249 127
+Width: 1237
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 88 117 N 1 0 0 1 0 0 2
+Refer: 67 96 N 1 0 0 1 227 0 2
+Validated: 1
+EndChar
+
+StartChar: ucircumflex
+Encoding: 251 251 128
+Width: 1237
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 88 117 N 1 0 0 1 0 0 2
+Refer: 215 710 N 1 0 0 1 227 0 2
+Validated: 1
+EndChar
+
+StartChar: udieresis
+Encoding: 252 252 129
+Width: 1237
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 88 117 N 1 0 0 1 0 0 2
+Refer: 142 168 N 1 0 0 1 227 0 2
+Validated: 1
+EndChar
+
+StartChar: dagger
+Encoding: 8224 8224 130
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 27
+ 0
+ 17
+ 1
+ 0
+ 24
+ 1
+ 0
+ 48
+ 8
+ 1
+ 0
+ 7
+ 29
+ 13
+ 12
+ 0
+ 25
+ 1
+ 0
+ 0
+ 1
+ 0
+ 146
+ 16
+ 9
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MDAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+485 -242 m 2,0,-1
+ 485 838 l 1,1,-1
+ 207 838 l 2,2,3
+ 142 838 142 838 109 867.5 c 128,-1,4
+ 76 897 76 897 76 944 c 0,5,6
+ 76 992 76 992 109.5 1021.5 c 128,-1,7
+ 143 1051 143 1051 207 1051 c 2,8,-1
+ 485 1051 l 1,9,-1
+ 485 1327 l 2,10,11
+ 485 1404 485 1404 519 1441.5 c 128,-1,12
+ 553 1479 553 1479 608 1479 c 0,13,14
+ 664 1479 664 1479 698.5 1441.5 c 128,-1,15
+ 733 1404 733 1404 733 1327 c 2,16,-1
+ 733 1051 l 1,17,-1
+ 1012 1051 l 2,18,19
+ 1078 1051 1078 1051 1110.5 1022 c 128,-1,20
+ 1143 993 1143 993 1143 944 c 0,21,22
+ 1143 897 1143 897 1110 867.5 c 128,-1,23
+ 1077 838 1077 838 1012 838 c 2,24,-1
+ 733 838 l 1,25,-1
+ 733 -242 l 2,26,27
+ 733 -318 733 -318 698.5 -355.5 c 128,-1,28
+ 664 -393 664 -393 608 -393 c 0,29,30
+ 553 -393 553 -393 519 -355.5 c 128,-1,31
+ 485 -318 485 -318 485 -242 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: degree
+Encoding: 176 176 131
+Width: 811
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 26
+ 0
+ 1
+ 26
+ 19
+ 1
+ 26
+ 62
+ 5
+ 12
+ 12
+ 62
+ 19
+ 13
+ 10
+ 2
+ 7
+ 164
+ 9
+ 22
+ 10
+ 165
+ 16
+ 0
+ 10
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+86 1171 m 0,0,1
+ 86 1237 86 1237 112 1297 c 128,-1,2
+ 138 1357 138 1357 181.5 1399.5 c 128,-1,3
+ 225 1442 225 1442 283 1466.5 c 128,-1,4
+ 341 1491 341 1491 406 1491 c 0,5,6
+ 491 1491 491 1491 565 1448.5 c 128,-1,7
+ 639 1406 639 1406 682 1332 c 128,-1,8
+ 725 1258 725 1258 725 1171 c 0,9,10
+ 725 1085 725 1085 682 1011.5 c 128,-1,11
+ 639 938 639 938 566 896 c 128,-1,12
+ 493 854 493 854 406 854 c 0,13,14
+ 274 854 274 854 180 947 c 128,-1,15
+ 86 1040 86 1040 86 1171 c 0,0,1
+252 1171 m 256,16,17
+ 252 1108 252 1108 298 1064 c 128,-1,18
+ 344 1020 344 1020 406 1020 c 256,19,20
+ 468 1020 468 1020 512.5 1063.5 c 128,-1,21
+ 557 1107 557 1107 557 1171 c 0,22,23
+ 557 1214 557 1214 536.5 1249 c 128,-1,24
+ 516 1284 516 1284 480.5 1304.5 c 128,-1,25
+ 445 1325 445 1325 406 1325 c 0,26,27
+ 343 1325 343 1325 297.5 1279.5 c 128,-1,28
+ 252 1234 252 1234 252 1171 c 256,16,17
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: cent
+Encoding: 162 162 132
+Width: 1194
+GlyphClass: 1
+Flags: WO
+LayerCount: 2
+Fore
+SplineSet
+1111 815 m 6,0,1
+ 1140 815 1140 815 1160 796 c 132,-1,2
+ 1180 777 1180 777 1180 751 c 6,3,-1
+ 1180 217 l 6,4,5
+ 1180 191 1180 191 1160 172 c 132,-1,6
+ 1140 153 1140 153 1111 153 c 6,7,-1
+ 88 153 l 6,8,9
+ 61 153 61 153 40 172 c 132,-1,10
+ 19 191 19 191 19 217 c 6,11,-1
+ 19 842 l 6,12,13
+ 19 871 19 871 39 888 c 4,14,15
+ 60 906 60 906 88 906 c 6,16,-1
+ 563 906 l 6,17,18
+ 592 906 592 906 617 892 c 132,-1,19
+ 642 878 642 878 655 854 c 6,20,-1
+ 677 815 l 5,21,-1
+ 1111 815 l 6,0,1
+EndSplineSet
+EndChar
+
+StartChar: sterling
+Encoding: 163 163 133
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 65
+ 45
+ 1
+ 7
+ 19
+ 1
+ 0
+ 0
+ 0
+ 0
+ 66
+ 1
+ 76
+ 52
+ 63
+ 12
+ 9
+ 71
+ 1
+ 56
+ 1
+ 0
+ 50
+ 1
+ 0
+ 55
+ 0
+ 7
+ 0
+ 22
+ 16
+ 2
+ 0
+ 0
+ 0
+ 34
+ 30
+ 12
+ 3
+ 19
+ 37
+ 28
+ 9
+ 8
+ 3
+ 7
+ 73
+ 10
+ 38
+ 9
+ 0
+ 0
+ 54
+ 41
+ 2
+ 0
+ 57
+ 50
+ 48
+ 12
+ 4
+ 136
+ 79
+ 59
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+494 823 m 1,0,-1
+ 643 823 l 2,1,2
+ 725 823 725 823 770 806.5 c 128,-1,3
+ 815 790 815 790 815 729 c 0,4,5
+ 815 687 815 687 785 661 c 128,-1,6
+ 755 635 755 635 707 635 c 2,7,-1
+ 530 635 l 1,8,-1
+ 530 618 l 2,9,10
+ 530 517 530 517 484.5 432.5 c 128,-1,11
+ 439 348 439 348 326 221 c 1,12,13
+ 359 229 359 229 391.5 236 c 128,-1,14
+ 424 243 424 243 464.5 248.5 c 128,-1,15
+ 505 254 505 254 553 254 c 0,16,17
+ 620 254 620 254 740 238.5 c 128,-1,18
+ 860 223 860 223 899 223 c 0,19,20
+ 956 223 956 223 1021.5 243.5 c 128,-1,21
+ 1087 264 1087 264 1104 264 c 0,22,23
+ 1149 264 1149 264 1184 228 c 128,-1,24
+ 1219 192 1219 192 1219 143 c 0,25,26
+ 1219 60 1219 60 1125.5 15.5 c 128,-1,27
+ 1032 -29 1032 -29 926 -29 c 0,28,29
+ 861 -29 861 -29 557 41 c 0,30,31
+ 549 43 549 43 530 49 c 128,-1,32
+ 511 55 511 55 483 59 c 128,-1,33
+ 455 63 455 63 416 63 c 0,34,35
+ 374 63 374 63 342 51 c 128,-1,36
+ 310 39 310 39 231.5 7 c 128,-1,37
+ 153 -25 153 -25 125 -25 c 0,38,39
+ 87 -25 87 -25 50.5 9.5 c 128,-1,40
+ 14 44 14 44 14 100 c 0,41,42
+ 14 121 14 121 27 144 c 128,-1,43
+ 40 167 40 167 68 196.5 c 128,-1,44
+ 96 226 96 226 152 274 c 0,45,46
+ 203 317 203 317 237.5 394.5 c 128,-1,47
+ 272 472 272 472 272 547 c 0,48,49
+ 272 573 272 573 262 635 c 1,50,-1
+ 178 635 l 2,51,52
+ 104 635 104 635 66.5 653 c 128,-1,53
+ 29 671 29 671 29 725 c 0,54,55
+ 29 823 29 823 156 823 c 2,56,-1
+ 215 823 l 1,57,58
+ 166 979 166 979 166 1069 c 0,59,60
+ 166 1192 166 1192 224 1288 c 128,-1,61
+ 282 1384 282 1384 390 1438.5 c 128,-1,62
+ 498 1493 498 1493 637 1493 c 0,63,64
+ 760 1493 760 1493 848 1462.5 c 128,-1,65
+ 936 1432 936 1432 1004 1362 c 0,66,67
+ 1120 1241 1120 1241 1120 1104 c 0,68,69
+ 1120 1055 1120 1055 1082 1017 c 128,-1,70
+ 1044 979 1044 979 989 979 c 0,71,72
+ 892 979 892 979 860 1087 c 0,73,74
+ 831 1191 831 1191 780.5 1240.5 c 128,-1,75
+ 730 1290 730 1290 645 1290 c 0,76,77
+ 553 1290 553 1290 496.5 1230.5 c 128,-1,78
+ 440 1171 440 1171 440 1077 c 0,79,80
+ 440 1020 440 1020 452 970.5 c 128,-1,81
+ 464 921 464 921 494 823 c 1,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: section
+Encoding: 167 167 134
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 72
+ 80
+ 77
+ 69
+ 62
+ 52
+ 50
+ 47
+ 32
+ 24
+ 0
+ 10
+ 17
+ 54
+ 1
+ 0
+ 0
+ 12
+ 1
+ 0
+ 0
+ 17
+ 52
+ 4
+ 12
+ 9
+ 54
+ 52
+ 39
+ 7
+ 11
+ 2
+ 7
+ 71
+ 80
+ 77
+ 24
+ 3
+ 57
+ 20
+ 1
+ 29
+ 1
+ 0
+ 0
+ 0
+ 82
+ 32
+ 9
+ 3
+ 138
+ 34
+ 57
+ 0
+ 0
+ 0
+ 67
+ 44
+ 2
+ 0
+ 73
+ 71
+ 69
+ 62
+ 52
+ 50
+ 6
+ 138
+ 20
+ 0
+ 0
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+172 1163 m 0,0,1
+ 172 1251 172 1251 221.5 1326.5 c 128,-1,2
+ 271 1402 271 1402 367.5 1447.5 c 128,-1,3
+ 464 1493 464 1493 596 1493 c 0,4,5
+ 694 1493 694 1493 777.5 1467 c 128,-1,6
+ 861 1441 861 1441 919.5 1397.5 c 128,-1,7
+ 978 1354 978 1354 1009 1302.5 c 128,-1,8
+ 1040 1251 1040 1251 1040 1200 c 0,9,10
+ 1040 1160 1040 1160 1005 1129 c 128,-1,11
+ 970 1098 970 1098 926 1098 c 0,12,13
+ 884 1098 884 1098 860.5 1118.5 c 128,-1,14
+ 837 1139 837 1139 796.5 1188.5 c 128,-1,15
+ 756 1238 756 1238 714.5 1264 c 128,-1,16
+ 673 1290 673 1290 606 1290 c 0,17,18
+ 529 1290 529 1290 483.5 1253 c 128,-1,19
+ 438 1216 438 1216 438 1167 c 0,20,21
+ 438 1116 438 1116 477 1079.5 c 128,-1,22
+ 516 1043 516 1043 608.5 993 c 128,-1,23
+ 701 943 701 943 731 924 c 0,24,25
+ 819 872 819 872 888.5 831.5 c 128,-1,26
+ 958 791 958 791 1015 743.5 c 128,-1,27
+ 1072 696 1072 696 1104.5 633.5 c 128,-1,28
+ 1137 571 1137 571 1137 487 c 0,29,30
+ 1137 393 1137 393 1086 316.5 c 128,-1,31
+ 1035 240 1035 240 938 186 c 1,32,33
+ 1073 74 1073 74 1073 -78 c 0,34,35
+ 1073 -150 1073 -150 1042.5 -214 c 128,-1,36
+ 1012 -278 1012 -278 953 -327 c 128,-1,37
+ 894 -376 894 -376 813 -403 c 128,-1,38
+ 732 -430 732 -430 635 -430 c 0,39,40
+ 518 -430 518 -430 429 -398.5 c 128,-1,41
+ 340 -367 340 -367 275.5 -312 c 128,-1,42
+ 211 -257 211 -257 180.5 -196.5 c 128,-1,43
+ 150 -136 150 -136 150 -82 c 0,44,45
+ 150 -32 150 -32 186 6.5 c 128,-1,46
+ 222 45 222 45 276 45 c 0,47,48
+ 297 45 297 45 318.5 36.5 c 128,-1,49
+ 340 28 340 28 350 16 c 0,50,51
+ 400 -47 400 -47 422 -94 c 0,52,53
+ 480 -227 480 -227 627 -227 c 0,54,55
+ 708 -227 708 -227 757.5 -183.5 c 128,-1,56
+ 807 -140 807 -140 807 -82 c 0,57,58
+ 807 -42 807 -42 779 -7.5 c 128,-1,59
+ 751 27 751 27 698.5 63 c 128,-1,60
+ 646 99 646 99 538 165.5 c 128,-1,61
+ 430 232 430 232 319 303 c 0,62,63
+ 277 331 277 331 232 362.5 c 128,-1,64
+ 187 394 187 394 153 431 c 128,-1,65
+ 119 468 119 468 99.5 516.5 c 128,-1,66
+ 80 565 80 565 80 631 c 0,67,68
+ 80 813 80 813 291 924 c 1,69,70
+ 172 1026 172 1026 172 1163 c 0,0,1
+426 813 m 1,71,72
+ 309 738 309 738 309 659 c 0,73,74
+ 309 618 309 618 338.5 583 c 128,-1,75
+ 368 548 368 548 418 515.5 c 128,-1,76
+ 468 483 468 483 573 420 c 0,77,78
+ 604 402 604 402 658 369.5 c 128,-1,79
+ 712 337 712 337 764 309 c 1,80,81
+ 883 394 883 394 883 461 c 0,82,83
+ 883 497 883 497 862 527.5 c 128,-1,84
+ 841 558 841 558 805 586 c 128,-1,85
+ 769 614 769 614 715.5 646.5 c 128,-1,86
+ 662 679 662 679 578 727 c 0,87,88
+ 510 766 510 766 476 785.5 c 128,-1,89
+ 442 805 442 805 426 813 c 1,71,72
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: bullet
+Encoding: 8226 8226 135
+Width: 725
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 10
+ 25
+ 9
+ 3
+ 10
+ 7
+ 121
+ 0
+ 6
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+659 723 m 0,0,1
+ 659 600 659 600 571 514 c 128,-1,2
+ 483 428 483 428 362 428 c 0,3,4
+ 240 428 240 428 154 514 c 128,-1,5
+ 68 600 68 600 68 723 c 0,6,7
+ 68 845 68 845 153.5 932.5 c 128,-1,8
+ 239 1020 239 1020 362 1020 c 0,9,10
+ 441 1020 441 1020 510 980 c 128,-1,11
+ 579 940 579 940 619 871 c 128,-1,12
+ 659 802 659 802 659 723 c 0,0,1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: paragraph
+Encoding: 182 182 136
+Width: 1153
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 27
+ 0
+ 0
+ 0
+ 18
+ 1
+ 0
+ 1
+ 84
+ 17
+ 12
+ 9
+ 7
+ 21
+ 3
+ 18
+ 1
+ 0
+ 173
+ 19
+ 21
+ 15
+ 174
+ 1
+ 3
+ 10
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MDAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+852 1386 m 1,0,-1
+ 664 1386 l 1,1,-1
+ 664 -399 l 1,2,-1
+ 561 -399 l 1,3,-1
+ 561 504 l 1,4,5
+ 490 507 490 507 435.5 514 c 128,-1,6
+ 381 521 381 521 326 537.5 c 128,-1,7
+ 271 554 271 554 223 582 c 128,-1,8
+ 175 610 175 610 135 649 c 0,9,10
+ 2 782 2 782 2 989 c 0,11,12
+ 2 1239 2 1239 180 1374 c 0,13,14
+ 257 1433 257 1433 370 1449.5 c 128,-1,15
+ 483 1466 483 1466 696 1466 c 2,16,-1
+ 1126 1466 l 1,17,-1
+ 1126 1386 l 1,18,-1
+ 956 1386 l 1,19,-1
+ 956 -399 l 1,20,-1
+ 852 -399 l 1,21,-1
+ 852 1386 l 1,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: germandbls
+Encoding: 223 223 137
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 58
+ 33
+ 1
+ 3
+ 52
+ 1
+ 0
+ 0
+ 0
+ 0
+ 19
+ 1
+ 3
+ 53
+ 22
+ 12
+ 9
+ 48
+ 1
+ 0
+ 0
+ 11
+ 1
+ 0
+ 52
+ 53
+ 41
+ 9
+ 8
+ 2
+ 7
+ 45
+ 1
+ 61
+ 7
+ 1
+ 33
+ 26
+ 2
+ 147
+ 37
+ 55
+ 13
+ 63
+ 58
+ 0
+ 3
+ 138
+ 31
+ 61
+ 13
+ 19
+ 1
+ 138
+ 7
+ 15
+ 13
+ 3
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+707 1174 m 0,0,1
+ 707 1227 707 1227 669 1260.5 c 128,-1,2
+ 631 1294 631 1294 565 1294 c 0,3,4
+ 500 1294 500 1294 460 1261.5 c 128,-1,5
+ 420 1229 420 1229 403.5 1166 c 128,-1,6
+ 387 1103 387 1103 387 1014 c 2,7,-1
+ 387 137 l 2,8,9
+ 387 57 387 57 350 16 c 128,-1,10
+ 313 -25 313 -25 254 -25 c 256,11,12
+ 195 -25 195 -25 158 16 c 128,-1,13
+ 121 57 121 57 121 137 c 2,14,-1
+ 121 993 l 2,15,16
+ 121 1055 121 1055 125.5 1106 c 128,-1,17
+ 130 1157 130 1157 143 1206 c 128,-1,18
+ 156 1255 156 1255 180 1296 c 0,19,20
+ 237 1396 237 1396 333 1443.5 c 128,-1,21
+ 429 1491 429 1491 571 1491 c 0,22,23
+ 701 1491 701 1491 791.5 1452.5 c 128,-1,24
+ 882 1414 882 1414 927.5 1348 c 128,-1,25
+ 973 1282 973 1282 973 1198 c 0,26,27
+ 973 1147 973 1147 950.5 1087 c 128,-1,28
+ 928 1027 928 1027 893 979 c 0,29,30
+ 827 889 827 889 827 827 c 0,31,32
+ 827 768 827 768 938 670 c 0,33,34
+ 1014 602 1014 602 1058 546 c 128,-1,35
+ 1102 490 1102 490 1124.5 432 c 128,-1,36
+ 1147 374 1147 374 1147 307 c 0,37,38
+ 1147 214 1147 214 1102 137.5 c 128,-1,39
+ 1057 61 1057 61 978.5 18 c 128,-1,40
+ 900 -25 900 -25 803 -25 c 0,41,42
+ 710 -25 710 -25 634.5 10 c 128,-1,43
+ 559 45 559 45 516 96.5 c 128,-1,44
+ 473 148 473 148 473 193 c 0,45,46
+ 473 234 473 234 503.5 264.5 c 128,-1,47
+ 534 295 534 295 578 295 c 0,48,49
+ 631 295 631 295 674 233 c 0,50,51
+ 716 172 716 172 780 172 c 0,52,53
+ 829 172 829 172 865 209 c 128,-1,54
+ 901 246 901 246 901 297 c 256,55,56
+ 901 348 901 348 854 409 c 128,-1,57
+ 807 470 807 470 735 522 c 0,58,59
+ 660 578 660 578 610.5 648.5 c 128,-1,60
+ 561 719 561 719 561 772 c 0,61,62
+ 561 862 561 862 635 979 c 0,63,64
+ 707 1094 707 1094 707 1174 c 0,0,1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: registered
+Encoding: 174 174 138
+Width: 1516
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 67
+ 16
+ 15
+ 13
+ 1
+ 4
+ 21
+ 56
+ 1
+ 48
+ 66
+ 31
+ 12
+ 12
+ 74
+ 3
+ 22
+ 10
+ 10
+ 1
+ 74
+ 24
+ 21
+ 13
+ 56
+ 66
+ 40
+ 9
+ 11
+ 4
+ 7
+ 48
+ 31
+ 16
+ 3
+ 27
+ 21
+ 1
+ 169
+ 36
+ 60
+ 10
+ 14
+ 1
+ 0
+ 10
+ 1
+ 0
+ 15
+ 13
+ 2
+ 160
+ 7
+ 27
+ 0
+ 0
+ 23
+ 1
+ 165
+ 21
+ 2
+ 15
+ 168
+ 52
+ 44
+ 10
+ 4
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+578 315 m 1,0,-1
+ 412 315 l 1,1,-1
+ 412 1128 l 1,2,-1
+ 797 1128 l 2,3,4
+ 887 1128 887 1128 948 1099.5 c 128,-1,5
+ 1009 1071 1009 1071 1040 1018.5 c 128,-1,6
+ 1071 966 1071 966 1071 897 c 0,7,8
+ 1071 811 1071 811 1013 748.5 c 128,-1,9
+ 955 686 955 686 852 672 c 1,10,11
+ 905 652 905 652 937.5 612.5 c 128,-1,12
+ 970 573 970 573 1024 479 c 2,13,-1
+ 1120 315 l 1,14,-1
+ 915 315 l 1,15,-1
+ 848 446 l 2,16,17
+ 801 534 801 534 768 576.5 c 128,-1,18
+ 735 619 735 619 702 634 c 128,-1,19
+ 669 649 669 649 621 649 c 2,20,-1
+ 578 649 l 1,21,-1
+ 578 315 l 1,0,-1
+578 999 m 1,22,-1
+ 578 778 l 1,23,-1
+ 711 778 l 2,24,25
+ 801 778 801 778 848 801.5 c 128,-1,26
+ 895 825 895 825 895 895 c 0,27,28
+ 895 943 895 943 854 971 c 128,-1,29
+ 813 999 813 999 727 999 c 2,30,-1
+ 578 999 l 1,22,-1
+758 1491 m 0,31,32
+ 915 1491 915 1491 1054.5 1432.5 c 128,-1,33
+ 1194 1374 1194 1374 1300.5 1267.5 c 128,-1,34
+ 1407 1161 1407 1161 1465.5 1021.5 c 128,-1,35
+ 1524 882 1524 882 1524 725 c 0,36,37
+ 1524 517 1524 517 1421.5 340.5 c 128,-1,38
+ 1319 164 1319 164 1142.5 61.5 c 128,-1,39
+ 966 -41 966 -41 758 -41 c 256,40,41
+ 550 -41 550 -41 373.5 61.5 c 128,-1,42
+ 197 164 197 164 94.5 340.5 c 128,-1,43
+ -8 517 -8 517 -8 725 c 256,44,45
+ -8 933 -8 933 94.5 1109.5 c 128,-1,46
+ 197 1286 197 1286 373.5 1388.5 c 128,-1,47
+ 550 1491 550 1491 758 1491 c 0,31,32
+760 1341 m 0,48,49
+ 593 1341 593 1341 451 1258.5 c 128,-1,50
+ 309 1176 309 1176 226 1034 c 128,-1,51
+ 143 892 143 892 143 725 c 256,52,53
+ 143 558 143 558 226.5 415.5 c 128,-1,54
+ 310 273 310 273 452 191 c 128,-1,55
+ 594 109 594 109 760 109 c 0,56,57
+ 929 109 929 109 1069.5 191.5 c 128,-1,58
+ 1210 274 1210 274 1292 416 c 128,-1,59
+ 1374 558 1374 558 1374 725 c 0,60,61
+ 1374 893 1374 893 1292 1035 c 128,-1,62
+ 1210 1177 1210 1177 1069 1259 c 128,-1,63
+ 928 1341 928 1341 760 1341 c 0,48,49
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: copyright
+Encoding: 169 169 139
+Width: 1516
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 56
+ 13
+ 0
+ 2
+ 3
+ 10
+ 1
+ 42
+ 66
+ 25
+ 12
+ 12
+ 1
+ 1
+ 0
+ 69
+ 23
+ 3
+ 14
+ 12
+ 1
+ 0
+ 68
+ 10
+ 15
+ 15
+ 50
+ 66
+ 34
+ 9
+ 11
+ 4
+ 7
+ 42
+ 25
+ 13
+ 12
+ 1
+ 0
+ 6
+ 54
+ 6
+ 1
+ 169
+ 30
+ 54
+ 10
+ 160
+ 6
+ 19
+ 10
+ 168
+ 46
+ 38
+ 10
+ 3
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1106 907 m 1,0,-1
+ 942 868 l 1,1,2
+ 889 1008 889 1008 764 1008 c 0,3,4
+ 668 1008 668 1008 613.5 934 c 128,-1,5
+ 559 860 559 860 559 737 c 0,6,7
+ 559 640 559 640 582 573.5 c 128,-1,8
+ 605 507 605 507 649.5 473.5 c 128,-1,9
+ 694 440 694 440 756 440 c 0,10,11
+ 894 440 894 440 944 612 c 1,12,-1
+ 1106 557 l 1,13,14
+ 1026 297 1026 297 752 297 c 0,15,16
+ 654 297 654 297 569.5 345 c 128,-1,17
+ 485 393 485 393 434 491 c 128,-1,18
+ 383 589 383 589 383 725 c 0,19,20
+ 383 852 383 852 430 947.5 c 128,-1,21
+ 477 1043 477 1043 564.5 1096 c 128,-1,22
+ 652 1149 652 1149 770 1149 c 0,23,24
+ 1018 1149 1018 1149 1106 907 c 1,0,-1
+758 1491 m 0,25,26
+ 915 1491 915 1491 1054.5 1432.5 c 128,-1,27
+ 1194 1374 1194 1374 1300.5 1267.5 c 128,-1,28
+ 1407 1161 1407 1161 1465.5 1021.5 c 128,-1,29
+ 1524 882 1524 882 1524 725 c 0,30,31
+ 1524 519 1524 519 1420.5 342.5 c 128,-1,32
+ 1317 166 1317 166 1141 63.5 c 128,-1,33
+ 965 -39 965 -39 758 -39 c 0,34,35
+ 548 -39 548 -39 372.5 63 c 128,-1,36
+ 197 165 197 165 94.5 341.5 c 128,-1,37
+ -8 518 -8 518 -8 725 c 0,38,39
+ -8 933 -8 933 94.5 1109.5 c 128,-1,40
+ 197 1286 197 1286 373.5 1388.5 c 128,-1,41
+ 550 1491 550 1491 758 1491 c 0,25,26
+758 1341 m 0,42,43
+ 589 1341 589 1341 448.5 1258 c 128,-1,44
+ 308 1175 308 1175 225.5 1033.5 c 128,-1,45
+ 143 892 143 892 143 725 c 0,46,47
+ 143 557 143 557 225.5 416.5 c 128,-1,48
+ 308 276 308 276 449 193.5 c 128,-1,49
+ 590 111 590 111 758 111 c 0,50,51
+ 925 111 925 111 1067 193 c 128,-1,52
+ 1209 275 1209 275 1291.5 415.5 c 128,-1,53
+ 1374 556 1374 556 1374 725 c 0,54,55
+ 1374 891 1374 891 1291 1033 c 128,-1,56
+ 1208 1175 1208 1175 1066.5 1258 c 128,-1,57
+ 925 1341 925 1341 758 1341 c 0,42,43
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: trademark
+Encoding: 8482 8482 140
+Width: 2048
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 45
+ 0
+ 14
+ 11
+ 2
+ 20
+ 17
+ 2
+ 6
+ 1
+ 0
+ 2
+ 68
+ 5
+ 12
+ 9
+ 7
+ 19
+ 16
+ 12
+ 9
+ 1
+ 13
+ 12
+ 11
+ 3
+ 16
+ 20
+ 1
+ 166
+ 15
+ 16
+ 10
+ 6
+ 1
+ 0
+ 167
+ 20
+ 10
+ 14
+ 165
+ 7
+ 1
+ 10
+ 3
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+637 647 m 1,0,-1
+ 471 647 l 1,1,-1
+ 471 1323 l 1,2,-1
+ 217 1323 l 1,3,-1
+ 217 1466 l 1,4,-1
+ 883 1466 l 1,5,-1
+ 883 1323 l 1,6,-1
+ 637 1323 l 1,7,-1
+ 637 647 l 1,0,-1
+1137 647 m 1,8,-1
+ 981 647 l 1,9,-1
+ 981 1466 l 1,10,-1
+ 1241 1466 l 1,11,-1
+ 1389 901 l 1,12,-1
+ 1538 1466 l 1,13,-1
+ 1798 1466 l 1,14,-1
+ 1798 647 l 1,15,-1
+ 1640 647 l 1,16,-1
+ 1640 1300 l 1,17,-1
+ 1462 647 l 1,18,-1
+ 1313 647 l 1,19,-1
+ 1137 1300 l 1,20,-1
+ 1137 647 l 1,8,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: acute
+Encoding: 180 180 141
+Width: 682
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 11
+ 9
+ 34
+ 1
+ 12
+ 12
+ 7
+ 125
+ 3
+ 11
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+422 1477 m 2,0,-1
+ 557 1477 l 2,1,2
+ 608 1477 608 1477 608 1462 c 0,3,4
+ 608 1454 608 1454 552 1397 c 128,-1,5
+ 496 1340 496 1340 439 1288 c 128,-1,6
+ 382 1236 382 1236 360 1225 c 0,7,8
+ 303 1196 303 1196 238 1196 c 0,9,10
+ 195 1196 195 1196 195 1221 c 0,11,12
+ 195 1238 195 1238 221 1280 c 2,13,-1
+ 266 1364 l 2,14,15
+ 305 1437 305 1437 334 1457 c 128,-1,16
+ 363 1477 363 1477 422 1477 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: dieresis
+Encoding: 168 168 142
+Width: 682
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 22
+ 0
+ 12
+ 1
+ 0
+ 19
+ 1
+ 0
+ 45
+ 6
+ 0
+ 0
+ 7
+ 152
+ 16
+ 22
+ 10
+ 152
+ 9
+ 3
+ 10
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+147 1219 m 0,0,1
+ 104 1219 104 1219 69.5 1249 c 128,-1,2
+ 35 1279 35 1279 35 1331 c 0,3,4
+ 35 1381 35 1381 68 1412.5 c 128,-1,5
+ 101 1444 101 1444 147 1444 c 0,6,7
+ 192 1444 192 1444 226 1415.5 c 128,-1,8
+ 260 1387 260 1387 260 1331 c 0,9,10
+ 260 1279 260 1279 226 1249 c 128,-1,11
+ 192 1219 192 1219 147 1219 c 0,0,1
+537 1444 m 0,12,13
+ 565 1444 565 1444 592 1429 c 128,-1,14
+ 619 1414 619 1414 634 1387 c 128,-1,15
+ 649 1360 649 1360 649 1331 c 0,16,17
+ 649 1279 649 1279 616 1249 c 128,-1,18
+ 583 1219 583 1219 537 1219 c 0,19,20
+ 493 1219 493 1219 458.5 1249 c 128,-1,21
+ 424 1279 424 1279 424 1331 c 0,22,23
+ 424 1376 424 1376 458 1410 c 128,-1,24
+ 492 1444 492 1444 537 1444 c 0,12,13
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: notequal
+Encoding: 8800 8800 143
+Width: 1124
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 50
+ 0
+ 18
+ 1
+ 0
+ 16
+ 1
+ 0
+ 77
+ 2
+ 4
+ 0
+ 0
+ 14
+ 1
+ 0
+ 12
+ 1
+ 0
+ 77
+ 6
+ 8
+ 0
+ 2
+ 7
+ 10
+ 0
+ 0
+ 4
+ 1
+ 0
+ 18
+ 1
+ 19
+ 16
+ 15
+ 12
+ 11
+ 10
+ 9
+ 6
+ 5
+ 2
+ 1
+ 0
+ 12
+ 98
+ 8
+ 14
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MDAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+823 1124 m 1,0,-1
+ 924 1067 l 1,1,-1
+ 768 788 l 1,2,-1
+ 1106 788 l 1,3,-1
+ 1106 676 l 1,4,-1
+ 707 676 l 1,5,-1
+ 547 391 l 1,6,-1
+ 1106 391 l 1,7,-1
+ 1106 279 l 1,8,-1
+ 485 279 l 1,9,-1
+ 301 -51 l 1,10,-1
+ 201 6 l 1,11,-1
+ 352 279 l 1,12,-1
+ 31 279 l 1,13,-1
+ 31 391 l 1,14,-1
+ 416 391 l 1,15,-1
+ 573 676 l 1,16,-1
+ 31 676 l 1,17,-1
+ 31 788 l 1,18,-1
+ 637 788 l 1,19,-1
+ 823 1124 l 1,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: AE
+Encoding: 198 198 144
+Width: 2028
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 47
+ 0
+ 0
+ 0
+ 0
+ 13
+ 1
+ 24
+ 46
+ 18
+ 12
+ 9
+ 46
+ 26
+ 33
+ 10
+ 41
+ 48
+ 1
+ 10
+ 0
+ 0
+ 5
+ 1
+ 0
+ 12
+ 2
+ 2
+ 35
+ 46
+ 43
+ 9
+ 8
+ 4
+ 7
+ 50
+ 0
+ 26
+ 1
+ 0
+ 49
+ 1
+ 0
+ 131
+ 35
+ 46
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+924 352 m 1,0,-1
+ 397 352 l 1,1,-1
+ 307 145 l 2,2,3
+ 273 65 273 65 231.5 20 c 128,-1,4
+ 190 -25 190 -25 123 -25 c 0,5,6
+ 64 -25 64 -25 29 7.5 c 128,-1,7
+ -6 40 -6 40 -6 84 c 0,8,9
+ -6 114 -6 114 -1.5 135 c 128,-1,10
+ 3 156 3 156 8.5 168.5 c 128,-1,11
+ 14 181 14 181 33 221 c 2,12,-1
+ 524 1288 l 2,13,14
+ 566 1377 566 1377 583.5 1406 c 128,-1,15
+ 601 1435 601 1435 634 1450.5 c 128,-1,16
+ 667 1466 667 1466 733 1466 c 2,17,-1
+ 1794 1466 l 2,18,19
+ 1864 1466 1864 1466 1898.5 1434.5 c 128,-1,20
+ 1933 1403 1933 1403 1933 1352 c 0,21,22
+ 1933 1302 1933 1302 1899 1272.5 c 128,-1,23
+ 1865 1243 1865 1243 1794 1243 c 2,24,-1
+ 1210 1243 l 1,25,-1
+ 1210 877 l 1,26,-1
+ 1743 877 l 2,27,28
+ 1811 877 1811 877 1844.5 846 c 128,-1,29
+ 1878 815 1878 815 1878 764 c 256,30,31
+ 1878 713 1878 713 1844 683 c 128,-1,32
+ 1810 653 1810 653 1743 653 c 2,33,-1
+ 1210 653 l 1,34,-1
+ 1210 223 l 1,35,-1
+ 1815 223 l 2,36,37
+ 1887 223 1887 223 1922.5 195 c 128,-1,38
+ 1958 167 1958 167 1958 115 c 0,39,40
+ 1958 62 1958 62 1922.5 31 c 128,-1,41
+ 1887 0 1887 0 1815 0 c 2,42,-1
+ 1102 0 l 2,43,44
+ 1009 0 1009 0 966.5 41.5 c 128,-1,45
+ 924 83 924 83 924 174 c 2,46,-1
+ 924 352 l 1,0,-1
+494 588 m 1,47,-1
+ 924 588 l 1,48,-1
+ 924 1253 l 1,49,-1
+ 782 1253 l 1,50,-1
+ 494 588 l 1,47,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: Oslash
+Encoding: 216 216 145
+Width: 1622
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 78
+ 53
+ 52
+ 43
+ 42
+ 22
+ 1
+ 0
+ 7
+ 46
+ 55
+ 1
+ 16
+ 1
+ 0
+ 0
+ 0
+ 21
+ 13
+ 12
+ 3
+ 46
+ 41
+ 9
+ 12
+ 9
+ 0
+ 0
+ 0
+ 29
+ 1
+ 32
+ 31
+ 2
+ 55
+ 41
+ 36
+ 9
+ 8
+ 2
+ 7
+ 52
+ 42
+ 2
+ 59
+ 50
+ 1
+ 19
+ 1
+ 0
+ 43
+ 1
+ 0
+ 22
+ 21
+ 13
+ 12
+ 4
+ 128
+ 24
+ 59
+ 0
+ 53
+ 1
+ 0
+ 0
+ 4
+ 1
+ 32
+ 31
+ 1
+ 0
+ 4
+ 128
+ 50
+ 39
+ 0
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+190 215 m 2,0,-1
+ 225 252 l 1,1,2
+ 158 350 158 350 125 472 c 128,-1,3
+ 92 594 92 594 92 737 c 0,4,5
+ 92 906 92 906 140.5 1047 c 128,-1,6
+ 189 1188 189 1188 281 1287 c 128,-1,7
+ 373 1386 373 1386 505 1438.5 c 128,-1,8
+ 637 1491 637 1491 805 1491 c 0,9,10
+ 949 1491 949 1491 1062 1457.5 c 128,-1,11
+ 1175 1424 1175 1424 1268 1352 c 1,12,-1
+ 1294 1380 l 2,13,14
+ 1357 1446 1357 1446 1390.5 1469.5 c 128,-1,15
+ 1424 1493 1424 1493 1458 1493 c 0,16,17
+ 1490 1493 1490 1493 1510 1472 c 128,-1,18
+ 1530 1451 1530 1451 1530 1415 c 0,19,20
+ 1530 1355 1530 1355 1438 1260 c 2,21,-1
+ 1397 1217 l 1,22,23
+ 1528 1024 1528 1024 1528 735 c 0,24,25
+ 1528 565 1528 565 1482 426 c 128,-1,26
+ 1436 287 1436 287 1344 185 c 128,-1,27
+ 1252 83 1252 83 1118 29 c 128,-1,28
+ 984 -25 984 -25 811 -25 c 0,29,30
+ 527 -25 527 -25 352 115 c 1,31,-1
+ 330 88 l 2,32,33
+ 306 62 306 62 279.5 34.5 c 128,-1,34
+ 253 7 253 7 226.5 -9 c 128,-1,35
+ 200 -25 200 -25 166 -25 c 0,36,37
+ 134 -25 134 -25 113 -2 c 128,-1,38
+ 92 21 92 21 92 49 c 0,39,40
+ 92 89 92 89 115.5 126 c 128,-1,41
+ 139 163 139 163 190 215 c 2,0,-1
+436 473 m 1,42,-1
+ 1079 1155 l 1,43,44
+ 1032 1201 1032 1201 959.5 1228 c 128,-1,45
+ 887 1255 887 1255 809 1255 c 0,46,47
+ 684 1255 684 1255 589.5 1194.5 c 128,-1,48
+ 495 1134 495 1134 444 1016.5 c 128,-1,49
+ 393 899 393 899 393 737 c 0,50,51
+ 393 589 393 589 436 473 c 1,42,-1
+1184 991 m 1,52,-1
+ 543 313 l 1,53,54
+ 654 211 654 211 809 211 c 0,55,56
+ 923 211 923 211 1018.5 268 c 128,-1,57
+ 1114 325 1114 325 1170.5 444 c 128,-1,58
+ 1227 563 1227 563 1227 737 c 0,59,60
+ 1227 876 1227 876 1184 991 c 1,52,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: infinity
+Encoding: 8734 8734 146
+Width: 1460
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 32
+ 18
+ 1
+ 55
+ 1
+ 0
+ 13
+ 1
+ 0
+ 81
+ 48
+ 23
+ 0
+ 7
+ 63
+ 39
+ 32
+ 4
+ 0
+ 63
+ 59
+ 55
+ 51
+ 48
+ 44
+ 39
+ 36
+ 8
+ 93
+ 9
+ 27
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+738 608 m 1,0,1
+ 813 675 813 675 848.5 705 c 128,-1,2
+ 884 735 884 735 920.5 758 c 128,-1,3
+ 957 781 957 781 1002 801 c 0,4,5
+ 1074 833 1074 833 1145 828.5 c 128,-1,6
+ 1216 824 1216 824 1276 787.5 c 128,-1,7
+ 1336 751 1336 751 1373 694 c 128,-1,8
+ 1410 637 1410 637 1416 571 c 0,9,10
+ 1424 493 1424 493 1386.5 416.5 c 128,-1,11
+ 1349 340 1349 340 1276.5 293.5 c 128,-1,12
+ 1204 247 1204 247 1115 256 c 0,13,14
+ 1045 263 1045 263 981 290.5 c 128,-1,15
+ 917 318 917 318 872 351.5 c 128,-1,16
+ 827 385 827 385 784.5 427.5 c 128,-1,17
+ 742 470 742 470 738 473 c 1,18,19
+ 714 449 714 449 681.5 417 c 128,-1,20
+ 649 385 649 385 605 351.5 c 128,-1,21
+ 561 318 561 318 497 290.5 c 128,-1,22
+ 433 263 433 263 361 256 c 0,23,24
+ 272 247 272 247 199.5 293.5 c 128,-1,25
+ 127 340 127 340 89.5 416.5 c 128,-1,26
+ 52 493 52 493 60 571 c 0,27,28
+ 67 638 67 638 104 695 c 128,-1,29
+ 141 752 141 752 201 788 c 128,-1,30
+ 261 824 261 824 332 828.5 c 128,-1,31
+ 403 833 403 833 474 801 c 0,32,33
+ 519 781 519 781 555.5 758 c 128,-1,34
+ 592 735 592 735 627.5 705 c 128,-1,35
+ 663 675 663 675 738 608 c 1,0,1
+671 541 m 1,36,37
+ 583 616 583 616 529.5 653 c 128,-1,38
+ 476 690 476 690 427 707 c 0,39,40
+ 366 729 366 729 316.5 719.5 c 128,-1,41
+ 267 710 267 710 232 679 c 128,-1,42
+ 197 648 197 648 180 607.5 c 128,-1,43
+ 163 567 163 567 163 530 c 0,44,45
+ 164 474 164 474 200 428.5 c 128,-1,46
+ 236 383 236 383 291 364 c 128,-1,47
+ 346 345 346 345 400 358 c 0,48,49
+ 481 377 481 377 524 408.5 c 128,-1,50
+ 567 440 567 440 671 541 c 1,36,37
+806 541 m 1,51,52
+ 874 474 874 474 911 441.5 c 128,-1,53
+ 948 409 948 409 984 390 c 128,-1,54
+ 1020 371 1020 371 1076 358 c 0,55,56
+ 1131 345 1131 345 1186 364 c 128,-1,57
+ 1241 383 1241 383 1277 428.5 c 128,-1,58
+ 1313 474 1313 474 1314 530 c 0,59,60
+ 1316 579 1316 579 1284.5 632.5 c 128,-1,61
+ 1253 686 1253 686 1192.5 710.5 c 128,-1,62
+ 1132 735 1132 735 1049 707 c 0,63,64
+ 999 689 999 689 946 651.5 c 128,-1,65
+ 893 614 893 614 806 541 c 1,51,52
+EndSplineSet
+Validated: 33
+EndChar
+
+StartChar: plusminus
+Encoding: 177 177 147
+Width: 1194
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 37
+ 0
+ 8
+ 1
+ 0
+ 10
+ 1
+ 0
+ 36
+ 4
+ 2
+ 0
+ 1
+ 1
+ 0
+ 0
+ 0
+ 0
+ 15
+ 36
+ 13
+ 9
+ 8
+ 2
+ 7
+ 7
+ 0
+ 11
+ 1
+ 0
+ 1
+ 1
+ 0
+ 141
+ 7
+ 5
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+725 356 m 1,0,-1
+ 467 356 l 1,1,-1
+ 467 737 l 1,2,-1
+ 84 737 l 1,3,-1
+ 84 999 l 1,4,-1
+ 467 999 l 1,5,-1
+ 467 1380 l 1,6,-1
+ 725 1380 l 1,7,-1
+ 725 999 l 1,8,-1
+ 1110 999 l 1,9,-1
+ 1110 737 l 1,10,-1
+ 725 737 l 1,11,-1
+ 725 356 l 1,0,-1
+1110 0 m 1,12,-1
+ 84 0 l 1,13,-1
+ 84 262 l 1,14,-1
+ 1110 262 l 1,15,-1
+ 1110 0 l 1,12,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: lessequal
+Encoding: 8804 8804 148
+Width: 1124
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 25
+ 18
+ 6
+ 10
+ 10
+ 2
+ 77
+ 0
+ 9
+ 11
+ 2
+ 7
+ 0
+ 10
+ 7
+ 2
+ 0
+ 5
+ 1
+ 8
+ 1
+ 104
+ 3
+ 1
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+59 0 m 1,0,-1
+ 59 113 l 1,1,-1
+ 1077 113 l 1,2,-1
+ 1077 0 l 1,3,-1
+ 59 0 l 1,0,-1
+59 711 m 1,4,-1
+ 59 838 l 1,5,-1
+ 1077 1309 l 1,6,-1
+ 1077 1182 l 1,7,-1
+ 190 774 l 1,8,-1
+ 1077 367 l 1,9,-1
+ 1077 240 l 1,10,-1
+ 59 711 l 1,4,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: greaterequal
+Encoding: 8805 8805 149
+Width: 1124
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 25
+ 18
+ 10
+ 6
+ 10
+ 0
+ 77
+ 2
+ 9
+ 11
+ 2
+ 7
+ 0
+ 5
+ 1
+ 0
+ 10
+ 7
+ 2
+ 8
+ 1
+ 104
+ 1
+ 3
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1077 113 m 1,0,-1
+ 1077 0 l 1,1,-1
+ 59 0 l 1,2,-1
+ 59 113 l 1,3,-1
+ 1077 113 l 1,0,-1
+1077 838 m 1,4,-1
+ 1077 711 l 1,5,-1
+ 59 240 l 1,6,-1
+ 59 367 l 1,7,-1
+ 946 774 l 1,8,-1
+ 59 1182 l 1,9,-1
+ 59 1309 l 1,10,-1
+ 1077 838 l 1,4,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: yen
+Encoding: 165 165 150
+Width: 1280
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 46
+ 19
+ 1
+ 32
+ 1
+ 0
+ 37
+ 1
+ 0
+ 56
+ 7
+ 2
+ 0
+ 0
+ 0
+ 1
+ 0
+ 51
+ 1
+ 0
+ 56
+ 39
+ 44
+ 0
+ 2
+ 7
+ 48
+ 9
+ 25
+ 12
+ 15
+ 12
+ 32
+ 1
+ 45
+ 1
+ 8
+ 1
+ 50
+ 1
+ 19
+ 1
+ 137
+ 39
+ 2
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+287 444 m 2,0,-1
+ 512 444 l 1,1,-1
+ 512 588 l 1,2,-1
+ 287 588 l 2,3,4
+ 145 588 145 588 145 682 c 0,5,6
+ 145 774 145 774 287 774 c 2,7,-1
+ 414 774 l 1,8,-1
+ 115 1243 l 2,9,10
+ 79 1299 79 1299 68 1323 c 128,-1,11
+ 57 1347 57 1347 57 1376 c 0,12,13
+ 57 1428 57 1428 88.5 1459.5 c 128,-1,14
+ 120 1491 120 1491 170 1491 c 0,15,16
+ 221 1491 221 1491 252.5 1460 c 128,-1,17
+ 284 1429 284 1429 326 1360 c 2,18,-1
+ 649 854 l 1,19,-1
+ 938 1331 l 2,20,21
+ 954 1359 954 1359 972 1389.5 c 128,-1,22
+ 990 1420 990 1420 1007 1441.5 c 128,-1,23
+ 1024 1463 1024 1463 1049.5 1477 c 128,-1,24
+ 1075 1491 1075 1491 1110 1491 c 0,25,26
+ 1160 1491 1160 1491 1191.5 1460.5 c 128,-1,27
+ 1223 1430 1223 1430 1223 1386 c 0,28,29
+ 1223 1351 1223 1351 1210.5 1322 c 128,-1,30
+ 1198 1293 1198 1293 1171 1249 c 2,31,-1
+ 883 774 l 1,32,-1
+ 1010 774 l 2,33,34
+ 1151 774 1151 774 1151 682 c 0,35,36
+ 1151 588 1151 588 1010 588 c 2,37,-1
+ 784 588 l 1,38,-1
+ 784 444 l 1,39,-1
+ 1010 444 l 2,40,41
+ 1151 444 1151 444 1151 350 c 0,42,43
+ 1151 258 1151 258 1010 258 c 2,44,-1
+ 784 258 l 1,45,-1
+ 784 178 l 2,46,47
+ 784 -25 784 -25 649 -25 c 0,48,49
+ 512 -25 512 -25 512 178 c 2,50,-1
+ 512 258 l 1,51,-1
+ 287 258 l 2,52,53
+ 145 258 145 258 145 350 c 0,54,55
+ 145 444 145 444 287 444 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: mu
+Encoding: 181 181 151
+Width: 1260
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 36
+ 0
+ 0
+ 0
+ 0
+ 7
+ 1
+ 2
+ 17
+ 44
+ 4
+ 9
+ 8
+ 7
+ 22
+ 10
+ 11
+ 10
+ 9
+ 7
+ 0
+ 9
+ 0
+ 1
+ 132
+ 23
+ 20
+ 13
+ 0
+ 11
+ 1
+ 135
+ 7
+ 10
+ 15
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+856 0 m 1,0,-1
+ 856 129 l 1,1,2
+ 814 49 814 49 757.5 11 c 128,-1,3
+ 701 -27 701 -27 643 -27 c 0,4,5
+ 561 -27 561 -27 515 14.5 c 128,-1,6
+ 469 56 469 56 430 129 c 1,7,-1
+ 430 -408 l 1,8,-1
+ 152 -408 l 1,9,-1
+ 152 1061 l 1,10,-1
+ 430 1061 l 1,11,-1
+ 430 582 l 2,12,13
+ 430 520 430 520 446 373 c 0,14,15
+ 454 307 454 307 505.5 254 c 128,-1,16
+ 557 201 557 201 629 201 c 0,17,18
+ 723 201 723 201 778.5 279.5 c 128,-1,19
+ 834 358 834 358 834 516 c 2,20,-1
+ 834 1061 l 1,21,-1
+ 1118 1061 l 1,22,-1
+ 1118 0 l 1,23,-1
+ 856 0 l 1,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: partialdiff
+Encoding: 8706 8706 152
+Width: 1012
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 45
+ 34
+ 1
+ 0
+ 84
+ 31
+ 50
+ 14
+ 7
+ 62
+ 42
+ 18
+ 4
+ 0
+ 64
+ 62
+ 59
+ 52
+ 50
+ 42
+ 39
+ 34
+ 31
+ 18
+ 4
+ 11
+ 36
+ 56
+ 1
+ 47
+ 1
+ 0
+ 166
+ 11
+ 36
+ 14
+ 28
+ 1
+ 0
+ 3
+ 161
+ 56
+ 25
+ 13
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+220 1366 m 1,0,-1
+ 140 1468 l 1,1,2
+ 216 1502 216 1502 317 1520 c 128,-1,3
+ 418 1538 418 1538 511 1516 c 0,4,5
+ 613 1492 613 1492 699.5 1427 c 128,-1,6
+ 786 1362 786 1362 855 1241 c 0,7,8
+ 897 1168 897 1168 919 1077 c 128,-1,9
+ 941 986 941 986 947 916.5 c 128,-1,10
+ 953 847 953 847 953 805 c 0,11,12
+ 953 758 953 758 943 662 c 128,-1,13
+ 933 566 933 566 908.5 456.5 c 128,-1,14
+ 884 347 884 347 847 268 c 0,15,16
+ 799 166 799 166 755.5 108 c 128,-1,17
+ 712 50 712 50 634 6 c 0,18,19
+ 532 -50 532 -50 425.5 -42.5 c 128,-1,20
+ 319 -35 319 -35 234 23 c 0,21,22
+ 189 54 189 54 154 93.5 c 128,-1,23
+ 119 133 119 133 93.5 190 c 128,-1,24
+ 68 247 68 247 62 319 c 0,25,26
+ 53 430 53 430 89 523 c 128,-1,27
+ 125 616 125 616 175 678 c 0,28,29
+ 233 749 233 749 303 787.5 c 128,-1,30
+ 373 826 373 826 466 823 c 0,31,32
+ 554 820 554 820 613 792 c 128,-1,33
+ 672 764 672 764 773 684 c 1,34,35
+ 791 783 791 783 795 922 c 0,36,37
+ 798 987 798 987 775.5 1090.5 c 128,-1,38
+ 753 1194 753 1194 730 1247 c 0,39,40
+ 706 1306 706 1306 645.5 1364.5 c 128,-1,41
+ 585 1423 585 1423 501 1430 c 0,42,43
+ 445 1435 445 1435 411.5 1433 c 128,-1,44
+ 378 1431 378 1431 355 1424 c 128,-1,45
+ 332 1417 332 1417 291 1398 c 128,-1,46
+ 250 1379 250 1379 220 1366 c 1,0,-1
+757 612 m 1,47,48
+ 698 679 698 679 656 711.5 c 128,-1,49
+ 614 744 614 744 535 743 c 0,50,51
+ 418 740 418 740 339 633 c 0,52,53
+ 298 575 298 575 276.5 522.5 c 128,-1,54
+ 255 470 255 470 245.5 415.5 c 128,-1,55
+ 236 361 236 361 236 303 c 0,56,57
+ 236 229 236 229 253.5 158.5 c 128,-1,58
+ 271 88 271 88 331 47 c 0,59,60
+ 375 19 375 19 414.5 18 c 128,-1,61
+ 454 17 454 17 501 37 c 0,62,63
+ 604 82 604 82 666 227 c 0,64,65
+ 702 315 702 315 723.5 413.5 c 128,-1,66
+ 745 512 745 512 757 612 c 1,47,48
+EndSplineSet
+Validated: 33
+EndChar
+
+StartChar: summation
+Encoding: 8721 8721 153
+Width: 1460
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 39
+ 27
+ 15
+ 2
+ 3
+ 7
+ 10
+ 1
+ 28
+ 1
+ 0
+ 83
+ 31
+ 7
+ 15
+ 26
+ 18
+ 2
+ 0
+ 51
+ 10
+ 22
+ 14
+ 2
+ 7
+ 28
+ 27
+ 14
+ 9
+ 8
+ 7
+ 2
+ 1
+ 0
+ 9
+ 90
+ 15
+ 26
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1264 1526 m 1,0,-1
+ 1276 1200 l 1,1,-1
+ 1235 1200 l 1,2,3
+ 1203 1302 1203 1302 1184.5 1339 c 128,-1,4
+ 1166 1376 1166 1376 1105.5 1405 c 128,-1,5
+ 1045 1434 1045 1434 922 1434 c 2,6,-1
+ 383 1434 l 1,7,-1
+ 942 700 l 1,8,-1
+ 340 6 l 1,9,-1
+ 1100 6 l 2,10,11
+ 1183 6 1183 6 1228 25.5 c 128,-1,12
+ 1273 45 1273 45 1305 91.5 c 128,-1,13
+ 1337 138 1337 138 1376 238 c 1,14,-1
+ 1423 238 l 1,15,16
+ 1378 53 1378 53 1367 -7 c 128,-1,17
+ 1356 -67 1356 -67 1335 -221 c 1,18,19
+ 1296 -214 1296 -214 1255 -206.5 c 128,-1,20
+ 1214 -199 1214 -199 1178 -199 c 2,21,-1
+ 147 -199 l 2,22,23
+ 133 -199 133 -199 110.5 -200.5 c 128,-1,24
+ 88 -202 88 -202 65.5 -203.5 c 128,-1,25
+ 43 -205 43 -205 29 -205 c 1,26,-1
+ 743 610 l 1,27,-1
+ 33 1540 l 1,28,29
+ 65 1538 65 1538 138 1532 c 128,-1,30
+ 211 1526 211 1526 246 1526 c 2,31,-1
+ 1264 1526 l 1,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: product
+Encoding: 8719 8719 154
+Width: 1686
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 54
+ 0
+ 1
+ 13
+ 5
+ 1
+ 77
+ 29
+ 13
+ 10
+ 0
+ 21
+ 18
+ 8
+ 3
+ 0
+ 20
+ 1
+ 0
+ 86
+ 5
+ 7
+ 0
+ 2
+ 7
+ 30
+ 12
+ 27
+ 12
+ 30
+ 6
+ 2
+ 0
+ 8
+ 1
+ 0
+ 0
+ 151
+ 1
+ 12
+ 0
+ 19
+ 1
+ 0
+ 28
+ 21
+ 2
+ 0
+ 0
+ 151
+ 14
+ 25
+ 0
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1446 1288 m 2,0,-1
+ 1446 6 l 2,1,2
+ 1446 -63 1446 -63 1469.5 -99 c 128,-1,3
+ 1493 -135 1493 -135 1536.5 -147.5 c 128,-1,4
+ 1580 -160 1580 -160 1645 -160 c 1,5,-1
+ 1645 -207 l 1,6,-1
+ 1018 -207 l 1,7,-1
+ 1018 -160 l 1,8,9
+ 1118 -160 1118 -160 1166 -127 c 128,-1,10
+ 1214 -94 1214 -94 1214 6 c 2,11,-1
+ 1214 1425 l 1,12,-1
+ 481 1425 l 1,13,-1
+ 481 6 l 2,14,15
+ 481 -63 481 -63 504.5 -99 c 128,-1,16
+ 528 -135 528 -135 571.5 -147.5 c 128,-1,17
+ 615 -160 615 -160 680 -160 c 1,18,-1
+ 680 -207 l 1,19,-1
+ 51 -207 l 1,20,-1
+ 51 -160 l 1,21,22
+ 153 -160 153 -160 201.5 -127 c 128,-1,23
+ 250 -94 250 -94 250 6 c 2,24,-1
+ 250 1288 l 2,25,26
+ 250 1491 250 1491 55 1491 c 1,27,-1
+ 55 1538 l 1,28,-1
+ 1638 1538 l 1,29,-1
+ 1638 1491 l 1,30,31
+ 1446 1491 1446 1491 1446 1288 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: pi
+Encoding: 960 960 155
+Width: 1124
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 66
+ 0
+ 0
+ 27
+ 1
+ 35
+ 1
+ 2
+ 30
+ 1
+ 60
+ 34
+ 22
+ 0
+ 7
+ 56
+ 9
+ 49
+ 44
+ 8
+ 9
+ 53
+ 41
+ 2
+ 48
+ 36
+ 61
+ 58
+ 2
+ 0
+ 1
+ 30
+ 20
+ 8
+ 3
+ 21
+ 26
+ 3
+ 1
+ 35
+ 1
+ 175
+ 49
+ 48
+ 13
+ 56
+ 38
+ 2
+ 172
+ 36
+ 0
+ 13
+ 5
+ 1
+ 172
+ 1
+ 21
+ 13
+ 11
+ 1
+ 0
+ 176
+ 26
+ 27
+ 15
+ 4
+ 7
+LOOPCALL
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MIAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+686 821 m 1,0,-1
+ 455 821 l 1,1,2
+ 438 620 438 620 422 491.5 c 128,-1,3
+ 406 363 406 363 391 270.5 c 128,-1,4
+ 376 178 376 178 360 102 c 0,5,6
+ 347 43 347 43 322 9.5 c 128,-1,7
+ 297 -24 297 -24 248 -37 c 0,8,9
+ 208 -47 208 -47 168.5 -21 c 128,-1,10
+ 129 5 129 5 121 41 c 0,11,12
+ 115 68 115 68 118 86.5 c 128,-1,13
+ 121 105 121 105 129 121 c 128,-1,14
+ 137 137 137 137 147 150 c 128,-1,15
+ 157 163 157 163 168 176 c 0,16,17
+ 171 180 171 180 202.5 217 c 128,-1,18
+ 234 254 234 254 250 284.5 c 128,-1,19
+ 266 315 266 315 270 352 c 2,20,-1
+ 330 821 l 1,21,-1
+ 233 821 l 2,22,23
+ 192 821 192 821 155 801.5 c 128,-1,24
+ 118 782 118 782 98 756 c 2,25,-1
+ 55 692 l 1,26,-1
+ 20 692 l 1,27,28
+ 34 731 34 731 55 785.5 c 128,-1,29
+ 76 840 76 840 113 891 c 0,30,31
+ 142 934 142 934 191 965.5 c 128,-1,32
+ 240 997 240 997 305 997 c 2,33,-1
+ 1069 997 l 1,34,-1
+ 1069 821 l 1,35,-1
+ 811 821 l 1,36,37
+ 786 582 786 582 786 340 c 0,38,39
+ 786 296 786 296 801 254 c 128,-1,40
+ 816 212 816 212 838 190 c 0,41,42
+ 866 164 866 164 906.5 156.5 c 128,-1,43
+ 947 149 947 149 989 182 c 0,44,45
+ 1012 200 1012 200 1022.5 223 c 128,-1,46
+ 1033 246 1033 246 1036 267 c 128,-1,47
+ 1039 288 1039 288 1042 309 c 1,48,-1
+ 1085 309 l 1,49,50
+ 1084 226 1084 226 1060 159.5 c 128,-1,51
+ 1036 93 1036 93 1003 52.5 c 128,-1,52
+ 970 12 970 12 938 -6 c 0,53,54
+ 902 -28 902 -28 854 -32.5 c 128,-1,55
+ 806 -37 806 -37 766 -10 c 0,56,57
+ 700 38 700 38 666 141 c 0,58,59
+ 647 201 647 201 644.5 299.5 c 128,-1,60
+ 642 398 642 398 651 492 c 2,61,-1
+ 686 821 l 1,0,-1
+EndSplineSet
+Validated: 33
+EndChar
+
+StartChar: integral
+Encoding: 8747 8747 156
+Width: 561
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 20
+ 35
+ 17
+ 14
+ 9
+ 8
+ 42
+ 1
+ 0
+ 0
+ 0
+ 50
+ 32
+ 21
+ 3
+ 4
+ 170
+ 0
+ 27
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MIAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+395 999 m 2,0,-1
+ 393 557 l 2,1,2
+ 391 193 391 193 323 -43 c 0,3,4
+ 302 -119 302 -119 264 -168 c 0,5,6
+ 247 -190 247 -190 188.5 -210 c 128,-1,7
+ 130 -230 130 -230 84 -209 c 0,8,9
+ 62 -198 62 -198 42.5 -173 c 128,-1,10
+ 23 -148 23 -148 16 -129 c 0,11,12
+ 4 -94 4 -94 16 -64 c 128,-1,13
+ 28 -34 28 -34 65 -16 c 0,14,15
+ 99 1 99 1 125.5 -11 c 128,-1,16
+ 152 -23 152 -23 182 -57 c 0,17,18
+ 211 -87 211 -87 230.5 -61 c 128,-1,19
+ 250 -35 250 -35 258 21.5 c 128,-1,20
+ 266 78 266 78 264 152 c 0,21,22
+ 262 228 262 228 260 293 c 128,-1,23
+ 258 358 258 358 256 412.5 c 128,-1,24
+ 254 467 254 467 253 575.5 c 128,-1,25
+ 252 684 252 684 252 795 c 2,26,-1
+ 252 1090 l 2,27,28
+ 252 1180 252 1180 254 1282 c 128,-1,29
+ 256 1384 256 1384 261.5 1463.5 c 128,-1,30
+ 267 1543 267 1543 277.5 1603 c 128,-1,31
+ 288 1663 288 1663 305 1724 c 0,32,33
+ 315 1758 315 1758 342.5 1799.5 c 128,-1,34
+ 370 1841 370 1841 397 1858 c 0,35,36
+ 423 1874 423 1874 453.5 1875.5 c 128,-1,37
+ 484 1877 484 1877 513 1867 c 128,-1,38
+ 542 1857 542 1857 557 1847 c 0,39,40
+ 584 1830 584 1830 597.5 1787 c 128,-1,41
+ 611 1744 611 1744 584 1710 c 0,42,43
+ 569 1692 569 1692 541 1680.5 c 128,-1,44
+ 513 1669 513 1669 485 1672 c 128,-1,45
+ 457 1675 457 1675 438 1696 c 0,46,47
+ 416 1718 416 1718 397.5 1720 c 128,-1,48
+ 379 1722 379 1722 368.5 1708.5 c 128,-1,49
+ 358 1695 358 1695 356 1675 c 0,50,51
+ 355 1649 355 1649 358 1612.5 c 128,-1,52
+ 361 1576 361 1576 372 1439.5 c 128,-1,53
+ 383 1303 383 1303 389 1196.5 c 128,-1,54
+ 395 1090 395 1090 395 999 c 2,0,-1
+EndSplineSet
+Validated: 33
+EndChar
+
+StartChar: ordfeminine
+Encoding: 170 170 157
+Width: 768
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 53
+ 41
+ 31
+ 11
+ 3
+ 14
+ 49
+ 1
+ 0
+ 0
+ 18
+ 1
+ 0
+ 0
+ 14
+ 70
+ 25
+ 12
+ 9
+ 0
+ 0
+ 37
+ 1
+ 0
+ 0
+ 1
+ 73
+ 49
+ 3
+ 0
+ 2
+ 7
+ 42
+ 34
+ 28
+ 2
+ 0
+ 11
+ 1
+ 0
+ 0
+ 1
+ 156
+ 31
+ 42
+ 0
+ 21
+ 1
+ 154
+ 46
+ 6
+ 13
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+524 895 m 1,0,1
+ 453 850 453 850 399 829.5 c 128,-1,2
+ 345 809 345 809 270 809 c 0,3,4
+ 165 809 165 809 100 866 c 128,-1,5
+ 35 923 35 923 35 1004 c 0,6,7
+ 35 1074 35 1074 70.5 1115.5 c 128,-1,8
+ 106 1157 106 1157 166 1177 c 128,-1,9
+ 226 1197 226 1197 347.5 1221 c 128,-1,10
+ 469 1245 469 1245 502 1253 c 1,11,12
+ 498 1305 498 1305 476.5 1328.5 c 128,-1,13
+ 455 1352 455 1352 385 1352 c 0,14,15
+ 305 1352 305 1352 282.5 1334.5 c 128,-1,16
+ 260 1317 260 1317 227.5 1272 c 128,-1,17
+ 195 1227 195 1227 152 1227 c 0,18,19
+ 118 1227 118 1227 92 1248 c 128,-1,20
+ 66 1269 66 1269 66 1303 c 0,21,22
+ 66 1349 66 1349 100.5 1392.5 c 128,-1,23
+ 135 1436 135 1436 206.5 1463.5 c 128,-1,24
+ 278 1491 278 1491 385 1491 c 0,25,26
+ 560 1491 560 1491 629 1431 c 128,-1,27
+ 698 1371 698 1371 698 1229 c 0,28,29
+ 698 1166 698 1166 697.5 1128 c 128,-1,30
+ 697 1090 697 1090 696 1044 c 0,31,32
+ 696 1001 696 1001 712.5 953.5 c 128,-1,33
+ 729 906 729 906 729 887 c 0,34,35
+ 729 854 729 854 700.5 830.5 c 128,-1,36
+ 672 807 672 807 635 807 c 0,37,38
+ 615 807 615 807 595 819 c 128,-1,39
+ 575 831 575 831 558.5 849.5 c 128,-1,40
+ 542 868 542 868 524 895 c 1,0,1
+504 1114 m 2,41,-1
+ 504 1126 l 1,42,43
+ 494 1124 494 1124 391.5 1101 c 128,-1,44
+ 289 1078 289 1078 262.5 1063 c 128,-1,45
+ 236 1048 236 1048 236 1016 c 256,46,47
+ 236 984 236 984 262 962 c 128,-1,48
+ 288 940 288 940 332 940 c 0,49,50
+ 412 940 412 940 458 983.5 c 128,-1,51
+ 504 1027 504 1027 504 1114 c 2,41,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: ordmasculine
+Encoding: 186 186 158
+Width: 788
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 26
+ 0
+ 1
+ 18
+ 24
+ 1
+ 18
+ 66
+ 11
+ 12
+ 12
+ 66
+ 24
+ 4
+ 10
+ 2
+ 7
+ 154
+ 0
+ 15
+ 10
+ 154
+ 21
+ 7
+ 10
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+756 1149 m 256,0,1
+ 756 1048 756 1048 712 971.5 c 128,-1,2
+ 668 895 668 895 587 852 c 128,-1,3
+ 506 809 506 809 395 809 c 0,4,5
+ 231 809 231 809 133 903.5 c 128,-1,6
+ 35 998 35 998 35 1149 c 0,7,8
+ 35 1250 35 1250 79 1328 c 128,-1,9
+ 123 1406 123 1406 205 1449.5 c 128,-1,10
+ 287 1493 287 1493 395 1493 c 256,11,12
+ 503 1493 503 1493 585 1449.5 c 128,-1,13
+ 667 1406 667 1406 711.5 1328 c 128,-1,14
+ 756 1250 756 1250 756 1149 c 256,0,1
+555 1149 m 0,15,16
+ 555 1241 555 1241 512.5 1292 c 128,-1,17
+ 470 1343 470 1343 395 1343 c 0,18,19
+ 321 1343 321 1343 278.5 1292 c 128,-1,20
+ 236 1241 236 1241 236 1149 c 0,21,22
+ 236 1058 236 1058 278 1008 c 128,-1,23
+ 320 958 320 958 395 958 c 0,24,25
+ 471 958 471 958 513 1008 c 128,-1,26
+ 555 1058 555 1058 555 1149 c 0,15,16
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: Omega
+Encoding: 8486 8486 159
+Width: 1573
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 68
+ 58
+ 54
+ 45
+ 36
+ 33
+ 26
+ 20
+ 13
+ 9
+ 0
+ 10
+ 56
+ 8
+ 1
+ 85
+ 23
+ 56
+ 10
+ 42
+ 4
+ 2
+ 38
+ 1
+ 0
+ 44
+ 1
+ 0
+ 8
+ 50
+ 2
+ 9
+ 8
+ 2
+ 7
+ 29
+ 10
+ 17
+ 10
+ 54
+ 50
+ 45
+ 41
+ 37
+ 36
+ 33
+ 29
+ 26
+ 9
+ 120
+ 43
+ 44
+ 13
+ 62
+ 58
+ 20
+ 17
+ 13
+ 9
+ 8
+ 4
+ 0
+ 9
+ 120
+ 1
+ 3
+ 13
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+641 311 m 1,0,-1
+ 674 0 l 1,1,-1
+ 70 0 l 1,2,-1
+ 70 332 l 1,3,-1
+ 100 332 l 1,4,5
+ 120 254 120 254 145.5 230.5 c 128,-1,6
+ 171 207 171 207 236 207 c 2,7,-1
+ 559 207 l 1,8,-1
+ 555 264 l 1,9,10
+ 466 291 466 291 409.5 317.5 c 128,-1,11
+ 353 344 353 344 303 386 c 128,-1,12
+ 253 428 253 428 213 487 c 0,13,14
+ 144 590 144 590 122.5 699.5 c 128,-1,15
+ 101 809 101 809 118.5 911.5 c 128,-1,16
+ 136 1014 136 1014 180 1092 c 0,17,18
+ 232 1187 232 1187 286.5 1232 c 128,-1,19
+ 341 1277 341 1277 414 1319 c 0,20,21
+ 483 1360 483 1360 583.5 1384.5 c 128,-1,22
+ 684 1409 684 1409 788 1409 c 0,23,24
+ 893 1409 893 1409 993.5 1384.5 c 128,-1,25
+ 1094 1360 1094 1360 1163 1319 c 0,26,27
+ 1236 1277 1236 1277 1290 1233 c 128,-1,28
+ 1344 1189 1344 1189 1397 1092 c 0,29,30
+ 1441 1014 1441 1014 1458.5 911.5 c 128,-1,31
+ 1476 809 1476 809 1454.5 699.5 c 128,-1,32
+ 1433 590 1433 590 1364 487 c 0,33,34
+ 1304 400 1304 400 1226.5 351.5 c 128,-1,35
+ 1149 303 1149 303 1022 264 c 1,36,-1
+ 1018 207 l 1,37,-1
+ 1341 207 l 2,38,39
+ 1406 207 1406 207 1432.5 231.5 c 128,-1,40
+ 1459 256 1459 256 1477 332 c 1,41,-1
+ 1507 332 l 1,42,-1
+ 1507 0 l 1,43,-1
+ 903 0 l 1,44,-1
+ 936 311 l 1,45,46
+ 961 322 961 322 991.5 335.5 c 128,-1,47
+ 1022 349 1022 349 1053 371 c 128,-1,48
+ 1084 393 1084 393 1117 436.5 c 128,-1,49
+ 1150 480 1150 480 1178 545 c 0,50,51
+ 1215 631 1215 631 1225.5 760.5 c 128,-1,52
+ 1236 890 1236 890 1203 1021.5 c 128,-1,53
+ 1170 1153 1170 1153 1085 1237 c 0,54,55
+ 979 1343 979 1343 788 1343 c 256,56,57
+ 597 1343 597 1343 492 1237 c 0,58,59
+ 407 1153 407 1153 374 1021.5 c 128,-1,60
+ 341 890 341 890 351.5 760.5 c 128,-1,61
+ 362 631 362 631 399 545 c 0,62,63
+ 427 480 427 480 459.5 437 c 128,-1,64
+ 492 394 492 394 524 371 c 128,-1,65
+ 556 348 556 348 585 335 c 128,-1,66
+ 614 322 614 322 641 311 c 1,0,-1
+EndSplineSet
+Validated: 33
+EndChar
+
+StartChar: ae
+Encoding: 230 230 160
+Width: 1898
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 91
+ 38
+ 1
+ 42
+ 61
+ 79
+ 68
+ 15
+ 3
+ 7
+ 76
+ 2
+ 1
+ 0
+ 54
+ 1
+ 0
+ 64
+ 1
+ 57
+ 1
+ 42
+ 54
+ 0
+ 10
+ 9
+ 47
+ 1
+ 0
+ 18
+ 1
+ 0
+ 69
+ 36
+ 2
+ 65
+ 61
+ 7
+ 0
+ 12
+ 1
+ 0
+ 0
+ 25
+ 1
+ 29
+ 1
+ 76
+ 60
+ 31
+ 9
+ 8
+ 3
+ 7
+ 0
+ 1
+ 61
+ 8
+ 36
+ 1
+ 39
+ 73
+ 2
+ 1
+ 20
+ 15
+ 2
+ 141
+ 5
+ 61
+ 13
+ 0
+ 60
+ 1
+ 0
+ 69
+ 1
+ 57
+ 29
+ 2
+ 141
+ 8
+ 39
+ 0
+ 50
+ 1
+ 136
+ 73
+ 34
+ 13
+ 3
+ 7
+LOOPCALL
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1288 1087 m 0,0,1
+ 1452 1087 1452 1087 1566.5 1026 c 128,-1,2
+ 1681 965 1681 965 1753 836 c 0,3,4
+ 1810 734 1810 734 1810 629 c 0,5,6
+ 1810 465 1810 465 1628 465 c 2,7,-1
+ 1061 465 l 1,8,9
+ 1064 368 1064 368 1097 300 c 128,-1,10
+ 1130 232 1130 232 1188 196 c 128,-1,11
+ 1246 160 1246 160 1327 160 c 0,12,13
+ 1401 160 1401 160 1471 190.5 c 128,-1,14
+ 1541 221 1541 221 1575 264 c 0,15,16
+ 1624 325 1624 325 1650.5 343.5 c 128,-1,17
+ 1677 362 1677 362 1708 362 c 0,18,19
+ 1800 362 1800 362 1800 254 c 0,20,21
+ 1800 231 1800 231 1775 184.5 c 128,-1,22
+ 1750 138 1750 138 1694.5 90 c 128,-1,23
+ 1639 42 1639 42 1548 8.5 c 128,-1,24
+ 1457 -25 1457 -25 1333 -25 c 0,25,26
+ 1231 -25 1231 -25 1152 -7 c 128,-1,27
+ 1073 11 1073 11 1013 48.5 c 128,-1,28
+ 953 86 953 86 903 147 c 1,29,30
+ 696 -25 696 -25 453 -25 c 0,31,32
+ 279 -25 279 -25 182.5 62.5 c 128,-1,33
+ 86 150 86 150 86 279 c 0,34,35
+ 86 526 86 526 399 590 c 0,36,37
+ 753 661 753 661 803 686 c 1,38,-1
+ 803 698 l 2,39,40
+ 803 805 803 805 766 851 c 128,-1,41
+ 729 897 729 897 598 897 c 0,42,43
+ 498 897 498 897 450 866.5 c 128,-1,44
+ 402 836 402 836 367 773.5 c 128,-1,45
+ 332 711 332 711 313 689.5 c 128,-1,46
+ 294 668 294 668 236 668 c 0,47,48
+ 186 668 186 668 156.5 697.5 c 128,-1,49
+ 127 727 127 727 127 776 c 0,50,51
+ 127 858 127 858 179.5 929.5 c 128,-1,52
+ 232 1001 232 1001 338.5 1044 c 128,-1,53
+ 445 1087 445 1087 598 1087 c 0,54,55
+ 730 1087 730 1087 813.5 1061 c 128,-1,56
+ 897 1035 897 1035 963 969 c 1,57,58
+ 1041 1031 1041 1031 1116.5 1059 c 128,-1,59
+ 1192 1087 1192 1087 1288 1087 c 0,0,1
+1061 621 m 1,60,-1
+ 1552 621 l 1,61,62
+ 1543 758 1543 758 1479 827.5 c 128,-1,63
+ 1415 897 1415 897 1309 897 c 0,64,65
+ 1198 897 1198 897 1129.5 816.5 c 128,-1,66
+ 1061 736 1061 736 1061 627 c 2,67,-1
+ 1061 621 l 1,60,-1
+803 449 m 2,68,-1
+ 803 522 l 1,69,70
+ 754 507 754 507 610 474.5 c 128,-1,71
+ 466 442 466 442 413 408 c 128,-1,72
+ 360 374 360 374 360 301 c 0,73,74
+ 360 239 360 239 407.5 195.5 c 128,-1,75
+ 455 152 455 152 537 152 c 0,76,77
+ 612 152 612 152 676 187.5 c 128,-1,78
+ 740 223 740 223 770 279 c 0,79,80
+ 793 319 793 319 798 353 c 128,-1,81
+ 803 387 803 387 803 449 c 2,68,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: oslash
+Encoding: 248 248 161
+Width: 1237
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 74
+ 51
+ 50
+ 43
+ 22
+ 1
+ 5
+ 53
+ 45
+ 1
+ 36
+ 1
+ 0
+ 42
+ 1
+ 0
+ 33
+ 32
+ 0
+ 3
+ 53
+ 52
+ 29
+ 10
+ 9
+ 0
+ 0
+ 15
+ 1
+ 0
+ 11
+ 1
+ 45
+ 52
+ 8
+ 9
+ 8
+ 2
+ 7
+ 50
+ 42
+ 2
+ 48
+ 57
+ 1
+ 39
+ 1
+ 0
+ 51
+ 1
+ 0
+ 33
+ 32
+ 1
+ 0
+ 4
+ 136
+ 3
+ 48
+ 0
+ 43
+ 1
+ 0
+ 18
+ 1
+ 0
+ 22
+ 11
+ 2
+ 136
+ 57
+ 24
+ 0
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1116 926 m 2,0,-1
+ 1065 874 l 1,1,2
+ 1163 725 1163 725 1163 530 c 0,3,4
+ 1163 407 1163 407 1125.5 305.5 c 128,-1,5
+ 1088 204 1088 204 1015.5 129 c 128,-1,6
+ 943 54 943 54 842.5 14.5 c 128,-1,7
+ 742 -25 742 -25 618 -25 c 0,8,9
+ 519 -25 519 -25 428.5 4 c 128,-1,10
+ 338 33 338 33 270 84 c 1,11,-1
+ 233 47 l 2,12,13
+ 189 3 189 3 168 -15 c 128,-1,14
+ 147 -33 147 -33 127 -33 c 0,15,16
+ 97 -33 97 -33 77 -14 c 128,-1,17
+ 57 5 57 5 57 31 c 0,18,19
+ 57 61 57 61 72 83 c 128,-1,20
+ 87 105 87 105 127 145 c 2,21,-1
+ 172 190 l 1,22,23
+ 76 336 76 336 76 530 c 0,24,25
+ 76 654 76 654 114 757 c 128,-1,26
+ 152 860 152 860 223 933 c 128,-1,27
+ 294 1006 294 1006 395 1045.5 c 128,-1,28
+ 496 1085 496 1085 618 1085 c 0,29,30
+ 720 1085 720 1085 809 1058 c 128,-1,31
+ 898 1031 898 1031 967 979 c 1,32,-1
+ 1016 1030 l 2,33,34
+ 1048 1062 1048 1062 1068.5 1077 c 128,-1,35
+ 1089 1092 1089 1092 1116 1092 c 0,36,37
+ 1141 1092 1141 1092 1160.5 1073.5 c 128,-1,38
+ 1180 1055 1180 1055 1180 1024 c 0,39,40
+ 1180 999 1180 999 1164.5 978 c 128,-1,41
+ 1149 957 1149 957 1116 926 c 2,0,-1
+868 680 m 1,42,-1
+ 440 252 l 1,43,44
+ 511 178 511 178 618 178 c 0,45,46
+ 742 178 742 178 815.5 271.5 c 128,-1,47
+ 889 365 889 365 889 530 c 0,48,49
+ 889 609 889 609 868 680 c 1,42,-1
+369 385 m 1,50,-1
+ 797 811 l 1,51,52
+ 725 883 725 883 618 883 c 0,53,54
+ 538 883 538 883 477 841.5 c 128,-1,55
+ 416 800 416 800 383 719 c 128,-1,56
+ 350 638 350 638 350 530 c 0,57,58
+ 350 454 350 454 369 385 c 1,50,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: questiondown
+Encoding: 191 191 162
+Width: 1174
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 39
+ 50
+ 31
+ 43
+ 10
+ 12
+ 0
+ 0
+ 0
+ 0
+ 40
+ 37
+ 33
+ 3
+ 19
+ 15
+ 5
+ 7
+ 8
+ 2
+ 7
+ 0
+ 9
+ 14
+ 1
+ 54
+ 30
+ 1
+ 22
+ 1
+ 128
+ 46
+ 54
+ 13
+ 136
+ 30
+ 9
+ 10
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1083 -10 m 0,0,1
+ 1083 -77 1083 -77 1050 -150.5 c 128,-1,2
+ 1017 -224 1017 -224 950.5 -288 c 128,-1,3
+ 884 -352 884 -352 788.5 -390 c 128,-1,4
+ 693 -428 693 -428 571 -428 c 0,5,6
+ 428 -428 428 -428 316.5 -374.5 c 128,-1,7
+ 205 -321 205 -321 145.5 -229.5 c 128,-1,8
+ 86 -138 86 -138 86 -31 c 0,9,10
+ 86 31 86 31 106.5 85.5 c 128,-1,11
+ 127 140 127 140 163.5 185 c 128,-1,12
+ 200 230 200 230 229.5 257 c 128,-1,13
+ 259 284 259 284 371 385 c 0,14,15
+ 437 445 437 445 454.5 479.5 c 128,-1,16
+ 472 514 472 514 487 592 c 0,17,18
+ 507 694 507 694 606 694 c 0,19,20
+ 659 694 659 694 694 660 c 128,-1,21
+ 729 626 729 626 729 559 c 0,22,23
+ 729 493 729 493 713.5 443 c 128,-1,24
+ 698 393 698 393 670.5 352.5 c 128,-1,25
+ 643 312 643 312 611.5 280.5 c 128,-1,26
+ 580 249 580 249 518 195 c 0,27,28
+ 432 120 432 120 396 75 c 128,-1,29
+ 360 30 360 30 360 -29 c 0,30,31
+ 360 -107 360 -107 419 -162 c 128,-1,32
+ 478 -217 478 -217 571 -217 c 0,33,34
+ 648 -217 648 -217 696.5 -188.5 c 128,-1,35
+ 745 -160 745 -160 772.5 -112.5 c 128,-1,36
+ 800 -65 800 -65 821 2 c 0,37,38
+ 841 57 841 57 869.5 86 c 128,-1,39
+ 898 115 898 115 952 115 c 0,40,41
+ 1009 115 1009 115 1046 75.5 c 128,-1,42
+ 1083 36 1083 36 1083 -10 c 0,0,1
+598 1085 m 0,43,44
+ 660 1085 660 1085 704 1045.5 c 128,-1,45
+ 748 1006 748 1006 748 936 c 0,46,47
+ 748 899 748 899 726.5 864 c 128,-1,48
+ 705 829 705 829 670 807.5 c 128,-1,49
+ 635 786 635 786 598 786 c 0,50,51
+ 556 786 556 786 521.5 806 c 128,-1,52
+ 487 826 487 826 466.5 859.5 c 128,-1,53
+ 446 893 446 893 446 936 c 0,54,55
+ 446 1007 446 1007 490.5 1046 c 128,-1,56
+ 535 1085 535 1085 598 1085 c 0,43,44
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: exclamdown
+Encoding: 161 161 163
+Width: 1200
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+SplineSet
+976 894 m 0,0,1
+ 989 881 989 881 998 858 c 0,2,3
+ 1007 836 1007 836 1007 819 c 2,4,-1
+ 1007 41 l 2,5,6
+ 1007 24 1007 24 993 12 c 128,-1,7
+ 979 0 979 0 960 0 c 2,8,-1
+ 230 0 l 2,9,10
+ 212 0 212 0 197 11 c 0,11,12
+ 183 21 183 21 183 41 c 2,13,-1
+ 183 1006 l 2,14,15
+ 183 1025 183 1025 197 1037 c 128,-1,16
+ 211 1049 211 1049 230 1049 c 2,17,-1
+ 780 1049 l 2,18,19
+ 801 1049 801 1049 822 1040 c 0,20,21
+ 848 1029 848 1029 858 1017 c 0,22,23
+ 863 1011 863 1011 882 992 c 0,24,25
+ 895 979 895 979 910 963 c 0,26,27
+ 938 934 938 934 976 894 c 0,0,1
+EndSplineSet
+EndChar
+
+StartChar: logicalnot
+Encoding: 172 172 164
+Width: 1194
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 12
+ 2
+ 36
+ 5
+ 10
+ 12
+ 7
+ 1
+ 141
+ 0
+ 1
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1110 377 m 1,0,-1
+ 852 377 l 1,1,-1
+ 852 815 l 1,2,-1
+ 84 815 l 1,3,-1
+ 84 1077 l 1,4,-1
+ 1110 1077 l 1,5,-1
+ 1110 377 l 1,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: radical
+Encoding: 8730 8730 165
+Width: 1124
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 7
+ 7
+ 6
+ 4
+ 3
+ 2
+ 10
+ 0
+SVTCA[y-axis]
+MDAP[rnd]
+MIAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+53 854 m 1,0,-1
+ 20 922 l 1,1,-1
+ 319 1069 l 1,2,-1
+ 723 244 l 1,3,-1
+ 983 1878 l 1,4,-1
+ 1055 1868 l 1,5,-1
+ 748 -78 l 1,6,-1
+ 250 950 l 1,7,-1
+ 53 854 l 1,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: florin
+Encoding: 402 402 166
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 47
+ 14
+ 54
+ 7
+ 12
+ 12
+ 0
+ 0
+ 1
+ 0
+ 46
+ 1
+ 0
+ 53
+ 19
+ 26
+ 0
+ 39
+ 1
+ 0
+ 0
+ 0
+ 0
+ 42
+ 54
+ 33
+ 7
+ 8
+ 3
+ 7
+ 28
+ 9
+ 2
+ 10
+ 46
+ 45
+ 28
+ 27
+ 19
+ 2
+ 1
+ 0
+ 8
+ 115
+ 23
+ 50
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+440 778 m 2,0,-1
+ 492 778 l 1,1,-1
+ 549 1094 l 2,2,3
+ 570 1205 570 1205 588 1266 c 128,-1,4
+ 606 1327 606 1327 645.5 1380 c 128,-1,5
+ 685 1433 685 1433 754.5 1461 c 128,-1,6
+ 824 1489 824 1489 934 1489 c 0,7,8
+ 1049 1489 1049 1489 1116.5 1458.5 c 128,-1,9
+ 1184 1428 1184 1428 1184 1366 c 0,10,11
+ 1184 1303 1184 1303 1142.5 1288 c 128,-1,12
+ 1101 1273 1101 1273 1026.5 1285.5 c 128,-1,13
+ 952 1298 952 1298 948 1298 c 0,14,15
+ 895 1298 895 1298 867.5 1271 c 128,-1,16
+ 840 1244 840 1244 824.5 1192 c 128,-1,17
+ 809 1140 809 1140 787 1004.5 c 128,-1,18
+ 765 869 765 869 748 778 c 1,19,-1
+ 811 778 l 2,20,21
+ 882 778 882 778 921.5 759.5 c 128,-1,22
+ 961 741 961 741 961 682 c 0,23,24
+ 961 627 961 627 920 604.5 c 128,-1,25
+ 879 582 879 582 797 582 c 2,26,-1
+ 713 582 l 1,27,-1
+ 604 -45 l 2,28,29
+ 589 -136 589 -136 566.5 -204 c 128,-1,30
+ 544 -272 544 -272 503.5 -322 c 128,-1,31
+ 463 -372 463 -372 395 -400 c 128,-1,32
+ 327 -428 327 -428 223 -428 c 0,33,34
+ 105 -428 105 -428 37 -397 c 128,-1,35
+ -31 -366 -31 -366 -31 -309 c 0,36,37
+ -31 -269 -31 -269 -3.5 -244 c 128,-1,38
+ 24 -219 24 -219 72 -219 c 0,39,40
+ 81 -219 81 -219 123.5 -228.5 c 128,-1,41
+ 166 -238 166 -238 193 -238 c 0,42,43
+ 273 -238 273 -238 301.5 -194.5 c 128,-1,44
+ 330 -151 330 -151 348 -51 c 2,45,-1
+ 457 582 l 1,46,-1
+ 418 582 l 2,47,48
+ 344 582 344 582 304 602 c 128,-1,49
+ 264 622 264 622 264 672 c 0,50,51
+ 264 733 264 733 309.5 755.5 c 128,-1,52
+ 355 778 355 778 440 778 c 2,0,-1
+EndSplineSet
+Validated: 33
+EndChar
+
+StartChar: approxequal
+Encoding: 8776 8776 167
+Width: 1124
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 24
+ 34
+ 33
+ 29
+ 24
+ 23
+ 19
+ 15
+ 14
+ 10
+ 5
+ 4
+ 0
+ 0
+ 20
+ 1
+ 0
+ 30
+ 1
+ 0
+ 100
+ 1
+ 11
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1004 807 m 1,0,-1
+ 1079 758 l 1,1,2
+ 1021 661 1021 661 915.5 620 c 128,-1,3
+ 810 579 810 579 715 606 c 2,4,-1
+ 408 694 l 2,5,6
+ 342 713 342 713 290 705.5 c 128,-1,7
+ 238 698 238 698 203.5 675.5 c 128,-1,8
+ 169 653 169 653 149 627 c 128,-1,9
+ 129 601 129 601 117 586 c 1,10,-1
+ 29 641 l 1,11,12
+ 108 746 108 746 211.5 783 c 128,-1,13
+ 315 820 315 820 428 788 c 2,14,-1
+ 737 702 l 2,15,16
+ 805 682 805 682 899 721 c 0,17,18
+ 965 749 965 749 1004 807 c 1,0,-1
+1004 498 m 1,19,-1
+ 1079 449 l 1,20,21
+ 1021 350 1021 350 915.5 310 c 128,-1,22
+ 810 270 810 270 715 297 c 2,23,-1
+ 408 385 l 2,24,25
+ 342 404 342 404 290 396.5 c 128,-1,26
+ 238 389 238 389 203.5 366.5 c 128,-1,27
+ 169 344 169 344 147.5 316 c 128,-1,28
+ 126 288 126 288 117 276 c 1,29,-1
+ 29 332 l 1,30,31
+ 108 437 108 437 211.5 474 c 128,-1,32
+ 315 511 315 511 428 479 c 2,33,-1
+ 737 393 l 2,34,35
+ 805 373 805 373 899 412 c 0,36,37
+ 965 440 965 440 1004 498 c 1,19,-1
+EndSplineSet
+Validated: 33
+EndChar
+
+StartChar: Delta
+Encoding: 8710 8710 168
+Width: 1253
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 18
+ 5
+ 82
+ 2
+ 9
+ 11
+ 7
+ 3
+ 10
+ 0
+ 5
+ 4
+ 3
+ 3
+ 95
+ 1
+ 2
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MIAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+668 1409 m 1,0,-1
+ 1245 0 l 1,1,-1
+ 12 0 l 1,2,-1
+ 668 1409 l 1,0,-1
+594 1059 m 1,3,-1
+ 147 100 l 1,4,-1
+ 991 100 l 1,5,-1
+ 594 1059 l 1,3,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: guillemotleft
+Encoding: 171 171 169
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 35
+ 0
+ 42
+ 1
+ 0
+ 31
+ 1
+ 0
+ 20
+ 18
+ 7
+ 0
+ 7
+ 45
+ 40
+ 39
+ 25
+ 24
+ 5
+ 123
+ 28
+ 37
+ 13
+ 21
+ 16
+ 15
+ 2
+ 1
+ 0
+ 6
+ 124
+ 4
+ 13
+ 13
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+543 813 m 2,0,-1
+ 362 524 l 1,1,-1
+ 553 221 l 2,2,3
+ 580 183 580 183 580 150 c 0,4,5
+ 580 114 580 114 553 88.5 c 128,-1,6
+ 526 63 526 63 487 63 c 0,7,8
+ 457 63 457 63 431.5 83 c 128,-1,9
+ 406 103 406 103 369 158 c 2,10,-1
+ 190 426 l 2,11,12
+ 147 492 147 492 147 522 c 0,13,14
+ 147 558 147 558 190 625 c 2,15,-1
+ 375 901 l 2,16,17
+ 429 983 429 983 485 983 c 0,18,19
+ 523 983 523 983 550.5 958.5 c 128,-1,20
+ 578 934 578 934 578 899 c 0,21,22
+ 578 872 578 872 566.5 852 c 128,-1,23
+ 555 832 555 832 543 813 c 2,0,-1
+1001 813 m 2,24,-1
+ 821 524 l 1,25,-1
+ 1012 221 l 2,26,27
+ 1040 176 1040 176 1040 150 c 0,28,29
+ 1040 114 1040 114 1013 88.5 c 128,-1,30
+ 986 63 986 63 946 63 c 0,31,32
+ 915 63 915 63 889.5 83 c 128,-1,33
+ 864 103 864 103 827 158 c 2,34,-1
+ 651 426 l 2,35,36
+ 606 498 606 498 606 522 c 0,37,38
+ 606 555 606 555 651 625 c 2,39,-1
+ 834 901 l 2,40,41
+ 886 983 886 983 946 983 c 0,42,43
+ 983 983 983 983 1010.5 958 c 128,-1,44
+ 1038 933 1038 933 1038 899 c 0,45,46
+ 1038 880 1038 880 1033 866.5 c 128,-1,47
+ 1028 853 1028 853 1022 844.5 c 128,-1,48
+ 1016 836 1016 836 1001 813 c 2,24,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: guillemotright
+Encoding: 187 187 170
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 33
+ 0
+ 35
+ 1
+ 0
+ 46
+ 1
+ 0
+ 20
+ 9
+ 21
+ 0
+ 7
+ 6
+ 2
+ 1
+ 0
+ 4
+ 123
+ 15
+ 24
+ 13
+ 38
+ 37
+ 32
+ 27
+ 26
+ 5
+ 124
+ 40
+ 49
+ 13
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+664 221 m 1,0,-1
+ 854 524 l 1,1,-1
+ 674 813 l 2,2,3
+ 662 829 662 829 655 840 c 128,-1,4
+ 648 851 648 851 642.5 865.5 c 128,-1,5
+ 637 880 637 880 637 899 c 0,6,7
+ 637 933 637 933 665 958 c 128,-1,8
+ 693 983 693 983 729 983 c 0,9,10
+ 788 983 788 983 842 901 c 2,11,-1
+ 1024 625 l 2,12,13
+ 1047 590 1047 590 1058 568.5 c 128,-1,14
+ 1069 547 1069 547 1069 522 c 0,15,16
+ 1069 493 1069 493 1024 426 c 2,17,-1
+ 848 158 l 2,18,19
+ 812 103 812 103 785.5 83 c 128,-1,20
+ 759 63 759 63 729 63 c 0,21,22
+ 690 63 690 63 662.5 88 c 128,-1,23
+ 635 113 635 113 635 150 c 0,24,25
+ 635 184 635 184 664 221 c 1,0,-1
+205 221 m 2,26,-1
+ 395 524 l 1,27,-1
+ 215 813 l 2,28,29
+ 205 829 205 829 196.5 841.5 c 128,-1,30
+ 188 854 188 854 183 869 c 128,-1,31
+ 178 884 178 884 178 899 c 0,32,33
+ 178 933 178 933 206 958 c 128,-1,34
+ 234 983 234 983 270 983 c 0,35,36
+ 327 983 327 983 381 901 c 2,37,-1
+ 565 625 l 2,38,39
+ 608 562 608 562 608 522 c 0,40,41
+ 608 491 608 491 565 426 c 2,42,-1
+ 389 158 l 2,43,44
+ 353 103 353 103 326.5 83 c 128,-1,45
+ 300 63 300 63 270 63 c 0,46,47
+ 230 63 230 63 203 88.5 c 128,-1,48
+ 176 114 176 114 176 150 c 0,49,50
+ 176 180 176 180 205 221 c 2,26,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: ellipsis
+Encoding: 8230 8230 171
+Width: 2048
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 29
+ 0
+ 30
+ 18
+ 2
+ 0
+ 24
+ 12
+ 2
+ 0
+ 6
+ 31
+ 0
+ 9
+ 8
+ 7
+ 128
+ 33
+ 27
+ 10
+ 128
+ 9
+ 3
+ 10
+ 128
+ 21
+ 15
+ 10
+ 3
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1024 -23 m 256,0,1
+ 964 -23 964 -23 919 17 c 128,-1,2
+ 874 57 874 57 874 127 c 0,3,4
+ 874 189 874 189 917.5 232.5 c 128,-1,5
+ 961 276 961 276 1024 276 c 256,6,7
+ 1087 276 1087 276 1131.5 232.5 c 128,-1,8
+ 1176 189 1176 189 1176 127 c 0,9,10
+ 1176 56 1176 56 1130 16.5 c 128,-1,11
+ 1084 -23 1084 -23 1024 -23 c 256,0,1
+342 -23 m 256,12,13
+ 282 -23 282 -23 237.5 16.5 c 128,-1,14
+ 193 56 193 56 193 127 c 0,15,16
+ 193 190 193 190 236 233 c 128,-1,17
+ 279 276 279 276 342 276 c 256,18,19
+ 405 276 405 276 449.5 232.5 c 128,-1,20
+ 494 189 494 189 494 127 c 0,21,22
+ 494 56 494 56 448 16.5 c 128,-1,23
+ 402 -23 402 -23 342 -23 c 256,12,13
+1706 -23 m 0,24,25
+ 1647 -23 1647 -23 1601.5 17 c 128,-1,26
+ 1556 57 1556 57 1556 127 c 0,27,28
+ 1556 189 1556 189 1599.5 232.5 c 128,-1,29
+ 1643 276 1643 276 1706 276 c 256,30,31
+ 1769 276 1769 276 1813.5 232.5 c 128,-1,32
+ 1858 189 1858 189 1858 127 c 0,33,34
+ 1858 57 1858 57 1812.5 17 c 128,-1,35
+ 1767 -23 1767 -23 1706 -23 c 0,24,25
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: nonbreakingspace
+Encoding: 160 160 172
+Width: 512
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Validated: 1
+EndChar
+
+StartChar: Agrave
+Encoding: 192 192 173
+Width: 1473
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 36 65 N 1 0 0 1 0 0 2
+Refer: 67 96 N 1 0 0 1 342 371 2
+Validated: 1
+EndChar
+
+StartChar: Atilde
+Encoding: 195 195 174
+Width: 1473
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 36 65 N 1 0 0 1 0 0 2
+Refer: 216 732 N 1 0 0 1 342 371 2
+Validated: 1
+EndChar
+
+StartChar: Otilde
+Encoding: 213 213 175
+Width: 1622
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 50 79 N 1 0 0 1 0 0 2
+Refer: 216 732 N 1 0 0 1 500 371 2
+Validated: 1
+EndChar
+
+StartChar: OE
+Encoding: 338 338 176
+Width: 2111
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 64
+ 8
+ 1
+ 51
+ 9
+ 62
+ 18
+ 2
+ 16
+ 59
+ 2
+ 1
+ 0
+ 0
+ 0
+ 0
+ 43
+ 1
+ 51
+ 41
+ 40
+ 12
+ 9
+ 47
+ 1
+ 41
+ 9
+ 16
+ 13
+ 0
+ 0
+ 0
+ 0
+ 27
+ 1
+ 59
+ 41
+ 30
+ 9
+ 8
+ 3
+ 7
+ 24
+ 9
+ 1
+ 12
+ 0
+ 9
+ 1
+ 0
+ 0
+ 43
+ 27
+ 0
+ 3
+ 131
+ 18
+ 48
+ 0
+ 128
+ 54
+ 35
+ 10
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+LOOPCALL
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1292 1466 m 2,0,-1
+ 1898 1466 l 2,1,2
+ 1970 1466 1970 1466 2007 1433.5 c 128,-1,3
+ 2044 1401 2044 1401 2044 1348 c 256,4,5
+ 2044 1295 2044 1295 2008 1263 c 128,-1,6
+ 1972 1231 1972 1231 1898 1231 c 2,7,-1
+ 1352 1231 l 1,8,-1
+ 1352 883 l 1,9,-1
+ 1847 883 l 2,10,11
+ 1920 883 1920 883 1955.5 849.5 c 128,-1,12
+ 1991 816 1991 816 1991 764 c 0,13,14
+ 1991 711 1991 711 1956 679 c 128,-1,15
+ 1921 647 1921 647 1847 647 c 2,16,-1
+ 1352 647 l 1,17,-1
+ 1352 236 l 1,18,-1
+ 1931 236 l 2,19,20
+ 2075 236 2075 236 2075 117 c 0,21,22
+ 2075 0 2075 0 1931 0 c 2,23,-1
+ 1286 0 l 2,24,25
+ 1177 0 1177 0 1134.5 39.5 c 128,-1,26
+ 1092 79 1092 79 1092 178 c 1,27,28
+ 1018 74 1018 74 921.5 24.5 c 128,-1,29
+ 825 -25 825 -25 678 -25 c 0,30,31
+ 542 -25 542 -25 430.5 27.5 c 128,-1,32
+ 319 80 319 80 240.5 180.5 c 128,-1,33
+ 162 281 162 281 121 421.5 c 128,-1,34
+ 80 562 80 562 80 733 c 0,35,36
+ 80 909 80 909 121.5 1050 c 128,-1,37
+ 163 1191 163 1191 240 1289.5 c 128,-1,38
+ 317 1388 317 1388 426.5 1439.5 c 128,-1,39
+ 536 1491 536 1491 670 1491 c 0,40,41
+ 812 1491 812 1491 910.5 1444 c 128,-1,42
+ 1009 1397 1009 1397 1092 1298 c 1,43,44
+ 1093 1368 1093 1368 1115 1404 c 128,-1,45
+ 1137 1440 1137 1440 1180 1453 c 128,-1,46
+ 1223 1466 1223 1466 1292 1466 c 2,0,-1
+1065 705 m 2,47,-1
+ 1065 797 l 2,48,49
+ 1065 1024 1065 1024 977 1139.5 c 128,-1,50
+ 889 1255 889 1255 727 1255 c 0,51,52
+ 563 1255 563 1255 472 1125 c 128,-1,53
+ 381 995 381 995 381 748 c 0,54,55
+ 381 613 381 613 404 512.5 c 128,-1,56
+ 427 412 427 412 472.5 344.5 c 128,-1,57
+ 518 277 518 277 583.5 244 c 128,-1,58
+ 649 211 649 211 731 211 c 0,59,60
+ 816 211 816 211 888 252.5 c 128,-1,61
+ 960 294 960 294 1001 367 c 0,62,63
+ 1065 476 1065 476 1065 705 c 2,47,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: oe
+Encoding: 339 339 177
+Width: 1962
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 69
+ 16
+ 1
+ 6
+ 54
+ 1
+ 0
+ 0
+ 0
+ 0
+ 46
+ 39
+ 2
+ 61
+ 51
+ 0
+ 10
+ 9
+ 50
+ 1
+ 64
+ 43
+ 6
+ 13
+ 0
+ 0
+ 0
+ 23
+ 1
+ 26
+ 11
+ 2
+ 54
+ 52
+ 28
+ 9
+ 8
+ 3
+ 7
+ 36
+ 10
+ 0
+ 1
+ 43
+ 42
+ 1
+ 19
+ 1
+ 140
+ 4
+ 43
+ 13
+ 7
+ 1
+ 0
+ 0
+ 0
+ 39
+ 26
+ 2
+ 143
+ 42
+ 57
+ 0
+ 138
+ 50
+ 32
+ 10
+ 3
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1370 1087 m 0,0,1
+ 1535 1087 1535 1087 1652.5 1019.5 c 128,-1,2
+ 1770 952 1770 952 1828 846.5 c 128,-1,3
+ 1886 741 1886 741 1886 625 c 0,4,5
+ 1886 463 1886 463 1704 463 c 2,6,-1
+ 1135 463 l 1,7,8
+ 1141 364 1141 364 1174.5 296 c 128,-1,9
+ 1208 228 1208 228 1265.5 194 c 128,-1,10
+ 1323 160 1323 160 1401 160 c 0,11,12
+ 1491 160 1491 160 1547 186.5 c 128,-1,13
+ 1603 213 1603 213 1640.5 251.5 c 128,-1,14
+ 1678 290 1678 290 1712 323 c 128,-1,15
+ 1746 356 1746 356 1780 356 c 0,16,17
+ 1820 356 1820 356 1845 329 c 128,-1,18
+ 1870 302 1870 302 1870 260 c 0,19,20
+ 1870 214 1870 214 1821 145.5 c 128,-1,21
+ 1772 77 1772 77 1668.5 26 c 128,-1,22
+ 1565 -25 1565 -25 1417 -25 c 256,23,24
+ 1269 -25 1269 -25 1175 14.5 c 128,-1,25
+ 1081 54 1081 54 997 141 c 1,26,27
+ 846 -25 846 -25 610 -25 c 0,28,29
+ 458 -25 458 -25 336 46 c 128,-1,30
+ 214 117 214 117 146 244 c 128,-1,31
+ 78 371 78 371 78 530 c 0,32,33
+ 78 690 78 690 142 816.5 c 128,-1,34
+ 206 943 206 943 326.5 1014 c 128,-1,35
+ 447 1085 447 1085 606 1085 c 0,36,37
+ 723 1085 723 1085 816 1046.5 c 128,-1,38
+ 909 1008 909 1008 991 926 c 1,39,40
+ 1069 1009 1069 1009 1160 1048 c 128,-1,41
+ 1251 1087 1251 1087 1370 1087 c 0,0,1
+1133 621 m 1,42,-1
+ 1626 621 l 1,43,44
+ 1616 761 1616 761 1553 829 c 128,-1,45
+ 1490 897 1490 897 1382 897 c 0,46,47
+ 1273 897 1273 897 1203 818 c 128,-1,48
+ 1133 739 1133 739 1133 627 c 2,49,-1
+ 1133 621 l 1,42,-1
+344 526 m 0,50,51
+ 344 418 344 418 377.5 340 c 128,-1,52
+ 411 262 411 262 473 220 c 128,-1,53
+ 535 178 535 178 616 178 c 0,54,55
+ 731 178 731 178 805 270.5 c 128,-1,56
+ 879 363 879 363 879 526 c 0,57,58
+ 879 636 879 636 846.5 717.5 c 128,-1,59
+ 814 799 814 799 753.5 841 c 128,-1,60
+ 693 883 693 883 612 883 c 0,61,62
+ 488 883 488 883 416 784.5 c 128,-1,63
+ 344 686 344 686 344 526 c 0,50,51
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: endash
+Encoding: 8211 8211 178
+Width: 1024
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 5
+ 57
+ 3
+ 1
+ 10
+ 7
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1036 426 m 1,0,-1
+ -12 426 l 1,1,-1
+ -12 610 l 1,2,-1
+ 1036 610 l 1,3,-1
+ 1036 426 l 1,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: emdash
+Encoding: 8212 8212 179
+Width: 2048
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 5
+ 57
+ 3
+ 1
+ 10
+ 7
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+2060 426 m 1,0,-1
+ -12 426 l 1,1,-1
+ -12 610 l 1,2,-1
+ 2060 610 l 1,3,-1
+ 2060 426 l 1,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: quotedblleft
+Encoding: 8220 8220 180
+Width: 938
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 33
+ 0
+ 37
+ 1
+ 29
+ 1
+ 0
+ 42
+ 22
+ 2
+ 7
+ 24
+ 14
+ 12
+ 9
+ 7
+ 42
+ 40
+ 22
+ 3
+ 126
+ 26
+ 32
+ 13
+ 19
+ 17
+ 0
+ 3
+ 126
+ 4
+ 10
+ 13
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+258 1192 m 1,0,-1
+ 272 1192 l 2,1,2
+ 329 1192 329 1192 374.5 1148.5 c 128,-1,3
+ 420 1105 420 1105 420 1040 c 0,4,5
+ 420 976 420 976 374.5 934.5 c 128,-1,6
+ 329 893 329 893 262 893 c 0,7,8
+ 189 893 189 893 140.5 951.5 c 128,-1,9
+ 92 1010 92 1010 92 1118 c 0,10,11
+ 92 1217 92 1217 134.5 1303.5 c 128,-1,12
+ 177 1390 177 1390 238.5 1440.5 c 128,-1,13
+ 300 1491 300 1491 348 1491 c 0,14,15
+ 380 1491 380 1491 398 1472 c 128,-1,16
+ 416 1453 416 1453 416 1423 c 0,17,18
+ 416 1379 416 1379 377 1358 c 0,19,20
+ 324 1329 324 1329 293 1290 c 128,-1,21
+ 262 1251 262 1251 258 1192 c 1,0,-1
+700 1192 m 1,22,-1
+ 713 1192 l 2,23,24
+ 769 1192 769 1192 814.5 1148.5 c 128,-1,25
+ 860 1105 860 1105 860 1040 c 0,26,27
+ 860 977 860 977 814.5 934 c 128,-1,28
+ 769 891 769 891 702 891 c 0,29,30
+ 628 891 628 891 580 951 c 128,-1,31
+ 532 1011 532 1011 532 1118 c 0,32,33
+ 532 1195 532 1195 557 1263 c 128,-1,34
+ 582 1331 582 1331 621.5 1381.5 c 128,-1,35
+ 661 1432 661 1432 706.5 1461.5 c 128,-1,36
+ 752 1491 752 1491 788 1491 c 0,37,38
+ 821 1491 821 1491 838.5 1472.5 c 128,-1,39
+ 856 1454 856 1454 856 1423 c 0,40,41
+ 856 1378 856 1378 817 1358 c 0,42,43
+ 762 1327 762 1327 734 1289.5 c 128,-1,44
+ 706 1252 706 1252 700 1192 c 1,22,-1
+EndSplineSet
+Validated: 1
+Kerns2: 99 -53 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 98 -53 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 36 -53 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: quotedblright
+Encoding: 8221 8221 181
+Width: 938
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 31
+ 0
+ 29
+ 1
+ 0
+ 36
+ 1
+ 0
+ 14
+ 23
+ 7
+ 12
+ 9
+ 7
+ 41
+ 39
+ 22
+ 3
+ 126
+ 32
+ 26
+ 13
+ 19
+ 17
+ 0
+ 3
+ 126
+ 10
+ 4
+ 13
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+238 1188 m 1,0,-1
+ 223 1188 l 2,1,2
+ 167 1188 167 1188 121.5 1233.5 c 128,-1,3
+ 76 1279 76 1279 76 1341 c 0,4,5
+ 76 1405 76 1405 121.5 1448 c 128,-1,6
+ 167 1491 167 1491 233 1491 c 0,7,8
+ 308 1491 308 1491 355.5 1431 c 128,-1,9
+ 403 1371 403 1371 403 1264 c 0,10,11
+ 403 1166 403 1166 361.5 1079.5 c 128,-1,12
+ 320 993 320 993 259.5 942 c 128,-1,13
+ 199 891 199 891 150 891 c 0,14,15
+ 119 891 119 891 99.5 910.5 c 128,-1,16
+ 80 930 80 930 80 958 c 0,17,18
+ 80 1003 80 1003 121 1024 c 0,19,20
+ 174 1055 174 1055 204 1092 c 128,-1,21
+ 234 1129 234 1129 238 1188 c 1,0,-1
+678 1188 m 1,22,-1
+ 666 1188 l 2,23,24
+ 609 1188 609 1188 562.5 1233 c 128,-1,25
+ 516 1278 516 1278 516 1341 c 256,26,27
+ 516 1404 516 1404 562 1447.5 c 128,-1,28
+ 608 1491 608 1491 674 1491 c 0,29,30
+ 750 1491 750 1491 797 1432 c 128,-1,31
+ 844 1373 844 1373 844 1264 c 0,32,33
+ 844 1163 844 1163 802.5 1077.5 c 128,-1,34
+ 761 992 761 992 700.5 941.5 c 128,-1,35
+ 640 891 640 891 590 891 c 0,36,37
+ 558 891 558 891 539 910 c 128,-1,38
+ 520 929 520 929 520 958 c 0,39,40
+ 520 1002 520 1002 561 1024 c 0,41,42
+ 618 1057 618 1057 646 1092.5 c 128,-1,43
+ 674 1128 674 1128 678 1188 c 1,22,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: quoteleft
+Encoding: 8216 8216 182
+Width: 641
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 15
+ 7
+ 24
+ 14
+ 12
+ 12
+ 7
+ 19
+ 17
+ 0
+ 3
+ 126
+ 4
+ 10
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+330 1192 m 1,0,-1
+ 344 1192 l 2,1,2
+ 401 1192 401 1192 446.5 1148.5 c 128,-1,3
+ 492 1105 492 1105 492 1040 c 0,4,5
+ 492 976 492 976 446.5 934.5 c 128,-1,6
+ 401 893 401 893 334 893 c 0,7,8
+ 261 893 261 893 212.5 951.5 c 128,-1,9
+ 164 1010 164 1010 164 1118 c 0,10,11
+ 164 1217 164 1217 206.5 1303.5 c 128,-1,12
+ 249 1390 249 1390 310.5 1440.5 c 128,-1,13
+ 372 1491 372 1491 420 1491 c 0,14,15
+ 450 1491 450 1491 468.5 1471.5 c 128,-1,16
+ 487 1452 487 1452 487 1423 c 0,17,18
+ 487 1378 487 1378 449 1358 c 0,19,20
+ 396 1329 396 1329 365 1290 c 128,-1,21
+ 334 1251 334 1251 330 1192 c 1,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 99 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 98 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 36 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: quoteright
+Encoding: 8217 8217 183
+Width: 641
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 15
+ 15
+ 23
+ 7
+ 12
+ 12
+ 7
+ 20
+ 18
+ 0
+ 3
+ 126
+ 11
+ 4
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+326 1188 m 1,0,-1
+ 311 1188 l 2,1,2
+ 255 1188 255 1188 209.5 1233.5 c 128,-1,3
+ 164 1279 164 1279 164 1341 c 0,4,5
+ 164 1405 164 1405 209.5 1448 c 128,-1,6
+ 255 1491 255 1491 322 1491 c 0,7,8
+ 368 1491 368 1491 408 1464.5 c 128,-1,9
+ 448 1438 448 1438 470 1387.5 c 128,-1,10
+ 492 1337 492 1337 492 1264 c 0,11,12
+ 492 1165 492 1165 450 1078.5 c 128,-1,13
+ 408 992 408 992 347.5 941.5 c 128,-1,14
+ 287 891 287 891 238 891 c 0,15,16
+ 207 891 207 891 187.5 910.5 c 128,-1,17
+ 168 930 168 930 168 958 c 0,18,19
+ 168 1003 168 1003 209 1024 c 0,20,21
+ 262 1055 262 1055 292 1092 c 128,-1,22
+ 322 1129 322 1129 326 1188 c 1,0,-1
+EndSplineSet
+Validated: 1
+Kerns2: 89 -27 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 87 25 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 86 -78 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 85 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable" 71 -51 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: divide
+Encoding: 247 247 184
+Width: 1194
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 26
+ 33
+ 11
+ 4
+ 10
+ 36
+ 0
+ 2
+ 10
+ 33
+ 24
+ 17
+ 10
+ 3
+ 7
+ 0
+ 27
+ 1
+ 0
+ 21
+ 1
+ 0
+ 133
+ 14
+ 8
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1110 854 m 1,0,-1
+ 1110 592 l 1,1,-1
+ 84 592 l 1,2,-1
+ 84 854 l 1,3,-1
+ 1110 854 l 1,0,-1
+598 981 m 0,4,5
+ 563 981 563 981 530.5 1001.5 c 128,-1,6
+ 498 1022 498 1022 477.5 1055.5 c 128,-1,7
+ 457 1089 457 1089 457 1122 c 0,8,9
+ 457 1189 457 1189 499 1226.5 c 128,-1,10
+ 541 1264 541 1264 598 1264 c 0,11,12
+ 654 1264 654 1264 696.5 1226 c 128,-1,13
+ 739 1188 739 1188 739 1122 c 0,14,15
+ 739 1065 739 1065 697 1023 c 128,-1,16
+ 655 981 655 981 598 981 c 0,4,5
+598 184 m 0,17,18
+ 563 184 563 184 530 205.5 c 128,-1,19
+ 497 227 497 227 477 259.5 c 128,-1,20
+ 457 292 457 292 457 326 c 0,21,22
+ 457 392 457 392 499 429.5 c 128,-1,23
+ 541 467 541 467 598 467 c 0,24,25
+ 654 467 654 467 696.5 429 c 128,-1,26
+ 739 391 739 391 739 326 c 0,27,28
+ 739 269 739 269 697.5 226.5 c 128,-1,29
+ 656 184 656 184 598 184 c 0,17,18
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: lozenge
+Encoding: 9674 9674 185
+Width: 1012
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 25
+ 0
+ 0
+ 0
+ 0
+ 9
+ 8
+ 6
+ 3
+ 4
+ 14
+ 1
+ 9
+ 8
+ 7
+ 7
+ 9
+ 8
+ 7
+ 6
+ 4
+ 112
+ 5
+ 2
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+557 0 m 1,0,-1
+ 434 0 l 1,1,-1
+ 37 772 l 1,2,-1
+ 434 1526 l 1,3,-1
+ 557 1526 l 1,4,-1
+ 954 772 l 1,5,-1
+ 557 0 l 1,0,-1
+831 772 m 1,6,-1
+ 496 1415 l 1,7,-1
+ 160 772 l 1,8,-1
+ 496 111 l 1,9,-1
+ 831 772 l 1,6,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: ydieresis
+Encoding: 255 255 186
+Width: 1110
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 92 121 N 1 0 0 1 0 0 2
+Refer: 142 168 N 1 0 0 1 170 0 2
+Validated: 1
+EndChar
+
+StartChar: Ydieresis
+Encoding: 376 376 187
+Width: 1280
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 60 89 N 1 0 0 1 0 0 2
+Refer: 142 168 N 1 0 0 1 342 371 2
+Validated: 1
+EndChar
+
+StartChar: fraction
+Encoding: 8725 8725 188
+Width: 299
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 3
+ 12
+ 12
+ 3
+SVTCA[y-axis]
+MDAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+621 1343 m 2,0,-1
+ -213 0 l 2,1,2
+ -245 -55 -245 -55 -287 -55 c 0,3,4
+ -310 -55 -310 -55 -333 -37.5 c 128,-1,5
+ -356 -20 -356 -20 -356 8 c 0,6,7
+ -356 29 -356 29 -336 59 c 2,8,-1
+ 504 1413 l 2,9,10
+ 530 1457 530 1457 544 1474 c 128,-1,11
+ 558 1491 558 1491 590 1491 c 0,12,13
+ 621 1491 621 1491 638 1472.5 c 128,-1,14
+ 655 1454 655 1454 655 1423 c 0,15,16
+ 655 1400 655 1400 621 1343 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: Euro
+Encoding: 8364 8364 189
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 57
+ 17
+ 0
+ 61
+ 24
+ 61
+ 27
+ 58
+ 51
+ 34
+ 51
+ 40
+ 51
+ 1
+ 61
+ 51
+ 61
+ 51
+ 14
+ 36
+ 8
+ 42
+ 1
+ 42
+ 48
+ 36
+ 7
+ 8
+ 23
+ 8
+ 39
+ 8
+ 3
+ 8
+ 2
+ 14
+ 39
+ 11
+ 64
+ 54
+ 61
+ 0
+ 58
+ 51
+ 4
+ 59
+ 24
+ 17
+ 27
+ 34
+ 4
+ 30
+ 20
+ 167
+ 25
+ 1
+ 0
+ 25
+MDAP[rnd]
+SDS
+DELTAP1
+MDRP[rnd,grey]
+SHP[rp2]
+SLOOP
+SHP[rp1]
+MDRP[rp0,min,rnd,black]
+SLOOP
+SHP[rp2]
+MDRP[rnd,grey]
+SHP[rp2]
+MDRP[rp0,rnd,grey]
+MDRP[rnd,grey]
+SVTCA[y-axis]
+MDAP[rnd]
+MDRP[rp0,min,rnd,black]
+MDRP[rnd,grey]
+DELTAP1
+MDAP[rnd]
+MDRP[rp0,min,rnd,black]
+MDRP[rnd,grey]
+DELTAP1
+SRP1
+SRP2
+IP
+IP
+MDAP[rnd]
+MDAP[rnd]
+DELTAP1
+SRP1
+SHP[rp1]
+SRP0
+MDRP[min,rnd,black]
+SHP[rp2]
+SRP1
+SHP[rp1]
+SRP0
+MDRP[min,rnd,black]
+SHP[rp2]
+IUP[x]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+444 539 m 1,0,1
+ 479 180 479 180 674 180 c 0,2,3
+ 747 180 747 180 807.5 215 c 128,-1,4
+ 868 250 868 250 924 379 c 0,5,6
+ 960 463 960 463 986 483.5 c 128,-1,7
+ 1012 504 1012 504 1042 504 c 0,8,9
+ 1102 504 1102 504 1135.5 469.5 c 128,-1,10
+ 1169 435 1169 435 1169 373 c 0,11,12
+ 1169 226 1169 226 1025 101.5 c 128,-1,13
+ 881 -23 881 -23 676 -23 c 0,14,15
+ 484 -23 484 -23 341 116.5 c 128,-1,16
+ 198 256 198 256 170 539 c 1,17,-1
+ 43 539 l 2,18,19
+ 25 539 25 539 25 565 c 0,20,21
+ 25 590 25 590 44 628 c 128,-1,22
+ 63 666 63 666 76 666 c 2,23,-1
+ 162 666 l 1,24,-1
+ 162 702 l 2,25,26
+ 162 746 162 746 166 829 c 1,27,-1
+ 43 829 l 2,28,29
+ 25 829 25 829 25 854 c 0,30,31
+ 25 880 25 880 44 918 c 128,-1,32
+ 63 956 63 956 76 956 c 2,33,-1
+ 176 956 l 1,34,35
+ 241 1477 241 1477 668 1477 c 0,36,37
+ 856 1477 856 1477 992 1380 c 128,-1,38
+ 1128 1283 1128 1283 1128 1139 c 0,39,40
+ 1128 1090 1128 1090 1096 1056 c 128,-1,41
+ 1064 1022 1064 1022 1018 1022 c 0,42,43
+ 967 1022 967 1022 943.5 1048 c 128,-1,44
+ 920 1074 920 1074 897 1128 c 0,45,46
+ 868 1199 868 1199 828 1236.5 c 128,-1,47
+ 788 1274 788 1274 692 1274 c 0,48,49
+ 582 1274 582 1274 522.5 1197 c 128,-1,50
+ 463 1120 463 1120 446 956 c 1,51,-1
+ 768 956 l 2,52,53
+ 788 956 788 956 788 930 c 0,54,55
+ 788 902 788 902 769.5 865.5 c 128,-1,56
+ 751 829 751 829 737 829 c 2,57,-1
+ 438 829 l 1,58,-1
+ 436 731 l 2,59,60
+ 436 686 436 686 438 666 c 1,61,-1
+ 768 666 l 2,62,63
+ 788 666 788 666 788 641 c 0,64,65
+ 788 612 788 612 769.5 575.5 c 128,-1,66
+ 751 539 751 539 737 539 c 2,67,-1
+ 444 539 l 1,0,1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: guilsinglleft
+Encoding: 8249 8249 190
+Width: 748
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 17
+ 20
+ 18
+ 7
+ 10
+ 7
+ 21
+ 16
+ 15
+ 2
+ 1
+ 0
+ 6
+ 124
+ 4
+ 13
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+539 813 m 2,0,-1
+ 358 524 l 1,1,-1
+ 549 221 l 2,2,3
+ 575 185 575 185 575 150 c 0,4,5
+ 575 112 575 112 548.5 87.5 c 128,-1,6
+ 522 63 522 63 483 63 c 0,7,8
+ 452 63 452 63 427.5 82 c 128,-1,9
+ 403 101 403 101 365 158 c 2,10,-1
+ 186 426 l 2,11,12
+ 143 492 143 492 143 522 c 0,13,14
+ 143 558 143 558 186 625 c 2,15,-1
+ 371 901 l 2,16,17
+ 423 983 423 983 481 983 c 0,18,19
+ 519 983 519 983 546 958.5 c 128,-1,20
+ 573 934 573 934 573 899 c 0,21,22
+ 573 879 573 879 568 865.5 c 128,-1,23
+ 563 852 563 852 555 838.5 c 128,-1,24
+ 547 825 547 825 539 813 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: guilsinglright
+Encoding: 8250 8250 191
+Width: 748
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 16
+ 20
+ 9
+ 20
+ 10
+ 7
+ 12
+ 11
+ 6
+ 1
+ 0
+ 5
+ 124
+ 14
+ 23
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+201 221 m 1,0,-1
+ 391 524 l 1,1,-1
+ 211 813 l 2,2,3
+ 201 829 201 829 192.5 841.5 c 128,-1,4
+ 184 854 184 854 179 869 c 128,-1,5
+ 174 884 174 884 174 899 c 0,6,7
+ 174 933 174 933 202 958 c 128,-1,8
+ 230 983 230 983 266 983 c 0,9,10
+ 323 983 323 983 377 901 c 2,11,-1
+ 561 625 l 2,12,13
+ 604 562 604 562 604 522 c 0,14,15
+ 604 491 604 491 561 426 c 2,16,-1
+ 385 158 l 2,17,18
+ 349 103 349 103 322.5 83 c 128,-1,19
+ 296 63 296 63 266 63 c 0,20,21
+ 226 63 226 63 199 88.5 c 128,-1,22
+ 172 114 172 114 172 150 c 0,23,24
+ 172 184 172 184 201 221 c 1,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: fi
+Encoding: 61441 61441 192
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 64
+ 5
+ 1
+ 0
+ 0
+ 0
+ 0
+ 60
+ 35
+ 54
+ 12
+ 9
+ 0
+ 0
+ 1
+ 0
+ 34
+ 1
+ 40
+ 1
+ 25
+ 53
+ 17
+ 10
+ 9
+ 2
+ 7
+ 51
+ 10
+ 44
+ 9
+ 30
+ 9
+ 22
+ 1
+ 48
+ 17
+ 1
+ 0
+ 57
+ 1
+ 20
+ 8
+ 2
+ 63
+ 1
+ 0
+ 141
+ 41
+ 48
+ 0
+ 0
+ 26
+ 1
+ 37
+ 1
+ 33
+ 1
+ 0
+ 141
+ 17
+ 1
+ 0
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+109 1061 m 2,0,-1
+ 182 1061 l 1,1,-1
+ 182 1143 l 2,2,3
+ 182 1314 182 1314 249.5 1402.5 c 128,-1,4
+ 317 1491 317 1491 500 1491 c 0,5,6
+ 621 1491 621 1491 687.5 1461.5 c 128,-1,7
+ 754 1432 754 1432 754 1374 c 0,8,9
+ 754 1332 754 1332 735.5 1313.5 c 128,-1,10
+ 717 1295 717 1295 691.5 1293 c 128,-1,11
+ 666 1291 666 1291 621 1295.5 c 128,-1,12
+ 576 1300 576 1300 571 1300 c 0,13,14
+ 494 1300 494 1300 467 1257.5 c 128,-1,15
+ 440 1215 440 1215 440 1126 c 2,16,-1
+ 440 1061 l 1,17,-1
+ 506 1061 l 2,18,19
+ 662 1061 662 1061 662 958 c 0,20,21
+ 662 933 662 933 635 901 c 0,22,23
+ 613 877 613 877 583.5 870.5 c 128,-1,24
+ 554 864 554 864 506 864 c 2,25,-1
+ 440 864 l 1,26,-1
+ 440 133 l 2,27,28
+ 440 52 440 52 404.5 13.5 c 128,-1,29
+ 369 -25 369 -25 311 -25 c 256,30,31
+ 253 -25 253 -25 217.5 15 c 128,-1,32
+ 182 55 182 55 182 133 c 2,33,-1
+ 182 864 l 1,34,-1
+ 106 864 l 2,35,36
+ -20 864 -20 864 -20 963 c 0,37,38
+ -20 1008 -20 1008 13.5 1034.5 c 128,-1,39
+ 47 1061 47 1061 109 1061 c 2,0,-1
+1069 907 m 2,40,-1
+ 1069 135 l 2,41,42
+ 1069 55 1069 55 1034 15 c 128,-1,43
+ 999 -25 999 -25 940 -25 c 0,44,45
+ 884 -25 884 -25 847.5 15.5 c 128,-1,46
+ 811 56 811 56 811 135 c 2,47,-1
+ 811 928 l 2,48,49
+ 811 1006 811 1006 845.5 1045.5 c 128,-1,50
+ 880 1085 880 1085 940 1085 c 0,51,52
+ 1013 1085 1013 1085 1041 1040 c 128,-1,53
+ 1069 995 1069 995 1069 907 c 2,40,-1
+940 1479 m 256,54,55
+ 995 1479 995 1479 1032 1440 c 128,-1,56
+ 1069 1401 1069 1401 1069 1346 c 0,57,58
+ 1069 1283 1069 1283 1031.5 1247.5 c 128,-1,59
+ 994 1212 994 1212 940 1212 c 0,60,61
+ 887 1212 887 1212 849 1248 c 128,-1,62
+ 811 1284 811 1284 811 1346 c 0,63,64
+ 811 1401 811 1401 848 1440 c 128,-1,65
+ 885 1479 885 1479 940 1479 c 256,54,55
+EndSplineSet
+Validated: 33
+EndChar
+
+StartChar: fl
+Encoding: 61442 61442 193
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 57
+ 0
+ 11
+ 1
+ 0
+ 0
+ 0
+ 1
+ 26
+ 54
+ 18
+ 12
+ 9
+ 0
+ 13
+ 1
+ 0
+ 47
+ 1
+ 0
+ 38
+ 53
+ 30
+ 10
+ 9
+ 2
+ 7
+ 43
+ 9
+ 4
+ 9
+ 35
+ 1
+ 8
+ 30
+ 1
+ 33
+ 21
+ 2
+ 0
+ 141
+ 1
+ 8
+ 14
+ 0
+ 39
+ 1
+ 50
+ 1
+ 46
+ 1
+ 0
+ 141
+ 30
+ 14
+ 0
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1069 1337 m 2,0,-1
+ 1069 135 l 2,1,2
+ 1069 57 1069 57 1033.5 16 c 128,-1,3
+ 998 -25 998 -25 940 -25 c 0,4,5
+ 883 -25 883 -25 847 15 c 128,-1,6
+ 811 55 811 55 811 135 c 2,7,-1
+ 811 1333 l 2,8,9
+ 811 1412 811 1412 846 1451.5 c 128,-1,10
+ 881 1491 881 1491 940 1491 c 0,11,12
+ 1069 1491 1069 1491 1069 1337 c 2,0,-1
+109 1061 m 2,13,-1
+ 182 1061 l 1,14,-1
+ 182 1143 l 2,15,16
+ 182 1314 182 1314 249.5 1402.5 c 128,-1,17
+ 317 1491 317 1491 500 1491 c 0,18,19
+ 621 1491 621 1491 687.5 1461.5 c 128,-1,20
+ 754 1432 754 1432 754 1374 c 0,21,22
+ 754 1332 754 1332 735.5 1313.5 c 128,-1,23
+ 717 1295 717 1295 691.5 1293 c 128,-1,24
+ 666 1291 666 1291 621 1295.5 c 128,-1,25
+ 576 1300 576 1300 571 1300 c 0,26,27
+ 494 1300 494 1300 467 1257.5 c 128,-1,28
+ 440 1215 440 1215 440 1126 c 2,29,-1
+ 440 1061 l 1,30,-1
+ 506 1061 l 2,31,32
+ 662 1061 662 1061 662 958 c 0,33,34
+ 662 933 662 933 635 901 c 0,35,36
+ 613 877 613 877 583.5 870.5 c 128,-1,37
+ 554 864 554 864 506 864 c 2,38,-1
+ 440 864 l 1,39,-1
+ 440 133 l 2,40,41
+ 440 52 440 52 404.5 13.5 c 128,-1,42
+ 369 -25 369 -25 311 -25 c 256,43,44
+ 253 -25 253 -25 217.5 15 c 128,-1,45
+ 182 55 182 55 182 133 c 2,46,-1
+ 182 864 l 1,47,-1
+ 106 864 l 2,48,49
+ -20 864 -20 864 -20 963 c 0,50,51
+ -20 1008 -20 1008 13.5 1034.5 c 128,-1,52
+ 47 1061 47 1061 109 1061 c 2,13,-1
+EndSplineSet
+Validated: 33
+EndChar
+
+StartChar: daggerdbl
+Encoding: 8225 8225 194
+Width: 1217
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 43
+ 0
+ 26
+ 1
+ 0
+ 33
+ 1
+ 0
+ 10
+ 48
+ 17
+ 10
+ 9
+ 0
+ 35
+ 1
+ 0
+ 42
+ 1
+ 0
+ 8
+ 48
+ 1
+ 9
+ 8
+ 2
+ 7
+ 47
+ 22
+ 12
+ 0
+ 43
+ 35
+ 2
+ 0
+ 10
+ 0
+ 2
+ 0
+ 146
+ 25
+ 18
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MDAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+485 -242 m 2,0,-1
+ 485 -12 l 1,1,-1
+ 207 -12 l 2,2,3
+ 141 -12 141 -12 108.5 17 c 128,-1,4
+ 76 46 76 46 76 94 c 0,5,6
+ 76 143 76 143 108.5 172 c 128,-1,7
+ 141 201 141 201 207 201 c 2,8,-1
+ 485 201 l 1,9,-1
+ 485 883 l 1,10,-1
+ 207 883 l 2,11,12
+ 143 883 143 883 109.5 912.5 c 128,-1,13
+ 76 942 76 942 76 989 c 0,14,15
+ 76 1037 76 1037 109 1066.5 c 128,-1,16
+ 142 1096 142 1096 207 1096 c 2,17,-1
+ 485 1096 l 1,18,-1
+ 485 1327 l 2,19,20
+ 485 1403 485 1403 519.5 1441 c 128,-1,21
+ 554 1479 554 1479 610 1479 c 0,22,23
+ 667 1479 667 1479 700 1440.5 c 128,-1,24
+ 733 1402 733 1402 733 1327 c 2,25,-1
+ 733 1096 l 1,26,-1
+ 1012 1096 l 2,27,28
+ 1078 1096 1078 1096 1110.5 1067 c 128,-1,29
+ 1143 1038 1143 1038 1143 989 c 0,30,31
+ 1143 941 1143 941 1110.5 912 c 128,-1,32
+ 1078 883 1078 883 1012 883 c 2,33,-1
+ 733 883 l 1,34,-1
+ 733 201 l 1,35,-1
+ 1012 201 l 2,36,37
+ 1078 201 1078 201 1110.5 172 c 128,-1,38
+ 1143 143 1143 143 1143 94 c 0,39,40
+ 1143 46 1143 46 1110.5 17 c 128,-1,41
+ 1078 -12 1078 -12 1012 -12 c 2,42,-1
+ 733 -12 l 1,43,-1
+ 733 -242 l 2,44,45
+ 733 -317 733 -317 699 -355 c 128,-1,46
+ 665 -393 665 -393 610 -393 c 256,47,48
+ 555 -393 555 -393 520 -355 c 128,-1,49
+ 485 -317 485 -317 485 -242 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: periodcentered
+Encoding: 8729 8729 195
+Width: 641
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 7
+ 4
+ 0
+ 128
+ 7
+ 0
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MDAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+170 725 m 0,0,1
+ 170 766 170 766 190.5 800 c 128,-1,2
+ 211 834 211 834 245 854 c 128,-1,3
+ 279 874 279 874 319 874 c 0,4,5
+ 382 874 382 874 426.5 830.5 c 128,-1,6
+ 471 787 471 787 471 725 c 0,7,8
+ 471 631 471 631 396 592.5 c 128,-1,9
+ 321 554 321 554 245.5 592.5 c 128,-1,10
+ 170 631 170 631 170 725 c 0,0,1
+EndSplineSet
+Validated: 33
+EndChar
+
+StartChar: quotesinglbase
+Encoding: 8218 8218 196
+Width: 641
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 14
+ 23
+ 6
+ 14
+ 10
+ 7
+ 19
+ 17
+ 0
+ 3
+ 126
+ 10
+ 3
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+326 -27 m 1,0,1
+ 260 -27 260 -27 212 13.5 c 128,-1,2
+ 164 54 164 54 164 127 c 0,3,4
+ 164 190 164 190 211 233 c 128,-1,5
+ 258 276 258 276 322 276 c 0,6,7
+ 370 276 370 276 409 250 c 128,-1,8
+ 448 224 448 224 470 173.5 c 128,-1,9
+ 492 123 492 123 492 49 c 0,10,11
+ 492 -50 492 -50 450 -136.5 c 128,-1,12
+ 408 -223 408 -223 347.5 -273.5 c 128,-1,13
+ 287 -324 287 -324 238 -324 c 0,14,15
+ 207 -324 207 -324 187.5 -303.5 c 128,-1,16
+ 168 -283 168 -283 168 -256 c 0,17,18
+ 168 -215 168 -215 209 -190 c 0,19,20
+ 326 -125 326 -125 326 -27 c 1,0,1
+EndSplineSet
+Validated: 1
+Kerns2: 196 -205 "'kern' Horizontal Kerning in Latin lookup 0 subtable"
+EndChar
+
+StartChar: quotedblbase
+Encoding: 8222 8222 197
+Width: 938
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 30
+ 0
+ 27
+ 1
+ 0
+ 35
+ 1
+ 0
+ 23
+ 6
+ 14
+ 0
+ 7
+ 19
+ 17
+ 0
+ 3
+ 126
+ 10
+ 3
+ 13
+ 40
+ 38
+ 21
+ 3
+ 126
+ 31
+ 24
+ 13
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+682 -27 m 1,0,1
+ 616 -27 616 -27 568 13.5 c 128,-1,2
+ 520 54 520 54 520 127 c 0,3,4
+ 520 190 520 190 567 233 c 128,-1,5
+ 614 276 614 276 678 276 c 0,6,7
+ 726 276 726 276 765 250 c 128,-1,8
+ 804 224 804 224 826 173.5 c 128,-1,9
+ 848 123 848 123 848 49 c 0,10,11
+ 848 -50 848 -50 806 -136.5 c 128,-1,12
+ 764 -223 764 -223 703.5 -273.5 c 128,-1,13
+ 643 -324 643 -324 594 -324 c 0,14,15
+ 563 -324 563 -324 543.5 -303.5 c 128,-1,16
+ 524 -283 524 -283 524 -256 c 0,17,18
+ 524 -216 524 -216 565 -190 c 0,19,20
+ 682 -126 682 -126 682 -27 c 1,0,1
+242 -27 m 1,21,22
+ 176 -27 176 -27 128 13.5 c 128,-1,23
+ 80 54 80 54 80 127 c 0,24,25
+ 80 190 80 190 127 233 c 128,-1,26
+ 174 276 174 276 238 276 c 0,27,28
+ 286 276 286 276 325 250 c 128,-1,29
+ 364 224 364 224 386 173.5 c 128,-1,30
+ 408 123 408 123 408 49 c 0,31,32
+ 408 -50 408 -50 366 -136.5 c 128,-1,33
+ 324 -223 324 -223 263.5 -273.5 c 128,-1,34
+ 203 -324 203 -324 154 -324 c 0,35,36
+ 123 -324 123 -324 103.5 -303.5 c 128,-1,37
+ 84 -283 84 -283 84 -256 c 0,38,39
+ 84 -215 84 -215 125 -190 c 0,40,41
+ 242 -125 242 -125 242 -27 c 1,21,22
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: perthousand
+Encoding: 8240 8240 198
+Width: 2474
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 98
+ 58
+ 1
+ 19
+ 27
+ 75
+ 30
+ 2
+ 48
+ 55
+ 2
+ 1
+ 70
+ 1
+ 0
+ 0
+ 0
+ 67
+ 1
+ 19
+ 75
+ 11
+ 12
+ 9
+ 0
+ 0
+ 0
+ 92
+ 1
+ 86
+ 40
+ 3
+ 3
+ 48
+ 27
+ 48
+ 0
+ 0
+ 100
+ 1
+ 61
+ 1
+ 79
+ 1
+ 66
+ 1
+ 55
+ 75
+ 33
+ 9
+ 8
+ 3
+ 7
+ 59
+ 9
+ 0
+ 10
+ 73
+ 58
+ 2
+ 45
+ 52
+ 66
+ 64
+ 2
+ 16
+ 23
+ 2
+ 1
+ 157
+ 75
+ 89
+ 10
+ 157
+ 96
+ 83
+ 10
+ 157
+ 30
+ 45
+ 10
+ 67
+ 1
+ 157
+ 52
+ 37
+ 13
+ 59
+ 1
+ 157
+ 0
+ 16
+ 13
+ 157
+ 23
+ 7
+ 10
+ 6
+ 7
+LOOPCALL
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+LOOPCALL
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+676 1090 m 0,0,1
+ 676 899 676 899 592 806 c 128,-1,2
+ 508 713 508 713 362 713 c 0,3,4
+ 272 713 272 713 200.5 752.5 c 128,-1,5
+ 129 792 129 792 89 876 c 128,-1,6
+ 49 960 49 960 49 1081 c 0,7,8
+ 49 1211 49 1211 80 1298 c 128,-1,9
+ 111 1385 111 1385 180.5 1430 c 128,-1,10
+ 250 1475 250 1475 358 1475 c 0,11,12
+ 436 1475 436 1475 495 1451 c 128,-1,13
+ 554 1427 554 1427 595 1377.5 c 128,-1,14
+ 636 1328 636 1328 656 1257 c 128,-1,15
+ 676 1186 676 1186 676 1090 c 0,0,1
+489 1100 m 0,16,17
+ 489 1231 489 1231 461 1290.5 c 128,-1,18
+ 433 1350 433 1350 362 1350 c 0,19,20
+ 314 1350 314 1350 285.5 1321.5 c 128,-1,21
+ 257 1293 257 1293 246.5 1237.5 c 128,-1,22
+ 236 1182 236 1182 236 1096 c 0,23,24
+ 236 1007 236 1007 246.5 951 c 128,-1,25
+ 257 895 257 895 285 866.5 c 128,-1,26
+ 313 838 313 838 362 838 c 0,27,28
+ 436 838 436 838 462.5 901 c 128,-1,29
+ 489 964 489 964 489 1100 c 0,16,17
+1700 367 m 0,30,31
+ 1700 176 1700 176 1616 83 c 128,-1,32
+ 1532 -10 1532 -10 1386 -10 c 0,33,34
+ 1295 -10 1295 -10 1223.5 30 c 128,-1,35
+ 1152 70 1152 70 1111.5 153 c 128,-1,36
+ 1071 236 1071 236 1071 358 c 0,37,38
+ 1071 553 1071 553 1145.5 651.5 c 128,-1,39
+ 1220 750 1220 750 1382 750 c 0,40,41
+ 1460 750 1460 750 1518.5 726 c 128,-1,42
+ 1577 702 1577 702 1618.5 654 c 128,-1,43
+ 1660 606 1660 606 1680 534.5 c 128,-1,44
+ 1700 463 1700 463 1700 367 c 0,30,31
+1513 377 m 0,45,46
+ 1513 506 1513 506 1485 565.5 c 128,-1,47
+ 1457 625 1457 625 1386 625 c 0,48,49
+ 1336 625 1336 625 1308 597 c 128,-1,50
+ 1280 569 1280 569 1268.5 514.5 c 128,-1,51
+ 1257 460 1257 460 1257 373 c 0,52,53
+ 1257 239 1257 239 1285.5 177 c 128,-1,54
+ 1314 115 1314 115 1386 115 c 0,55,56
+ 1459 115 1459 115 1486 178.5 c 128,-1,57
+ 1513 242 1513 242 1513 377 c 0,45,46
+1343 1343 m 2,58,-1
+ 510 0 l 2,59,60
+ 478 -55 478 -55 438 -55 c 0,61,62
+ 415 -55 415 -55 392 -37.5 c 128,-1,63
+ 369 -20 369 -20 369 8 c 0,64,65
+ 369 29 369 29 389 59 c 2,66,-1
+ 1227 1413 l 2,67,68
+ 1249 1450 1249 1450 1265.5 1468.5 c 128,-1,69
+ 1282 1487 1282 1487 1313 1487 c 0,70,71
+ 1343 1487 1343 1487 1361.5 1469.5 c 128,-1,72
+ 1380 1452 1380 1452 1380 1423 c 0,73,74
+ 1380 1402 1380 1402 1343 1343 c 2,58,-1
+2427 367 m 0,75,76
+ 2427 239 2427 239 2388 155 c 128,-1,77
+ 2349 71 2349 71 2277.5 30.5 c 128,-1,78
+ 2206 -10 2206 -10 2111 -10 c 0,79,80
+ 2022 -10 2022 -10 1950 30 c 128,-1,81
+ 1878 70 1878 70 1838 153.5 c 128,-1,82
+ 1798 237 1798 237 1798 358 c 0,83,84
+ 1798 552 1798 552 1871 651 c 128,-1,85
+ 1944 750 1944 750 2107 750 c 0,86,87
+ 2263 750 2263 750 2345 653.5 c 128,-1,88
+ 2427 557 2427 557 2427 367 c 0,75,76
+2241 377 m 0,89,90
+ 2241 506 2241 506 2212.5 565.5 c 128,-1,91
+ 2184 625 2184 625 2111 625 c 0,92,93
+ 2062 625 2062 625 2034 597 c 128,-1,94
+ 2006 569 2006 569 1995.5 513.5 c 128,-1,95
+ 1985 458 1985 458 1985 373 c 0,96,97
+ 1985 286 1985 286 1995.5 229.5 c 128,-1,98
+ 2006 173 2006 173 2034.5 144 c 128,-1,99
+ 2063 115 2063 115 2111 115 c 0,100,101
+ 2186 115 2186 115 2213.5 179 c 128,-1,102
+ 2241 243 2241 243 2241 377 c 0,89,90
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: Acircumflex
+Encoding: 194 194 199
+Width: 1473
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 36 65 N 1 0 0 1 0 0 2
+Refer: 215 710 N 1 0 0 1 342 371 2
+Validated: 1
+EndChar
+
+StartChar: Ecircumflex
+Encoding: 202 202 200
+Width: 1366
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 40 69 N 1 0 0 1 0 0 2
+Refer: 215 710 N 1 0 0 1 342 371 2
+Validated: 1
+EndChar
+
+StartChar: Aacute
+Encoding: 193 193 201
+Width: 1473
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 36 65 N 1 0 0 1 0 0 2
+Refer: 141 180 N 1 0 0 1 342 371 2
+Validated: 1
+EndChar
+
+StartChar: Edieresis
+Encoding: 203 203 202
+Width: 1366
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 40 69 N 1 0 0 1 0 0 2
+Refer: 142 168 N 1 0 0 1 342 371 2
+Validated: 1
+EndChar
+
+StartChar: Egrave
+Encoding: 200 200 203
+Width: 1366
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 40 69 N 1 0 0 1 0 0 2
+Refer: 67 96 N 1 0 0 1 342 371 2
+Validated: 1
+EndChar
+
+StartChar: Iacute
+Encoding: 205 205 204
+Width: 641
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 44 73 N 1 0 0 1 0 0 2
+Refer: 141 180 N 1 0 0 1 -55 371 2
+Validated: 1
+EndChar
+
+StartChar: Icircumflex
+Encoding: 206 206 205
+Width: 641
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 44 73 N 1 0 0 1 0 0 2
+Refer: 215 710 N 1 0 0 1 -55 371 2
+Validated: 1
+EndChar
+
+StartChar: Idieresis
+Encoding: 207 207 206
+Width: 641
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 44 73 N 1 0 0 1 0 0 2
+Refer: 142 168 N 1 0 0 1 -55 371 2
+Validated: 1
+EndChar
+
+StartChar: Igrave
+Encoding: 204 204 207
+Width: 641
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 44 73 N 1 0 0 1 0 0 2
+Refer: 67 96 N 1 0 0 1 -55 371 2
+Validated: 1
+EndChar
+
+StartChar: Oacute
+Encoding: 211 211 208
+Width: 1622
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 50 79 N 1 0 0 1 0 0 2
+Refer: 141 180 N 1 0 0 1 500 371 2
+Validated: 1
+EndChar
+
+StartChar: Ocircumflex
+Encoding: 212 212 209
+Width: 1622
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 50 79 N 1 0 0 1 0 0 2
+Refer: 215 710 N 1 0 0 1 500 371 2
+Validated: 1
+EndChar
+
+StartChar: Ograve
+Encoding: 210 210 210
+Width: 1622
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 50 79 N 1 0 0 1 0 0 2
+Refer: 67 96 N 1 0 0 1 500 371 2
+Validated: 1
+EndChar
+
+StartChar: Uacute
+Encoding: 218 218 211
+Width: 1556
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 56 85 N 1 0 0 1 0 0 2
+Refer: 141 180 N 1 0 0 1 397 371 2
+Validated: 1
+EndChar
+
+StartChar: Ucircumflex
+Encoding: 219 219 212
+Width: 1556
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 56 85 N 1 0 0 1 0 0 2
+Refer: 215 710 N 1 0 0 1 397 371 2
+Validated: 1
+EndChar
+
+StartChar: Ugrave
+Encoding: 217 217 213
+Width: 1556
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 56 85 N 1 0 0 1 0 0 2
+Refer: 67 96 N 1 0 0 1 397 371 2
+Validated: 1
+EndChar
+
+StartChar: dotlessi
+Encoding: 305 305 214
+Width: 555
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 9
+ 11
+ 10
+ 4
+ 9
+ 137
+ 1
+ 8
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+414 930 m 2,0,-1
+ 414 141 l 2,1,2
+ 414 59 414 59 375 17 c 128,-1,3
+ 336 -25 336 -25 276 -25 c 256,4,5
+ 216 -25 216 -25 178.5 18 c 128,-1,6
+ 141 61 141 61 141 141 c 2,7,-1
+ 141 922 l 2,8,9
+ 141 1003 141 1003 178.5 1044 c 128,-1,10
+ 216 1085 216 1085 276 1085 c 256,11,12
+ 336 1085 336 1085 375 1044 c 128,-1,13
+ 414 1003 414 1003 414 930 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: circumflex
+Encoding: 710 710 215
+Width: 682
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 20
+ 0
+ 0
+ 0
+ 26
+ 1
+ 2
+ 1
+ 0
+ 3
+ 6
+ 32
+ 17
+ 12
+ 9
+ 7
+ 117
+ 23
+ 8
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+442 1272 m 2,0,-1
+ 342 1389 l 1,1,-1
+ 242 1272 l 2,2,3
+ 200 1222 200 1222 185 1211 c 128,-1,4
+ 170 1200 170 1200 129 1200 c 2,5,-1
+ 49 1200 l 2,6,7
+ 8 1200 8 1200 8 1214 c 0,8,9
+ 8 1225 8 1225 39 1264 c 2,10,-1
+ 150 1397 l 2,11,12
+ 164 1414 164 1414 182 1436.5 c 128,-1,13
+ 200 1459 200 1459 213.5 1468.5 c 128,-1,14
+ 227 1478 227 1478 253 1483.5 c 128,-1,15
+ 279 1489 279 1489 313 1489 c 2,16,-1
+ 369 1489 l 2,17,18
+ 435 1489 435 1489 459.5 1473 c 128,-1,19
+ 484 1457 484 1457 532 1397 c 2,20,-1
+ 647 1262 l 2,21,22
+ 676 1224 676 1224 676 1217 c 0,23,24
+ 676 1200 676 1200 631 1200 c 2,25,-1
+ 555 1200 l 2,26,27
+ 525 1200 525 1200 507.5 1208.5 c 128,-1,28
+ 490 1217 490 1217 474 1235 c 128,-1,29
+ 458 1253 458 1253 442 1272 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: tilde
+Encoding: 732 732 216
+Width: 682
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 22
+ 21
+ 1
+ 0
+ 4
+ 1
+ 0
+ 19
+ 16
+ 2
+ 0
+ 4
+ 27
+ 37
+ 11
+ 12
+ 9
+ 7
+ 116
+ 24
+ 7
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+182 1311 m 0,0,1
+ 131 1311 131 1311 113 1243 c 0,2,3
+ 95 1184 95 1184 59 1184 c 0,4,5
+ 37 1184 37 1184 19.5 1204.5 c 128,-1,6
+ 2 1225 2 1225 2 1262 c 0,7,8
+ 2 1312 2 1312 24 1358.5 c 128,-1,9
+ 46 1405 46 1405 85.5 1432.5 c 128,-1,10
+ 125 1460 125 1460 170 1460 c 256,11,12
+ 215 1460 215 1460 253.5 1447 c 128,-1,13
+ 292 1434 292 1434 356.5 1404.5 c 128,-1,14
+ 421 1375 421 1375 445 1366.5 c 128,-1,15
+ 469 1358 469 1358 498 1358 c 256,16,17
+ 527 1358 527 1358 543.5 1372.5 c 128,-1,18
+ 560 1387 560 1387 569 1425 c 0,19,20
+ 585 1483 585 1483 623 1483 c 0,21,22
+ 646 1483 646 1483 663 1462 c 128,-1,23
+ 680 1441 680 1441 680 1405 c 0,24,25
+ 680 1349 680 1349 637.5 1278.5 c 128,-1,26
+ 595 1208 595 1208 506 1208 c 0,27,28
+ 472 1208 472 1208 436 1219.5 c 128,-1,29
+ 400 1231 400 1231 337 1259 c 128,-1,30
+ 274 1287 274 1287 243 1299 c 128,-1,31
+ 212 1311 212 1311 182 1311 c 0,0,1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: macron
+Encoding: 713 713 217
+Width: 682
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 5
+ 70
+ 3
+ 1
+ 10
+ 7
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+702 1264 m 1,0,-1
+ -23 1264 l 1,1,-1
+ -23 1403 l 1,2,-1
+ 702 1403 l 1,3,-1
+ 702 1264 l 1,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: breve
+Encoding: 728 728 218
+Width: 682
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 12
+ 72
+ 0
+ 12
+ 10
+ 7
+ 18
+ 5
+ 118
+ 8
+ 15
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MDAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+344 1341 m 256,0,1
+ 418 1341 418 1341 468.5 1379 c 128,-1,2
+ 519 1417 519 1417 532 1483 c 0,3,4
+ 546 1548 546 1548 592 1548 c 0,5,6
+ 619 1548 619 1548 636 1528.5 c 128,-1,7
+ 653 1509 653 1509 653 1481 c 0,8,9
+ 653 1417 653 1417 615 1353 c 128,-1,10
+ 577 1289 577 1289 506.5 1247.5 c 128,-1,11
+ 436 1206 436 1206 346 1206 c 0,12,13
+ 211 1206 211 1206 120 1293 c 128,-1,14
+ 29 1380 29 1380 29 1481 c 0,15,16
+ 29 1506 29 1506 47 1527 c 128,-1,17
+ 65 1548 65 1548 90 1548 c 0,18,19
+ 133 1548 133 1548 152 1479 c 0,20,21
+ 168 1415 168 1415 219 1378 c 128,-1,22
+ 270 1341 270 1341 344 1341 c 256,0,1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: dotaccent
+Encoding: 729 729 219
+Width: 682
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 7
+ 8
+ 0
+ 152
+ 4
+ 8
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MDAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+342 1444 m 0,0,1
+ 371 1444 371 1444 397 1429 c 128,-1,2
+ 423 1414 423 1414 439 1387.5 c 128,-1,3
+ 455 1361 455 1361 455 1331 c 0,4,5
+ 455 1260 455 1260 398.5 1232 c 128,-1,6
+ 342 1204 342 1204 285.5 1232 c 128,-1,7
+ 229 1260 229 1260 229 1331 c 0,8,9
+ 229 1377 229 1377 262.5 1410.5 c 128,-1,10
+ 296 1444 296 1444 342 1444 c 0,0,1
+EndSplineSet
+Validated: 33
+EndChar
+
+StartChar: ring
+Encoding: 730 730 220
+Width: 682
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 26
+ 0
+ 80
+ 13
+ 12
+ 11
+ 79
+ 19
+ 6
+ 10
+ 2
+ 7
+ 0
+ 1
+ 23
+ 16
+ 1
+ 173
+ 3
+ 23
+ 10
+ 173
+ 16
+ 10
+ 10
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+340 1567 m 256,0,1
+ 425 1567 425 1567 486 1506 c 128,-1,2
+ 547 1445 547 1445 547 1360 c 256,3,4
+ 547 1275 547 1275 486 1214 c 128,-1,5
+ 425 1153 425 1153 340 1153 c 0,6,7
+ 283 1153 283 1153 236 1181 c 128,-1,8
+ 189 1209 189 1209 161 1256 c 128,-1,9
+ 133 1303 133 1303 133 1360 c 0,10,11
+ 133 1445 133 1445 194 1506 c 128,-1,12
+ 255 1567 255 1567 340 1567 c 256,0,1
+340 1462 m 0,13,14
+ 296 1462 296 1462 267 1433 c 128,-1,15
+ 238 1404 238 1404 238 1360 c 0,16,17
+ 238 1317 238 1317 267.5 1288.5 c 128,-1,18
+ 297 1260 297 1260 340 1260 c 0,19,20
+ 368 1260 368 1260 391.5 1273 c 128,-1,21
+ 415 1286 415 1286 428.5 1309 c 128,-1,22
+ 442 1332 442 1332 442 1360 c 0,23,24
+ 442 1381 442 1381 434 1400.5 c 128,-1,25
+ 426 1420 426 1420 413 1433 c 128,-1,26
+ 400 1446 400 1446 380.5 1454 c 128,-1,27
+ 361 1462 361 1462 340 1462 c 0,13,14
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: cedilla
+Encoding: 184 184 221
+Width: 682
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 30
+ 27
+ 15
+ 2
+ 24
+ 18
+ 1
+ 0
+ 0
+ 0
+ 0
+ 30
+ 0
+ 2
+ 24
+ 75
+ 2
+ 9
+ 9
+ 18
+ 79
+ 10
+ 7
+ 11
+ 2
+ 7
+ 159
+ 6
+ 21
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+215 -96 m 0,0,1
+ 224 -23 224 -23 358 -23 c 0,2,3
+ 435 -23 435 -23 496 -53 c 128,-1,4
+ 557 -83 557 -83 590 -128.5 c 128,-1,5
+ 623 -174 623 -174 623 -221 c 0,6,7
+ 623 -275 623 -275 587 -318.5 c 128,-1,8
+ 551 -362 551 -362 480 -386 c 128,-1,9
+ 409 -410 409 -410 305 -410 c 0,10,11
+ 106 -410 106 -410 106 -344 c 0,12,13
+ 106 -324 106 -324 120.5 -309.5 c 128,-1,14
+ 135 -295 135 -295 160 -295 c 0,15,16
+ 163 -295 163 -295 211 -299 c 128,-1,17
+ 259 -303 259 -303 297 -303 c 0,18,19
+ 368 -303 368 -303 406 -281 c 128,-1,20
+ 444 -259 444 -259 444 -221 c 0,21,22
+ 444 -187 444 -187 416.5 -167 c 128,-1,23
+ 389 -147 389 -147 332 -147 c 0,24,25
+ 310 -147 310 -147 283.5 -153.5 c 128,-1,26
+ 257 -160 257 -160 254 -160 c 0,27,28
+ 237 -160 237 -160 225 -145 c 128,-1,29
+ 213 -130 213 -130 213 -111 c 0,30,31
+ 214 -107 214 -107 214.5 -104 c 128,-1,32
+ 215 -101 215 -101 215 -96 c 0,0,1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: hungarumlaut
+Encoding: 733 733 222
+Width: 682
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 28
+ 0
+ 18
+ 1
+ 0
+ 26
+ 1
+ 0
+ 9
+ 34
+ 1
+ 12
+ 9
+ 7
+ 33
+ 32
+ 28
+ 17
+ 14
+ 13
+ 6
+ 3
+ 0
+ 9
+ 113
+ 20
+ 11
+ 13
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+313 1477 m 2,0,-1
+ 449 1477 l 2,1,2
+ 500 1477 500 1477 500 1462 c 0,3,4
+ 500 1452 500 1452 438 1390 c 128,-1,5
+ 376 1328 376 1328 272 1237 c 0,6,7
+ 255 1223 255 1223 209 1209.5 c 128,-1,8
+ 163 1196 163 1196 129 1196 c 0,9,10
+ 86 1196 86 1196 86 1221 c 0,11,12
+ 86 1241 86 1241 113 1280 c 1,13,-1
+ 158 1364 l 2,14,15
+ 199 1437 199 1437 227.5 1457 c 128,-1,16
+ 256 1477 256 1477 313 1477 c 2,0,-1
+670 1477 m 2,17,-1
+ 805 1477 l 2,18,19
+ 856 1477 856 1477 856 1462 c 0,20,21
+ 856 1452 856 1452 790 1386 c 128,-1,22
+ 724 1320 724 1320 629 1237 c 0,23,24
+ 613 1223 613 1223 566 1209.5 c 128,-1,25
+ 519 1196 519 1196 485 1196 c 0,26,27
+ 442 1196 442 1196 442 1221 c 0,28,29
+ 442 1229 442 1229 446 1238.5 c 128,-1,30
+ 450 1248 450 1248 455 1256.5 c 128,-1,31
+ 460 1265 460 1265 469 1280 c 2,32,-1
+ 514 1364 l 2,33,34
+ 541 1413 541 1413 562 1437 c 128,-1,35
+ 583 1461 583 1461 607.5 1469 c 128,-1,36
+ 632 1477 632 1477 670 1477 c 2,17,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: ogonek
+Encoding: 731 731 223
+Width: 682
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 17
+ 17
+ 1
+ 0
+ 65
+ 14
+ 24
+ 15
+ 7
+ 4
+ 7
+ 1
+ 0
+ 155
+ 12
+ 0
+ 15
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+94 -190 m 0,0,1
+ 94 -137 94 -137 131 -79.5 c 128,-1,2
+ 168 -22 168 -22 217.5 16.5 c 128,-1,3
+ 267 55 267 55 301 55 c 0,4,5
+ 331 55 331 55 354 29.5 c 128,-1,6
+ 377 4 377 4 377 -23 c 0,7,8
+ 377 -43 377 -43 367 -56.5 c 128,-1,9
+ 357 -70 357 -70 334 -96 c 0,10,11
+ 291 -139 291 -139 291 -168 c 0,12,13
+ 291 -215 291 -215 362 -215 c 0,14,15
+ 384 -215 384 -215 440.5 -197.5 c 128,-1,16
+ 497 -180 497 -180 518 -180 c 0,17,18
+ 549 -180 549 -180 568.5 -201.5 c 128,-1,19
+ 588 -223 588 -223 588 -250 c 0,20,21
+ 588 -287 588 -287 548 -314.5 c 128,-1,22
+ 508 -342 508 -342 444 -356.5 c 128,-1,23
+ 380 -371 380 -371 326 -371 c 0,24,25
+ 257 -371 257 -371 204.5 -349.5 c 128,-1,26
+ 152 -328 152 -328 123 -286.5 c 128,-1,27
+ 94 -245 94 -245 94 -190 c 0,0,1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: caron
+Encoding: 711 711 224
+Width: 682
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 19
+ 0
+ 28
+ 1
+ 0
+ 0
+ 1
+ 0
+ 2
+ 17
+ 32
+ 6
+ 12
+ 9
+ 7
+ 117
+ 8
+ 24
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+242 1417 m 2,0,-1
+ 342 1300 l 1,1,-1
+ 440 1417 l 2,2,3
+ 482 1467 482 1467 497.5 1478 c 128,-1,4
+ 513 1489 513 1489 555 1489 c 2,5,-1
+ 635 1489 l 2,6,7
+ 676 1489 676 1489 676 1475 c 0,8,9
+ 676 1464 676 1464 645 1425 c 2,10,-1
+ 535 1292 l 2,11,12
+ 510 1262 510 1262 497.5 1247 c 128,-1,13
+ 485 1232 485 1232 468 1220.5 c 128,-1,14
+ 451 1209 451 1209 427.5 1204.5 c 128,-1,15
+ 404 1200 404 1200 371 1200 c 2,16,-1
+ 315 1200 l 2,17,18
+ 270 1200 270 1200 244.5 1208.5 c 128,-1,19
+ 219 1217 219 1217 207.5 1229 c 128,-1,20
+ 196 1241 196 1241 152 1292 c 2,21,-1
+ 37 1427 l 2,22,23
+ 8 1465 8 1465 8 1475 c 0,24,25
+ 8 1487 8 1487 15.5 1488 c 128,-1,26
+ 23 1489 23 1489 51 1489 c 2,27,-1
+ 129 1489 l 2,28,29
+ 171 1489 171 1489 187.5 1476 c 128,-1,30
+ 204 1463 204 1463 242 1417 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: Scaron
+Encoding: 352 352 225
+Width: 1366
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 54 83 N 1 0 0 1 0 0 2
+Refer: 224 711 N 1 0 0 1 342 371 2
+Validated: 1
+EndChar
+
+StartChar: scaron
+Encoding: 353 353 226
+Width: 1110
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 86 115 N 1 0 0 1 0 0 2
+Refer: 224 711 N 1 0 0 1 170 0 2
+Validated: 1
+EndChar
+
+StartChar: brokenbar
+Encoding: 166 166 227
+Width: 575
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 18
+ 25
+ 12
+ 18
+ 11
+ 4
+ 7
+ 0
+ 15
+ 1
+ 0
+ 22
+ 1
+ 0
+ 153
+ 1
+ 8
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MIAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+399 223 m 2,0,-1
+ 399 -244 l 2,1,2
+ 399 -331 399 -331 382 -380.5 c 128,-1,3
+ 365 -430 365 -430 289 -430 c 0,4,5
+ 240 -430 240 -430 208 -395 c 128,-1,6
+ 176 -360 176 -360 176 -293 c 2,7,-1
+ 176 223 l 2,8,9
+ 176 290 176 290 208 325 c 128,-1,10
+ 240 360 240 360 289 360 c 256,11,12
+ 338 360 338 360 368.5 324.5 c 128,-1,13
+ 399 289 399 289 399 223 c 2,0,-1
+399 1354 m 2,14,-1
+ 399 838 l 2,15,16
+ 399 768 399 768 368.5 734 c 128,-1,17
+ 338 700 338 700 289 700 c 256,18,19
+ 240 700 240 700 208 735 c 128,-1,20
+ 176 770 176 770 176 838 c 2,21,-1
+ 176 1354 l 2,22,23
+ 176 1421 176 1421 208 1456 c 128,-1,24
+ 240 1491 240 1491 289 1491 c 256,25,26
+ 338 1491 338 1491 368.5 1455.5 c 128,-1,27
+ 399 1420 399 1420 399 1354 c 2,14,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: Eth
+Encoding: 208 208 228
+Width: 1516
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 53
+ 42
+ 41
+ 12
+ 12
+ 12
+ 0
+ 43
+ 1
+ 0
+ 28
+ 1
+ 0
+ 55
+ 6
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ 31
+ 41
+ 24
+ 9
+ 8
+ 3
+ 7
+ 47
+ 28
+ 2
+ 36
+ 30
+ 1
+ 128
+ 17
+ 36
+ 10
+ 0
+ 43
+ 1
+ 4
+ 1
+ 0
+ 1
+ 0
+ 129
+ 30
+ 7
+ 0
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+162 209 m 2,0,-1
+ 162 639 l 1,1,-1
+ 119 639 l 2,2,3
+ 0 639 0 639 0 733 c 256,4,5
+ 0 827 0 827 119 827 c 2,6,-1
+ 162 827 l 1,7,-1
+ 162 1284 l 2,8,9
+ 162 1380 162 1380 205 1423 c 128,-1,10
+ 248 1466 248 1466 344 1466 c 2,11,-1
+ 731 1466 l 2,12,13
+ 882 1466 882 1466 989 1438 c 128,-1,14
+ 1096 1410 1096 1410 1186 1333 c 0,15,16
+ 1415 1137 1415 1137 1415 737 c 0,17,18
+ 1415 536 1415 536 1363 391 c 128,-1,19
+ 1311 246 1311 246 1196 143 c 0,20,21
+ 1109 65 1109 65 999 32.5 c 128,-1,22
+ 889 0 889 0 735 0 c 2,23,-1
+ 350 0 l 2,24,25
+ 269 0 269 0 228 24.5 c 128,-1,26
+ 187 49 187 49 174.5 93.5 c 128,-1,27
+ 162 138 162 138 162 209 c 2,0,-1
+686 639 m 2,28,-1
+ 459 639 l 1,29,-1
+ 459 236 l 1,30,-1
+ 682 236 l 2,31,32
+ 814 236 814 236 888.5 261 c 128,-1,33
+ 963 286 963 286 1024 371 c 0,34,35
+ 1114 497 1114 497 1114 739 c 0,36,37
+ 1114 906 1114 906 1074.5 1007 c 128,-1,38
+ 1035 1108 1035 1108 970 1156 c 128,-1,39
+ 905 1204 905 1204 829 1217.5 c 128,-1,40
+ 753 1231 753 1231 653 1231 c 2,41,-1
+ 459 1231 l 1,42,-1
+ 459 827 l 1,43,-1
+ 625 827 l 2,44,45
+ 706 827 706 827 745 812.5 c 128,-1,46
+ 784 798 784 798 784 733 c 0,47,48
+ 784 689 784 689 757 664 c 128,-1,49
+ 730 639 730 639 686 639 c 2,28,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: eth
+Encoding: 240 240 229
+Width: 1237
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 61
+ 25
+ 22
+ 2
+ 0
+ 0
+ 0
+ 19
+ 1
+ 61
+ 52
+ 17
+ 10
+ 9
+ 54
+ 52
+ 9
+ 9
+ 11
+ 2
+ 7
+ 44
+ 12
+ 40
+ 37
+ 12
+ 41
+ 40
+ 31
+ 23
+ 22
+ 0
+ 6
+ 58
+ 50
+ 1
+ 0
+ 0
+ 19
+ 1
+ 2
+ 0
+ 47
+ 1
+ 136
+ 5
+ 58
+ 0
+ 34
+ 32
+ 2
+ 0
+ 0
+ 0
+ 28
+ 1
+ 136
+ 50
+ 13
+ 0
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MDAP[rnd]
+MIAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+807 1319 m 2,0,-1
+ 797 1313 l 1,1,2
+ 920 1195 920 1195 1001 1067 c 128,-1,3
+ 1082 939 1082 939 1122.5 807 c 128,-1,4
+ 1163 675 1163 675 1163 547 c 0,5,6
+ 1163 372 1163 372 1094.5 241 c 128,-1,7
+ 1026 110 1026 110 902.5 41.5 c 128,-1,8
+ 779 -27 779 -27 616 -27 c 0,9,10
+ 452 -27 452 -27 329 44 c 128,-1,11
+ 206 115 206 115 139 241 c 128,-1,12
+ 72 367 72 367 72 532 c 0,13,14
+ 72 690 72 690 144 810.5 c 128,-1,15
+ 216 931 216 931 335 996 c 128,-1,16
+ 454 1061 454 1061 588 1061 c 0,17,18
+ 660 1061 660 1061 723 1034 c 1,19,20
+ 691 1082 691 1082 656.5 1121 c 128,-1,21
+ 622 1160 622 1160 586 1196 c 1,22,-1
+ 496 1147 l 2,23,24
+ 420 1102 420 1102 391 1102 c 256,25,26
+ 362 1102 362 1102 343 1126 c 128,-1,27
+ 324 1150 324 1150 324 1174 c 0,28,29
+ 324 1206 324 1206 346.5 1223.5 c 128,-1,30
+ 369 1241 369 1241 426 1274 c 2,31,-1
+ 471 1298 l 1,32,33
+ 418 1348 418 1348 418 1397 c 0,34,35
+ 418 1433 418 1433 445 1462 c 128,-1,36
+ 472 1491 472 1491 518 1491 c 0,37,38
+ 563 1491 563 1491 600 1470.5 c 128,-1,39
+ 637 1450 637 1450 684 1417 c 1,40,-1
+ 737 1446 l 2,41,42
+ 785 1473 785 1473 803.5 1481 c 128,-1,43
+ 822 1489 822 1489 842 1489 c 0,44,45
+ 871 1489 871 1489 890 1466.5 c 128,-1,46
+ 909 1444 909 1444 909 1419 c 0,47,48
+ 909 1388 909 1388 887.5 1370.5 c 128,-1,49
+ 866 1353 866 1353 807 1319 c 2,0,-1
+346 520 m 0,50,51
+ 346 411 346 411 381.5 334 c 128,-1,52
+ 417 257 417 257 478.5 216.5 c 128,-1,53
+ 540 176 540 176 616 176 c 0,54,55
+ 690 176 690 176 752.5 216 c 128,-1,56
+ 815 256 815 256 852 333 c 128,-1,57
+ 889 410 889 410 889 518 c 0,58,59
+ 889 680 889 680 815.5 769 c 128,-1,60
+ 742 858 742 858 618 858 c 0,61,62
+ 498 858 498 858 422 766.5 c 128,-1,63
+ 346 675 346 675 346 520 c 0,50,51
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: Yacute
+Encoding: 221 221 230
+Width: 1280
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 60 89 N 1 0 0 1 0 0 2
+Refer: 141 180 N 1 0 0 1 342 371 2
+Validated: 1
+EndChar
+
+StartChar: yacute
+Encoding: 253 253 231
+Width: 1110
+GlyphClass: 1
+Flags: W
+LayerCount: 2
+Fore
+Refer: 92 121 N 1 0 0 1 0 0 2
+Refer: 141 180 N 1 0 0 1 170 0 2
+Validated: 1
+EndChar
+
+StartChar: Thorn
+Encoding: 222 222 232
+Width: 1366
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 33
+ 46
+ 19
+ 29
+ 10
+ 46
+ 31
+ 0
+ 10
+ 2
+ 7
+ 12
+ 12
+ 5
+ 9
+ 0
+ 1
+ 35
+ 1
+ 1
+ 128
+ 26
+ 35
+ 10
+ 0
+ 30
+ 18
+ 2
+ 129
+ 1
+ 9
+ 15
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+729 287 m 2,0,-1
+ 457 287 l 1,1,-1
+ 457 154 l 2,2,3
+ 457 65 457 65 415 20 c 128,-1,4
+ 373 -25 373 -25 307 -25 c 256,5,6
+ 241 -25 241 -25 200.5 20.5 c 128,-1,7
+ 160 66 160 66 160 154 c 2,8,-1
+ 160 1313 l 2,9,10
+ 160 1401 160 1401 199.5 1446 c 128,-1,11
+ 239 1491 239 1491 307 1491 c 0,12,13
+ 348 1491 348 1491 383 1471.5 c 128,-1,14
+ 418 1452 418 1452 436 1419 c 0,15,16
+ 452 1393 452 1393 454.5 1358.5 c 128,-1,17
+ 457 1324 457 1324 457 1245 c 2,18,-1
+ 457 1180 l 1,19,-1
+ 729 1180 l 2,20,21
+ 887 1180 887 1180 985.5 1156 c 128,-1,22
+ 1084 1132 1084 1132 1159 1057 c 0,23,24
+ 1220 996 1220 996 1249 918 c 128,-1,25
+ 1278 840 1278 840 1278 741 c 0,26,27
+ 1278 287 1278 287 729 287 c 2,0,-1
+657 956 m 2,28,-1
+ 457 956 l 1,29,-1
+ 457 510 l 1,30,-1
+ 657 510 l 2,31,32
+ 760 510 760 510 831 531 c 128,-1,33
+ 902 552 902 552 939.5 601.5 c 128,-1,34
+ 977 651 977 651 977 733 c 0,35,36
+ 977 826 977 826 920 891 c 1,37,38
+ 856 956 856 956 657 956 c 2,28,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: thorn
+Encoding: 254 254 233
+Width: 1280
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 42
+ 0
+ 0
+ 0
+ 0
+ 1
+ 1
+ 33
+ 52
+ 4
+ 10
+ 9
+ 0
+ 0
+ 0
+ 0
+ 16
+ 1
+ 39
+ 49
+ 13
+ 9
+ 8
+ 2
+ 7
+ 26
+ 12
+ 19
+ 7
+ 136
+ 8
+ 29
+ 10
+ 36
+ 1
+ 0
+ 1
+ 141
+ 16
+ 23
+ 15
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+MIAP[rnd]
+MIAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+393 1335 m 2,0,-1
+ 393 899 l 1,1,2
+ 470 994 470 994 553 1038.5 c 128,-1,3
+ 636 1083 636 1083 741 1083 c 0,4,5
+ 867 1083 867 1083 973 1018 c 128,-1,6
+ 1079 953 1079 953 1140.5 828 c 128,-1,7
+ 1202 703 1202 703 1202 532 c 0,8,9
+ 1202 406 1202 406 1166.5 300.5 c 128,-1,10
+ 1131 195 1131 195 1069 123.5 c 128,-1,11
+ 1007 52 1007 52 922.5 13.5 c 128,-1,12
+ 838 -25 838 -25 741 -25 c 0,13,14
+ 624 -25 624 -25 544.5 22 c 128,-1,15
+ 465 69 465 69 393 160 c 1,16,-1
+ 393 -250 l 2,17,18
+ 393 -430 393 -430 262 -430 c 0,19,20
+ 185 -430 185 -430 160 -383.5 c 128,-1,21
+ 135 -337 135 -337 135 -248 c 2,22,-1
+ 135 1335 l 2,23,24
+ 135 1414 135 1414 169 1452.5 c 128,-1,25
+ 203 1491 203 1491 262 1491 c 0,26,27
+ 320 1491 320 1491 356.5 1452 c 128,-1,28
+ 393 1413 393 1413 393 1335 c 2,0,-1
+928 535 m 0,29,30
+ 928 643 928 643 895 720.5 c 128,-1,31
+ 862 798 862 798 803.5 839.5 c 128,-1,32
+ 745 881 745 881 674 881 c 0,33,34
+ 561 881 561 881 483.5 792 c 128,-1,35
+ 406 703 406 703 406 530 c 0,36,37
+ 406 367 406 367 483 276.5 c 128,-1,38
+ 560 186 560 186 674 186 c 0,39,40
+ 742 186 742 186 800 225.5 c 128,-1,41
+ 858 265 858 265 893 344 c 128,-1,42
+ 928 423 928 423 928 535 c 0,29,30
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: multiply
+Encoding: 215 215 234
+Width: 1194
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 34
+ 0
+ 6
+ 1
+ 10
+ 1
+ 0
+ 11
+ 9
+ 8
+ 7
+ 5
+ 5
+ 19
+ 4
+ 0
+ 0
+ 7
+ 9
+ 1
+ 0
+ 0
+ 0
+ 11
+ 10
+ 8
+ 2
+ 1
+ 0
+ 6
+ 109
+ 7
+ 3
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+293 238 m 1,0,-1
+ 111 420 l 1,1,-1
+ 412 721 l 1,2,-1
+ 109 1026 l 1,3,-1
+ 295 1210 l 1,4,-1
+ 598 907 l 1,5,-1
+ 901 1210 l 1,6,-1
+ 1081 1028 l 1,7,-1
+ 780 725 l 1,8,-1
+ 1083 422 l 1,9,-1
+ 899 236 l 1,10,-1
+ 594 541 l 1,11,-1
+ 293 238 l 1,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: onesuperior
+Encoding: 185 185 235
+Width: 725
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 10
+ 19
+ 13
+ 12
+ 3
+ 1
+ 157
+ 17
+ 0
+ 10
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MDAP[rnd]
+MIAP[rnd]
+MDAP[rnd]
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+332 805 m 2,0,-1
+ 332 1227 l 1,1,2
+ 192 1141 192 1141 143 1141 c 0,3,4
+ 113 1141 113 1141 90.5 1160.5 c 128,-1,5
+ 68 1180 68 1180 68 1208 c 0,6,7
+ 68 1259 68 1259 160 1288 c 0,8,9
+ 225 1310 225 1310 266.5 1340 c 128,-1,10
+ 308 1370 308 1370 340.5 1409 c 128,-1,11
+ 373 1448 373 1448 389 1461.5 c 128,-1,12
+ 405 1475 405 1475 436 1475 c 0,13,14
+ 473 1475 473 1475 495.5 1450.5 c 128,-1,15
+ 518 1426 518 1426 518 1384 c 2,16,-1
+ 518 825 l 2,17,18
+ 518 711 518 711 424 711 c 0,19,20
+ 384 711 384 711 358 736 c 128,-1,21
+ 332 761 332 761 332 805 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: twosuperior
+Encoding: 178 178 236
+Width: 725
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 30
+ 0
+ 0
+ 20
+ 1
+ 0
+ 0
+ 15
+ 75
+ 27
+ 12
+ 9
+ 67
+ 34
+ 1
+ 10
+ 2
+ 7
+ 38
+ 1
+ 0
+ 34
+ 1
+ 0
+ 0
+ 1
+ 157
+ 30
+ 12
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+598 723 m 2,0,-1
+ 164 723 l 2,1,2
+ 113 723 113 723 85 748 c 128,-1,3
+ 57 773 57 773 57 807 c 0,4,5
+ 57 843 57 843 82 875.5 c 128,-1,6
+ 107 908 107 908 147 941 c 128,-1,7
+ 187 974 187 974 268 1036 c 0,8,9
+ 275 1041 275 1041 349.5 1092.5 c 128,-1,10
+ 424 1144 424 1144 454.5 1178 c 128,-1,11
+ 485 1212 485 1212 485 1253 c 0,12,13
+ 485 1297 485 1297 451.5 1322.5 c 128,-1,14
+ 418 1348 418 1348 365 1348 c 0,15,16
+ 309 1348 309 1348 281.5 1326 c 128,-1,17
+ 254 1304 254 1304 232.5 1260.5 c 128,-1,18
+ 211 1217 211 1217 195 1199.5 c 128,-1,19
+ 179 1182 179 1182 139 1182 c 0,20,21
+ 105 1182 105 1182 82 1202.5 c 128,-1,22
+ 59 1223 59 1223 59 1257 c 0,23,24
+ 59 1306 59 1306 93 1356.5 c 128,-1,25
+ 127 1407 127 1407 197 1440 c 128,-1,26
+ 267 1473 267 1473 369 1473 c 0,27,28
+ 522 1473 522 1473 597 1409.5 c 128,-1,29
+ 672 1346 672 1346 672 1255 c 0,30,31
+ 672 1172 672 1172 613 1110.5 c 128,-1,32
+ 554 1049 554 1049 444.5 976.5 c 128,-1,33
+ 335 904 335 904 303 868 c 1,34,-1
+ 580 868 l 2,35,36
+ 631 868 631 868 658.5 848.5 c 128,-1,37
+ 686 829 686 829 686 795 c 0,38,39
+ 686 766 686 766 663.5 744.5 c 128,-1,40
+ 641 723 641 723 598 723 c 2,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: threesuperior
+Encoding: 179 179 237
+Width: 725
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 48
+ 20
+ 17
+ 2
+ 13
+ 6
+ 50
+ 47
+ 2
+ 59
+ 53
+ 2
+ 1
+ 13
+ 75
+ 27
+ 12
+ 12
+ 0
+ 0
+ 0
+ 1
+ 0
+ 34
+ 1
+ 6
+ 75
+ 59
+ 10
+ 8
+ 75
+ 53
+ 40
+ 10
+ 3
+ 7
+ 0
+ 0
+ 10
+ 1
+ 0
+ 34
+ 31
+ 2
+ 157
+ 37
+ 56
+ 0
+ 7
+CALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+291 1051 m 0,0,1
+ 259 1051 259 1051 237 1068 c 128,-1,2
+ 215 1085 215 1085 215 1114 c 0,3,4
+ 215 1145 215 1145 238.5 1163.5 c 128,-1,5
+ 262 1182 262 1182 303 1182 c 2,6,-1
+ 340 1182 l 2,7,8
+ 383 1182 383 1182 419 1205 c 128,-1,9
+ 455 1228 455 1228 455 1270 c 0,10,11
+ 455 1306 455 1306 427.5 1328 c 128,-1,12
+ 400 1350 400 1350 352 1350 c 0,13,14
+ 310 1350 310 1350 286 1338.5 c 128,-1,15
+ 262 1327 262 1327 252 1311.5 c 128,-1,16
+ 242 1296 242 1296 219 1251 c 0,17,18
+ 215 1241 215 1241 195.5 1231 c 128,-1,19
+ 176 1221 176 1221 156 1221 c 0,20,21
+ 123 1221 123 1221 100.5 1242.5 c 128,-1,22
+ 78 1264 78 1264 78 1292 c 0,23,24
+ 78 1335 78 1335 113 1377 c 128,-1,25
+ 148 1419 148 1419 213 1447 c 128,-1,26
+ 278 1475 278 1475 365 1475 c 0,27,28
+ 448 1475 448 1475 510.5 1449 c 128,-1,29
+ 573 1423 573 1423 607 1379 c 128,-1,30
+ 641 1335 641 1335 641 1280 c 0,31,32
+ 641 1232 641 1232 618 1197.5 c 128,-1,33
+ 595 1163 595 1163 553 1128 c 1,34,35
+ 615 1098 615 1098 647.5 1052 c 128,-1,36
+ 680 1006 680 1006 680 950 c 0,37,38
+ 680 850 680 850 590 777.5 c 128,-1,39
+ 500 705 500 705 356 705 c 0,40,41
+ 263 705 263 705 193 740.5 c 128,-1,42
+ 123 776 123 776 87 827 c 128,-1,43
+ 51 878 51 878 51 920 c 0,44,45
+ 51 948 51 948 76 970.5 c 128,-1,46
+ 101 993 101 993 139 993 c 0,47,48
+ 160 993 160 993 180 982.5 c 128,-1,49
+ 200 972 200 972 205 958 c 0,50,51
+ 236 889 236 889 266.5 859 c 128,-1,52
+ 297 829 297 829 356 829 c 0,53,54
+ 411 829 411 829 452.5 861 c 128,-1,55
+ 494 893 494 893 494 946 c 0,56,57
+ 494 997 494 997 460.5 1027 c 128,-1,58
+ 427 1057 427 1057 369 1057 c 0,59,60
+ 355 1057 355 1057 347.5 1056.5 c 128,-1,61
+ 340 1056 340 1056 329 1055 c 128,-1,62
+ 318 1054 318 1054 307.5 1052.5 c 128,-1,63
+ 297 1051 297 1051 291 1051 c 0,0,1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: onehalf
+Encoding: 189 189 238
+Width: 1749
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 62
+ 0
+ 0
+ 42
+ 1
+ 0
+ 19
+ 1
+ 75
+ 49
+ 37
+ 0
+ 0
+ 0
+ 68
+ 1
+ 66
+ 1
+ 73
+ 1
+ 58
+ 68
+ 23
+ 9
+ 8
+ 2
+ 7
+ 77
+ 12
+ 13
+ 12
+ 3
+ 1
+ 74
+ 65
+ 45
+ 26
+ 4
+ 34
+ 17
+ 1
+ 62
+ 1
+ 0
+ 80
+ 58
+ 2
+ 0
+ 22
+ 1
+ 157
+ 53
+ 34
+ 0
+ 73
+ 71
+ 2
+ 157
+ 17
+ 0
+ 13
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MDAP[rnd]
+MIAP[rnd]
+MIAP[rnd]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+332 805 m 2,0,-1
+ 332 1227 l 1,1,2
+ 192 1141 192 1141 143 1141 c 0,3,4
+ 113 1141 113 1141 90.5 1160.5 c 128,-1,5
+ 68 1180 68 1180 68 1208 c 0,6,7
+ 68 1259 68 1259 160 1288 c 0,8,9
+ 225 1310 225 1310 266.5 1340 c 128,-1,10
+ 308 1370 308 1370 340.5 1409 c 128,-1,11
+ 373 1448 373 1448 389 1461.5 c 128,-1,12
+ 405 1475 405 1475 436 1475 c 0,13,14
+ 473 1475 473 1475 495.5 1450.5 c 128,-1,15
+ 518 1426 518 1426 518 1384 c 2,16,-1
+ 518 825 l 2,17,18
+ 518 711 518 711 424 711 c 0,19,20
+ 384 711 384 711 358 736 c 128,-1,21
+ 332 761 332 761 332 805 c 2,0,-1
+1622 0 m 2,22,-1
+ 1188 0 l 2,23,24
+ 1138 0 1138 0 1109.5 24 c 128,-1,25
+ 1081 48 1081 48 1081 82 c 0,26,27
+ 1081 118 1081 118 1106 150.5 c 128,-1,28
+ 1131 183 1131 183 1171 216 c 128,-1,29
+ 1211 249 1211 249 1292 311 c 0,30,31
+ 1299 316 1299 316 1373.5 367.5 c 128,-1,32
+ 1448 419 1448 419 1478.5 453 c 128,-1,33
+ 1509 487 1509 487 1509 528 c 0,34,35
+ 1509 570 1509 570 1474.5 597.5 c 128,-1,36
+ 1440 625 1440 625 1389 625 c 0,37,38
+ 1333 625 1333 625 1306 604 c 128,-1,39
+ 1279 583 1279 583 1260 541.5 c 128,-1,40
+ 1241 500 1241 500 1223 479.5 c 128,-1,41
+ 1205 459 1205 459 1165 459 c 0,42,43
+ 1131 459 1131 459 1107 478 c 128,-1,44
+ 1083 497 1083 497 1083 532 c 0,45,46
+ 1083 582 1083 582 1117 633 c 128,-1,47
+ 1151 684 1151 684 1221.5 717 c 128,-1,48
+ 1292 750 1292 750 1393 750 c 0,49,50
+ 1498 750 1498 750 1565 720 c 128,-1,51
+ 1632 690 1632 690 1664 640 c 128,-1,52
+ 1696 590 1696 590 1696 532 c 0,53,54
+ 1696 467 1696 467 1657.5 414.5 c 128,-1,55
+ 1619 362 1619 362 1543.5 308 c 128,-1,56
+ 1468 254 1468 254 1411 214.5 c 128,-1,57
+ 1354 175 1354 175 1327 143 c 1,58,-1
+ 1604 143 l 2,59,60
+ 1655 143 1655 143 1682.5 124 c 128,-1,61
+ 1710 105 1710 105 1710 72 c 0,62,63
+ 1710 43 1710 43 1687.5 21.5 c 128,-1,64
+ 1665 0 1665 0 1622 0 c 2,22,-1
+1339 1343 m 2,65,-1
+ 506 0 l 2,66,67
+ 472 -55 472 -55 432 -55 c 0,68,69
+ 408 -55 408 -55 385 -37.5 c 128,-1,70
+ 362 -20 362 -20 362 8 c 0,71,72
+ 362 28 362 28 383 59 c 2,73,-1
+ 1223 1413 l 2,74,75
+ 1246 1453 1246 1453 1261.5 1470 c 128,-1,76
+ 1277 1487 1277 1487 1309 1487 c 0,77,78
+ 1339 1487 1339 1487 1356.5 1469.5 c 128,-1,79
+ 1374 1452 1374 1452 1374 1423 c 0,80,81
+ 1374 1399 1374 1399 1339 1343 c 2,65,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: onequarter
+Encoding: 188 188 239
+Width: 1749
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 55
+ 0
+ 53
+ 1
+ 49
+ 1
+ 44
+ 1
+ 0
+ 71
+ 38
+ 23
+ 0
+ 7
+ 69
+ 12
+ 58
+ 54
+ 34
+ 19
+ 13
+ 12
+ 3
+ 1
+ 56
+ 55
+ 52
+ 31
+ 30
+ 27
+ 6
+ 22
+ 17
+ 1
+ 42
+ 1
+ 45
+ 1
+ 72
+ 1
+ 54
+ 1
+ 0
+ 162
+ 37
+ 22
+ 0
+ 63
+ 61
+ 2
+ 157
+ 17
+ 0
+ 13
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+MDAP[rnd]
+MIAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MDAP[rnd]
+MIAP[rnd]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+332 805 m 2,0,-1
+ 332 1227 l 1,1,2
+ 192 1141 192 1141 143 1141 c 0,3,4
+ 113 1141 113 1141 90.5 1160.5 c 128,-1,5
+ 68 1180 68 1180 68 1208 c 0,6,7
+ 68 1259 68 1259 160 1288 c 0,8,9
+ 225 1310 225 1310 266.5 1340 c 128,-1,10
+ 308 1370 308 1370 340.5 1409 c 128,-1,11
+ 373 1448 373 1448 389 1461.5 c 128,-1,12
+ 405 1475 405 1475 436 1475 c 0,13,14
+ 473 1475 473 1475 495.5 1450.5 c 128,-1,15
+ 518 1426 518 1426 518 1384 c 2,16,-1
+ 518 825 l 2,17,18
+ 518 711 518 711 424 711 c 0,19,20
+ 384 711 384 711 358 736 c 128,-1,21
+ 332 761 332 761 332 805 c 2,0,-1
+1438 76 m 2,22,-1
+ 1438 154 l 1,23,-1
+ 1153 154 l 2,24,25
+ 1092 154 1092 154 1061 179.5 c 128,-1,26
+ 1030 205 1030 205 1030 246 c 0,27,28
+ 1030 270 1030 270 1044.5 289 c 128,-1,29
+ 1059 308 1059 308 1087 338 c 2,30,-1
+ 1401 686 l 2,31,32
+ 1432 721 1432 721 1455 738.5 c 128,-1,33
+ 1478 756 1478 756 1507 756 c 0,34,35
+ 1556 756 1556 756 1583 730 c 128,-1,36
+ 1610 704 1610 704 1610 655 c 2,37,-1
+ 1610 291 l 1,38,-1
+ 1651 291 l 2,39,40
+ 1691 291 1691 291 1714 270.5 c 128,-1,41
+ 1737 250 1737 250 1737 221 c 0,42,43
+ 1737 154 1737 154 1634 154 c 2,44,-1
+ 1610 154 l 1,45,-1
+ 1610 76 l 2,46,47
+ 1610 32 1610 32 1585.5 10 c 128,-1,48
+ 1561 -12 1561 -12 1524 -12 c 256,49,50
+ 1487 -12 1487 -12 1462.5 9.5 c 128,-1,51
+ 1438 31 1438 31 1438 76 c 2,22,-1
+1227 291 m 1,52,-1
+ 1438 291 l 1,53,-1
+ 1438 528 l 1,54,-1
+ 1227 291 l 1,52,-1
+1356 1343 m 2,55,-1
+ 522 0 l 2,56,57
+ 490 -55 490 -55 451 -55 c 0,58,59
+ 427 -55 427 -55 404 -37.5 c 128,-1,60
+ 381 -20 381 -20 381 8 c 0,61,62
+ 381 29 381 29 401 59 c 2,63,-1
+ 1241 1413 l 2,64,65
+ 1250 1427 1250 1427 1258.5 1441 c 128,-1,66
+ 1267 1455 1267 1455 1275.5 1465 c 128,-1,67
+ 1284 1475 1284 1475 1296.5 1481 c 128,-1,68
+ 1309 1487 1309 1487 1327 1487 c 0,69,70
+ 1359 1487 1359 1487 1376 1469 c 128,-1,71
+ 1393 1451 1393 1451 1393 1423 c 0,72,73
+ 1393 1405 1393 1405 1356 1343 c 2,55,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: threequarters
+Encoding: 190 190 240
+Width: 1749
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 107
+ 70
+ 67
+ 31
+ 3
+ 63
+ 56
+ 100
+ 97
+ 2
+ 109
+ 103
+ 8
+ 7
+ 2
+ 90
+ 15
+ 3
+ 1
+ 43
+ 1
+ 0
+ 0
+ 0
+ 40
+ 1
+ 63
+ 75
+ 77
+ 12
+ 9
+ 0
+ 0
+ 50
+ 1
+ 0
+ 84
+ 1
+ 56
+ 75
+ 109
+ 10
+ 8
+ 0
+ 0
+ 30
+ 1
+ 0
+ 11
+ 1
+ 75
+ 103
+ 90
+ 0
+ 0
+ 29
+ 1
+ 26
+ 1
+ 21
+ 1
+ 0
+ 71
+ 15
+ 1
+ 0
+ 4
+ 7
+ 34
+ 40
+ 31
+ 28
+ 8
+ 7
+ 4
+ 6
+ 0
+ 87
+ 1
+ 19
+ 1
+ 22
+ 1
+ 46
+ 1
+ 30
+ 1
+ 0
+ 163
+ 14
+ 0
+ 0
+ 0
+ 0
+ 60
+ 37
+ 2
+ 0
+ 84
+ 81
+ 32
+ 3
+ 157
+ 87
+ 106
+ 0
+ 2
+ 7
+LOOPCALL
+CALL
+IUP[x]
+SVTCA[y-axis]
+MDAP[rnd]
+LOOPCALL
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+1440 76 m 2,0,-1
+ 1440 154 l 1,1,-1
+ 1155 154 l 2,2,3
+ 1032 154 1032 154 1032 246 c 0,4,5
+ 1032 270 1032 270 1044.5 286.5 c 128,-1,6
+ 1057 303 1057 303 1090 338 c 2,7,-1
+ 1403 686 l 2,8,9
+ 1438 723 1438 723 1458.5 739.5 c 128,-1,10
+ 1479 756 1479 756 1509 756 c 0,11,12
+ 1558 756 1558 756 1584 730 c 128,-1,13
+ 1610 704 1610 704 1610 655 c 2,14,-1
+ 1610 291 l 1,15,-1
+ 1653 291 l 2,16,17
+ 1694 291 1694 291 1715.5 270.5 c 128,-1,18
+ 1737 250 1737 250 1737 221 c 0,19,20
+ 1737 154 1737 154 1634 154 c 2,21,-1
+ 1610 154 l 1,22,-1
+ 1610 76 l 2,23,24
+ 1610 31 1610 31 1587 9.5 c 128,-1,25
+ 1564 -12 1564 -12 1526 -12 c 0,26,27
+ 1440 -12 1440 -12 1440 76 c 2,0,-1
+1229 291 m 1,28,-1
+ 1440 291 l 1,29,-1
+ 1440 528 l 1,30,-1
+ 1229 291 l 1,28,-1
+1395 1343 m 2,31,-1
+ 561 0 l 2,32,33
+ 529 -55 529 -55 487 -55 c 0,34,35
+ 463 -55 463 -55 440.5 -37 c 128,-1,36
+ 418 -19 418 -19 418 8 c 0,37,38
+ 418 29 418 29 438 59 c 2,39,-1
+ 1278 1413 l 2,40,41
+ 1301 1453 1301 1453 1316.5 1470 c 128,-1,42
+ 1332 1487 1332 1487 1364 1487 c 0,43,44
+ 1395 1487 1395 1487 1412.5 1469.5 c 128,-1,45
+ 1430 1452 1430 1452 1430 1423 c 0,46,47
+ 1430 1412 1430 1412 1425.5 1399 c 128,-1,48
+ 1421 1386 1421 1386 1412 1371.5 c 128,-1,49
+ 1403 1357 1403 1357 1395 1343 c 2,31,-1
+293 1051 m 0,50,51
+ 261 1051 261 1051 239 1068 c 128,-1,52
+ 217 1085 217 1085 217 1114 c 0,53,54
+ 217 1145 217 1145 240.5 1163.5 c 128,-1,55
+ 264 1182 264 1182 305 1182 c 2,56,-1
+ 342 1182 l 2,57,58
+ 385 1182 385 1182 421 1205 c 128,-1,59
+ 457 1228 457 1228 457 1270 c 0,60,61
+ 457 1306 457 1306 429.5 1328 c 128,-1,62
+ 402 1350 402 1350 354 1350 c 0,63,64
+ 312 1350 312 1350 288 1338.5 c 128,-1,65
+ 264 1327 264 1327 254 1311.5 c 128,-1,66
+ 244 1296 244 1296 221 1251 c 0,67,68
+ 217 1241 217 1241 197.5 1231 c 128,-1,69
+ 178 1221 178 1221 158 1221 c 0,70,71
+ 125 1221 125 1221 102.5 1242.5 c 128,-1,72
+ 80 1264 80 1264 80 1292 c 0,73,74
+ 80 1335 80 1335 115 1377 c 128,-1,75
+ 150 1419 150 1419 215 1447 c 128,-1,76
+ 280 1475 280 1475 367 1475 c 0,77,78
+ 450 1475 450 1475 512.5 1449 c 128,-1,79
+ 575 1423 575 1423 609 1379 c 128,-1,80
+ 643 1335 643 1335 643 1280 c 0,81,82
+ 643 1232 643 1232 620 1197.5 c 128,-1,83
+ 597 1163 597 1163 555 1128 c 1,84,85
+ 617 1098 617 1098 649.5 1052 c 128,-1,86
+ 682 1006 682 1006 682 950 c 0,87,88
+ 682 850 682 850 592 777.5 c 128,-1,89
+ 502 705 502 705 358 705 c 0,90,91
+ 265 705 265 705 195 740.5 c 128,-1,92
+ 125 776 125 776 89 827 c 128,-1,93
+ 53 878 53 878 53 920 c 0,94,95
+ 53 948 53 948 78 970.5 c 128,-1,96
+ 103 993 103 993 141 993 c 0,97,98
+ 162 993 162 993 182 982.5 c 128,-1,99
+ 202 972 202 972 207 958 c 0,100,101
+ 238 889 238 889 268.5 859 c 128,-1,102
+ 299 829 299 829 358 829 c 0,103,104
+ 413 829 413 829 454.5 861 c 128,-1,105
+ 496 893 496 893 496 946 c 0,106,107
+ 496 996 496 996 462.5 1026.5 c 128,-1,108
+ 429 1057 429 1057 371 1057 c 0,109,110
+ 357 1057 357 1057 349.5 1056.5 c 128,-1,111
+ 342 1056 342 1056 331 1055 c 128,-1,112
+ 320 1054 320 1054 309.5 1052.5 c 128,-1,113
+ 299 1051 299 1051 293 1051 c 0,50,51
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: macron
+Encoding: 175 175 241
+Width: 1024
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 5
+ 81
+ 2
+ 0
+ 10
+ 7
+SVTCA[y-axis]
+CALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+-12 1654 m 1,0,-1
+ -12 1756 l 1,1,-1
+ 1036 1756 l 1,2,-1
+ 1036 1654 l 1,3,-1
+ -12 1654 l 1,0,-1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: currency
+Encoding: 164 164 242
+Width: 1130
+GlyphClass: 1
+Flags: W
+TtInstrs:
+NPUSHB
+ 64
+ 17
+ 6
+ 2
+ 0
+ 0
+ 0
+ 23
+ 14
+ 9
+ 0
+ 4
+ 40
+ 11
+ 67
+ 0
+ 0
+ 0
+ 45
+ 34
+ 2
+ 0
+ 51
+ 42
+ 37
+ 28
+ 4
+ 41
+ 59
+ 39
+ 0
+ 2
+ 7
+ 31
+ 20
+ 2
+ 0
+ 0
+ 0
+ 37
+ 28
+ 23
+ 14
+ 4
+ 149
+ 25
+ 63
+ 0
+ 0
+ 0
+ 48
+ 3
+ 2
+ 0
+ 51
+ 42
+ 9
+ 0
+ 4
+ 148
+ 55
+ 53
+ 0
+ 2
+ 7
+LOOPCALL
+IUP[x]
+SVTCA[y-axis]
+LOOPCALL
+IUP[y]
+EndTTInstrs
+LayerCount: 2
+Fore
+SplineSet
+176 938 m 1,0,1
+ 133 982 133 982 114.5 1008 c 128,-1,2
+ 96 1034 96 1034 96 1075 c 0,3,4
+ 96 1130 96 1130 127.5 1163 c 128,-1,5
+ 159 1196 159 1196 215 1196 c 0,6,7
+ 251 1196 251 1196 281.5 1175.5 c 128,-1,8
+ 312 1155 312 1155 350 1116 c 1,9,10
+ 456 1171 456 1171 565 1171 c 0,11,12
+ 636 1171 636 1171 687.5 1155.5 c 128,-1,13
+ 739 1140 739 1140 782 1116 c 1,14,15
+ 826 1160 826 1160 852 1178 c 128,-1,16
+ 878 1196 878 1196 915 1196 c 0,17,18
+ 971 1196 971 1196 1002.5 1162 c 128,-1,19
+ 1034 1128 1034 1128 1034 1075 c 0,20,21
+ 1034 1035 1034 1035 1014.5 1005.5 c 128,-1,22
+ 995 976 995 976 956 938 c 1,23,24
+ 1008 839 1008 839 1008 729 c 0,25,26
+ 1008 671 1008 671 995 621.5 c 128,-1,27
+ 982 572 982 572 956 520 c 1,28,29
+ 996 482 996 482 1015 453 c 128,-1,30
+ 1034 424 1034 424 1034 383 c 0,31,32
+ 1034 330 1034 330 1002 296 c 128,-1,33
+ 970 262 970 262 915 262 c 0,34,35
+ 880 262 880 262 855 279 c 128,-1,36
+ 830 296 830 296 782 342 c 1,37,38
+ 682 289 682 289 565 289 c 0,39,40
+ 497 289 497 289 452 301.5 c 128,-1,41
+ 407 314 407 314 350 342 c 1,42,43
+ 310 302 310 302 280.5 282 c 128,-1,44
+ 251 262 251 262 215 262 c 0,45,46
+ 159 262 159 262 127.5 295.5 c 128,-1,47
+ 96 329 96 329 96 383 c 0,48,49
+ 96 423 96 423 116 452.5 c 128,-1,50
+ 136 482 136 482 176 520 c 1,51,52
+ 123 630 123 630 123 729 c 0,53,54
+ 123 837 123 837 176 938 c 1,0,1
+365 729 m 0,55,56
+ 365 674 365 674 392 626.5 c 128,-1,57
+ 419 579 419 579 464.5 551.5 c 128,-1,58
+ 510 524 510 524 565 524 c 256,59,60
+ 620 524 620 524 666.5 551.5 c 128,-1,61
+ 713 579 713 579 740.5 626 c 128,-1,62
+ 768 673 768 673 768 729 c 0,63,64
+ 768 784 768 784 740.5 830.5 c 128,-1,65
+ 713 877 713 877 666 903.5 c 128,-1,66
+ 619 930 619 930 565 930 c 0,67,68
+ 510 930 510 930 464 903 c 128,-1,69
+ 418 876 418 876 391.5 829 c 128,-1,70
+ 365 782 365 782 365 729 c 0,55,56
+EndSplineSet
+Validated: 1
+EndChar
+EndChars
+EndSplineFont
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Assets/ArialRoundedMTBold.ttf b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Assets/ArialRoundedMTBold.ttf
new file mode 100644
index 0000000..12be6fd
Binary files /dev/null and b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Assets/ArialRoundedMTBold.ttf differ
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Assets/Controller - Microsoft Xbox One.otf b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Assets/Controller - Microsoft Xbox One.otf
new file mode 100644
index 0000000..eeb3a78
Binary files /dev/null and b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Assets/Controller - Microsoft Xbox One.otf differ
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Assets/file-fill.svg b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Assets/file-fill.svg
new file mode 100644
index 0000000..1eb3131
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Assets/file-fill.svg
@@ -0,0 +1,7 @@
+
+
+IcoFont Icons
+file-fill
+
+
+
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Assets/folder.svg b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Assets/folder.svg
new file mode 100644
index 0000000..566a1c0
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/Assets/folder.svg
@@ -0,0 +1,7 @@
+
+
+IcoFont Icons
+folder
+
+
+
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe.sln b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe.sln
new file mode 100644
index 0000000..260c4e8
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe.sln
@@ -0,0 +1,72 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PrometheOSXbe", "PrometheOSXbe\PrometheOSXbe.vcproj", "{03813F8D-2AD5-44E4-B724-44240DB90B0B}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug-Aladdin1mb = Debug-Aladdin1mb
+ Debug-Aladdin2mb = Debug-Aladdin2mb
+ Debug-Dummy = Debug-Dummy
+ Debug-Modxo = Debug-Modxo
+ Debug-Tools = Debug-Tools
+ Debug-Xchanger = Debug-Xchanger
+ Debug-Xecuter = Debug-Xecuter
+ Debug-Xenium = Debug-Xenium
+ Profile = Profile
+ Profile_FastCap = Profile_FastCap
+ Release_LTCG = Release_LTCG
+ Release-Aladdin1mb = Release-Aladdin1mb
+ Release-Aladdin2mb = Release-Aladdin2mb
+ Release-Dummy = Release-Dummy
+ Release-Modxo = Release-Modxo
+ Release-Tools = Release-Tools
+ Release-Xchanger = Release-Xchanger
+ Release-Xecuter = Release-Xecuter
+ Release-Xenium = Release-Xenium
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Debug-Aladdin1mb.ActiveCfg = Debug-Aladdin1mb|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Debug-Aladdin1mb.Build.0 = Debug-Aladdin1mb|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Debug-Aladdin2mb.ActiveCfg = Debug-Aladdin2mb|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Debug-Aladdin2mb.Build.0 = Debug-Aladdin2mb|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Debug-Dummy.ActiveCfg = Debug-Dummy|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Debug-Dummy.Build.0 = Debug-Dummy|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Debug-Modxo.ActiveCfg = Debug-Modxo|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Debug-Modxo.Build.0 = Debug-Modxo|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Debug-Tools.ActiveCfg = Debug-Tools|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Debug-Tools.Build.0 = Debug-Tools|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Debug-Xchanger.ActiveCfg = Debug-Xchanger|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Debug-Xchanger.Build.0 = Debug-Xchanger|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Debug-Xecuter.ActiveCfg = Debug-Xecuter|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Debug-Xecuter.Build.0 = Debug-Xecuter|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Debug-Xenium.ActiveCfg = Debug-Xenium|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Debug-Xenium.Build.0 = Debug-Xenium|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Profile.ActiveCfg = Profile|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Profile.Build.0 = Profile|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Profile_FastCap.ActiveCfg = Profile_FastCap|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Profile_FastCap.Build.0 = Profile_FastCap|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Release_LTCG.ActiveCfg = Release_LTCG|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Release_LTCG.Build.0 = Release_LTCG|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Release-Aladdin1mb.ActiveCfg = Release-Aladdin1mb|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Release-Aladdin1mb.Build.0 = Release-Aladdin1mb|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Release-Aladdin2mb.ActiveCfg = Release-Aladdin2mb|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Release-Aladdin2mb.Build.0 = Release-Aladdin2mb|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Release-Dummy.ActiveCfg = Release-Dummy|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Release-Dummy.Build.0 = Release-Dummy|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Release-Modxo.ActiveCfg = Release-Modxo|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Release-Modxo.Build.0 = Release-Modxo|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Release-Tools.ActiveCfg = Release-Tools|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Release-Tools.Build.0 = Release-Tools|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Release-Xchanger.ActiveCfg = Release-Xchanger|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Release-Xchanger.Build.0 = Release-Xchanger|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Release-Xecuter.ActiveCfg = Release-Xecuter|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Release-Xecuter.Build.0 = Release-Xecuter|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Release-Xenium.ActiveCfg = Release-Xenium|Xbox
+ {03813F8D-2AD5-44E4-B724-44240DB90B0B}.Release-Xenium.Build.0 = Release-Xenium|Xbox
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Font/freesans_sfn.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Font/freesans_sfn.h
new file mode 100644
index 0000000..af6ac9c
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Font/freesans_sfn.h
@@ -0,0 +1,801 @@
+#pragma once
+
+const uint8_t font_sfn[] = {
+ 0x53, 0x46, 0x4E, 0x32, 0x53, 0x25, 0x00, 0x00, 0x10, 0x00, 0xDF, 0xFF,
+ 0xD4, 0xF5, 0x79, 0x00, 0x07, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xAC, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x72, 0x69, 0x61,
+ 0x6C, 0x20, 0x42, 0x6F, 0x6C, 0x64, 0x00, 0x41, 0x72, 0x69, 0x61, 0x6C,
+ 0x00, 0x42, 0x6F, 0x6C, 0x64, 0x00, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F,
+ 0x6E, 0x20, 0x32, 0x2E, 0x39, 0x30, 0x00, 0x4D, 0x6F, 0x6E, 0x6F, 0x74,
+ 0x79, 0x70, 0x65, 0x20, 0x54, 0x79, 0x70, 0x6F, 0x67, 0x72, 0x61, 0x70,
+ 0x68, 0x79, 0x00, 0x4E, 0x4F, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54,
+ 0x49, 0x4F, 0x4E, 0x20, 0x4F, 0x46, 0x20, 0x4C, 0x49, 0x43, 0x45, 0x4E,
+ 0x53, 0x45, 0x20, 0x41, 0x47, 0x52, 0x45, 0x45, 0x4D, 0x45, 0x4E, 0x54,
+ 0x00, 0x04, 0x54, 0x01, 0x00, 0x1D, 0x00, 0x00, 0x1D, 0x00, 0x1D, 0x1D,
+ 0x00, 0x1D, 0x08, 0xFC, 0xFF, 0x03, 0x6F, 0x00, 0x20, 0x21, 0x50, 0x00,
+ 0x35, 0x0D, 0x00, 0x6F, 0x0C, 0x35, 0x00, 0x51, 0x20, 0xBE, 0x00, 0x8E,
+ 0x0C, 0xAA, 0x6F, 0xDE, 0x35, 0xD2, 0x50, 0xDE, 0xBD, 0xBE, 0x8D, 0xDE,
+ 0xA9, 0xD2, 0xDE, 0x6F, 0xD1, 0xAA, 0xDE, 0x8E, 0xBD, 0x21, 0xDE, 0x51,
+ 0xD1, 0x35, 0x6F, 0x00, 0xA9, 0x0D, 0x8D, 0x00, 0x08, 0xFC, 0xFF, 0x03,
+ 0xAB, 0x1D, 0xC8, 0x63, 0xBD, 0x2F, 0xC8, 0x48, 0xAB, 0xAA, 0xC8, 0x7F,
+ 0xBD, 0x98, 0x64, 0xC7, 0x99, 0xBC, 0x80, 0xC7, 0x1D, 0xAA, 0x48, 0xC7,
+ 0x2F, 0xBC, 0x00, 0x63, 0x0B, 0x98, 0x00, 0x7F, 0x1D, 0x1D, 0x00, 0x48,
+ 0x0B, 0x2F, 0x64, 0x00, 0x2F, 0x0B, 0x48, 0x00, 0xAB, 0x1D, 0x80, 0x00,
+ 0x99, 0x0B, 0x04, 0x54, 0x01, 0x00, 0x1A, 0x00, 0x00, 0x1D, 0x00, 0x1D,
+ 0x1A, 0x00, 0x1A, 0x06, 0x54, 0x15, 0x05, 0x35, 0x00, 0x19, 0x00, 0x00,
+ 0x1F, 0x00, 0x1F, 0x19, 0x1B, 0x35, 0x05, 0x35, 0x09, 0xF4, 0xFF, 0x05,
+ 0x00, 0x00, 0x0E, 0x00, 0x24, 0x01, 0x1A, 0x00, 0x21, 0x00, 0x2D, 0x05,
+ 0x28, 0x01, 0x2B, 0x03, 0x31, 0x0F, 0x2F, 0x08, 0x31, 0x0B, 0x2D, 0x18,
+ 0x31, 0x13, 0x2F, 0x16, 0x23, 0x1D, 0x2A, 0x1B, 0x27, 0x1C, 0x10, 0x1D,
+ 0x20, 0x1D, 0x1A, 0x1D, 0x00, 0x1D, 0x00, 0x00, 0x09, 0xF4, 0xFF, 0x05,
+ 0x00, 0x00, 0x14, 0x00, 0x2A, 0x02, 0x1F, 0x00, 0x27, 0x01, 0x32, 0x08,
+ 0x2E, 0x03, 0x31, 0x05, 0x35, 0x11, 0x34, 0x0B, 0x35, 0x0E, 0x32, 0x1C,
+ 0x35, 0x16, 0x34, 0x1A, 0x28, 0x21, 0x2F, 0x1F, 0x2C, 0x20, 0x17, 0x22,
+ 0x26, 0x22, 0x20, 0x22, 0x00, 0x22, 0x00, 0x00, 0x0A, 0x94, 0x9A, 0x16,
+ 0x02, 0x00, 0x1F, 0x00, 0x1F, 0x15, 0x1D, 0x28, 0x1F, 0x21, 0x15, 0x35,
+ 0x1B, 0x2F, 0x06, 0x3E, 0x0F, 0x3B, 0x00, 0x32, 0x0C, 0x2A, 0x09, 0x2F,
+ 0x10, 0x1D, 0x10, 0x25, 0x02, 0x1D, 0x02, 0x00, 0x0F, 0xD4, 0xFF, 0xFF,
+ 0x7F, 0x00, 0x00, 0x00, 0x7E, 0x2B, 0x7E, 0x49, 0x7D, 0x3B, 0x7E, 0x45,
+ 0x7E, 0x5A, 0x77, 0x50, 0x7D, 0x56, 0x7B, 0x65, 0x6A, 0x5F, 0x74, 0x63,
+ 0x70, 0x69, 0x5A, 0x68, 0x65, 0x69, 0x5F, 0x63, 0x47, 0x69, 0x52, 0x67,
+ 0x4C, 0x52, 0x3B, 0x5F, 0x41, 0x59, 0x3E, 0x5F, 0x30, 0x57, 0x39, 0x5B,
+ 0x35, 0x63, 0x20, 0x62, 0x2B, 0x63, 0x26, 0x5F, 0x11, 0x63, 0x1B, 0x62,
+ 0x16, 0x56, 0x07, 0x5D, 0x0D, 0x5A, 0x0A, 0x48, 0x02, 0x52, 0x04, 0x4D,
+ 0x02, 0x32, 0x00, 0x44, 0x01, 0x3C, 0x00, 0x00, 0x00, 0x03, 0x54, 0x23,
+ 0x2E, 0x00, 0x2E, 0x12, 0x00, 0x23, 0x2E, 0x03, 0x54, 0x29, 0x37, 0x14,
+ 0x00, 0x00, 0x37, 0x29, 0x37, 0x03, 0x54, 0x22, 0x33, 0x22, 0x00, 0x00,
+ 0x33, 0x22, 0x33, 0x04, 0x54, 0x01, 0x00, 0x96, 0x00, 0x00, 0x2B, 0x00,
+ 0x2B, 0x96, 0x00, 0x96, 0x04, 0x54, 0x01, 0x00, 0x96, 0x00, 0x00, 0x1E,
+ 0x00, 0x1E, 0x96, 0x00, 0x96, 0x04, 0x54, 0x01, 0x06, 0x00, 0x00, 0x1E,
+ 0x16, 0x1E, 0x1C, 0x00, 0x06, 0x00, 0x04, 0x54, 0x01, 0x16, 0x9E, 0x00,
+ 0x9E, 0x50, 0x00, 0x65, 0x00, 0x16, 0x9E, 0x04, 0x54, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x54, 0x01, 0x2E,
+ 0x1F, 0x1C, 0x1F, 0x00, 0x00, 0x20, 0x00, 0x2E, 0x1F, 0x04, 0x54, 0x01,
+ 0x00, 0x12, 0x00, 0x00, 0x78, 0x00, 0x78, 0x12, 0x00, 0x12, 0x04, 0x54,
+ 0x01, 0x00, 0x1B, 0x00, 0x00, 0x69, 0x00, 0x69, 0x1B, 0x00, 0x1B, 0x04,
+ 0x54, 0x01, 0x00, 0x1A, 0x00, 0x00, 0x69, 0x00, 0x69, 0x1A, 0x00, 0x1A,
+ 0x04, 0x54, 0x01, 0x00, 0x96, 0x00, 0x00, 0x1D, 0x00, 0x1D, 0x96, 0x00,
+ 0x96, 0x04, 0x54, 0x01, 0x00, 0x6D, 0x00, 0x00, 0x1D, 0x00, 0x1D, 0x6D,
+ 0x00, 0x6D, 0x04, 0x54, 0x01, 0x00, 0x00, 0x15, 0x00, 0x3B, 0x9B, 0x25,
+ 0x9B, 0x00, 0x00, 0x04, 0x54, 0x01, 0x00, 0x1D, 0x00, 0x00, 0x38, 0x00,
+ 0x38, 0x1D, 0x00, 0x1D, 0x04, 0x54, 0x01, 0x00, 0xC3, 0x00, 0x00, 0x17,
+ 0x00, 0x17, 0xC3, 0x00, 0xC3, 0x04, 0x54, 0x01, 0x00, 0x9B, 0x25, 0x00,
+ 0x3B, 0x00, 0x15, 0x9B, 0x00, 0x9B, 0x05, 0xA8, 0x06, 0x0D, 0x00, 0x03,
+ 0x07, 0x07, 0x02, 0x00, 0x12, 0x00, 0x0C, 0x03, 0x1C, 0x00, 0x17, 0x0D,
+ 0x23, 0x06, 0x21, 0x0D, 0x00, 0x05, 0xA8, 0x06, 0x00, 0x28, 0x0C, 0x21,
+ 0x07, 0x27, 0x11, 0x13, 0x11, 0x1B, 0x0D, 0x08, 0x11, 0x0D, 0x00, 0x00,
+ 0x09, 0x03, 0x00, 0x28, 0x05, 0xA8, 0x06, 0x2B, 0x19, 0x25, 0x06, 0x2B,
+ 0x0D, 0x16, 0x00, 0x1E, 0x00, 0x06, 0x06, 0x0C, 0x00, 0x00, 0x19, 0x00,
+ 0x0D, 0x2B, 0x19, 0x06, 0x54, 0x15, 0x00, 0x53, 0x3B, 0x53, 0x3B, 0x45,
+ 0x11, 0x45, 0x11, 0x00, 0x00, 0x00, 0x00, 0x53, 0x06, 0x54, 0x15, 0x06,
+ 0x35, 0x00, 0x19, 0x00, 0x00, 0x1F, 0x00, 0x1F, 0x19, 0x1B, 0x35, 0x06,
+ 0x35, 0x06, 0x54, 0x15, 0x00, 0x95, 0x00, 0x00, 0x1E, 0x00, 0x1E, 0x7B,
+ 0x6A, 0x7B, 0x6A, 0x95, 0x00, 0x95, 0x06, 0x54, 0x15, 0x07, 0x6F, 0x00,
+ 0x23, 0x00, 0x00, 0x1F, 0x00, 0x1F, 0x23, 0x18, 0x6F, 0x07, 0x6F, 0x07,
+ 0x54, 0x55, 0x00, 0x52, 0x26, 0x00, 0x3D, 0x00, 0x63, 0x52, 0x46, 0x52,
+ 0x31, 0x20, 0x1D, 0x52, 0x00, 0x52, 0x07, 0xFC, 0x7F, 0x00, 0xC7, 0x07,
+ 0x40, 0x00, 0x92, 0x02, 0x64, 0x19, 0x00, 0x0B, 0x1F, 0x11, 0x08, 0x1C,
+ 0x00, 0x1A, 0x00, 0x1B, 0x00, 0x9D, 0x39, 0x65, 0x00, 0x8A, 0x15, 0xAD,
+ 0xA0, 0xAA, 0x54, 0xAD, 0x78, 0xAD, 0xC7, 0xAD, 0xAD, 0xAD, 0xBA, 0x00,
+ 0xC7, 0x07, 0x54, 0x55, 0x00, 0x72, 0x00, 0x55, 0x48, 0x39, 0x00, 0x1D,
+ 0x00, 0x00, 0x67, 0x2C, 0x67, 0x45, 0x00, 0x72, 0x07, 0xA8, 0x6A, 0x14,
+ 0x00, 0x05, 0x0C, 0x0A, 0x05, 0x00, 0x1B, 0x00, 0x13, 0x07, 0x2A, 0x00,
+ 0x24, 0x17, 0x30, 0x0D, 0x30, 0x24, 0x2D, 0x1E, 0x30, 0x31, 0x24, 0x2A,
+ 0x2A, 0x14, 0x00, 0x07, 0xFC, 0x7F, 0x01, 0xC7, 0x00, 0xA0, 0x00, 0xBA,
+ 0x00, 0xAD, 0x11, 0x39, 0x00, 0x78, 0x03, 0x54, 0x91, 0x00, 0x23, 0x15,
+ 0x48, 0x00, 0x94, 0x00, 0x92, 0x00, 0x93, 0x00, 0xA7, 0x40, 0x9D, 0x08,
+ 0xA3, 0x1F, 0xAD, 0xC7, 0xAB, 0x64, 0xAD, 0x92, 0x01, 0xC7, 0x07, 0x54,
+ 0x55, 0x36, 0x96, 0x00, 0x00, 0x21, 0x00, 0x47, 0x6F, 0x6C, 0x00, 0x8C,
+ 0x00, 0x56, 0x96, 0x36, 0x96, 0x07, 0x54, 0x55, 0x67, 0x72, 0x00, 0x45,
+ 0x00, 0x2C, 0x67, 0x00, 0x67, 0x1D, 0x1F, 0x38, 0x67, 0x55, 0x67, 0x72,
+ 0x08, 0x54, 0x55, 0x01, 0x2D, 0x96, 0x2D, 0x19, 0x00, 0x19, 0x00, 0x00,
+ 0x77, 0x00, 0x77, 0x19, 0x4B, 0x19, 0x4B, 0x96, 0x2D, 0x96, 0x08, 0xA8,
+ 0xAA, 0x02, 0x00, 0x12, 0x05, 0x1F, 0x00, 0x1A, 0x12, 0x24, 0x0A, 0x24,
+ 0x1F, 0x1F, 0x1A, 0x24, 0x24, 0x12, 0x24, 0x1A, 0x1F, 0x05, 0x24, 0x0A,
+ 0x12, 0x00, 0x1A, 0x00, 0x05, 0x05, 0x0A, 0x00, 0x00, 0x12, 0x00, 0x0A,
+ 0x08, 0xA8, 0xAA, 0x02, 0x00, 0x17, 0x06, 0x2A, 0x00, 0x23, 0x16, 0x30,
+ 0x0D, 0x30, 0x24, 0x2A, 0x1F, 0x30, 0x2A, 0x17, 0x2A, 0x23, 0x24, 0x07,
+ 0x2A, 0x0D, 0x15, 0x00, 0x1E, 0x00, 0x05, 0x07, 0x0B, 0x00, 0x00, 0x17,
+ 0x00, 0x0F, 0x08, 0xA8, 0xAA, 0x02, 0x31, 0x21, 0x2A, 0x08, 0x31, 0x10,
+ 0x19, 0x00, 0x23, 0x00, 0x07, 0x08, 0x0E, 0x00, 0x00, 0x23, 0x00, 0x11,
+ 0x07, 0x3D, 0x00, 0x35, 0x18, 0x44, 0x0E, 0x44, 0x29, 0x3C, 0x22, 0x44,
+ 0x31, 0x21, 0x31, 0x33, 0x08, 0xA8, 0xAA, 0x02, 0x00, 0x21, 0x08, 0x3C,
+ 0x00, 0x33, 0x19, 0x44, 0x0F, 0x44, 0x2A, 0x3C, 0x23, 0x44, 0x31, 0x22,
+ 0x31, 0x34, 0x2A, 0x09, 0x31, 0x11, 0x19, 0x00, 0x23, 0x00, 0x07, 0x08,
+ 0x0E, 0x00, 0x00, 0x21, 0x00, 0x11, 0x08, 0xA8, 0xAA, 0x02, 0x28, 0x1D,
+ 0x21, 0x08, 0x28, 0x0F, 0x13, 0x00, 0x1B, 0x00, 0x05, 0x06, 0x0B, 0x00,
+ 0x00, 0x1B, 0x00, 0x0D, 0x06, 0x30, 0x00, 0x29, 0x14, 0x37, 0x0C, 0x37,
+ 0x22, 0x30, 0x1D, 0x37, 0x28, 0x1D, 0x28, 0x2A, 0x08, 0x54, 0x55, 0x01,
+ 0x2E, 0x8F, 0x2E, 0x21, 0x00, 0x21, 0x00, 0x00, 0x7D, 0x00, 0x7D, 0x21,
+ 0x4F, 0x21, 0x4F, 0x8F, 0x2E, 0x8F, 0x08, 0x54, 0x55, 0x01, 0x18, 0x53,
+ 0x29, 0x53, 0x29, 0x0E, 0x42, 0x0E, 0x42, 0x00, 0x00, 0x00, 0x00, 0x0E,
+ 0x18, 0x0E, 0x18, 0x53, 0x08, 0x54, 0x55, 0x01, 0x00, 0xC0, 0x00, 0x00,
+ 0x33, 0x00, 0x33, 0x16, 0x1B, 0x16, 0x1B, 0xA9, 0x33, 0xA9, 0x33, 0xC0,
+ 0x00, 0xC0, 0x08, 0xA8, 0xAA, 0x02, 0x00, 0x34, 0x0C, 0x5A, 0x00, 0x4D,
+ 0x2A, 0x67, 0x18, 0x67, 0x48, 0x5A, 0x3C, 0x67, 0x53, 0x33, 0x53, 0x4D,
+ 0x48, 0x0D, 0x53, 0x19, 0x2A, 0x00, 0x3D, 0x00, 0x0C, 0x0D, 0x17, 0x00,
+ 0x00, 0x34, 0x00, 0x1A, 0x08, 0xA8, 0xAA, 0x02, 0x00, 0x1A, 0x07, 0x30,
+ 0x00, 0x28, 0x15, 0x37, 0x0D, 0x37, 0x23, 0x31, 0x1D, 0x37, 0x28, 0x1D,
+ 0x28, 0x2B, 0x22, 0x07, 0x28, 0x0E, 0x14, 0x00, 0x1D, 0x00, 0x06, 0x07,
+ 0x0C, 0x00, 0x00, 0x1A, 0x00, 0x0D, 0x08, 0xA8, 0xAA, 0x02, 0x00, 0x21,
+ 0x08, 0x3A, 0x00, 0x32, 0x1B, 0x43, 0x10, 0x43, 0x2E, 0x3A, 0x26, 0x43,
+ 0x36, 0x21, 0x36, 0x32, 0x2E, 0x09, 0x36, 0x11, 0x1B, 0x00, 0x26, 0x00,
+ 0x08, 0x09, 0x10, 0x00, 0x00, 0x21, 0x00, 0x11, 0x08, 0x54, 0x55, 0x01,
+ 0x19, 0x53, 0x2A, 0x53, 0x2A, 0x0E, 0x43, 0x0E, 0x43, 0x00, 0x00, 0x00,
+ 0x00, 0x0E, 0x19, 0x0E, 0x19, 0x53, 0x08, 0x54, 0x55, 0x01, 0x33, 0x00,
+ 0x33, 0xC0, 0x00, 0xC0, 0x00, 0xA9, 0x18, 0xA9, 0x18, 0x16, 0x00, 0x16,
+ 0x00, 0x00, 0x33, 0x00, 0x08, 0xA8, 0xAA, 0x02, 0x00, 0x28, 0x09, 0x0A,
+ 0x00, 0x14, 0x21, 0x00, 0x12, 0x00, 0x3A, 0x0A, 0x31, 0x00, 0x42, 0x28,
+ 0x42, 0x14, 0x3A, 0x46, 0x42, 0x3C, 0x22, 0x50, 0x31, 0x50, 0x09, 0x46,
+ 0x12, 0x50, 0x00, 0x28, 0x00, 0x3C, 0x08, 0x54, 0x55, 0x01, 0x97, 0x96,
+ 0x76, 0x96, 0x68, 0x74, 0x2D, 0x74, 0x20, 0x96, 0x00, 0x96, 0x3A, 0x00,
+ 0x5A, 0x00, 0x97, 0x96, 0x08, 0x94, 0x69, 0x01, 0x42, 0x97, 0x25, 0x97,
+ 0x25, 0x2A, 0x00, 0x40, 0x15, 0x39, 0x00, 0x26, 0x18, 0x18, 0x0B, 0x22,
+ 0x2B, 0x00, 0x26, 0x0E, 0x42, 0x00, 0x42, 0x97, 0x08, 0xA8, 0xAA, 0x02,
+ 0x00, 0x20, 0x07, 0x3A, 0x00, 0x31, 0x18, 0x41, 0x0E, 0x41, 0x2A, 0x39,
+ 0x22, 0x41, 0x31, 0x21, 0x31, 0x31, 0x2A, 0x08, 0x31, 0x10, 0x18, 0x00,
+ 0x23, 0x00, 0x07, 0x08, 0x0E, 0x00, 0x00, 0x20, 0x00, 0x10, 0x08, 0xA8,
+ 0xAA, 0x02, 0x00, 0x17, 0x03, 0x2A, 0x00, 0x26, 0x0A, 0x2E, 0x06, 0x2E,
+ 0x11, 0x2B, 0x0F, 0x2E, 0x14, 0x17, 0x14, 0x26, 0x11, 0x03, 0x14, 0x08,
+ 0x0A, 0x00, 0x0F, 0x00, 0x03, 0x03, 0x05, 0x00, 0x00, 0x17, 0x00, 0x08,
+ 0x08, 0xA8, 0xAA, 0x02, 0x00, 0x18, 0x04, 0x2B, 0x00, 0x26, 0x0B, 0x2F,
+ 0x06, 0x2F, 0x12, 0x2B, 0x0F, 0x2F, 0x15, 0x18, 0x15, 0x26, 0x12, 0x04,
+ 0x15, 0x09, 0x0B, 0x00, 0x0F, 0x00, 0x04, 0x04, 0x06, 0x00, 0x00, 0x18,
+ 0x00, 0x09, 0x08, 0x54, 0x55, 0x01, 0x7F, 0x7E, 0x4C, 0x00, 0x31, 0x00,
+ 0x00, 0x7E, 0x1B, 0x7E, 0x26, 0x62, 0x58, 0x62, 0x63, 0x7E, 0x7F, 0x7E,
+ 0x08, 0xA8, 0xAA, 0x02, 0x31, 0x00, 0x53, 0x10, 0x47, 0x00, 0x61, 0x4D,
+ 0x61, 0x22, 0x53, 0x8A, 0x61, 0x77, 0x31, 0x99, 0x47, 0x99, 0x0D, 0x88,
+ 0x1B, 0x99, 0x00, 0x4C, 0x00, 0x78, 0x0F, 0x0F, 0x00, 0x22, 0x31, 0x00,
+ 0x1B, 0x00, 0x08, 0xA8, 0xAA, 0x02, 0x00, 0x20, 0x05, 0x39, 0x00, 0x31,
+ 0x19, 0x44, 0x0C, 0x44, 0x2A, 0x3C, 0x23, 0x44, 0x30, 0x23, 0x30, 0x34,
+ 0x2A, 0x08, 0x30, 0x10, 0x18, 0x00, 0x23, 0x00, 0x07, 0x08, 0x0E, 0x00,
+ 0x00, 0x20, 0x00, 0x10, 0x08, 0xA4, 0xAA, 0x01, 0x0D, 0x21, 0x15, 0x1B,
+ 0x1E, 0x0E, 0x1E, 0x14, 0x1A, 0x04, 0x1E, 0x08, 0x0E, 0x00, 0x16, 0x00,
+ 0x04, 0x04, 0x08, 0x00, 0x00, 0x0C, 0x00, 0x07, 0x06, 0x19, 0x00, 0x11,
+ 0x0D, 0x21, 0x08, 0xA8, 0xAA, 0x02, 0x00, 0x20, 0x05, 0x39, 0x00, 0x31,
+ 0x19, 0x44, 0x0C, 0x44, 0x29, 0x3C, 0x22, 0x44, 0x30, 0x23, 0x30, 0x34,
+ 0x29, 0x08, 0x30, 0x10, 0x18, 0x00, 0x22, 0x00, 0x06, 0x08, 0x0D, 0x00,
+ 0x00, 0x20, 0x00, 0x10, 0x08, 0xA8, 0xAA, 0x02, 0x00, 0x28, 0x09, 0x0A,
+ 0x00, 0x14, 0x21, 0x00, 0x12, 0x00, 0x39, 0x0A, 0x31, 0x00, 0x42, 0x28,
+ 0x42, 0x13, 0x39, 0x46, 0x42, 0x3C, 0x21, 0x4F, 0x31, 0x4F, 0x09, 0x46,
+ 0x12, 0x4F, 0x00, 0x28, 0x00, 0x3C, 0x09, 0x54, 0x55, 0x05, 0x2E, 0x7E,
+ 0x48, 0x7E, 0x48, 0x49, 0x76, 0x00, 0x58, 0x00, 0x3C, 0x32, 0x1E, 0x00,
+ 0x00, 0x00, 0x2E, 0x49, 0x2E, 0x7E, 0x09, 0x94, 0xAA, 0x06, 0x00, 0x00,
+ 0x00, 0x28, 0x1C, 0x28, 0x31, 0x28, 0x2D, 0x28, 0x3C, 0x22, 0x38, 0x26,
+ 0x40, 0x15, 0x40, 0x1D, 0x3D, 0x09, 0x40, 0x0E, 0x34, 0x02, 0x3A, 0x05,
+ 0x19, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x09, 0xA8, 0xAA, 0x06, 0x27, 0x00,
+ 0x15, 0x04, 0x21, 0x01, 0x05, 0x09, 0x09, 0x06, 0x00, 0x13, 0x00, 0x0D,
+ 0x04, 0x1E, 0x00, 0x19, 0x10, 0x22, 0x09, 0x22, 0x1F, 0x1D, 0x17, 0x22,
+ 0x25, 0x13, 0x24, 0x19, 0x27, 0x05, 0x27, 0x10, 0x27, 0x00, 0x09, 0x94,
+ 0xAA, 0x06, 0x00, 0x00, 0x00, 0x22, 0x14, 0x22, 0x2A, 0x22, 0x26, 0x22,
+ 0x36, 0x1D, 0x32, 0x21, 0x3B, 0x11, 0x3B, 0x18, 0x37, 0x06, 0x3B, 0x0A,
+ 0x2C, 0x00, 0x33, 0x01, 0x12, 0x00, 0x27, 0x00, 0x00, 0x00, 0x09, 0xA8,
+ 0xAA, 0x0A, 0x00, 0x11, 0x05, 0x1C, 0x00, 0x18, 0x10, 0x21, 0x0A, 0x21,
+ 0x1C, 0x1C, 0x17, 0x21, 0x20, 0x11, 0x20, 0x18, 0x1E, 0x08, 0x20, 0x0C,
+ 0x18, 0x03, 0x1C, 0x05, 0x10, 0x00, 0x14, 0x00, 0x05, 0x05, 0x0A, 0x00,
+ 0x00, 0x11, 0x00, 0x0A, 0x09, 0xD4, 0xFF, 0x07, 0x00, 0x15, 0x00, 0x00,
+ 0x0D, 0x00, 0x1A, 0x00, 0x14, 0x00, 0x18, 0x00, 0x20, 0x03, 0x1C, 0x00,
+ 0x1E, 0x02, 0x22, 0x0A, 0x21, 0x05, 0x22, 0x07, 0x20, 0x10, 0x22, 0x0D,
+ 0x22, 0x0F, 0x1C, 0x14, 0x1F, 0x12, 0x1E, 0x13, 0x0D, 0x15, 0x1A, 0x15,
+ 0x15, 0x15, 0x00, 0x15, 0x09, 0x54, 0x55, 0x05, 0x37, 0x96, 0x37, 0x57,
+ 0x00, 0x00, 0x24, 0x00, 0x47, 0x3B, 0x69, 0x00, 0x8C, 0x00, 0x55, 0x57,
+ 0x55, 0x96, 0x37, 0x96, 0x09, 0x94, 0xAA, 0x06, 0x00, 0x00, 0x00, 0x2B,
+ 0x11, 0x2B, 0x29, 0x28, 0x23, 0x2B, 0x32, 0x21, 0x2F, 0x26, 0x36, 0x15,
+ 0x36, 0x1C, 0x31, 0x08, 0x36, 0x0D, 0x25, 0x01, 0x2C, 0x02, 0x0F, 0x00,
+ 0x1F, 0x00, 0x00, 0x00, 0x09, 0xA4, 0xAA, 0x05, 0x00, 0x26, 0x17, 0x26,
+ 0x32, 0x24, 0x2C, 0x26, 0x3A, 0x1E, 0x37, 0x22, 0x3D, 0x13, 0x3D, 0x19,
+ 0x39, 0x07, 0x3D, 0x0B, 0x2E, 0x01, 0x35, 0x02, 0x18, 0x00, 0x2A, 0x00,
+ 0x00, 0x00, 0x00, 0x26, 0x0A, 0x54, 0x6A, 0x1A, 0x00, 0x1A, 0x00, 0x00,
+ 0x62, 0x00, 0x62, 0x15, 0x4A, 0x37, 0x56, 0x21, 0x36, 0x67, 0x3D, 0x4D,
+ 0x30, 0x94, 0x30, 0x80, 0x14, 0x94, 0x21, 0x54, 0x15, 0x75, 0x41, 0x1A,
+ 0x2D, 0x34, 0x00, 0x1A, 0x0A, 0x54, 0x55, 0x15, 0x00, 0x96, 0x00, 0x00,
+ 0x1D, 0x00, 0x5B, 0x64, 0x5B, 0x00, 0x77, 0x00, 0x77, 0x96, 0x59, 0x96,
+ 0x1C, 0x34, 0x1C, 0x96, 0x00, 0x96, 0x0A, 0x54, 0x55, 0x15, 0x00, 0x96,
+ 0x00, 0x7A, 0x4F, 0x19, 0x09, 0x19, 0x09, 0x00, 0x77, 0x00, 0x77, 0x17,
+ 0x25, 0x7C, 0x7A, 0x7C, 0x7A, 0x96, 0x00, 0x96, 0x0A, 0xFC, 0xFF, 0x1F,
+ 0xBE, 0xDE, 0xC3, 0xD9, 0xC1, 0xDE, 0xC3, 0xDC, 0xBD, 0x4B, 0xC3, 0xAB,
+ 0xC2, 0x79, 0xA5, 0x02, 0xB8, 0x25, 0xB0, 0x0B, 0xA1, 0x00, 0xA4, 0x01,
+ 0xA2, 0x00, 0x9D, 0x00, 0xA0, 0x00, 0x9E, 0x00, 0x12, 0x40, 0x4E, 0x00,
+ 0x26, 0x19, 0x00, 0xAE, 0x03, 0x5E, 0x00, 0x84, 0x01, 0xD9, 0x00, 0xBC,
+ 0x00, 0xCA, 0x06, 0xDE, 0x01, 0xDC, 0x03, 0xDE, 0xBE, 0xDE, 0x0A, 0xA8,
+ 0xAA, 0x2A, 0x00, 0x37, 0x07, 0x1B, 0x00, 0x29, 0x1B, 0x07, 0x0E, 0x0E,
+ 0x38, 0x00, 0x28, 0x00, 0x60, 0x10, 0x51, 0x00, 0x70, 0x38, 0x70, 0x20,
+ 0x60, 0x61, 0x70, 0x51, 0x38, 0x71, 0x50, 0x71, 0x1C, 0x6A, 0x29, 0x71,
+ 0x07, 0x57, 0x0E, 0x64, 0x00, 0x37, 0x00, 0x4A, 0x0A, 0xA8, 0xAA, 0x2A,
+ 0x00, 0x4F, 0x07, 0x28, 0x00, 0x38, 0x15, 0x14, 0x0C, 0x1D, 0x28, 0x06,
+ 0x1E, 0x0A, 0x49, 0x00, 0x36, 0x00, 0x7E, 0x15, 0x6A, 0x00, 0x92, 0x4E,
+ 0x92, 0x29, 0x7E, 0x87, 0x92, 0x72, 0x49, 0x9B, 0x6A, 0x9B, 0x14, 0x87,
+ 0x27, 0x9B, 0x00, 0x4F, 0x00, 0x72, 0x0A, 0xF4, 0xAF, 0x3F, 0x06, 0xDE,
+ 0xBD, 0xDE, 0xC3, 0xD9, 0xC0, 0xDE, 0xC2, 0xDC, 0xC3, 0xAE, 0xC3, 0xCA,
+ 0xC3, 0xBC, 0xB1, 0x40, 0xC3, 0x84, 0xC0, 0x5E, 0x26, 0x00, 0x9D, 0x19,
+ 0x75, 0x00, 0x23, 0x00, 0x25, 0x00, 0x1F, 0x02, 0x21, 0x00, 0x07, 0x4B,
+ 0x13, 0x0B, 0x0B, 0x25, 0x00, 0xD9, 0x01, 0x79, 0x00, 0xAB, 0x06, 0xDE,
+ 0x00, 0xDC, 0x02, 0xDE, 0x0A, 0x54, 0x55, 0x15, 0x00, 0x96, 0x00, 0x00,
+ 0x67, 0x00, 0x67, 0x19, 0x1E, 0x19, 0x1E, 0x3D, 0x5D, 0x3D, 0x5D, 0x56,
+ 0x1E, 0x56, 0x1E, 0x96, 0x00, 0x96, 0x0A, 0x54, 0x69, 0x15, 0x2C, 0x6D,
+ 0x00, 0x00, 0x1E, 0x00, 0x33, 0x38, 0x39, 0x4A, 0x3C, 0x41, 0x3B, 0x43,
+ 0x3F, 0x38, 0x3D, 0x3C, 0x53, 0x00, 0x71, 0x00, 0x46, 0x6D, 0x2C, 0x6D,
+ 0x0B, 0xA4, 0xAA, 0x5A, 0x00, 0x00, 0x37, 0x00, 0x54, 0x03, 0x4A, 0x00,
+ 0x6B, 0x10, 0x61, 0x06, 0x79, 0x29, 0x74, 0x1A, 0x7E, 0x4C, 0x7E, 0x37,
+ 0x79, 0x6C, 0x7E, 0x5F, 0x69, 0x87, 0x74, 0x7C, 0x54, 0x93, 0x61, 0x8E,
+ 0x39, 0x96, 0x4A, 0x96, 0x00, 0x96, 0x00, 0x00, 0x0B, 0x54, 0x55, 0x55,
+ 0x3D, 0x97, 0x3D, 0x79, 0x00, 0x79, 0x00, 0x5F, 0x41, 0x00, 0x59, 0x00,
+ 0x59, 0x5F, 0x6C, 0x5F, 0x6C, 0x79, 0x59, 0x79, 0x59, 0x97, 0x3D, 0x97,
+ 0x0B, 0xA4, 0x9A, 0xAA, 0x34, 0xC3, 0x20, 0xC3, 0x08, 0x94, 0x10, 0xAD,
+ 0x00, 0x62, 0x00, 0x7A, 0x0A, 0x2A, 0x00, 0x45, 0x20, 0x00, 0x13, 0x13,
+ 0x34, 0x00, 0x21, 0x35, 0x26, 0x1F, 0x1C, 0x63, 0x1C, 0x4B, 0x1F, 0x85,
+ 0x1C, 0x74, 0x27, 0xA7, 0x22, 0x97, 0x34, 0xC3, 0x2B, 0xB1, 0x0B, 0xA8,
+ 0xAA, 0xAA, 0x00, 0x31, 0x05, 0x44, 0x00, 0x3E, 0x12, 0x4A, 0x0B, 0x4A,
+ 0x1D, 0x47, 0x18, 0x4A, 0x25, 0x41, 0x21, 0x45, 0x2E, 0x2E, 0x2A, 0x3A,
+ 0x32, 0x18, 0x32, 0x22, 0x2D, 0x06, 0x32, 0x0D, 0x1F, 0x00, 0x27, 0x00,
+ 0x0F, 0x07, 0x16, 0x00, 0x04, 0x1A, 0x08, 0x0E, 0x00, 0x31, 0x00, 0x27,
+ 0x0B, 0x94, 0xAA, 0x6A, 0x00, 0x00, 0x00, 0x63, 0x17, 0x63, 0x29, 0x62,
+ 0x24, 0x63, 0x35, 0x5C, 0x31, 0x60, 0x3D, 0x4D, 0x3A, 0x57, 0x40, 0x32,
+ 0x40, 0x43, 0x3D, 0x17, 0x40, 0x20, 0x35, 0x09, 0x3A, 0x0E, 0x27, 0x02,
+ 0x2F, 0x03, 0x0E, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0C, 0xA8, 0xAA, 0x6A,
+ 0x02, 0x48, 0x5B, 0x50, 0x4A, 0x4D, 0x54, 0x53, 0x34, 0x53, 0x40, 0x48,
+ 0x0D, 0x53, 0x1A, 0x2A, 0x00, 0x3C, 0x00, 0x0C, 0x0D, 0x17, 0x00, 0x00,
+ 0x34, 0x00, 0x1A, 0x0C, 0x5B, 0x00, 0x4E, 0x29, 0x68, 0x17, 0x68, 0x35,
+ 0x66, 0x2F, 0x68, 0x22, 0x5D, 0x2C, 0x60, 0x2B, 0x4B, 0x48, 0x5B, 0x3A,
+ 0x50, 0x0C, 0x54, 0x55, 0x55, 0x01, 0x27, 0x69, 0x27, 0x42, 0x00, 0x42,
+ 0x00, 0x27, 0x27, 0x27, 0x27, 0x00, 0x41, 0x00, 0x41, 0x27, 0x69, 0x27,
+ 0x69, 0x42, 0x41, 0x42, 0x41, 0x69, 0x27, 0x69, 0x0C, 0x94, 0xAA, 0x5A,
+ 0x01, 0x00, 0x96, 0x00, 0x00, 0x31, 0x00, 0x55, 0x02, 0x4C, 0x00, 0x6A,
+ 0x11, 0x62, 0x05, 0x73, 0x2E, 0x73, 0x1C, 0x6E, 0x45, 0x73, 0x3C, 0x61,
+ 0x54, 0x69, 0x4E, 0x51, 0x5B, 0x59, 0x59, 0x32, 0x5D, 0x47, 0x5D, 0x1E,
+ 0x5D, 0x1E, 0x96, 0x00, 0x96, 0x0C, 0x54, 0x55, 0x55, 0x01, 0x00, 0x7E,
+ 0x1F, 0x7E, 0x3B, 0x54, 0x57, 0x7E, 0x75, 0x7E, 0x4A, 0x3D, 0x71, 0x00,
+ 0x54, 0x00, 0x3B, 0x26, 0x22, 0x00, 0x05, 0x00, 0x2C, 0x3D, 0x00, 0x7E,
+ 0x0C, 0xA4, 0x69, 0x9A, 0x02, 0x5A, 0x3F, 0x5A, 0x0F, 0x56, 0x04, 0x5A,
+ 0x08, 0x4C, 0x00, 0x52, 0x00, 0x0F, 0x00, 0x04, 0x04, 0x09, 0x00, 0x00,
+ 0x0F, 0x00, 0x08, 0x00, 0x3F, 0x04, 0x49, 0x00, 0x45, 0x0F, 0x4D, 0x09,
+ 0x4D, 0x4C, 0x4D, 0x56, 0x49, 0x52, 0x4D, 0x5A, 0x3F, 0x5A, 0x45, 0x0C,
+ 0x54, 0x55, 0x55, 0x01, 0x00, 0x96, 0x00, 0x00, 0x1D, 0x00, 0x1D, 0x4F,
+ 0x3E, 0x29, 0x62, 0x29, 0x3D, 0x51, 0x64, 0x96, 0x45, 0x96, 0x2A, 0x65,
+ 0x1D, 0x73, 0x1D, 0x96, 0x00, 0x96, 0x0C, 0x54, 0x55, 0x55, 0x01, 0x00,
+ 0x96, 0x00, 0x00, 0x1E, 0x00, 0x1E, 0x42, 0x5B, 0x00, 0x84, 0x00, 0x4C,
+ 0x3A, 0x87, 0x96, 0x60, 0x96, 0x37, 0x4F, 0x1E, 0x68, 0x1E, 0x96, 0x00,
+ 0x96, 0x0C, 0xA8, 0xAA, 0xAA, 0x02, 0x13, 0x00, 0x09, 0x03, 0x0D, 0x00,
+ 0x03, 0x0F, 0x05, 0x07, 0x00, 0x35, 0x00, 0x1A, 0x03, 0x59, 0x00, 0x4F,
+ 0x09, 0x66, 0x05, 0x63, 0x13, 0x69, 0x0D, 0x69, 0x1C, 0x66, 0x18, 0x69,
+ 0x22, 0x5A, 0x20, 0x63, 0x25, 0x35, 0x25, 0x4F, 0x23, 0x11, 0x25, 0x1A,
+ 0x1C, 0x03, 0x20, 0x07, 0x13, 0x00, 0x18, 0x00, 0x0C, 0xA8, 0xAA, 0xAA,
+ 0x02, 0x00, 0x23, 0x03, 0x15, 0x00, 0x1C, 0x0A, 0x0A, 0x06, 0x0F, 0x15,
+ 0x03, 0x0F, 0x06, 0x22, 0x00, 0x1B, 0x00, 0x33, 0x05, 0x2B, 0x00, 0x40,
+ 0x12, 0x3B, 0x0A, 0x44, 0x23, 0x44, 0x19, 0x40, 0x34, 0x44, 0x2C, 0x33,
+ 0x40, 0x3B, 0x3C, 0x22, 0x45, 0x2C, 0x45, 0x0A, 0x3B, 0x14, 0x45, 0x00,
+ 0x23, 0x00, 0x31, 0x0C, 0x54, 0x55, 0x55, 0x01, 0x6D, 0x8F, 0x6D, 0x57,
+ 0x21, 0x57, 0x21, 0x8F, 0x00, 0x8F, 0x00, 0x00, 0x21, 0x00, 0x21, 0x36,
+ 0x6D, 0x36, 0x6D, 0x00, 0x8F, 0x00, 0x8F, 0x8F, 0x6D, 0x8F, 0x0C, 0x54,
+ 0xAA, 0x6A, 0x01, 0x00, 0x96, 0x00, 0x00, 0x1D, 0x00, 0x1D, 0x36, 0x3C,
+ 0x27, 0x2A, 0x27, 0x5D, 0x35, 0x50, 0x27, 0x6A, 0x5E, 0x6A, 0x43, 0x5D,
+ 0x89, 0x6A, 0x7A, 0x3D, 0x98, 0x50, 0x98, 0x2A, 0x94, 0x33, 0x98, 0x1B,
+ 0x86, 0x21, 0x8F, 0x1B, 0x96, 0x00, 0x96, 0x0C, 0x54, 0x55, 0x55, 0x01,
+ 0x00, 0x96, 0x00, 0x00, 0x1E, 0x00, 0x1E, 0x3B, 0x5A, 0x3B, 0x5A, 0x00,
+ 0x78, 0x00, 0x78, 0x96, 0x5A, 0x96, 0x5A, 0x54, 0x1E, 0x54, 0x1E, 0x96,
+ 0x00, 0x96, 0x0C, 0x54, 0x55, 0x55, 0x01, 0x00, 0x96, 0x00, 0x00, 0x6F,
+ 0x00, 0x6F, 0x19, 0x1E, 0x19, 0x1E, 0x3A, 0x6A, 0x3A, 0x6A, 0x54, 0x1E,
+ 0x54, 0x1E, 0x7C, 0x72, 0x7C, 0x72, 0x96, 0x00, 0x96, 0x0C, 0x94, 0xAA,
+ 0x5A, 0x01, 0x6A, 0x96, 0x4F, 0x96, 0x4F, 0x86, 0x40, 0x94, 0x49, 0x8F,
+ 0x2D, 0x98, 0x37, 0x98, 0x0D, 0x89, 0x1B, 0x98, 0x00, 0x5F, 0x00, 0x7A,
+ 0x0D, 0x35, 0x00, 0x43, 0x2E, 0x27, 0x1A, 0x27, 0x4D, 0x36, 0x40, 0x27,
+ 0x4D, 0x00, 0x6A, 0x00, 0x6A, 0x96, 0x0C, 0x54, 0x55, 0x55, 0x01, 0x00,
+ 0x96, 0x33, 0x47, 0x05, 0x00, 0x28, 0x00, 0x46, 0x30, 0x64, 0x00, 0x87,
+ 0x00, 0x58, 0x49, 0x8B, 0x96, 0x67, 0x96, 0x46, 0x62, 0x24, 0x96, 0x00,
+ 0x96, 0x0C, 0x54, 0x55, 0x55, 0x01, 0x00, 0x6D, 0x27, 0x35, 0x02, 0x00,
+ 0x25, 0x00, 0x38, 0x1E, 0x4C, 0x00, 0x6E, 0x00, 0x49, 0x34, 0x71, 0x6D,
+ 0x4E, 0x6D, 0x38, 0x4B, 0x22, 0x6D, 0x00, 0x6D, 0x0C, 0xA8, 0x6A, 0xAA,
+ 0x01, 0x00, 0xC3, 0x0C, 0xA9, 0x09, 0xB3, 0x13, 0x92, 0x10, 0x9F, 0x17,
+ 0x7A, 0x16, 0x86, 0x18, 0x63, 0x18, 0x6F, 0x13, 0x35, 0x18, 0x4B, 0x00,
+ 0x00, 0x0E, 0x1F, 0x14, 0x00, 0x2B, 0x2F, 0x23, 0x16, 0x34, 0x61, 0x34,
+ 0x47, 0x2D, 0x8F, 0x34, 0x76, 0x14, 0xC3, 0x26, 0xAA, 0x00, 0xC3, 0x0D,
+ 0x54, 0xA9, 0xA9, 0x06, 0x1D, 0x6F, 0x00, 0x6F, 0x00, 0x02, 0x1B, 0x02,
+ 0x1B, 0x11, 0x27, 0x03, 0x22, 0x07, 0x33, 0x00, 0x2D, 0x00, 0x46, 0x05,
+ 0x3D, 0x00, 0x3D, 0x1E, 0x30, 0x19, 0x36, 0x19, 0x26, 0x1D, 0x2A, 0x19,
+ 0x1F, 0x29, 0x22, 0x20, 0x1D, 0x4D, 0x1D, 0x31, 0x1D, 0x6F, 0x0D, 0x94,
+ 0xAA, 0xA9, 0x06, 0x42, 0x00, 0x60, 0x00, 0x60, 0x5F, 0x5D, 0x7B, 0x60,
+ 0x71, 0x4D, 0x90, 0x58, 0x88, 0x2E, 0x98, 0x41, 0x98, 0x0C, 0x8C, 0x18,
+ 0x98, 0x00, 0x67, 0x00, 0x7F, 0x1D, 0x64, 0x20, 0x76, 0x1D, 0x71, 0x2F,
+ 0x7E, 0x25, 0x7E, 0x3E, 0x79, 0x39, 0x7E, 0x42, 0x61, 0x42, 0x73, 0x42,
+ 0x00, 0x0D, 0xA4, 0xAA, 0x5A, 0x05, 0x4D, 0x98, 0x4D, 0x61, 0x3F, 0x6D,
+ 0x47, 0x69, 0x2D, 0x71, 0x36, 0x71, 0x0E, 0x63, 0x1A, 0x71, 0x00, 0x37,
+ 0x00, 0x53, 0x0D, 0x0E, 0x00, 0x1D, 0x2E, 0x00, 0x1B, 0x00, 0x41, 0x04,
+ 0x39, 0x00, 0x4F, 0x12, 0x49, 0x09, 0x4F, 0x02, 0x69, 0x02, 0x69, 0x98,
+ 0x4D, 0x98, 0x0D, 0x54, 0x55, 0x55, 0x05, 0x00, 0x96, 0x00, 0x00, 0x2D,
+ 0x00, 0x49, 0x66, 0x63, 0x00, 0x91, 0x00, 0x91, 0x96, 0x75, 0x96, 0x75,
+ 0x20, 0x57, 0x96, 0x3A, 0x96, 0x1C, 0x20, 0x1C, 0x96, 0x00, 0x96, 0x0D,
+ 0x94, 0xAA, 0x6A, 0x05, 0x00, 0x02, 0x1B, 0x02, 0x1B, 0x12, 0x29, 0x05,
+ 0x20, 0x0A, 0x3D, 0x00, 0x32, 0x00, 0x5D, 0x0E, 0x50, 0x00, 0x6A, 0x38,
+ 0x6A, 0x1D, 0x5D, 0x62, 0x6A, 0x53, 0x3C, 0x71, 0x4F, 0x71, 0x2C, 0x6E,
+ 0x33, 0x71, 0x1D, 0x61, 0x25, 0x6A, 0x1D, 0x98, 0x00, 0x98, 0x00, 0x02,
+ 0x0D, 0x98, 0xAA, 0xAA, 0x0A, 0x7F, 0x86, 0x97, 0x92, 0x8A, 0x8E, 0x8C,
+ 0xA8, 0x7F, 0xA2, 0x85, 0xA6, 0x6A, 0x95, 0x7D, 0xA1, 0x4A, 0x9B, 0x5C,
+ 0x9B, 0x14, 0x87, 0x27, 0x9B, 0x00, 0x4E, 0x00, 0x73, 0x14, 0x15, 0x00,
+ 0x29, 0x49, 0x00, 0x27, 0x00, 0x7E, 0x15, 0x6A, 0x00, 0x91, 0x4E, 0x91,
+ 0x29, 0x8C, 0x70, 0x91, 0x61, 0x7F, 0x86, 0x88, 0x7B, 0x0D, 0x54, 0x55,
+ 0x55, 0x05, 0x24, 0x96, 0x00, 0x00, 0x1F, 0x00, 0x36, 0x67, 0x51, 0x00,
+ 0x75, 0x00, 0x8F, 0x68, 0xA6, 0x00, 0xC5, 0x00, 0xA0, 0x96, 0x80, 0x96,
+ 0x62, 0x26, 0x45, 0x96, 0x24, 0x96, 0x0D, 0x54, 0x55, 0x55, 0x05, 0x22,
+ 0x6D, 0x00, 0x00, 0x1C, 0x00, 0x30, 0x47, 0x43, 0x00, 0x5F, 0x00, 0x71,
+ 0x47, 0x86, 0x00, 0xA2, 0x00, 0x7F, 0x6D, 0x63, 0x6D, 0x51, 0x27, 0x3E,
+ 0x6D, 0x22, 0x6D, 0x0D, 0x54, 0x55, 0x55, 0x05, 0x00, 0x00, 0x17, 0x00,
+ 0x21, 0x56, 0x2D, 0x00, 0x49, 0x00, 0x55, 0x56, 0x5E, 0x00, 0x73, 0x00,
+ 0x61, 0x7F, 0x47, 0x7F, 0x3B, 0x24, 0x2E, 0x7F, 0x14, 0x7F, 0x00, 0x00,
+ 0x0E, 0xA4, 0xAA, 0x9A, 0x2A, 0x47, 0x4C, 0x64, 0x51, 0x52, 0x69, 0x5E,
+ 0x61, 0x35, 0x71, 0x47, 0x71, 0x0B, 0x5F, 0x18, 0x71, 0x00, 0x39, 0x00,
+ 0x50, 0x0E, 0x0F, 0x00, 0x1E, 0x32, 0x00, 0x1C, 0x00, 0x58, 0x10, 0x4A,
+ 0x00, 0x66, 0x41, 0x66, 0x20, 0x1D, 0x41, 0x24, 0x55, 0x1E, 0x4D, 0x35,
+ 0x5C, 0x2B, 0x5C, 0x40, 0x58, 0x3C, 0x5C, 0x47, 0x4C, 0x45, 0x54, 0x0E,
+ 0xA4, 0x6A, 0xAA, 0x16, 0x35, 0x00, 0x35, 0x69, 0x32, 0x87, 0x35, 0x7E,
+ 0x28, 0x94, 0x2F, 0x8F, 0x14, 0x97, 0x20, 0x97, 0x0B, 0x97, 0x10, 0x97,
+ 0x00, 0x96, 0x06, 0x97, 0x05, 0x7D, 0x09, 0x7E, 0x07, 0x7E, 0x0C, 0x7E,
+ 0x0B, 0x7E, 0x13, 0x7C, 0x11, 0x7E, 0x17, 0x78, 0x16, 0x7A, 0x18, 0x68,
+ 0x18, 0x75, 0x18, 0x00, 0x35, 0x00, 0x0E, 0xA8, 0x56, 0xAA, 0x15, 0x21,
+ 0x52, 0x22, 0x5E, 0x21, 0x59, 0x26, 0x66, 0x23, 0x63, 0x2E, 0x6C, 0x29,
+ 0x6A, 0x3B, 0x6E, 0x33, 0x6E, 0x72, 0x6E, 0x72, 0x8F, 0x3B, 0x8F, 0x21,
+ 0x8B, 0x2C, 0x8F, 0x0F, 0x7F, 0x16, 0x86, 0x04, 0x6B, 0x08, 0x76, 0x00,
+ 0x51, 0x00, 0x60, 0x00, 0x00, 0x21, 0x00, 0x21, 0x52, 0x0E, 0xA4, 0xAA,
+ 0xA9, 0x2A, 0x00, 0x2A, 0x00, 0x0F, 0x1E, 0x01, 0x0D, 0x01, 0x2A, 0x02,
+ 0x25, 0x01, 0x3E, 0x09, 0x30, 0x04, 0x51, 0x0F, 0x4C, 0x0F, 0x5E, 0x0B,
+ 0x56, 0x0F, 0x6D, 0x00, 0x66, 0x08, 0x6D, 0x1C, 0x5F, 0x25, 0x68, 0x21,
+ 0x4E, 0x29, 0x57, 0x29, 0x44, 0x28, 0x49, 0x29, 0x35, 0x22, 0x3F, 0x27,
+ 0x1C, 0x1B, 0x25, 0x1B, 0x00, 0x2A, 0x0E, 0x1B, 0x0E, 0x94, 0x56, 0x95,
+ 0x15, 0x00, 0x6D, 0x00, 0x56, 0x29, 0x28, 0x38, 0x17, 0x33, 0x1C, 0x2A,
+ 0x18, 0x33, 0x18, 0x04, 0x18, 0x04, 0x00, 0x5E, 0x00, 0x5E, 0x14, 0x34,
+ 0x44, 0x26, 0x54, 0x34, 0x53, 0x32, 0x53, 0x61, 0x53, 0x61, 0x6D, 0x00,
+ 0x6D, 0x0F, 0xA4, 0xAA, 0xAA, 0x5A, 0x00, 0x00, 0x3C, 0x00, 0x56, 0x01,
+ 0x4E, 0x00, 0x66, 0x07, 0x5F, 0x03, 0x72, 0x14, 0x6D, 0x0C, 0x76, 0x25,
+ 0x76, 0x1C, 0x71, 0x39, 0x76, 0x30, 0x61, 0x46, 0x6B, 0x42, 0x76, 0x54,
+ 0x6F, 0x4A, 0x7E, 0x6A, 0x7E, 0x5D, 0x79, 0x7E, 0x7E, 0x74, 0x6C, 0x8E,
+ 0x74, 0x88, 0x58, 0x95, 0x64, 0x93, 0x33, 0x96, 0x50, 0x96, 0x00, 0x96,
+ 0x00, 0x00, 0x10, 0xA4, 0xAA, 0xAA, 0xAA, 0x02, 0x61, 0x25, 0x46, 0x29,
+ 0x40, 0x1C, 0x45, 0x20, 0x35, 0x18, 0x3C, 0x18, 0x26, 0x20, 0x2C, 0x18,
+ 0x1E, 0x42, 0x1F, 0x28, 0x38, 0x35, 0x29, 0x35, 0x57, 0x43, 0x4A, 0x35,
+ 0x64, 0x66, 0x64, 0x51, 0x57, 0x8B, 0x64, 0x7D, 0x34, 0x99, 0x49, 0x99,
+ 0x0F, 0x88, 0x1D, 0x99, 0x00, 0x4E, 0x00, 0x76, 0x0F, 0x12, 0x00, 0x25,
+ 0x37, 0x00, 0x1E, 0x00, 0x53, 0x0A, 0x48, 0x00, 0x61, 0x25, 0x5E, 0x13,
+ 0x10, 0xA8, 0xAA, 0xAA, 0xAA, 0x02, 0x19, 0x46, 0x09, 0x39, 0x0E, 0x41,
+ 0x04, 0x27, 0x04, 0x31, 0x0F, 0x0B, 0x04, 0x16, 0x31, 0x00, 0x1B, 0x00,
+ 0x52, 0x0B, 0x46, 0x00, 0x5E, 0x27, 0x5E, 0x16, 0x58, 0x39, 0x5E, 0x31,
+ 0x49, 0x46, 0x53, 0x41, 0x5C, 0x54, 0x56, 0x4B, 0x63, 0x6B, 0x63, 0x5E,
+ 0x55, 0x8C, 0x63, 0x7F, 0x32, 0x99, 0x48, 0x99, 0x10, 0x8F, 0x1E, 0x99,
+ 0x00, 0x6C, 0x00, 0x82, 0x06, 0x56, 0x00, 0x60, 0x19, 0x46, 0x0C, 0x4B,
+ 0x10, 0x54, 0x95, 0xAA, 0xA9, 0x01, 0x00, 0x00, 0x1F, 0x00, 0x39, 0x4D,
+ 0x52, 0x00, 0x70, 0x00, 0x49, 0x69, 0x43, 0x7C, 0x3B, 0x8A, 0x3F, 0x85,
+ 0x33, 0x92, 0x38, 0x8F, 0x28, 0x97, 0x2F, 0x95, 0x1A, 0x97, 0x22, 0x97,
+ 0x0A, 0x97, 0x11, 0x97, 0x07, 0x81, 0x13, 0x82, 0x0E, 0x82, 0x22, 0x7C,
+ 0x1D, 0x82, 0x29, 0x6D, 0x27, 0x76, 0x00, 0x00, 0x10, 0x94, 0xA6, 0x69,
+ 0x9A, 0x02, 0xA2, 0x10, 0x61, 0x10, 0x5E, 0x09, 0x59, 0x02, 0x5C, 0x05,
+ 0x51, 0x00, 0x55, 0x00, 0x0A, 0x00, 0x03, 0x03, 0x06, 0x00, 0x00, 0x0B,
+ 0x00, 0x06, 0x00, 0x78, 0x03, 0x80, 0x00, 0x7D, 0x0A, 0x83, 0x06, 0x83,
+ 0xA2, 0x83, 0xA9, 0x80, 0xA6, 0x83, 0xAC, 0x78, 0xAC, 0x7D, 0xAC, 0x1B,
+ 0xA9, 0x13, 0xAC, 0x16, 0xA2, 0x10, 0xA6, 0x10, 0x10, 0xA8, 0xA6, 0x69,
+ 0x9A, 0x02, 0x7D, 0x1B, 0x73, 0x0F, 0x76, 0x13, 0x6B, 0x06, 0x70, 0x0C,
+ 0x65, 0x02, 0x69, 0x04, 0x5E, 0x00, 0x61, 0x00, 0x07, 0x00, 0x02, 0x03,
+ 0x04, 0x00, 0x00, 0x07, 0x00, 0x05, 0x00, 0xAA, 0x02, 0xAF, 0x00, 0xAD,
+ 0x07, 0xB1, 0x04, 0xB1, 0x7B, 0xB1, 0x80, 0xAF, 0x7E, 0xB1, 0x82, 0xAA,
+ 0x82, 0xAD, 0x82, 0x27, 0x81, 0x20, 0x82, 0x24, 0x7D, 0x1B, 0x7F, 0x1D,
+ 0x10, 0xA4, 0xAA, 0xAA, 0xAA, 0x02, 0x03, 0x74, 0x1F, 0x71, 0x24, 0x7E,
+ 0x20, 0x79, 0x2F, 0x82, 0x28, 0x82, 0x3F, 0x79, 0x38, 0x82, 0x47, 0x57,
+ 0x45, 0x71, 0x2B, 0x64, 0x3C, 0x64, 0x0D, 0x56, 0x1A, 0x64, 0x00, 0x33,
+ 0x00, 0x49, 0x0E, 0x0E, 0x00, 0x1C, 0x30, 0x00, 0x1B, 0x00, 0x56, 0x12,
+ 0x47, 0x00, 0x64, 0x4C, 0x64, 0x23, 0x55, 0x87, 0x64, 0x75, 0x2D, 0x99,
+ 0x46, 0x99, 0x11, 0x90, 0x1C, 0x99, 0x03, 0x74, 0x06, 0x87, 0x12, 0xA4,
+ 0xAA, 0x9A, 0xAA, 0x2A, 0x65, 0x62, 0x83, 0x6B, 0x6C, 0x8F, 0x7C, 0x83,
+ 0x44, 0x9B, 0x5D, 0x9B, 0x13, 0x87, 0x26, 0x9B, 0x00, 0x4F, 0x00, 0x72,
+ 0x13, 0x15, 0x00, 0x2A, 0x46, 0x00, 0x27, 0x00, 0x73, 0x10, 0x62, 0x00,
+ 0x82, 0x2C, 0x7D, 0x1A, 0x64, 0x33, 0x59, 0x21, 0x62, 0x28, 0x45, 0x1A,
+ 0x51, 0x1A, 0x2A, 0x26, 0x34, 0x1A, 0x1F, 0x4D, 0x1F, 0x32, 0x29, 0x75,
+ 0x1F, 0x69, 0x44, 0x81, 0x34, 0x81, 0x59, 0x7A, 0x50, 0x81, 0x65, 0x62,
+ 0x62, 0x72, 0x12, 0x54, 0x7F, 0xF5, 0xFF, 0x17, 0x00, 0x53, 0x11, 0x53,
+ 0x11, 0x30, 0x14, 0x30, 0x1D, 0x31, 0x18, 0x30, 0x1B, 0x31, 0x22, 0x35,
+ 0x1F, 0x32, 0x21, 0x33, 0x2B, 0x41, 0x24, 0x36, 0x27, 0x3B, 0x37, 0x53,
+ 0x4B, 0x53, 0x41, 0x43, 0x37, 0x35, 0x3D, 0x3C, 0x3A, 0x38, 0x2E, 0x2E,
+ 0x35, 0x33, 0x32, 0x31, 0x3F, 0x27, 0x36, 0x2D, 0x3B, 0x2B, 0x45, 0x17,
+ 0x43, 0x23, 0x45, 0x1D, 0x41, 0x0A, 0x45, 0x12, 0x43, 0x0D, 0x37, 0x02,
+ 0x3F, 0x06, 0x3B, 0x03, 0x24, 0x00, 0x33, 0x00, 0x2D, 0x00, 0x00, 0x00,
+ 0x00, 0x53, 0x12, 0x94, 0xAA, 0x5A, 0xA9, 0x15, 0x00, 0x96, 0x00, 0x00,
+ 0x40, 0x00, 0x63, 0x04, 0x58, 0x00, 0x74, 0x12, 0x6E, 0x08, 0x7B, 0x2A,
+ 0x7B, 0x1C, 0x71, 0x46, 0x7B, 0x3B, 0x53, 0x54, 0x67, 0x51, 0x63, 0x60,
+ 0x5D, 0x59, 0x75, 0x78, 0x6A, 0x67, 0x87, 0x96, 0x63, 0x96, 0x4D, 0x75,
+ 0x3D, 0x5F, 0x41, 0x64, 0x34, 0x59, 0x38, 0x5A, 0x24, 0x57, 0x2F, 0x57,
+ 0x1E, 0x57, 0x1E, 0x96, 0x00, 0x96, 0x12, 0xA4, 0xAA, 0x9A, 0xAA, 0x2A,
+ 0x65, 0x22, 0x49, 0x27, 0x42, 0x1B, 0x47, 0x1F, 0x35, 0x16, 0x3D, 0x16,
+ 0x24, 0x1E, 0x2A, 0x16, 0x1E, 0x36, 0x1E, 0x25, 0x24, 0x52, 0x1E, 0x4A,
+ 0x36, 0x5A, 0x2B, 0x5A, 0x43, 0x55, 0x3E, 0x5A, 0x4A, 0x45, 0x48, 0x50,
+ 0x67, 0x4A, 0x56, 0x67, 0x62, 0x5D, 0x34, 0x71, 0x49, 0x71, 0x0E, 0x62,
+ 0x1C, 0x71, 0x00, 0x38, 0x00, 0x53, 0x0E, 0x0F, 0x00, 0x1E, 0x35, 0x00,
+ 0x1C, 0x00, 0x54, 0x08, 0x49, 0x00, 0x65, 0x22, 0x60, 0x11, 0x13, 0xA4,
+ 0xAA, 0x6A, 0xAA, 0xAA, 0x42, 0x71, 0x28, 0x71, 0x28, 0x6A, 0x28, 0x6B,
+ 0x2C, 0x55, 0x28, 0x5D, 0x3D, 0x43, 0x30, 0x4D, 0x4C, 0x35, 0x49, 0x39,
+ 0x50, 0x2A, 0x50, 0x30, 0x49, 0x1C, 0x50, 0x22, 0x37, 0x16, 0x42, 0x16,
+ 0x25, 0x1C, 0x2C, 0x16, 0x1A, 0x2F, 0x1D, 0x23, 0x00, 0x2C, 0x10, 0x0D,
+ 0x01, 0x1A, 0x36, 0x00, 0x1E, 0x00, 0x5D, 0x0D, 0x4E, 0x00, 0x6C, 0x2B,
+ 0x6C, 0x1A, 0x66, 0x3D, 0x6C, 0x35, 0x4F, 0x54, 0x61, 0x46, 0x44, 0x61,
+ 0x46, 0x5C, 0x42, 0x71, 0x42, 0x65, 0x13, 0xA4, 0x9A, 0xA6, 0x66, 0x96,
+ 0x16, 0x48, 0x07, 0x3C, 0x16, 0x2C, 0x0E, 0x33, 0x1A, 0x28, 0x19, 0x29,
+ 0x0B, 0x25, 0x18, 0x28, 0x00, 0x21, 0x03, 0x22, 0x06, 0x0F, 0x1E, 0x1B,
+ 0x13, 0x15, 0x1C, 0x00, 0x1C, 0x0B, 0x2E, 0x00, 0x2B, 0x1C, 0x2E, 0x08,
+ 0x34, 0x18, 0x2D, 0x1B, 0x45, 0x10, 0x3D, 0x13, 0x4A, 0x23, 0x30, 0x28,
+ 0x3F, 0x25, 0x3C, 0x36, 0x42, 0x3D, 0x40, 0x3A, 0x32, 0x47, 0x25, 0x30,
+ 0x16, 0x48, 0x1E, 0x3B, 0x13, 0x94, 0x6A, 0x6A, 0x55, 0x55, 0x00, 0x2C,
+ 0x10, 0x2C, 0x10, 0x24, 0x13, 0x0F, 0x10, 0x16, 0x1E, 0x04, 0x16, 0x09,
+ 0x31, 0x00, 0x25, 0x00, 0x49, 0x04, 0x3E, 0x00, 0x46, 0x18, 0x38, 0x16,
+ 0x3F, 0x16, 0x2F, 0x19, 0x32, 0x16, 0x2D, 0x24, 0x2D, 0x1C, 0x2D, 0x2C,
+ 0x42, 0x2C, 0x42, 0x43, 0x2D, 0x43, 0x2D, 0x99, 0x10, 0x99, 0x10, 0x43,
+ 0x00, 0x43, 0x00, 0x2C, 0x13, 0xA4, 0x6A, 0xA5, 0xAA, 0x55, 0x48, 0x6D,
+ 0x48, 0x5C, 0x38, 0x6A, 0x42, 0x65, 0x24, 0x6F, 0x2F, 0x6F, 0x10, 0x6A,
+ 0x19, 0x6F, 0x04, 0x5D, 0x08, 0x66, 0x00, 0x45, 0x00, 0x54, 0x00, 0x00,
+ 0x1D, 0x00, 0x1D, 0x32, 0x1E, 0x4E, 0x1D, 0x49, 0x24, 0x56, 0x20, 0x53,
+ 0x2F, 0x59, 0x28, 0x59, 0x3C, 0x55, 0x36, 0x59, 0x44, 0x4B, 0x42, 0x51,
+ 0x46, 0x2E, 0x46, 0x45, 0x46, 0x00, 0x63, 0x00, 0x63, 0x6D, 0x48, 0x6D,
+ 0x13, 0x94, 0xAA, 0x56, 0xA5, 0x6A, 0x63, 0x6F, 0x46, 0x6F, 0x46, 0x37,
+ 0x44, 0x21, 0x46, 0x26, 0x3E, 0x18, 0x43, 0x1B, 0x34, 0x16, 0x3A, 0x16,
+ 0x27, 0x1A, 0x2D, 0x16, 0x1F, 0x25, 0x21, 0x1E, 0x1D, 0x3D, 0x1D, 0x2B,
+ 0x1D, 0x6F, 0x00, 0x6F, 0x00, 0x02, 0x1B, 0x02, 0x1B, 0x12, 0x3F, 0x00,
+ 0x29, 0x00, 0x50, 0x03, 0x48, 0x00, 0x5C, 0x0C, 0x58, 0x06, 0x61, 0x18,
+ 0x60, 0x11, 0x63, 0x2B, 0x63, 0x1F, 0x63, 0x6F, 0x13, 0xA4, 0x6A, 0xA5,
+ 0xAA, 0x55, 0x1D, 0x00, 0x1D, 0x37, 0x3E, 0x27, 0x2B, 0x27, 0x50, 0x2A,
+ 0x48, 0x27, 0x5C, 0x34, 0x58, 0x2E, 0x61, 0x40, 0x60, 0x39, 0x63, 0x56,
+ 0x63, 0x47, 0x63, 0x96, 0x46, 0x96, 0x46, 0x5C, 0x45, 0x47, 0x46, 0x4B,
+ 0x3F, 0x3F, 0x43, 0x42, 0x34, 0x3D, 0x3B, 0x3D, 0x28, 0x40, 0x2D, 0x3D,
+ 0x1F, 0x4B, 0x22, 0x44, 0x1D, 0x5F, 0x1D, 0x52, 0x1D, 0x96, 0x00, 0x96,
+ 0x00, 0x00, 0x1D, 0x00, 0x14, 0xA4, 0x9A, 0x6A, 0xAA, 0xA9, 0x02, 0x00,
+ 0x60, 0x00, 0x30, 0x04, 0x1D, 0x00, 0x25, 0x0E, 0x0D, 0x08, 0x14, 0x1D,
+ 0x03, 0x14, 0x07, 0x30, 0x00, 0x26, 0x00, 0x6D, 0x00, 0x80, 0x03, 0x77,
+ 0x00, 0x8E, 0x0D, 0x88, 0x07, 0x98, 0x1D, 0x95, 0x14, 0x9C, 0x30, 0x9C,
+ 0x25, 0x9C, 0x60, 0x98, 0x72, 0x9C, 0x6A, 0x8E, 0x81, 0x95, 0x7B, 0x80,
+ 0x8B, 0x88, 0x88, 0x6D, 0x8F, 0x77, 0x8F, 0x30, 0x8F, 0x1D, 0x8B, 0x26,
+ 0x8F, 0x0E, 0x81, 0x14, 0x88, 0x04, 0x72, 0x08, 0x7B, 0x00, 0x60, 0x00,
+ 0x6A, 0x14, 0x54, 0xA5, 0x5A, 0xAA, 0x55, 0x01, 0x4B, 0x77, 0x21, 0x31,
+ 0x21, 0x8F, 0x00, 0x8F, 0x00, 0x00, 0x18, 0x00, 0x20, 0x01, 0x1C, 0x00,
+ 0x29, 0x06, 0x25, 0x03, 0x30, 0x0C, 0x2D, 0x09, 0x36, 0x14, 0x34, 0x10,
+ 0x4B, 0x37, 0x5F, 0x14, 0x65, 0x0C, 0x62, 0x10, 0x6D, 0x06, 0x69, 0x08,
+ 0x75, 0x01, 0x71, 0x03, 0x7D, 0x00, 0x79, 0x00, 0x96, 0x00, 0x96, 0x8F,
+ 0x75, 0x8F, 0x75, 0x31, 0x4B, 0x77, 0x14, 0x94, 0xAA, 0x56, 0xAA, 0xAA,
+ 0x01, 0x00, 0x00, 0x1E, 0x00, 0x1E, 0x51, 0x1F, 0x6A, 0x1E, 0x64, 0x29,
+ 0x79, 0x21, 0x73, 0x3D, 0x7E, 0x30, 0x7E, 0x50, 0x79, 0x4A, 0x7E, 0x58,
+ 0x6C, 0x57, 0x74, 0x59, 0x53, 0x59, 0x64, 0x59, 0x00, 0x78, 0x00, 0x78,
+ 0x4E, 0x75, 0x75, 0x78, 0x6A, 0x6C, 0x87, 0x73, 0x80, 0x5A, 0x94, 0x66,
+ 0x8F, 0x3E, 0x98, 0x4F, 0x98, 0x1D, 0x93, 0x28, 0x98, 0x0B, 0x86, 0x12,
+ 0x8E, 0x03, 0x76, 0x05, 0x7E, 0x00, 0x50, 0x00, 0x69, 0x00, 0x00, 0x15,
+ 0xA4, 0xAA, 0x56, 0x95, 0xAA, 0x0A, 0x00, 0x6D, 0x1D, 0x6A, 0x24, 0x7A,
+ 0x1E, 0x74, 0x32, 0x7F, 0x2A, 0x7F, 0x41, 0x78, 0x3B, 0x7F, 0x47, 0x62,
+ 0x47, 0x71, 0x41, 0x4D, 0x47, 0x54, 0x31, 0x46, 0x3B, 0x46, 0x1B, 0x51,
+ 0x25, 0x46, 0x03, 0x4E, 0x12, 0x00, 0x5E, 0x00, 0x5E, 0x1B, 0x28, 0x1B,
+ 0x24, 0x34, 0x37, 0x2F, 0x2D, 0x2F, 0x58, 0x3D, 0x4A, 0x2F, 0x65, 0x61,
+ 0x65, 0x4B, 0x5A, 0x82, 0x65, 0x74, 0x32, 0x96, 0x4C, 0x96, 0x10, 0x8B,
+ 0x1D, 0x96, 0x00, 0x6D, 0x03, 0x80, 0x15, 0x94, 0xAA, 0x6A, 0xAA, 0xAA,
+ 0x06, 0x65, 0x7C, 0x65, 0x97, 0x00, 0x97, 0x0A, 0x7A, 0x02, 0x88, 0x2A,
+ 0x56, 0x12, 0x6C, 0x42, 0x3D, 0x3E, 0x44, 0x48, 0x2C, 0x48, 0x35, 0x43,
+ 0x1D, 0x48, 0x22, 0x34, 0x18, 0x3E, 0x18, 0x26, 0x1D, 0x2B, 0x18, 0x20,
+ 0x2F, 0x21, 0x23, 0x03, 0x2C, 0x13, 0x0A, 0x06, 0x15, 0x35, 0x00, 0x21,
+ 0x00, 0x58, 0x0C, 0x4B, 0x00, 0x65, 0x2A, 0x65, 0x18, 0x61, 0x3D, 0x65,
+ 0x34, 0x56, 0x50, 0x5E, 0x46, 0x43, 0x63, 0x50, 0x57, 0x32, 0x74, 0x35,
+ 0x70, 0x2C, 0x7C, 0x2E, 0x78, 0x65, 0x7C, 0x15, 0x94, 0xAA, 0x56, 0xAA,
+ 0x6A, 0x05, 0x00, 0x8F, 0x00, 0x38, 0x61, 0x38, 0x67, 0x37, 0x65, 0x38,
+ 0x6B, 0x34, 0x6A, 0x36, 0x6D, 0x30, 0x6D, 0x32, 0x6E, 0x2C, 0x6E, 0x2E,
+ 0x6B, 0x25, 0x6E, 0x28, 0x61, 0x21, 0x69, 0x21, 0x00, 0x21, 0x00, 0x00,
+ 0x61, 0x00, 0x74, 0x03, 0x6B, 0x00, 0x83, 0x0D, 0x7D, 0x07, 0x8F, 0x2C,
+ 0x8F, 0x1B, 0x8C, 0x3D, 0x8F, 0x35, 0x83, 0x4C, 0x89, 0x45, 0x74, 0x56,
+ 0x7D, 0x53, 0x61, 0x5A, 0x6B, 0x5A, 0x21, 0x5A, 0x21, 0x8F, 0x00, 0x8F,
+ 0x15, 0x54, 0xAA, 0xA9, 0x5A, 0x55, 0x05, 0x3E, 0x26, 0x3E, 0x3D, 0x2A,
+ 0x3D, 0x2A, 0x69, 0x2B, 0x78, 0x2A, 0x76, 0x2D, 0x7C, 0x2B, 0x7A, 0x32,
+ 0x7D, 0x2F, 0x7D, 0x3E, 0x7B, 0x36, 0x7D, 0x40, 0x91, 0x29, 0x95, 0x36,
+ 0x95, 0x1B, 0x93, 0x22, 0x95, 0x12, 0x8C, 0x15, 0x90, 0x0E, 0x81, 0x0F,
+ 0x88, 0x0D, 0x6C, 0x0D, 0x7C, 0x0D, 0x3D, 0x00, 0x3D, 0x00, 0x26, 0x0D,
+ 0x26, 0x0D, 0x10, 0x2A, 0x00, 0x2A, 0x26, 0x3E, 0x26, 0x17, 0xA4, 0x6A,
+ 0xAA, 0x5A, 0xA9, 0xAA, 0x04, 0x76, 0x25, 0x7A, 0x28, 0x82, 0x25, 0x80,
+ 0x35, 0x85, 0x2D, 0x85, 0x46, 0x81, 0x41, 0x85, 0x4C, 0x7A, 0x4A, 0x7F,
+ 0x4D, 0x6D, 0x4D, 0x77, 0x4D, 0x5D, 0x2D, 0x6F, 0x40, 0x6F, 0x0A, 0x5C,
+ 0x17, 0x6F, 0x00, 0x38, 0x00, 0x4E, 0x0D, 0x0E, 0x00, 0x1C, 0x2E, 0x00,
+ 0x1A, 0x00, 0x4F, 0x11, 0x42, 0x00, 0x4F, 0x02, 0x6A, 0x02, 0x6A, 0x64,
+ 0x67, 0x80, 0x6A, 0x77, 0x5E, 0x8F, 0x64, 0x8A, 0x4F, 0x98, 0x58, 0x95,
+ 0x36, 0x99, 0x45, 0x99, 0x0F, 0x91, 0x1B, 0x99, 0x04, 0x79, 0x04, 0x88,
+ 0x04, 0x76, 0x04, 0x78, 0x17, 0xA4, 0xAA, 0xAA, 0xAA, 0x66, 0xAA, 0x8B,
+ 0x86, 0x79, 0x9D, 0x61, 0x8B, 0x6D, 0x96, 0x4D, 0x97, 0x58, 0x94, 0x35,
+ 0x9B, 0x43, 0x9B, 0x0B, 0x8C, 0x19, 0x9B, 0x00, 0x70, 0x00, 0x7F, 0x09,
+ 0x56, 0x00, 0x61, 0x22, 0x42, 0x11, 0x4A, 0x17, 0x30, 0x1B, 0x39, 0x13,
+ 0x21, 0x13, 0x28, 0x1E, 0x0A, 0x13, 0x13, 0x3D, 0x00, 0x29, 0x00, 0x5B,
+ 0x0A, 0x50, 0x00, 0x66, 0x22, 0x66, 0x14, 0x61, 0x34, 0x66, 0x2B, 0x4B,
+ 0x46, 0x5B, 0x3C, 0x60, 0x62, 0x66, 0x51, 0x63, 0x5B, 0x80, 0x57, 0x79,
+ 0x6B, 0x7C, 0x64, 0x73, 0x75, 0x76, 0x71, 0x80, 0x7F, 0x78, 0x7A, 0x8B,
+ 0x86, 0x87, 0x85, 0x18, 0x54, 0xAA, 0xAA, 0x9A, 0xAA, 0x6A, 0x01, 0x4B,
+ 0x62, 0x4B, 0x48, 0x8C, 0x48, 0x8C, 0x84, 0x71, 0x94, 0x83, 0x8D, 0x4C,
+ 0x9B, 0x5F, 0x9B, 0x23, 0x91, 0x35, 0x9B, 0x09, 0x75, 0x12, 0x88, 0x00,
+ 0x4D, 0x00, 0x63, 0x0A, 0x24, 0x00, 0x36, 0x27, 0x08, 0x14, 0x11, 0x4A,
+ 0x00, 0x35, 0x00, 0x76, 0x0C, 0x66, 0x00, 0x8A, 0x2C, 0x86, 0x18, 0x6C,
+ 0x32, 0x60, 0x20, 0x69, 0x27, 0x4A, 0x1A, 0x58, 0x1A, 0x2B, 0x27, 0x37,
+ 0x1A, 0x1F, 0x4C, 0x1F, 0x33, 0x2B, 0x74, 0x1F, 0x67, 0x4A, 0x81, 0x37,
+ 0x81, 0x5D, 0x7E, 0x54, 0x81, 0x6E, 0x75, 0x67, 0x7A, 0x6E, 0x62, 0x4B,
+ 0x62, 0x19, 0xA4, 0x5A, 0x69, 0xA6, 0x5A, 0x69, 0x0A, 0x2B, 0x8C, 0x2B,
+ 0x61, 0x0D, 0x4F, 0x17, 0x5B, 0x04, 0x33, 0x04, 0x44, 0x0F, 0x17, 0x04,
+ 0x22, 0x2B, 0x0A, 0x19, 0x0B, 0x2B, 0x00, 0x3A, 0x00, 0x3A, 0x0A, 0x54,
+ 0x15, 0x4A, 0x0C, 0x60, 0x2D, 0x5D, 0x1E, 0x46, 0x31, 0x3A, 0x20, 0x44,
+ 0x25, 0x3A, 0x48, 0x5B, 0x5A, 0x52, 0x4F, 0x64, 0x75, 0x64, 0x64, 0x59,
+ 0x94, 0x64, 0x87, 0x3A, 0xA4, 0x4E, 0xA1, 0x3A, 0xB7, 0x2B, 0xB7, 0x2B,
+ 0xA4, 0x0E, 0x97, 0x19, 0xA2, 0x00, 0x78, 0x03, 0x8C, 0x1B, 0x75, 0x21,
+ 0x83, 0x1C, 0x7D, 0x2B, 0x8C, 0x25, 0x89, 0x19, 0xA8, 0x56, 0xAA, 0x55,
+ 0x5A, 0xA9, 0x06, 0x00, 0x31, 0x03, 0x1F, 0x00, 0x27, 0x0D, 0x0F, 0x07,
+ 0x16, 0x1D, 0x04, 0x14, 0x08, 0x33, 0x00, 0x27, 0x00, 0x89, 0x00, 0x89,
+ 0x21, 0x35, 0x21, 0x2D, 0x23, 0x31, 0x21, 0x26, 0x27, 0x29, 0x24, 0x23,
+ 0x2F, 0x24, 0x2B, 0x21, 0x37, 0x21, 0x33, 0x21, 0x37, 0x89, 0x37, 0x89,
+ 0x58, 0x21, 0x58, 0x26, 0x67, 0x21, 0x61, 0x35, 0x6E, 0x2C, 0x6E, 0x89,
+ 0x6E, 0x89, 0x8F, 0x33, 0x8F, 0x1D, 0x8B, 0x26, 0x8F, 0x0D, 0x7F, 0x13,
+ 0x86, 0x03, 0x70, 0x06, 0x78, 0x00, 0x5F, 0x00, 0x67, 0x00, 0x31, 0x19,
+ 0xA4, 0x6A, 0x9A, 0xAA, 0xAA, 0xA6, 0x0A, 0x1D, 0x23, 0x03, 0x1E, 0x12,
+ 0x07, 0x07, 0x0F, 0x32, 0x00, 0x1D, 0x00, 0x4F, 0x04, 0x45, 0x00, 0x5C,
+ 0x10, 0x58, 0x09, 0x60, 0x29, 0x60, 0x17, 0x5F, 0x4B, 0x61, 0x60, 0x5F,
+ 0x59, 0x66, 0x6F, 0x62, 0x67, 0x4A, 0x6F, 0x47, 0x66, 0x48, 0x6C, 0x46,
+ 0x63, 0x46, 0x64, 0x36, 0x6E, 0x3E, 0x6A, 0x24, 0x71, 0x2E, 0x71, 0x0A,
+ 0x68, 0x13, 0x71, 0x00, 0x51, 0x00, 0x5F, 0x04, 0x41, 0x00, 0x48, 0x11,
+ 0x36, 0x09, 0x39, 0x28, 0x2F, 0x19, 0x32, 0x44, 0x28, 0x3C, 0x2B, 0x44,
+ 0x25, 0x3F, 0x19, 0x44, 0x1D, 0x30, 0x16, 0x3B, 0x16, 0x24, 0x19, 0x28,
+ 0x16, 0x1D, 0x23, 0x20, 0x1C, 0x1A, 0xA4, 0xAA, 0xAA, 0x9A, 0xAA, 0xAA,
+ 0x2A, 0x00, 0x50, 0x1D, 0x4B, 0x24, 0x58, 0x1F, 0x54, 0x34, 0x5C, 0x2A,
+ 0x5C, 0x45, 0x58, 0x3F, 0x5C, 0x49, 0x51, 0x49, 0x55, 0x47, 0x4B, 0x49,
+ 0x4D, 0x3D, 0x47, 0x44, 0x49, 0x11, 0x39, 0x1A, 0x40, 0x04, 0x21, 0x04,
+ 0x31, 0x0F, 0x09, 0x04, 0x13, 0x32, 0x00, 0x1A, 0x00, 0x53, 0x07, 0x48,
+ 0x00, 0x62, 0x1C, 0x5E, 0x0E, 0x47, 0x21, 0x40, 0x18, 0x45, 0x1B, 0x32,
+ 0x14, 0x3B, 0x14, 0x22, 0x17, 0x27, 0x14, 0x1F, 0x1D, 0x1F, 0x1A, 0x22,
+ 0x22, 0x1F, 0x20, 0x3C, 0x2B, 0x25, 0x25, 0x5D, 0x37, 0x53, 0x30, 0x66,
+ 0x4D, 0x66, 0x3F, 0x59, 0x66, 0x66, 0x5C, 0x34, 0x71, 0x4D, 0x71, 0x11,
+ 0x68, 0x1E, 0x71, 0x00, 0x50, 0x04, 0x5F, 0x1B, 0x54, 0x95, 0xAA, 0x6A,
+ 0xA5, 0xAA, 0x5A, 0x6B, 0x8F, 0x52, 0x5A, 0x21, 0x5A, 0x21, 0x8F, 0x00,
+ 0x8F, 0x00, 0x38, 0x61, 0x38, 0x67, 0x37, 0x65, 0x38, 0x6B, 0x34, 0x6A,
+ 0x36, 0x6D, 0x31, 0x6D, 0x32, 0x6E, 0x2D, 0x6E, 0x2F, 0x6D, 0x29, 0x6E,
+ 0x2B, 0x6B, 0x25, 0x6D, 0x27, 0x67, 0x22, 0x6A, 0x23, 0x61, 0x21, 0x65,
+ 0x21, 0x00, 0x21, 0x00, 0x00, 0x61, 0x00, 0x74, 0x03, 0x6B, 0x00, 0x83,
+ 0x0D, 0x7D, 0x07, 0x8C, 0x1C, 0x89, 0x14, 0x8F, 0x2D, 0x8F, 0x24, 0x8C,
+ 0x3D, 0x8F, 0x34, 0x83, 0x4C, 0x89, 0x45, 0x7D, 0x51, 0x81, 0x4F, 0x76,
+ 0x55, 0x7A, 0x54, 0x91, 0x8F, 0x6B, 0x8F, 0x1C, 0xA4, 0xAA, 0xA6, 0xAA,
+ 0xA9, 0xAA, 0xAA, 0x02, 0x00, 0x6F, 0x1C, 0x6C, 0x23, 0x7C, 0x1D, 0x76,
+ 0x31, 0x81, 0x29, 0x81, 0x40, 0x7B, 0x3A, 0x81, 0x46, 0x68, 0x46, 0x74,
+ 0x40, 0x57, 0x46, 0x5E, 0x32, 0x51, 0x3B, 0x51, 0x25, 0x53, 0x2D, 0x51,
+ 0x28, 0x3C, 0x3A, 0x37, 0x34, 0x3C, 0x40, 0x28, 0x40, 0x31, 0x3C, 0x1C,
+ 0x40, 0x21, 0x30, 0x18, 0x37, 0x18, 0x23, 0x1D, 0x28, 0x18, 0x1D, 0x2C,
+ 0x1E, 0x22, 0x02, 0x27, 0x0A, 0x12, 0x05, 0x1A, 0x1A, 0x05, 0x10, 0x09,
+ 0x30, 0x00, 0x24, 0x00, 0x52, 0x0E, 0x46, 0x00, 0x5D, 0x27, 0x5D, 0x19,
+ 0x47, 0x46, 0x5D, 0x3A, 0x5C, 0x52, 0x54, 0x49, 0x64, 0x6A, 0x64, 0x5C,
+ 0x55, 0x8B, 0x64, 0x7D, 0x31, 0x99, 0x47, 0x99, 0x10, 0x8E, 0x1D, 0x99,
+ 0x00, 0x6F, 0x02, 0x82, 0x1C, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x01, 0x0E, 0x73, 0x00, 0x73, 0x00, 0x5D, 0x12, 0x5D, 0x19, 0x3F, 0x00,
+ 0x3F, 0x00, 0x28, 0x1D, 0x28, 0x25, 0x00, 0x3C, 0x00, 0x34, 0x28, 0x4B,
+ 0x28, 0x53, 0x00, 0x6A, 0x00, 0x62, 0x28, 0x70, 0x28, 0x70, 0x3F, 0x5E,
+ 0x3F, 0x57, 0x5D, 0x70, 0x5D, 0x70, 0x73, 0x53, 0x73, 0x4B, 0x9B, 0x34,
+ 0x9B, 0x3C, 0x73, 0x25, 0x73, 0x1D, 0x9B, 0x06, 0x9B, 0x0E, 0x73, 0x1E,
+ 0xA4, 0xAA, 0xAA, 0xAA, 0xA9, 0xAA, 0xAA, 0x2A, 0x00, 0x68, 0x1D, 0x65,
+ 0x28, 0x7B, 0x20, 0x74, 0x3E, 0x82, 0x30, 0x82, 0x54, 0x7C, 0x4D, 0x82,
+ 0x5C, 0x6D, 0x5C, 0x75, 0x59, 0x64, 0x5C, 0x68, 0x4E, 0x5E, 0x55, 0x60,
+ 0x35, 0x57, 0x48, 0x5C, 0x13, 0x48, 0x1D, 0x51, 0x05, 0x2A, 0x05, 0x3C,
+ 0x0C, 0x15, 0x05, 0x1F, 0x1F, 0x05, 0x12, 0x0B, 0x3C, 0x00, 0x2B, 0x00,
+ 0x67, 0x0D, 0x58, 0x00, 0x76, 0x2E, 0x75, 0x19, 0x57, 0x2F, 0x4F, 0x1E,
+ 0x55, 0x23, 0x3C, 0x19, 0x49, 0x19, 0x27, 0x1F, 0x2F, 0x19, 0x22, 0x28,
+ 0x22, 0x22, 0x27, 0x31, 0x22, 0x2D, 0x43, 0x3B, 0x2D, 0x36, 0x63, 0x46,
+ 0x59, 0x40, 0x74, 0x55, 0x6E, 0x4B, 0x7A, 0x6D, 0x7A, 0x5F, 0x73, 0x85,
+ 0x7A, 0x7A, 0x5F, 0x96, 0x6C, 0x90, 0x3E, 0x9B, 0x51, 0x9B, 0x12, 0x8E,
+ 0x21, 0x9B, 0x00, 0x68, 0x03, 0x81, 0x1E, 0x94, 0xAA, 0x6A, 0xA5, 0x6A,
+ 0xA5, 0xAA, 0x15, 0x00, 0x02, 0x1B, 0x02, 0x1B, 0x11, 0x3C, 0x00, 0x29,
+ 0x00, 0x4E, 0x04, 0x47, 0x00, 0x5B, 0x11, 0x56, 0x08, 0x6B, 0x04, 0x62,
+ 0x08, 0x7C, 0x00, 0x73, 0x00, 0x90, 0x04, 0x88, 0x00, 0x9D, 0x13, 0x99,
+ 0x09, 0xA0, 0x29, 0xA0, 0x1A, 0xA0, 0x6F, 0x83, 0x6F, 0x83, 0x31, 0x80,
+ 0x1C, 0x83, 0x20, 0x74, 0x16, 0x7C, 0x16, 0x68, 0x19, 0x6E, 0x16, 0x61,
+ 0x24, 0x63, 0x1D, 0x5E, 0x3B, 0x5E, 0x2B, 0x5E, 0x6F, 0x42, 0x6F, 0x42,
+ 0x33, 0x40, 0x1F, 0x42, 0x23, 0x3B, 0x18, 0x3F, 0x1A, 0x33, 0x16, 0x38,
+ 0x16, 0x27, 0x19, 0x2C, 0x16, 0x1F, 0x24, 0x21, 0x1D, 0x1D, 0x3A, 0x1D,
+ 0x2A, 0x1D, 0x6F, 0x00, 0x6F, 0x00, 0x02, 0x20, 0xA8, 0x56, 0xAA, 0xA9,
+ 0xAA, 0x56, 0xAA, 0xA9, 0x02, 0x00, 0x22, 0x03, 0x18, 0x01, 0x1E, 0x0A,
+ 0x0C, 0x05, 0x12, 0x17, 0x03, 0x0E, 0x07, 0x2B, 0x00, 0x1F, 0x00, 0x77,
+ 0x00, 0x63, 0x20, 0x2B, 0x20, 0x25, 0x21, 0x28, 0x20, 0x23, 0x25, 0x23,
+ 0x23, 0x24, 0x29, 0x23, 0x27, 0x27, 0x2C, 0x25, 0x2B, 0x64, 0x45, 0x70,
+ 0x4D, 0x6C, 0x49, 0x77, 0x57, 0x75, 0x52, 0x7B, 0x62, 0x7A, 0x5D, 0x7B,
+ 0x6D, 0x7B, 0x68, 0x79, 0x77, 0x7B, 0x71, 0x72, 0x83, 0x77, 0x7D, 0x65,
+ 0x8C, 0x6D, 0x88, 0x50, 0x8F, 0x5D, 0x8F, 0x15, 0x8F, 0x00, 0x6F, 0x50,
+ 0x6F, 0x56, 0x6E, 0x54, 0x6F, 0x59, 0x6A, 0x58, 0x6C, 0x58, 0x66, 0x59,
+ 0x68, 0x55, 0x63, 0x57, 0x64, 0x17, 0x4A, 0x0B, 0x42, 0x10, 0x47, 0x04,
+ 0x38, 0x07, 0x3D, 0x01, 0x2D, 0x01, 0x32, 0x00, 0x22, 0x00, 0x27, 0x21,
+ 0xA8, 0xAA, 0x96, 0xAA, 0xAA, 0xAA, 0xA5, 0xAA, 0x06, 0x46, 0x6F, 0x3B,
+ 0x71, 0x3F, 0x6F, 0x34, 0x77, 0x37, 0x73, 0x30, 0x82, 0x32, 0x7C, 0x30,
+ 0x93, 0x30, 0x87, 0x2E, 0xAF, 0x30, 0xA7, 0x27, 0xBB, 0x2C, 0xB7, 0x19,
+ 0xC3, 0x22, 0xC0, 0x05, 0xC3, 0x13, 0xC3, 0x00, 0xC3, 0x00, 0xAC, 0x0E,
+ 0xAB, 0x0B, 0xAC, 0x13, 0xA7, 0x12, 0xA9, 0x15, 0x9E, 0x15, 0xA4, 0x16,
+ 0x86, 0x15, 0x98, 0x19, 0x75, 0x16, 0x7C, 0x1E, 0x6A, 0x1B, 0x6F, 0x28,
+ 0x62, 0x22, 0x66, 0x1D, 0x59, 0x21, 0x5E, 0x17, 0x48, 0x18, 0x52, 0x15,
+ 0x28, 0x15, 0x41, 0x13, 0x1E, 0x15, 0x20, 0x0F, 0x1A, 0x12, 0x1B, 0x00,
+ 0x19, 0x0C, 0x19, 0x00, 0x00, 0x05, 0x00, 0x1B, 0x02, 0x13, 0x00, 0x27,
+ 0x0A, 0x22, 0x04, 0x2E, 0x16, 0x2C, 0x0F, 0x30, 0x2E, 0x30, 0x1E, 0x31,
+ 0x46, 0x30, 0x41, 0x38, 0x52, 0x33, 0x4F, 0x46, 0x56, 0x3D, 0x56, 0x46,
+ 0x6F, 0x22, 0xA4, 0xAA, 0x5A, 0xAA, 0xAA, 0xAA, 0x5A, 0xAA, 0x2A, 0x00,
+ 0x6F, 0x00, 0x56, 0x0B, 0x54, 0x07, 0x56, 0x12, 0x4E, 0x0F, 0x52, 0x16,
+ 0x43, 0x15, 0x49, 0x16, 0x32, 0x16, 0x3E, 0x18, 0x16, 0x16, 0x1E, 0x1F,
+ 0x0A, 0x1A, 0x0E, 0x2D, 0x02, 0x24, 0x05, 0x41, 0x00, 0x33, 0x00, 0x46,
+ 0x00, 0x46, 0x19, 0x37, 0x1A, 0x3B, 0x19, 0x33, 0x1E, 0x34, 0x1B, 0x31,
+ 0x27, 0x31, 0x20, 0x30, 0x3F, 0x31, 0x2D, 0x2E, 0x50, 0x30, 0x49, 0x28,
+ 0x5A, 0x2B, 0x56, 0x1E, 0x62, 0x25, 0x5E, 0x28, 0x6B, 0x24, 0x66, 0x2E,
+ 0x76, 0x2C, 0x6F, 0x30, 0x88, 0x30, 0x7D, 0x31, 0x9D, 0x31, 0x99, 0x33,
+ 0xA7, 0x31, 0xA4, 0x38, 0xAB, 0x34, 0xA9, 0x46, 0xAC, 0x3B, 0xAC, 0x46,
+ 0xC3, 0x41, 0xC3, 0x2B, 0xC3, 0x33, 0xC3, 0x1F, 0xBB, 0x24, 0xC0, 0x18,
+ 0xAF, 0x1A, 0xB6, 0x16, 0x97, 0x16, 0xA7, 0x15, 0x7F, 0x16, 0x84, 0x0E,
+ 0x73, 0x13, 0x76, 0x00, 0x6F, 0x09, 0x6F, 0x29, 0xA4, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0x6A, 0xA5, 0xAA, 0xAA, 0xAA, 0x0A, 0xB0, 0x97, 0xC5, 0x97, 0xA6,
+ 0xB7, 0xBB, 0xAC, 0x6B, 0xC3, 0x8E, 0xC3, 0x31, 0xB9, 0x49, 0xC3, 0x0C,
+ 0x98, 0x18, 0xAE, 0x00, 0x67, 0x00, 0x81, 0x0E, 0x32, 0x00, 0x4B, 0x33,
+ 0x0D, 0x1B, 0x19, 0x69, 0x00, 0x4A, 0x00, 0x97, 0x0A, 0x83, 0x00, 0xB5,
+ 0x27, 0xAB, 0x14, 0xC0, 0x4F, 0xC0, 0x39, 0xB0, 0x7E, 0xC0, 0x69, 0x7C,
+ 0x99, 0x9C, 0x99, 0x6F, 0x96, 0x74, 0x99, 0x6A, 0x8D, 0x6B, 0x93, 0x4E,
+ 0x99, 0x5E, 0x99, 0x32, 0x8D, 0x3D, 0x99, 0x26, 0x6E, 0x26, 0x81, 0x34,
+ 0x42, 0x26, 0x56, 0x5E, 0x2A, 0x44, 0x2A, 0x79, 0x38, 0x70, 0x2A, 0x7B,
+ 0x2C, 0x96, 0x2C, 0x87, 0x76, 0x86, 0x7F, 0x86, 0x7D, 0x87, 0x83, 0x86,
+ 0x81, 0x8A, 0x84, 0x88, 0x84, 0x96, 0x7E, 0x8E, 0x84, 0xA7, 0x69, 0xA1,
+ 0x76, 0xAE, 0x4E, 0xAE, 0x5C, 0x9B, 0x24, 0xAE, 0x35, 0x68, 0x13, 0x89,
+ 0x13, 0x39, 0x1E, 0x4D, 0x13, 0x1C, 0x3E, 0x26, 0x29, 0x13, 0x69, 0x13,
+ 0x53, 0x1D, 0x90, 0x13, 0x7E, 0x3C, 0xAA, 0x28, 0xA2, 0x69, 0xB2, 0x50,
+ 0xB2, 0x93, 0xAB, 0x82, 0xB2, 0xB0, 0x97, 0xA5, 0xA4, 0xC0, 0x00, 0x24,
+ 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x39, 0x00, 0x00,
+ 0x3C, 0x00, 0x00, 0x92, 0x00, 0xC0, 0x00, 0x37, 0x00, 0x00, 0xB6, 0x00,
+ 0x00, 0x83, 0x00, 0xC0, 0x00, 0x37, 0x00, 0x00, 0xB6, 0x00, 0x00, 0x71,
+ 0x00, 0xC0, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x9F, 0x00, 0xC0,
+ 0x00, 0x24, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0xB6,
+ 0x00, 0x00, 0xB6, 0x00, 0x00, 0x9B, 0x00, 0xC0, 0x00, 0xB6, 0x00, 0x00,
+ 0xB6, 0x00, 0x00, 0x9D, 0x00, 0xC0, 0x00, 0x24, 0x00, 0x00, 0x59, 0x00,
+ 0x00, 0x59, 0x00, 0xC0, 0x00, 0x24, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x3F,
+ 0x00, 0xC0, 0x00, 0x3D, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x97, 0x00, 0xC0,
+ 0x00, 0x24, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x21, 0x00, 0xC0, 0x00, 0x24,
+ 0x00, 0x00, 0x24, 0x00, 0x00, 0xA1, 0x00, 0x9F, 0x00, 0x00, 0x00, 0x00,
+ 0x3B, 0x00, 0x00, 0x02, 0x20, 0xD5, 0x34, 0x00, 0x00, 0x3E, 0x42, 0x03,
+ 0x00, 0x01, 0xB7, 0x79, 0x00, 0x00, 0x00, 0x02, 0x4E, 0x74, 0x59, 0x00,
+ 0x00, 0x3E, 0xFF, 0x00, 0x00, 0x2E, 0x3E, 0x20, 0x03, 0x00, 0x00, 0x02,
+ 0x71, 0xD7, 0x73, 0x00, 0x00, 0x3B, 0x20, 0x1A, 0x00, 0x2A, 0x7A, 0x21,
+ 0x02, 0x00, 0x00, 0x04, 0x65, 0xEA, 0x6E, 0x00, 0x01, 0x00, 0xA3, 0x1D,
+ 0x00, 0x00, 0x32, 0xC5, 0x17, 0x00, 0x1E, 0x52, 0xCA, 0x02, 0x00, 0x3A,
+ 0x97, 0xE1, 0x02, 0x00, 0x00, 0x05, 0xA8, 0xDB, 0xB2, 0x00, 0x00, 0x3B,
+ 0x3C, 0x07, 0x00, 0x21, 0x3B, 0x2E, 0x02, 0x00, 0x16, 0x4B, 0x6C, 0x06,
+ 0x00, 0x65, 0x8A, 0xC8, 0x05, 0x00, 0x7C, 0x9B, 0x46, 0x06, 0x00, 0x00,
+ 0x03, 0x8C, 0xD9, 0x8F, 0x00, 0x00, 0x3B, 0x08, 0x17, 0x00, 0x2F, 0x4F,
+ 0xF4, 0x06, 0x00, 0x1D, 0x8F, 0xA4, 0x03, 0x00, 0x00, 0x01, 0x20, 0x74,
+ 0x29, 0x00, 0x00, 0x3E, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x35, 0xFF, 0x3B,
+ 0x00, 0x00, 0x3B, 0x50, 0x0A, 0x00, 0x00, 0x02, 0x35, 0xFF, 0x40, 0x00,
+ 0x01, 0x00, 0xFD, 0x1D, 0x00, 0x00, 0x3B, 0x4C, 0x0D, 0x00, 0x00, 0x01,
+ 0x4B, 0x84, 0x4F, 0x00, 0x00, 0x3B, 0x4A, 0x13, 0x00, 0x00, 0x01, 0x6A,
+ 0xBF, 0x72, 0x00, 0x00, 0x55, 0x11, 0x0B, 0x00, 0x00, 0x01, 0x20, 0xF6,
+ 0x2F, 0x00, 0x00, 0xB7, 0x70, 0x01, 0x00, 0x00, 0x01, 0x39, 0xAD, 0x3B,
+ 0x00, 0x00, 0x8F, 0xA3, 0x02, 0x00, 0x00, 0x01, 0x1E, 0xD5, 0x2C, 0x00,
+ 0x00, 0xB7, 0x79, 0x00, 0x00, 0x01, 0x02, 0x3C, 0xD7, 0x3B, 0x00, 0x01,
+ 0x00, 0x99, 0x1D, 0x00, 0x00, 0x3B, 0xBD, 0x02, 0x00, 0x00, 0x02, 0x62,
+ 0xD7, 0x6C, 0x00, 0x00, 0x3D, 0xA8, 0x06, 0x00, 0x1E, 0x55, 0xE9, 0x0B,
+ 0x00, 0x00, 0x01, 0x43, 0xD5, 0x65, 0x00, 0x00, 0x3D, 0x04, 0x06, 0x00,
+ 0x00, 0x01, 0x66, 0xD5, 0x70, 0x00, 0x00, 0x3D, 0xC6, 0x15, 0x00, 0x00,
+ 0x02, 0x65, 0xD7, 0x6D, 0x00, 0x01, 0x00, 0x85, 0x1D, 0x00, 0x00, 0x3D,
+ 0xAB, 0x19, 0x00, 0x00, 0x02, 0x6D, 0xD5, 0x71, 0x00, 0x00, 0x3D, 0x34,
+ 0x0A, 0x00, 0x1B, 0x69, 0xFD, 0x01, 0x00, 0x00, 0x02, 0x66, 0xD7, 0x6C,
+ 0x00, 0x01, 0x00, 0x8F, 0x1D, 0x00, 0x00, 0x40, 0x77, 0x15, 0x00, 0x00,
+ 0x02, 0x65, 0xD7, 0x6C, 0x00, 0x00, 0x3D, 0x46, 0x10, 0x00, 0x20, 0x87,
+ 0x50, 0x05, 0x00, 0x00, 0x02, 0x63, 0xD5, 0x6C, 0x00, 0x01, 0x00, 0xB7,
+ 0x1D, 0x00, 0x00, 0x40, 0xA4, 0x08, 0x00, 0x00, 0x03, 0x64, 0xD7, 0x6D,
+ 0x00, 0x00, 0x3D, 0x8C, 0x10, 0x00, 0x1F, 0x54, 0x2A, 0x04, 0x00, 0x1C,
+ 0x8F, 0x50, 0x04, 0x00, 0x00, 0x03, 0x65, 0xD7, 0x6F, 0x00, 0x01, 0x00,
+ 0xF3, 0x1D, 0x00, 0x00, 0x3D, 0x88, 0x11, 0x00, 0x1C, 0x55, 0xC2, 0x04,
+ 0x00, 0x00, 0x03, 0x1E, 0xD5, 0x32, 0x00, 0x01, 0x00, 0xDF, 0x1D, 0x00,
+ 0x00, 0x67, 0x79, 0x00, 0x00, 0x00, 0xB7, 0x79, 0x00, 0x00, 0x00, 0x02,
+ 0x20, 0xF6, 0x35, 0x00, 0x02, 0x67, 0x79, 0x00, 0x00, 0x00, 0xB7, 0x70,
+ 0x01, 0x00, 0x00, 0x02, 0x68, 0xC4, 0x71, 0x00, 0x01, 0x00, 0xD5, 0x1D,
+ 0x00, 0x00, 0x51, 0x01, 0x04, 0x00, 0x00, 0x02, 0x6A, 0xAF, 0x72, 0x00,
+ 0x00, 0x66, 0x6F, 0x02, 0x00, 0x00, 0x93, 0x62, 0x02, 0x00, 0x00, 0x01,
+ 0x68, 0xC4, 0x71, 0x00, 0x00, 0x51, 0x91, 0x03, 0x00, 0x00, 0x02, 0x6D,
+ 0xD5, 0x76, 0x00, 0x00, 0x3C, 0xFA, 0x12, 0x00, 0x28, 0xB7, 0x79, 0x00,
+ 0x00, 0x00, 0x02, 0xC6, 0xFF, 0xC7, 0x00, 0x00, 0x3B, 0xDB, 0x1C, 0x00,
+ 0x41, 0x77, 0x7E, 0x0A, 0x00, 0x00, 0x02, 0x98, 0xD5, 0x98, 0x00, 0x00,
+ 0x3E, 0xEE, 0x05, 0x00, 0x36, 0x61, 0xF3, 0x01, 0x00, 0x00, 0x03, 0x7F,
+ 0xD5, 0x89, 0x00, 0x00, 0x3E, 0x09, 0x10, 0x00, 0x1E, 0x57, 0xC6, 0x07,
+ 0x00, 0x1E, 0x92, 0x7A, 0x07, 0x00, 0x00, 0x01, 0x84, 0xD7, 0x8E, 0x00,
+ 0x00, 0x3B, 0xCE, 0x11, 0x00, 0x00, 0x02, 0x7F, 0xD5, 0x89, 0x00, 0x00,
+ 0x3E, 0x08, 0x0A, 0x00, 0x1E, 0x57, 0xB0, 0x0A, 0x00, 0x00, 0x01, 0x73,
+ 0xD5, 0x7D, 0x00, 0x00, 0x3E, 0xC2, 0x0C, 0x00, 0x00, 0x01, 0x68, 0xD5,
+ 0x71, 0x00, 0x00, 0x3E, 0xD0, 0x09, 0x00, 0x00, 0x01, 0x8D, 0xD7, 0x9A,
+ 0x00, 0x00, 0x3B, 0x67, 0x17, 0x00, 0x00, 0x01, 0x79, 0xD5, 0x89, 0x00,
+ 0x00, 0x3E, 0xA3, 0x0C, 0x00, 0x00, 0x02, 0x1F, 0xD5, 0x2D, 0x00, 0x01,
+ 0x00, 0xC1, 0x1D, 0x00, 0x00, 0x3E, 0x14, 0x02, 0x00, 0x00, 0x01, 0x61,
+ 0xD7, 0x72, 0x00, 0x00, 0x3E, 0xAE, 0x0D, 0x00, 0x00, 0x01, 0x88, 0xD5,
+ 0x88, 0x00, 0x00, 0x3E, 0xCA, 0x0B, 0x00, 0x00, 0x01, 0x6B, 0xD5, 0x71,
+ 0x00, 0x00, 0x3F, 0x31, 0x03, 0x00, 0x00, 0x01, 0x92, 0xD5, 0xA0, 0x00,
+ 0x00, 0x3E, 0x12, 0x0E, 0x00, 0x00, 0x01, 0x78, 0xD5, 0x88, 0x00, 0x00,
+ 0x3E, 0xC8, 0x08, 0x00, 0x00, 0x02, 0x93, 0xD7, 0x9B, 0x00, 0x00, 0x3B,
+ 0x68, 0x09, 0x00, 0x1F, 0x55, 0x2A, 0x05, 0x00, 0x00, 0x02, 0x74, 0xD5,
+ 0x7D, 0x00, 0x00, 0x3E, 0x30, 0x0B, 0x00, 0x1E, 0x57, 0x5C, 0x08, 0x00,
+ 0x00, 0x02, 0x98, 0xE4, 0x9B, 0x00, 0x00, 0x3B, 0x64, 0x0E, 0x00, 0x1F,
+ 0x55, 0xDC, 0x0A, 0x00, 0x00, 0x02, 0x88, 0xD5, 0x89, 0x00, 0x00, 0x3E,
+ 0x6E, 0x12, 0x00, 0x1E, 0x57, 0x80, 0x08, 0x00, 0x00, 0x01, 0x7B, 0xD7,
+ 0x85, 0x00, 0x00, 0x3B, 0x63, 0x1A, 0x00, 0x00, 0x01, 0x78, 0xD5, 0x7C,
+ 0x00, 0x00, 0x3E, 0x14, 0x04, 0x00, 0x00, 0x02, 0x79, 0xD7, 0x89, 0x00,
+ 0x01, 0x00, 0xCB, 0x1D, 0x00, 0x00, 0x3E, 0x2A, 0x15, 0x00, 0x01, 0x01,
+ 0x8D, 0xD5, 0x8C, 0x00, 0x00, 0x3E, 0xEE, 0x03, 0x00, 0x00, 0x01, 0xC6,
+ 0xD5, 0xC6, 0x00, 0x00, 0x3E, 0x9D, 0x0E, 0x00, 0x00, 0x01, 0x8C, 0xD5,
+ 0x8C, 0x00, 0x00, 0x3E, 0x0E, 0x0D, 0x00, 0x01, 0x01, 0x8D, 0xD5, 0x8D,
+ 0x00, 0x00, 0x3E, 0x44, 0x08, 0x00, 0x00, 0x01, 0x7B, 0xD5, 0x7E, 0x00,
+ 0x00, 0x3E, 0xE2, 0x08, 0x00, 0x00, 0x01, 0x34, 0xFF, 0x37, 0x00, 0x00,
+ 0x3E, 0x14, 0x05, 0x00, 0x01, 0x01, 0x3C, 0xD7, 0x3B, 0x00, 0x00, 0x3B,
+ 0x96, 0x02, 0x00, 0x00, 0x01, 0x34, 0xFF, 0x43, 0x00, 0x00, 0x3E, 0xB2,
+ 0x05, 0x00, 0x00, 0x01, 0x64, 0x8E, 0x6F, 0x00, 0x00, 0x3B, 0x53, 0x03,
+ 0x00, 0x02, 0x01, 0x79, 0xFE, 0x77, 0x00, 0x00, 0xEB, 0x55, 0x02, 0x00,
+ 0x00, 0x01, 0x2F, 0x5B, 0x42, 0x00, 0x00, 0x3B, 0x48, 0x02, 0x00, 0x00,
+ 0x02, 0x67, 0xD7, 0x6E, 0x00, 0x00, 0x65, 0x77, 0x18, 0x00, 0x1D, 0xA0,
+ 0x9E, 0x07, 0x00, 0x00, 0x02, 0x6B, 0xD7, 0x73, 0x00, 0x00, 0x3E, 0x76,
+ 0x0C, 0x00, 0x1D, 0x7B, 0x16, 0x07, 0x00, 0x00, 0x01, 0x68, 0xD7, 0x6C,
+ 0x00, 0x00, 0x65, 0xAE, 0x12, 0x00, 0x00, 0x02, 0x6B, 0xD7, 0x78, 0x00,
+ 0x00, 0x3E, 0xE1, 0x0C, 0x00, 0x1D, 0x7B, 0xCE, 0x06, 0x00, 0x00, 0x02,
+ 0x67, 0xD7, 0x6F, 0x00, 0x00, 0x65, 0x00, 0x0F, 0x00, 0x1E, 0x7B, 0xF8,
+ 0x02, 0x00, 0x00, 0x01, 0x4A, 0xD5, 0x44, 0x00, 0x00, 0x3B, 0x90, 0x13,
+ 0x00, 0x00, 0x02, 0x6B, 0xFF, 0x78, 0x00, 0x00, 0x65, 0xAD, 0x16, 0x00,
+ 0x1D, 0x7B, 0x20, 0x06, 0x00, 0x00, 0x01, 0x64, 0xD5, 0x72, 0x00, 0x00,
+ 0x3E, 0x54, 0x14, 0x00, 0x00, 0x02, 0x1E, 0xD5, 0x2C, 0x00, 0x00, 0x3E,
+ 0xF2, 0x00, 0x00, 0x00, 0x67, 0x89, 0x02, 0x00, 0x0A, 0x02, 0x36, 0xFF,
+ 0x44, 0x00, 0x18, 0x3E, 0xF2, 0x00, 0x00, 0x00, 0x67, 0x3B, 0x0F, 0x00,
+ 0x00, 0x01, 0x65, 0xD5, 0x67, 0x00, 0x00, 0x3E, 0xAB, 0x0B, 0x00, 0x00,
+ 0x01, 0x1E, 0xD5, 0x2C, 0x00, 0x00, 0x3E, 0x7C, 0x02, 0x00, 0x00, 0x01,
+ 0xA1, 0xD5, 0xAE, 0x00, 0x00, 0x65, 0xE2, 0x1A, 0x00, 0x00, 0x01, 0x64,
+ 0xD5, 0x72, 0x00, 0x00, 0x65, 0x10, 0x14, 0x00, 0x00, 0x02, 0x71, 0xD7,
+ 0x78, 0x00, 0x00, 0x65, 0x3A, 0x09, 0x00, 0x1D, 0x7C, 0x76, 0x05, 0x00,
+ 0x00, 0x02, 0x6B, 0xFE, 0x72, 0x00, 0x00, 0x65, 0x33, 0x0E, 0x00, 0x1C,
+ 0x7B, 0x9C, 0x04, 0x00, 0x00, 0x02, 0x6A, 0xFE, 0x77, 0x00, 0x00, 0x65,
+ 0xE1, 0x0D, 0x00, 0x1D, 0x7B, 0x76, 0x04, 0x00, 0x00, 0x01, 0x47, 0xD5,
+ 0x44, 0x00, 0x00, 0x65, 0x7F, 0x0D, 0x00, 0x00, 0x01, 0x67, 0xD7, 0x70,
+ 0x00, 0x00, 0x65, 0xDD, 0x18, 0x00, 0x00, 0x01, 0x41, 0xD7, 0x43, 0x00,
+ 0x00, 0x41, 0x68, 0x16, 0x00, 0x00, 0x01, 0x64, 0xD7, 0x72, 0x00, 0x00,
+ 0x67, 0xCC, 0x13, 0x00, 0x00, 0x01, 0x72, 0xD5, 0x74, 0x00, 0x00, 0x67,
+ 0xEA, 0x09, 0x00, 0x00, 0x01, 0xA3, 0xD5, 0xA3, 0x00, 0x00, 0x67, 0xBE,
+ 0x0E, 0x00, 0x00, 0x01, 0x72, 0xD5, 0x74, 0x00, 0x00, 0x67, 0x2D, 0x0D,
+ 0x00, 0x00, 0x01, 0x71, 0xFF, 0x74, 0x00, 0x00, 0x67, 0xD4, 0x10, 0x00,
+ 0x00, 0x01, 0x62, 0xD5, 0x66, 0x00, 0x00, 0x67, 0xE0, 0x0F, 0x00, 0x00,
+ 0x01, 0x47, 0xFF, 0x4C, 0x00, 0x00, 0x3B, 0x51, 0x1C, 0x00, 0x00, 0x01,
+ 0x18, 0xFF, 0x29, 0x00, 0x00, 0x3B, 0xB0, 0x02, 0x00, 0x00, 0x01, 0x47,
+ 0xFF, 0x4E, 0x00, 0x00, 0x3B, 0xCB, 0x1B, 0x00, 0x00, 0x01, 0x6E, 0xA0,
+ 0x74, 0x00, 0x00, 0x75, 0xA5, 0x0F, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x00,
+ 0x3B, 0x00, 0x00, 0x04, 0xDF, 0xF1, 0xF3, 0x00, 0x00, 0x12, 0x86, 0x00,
+ 0x00, 0x0B, 0x1E, 0xBC, 0x00, 0x00, 0x2F, 0x42, 0x92, 0x06, 0x00, 0x5C,
+ 0x60, 0xE9, 0x01, 0x00, 0x00, 0x05, 0xDF, 0xF1, 0xF3, 0x00, 0x00, 0x12,
+ 0x86, 0x00, 0x00, 0x0B, 0x1E, 0xBC, 0x00, 0x00, 0x3F, 0x42, 0x94, 0x01,
+ 0x00, 0x59, 0x57, 0x10, 0x01, 0x00, 0x59, 0x89, 0x40, 0x01, 0x00, 0x00,
+ 0x03, 0xDF, 0xF1, 0xF3, 0x00, 0x00, 0x12, 0x86, 0x00, 0x00, 0x0B, 0x1E,
+ 0xBC, 0x00, 0x00, 0x34, 0x42, 0x5D, 0x0B, 0x00, 0x00, 0x03, 0xDF, 0xF1,
+ 0xF3, 0x00, 0x00, 0x12, 0x86, 0x00, 0x00, 0x0B, 0x1E, 0xBC, 0x00, 0x00,
+ 0x34, 0x42, 0x62, 0x07, 0x00, 0x00, 0x01, 0xAD, 0xE3, 0xAF, 0x00, 0x00,
+ 0x5F, 0x0C, 0x11, 0x00, 0x00, 0x01, 0x83, 0xF8, 0x98, 0x00, 0x00, 0x46,
+ 0x48, 0x11, 0x00, 0x00, 0x02, 0x90, 0xCC, 0x95, 0x00, 0x01, 0x00, 0xAD,
+ 0x1D, 0x00, 0x00, 0x3C, 0x1B, 0x16, 0x00, 0x00, 0x01, 0x92, 0xCC, 0x98,
+ 0x00, 0x00, 0x3C, 0x4B, 0x19, 0x00, 0x00, 0x02, 0x9D, 0xCC, 0xA6, 0x00,
+ 0x00, 0x3C, 0x98, 0x14, 0x00, 0x21, 0x5D, 0x7C, 0x0B, 0x00, 0x00, 0x01,
+ 0x97, 0xCC, 0xA0, 0x00, 0x00, 0x3C, 0xE9, 0x14, 0x00, 0x00, 0x01, 0x8A,
+ 0xCC, 0x93, 0x00, 0x00, 0x3C, 0x1F, 0x18, 0x00, 0x00, 0x01, 0x7E, 0xCC,
+ 0x86, 0x00, 0x00, 0x3C, 0xE8, 0x04, 0x00, 0x00, 0x01, 0x90, 0xCC, 0x99,
+ 0x00, 0x00, 0x3C, 0x57, 0x0C, 0x00, 0x00, 0x01, 0x7C, 0xCC, 0x80, 0x00,
+ 0x00, 0x3C, 0x4F, 0x1B, 0x00, 0x00, 0x01, 0x2C, 0xD5, 0x2C, 0x00, 0x00,
+ 0x3E, 0x07, 0x02, 0x00, 0x00, 0x01, 0x01, 0xD5, 0x2C, 0x00, 0x00, 0xD4,
+ 0x3B, 0x02, 0x00, 0x00, 0x02, 0x45, 0x6F, 0x46, 0x00, 0x00, 0x29, 0x20,
+ 0x0C, 0x00, 0x12, 0x3B, 0xEA, 0x07, 0x00, 0x00, 0x04, 0xC4, 0xF1, 0xE6,
+ 0x00, 0x00, 0x12, 0xFC, 0x08, 0x00, 0x0B, 0x1E, 0xC3, 0x03, 0x00, 0x28,
+ 0x6D, 0x0F, 0x03, 0x00, 0x60, 0x6D, 0x9C, 0x05, 0x00, 0x00, 0x05, 0xC4,
+ 0xF1, 0xE6, 0x00, 0x00, 0x12, 0x96, 0x09, 0x00, 0x0B, 0x1E, 0x66, 0x03,
+ 0x00, 0x1B, 0x6D, 0x1A, 0x12, 0x00, 0x6A, 0x6D, 0xFE, 0x04, 0x00, 0x2C,
+ 0x7B, 0x14, 0x08, 0x00, 0x00, 0x02, 0x73, 0xCC, 0x7B, 0x00, 0x01, 0x00,
+ 0xE9, 0x1D, 0x00, 0x00, 0x3C, 0x72, 0x0F, 0x00, 0x00, 0x02, 0xDF, 0xF1,
+ 0xF3, 0x00, 0x00, 0x12, 0x86, 0x00, 0x00, 0x34, 0x41, 0xDF, 0x0E, 0x00,
+ 0x00, 0x04, 0xDF, 0xF1, 0xF3, 0x00, 0x00, 0x12, 0x86, 0x00, 0x00, 0x3F,
+ 0x42, 0x94, 0x01, 0x00, 0x59, 0x57, 0x10, 0x01, 0x00, 0x59, 0x89, 0x40,
+ 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF,
+ 0xFE, 0xFF, 0xC3, 0x49, 0x00, 0xF2, 0x8C, 0x00, 0x00, 0xFE, 0x90, 0x00,
+ 0x04, 0xF2, 0x00, 0xF2, 0x00, 0xF2, 0x82, 0x00, 0x00, 0xFE, 0x84, 0x00,
+ 0x00, 0xF2, 0x81, 0x00, 0x07, 0xF6, 0xF2, 0x00, 0xF2, 0x00, 0xF2, 0x00,
+ 0xF2, 0x00, 0xF2, 0x9E, 0x00, 0x00, 0xF6, 0x82, 0x00, 0x00, 0xF6, 0x82,
+ 0x00, 0x00, 0xFE, 0x84, 0x00, 0x00, 0xF2, 0x81, 0x00, 0x00, 0xF6, 0x81,
+ 0x00, 0x00, 0xFA, 0x82, 0x00, 0x00, 0xFA, 0x00, 0xF6, 0x9E, 0x00, 0x00,
+ 0xFA, 0x82, 0x00, 0x00, 0xFE, 0x88, 0x00, 0x00, 0xFE, 0x81, 0x00, 0x00,
+ 0xFE, 0x81, 0x00, 0x00, 0xFE, 0x82, 0x00, 0x00, 0xFE, 0x00, 0xEE, 0x9E,
+ 0x00, 0x00, 0xF6, 0x82, 0x00, 0x00, 0xF6, 0x82, 0x00, 0x00, 0xFA, 0x84,
+ 0x00, 0x02, 0xF2, 0xF6, 0xF2, 0x82, 0x00, 0x81, 0xF6, 0x05, 0xF2, 0x00,
+ 0xF2, 0xF6, 0x00, 0xEE, 0x9B, 0x00, 0x03, 0xFA, 0xFE, 0x00, 0xFA, 0xD8,
+ 0x00, 0x00, 0xF6, 0x05, 0xF2, 0x00, 0xF2, 0xF6, 0x00, 0xEE, 0x9E, 0x00,
+ 0x00, 0xFA, 0xD8, 0x00, 0x00, 0xF6, 0x81, 0xFE, 0x01, 0x00, 0xFA, 0x00,
+ 0xFD, 0x81, 0xF8, 0x00, 0x04, 0x00, 0x08, 0x00, 0xF7, 0x00, 0xF6, 0x32,
+ 0x4E, 0x46, 0x53
+};
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/cerbiosini_html.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/cerbiosini_html.h
new file mode 100644
index 0000000..f6fb9b3
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/cerbiosini_html.h
@@ -0,0 +1,47 @@
+#pragma once
+
+const uint8_t cerbiosini_html[] = {
+ 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x3c,
+ 0x68, 0x74, 0x6d, 0x6c, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x3d, 0x65, 0x6e, 0x20, 0x64, 0x61, 0x74,
+ 0x61, 0x2d, 0x74, 0x68, 0x65, 0x6d, 0x65, 0x3d, 0x64, 0x61, 0x72, 0x6b, 0x3e, 0x3c, 0x68, 0x65,
+ 0x61, 0x64, 0x3e, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74,
+ 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x20, 0x2f, 0x3e, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x6e,
+ 0x61, 0x6d, 0x65, 0x3d, 0x76, 0x69, 0x65, 0x77, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x63, 0x6f, 0x6e,
+ 0x74, 0x65, 0x6e, 0x74, 0x3d, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x64, 0x65, 0x76, 0x69,
+ 0x63, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61,
+ 0x6c, 0x2d, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x3d, 0x31, 0x2c, 0x20, 0x73, 0x68, 0x72, 0x69, 0x6e,
+ 0x6b, 0x2d, 0x74, 0x6f, 0x2d, 0x66, 0x69, 0x74, 0x3d, 0x6e, 0x6f, 0x22, 0x20, 0x2f, 0x3e, 0x3c,
+ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x50, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x4f, 0x53,
+ 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x3c, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x72, 0x65,
+ 0x6c, 0x3d, 0x69, 0x63, 0x6f, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x69, 0x6d, 0x61, 0x67,
+ 0x65, 0x2f, 0x78, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x66, 0x61,
+ 0x76, 0x69, 0x63, 0x6f, 0x6e, 0x2e, 0x69, 0x63, 0x6f, 0x20, 0x2f, 0x3e, 0x3c, 0x6c, 0x69, 0x6e,
+ 0x6b, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x70, 0x69, 0x63, 0x6f, 0x2e, 0x63, 0x73, 0x73, 0x20,
+ 0x72, 0x65, 0x6c, 0x3d, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x73, 0x68, 0x65, 0x65, 0x74, 0x20, 0x2f,
+ 0x3e, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x6d,
+ 0x61, 0x69, 0x6e, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
+ 0x6e, 0x65, 0x72, 0x3e, 0x3c, 0x66, 0x6f, 0x72, 0x6d, 0x3e, 0x3c, 0x68, 0x32, 0x3e, 0x50, 0x72,
+ 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x4f, 0x53, 0x3a, 0x20, 0x43, 0x65, 0x72, 0x62, 0x69, 0x6f,
+ 0x73, 0x20, 0x49, 0x4e, 0x49, 0x3c, 0x2f, 0x68, 0x32, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x3e, 0x3c,
+ 0x73, 0x70, 0x61, 0x6e, 0x20, 0x69, 0x64, 0x3d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3e,
+ 0x50, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x57, 0x61, 0x69, 0x74, 0x2e, 0x2e, 0x2e, 0x3c, 0x2f,
+ 0x73, 0x70, 0x61, 0x6e, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x72, 0x20, 0x2f,
+ 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x67, 0x72, 0x69, 0x64,
+ 0x3e, 0x3c, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3a,
+ 0x76, 0x6f, 0x69, 0x64, 0x28, 0x30, 0x29, 0x20, 0x6f, 0x6e, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x3d,
+ 0x73, 0x65, 0x74, 0x43, 0x65, 0x72, 0x62, 0x69, 0x6f, 0x73, 0x49, 0x6e, 0x69, 0x28, 0x29, 0x3e,
+ 0x53, 0x61, 0x76, 0x65, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x3c, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65,
+ 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x73, 0x65,
+ 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x69, 0x6e, 0x64,
+ 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x42, 0x61, 0x63, 0x6b, 0x3c, 0x2f, 0x61, 0x3e,
+ 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x72, 0x20, 0x2f, 0x3e, 0x3c, 0x64, 0x69, 0x76,
+ 0x3e, 0x3c, 0x62, 0x3e, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x32, 0x30,
+ 0x32, 0x34, 0x20, 0x2d, 0x20, 0x54, 0x65, 0x61, 0x6d, 0x20, 0x43, 0x65, 0x72, 0x62, 0x69, 0x6f,
+ 0x73, 0x20, 0x2b, 0x20, 0x54, 0x65, 0x61, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x75, 0x72, 0x67, 0x65,
+ 0x6e, 0x74, 0x3c, 0x2f, 0x62, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x2f, 0x66, 0x6f,
+ 0x72, 0x6d, 0x3e, 0x3c, 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x3e, 0x3c, 0x73, 0x63, 0x72, 0x69, 0x70,
+ 0x74, 0x20, 0x73, 0x72, 0x63, 0x3d, 0x63, 0x65, 0x72, 0x62, 0x69, 0x6f, 0x73, 0x69, 0x6e, 0x69,
+ 0x2e, 0x6a, 0x73, 0x3e, 0x3c, 0x2f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3e, 0x3c, 0x2f, 0x62,
+ 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/cerbiosini_js.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/cerbiosini_js.h
new file mode 100644
index 0000000..abd5f0f
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/cerbiosini_js.h
@@ -0,0 +1,102 @@
+#pragma once
+
+const uint8_t cerbiosini_js[] = {
+ 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x6f, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x3d, 0x20,
+ 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x67, 0x65, 0x74, 0x43, 0x65, 0x72, 0x62, 0x69, 0x6f, 0x73, 0x49, 0x6e, 0x69,
+ 0x28, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x61, 0x73, 0x79, 0x6e, 0x63,
+ 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x67, 0x65, 0x74, 0x43, 0x65, 0x72,
+ 0x62, 0x69, 0x6f, 0x73, 0x49, 0x6e, 0x69, 0x28, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x28, 0x22, 0x2f,
+ 0x61, 0x70, 0x69, 0x2f, 0x63, 0x65, 0x72, 0x62, 0x69, 0x6f, 0x73, 0x69, 0x6e, 0x69, 0x22, 0x29,
+ 0x2e, 0x74, 0x68, 0x65, 0x6e, 0x28, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x72, 0x65, 0x73, 0x70,
+ 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x72, 0x65, 0x61, 0x64, 0x65,
+ 0x72, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x62, 0x6f, 0x64,
+ 0x79, 0x2e, 0x67, 0x65, 0x74, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x28, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x64, 0x65,
+ 0x63, 0x6f, 0x64, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x54, 0x65, 0x78, 0x74,
+ 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x28, 0x22, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x22, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x3d, 0x20, 0x27, 0x27, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x28, 0x74, 0x72,
+ 0x75, 0x65, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73,
+ 0x74, 0x20, 0x7b, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x2c, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20,
+ 0x7d, 0x20, 0x3d, 0x20, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x72, 0x65, 0x61, 0x64, 0x65, 0x72,
+ 0x2e, 0x72, 0x65, 0x61, 0x64, 0x28, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x64, 0x6f, 0x6e, 0x65, 0x29, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x20, 0x3d,
+ 0x20, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x28,
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x7b, 0x20, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x3a,
+ 0x20, 0x74, 0x72, 0x75, 0x65, 0x20, 0x7d, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x2b, 0x3d, 0x20, 0x63,
+ 0x68, 0x75, 0x6e, 0x6b, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20,
+ 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x6f, 0x64, 0x79, 0x20, 0x3d, 0x20, 0x22, 0x22,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65,
+ 0x6e, 0x74, 0x42, 0x6f, 0x64, 0x79, 0x20, 0x2b, 0x3d, 0x20, 0x22, 0x3c, 0x70, 0x3e, 0x3c, 0x64,
+ 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x5c, 0x22, 0x67, 0x72, 0x69, 0x64, 0x5c,
+ 0x22, 0x3e, 0x3c, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x20, 0x72, 0x6f, 0x77, 0x73,
+ 0x3d, 0x5c, 0x22, 0x34, 0x30, 0x5c, 0x22, 0x20, 0x63, 0x6f, 0x6c, 0x73, 0x3d, 0x5c, 0x22, 0x38,
+ 0x30, 0x5c, 0x22, 0x20, 0x73, 0x70, 0x65, 0x6c, 0x6c, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x3d, 0x5c,
+ 0x22, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x5c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x5c, 0x22, 0x63, 0x65,
+ 0x72, 0x62, 0x69, 0x6f, 0x73, 0x69, 0x6e, 0x69, 0x5c, 0x22, 0x3e, 0x22, 0x20, 0x2b, 0x20, 0x62,
+ 0x6f, 0x64, 0x79, 0x20, 0x2b, 0x20, 0x22, 0x3c, 0x2f, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65,
+ 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x2f, 0x70, 0x3e, 0x22, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74,
+ 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67,
+ 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x63,
+ 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x69, 0x6e, 0x6e, 0x65, 0x72,
+ 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x6f,
+ 0x64, 0x79, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x2e, 0x63, 0x61,
+ 0x74, 0x63, 0x68, 0x28, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x63, 0x6f,
+ 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74,
+ 0x2e, 0x67, 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28,
+ 0x22, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x69, 0x6e, 0x6e,
+ 0x65, 0x72, 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x3d, 0x20, 0x22, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x22, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x61,
+ 0x73, 0x79, 0x6e, 0x63, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x65,
+ 0x74, 0x43, 0x65, 0x72, 0x62, 0x69, 0x6f, 0x73, 0x49, 0x6e, 0x69, 0x28, 0x29, 0x0d, 0x0a, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
+ 0x74, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x65, 0x74,
+ 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x63, 0x65, 0x72,
+ 0x62, 0x69, 0x6f, 0x73, 0x69, 0x6e, 0x69, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x3d, 0x20, 0x6e, 0x65, 0x77,
+ 0x20, 0x46, 0x6f, 0x72, 0x6d, 0x44, 0x61, 0x74, 0x61, 0x28, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x28, 0x27, 0x62,
+ 0x6f, 0x64, 0x79, 0x27, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x69, 0x6e,
+ 0x6e, 0x65, 0x72, 0x54, 0x65, 0x78, 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61,
+ 0x77, 0x61, 0x69, 0x74, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x28, 0x22, 0x2f, 0x61, 0x70, 0x69,
+ 0x2f, 0x63, 0x65, 0x72, 0x62, 0x69, 0x6f, 0x73, 0x69, 0x6e, 0x69, 0x22, 0x2c, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x3a,
+ 0x20, 0x27, 0x50, 0x4f, 0x53, 0x54, 0x27, 0x2c, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x3a, 0x20, 0x64, 0x61, 0x74, 0x61, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x7d, 0x29, 0x2e, 0x74, 0x68, 0x65, 0x6e, 0x28, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x69, 0x66, 0x20, 0x28, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x73, 0x74,
+ 0x61, 0x74, 0x75, 0x73, 0x20, 0x3d, 0x3d, 0x20, 0x32, 0x30, 0x30, 0x29, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x6e, 0x64,
+ 0x6f, 0x77, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x68, 0x72, 0x65, 0x66,
+ 0x20, 0x3d, 0x20, 0x22, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x20, 0x65, 0x6c, 0x73,
+ 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x28, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x7d, 0x29, 0x2e, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x28, 0x29, 0x20, 0x3d, 0x3e,
+ 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x75, 0x70, 0x6c, 0x6f,
+ 0x61, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x28, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64,
+ 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x28, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x61, 0x6c, 0x65, 0x72, 0x74, 0x28, 0x22, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x66,
+ 0x61, 0x69, 0x6c, 0x65, 0x64, 0x2e, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/download_html.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/download_html.h
new file mode 100644
index 0000000..00d1b5a
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/download_html.h
@@ -0,0 +1,43 @@
+#pragma once
+
+const uint8_t download_html[] = {
+ 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x3c,
+ 0x68, 0x74, 0x6d, 0x6c, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x3d, 0x65, 0x6e, 0x20, 0x64, 0x61, 0x74,
+ 0x61, 0x2d, 0x74, 0x68, 0x65, 0x6d, 0x65, 0x3d, 0x64, 0x61, 0x72, 0x6b, 0x3e, 0x3c, 0x68, 0x65,
+ 0x61, 0x64, 0x3e, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74,
+ 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x20, 0x2f, 0x3e, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x6e,
+ 0x61, 0x6d, 0x65, 0x3d, 0x76, 0x69, 0x65, 0x77, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x63, 0x6f, 0x6e,
+ 0x74, 0x65, 0x6e, 0x74, 0x3d, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x64, 0x65, 0x76, 0x69,
+ 0x63, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61,
+ 0x6c, 0x2d, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x3d, 0x31, 0x2c, 0x20, 0x73, 0x68, 0x72, 0x69, 0x6e,
+ 0x6b, 0x2d, 0x74, 0x6f, 0x2d, 0x66, 0x69, 0x74, 0x3d, 0x6e, 0x6f, 0x22, 0x20, 0x2f, 0x3e, 0x3c,
+ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x50, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x4f, 0x53,
+ 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x3c, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x72, 0x65,
+ 0x6c, 0x3d, 0x69, 0x63, 0x6f, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x69, 0x6d, 0x61, 0x67,
+ 0x65, 0x2f, 0x78, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x66, 0x61,
+ 0x76, 0x69, 0x63, 0x6f, 0x6e, 0x2e, 0x69, 0x63, 0x6f, 0x20, 0x2f, 0x3e, 0x3c, 0x6c, 0x69, 0x6e,
+ 0x6b, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x70, 0x69, 0x63, 0x6f, 0x2e, 0x63, 0x73, 0x73, 0x20,
+ 0x72, 0x65, 0x6c, 0x3d, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x73, 0x68, 0x65, 0x65, 0x74, 0x20, 0x2f,
+ 0x3e, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x6d,
+ 0x61, 0x69, 0x6e, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
+ 0x6e, 0x65, 0x72, 0x3e, 0x3c, 0x66, 0x6f, 0x72, 0x6d, 0x3e, 0x3c, 0x68, 0x32, 0x3e, 0x50, 0x72,
+ 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x4f, 0x53, 0x3a, 0x20, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f,
+ 0x61, 0x64, 0x20, 0x42, 0x49, 0x4f, 0x53, 0x3c, 0x2f, 0x68, 0x32, 0x3e, 0x3c, 0x64, 0x69, 0x76,
+ 0x3e, 0x3c, 0x73, 0x70, 0x61, 0x6e, 0x20, 0x69, 0x64, 0x3d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
+ 0x74, 0x3e, 0x50, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x57, 0x61, 0x69, 0x74, 0x2e, 0x2e, 0x2e,
+ 0x3c, 0x2f, 0x73, 0x70, 0x61, 0x6e, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x72,
+ 0x20, 0x2f, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x67, 0x72,
+ 0x69, 0x64, 0x3e, 0x3c, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f,
+ 0x6e, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72,
+ 0x79, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d,
+ 0x6c, 0x3e, 0x42, 0x61, 0x63, 0x6b, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e,
+ 0x3c, 0x62, 0x72, 0x20, 0x2f, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x3e, 0x43, 0x6f,
+ 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x32, 0x30, 0x32, 0x34, 0x20, 0x2d, 0x20, 0x54,
+ 0x65, 0x61, 0x6d, 0x20, 0x43, 0x65, 0x72, 0x62, 0x69, 0x6f, 0x73, 0x20, 0x2b, 0x20, 0x54, 0x65,
+ 0x61, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x75, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x3c, 0x2f, 0x62, 0x3e,
+ 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x3e, 0x3c, 0x2f, 0x6d,
+ 0x61, 0x69, 0x6e, 0x3e, 0x3c, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x73, 0x72, 0x63, 0x3d,
+ 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x6a, 0x73, 0x3e, 0x3c, 0x2f, 0x73, 0x63,
+ 0x72, 0x69, 0x70, 0x74, 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, 0x74,
+ 0x6d, 0x6c, 0x3e
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/download_js.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/download_js.h
new file mode 100644
index 0000000..7af6655
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/download_js.h
@@ -0,0 +1,86 @@
+#pragma once
+
+const uint8_t download_js[] = {
+ 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x6f, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x3d, 0x20,
+ 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x67, 0x65, 0x74, 0x42, 0x61, 0x6e, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x28, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x7d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x66,
+ 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x67, 0x65, 0x74, 0x42, 0x61, 0x6e, 0x6b, 0x49,
+ 0x6e, 0x66, 0x6f, 0x28, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x77, 0x61,
+ 0x69, 0x74, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x28, 0x22, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x62,
+ 0x61, 0x6e, 0x6b, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x6a, 0x73, 0x6f, 0x6e, 0x22, 0x29, 0x2e, 0x74,
+ 0x68, 0x65, 0x6e, 0x28, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6a, 0x73, 0x6f, 0x6e, 0x20, 0x3d, 0x20,
+ 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x6a,
+ 0x73, 0x6f, 0x6e, 0x28, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x6f, 0x64,
+ 0x79, 0x20, 0x3d, 0x20, 0x22, 0x22, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x6c, 0x65, 0x74, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x30, 0x3b,
+ 0x20, 0x69, 0x20, 0x3c, 0x20, 0x6a, 0x73, 0x6f, 0x6e, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68,
+ 0x3b, 0x20, 0x69, 0x2b, 0x2b, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x6a, 0x73, 0x6f, 0x6e, 0x5b, 0x69,
+ 0x5d, 0x2e, 0x73, 0x6c, 0x6f, 0x74, 0x73, 0x20, 0x3e, 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x6f, 0x64, 0x79, 0x20, 0x2b, 0x3d, 0x20, 0x22,
+ 0x3c, 0x70, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x5c, 0x22,
+ 0x67, 0x72, 0x69, 0x64, 0x5c, 0x22, 0x3e, 0x3c, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x5c,
+ 0x22, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5c, 0x22, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x5c,
+ 0x22, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3a, 0x76, 0x6f, 0x69, 0x64,
+ 0x28, 0x30, 0x29, 0x5c, 0x22, 0x20, 0x6f, 0x6e, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x3d, 0x5c, 0x22,
+ 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6e, 0x6b, 0x28, 0x22, 0x20, 0x2b,
+ 0x20, 0x6a, 0x73, 0x6f, 0x6e, 0x5b, 0x69, 0x5d, 0x2e, 0x69, 0x64, 0x20, 0x2b, 0x20, 0x22, 0x2c,
+ 0x20, 0x27, 0x22, 0x20, 0x2b, 0x20, 0x6a, 0x73, 0x6f, 0x6e, 0x5b, 0x69, 0x5d, 0x2e, 0x6e, 0x61,
+ 0x6d, 0x65, 0x20, 0x2b, 0x20, 0x22, 0x2e, 0x62, 0x69, 0x6e, 0x27, 0x29, 0x5c, 0x22, 0x3e, 0x22,
+ 0x20, 0x2b, 0x20, 0x6a, 0x73, 0x6f, 0x6e, 0x5b, 0x69, 0x5d, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x20,
+ 0x2b, 0x20, 0x22, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x2f, 0x70,
+ 0x3e, 0x22, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65,
+ 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x65,
+ 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x63, 0x6f,
+ 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x48,
+ 0x54, 0x4d, 0x4c, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x6f, 0x64,
+ 0x79, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x22, 0x20, 0x3f, 0x20, 0x22, 0x4e, 0x6f, 0x20, 0x69, 0x74,
+ 0x65, 0x6d, 0x73, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x22, 0x20, 0x3a, 0x20, 0x63, 0x6f,
+ 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x6f, 0x64, 0x79, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x7d, 0x29, 0x2e, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d,
+ 0x3e, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d,
+ 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79,
+ 0x49, 0x64, 0x28, 0x22, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e,
+ 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x3d, 0x20, 0x22, 0x46, 0x61, 0x69,
+ 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x22,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x64,
+ 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6e, 0x6b, 0x28, 0x69, 0x64, 0x2c, 0x20,
+ 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x77,
+ 0x61, 0x69, 0x74, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x28, 0x22, 0x2f, 0x61, 0x70, 0x69, 0x2f,
+ 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x62, 0x61, 0x6e, 0x6b, 0x3f, 0x22, 0x20, 0x2b,
+ 0x20, 0x69, 0x64, 0x29, 0x2e, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x65, 0x72, 0x72, 0x6f, 0x72,
+ 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63,
+ 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x48, 0x54, 0x4d, 0x4c,
+ 0x20, 0x3d, 0x20, 0x22, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f,
+ 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x22, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x2e,
+ 0x74, 0x68, 0x65, 0x6e, 0x28, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x3d, 0x3e,
+ 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x62, 0x6c, 0x6f, 0x62, 0x28, 0x29,
+ 0x29, 0x2e, 0x74, 0x68, 0x65, 0x6e, 0x28, 0x62, 0x6c, 0x6f, 0x62, 0x20, 0x3d, 0x3e, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x75, 0x72,
+ 0x6c, 0x20, 0x3d, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x55, 0x52, 0x4c, 0x2e, 0x63,
+ 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x55, 0x52, 0x4c, 0x28, 0x62,
+ 0x6c, 0x6f, 0x62, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76,
+ 0x61, 0x72, 0x20, 0x61, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e,
+ 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x27, 0x61,
+ 0x27, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x2e, 0x68,
+ 0x72, 0x65, 0x66, 0x20, 0x3d, 0x20, 0x75, 0x72, 0x6c, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x61, 0x2e, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x3d,
+ 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x62, 0x6f, 0x64, 0x79, 0x2e, 0x61, 0x70,
+ 0x70, 0x65, 0x6e, 0x64, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x28, 0x61, 0x29, 0x3b, 0x20, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x2e, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x28,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x2e, 0x72, 0x65,
+ 0x6d, 0x6f, 0x76, 0x65, 0x28, 0x29, 0x3b, 0x20, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x7d
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/downloads_html.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/downloads_html.h
new file mode 100644
index 0000000..b9d4a2d
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/downloads_html.h
@@ -0,0 +1,58 @@
+#pragma once
+
+const uint8_t downloads_html[] = {
+ 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x3c,
+ 0x68, 0x74, 0x6d, 0x6c, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x3d, 0x65, 0x6e, 0x20, 0x64, 0x61, 0x74,
+ 0x61, 0x2d, 0x74, 0x68, 0x65, 0x6d, 0x65, 0x3d, 0x64, 0x61, 0x72, 0x6b, 0x3e, 0x3c, 0x68, 0x65,
+ 0x61, 0x64, 0x3e, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74,
+ 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x20, 0x2f, 0x3e, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x6e,
+ 0x61, 0x6d, 0x65, 0x3d, 0x76, 0x69, 0x65, 0x77, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x63, 0x6f, 0x6e,
+ 0x74, 0x65, 0x6e, 0x74, 0x3d, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x64, 0x65, 0x76, 0x69,
+ 0x63, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61,
+ 0x6c, 0x2d, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x3d, 0x31, 0x2c, 0x20, 0x73, 0x68, 0x72, 0x69, 0x6e,
+ 0x6b, 0x2d, 0x74, 0x6f, 0x2d, 0x66, 0x69, 0x74, 0x3d, 0x6e, 0x6f, 0x22, 0x20, 0x2f, 0x3e, 0x3c,
+ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x50, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x4f, 0x53,
+ 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x3c, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x72, 0x65,
+ 0x6c, 0x3d, 0x69, 0x63, 0x6f, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x69, 0x6d, 0x61, 0x67,
+ 0x65, 0x2f, 0x78, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x66, 0x61,
+ 0x76, 0x69, 0x63, 0x6f, 0x6e, 0x2e, 0x69, 0x63, 0x6f, 0x20, 0x2f, 0x3e, 0x3c, 0x6c, 0x69, 0x6e,
+ 0x6b, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x70, 0x69, 0x63, 0x6f, 0x2e, 0x63, 0x73, 0x73, 0x20,
+ 0x72, 0x65, 0x6c, 0x3d, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x73, 0x68, 0x65, 0x65, 0x74, 0x20, 0x2f,
+ 0x3e, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x6d,
+ 0x61, 0x69, 0x6e, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
+ 0x6e, 0x65, 0x72, 0x3e, 0x3c, 0x66, 0x6f, 0x72, 0x6d, 0x3e, 0x3c, 0x68, 0x32, 0x3e, 0x50, 0x72,
+ 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x4f, 0x53, 0x3c, 0x2f, 0x68, 0x32, 0x3e, 0x3c, 0x64, 0x69,
+ 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x67, 0x72, 0x69, 0x64, 0x3e, 0x3c, 0x61, 0x20,
+ 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x68, 0x72, 0x65, 0x66,
+ 0x3d, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x44,
+ 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x42, 0x49, 0x4f, 0x53, 0x3c, 0x2f, 0x61, 0x3e,
+ 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x72, 0x20, 0x2f, 0x3e, 0x3c, 0x64, 0x69, 0x76,
+ 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x67, 0x72, 0x69, 0x64, 0x3e, 0x3c, 0x61, 0x20, 0x72,
+ 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d,
+ 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3a, 0x76, 0x6f, 0x69, 0x64, 0x28,
+ 0x30, 0x29, 0x20, 0x6f, 0x6e, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x3d, 0x64, 0x6f, 0x77, 0x6e, 0x6c,
+ 0x6f, 0x61, 0x64, 0x45, 0x65, 0x70, 0x72, 0x6f, 0x6d, 0x28, 0x29, 0x3e, 0x44, 0x6f, 0x77, 0x6e,
+ 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x45, 0x45, 0x50, 0x52, 0x4f, 0x4d, 0x3c, 0x2f, 0x61, 0x3e, 0x3c,
+ 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x72, 0x20, 0x2f, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20,
+ 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x67, 0x72, 0x69, 0x64, 0x3e, 0x3c, 0x61, 0x20, 0x72, 0x6f,
+ 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x6a,
+ 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3a, 0x76, 0x6f, 0x69, 0x64, 0x28, 0x30,
+ 0x29, 0x20, 0x6f, 0x6e, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x3d, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f,
+ 0x61, 0x64, 0x50, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x4f, 0x53, 0x28, 0x29, 0x3e, 0x44,
+ 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x50, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65,
+ 0x4f, 0x53, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x72, 0x20,
+ 0x2f, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x67, 0x72, 0x69,
+ 0x64, 0x3e, 0x3c, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e,
+ 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79,
+ 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c,
+ 0x3e, 0x42, 0x61, 0x63, 0x6b, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c,
+ 0x62, 0x72, 0x20, 0x2f, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x3e, 0x43, 0x6f, 0x70,
+ 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x32, 0x30, 0x32, 0x34, 0x20, 0x2d, 0x20, 0x54, 0x65,
+ 0x61, 0x6d, 0x20, 0x43, 0x65, 0x72, 0x62, 0x69, 0x6f, 0x73, 0x20, 0x2b, 0x20, 0x54, 0x65, 0x61,
+ 0x6d, 0x20, 0x52, 0x65, 0x73, 0x75, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x3c, 0x2f, 0x62, 0x3e, 0x3c,
+ 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x3e, 0x3c, 0x2f, 0x6d, 0x61,
+ 0x69, 0x6e, 0x3e, 0x3c, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x73, 0x72, 0x63, 0x3d, 0x64,
+ 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x2e, 0x6a, 0x73, 0x3e, 0x3c, 0x2f, 0x73, 0x63,
+ 0x72, 0x69, 0x70, 0x74, 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, 0x74,
+ 0x6d, 0x6c, 0x3e
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/downloads_js.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/downloads_js.h
new file mode 100644
index 0000000..bf651aa
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/downloads_js.h
@@ -0,0 +1,42 @@
+#pragma once
+
+const uint8_t downloads_js[] = {
+ 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x64,
+ 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x45, 0x65, 0x70, 0x72, 0x6f, 0x6d, 0x28, 0x29, 0x7b,
+ 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x28, 0x22, 0x2f, 0x61, 0x70,
+ 0x69, 0x2f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x65, 0x70, 0x72, 0x6f, 0x6d,
+ 0x22, 0x29, 0x2e, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x28, 0x29, 0x3d, 0x3e, 0x7b, 0x63, 0x6f,
+ 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x48, 0x54, 0x4d, 0x4c, 0x3d,
+ 0x22, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65,
+ 0x63, 0x74, 0x2e, 0x22, 0x7d, 0x29, 0x2e, 0x74, 0x68, 0x65, 0x6e, 0x28, 0x6e, 0x3d, 0x3e, 0x6e,
+ 0x2e, 0x62, 0x6c, 0x6f, 0x62, 0x28, 0x29, 0x29, 0x2e, 0x74, 0x68, 0x65, 0x6e, 0x28, 0x6e, 0x3d,
+ 0x3e, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x69, 0x3d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x55,
+ 0x52, 0x4c, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x55,
+ 0x52, 0x4c, 0x28, 0x6e, 0x29, 0x2c, 0x74, 0x3d, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74,
+ 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22,
+ 0x61, 0x22, 0x29, 0x3b, 0x74, 0x2e, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x69, 0x3b, 0x74, 0x2e, 0x64,
+ 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x3d, 0x22, 0x45, 0x45, 0x50, 0x52, 0x4f, 0x4d, 0x2e,
+ 0x62, 0x69, 0x6e, 0x22, 0x3b, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x62, 0x6f,
+ 0x64, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x28, 0x74,
+ 0x29, 0x3b, 0x74, 0x2e, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x28, 0x29, 0x3b, 0x74, 0x2e, 0x72, 0x65,
+ 0x6d, 0x6f, 0x76, 0x65, 0x28, 0x29, 0x7d, 0x29, 0x7d, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x66,
+ 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64,
+ 0x50, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x4f, 0x53, 0x28, 0x29, 0x7b, 0x61, 0x77, 0x61,
+ 0x69, 0x74, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x28, 0x22, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x64,
+ 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x70, 0x72, 0x6f, 0x6d, 0x22, 0x29, 0x2e, 0x63, 0x61,
+ 0x74, 0x63, 0x68, 0x28, 0x28, 0x29, 0x3d, 0x3e, 0x7b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
+ 0x2e, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x48, 0x54, 0x4d, 0x4c, 0x3d, 0x22, 0x46, 0x61, 0x69, 0x6c,
+ 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x22, 0x7d,
+ 0x29, 0x2e, 0x74, 0x68, 0x65, 0x6e, 0x28, 0x6e, 0x3d, 0x3e, 0x6e, 0x2e, 0x62, 0x6c, 0x6f, 0x62,
+ 0x28, 0x29, 0x29, 0x2e, 0x74, 0x68, 0x65, 0x6e, 0x28, 0x6e, 0x3d, 0x3e, 0x7b, 0x76, 0x61, 0x72,
+ 0x20, 0x69, 0x3d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x55, 0x52, 0x4c, 0x2e, 0x63, 0x72,
+ 0x65, 0x61, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x55, 0x52, 0x4c, 0x28, 0x6e, 0x29,
+ 0x2c, 0x74, 0x3d, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x72, 0x65, 0x61,
+ 0x74, 0x65, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x61, 0x22, 0x29, 0x3b, 0x74,
+ 0x2e, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x69, 0x3b, 0x74, 0x2e, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f,
+ 0x61, 0x64, 0x3d, 0x22, 0x50, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x4f, 0x53, 0x2e, 0x62,
+ 0x69, 0x6e, 0x22, 0x3b, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x62, 0x6f, 0x64,
+ 0x79, 0x2e, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x28, 0x74, 0x29,
+ 0x3b, 0x74, 0x2e, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x28, 0x29, 0x3b, 0x74, 0x2e, 0x72, 0x65, 0x6d,
+ 0x6f, 0x76, 0x65, 0x28, 0x29, 0x7d, 0x29, 0x7d
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/favicon_ico.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/favicon_ico.h
new file mode 100644
index 0000000..138b4cb
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/favicon_ico.h
@@ -0,0 +1,272 @@
+#pragma once
+
+const uint8_t favicon_ico[] = {
+ 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xa8, 0x10,
+ 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x67,
+ 0x5a, 0xff, 0x86, 0x7e, 0x72, 0xff, 0x91, 0x85, 0x73, 0xff, 0x95, 0x89, 0x75, 0xff, 0xb2, 0xaa,
+ 0x96, 0xff, 0xbd, 0xb5, 0x9e, 0xff, 0xb8, 0xac, 0x91, 0xff, 0xb5, 0xa7, 0x8a, 0xff, 0x8d, 0x7f,
+ 0x6c, 0xff, 0x68, 0x5b, 0x4d, 0xff, 0x6a, 0x5c, 0x42, 0xff, 0x5c, 0x4e, 0x2c, 0xff, 0x3c, 0x31,
+ 0x22, 0xff, 0x53, 0x48, 0x2c, 0xff, 0x58, 0x50, 0x38, 0xff, 0x6a, 0x5f, 0x47, 0xff, 0x79, 0x6c,
+ 0x47, 0xff, 0x4f, 0x41, 0x29, 0xff, 0x66, 0x57, 0x38, 0xff, 0x7d, 0x6e, 0x52, 0xff, 0x88, 0x77,
+ 0x63, 0xff, 0xa2, 0x95, 0x87, 0xff, 0xc6, 0xc2, 0xb9, 0xff, 0xdc, 0xe0, 0xd9, 0xff, 0xdc, 0xe1,
+ 0xda, 0xff, 0xdc, 0xe1, 0xdb, 0xff, 0xdc, 0xde, 0xd5, 0xff, 0xd4, 0xd0, 0xc0, 0xff, 0xca, 0xc8,
+ 0xc3, 0xff, 0xc8, 0xca, 0xcb, 0xff, 0xc2, 0xc2, 0xbf, 0xff, 0xb9, 0xba, 0xb8, 0xff, 0x5b, 0x55,
+ 0x50, 0xff, 0x92, 0x86, 0x70, 0xff, 0xaa, 0x9e, 0x88, 0xff, 0xb6, 0xb1, 0x9c, 0xff, 0xbc, 0xb6,
+ 0x9c, 0xff, 0xc2, 0xbb, 0xa3, 0xff, 0xbe, 0xb4, 0x9a, 0xff, 0xc6, 0xbf, 0xa6, 0xff, 0xb1, 0xa6,
+ 0x8f, 0xff, 0x8a, 0x7b, 0x64, 0xff, 0x7c, 0x6d, 0x50, 0xff, 0x70, 0x62, 0x45, 0xff, 0x49, 0x3d,
+ 0x2a, 0xff, 0x57, 0x4d, 0x3c, 0xff, 0x5a, 0x50, 0x37, 0xff, 0x41, 0x38, 0x2b, 0xff, 0x65, 0x57,
+ 0x3f, 0xff, 0x6d, 0x5f, 0x45, 0xff, 0x77, 0x69, 0x4d, 0xff, 0x82, 0x72, 0x5e, 0xff, 0xbb, 0xb2,
+ 0x9b, 0xff, 0xbe, 0xb7, 0xae, 0xff, 0xd7, 0xda, 0xd4, 0xff, 0xdc, 0xe3, 0xde, 0xff, 0xdc, 0xe2,
+ 0xdd, 0xff, 0xdc, 0xde, 0xd6, 0xff, 0xda, 0xda, 0xcf, 0xff, 0xd8, 0xd7, 0xcf, 0xff, 0xd4, 0xd4,
+ 0xd0, 0xff, 0xcf, 0xd2, 0xd5, 0xff, 0xaf, 0xb8, 0xc0, 0xff, 0x83, 0x8c, 0x98, 0xff, 0x4a, 0x48,
+ 0x4b, 0xff, 0x5a, 0x56, 0x59, 0xff, 0x9f, 0x97, 0x85, 0xff, 0xbf, 0xb7, 0x9e, 0xff, 0xc1, 0xba,
+ 0xa0, 0xff, 0xc3, 0xbc, 0xa2, 0xff, 0xca, 0xc5, 0xb0, 0xff, 0xd2, 0xd0, 0xbd, 0xff, 0xcb, 0xc7,
+ 0xb6, 0xff, 0xa4, 0x96, 0x7c, 0xff, 0x74, 0x65, 0x50, 0xff, 0x66, 0x57, 0x3d, 0xff, 0x6a, 0x5e,
+ 0x42, 0xff, 0x7c, 0x70, 0x4f, 0xff, 0x53, 0x48, 0x2a, 0xff, 0x43, 0x38, 0x2c, 0xff, 0x79, 0x6c,
+ 0x44, 0xff, 0x75, 0x68, 0x4b, 0xff, 0x75, 0x65, 0x49, 0xff, 0x9b, 0x8c, 0x6c, 0xff, 0xa0, 0x93,
+ 0x81, 0xff, 0xd4, 0xd3, 0xca, 0xff, 0xdc, 0xe1, 0xdb, 0xff, 0xdc, 0xe2, 0xde, 0xff, 0xdc, 0xe1,
+ 0xdd, 0xff, 0xdc, 0xdf, 0xda, 0xff, 0xdb, 0xdd, 0xd8, 0xff, 0xda, 0xdd, 0xdb, 0xff, 0xd5, 0xd6,
+ 0xd2, 0xff, 0xb6, 0xb5, 0xb3, 0xff, 0x89, 0x86, 0x87, 0xff, 0x69, 0x5d, 0x58, 0xff, 0x61, 0x5d,
+ 0x5e, 0xff, 0x68, 0x70, 0x7e, 0xff, 0x65, 0x6e, 0x7f, 0xff, 0xa4, 0xa3, 0x98, 0xff, 0xbf, 0xb7,
+ 0x98, 0xff, 0xc6, 0xbe, 0xa5, 0xff, 0xca, 0xc5, 0xaf, 0xff, 0xd5, 0xd5, 0xc6, 0xff, 0xd9, 0xdb,
+ 0xd0, 0xff, 0xab, 0x9d, 0x86, 0xff, 0x78, 0x68, 0x58, 0xff, 0x75, 0x66, 0x52, 0xff, 0x86, 0x79,
+ 0x53, 0xff, 0x45, 0x3a, 0x2a, 0xff, 0x3a, 0x30, 0x23, 0xff, 0x45, 0x3b, 0x2d, 0xff, 0x5f, 0x53,
+ 0x3a, 0xff, 0x74, 0x66, 0x4b, 0xff, 0xb5, 0xab, 0x92, 0xff, 0x8e, 0x7e, 0x6c, 0xff, 0xae, 0xa1,
+ 0x91, 0xff, 0xcf, 0xcd, 0xc6, 0xff, 0xdc, 0xe1, 0xdb, 0xff, 0xdc, 0xe1, 0xda, 0xff, 0xdc, 0xe0,
+ 0xda, 0xff, 0xdc, 0xe0, 0xdb, 0xff, 0xdc, 0xde, 0xd7, 0xff, 0xd7, 0xd5, 0xcc, 0xff, 0xaf, 0xa0,
+ 0x90, 0xff, 0x9a, 0x94, 0x91, 0xff, 0x7a, 0x6a, 0x60, 0xff, 0x6c, 0x5e, 0x55, 0xff, 0x80, 0x7f,
+ 0x7f, 0xff, 0x78, 0x81, 0x8e, 0xff, 0x77, 0x81, 0x90, 0xff, 0x72, 0x76, 0x7f, 0xff, 0xc1, 0xbc,
+ 0xac, 0xff, 0xc7, 0xc1, 0xaa, 0xff, 0xca, 0xc3, 0xac, 0xff, 0xd2, 0xd0, 0xbf, 0xff, 0xd4, 0xd3,
+ 0xc2, 0xff, 0xbc, 0xb4, 0xa2, 0xff, 0x87, 0x78, 0x69, 0xff, 0x7c, 0x72, 0x63, 0xff, 0x5c, 0x56,
+ 0x4b, 0xff, 0x4f, 0x47, 0x3a, 0xff, 0x49, 0x3f, 0x31, 0xff, 0x47, 0x3e, 0x31, 0xff, 0x61, 0x57,
+ 0x4b, 0xff, 0x6b, 0x62, 0x56, 0xff, 0x82, 0x77, 0x69, 0xff, 0xa0, 0x96, 0x89, 0xff, 0xba, 0xb0,
+ 0xa2, 0xff, 0xd2, 0xd0, 0xc6, 0xff, 0xdc, 0xe3, 0xdd, 0xff, 0xdc, 0xe2, 0xdd, 0xff, 0xdc, 0xe3,
+ 0xdd, 0xff, 0xdc, 0xe3, 0xdf, 0xff, 0xdc, 0xe1, 0xdc, 0xff, 0xb8, 0xa9, 0x99, 0xff, 0x9a, 0x88,
+ 0x79, 0xff, 0x96, 0x89, 0x7f, 0xff, 0x7c, 0x6d, 0x61, 0xff, 0x8a, 0x82, 0x79, 0xff, 0x9e, 0x9b,
+ 0x94, 0xff, 0x6d, 0x6a, 0x68, 0xff, 0x7b, 0x83, 0x8f, 0xff, 0x71, 0x7d, 0x8e, 0xff, 0xb2, 0xac,
+ 0x9d, 0xff, 0xc9, 0xc4, 0xae, 0xff, 0xcd, 0xc8, 0xb4, 0xff, 0xd2, 0xd0, 0xbf, 0xff, 0xd4, 0xd3,
+ 0xc2, 0xff, 0xbb, 0xb4, 0xa1, 0xff, 0x80, 0x73, 0x65, 0xff, 0x5f, 0x57, 0x4d, 0xff, 0x6c, 0x69,
+ 0x64, 0xff, 0x4c, 0x43, 0x36, 0xff, 0x5e, 0x55, 0x48, 0xff, 0x53, 0x4b, 0x3f, 0xff, 0x7f, 0x7d,
+ 0x78, 0xff, 0x6d, 0x6b, 0x68, 0xff, 0x8b, 0x8a, 0x87, 0xff, 0x9a, 0x92, 0x89, 0xff, 0xb3, 0xa8,
+ 0x9b, 0xff, 0xd3, 0xd4, 0xcb, 0xff, 0xdc, 0xe3, 0xdd, 0xff, 0xdc, 0xe2, 0xdc, 0xff, 0xdc, 0xe3,
+ 0xdd, 0xff, 0xdc, 0xe4, 0xe0, 0xff, 0xd3, 0xd4, 0xcb, 0xff, 0xa4, 0x94, 0x85, 0xff, 0xa3, 0x9a,
+ 0x91, 0xff, 0x88, 0x7a, 0x6b, 0xff, 0x84, 0x79, 0x6d, 0xff, 0xba, 0xb8, 0xb2, 0xff, 0x94, 0x8e,
+ 0x85, 0xff, 0x73, 0x6e, 0x6a, 0xff, 0x63, 0x69, 0x76, 0xff, 0x72, 0x87, 0xa1, 0xff, 0x9d, 0xa8,
+ 0xb2, 0xff, 0xca, 0xc7, 0xb7, 0xff, 0xd2, 0xd0, 0xbf, 0xff, 0xd6, 0xd5, 0xc8, 0xff, 0xda, 0xdc,
+ 0xd1, 0xff, 0xbe, 0xbc, 0xb4, 0xff, 0x5c, 0x50, 0x43, 0xff, 0x5a, 0x57, 0x53, 0xff, 0x56, 0x51,
+ 0x49, 0xff, 0x52, 0x48, 0x3a, 0xff, 0x79, 0x72, 0x67, 0xff, 0x74, 0x73, 0x71, 0xff, 0x83, 0x7d,
+ 0x73, 0xff, 0x78, 0x71, 0x65, 0xff, 0x8e, 0x8e, 0x8c, 0xff, 0x8e, 0x89, 0x82, 0xff, 0x9e, 0x92,
+ 0x85, 0xff, 0xcc, 0xcd, 0xc9, 0xff, 0xdc, 0xe4, 0xde, 0xff, 0xdc, 0xe3, 0xde, 0xff, 0xdc, 0xe3,
+ 0xde, 0xff, 0xdc, 0xe3, 0xde, 0xff, 0xc3, 0xbb, 0xb0, 0xff, 0x91, 0x80, 0x6f, 0xff, 0x87, 0x77,
+ 0x67, 0xff, 0x6f, 0x5f, 0x4f, 0xff, 0xaa, 0xa4, 0x9b, 0xff, 0xa9, 0xa4, 0x98, 0xff, 0x6b, 0x62,
+ 0x55, 0xff, 0x80, 0x7d, 0x76, 0xff, 0x5e, 0x69, 0x7c, 0xff, 0x57, 0x5e, 0x6e, 0xff, 0x63, 0x6a,
+ 0x76, 0xff, 0x9c, 0x96, 0x8d, 0xff, 0xd4, 0xd3, 0xc6, 0xff, 0xda, 0xdc, 0xd3, 0xff, 0xdc, 0xdf,
+ 0xd8, 0xff, 0x8b, 0x87, 0x7f, 0xff, 0x4d, 0x48, 0x42, 0xff, 0x4a, 0x42, 0x3a, 0xff, 0x4b, 0x48,
+ 0x43, 0xff, 0x51, 0x49, 0x3e, 0xff, 0x77, 0x70, 0x65, 0xff, 0x7e, 0x78, 0x6f, 0xff, 0x86, 0x80,
+ 0x76, 0xff, 0x6b, 0x62, 0x56, 0xff, 0x70, 0x6f, 0x6e, 0xff, 0x7b, 0x71, 0x67, 0xff, 0x92, 0x8e,
+ 0x88, 0xff, 0xbe, 0xbb, 0xb5, 0xff, 0xdc, 0xe3, 0xe1, 0xff, 0xdc, 0xe4, 0xe1, 0xff, 0xdc, 0xe3,
+ 0xdf, 0xff, 0xda, 0xdf, 0xdb, 0xff, 0xa5, 0x9a, 0x8f, 0xff, 0x7d, 0x6f, 0x63, 0xff, 0x6e, 0x5e,
+ 0x4e, 0xff, 0x8f, 0x84, 0x77, 0xff, 0xad, 0xa7, 0x9a, 0xff, 0x9c, 0x8d, 0x71, 0xff, 0x7e, 0x6f,
+ 0x54, 0xff, 0x83, 0x77, 0x60, 0xff, 0x5a, 0x55, 0x52, 0xff, 0x57, 0x5f, 0x6c, 0xff, 0x5a, 0x68,
+ 0x7c, 0xff, 0x55, 0x59, 0x66, 0xff, 0x99, 0x97, 0x92, 0xff, 0xda, 0xde, 0xd8, 0xff, 0xdc, 0xe2,
+ 0xdd, 0xff, 0x69, 0x65, 0x60, 0xff, 0x48, 0x43, 0x3e, 0xff, 0x41, 0x39, 0x2f, 0xff, 0x47, 0x48,
+ 0x47, 0xff, 0x54, 0x51, 0x4e, 0xff, 0x80, 0x7c, 0x77, 0xff, 0x89, 0x86, 0x81, 0xff, 0x9c, 0x9e,
+ 0x9c, 0xff, 0x7e, 0x7c, 0x78, 0xff, 0x57, 0x4e, 0x43, 0xff, 0x67, 0x5f, 0x56, 0xff, 0x88, 0x80,
+ 0x78, 0xff, 0xa8, 0x9f, 0x95, 0xff, 0xd8, 0xde, 0xdd, 0xff, 0xdc, 0xe4, 0xe2, 0xff, 0xd4, 0xd6,
+ 0xcd, 0xff, 0xb2, 0xa7, 0x97, 0xff, 0x80, 0x6f, 0x5e, 0xff, 0x66, 0x56, 0x46, 0xff, 0x60, 0x51,
+ 0x40, 0xff, 0xac, 0xa3, 0x93, 0xff, 0xa7, 0x97, 0x78, 0xff, 0x95, 0x85, 0x68, 0xff, 0x8c, 0x7b,
+ 0x5d, 0xff, 0x94, 0x85, 0x68, 0xff, 0x60, 0x53, 0x40, 0xff, 0x54, 0x48, 0x3b, 0xff, 0x53, 0x4e,
+ 0x4d, 0xff, 0x4a, 0x4b, 0x51, 0xff, 0x58, 0x5f, 0x6c, 0xff, 0xc1, 0xc3, 0xbc, 0xff, 0xb2, 0xb5,
+ 0xb3, 0xff, 0x50, 0x4e, 0x4e, 0xff, 0x3d, 0x34, 0x2b, 0xff, 0x3a, 0x32, 0x28, 0xff, 0x38, 0x30,
+ 0x26, 0xff, 0x39, 0x34, 0x2b, 0xff, 0x5c, 0x65, 0x6e, 0xff, 0x59, 0x55, 0x4f, 0xff, 0x52, 0x52,
+ 0x52, 0xff, 0x45, 0x3c, 0x32, 0xff, 0x4a, 0x43, 0x3b, 0xff, 0x5f, 0x53, 0x45, 0xff, 0x65, 0x59,
+ 0x4b, 0xff, 0x8b, 0x7d, 0x6f, 0xff, 0xb9, 0xb5, 0xad, 0xff, 0xd5, 0xd8, 0xcf, 0xff, 0xa2, 0x94,
+ 0x84, 0xff, 0x7d, 0x6c, 0x5c, 0xff, 0x75, 0x64, 0x53, 0xff, 0x6a, 0x5b, 0x4b, 0xff, 0x75, 0x66,
+ 0x55, 0xff, 0xb7, 0xac, 0x8e, 0xff, 0xb1, 0xa3, 0x83, 0xff, 0xa3, 0x94, 0x75, 0xff, 0x85, 0x74,
+ 0x56, 0xff, 0x8e, 0x7d, 0x5e, 0xff, 0x8b, 0x85, 0x76, 0xff, 0x87, 0x85, 0x80, 0xff, 0x63, 0x5b,
+ 0x51, 0xff, 0x44, 0x3d, 0x37, 0xff, 0x40, 0x3a, 0x37, 0xff, 0x74, 0x71, 0x6b, 0xff, 0x70, 0x70,
+ 0x6f, 0xff, 0x38, 0x36, 0x35, 0xff, 0x3e, 0x3d, 0x3b, 0xff, 0x3d, 0x37, 0x2f, 0xff, 0x3f, 0x35,
+ 0x29, 0xff, 0x4a, 0x43, 0x39, 0xff, 0x50, 0x55, 0x5b, 0xff, 0x66, 0x68, 0x6b, 0xff, 0x50, 0x4f,
+ 0x4d, 0xff, 0x50, 0x47, 0x3b, 0xff, 0x4b, 0x41, 0x36, 0xff, 0x62, 0x5d, 0x54, 0xff, 0x7c, 0x73,
+ 0x68, 0xff, 0x81, 0x7a, 0x71, 0xff, 0x8c, 0x81, 0x75, 0xff, 0xa6, 0x9d, 0x8f, 0xff, 0x74, 0x67,
+ 0x5b, 0xff, 0x6a, 0x5a, 0x49, 0xff, 0x77, 0x69, 0x57, 0xff, 0xb8, 0xb6, 0xae, 0xff, 0xb6, 0xb1,
+ 0xa3, 0xff, 0xc3, 0xba, 0x9c, 0xff, 0xbb, 0xb0, 0x91, 0xff, 0xb6, 0xa9, 0x8a, 0xff, 0x8d, 0x7c,
+ 0x5d, 0xff, 0x8a, 0x79, 0x5a, 0xff, 0x93, 0x84, 0x64, 0xff, 0x5e, 0x54, 0x42, 0xff, 0x53, 0x49,
+ 0x3a, 0xff, 0x52, 0x4b, 0x41, 0xff, 0x39, 0x34, 0x30, 0xff, 0x2e, 0x2a, 0x24, 0xff, 0x26, 0x24,
+ 0x20, 0xff, 0x35, 0x34, 0x35, 0xff, 0x2f, 0x2c, 0x27, 0xff, 0x37, 0x38, 0x38, 0xff, 0x58, 0x55,
+ 0x4e, 0xff, 0x69, 0x64, 0x5c, 0xff, 0x74, 0x77, 0x79, 0xff, 0x66, 0x68, 0x6a, 0xff, 0x71, 0x71,
+ 0x71, 0xff, 0x8d, 0x89, 0x81, 0xff, 0x81, 0x7a, 0x71, 0xff, 0x67, 0x62, 0x5b, 0xff, 0x5e, 0x54,
+ 0x48, 0xff, 0x6d, 0x61, 0x53, 0xff, 0x6b, 0x62, 0x57, 0xff, 0x5a, 0x4f, 0x43, 0xff, 0x5d, 0x52,
+ 0x47, 0xff, 0x6e, 0x60, 0x4f, 0xff, 0x93, 0x88, 0x7a, 0xff, 0xa0, 0x97, 0x8a, 0xff, 0xc8, 0xc2,
+ 0xac, 0xff, 0xc2, 0xb8, 0x9a, 0xff, 0xbd, 0xb2, 0x92, 0xff, 0xbc, 0xb1, 0x92, 0xff, 0xa2, 0x93,
+ 0x72, 0xff, 0x8e, 0x7d, 0x5d, 0xff, 0x8f, 0x7e, 0x5e, 0xff, 0x7b, 0x6d, 0x53, 0xff, 0x5a, 0x50,
+ 0x41, 0xff, 0x58, 0x50, 0x43, 0xff, 0x45, 0x40, 0x39, 0xff, 0x2d, 0x2f, 0x2f, 0xff, 0x20, 0x1b,
+ 0x16, 0xff, 0x30, 0x2d, 0x28, 0xff, 0x2b, 0x27, 0x1f, 0xff, 0x2a, 0x28, 0x23, 0xff, 0x35, 0x3a,
+ 0x3e, 0xff, 0x4e, 0x4b, 0x46, 0xff, 0x82, 0x84, 0x84, 0xff, 0x65, 0x60, 0x5a, 0xff, 0x78, 0x76,
+ 0x72, 0xff, 0x7a, 0x79, 0x78, 0xff, 0x5a, 0x58, 0x55, 0xff, 0x3a, 0x34, 0x2d, 0xff, 0x3f, 0x3a,
+ 0x33, 0xff, 0x56, 0x4f, 0x48, 0xff, 0x4e, 0x43, 0x36, 0xff, 0x45, 0x3a, 0x2f, 0xff, 0x63, 0x58,
+ 0x4a, 0xff, 0x9a, 0x91, 0x84, 0xff, 0xa4, 0x9c, 0x91, 0xff, 0xb1, 0xa8, 0x95, 0xff, 0xc7, 0xbe,
+ 0xa2, 0xff, 0xc3, 0xb9, 0x9b, 0xff, 0xbd, 0xb3, 0x94, 0xff, 0xbd, 0xb3, 0x93, 0xff, 0xa9, 0x9b,
+ 0x79, 0xff, 0x97, 0x87, 0x66, 0xff, 0x91, 0x80, 0x60, 0xff, 0x8a, 0x7b, 0x5d, 0xff, 0x42, 0x39,
+ 0x2d, 0xff, 0x49, 0x41, 0x34, 0xff, 0x3b, 0x37, 0x31, 0xff, 0x25, 0x23, 0x21, 0xff, 0x23, 0x1e,
+ 0x18, 0xff, 0x2c, 0x26, 0x1d, 0xff, 0x32, 0x2b, 0x23, 0xff, 0x2e, 0x2a, 0x24, 0xff, 0x2a, 0x27,
+ 0x22, 0xff, 0x2a, 0x27, 0x23, 0xff, 0x32, 0x30, 0x2d, 0xff, 0x48, 0x42, 0x39, 0xff, 0x3b, 0x39,
+ 0x37, 0xff, 0x3f, 0x3c, 0x39, 0xff, 0x3a, 0x32, 0x2b, 0xff, 0x3a, 0x32, 0x2a, 0xff, 0x3d, 0x33,
+ 0x2a, 0xff, 0x46, 0x3a, 0x2c, 0xff, 0x4b, 0x3f, 0x2f, 0xff, 0x40, 0x37, 0x2d, 0xff, 0x73, 0x6c,
+ 0x62, 0xff, 0x99, 0x92, 0x87, 0xff, 0x97, 0x8f, 0x84, 0xff, 0xbd, 0xb8, 0xa6, 0xff, 0xcd, 0xc7,
+ 0xb0, 0xff, 0xc5, 0xbc, 0xa0, 0xff, 0xc4, 0xbb, 0x9f, 0xff, 0xc1, 0xb8, 0x9b, 0xff, 0xba, 0xaf,
+ 0x8f, 0xff, 0xaa, 0x9d, 0x7b, 0xff, 0x97, 0x87, 0x66, 0xff, 0x92, 0x83, 0x62, 0xff, 0x39, 0x30,
+ 0x23, 0xff, 0x38, 0x30, 0x26, 0xff, 0x2f, 0x29, 0x21, 0xff, 0x25, 0x22, 0x1c, 0xff, 0x27, 0x22,
+ 0x1a, 0xff, 0x32, 0x2a, 0x20, 0xff, 0x40, 0x37, 0x2c, 0xff, 0x45, 0x3c, 0x32, 0xff, 0x49, 0x44,
+ 0x3b, 0xff, 0x45, 0x40, 0x3a, 0xff, 0x4d, 0x45, 0x3a, 0xff, 0x4f, 0x48, 0x3e, 0xff, 0x47, 0x3e,
+ 0x33, 0xff, 0x4d, 0x45, 0x3b, 0xff, 0x51, 0x48, 0x3c, 0xff, 0x4f, 0x45, 0x38, 0xff, 0x52, 0x47,
+ 0x39, 0xff, 0x59, 0x4c, 0x3c, 0xff, 0x58, 0x4a, 0x38, 0xff, 0x44, 0x37, 0x2a, 0xff, 0x4e, 0x42,
+ 0x34, 0xff, 0x80, 0x76, 0x68, 0xff, 0x7a, 0x6e, 0x5d, 0xff, 0xbd, 0xb9, 0xaa, 0xff, 0xd4, 0xd3,
+ 0xc1, 0xff, 0xcd, 0xc7, 0xb0, 0xff, 0xca, 0xc2, 0xa7, 0xff, 0xc6, 0xbd, 0xa2, 0xff, 0xc1, 0xb9,
+ 0x9c, 0xff, 0xb9, 0xae, 0x8d, 0xff, 0xab, 0x9e, 0x7c, 0xff, 0xb2, 0xa5, 0x83, 0xff, 0x69, 0x5f,
+ 0x49, 0xff, 0x40, 0x36, 0x28, 0xff, 0x37, 0x2f, 0x23, 0xff, 0x2f, 0x29, 0x21, 0xff, 0x38, 0x2f,
+ 0x22, 0xff, 0x4f, 0x46, 0x39, 0xff, 0x65, 0x5e, 0x54, 0xff, 0x7a, 0x7a, 0x76, 0xff, 0x82, 0x80,
+ 0x7a, 0xff, 0x95, 0x93, 0x8d, 0xff, 0xad, 0xac, 0xa8, 0xff, 0x8e, 0x88, 0x7e, 0xff, 0x8b, 0x84,
+ 0x7a, 0xff, 0x7a, 0x74, 0x6d, 0xff, 0x89, 0x81, 0x76, 0xff, 0x9e, 0x98, 0x8c, 0xff, 0x96, 0x8e,
+ 0x81, 0xff, 0x87, 0x7b, 0x69, 0xff, 0x72, 0x63, 0x50, 0xff, 0x5f, 0x51, 0x3f, 0xff, 0x7e, 0x72,
+ 0x62, 0xff, 0x71, 0x63, 0x51, 0xff, 0x8a, 0x7e, 0x6b, 0xff, 0xce, 0xc9, 0xb4, 0xff, 0xcc, 0xc5,
+ 0xac, 0xff, 0xc9, 0xc1, 0xa6, 0xff, 0xc5, 0xbc, 0xa0, 0xff, 0xc3, 0xba, 0x9d, 0xff, 0xbd, 0xb3,
+ 0x93, 0xff, 0xb9, 0xae, 0x8c, 0xff, 0xbe, 0xb5, 0x95, 0xff, 0xba, 0xaf, 0x8e, 0xff, 0x9a, 0x8f,
+ 0x72, 0xff, 0x53, 0x48, 0x35, 0xff, 0x4d, 0x41, 0x31, 0xff, 0x56, 0x4c, 0x3b, 0xff, 0x5b, 0x52,
+ 0x40, 0xff, 0x82, 0x7b, 0x6f, 0xff, 0x92, 0x8b, 0x81, 0xff, 0xad, 0xa9, 0xa1, 0xff, 0xca, 0xcb,
+ 0xc7, 0xff, 0xc1, 0xc0, 0xba, 0xff, 0xaa, 0xa8, 0x9f, 0xff, 0xb4, 0xb1, 0xa8, 0xff, 0x96, 0x90,
+ 0x86, 0xff, 0xac, 0xa8, 0xa0, 0xff, 0xd0, 0xd0, 0xc9, 0xff, 0xdb, 0xdc, 0xd5, 0xff, 0xd0, 0xcf,
+ 0xc7, 0xff, 0xb4, 0xaf, 0xa3, 0xff, 0x96, 0x8a, 0x78, 0xff, 0x84, 0x76, 0x62, 0xff, 0x7d, 0x6f,
+ 0x5c, 0xff, 0x8e, 0x81, 0x6f, 0xff, 0xa9, 0x9e, 0x88, 0xff, 0xc8, 0xbf, 0xa4, 0xff, 0xc6, 0xbd,
+ 0xa2, 0xff, 0xc4, 0xbb, 0x9e, 0xff, 0xbf, 0xb6, 0x97, 0xff, 0xbd, 0xb4, 0x95, 0xff, 0xb5, 0xa8,
+ 0x86, 0xff, 0xb4, 0xa7, 0x85, 0xff, 0xad, 0x9f, 0x7c, 0xff, 0xa4, 0x95, 0x72, 0xff, 0xa6, 0x98,
+ 0x75, 0xff, 0x83, 0x78, 0x60, 0xff, 0x71, 0x6a, 0x5f, 0xff, 0x77, 0x6d, 0x5e, 0xff, 0x8a, 0x83,
+ 0x75, 0xff, 0xa7, 0xa4, 0x9a, 0xff, 0x93, 0x93, 0x8f, 0xff, 0x96, 0x91, 0x84, 0xff, 0xb4, 0xb1,
+ 0xa7, 0xff, 0xbd, 0xbc, 0xb4, 0xff, 0xb2, 0xaf, 0xa6, 0xff, 0xb6, 0xb4, 0xab, 0xff, 0x97, 0x91,
+ 0x87, 0xff, 0x9f, 0x99, 0x8e, 0xff, 0xb3, 0xae, 0xa3, 0xff, 0xbd, 0xb8, 0xad, 0xff, 0xbd, 0xb8,
+ 0xac, 0xff, 0xc9, 0xc5, 0xb9, 0xff, 0xbf, 0xb9, 0xaa, 0xff, 0xa3, 0x98, 0x87, 0xff, 0xa7, 0x9f,
+ 0x90, 0xff, 0xb1, 0xaa, 0x9c, 0xff, 0xcc, 0xc6, 0xb0, 0xff, 0xcf, 0xc9, 0xb3, 0xff, 0xcc, 0xc7,
+ 0xaf, 0xff, 0xc9, 0xc2, 0xa8, 0xff, 0xc5, 0xbc, 0xa0, 0xff, 0xbe, 0xb4, 0x95, 0xff, 0xb7, 0xab,
+ 0x8a, 0xff, 0xb8, 0xad, 0x8c, 0xff, 0xa3, 0x93, 0x70, 0xff, 0x9c, 0x8c, 0x6b, 0xff, 0xa1, 0x91,
+ 0x6e, 0xff, 0xab, 0x9d, 0x7b, 0xff, 0xb7, 0xb4, 0xa2, 0xff, 0xbc, 0xbd, 0xb5, 0xff, 0xb4, 0xb1,
+ 0xa6, 0xff, 0xc5, 0xc2, 0xb4, 0xff, 0xb4, 0xad, 0x9c, 0xff, 0x97, 0x8f, 0x80, 0xff, 0x93, 0x89,
+ 0x7a, 0xff, 0xa6, 0xa0, 0x94, 0xff, 0xae, 0xaa, 0xa2, 0xff, 0xb1, 0xb2, 0xad, 0xff, 0xa5, 0xa0,
+ 0x96, 0xff, 0xb6, 0xb1, 0xa7, 0xff, 0xb2, 0xaa, 0x9c, 0xff, 0xc0, 0xbb, 0xad, 0xff, 0xc6, 0xc1,
+ 0xb4, 0xff, 0xd5, 0xd3, 0xc7, 0xff, 0xc1, 0xbc, 0xaf, 0xff, 0xc1, 0xbe, 0xb4, 0xff, 0xcd, 0xcd,
+ 0xc3, 0xff, 0xd6, 0xd7, 0xc9, 0xff, 0xd0, 0xcc, 0xb9, 0xff, 0xce, 0xcb, 0xb6, 0xff, 0xc7, 0xbf,
+ 0xa5, 0xff, 0xc9, 0xc2, 0xa9, 0xff, 0xcc, 0xc7, 0xaf, 0xff, 0xbc, 0xb1, 0x92, 0xff, 0xb8, 0xad,
+ 0x8b, 0xff, 0xb8, 0xad, 0x8c, 0xff, 0xa9, 0x9a, 0x76, 0xff, 0xa2, 0x92, 0x6e, 0xff, 0xa3, 0x92,
+ 0x70, 0xff, 0xb3, 0xa6, 0x84, 0xff, 0xc8, 0xc2, 0xa7, 0xff, 0xd7, 0xd9, 0xca, 0xff, 0xd6, 0xd5,
+ 0xc3, 0xff, 0xd2, 0xcf, 0xba, 0xff, 0xd1, 0xcd, 0xb8, 0xff, 0xd4, 0xd5, 0xc9, 0xff, 0xa2, 0x9b,
+ 0x8b, 0xff, 0x7b, 0x6d, 0x59, 0xff, 0x88, 0x82, 0x7a, 0xff, 0x6a, 0x64, 0x5b, 0xff, 0x9e, 0x9b,
+ 0x93, 0xff, 0xb0, 0xa9, 0x9c, 0xff, 0xbc, 0xb6, 0xaa, 0xff, 0xda, 0xdc, 0xd4, 0xff, 0xdc, 0xe0,
+ 0xd7, 0xff, 0xdb, 0xdb, 0xcf, 0xff, 0xd5, 0xd3, 0xc2, 0xff, 0xd4, 0xd1, 0xc0, 0xff, 0xd2, 0xce,
+ 0xb9, 0xff, 0xd3, 0xd0, 0xbd, 0xff, 0xb6, 0xa9, 0x8b, 0xff, 0xac, 0x9e, 0x7f, 0xff, 0xad, 0x9f,
+ 0x7f, 0xff, 0xa8, 0x9a, 0x7b, 0xff, 0xaa, 0x9b, 0x7c, 0xff, 0xa7, 0x99, 0x79, 0xff, 0xb7, 0xac,
+ 0x8b, 0xff, 0xbb, 0xb1, 0x90, 0xff, 0xa6, 0x97, 0x74, 0xff, 0xa1, 0x91, 0x6e, 0xff, 0xa7, 0x97,
+ 0x74, 0xff, 0xaf, 0xa0, 0x7d, 0xff, 0xbe, 0xb5, 0x96, 0xff, 0xd1, 0xce, 0xb9, 0xff, 0xd9, 0xda,
+ 0xcd, 0xff, 0xd5, 0xd3, 0xc0, 0xff, 0xd5, 0xd5, 0xc4, 0xff, 0xd2, 0xd1, 0xc4, 0xff, 0xc6, 0xc0,
+ 0xaf, 0xff, 0x7c, 0x75, 0x69, 0xff, 0x5d, 0x5a, 0x55, 0xff, 0x56, 0x4f, 0x45, 0xff, 0x72, 0x6f,
+ 0x6c, 0xff, 0xa0, 0x9f, 0x9a, 0xff, 0xa4, 0x98, 0x87, 0xff, 0xc2, 0xbc, 0xab, 0xff, 0xda, 0xdf,
+ 0xd7, 0xff, 0xdc, 0xdf, 0xd7, 0xff, 0xda, 0xda, 0xce, 0xff, 0xd1, 0xcb, 0xb6, 0xff, 0xd1, 0xcd,
+ 0xb8, 0xff, 0xc8, 0xc0, 0xa5, 0xff, 0xb7, 0xaa, 0x8b, 0xff, 0xa2, 0x93, 0x76, 0xff, 0x98, 0x88,
+ 0x6b, 0xff, 0x8f, 0x7f, 0x63, 0xff, 0x8c, 0x7c, 0x5e, 0xff, 0x8c, 0x7d, 0x61, 0xff, 0xb8, 0xad,
+ 0x8c, 0xff, 0xb1, 0xa5, 0x84, 0xff, 0x95, 0x83, 0x62, 0xff, 0x90, 0x7f, 0x5d, 0xff, 0x9d, 0x8c,
+ 0x6a, 0xff, 0x9f, 0x8e, 0x6b, 0xff, 0xa2, 0x92, 0x6f, 0xff, 0xbd, 0xb3, 0x93, 0xff, 0xd0, 0xce,
+ 0xb8, 0xff, 0xd7, 0xd7, 0xc7, 0xff, 0xd8, 0xd9, 0xcb, 0xff, 0xcc, 0xca, 0xba, 0xff, 0x89, 0x7c,
+ 0x67, 0xff, 0x5b, 0x51, 0x43, 0xff, 0x4e, 0x44, 0x3a, 0xff, 0x46, 0x38, 0x2b, 0xff, 0x54, 0x4b,
+ 0x40, 0xff, 0x94, 0x8e, 0x84, 0xff, 0x8a, 0x7c, 0x69, 0xff, 0xac, 0xa1, 0x8d, 0xff, 0xd7, 0xda,
+ 0xd0, 0xff, 0xdc, 0xe2, 0xdb, 0xff, 0xdb, 0xdf, 0xd5, 0xff, 0xd0, 0xcb, 0xb6, 0xff, 0xd0, 0xca,
+ 0xb5, 0xff, 0xc4, 0xbb, 0x9f, 0xff, 0xb2, 0xa4, 0x84, 0xff, 0x9f, 0x8f, 0x71, 0xff, 0x94, 0x84,
+ 0x68, 0xff, 0x90, 0x80, 0x64, 0xff, 0x86, 0x76, 0x5b, 0xff, 0x7b, 0x6b, 0x52, 0xff, 0xa7, 0x98,
+ 0x75, 0xff, 0x9c, 0x8c, 0x69, 0xff, 0x8c, 0x79, 0x59, 0xff, 0x85, 0x74, 0x54, 0xff, 0x92, 0x80,
+ 0x5f, 0xff, 0x8e, 0x7c, 0x5a, 0xff, 0x93, 0x81, 0x60, 0xff, 0xaf, 0xa1, 0x7f, 0xff, 0xc1, 0xb8,
+ 0x99, 0xff, 0xd5, 0xd4, 0xc3, 0xff, 0xdb, 0xdd, 0xd4, 0xff, 0xbf, 0xba, 0xaa, 0xff, 0x68, 0x59,
+ 0x43, 0xff, 0x52, 0x4b, 0x40, 0xff, 0x3f, 0x37, 0x2d, 0xff, 0x3d, 0x32, 0x27, 0xff, 0x42, 0x36,
+ 0x2a, 0xff, 0x6d, 0x66, 0x5d, 0xff, 0x78, 0x69, 0x58, 0xff, 0xa1, 0x93, 0x7f, 0xff, 0xd2, 0xd1,
+ 0xc3, 0xff, 0xdc, 0xe3, 0xde, 0xff, 0xdb, 0xdd, 0xd1, 0xff, 0xd2, 0xce, 0xb9, 0xff, 0xcd, 0xc6,
+ 0xae, 0xff, 0xbc, 0xb0, 0x91, 0xff, 0xb2, 0xa3, 0x83, 0xff, 0xa7, 0x97, 0x77, 0xff, 0x96, 0x86,
+ 0x69, 0xff, 0x8b, 0x7a, 0x5f, 0xff, 0x7b, 0x6b, 0x52, 0xff, 0x73, 0x65, 0x4d, 0xff, 0x96, 0x84,
+ 0x63, 0xff, 0x91, 0x80, 0x5e, 0xff, 0x87, 0x75, 0x56, 0xff, 0x85, 0x73, 0x54, 0xff, 0x82, 0x71,
+ 0x52, 0xff, 0x84, 0x73, 0x54, 0xff, 0x8e, 0x7c, 0x5c, 0xff, 0x9f, 0x8f, 0x6d, 0xff, 0xb6, 0xaa,
+ 0x88, 0xff, 0xcd, 0xc9, 0xb1, 0xff, 0xcb, 0xc8, 0xba, 0xff, 0x8e, 0x81, 0x6b, 0xff, 0x58, 0x49,
+ 0x35, 0xff, 0x46, 0x3d, 0x32, 0xff, 0x3e, 0x34, 0x27, 0xff, 0x46, 0x3a, 0x2f, 0xff, 0x56, 0x4c,
+ 0x41, 0xff, 0x5c, 0x52, 0x46, 0xff, 0x6e, 0x60, 0x50, 0xff, 0x96, 0x86, 0x72, 0xff, 0xd1, 0xcd,
+ 0xc0, 0xff, 0xdc, 0xe3, 0xde, 0xff, 0xdc, 0xdf, 0xd6, 0xff, 0xdb, 0xdc, 0xd0, 0xff, 0xd8, 0xd7,
+ 0xc8, 0xff, 0xc3, 0xba, 0x9d, 0xff, 0xba, 0xad, 0x8d, 0xff, 0xb4, 0xa6, 0x86, 0xff, 0x9d, 0x8e,
+ 0x70, 0xff, 0x89, 0x79, 0x5d, 0xff, 0x7c, 0x6c, 0x52, 0xff, 0x73, 0x64, 0x4d, 0xff, 0x8a, 0x78,
+ 0x58, 0xff, 0x83, 0x72, 0x53, 0xff, 0x78, 0x67, 0x4b, 0xff, 0x77, 0x67, 0x4a, 0xff, 0x72, 0x62,
+ 0x48, 0xff, 0x7a, 0x69, 0x4d, 0xff, 0x87, 0x76, 0x57, 0xff, 0x91, 0x80, 0x5f, 0xff, 0xa3, 0x93,
+ 0x71, 0xff, 0xaf, 0xa2, 0x82, 0xff, 0x80, 0x72, 0x5b, 0xff, 0x6c, 0x5e, 0x49, 0xff, 0x50, 0x42,
+ 0x30, 0xff, 0x45, 0x3e, 0x35, 0xff, 0x42, 0x38, 0x2c, 0xff, 0x3f, 0x35, 0x29, 0xff, 0x4f, 0x44,
+ 0x39, 0xff, 0x6a, 0x63, 0x5a, 0xff, 0x77, 0x6d, 0x61, 0xff, 0x94, 0x86, 0x73, 0xff, 0xcf, 0xcb,
+ 0xbe, 0xff, 0xdc, 0xe1, 0xda, 0xff, 0xdc, 0xe4, 0xde, 0xff, 0xdc, 0xe0, 0xd8, 0xff, 0xd2, 0xce,
+ 0xb9, 0xff, 0xc5, 0xbc, 0x9f, 0xff, 0xc0, 0xb6, 0x97, 0xff, 0xb7, 0xa9, 0x88, 0xff, 0xa7, 0x98,
+ 0x79, 0xff, 0x94, 0x84, 0x68, 0xff, 0x80, 0x70, 0x56, 0xff, 0x77, 0x68, 0x50, 0xff, 0x7a, 0x69,
+ 0x4d, 0xff, 0x75, 0x65, 0x49, 0xff, 0x6b, 0x5b, 0x42, 0xff, 0x68, 0x58, 0x3f, 0xff, 0x6c, 0x5d,
+ 0x44, 0xff, 0x73, 0x63, 0x48, 0xff, 0x7d, 0x6b, 0x4f, 0xff, 0x82, 0x72, 0x54, 0xff, 0x92, 0x81,
+ 0x61, 0xff, 0xa2, 0x93, 0x73, 0xff, 0x9d, 0x91, 0x7a, 0xff, 0x7b, 0x6e, 0x59, 0xff, 0x4e, 0x3f,
+ 0x2e, 0xff, 0x46, 0x3f, 0x37, 0xff, 0x4b, 0x42, 0x37, 0xff, 0x4a, 0x3f, 0x33, 0xff, 0x66, 0x5d,
+ 0x54, 0xff, 0x74, 0x6d, 0x66, 0xff, 0x81, 0x79, 0x72, 0xff, 0x8f, 0x81, 0x6f, 0xff, 0xbd, 0xb6,
+ 0xa4, 0xff, 0xd5, 0xd4, 0xc6, 0xff, 0xdb, 0xe0, 0xd9, 0xff, 0xdc, 0xe1, 0xd8, 0xff, 0xd6, 0xd3,
+ 0xc1, 0xff, 0xcb, 0xc3, 0xa9, 0xff, 0xc3, 0xbb, 0x9e, 0xff, 0xb8, 0xab, 0x8b, 0xff, 0xac, 0x9d,
+ 0x7d, 0xff, 0x96, 0x86, 0x6b, 0xff, 0x88, 0x78, 0x5d, 0xff, 0x7c, 0x6c, 0x54, 0xff, 0x64, 0x55,
+ 0x3c, 0xff, 0x5f, 0x50, 0x37, 0xff, 0x5f, 0x51, 0x37, 0xff, 0x63, 0x55, 0x3b, 0xff, 0x66, 0x57,
+ 0x3d, 0xff, 0x69, 0x59, 0x40, 0xff, 0x72, 0x62, 0x47, 0xff, 0x7f, 0x6e, 0x51, 0xff, 0x94, 0x83,
+ 0x63, 0xff, 0xad, 0x9f, 0x7d, 0xff, 0xb6, 0xab, 0x8e, 0xff, 0x91, 0x86, 0x6e, 0xff, 0x48, 0x3b,
+ 0x2a, 0xff, 0x49, 0x41, 0x36, 0xff, 0x50, 0x46, 0x41, 0xff, 0x5f, 0x57, 0x50, 0xff, 0x77, 0x72,
+ 0x70, 0xff, 0x74, 0x6b, 0x68, 0xff, 0x80, 0x75, 0x69, 0xff, 0x94, 0x88, 0x75, 0xff, 0xc1, 0xbb,
+ 0xab, 0xff, 0xd7, 0xd6, 0xcc, 0xff, 0xdc, 0xe1, 0xdc, 0xff, 0xdc, 0xe2, 0xdb, 0xff, 0xd9, 0xd9,
+ 0xcb, 0xff, 0xd0, 0xcb, 0xb5, 0xff, 0xc5, 0xbc, 0x9f, 0xff, 0xb8, 0xab, 0x8b, 0xff, 0xab, 0x9c,
+ 0x7c, 0xff, 0x9c, 0x8c, 0x6f, 0xff, 0x8c, 0x7d, 0x62, 0xff, 0x81, 0x71, 0x57, 0xff, 0x59, 0x4b,
+ 0x33, 0xff, 0x55, 0x49, 0x31, 0xff, 0x58, 0x4b, 0x32, 0xff, 0x5c, 0x4e, 0x35, 0xff, 0x5c, 0x4e,
+ 0x35, 0xff, 0x60, 0x52, 0x39, 0xff, 0x6a, 0x5a, 0x41, 0xff, 0x78, 0x67, 0x4c, 0xff, 0x8d, 0x7d,
+ 0x5e, 0xff, 0xab, 0x9c, 0x7a, 0xff, 0xbd, 0xb3, 0x95, 0xff, 0xb4, 0xac, 0x95, 0xff, 0x5d, 0x51,
+ 0x3e, 0xff, 0x44, 0x3a, 0x2d, 0xff, 0x5b, 0x53, 0x4d, 0xff, 0x63, 0x5a, 0x52, 0xff, 0x72, 0x6a,
+ 0x64, 0xff, 0x79, 0x72, 0x6d, 0xff, 0x79, 0x6b, 0x5b, 0xff, 0x9d, 0x91, 0x7e, 0xff, 0xcb, 0xc7,
+ 0xb8, 0xff, 0xdb, 0xdf, 0xd7, 0xff, 0xdc, 0xe4, 0xdf, 0xff, 0xdc, 0xe4, 0xdf, 0xff, 0xdc, 0xde,
+ 0xd4, 0xff, 0xd5, 0xd3, 0xc2, 0xff, 0xc6, 0xbe, 0xa2, 0xff, 0xb7, 0xa9, 0x89, 0xff, 0xb2, 0xa4,
+ 0x84, 0xff, 0xab, 0x9b, 0x7c, 0xff, 0x97, 0x87, 0x6c, 0xff, 0x8c, 0x7c, 0x61, 0xff, 0x55, 0x48,
+ 0x31, 0xff, 0x54, 0x46, 0x2f, 0xff, 0x54, 0x46, 0x2f, 0xff, 0x55, 0x48, 0x31, 0xff, 0x58, 0x4a,
+ 0x32, 0xff, 0x5a, 0x4d, 0x34, 0xff, 0x62, 0x54, 0x3a, 0xff, 0x70, 0x60, 0x47, 0xff, 0x81, 0x70,
+ 0x53, 0xff, 0xab, 0x9d, 0x7c, 0xff, 0xca, 0xc5, 0xac, 0xff, 0xbe, 0xb8, 0xa4, 0xff, 0x62, 0x56,
+ 0x44, 0xff, 0x46, 0x3a, 0x2b, 0xff, 0x72, 0x6a, 0x61, 0xff, 0x96, 0x93, 0x8e, 0xff, 0xa6, 0xa5,
+ 0xa1, 0xff, 0xa2, 0xa1, 0x9d, 0xff, 0x82, 0x74, 0x61, 0xff, 0xba, 0xb1, 0xa1, 0xff, 0xd7, 0xd9,
+ 0xd1, 0xff, 0xdc, 0xe3, 0xdf, 0xff, 0xdc, 0xe4, 0xdf, 0xff, 0xdc, 0xe3, 0xdc, 0xff, 0xdc, 0xe1,
+ 0xd8, 0xff, 0xda, 0xda, 0xcc, 0xff, 0xce, 0xc8, 0xb1, 0xff, 0xc0, 0xb6, 0x98, 0xff, 0xbe, 0xb3,
+ 0x94, 0xff, 0xba, 0xaf, 0x8f, 0xff, 0xb0, 0xa4, 0x86, 0xff, 0x94, 0x84, 0x68, 0xff, 0x59, 0x4c,
+ 0x34, 0xff, 0x58, 0x4a, 0x33, 0xff, 0x55, 0x48, 0x31, 0xff, 0x55, 0x48, 0x30, 0xff, 0x58, 0x4b,
+ 0x33, 0xff, 0x5a, 0x4c, 0x34, 0xff, 0x61, 0x53, 0x39, 0xff, 0x6e, 0x5e, 0x45, 0xff, 0x82, 0x72,
+ 0x56, 0xff, 0x9d, 0x8d, 0x6c, 0xff, 0xbf, 0xb6, 0x99, 0xff, 0xac, 0xa7, 0x95, 0xff, 0x81, 0x77,
+ 0x66, 0xff, 0x5c, 0x51, 0x40, 0xff, 0x5f, 0x55, 0x47, 0xff, 0x7b, 0x75, 0x6b, 0xff, 0x98, 0x93,
+ 0x8b, 0xff, 0x8e, 0x83, 0x75, 0xff, 0xaf, 0xa5, 0x94, 0xff, 0xd4, 0xd5, 0xcc, 0xff, 0xdc, 0xe2,
+ 0xdf, 0xff, 0xdc, 0xe4, 0xe1, 0xff, 0xdc, 0xe0, 0xd7, 0xff, 0xdc, 0xe0, 0xd6, 0xff, 0xdc, 0xdd,
+ 0xd3, 0xff, 0xdb, 0xdc, 0xd0, 0xff, 0xd6, 0xd5, 0xc4, 0xff, 0xcd, 0xc7, 0xaf, 0xff, 0xcb, 0xc4,
+ 0xab, 0xff, 0xcb, 0xc5, 0xad, 0xff, 0xcf, 0xcb, 0xb7, 0xff, 0xa5, 0x97, 0x7c, 0xff, 0x61, 0x53,
+ 0x3a, 0xff, 0x61, 0x53, 0x3a, 0xff, 0x5c, 0x4e, 0x36, 0xff, 0x5a, 0x4d, 0x35, 0xff, 0x5b, 0x4d,
+ 0x35, 0xff, 0x61, 0x52, 0x39, 0xff, 0x6a, 0x5b, 0x42, 0xff, 0x77, 0x67, 0x4c, 0xff, 0x85, 0x75,
+ 0x58, 0xff, 0x8f, 0x7e, 0x60, 0xff, 0xa9, 0x9b, 0x7a, 0xff, 0xcd, 0xca, 0xb6, 0xff, 0xb9, 0xb2,
+ 0x9f, 0xff, 0x99, 0x8f, 0x7e, 0xff, 0x83, 0x78, 0x68, 0xff, 0x87, 0x7c, 0x6b, 0xff, 0x8b, 0x7e,
+ 0x6a, 0xff, 0xb4, 0xad, 0x9c, 0xff, 0xd4, 0xd4, 0xc8, 0xff, 0xdc, 0xe4, 0xe0, 0xff, 0xdc, 0xe4,
+ 0xe1, 0xff, 0xdc, 0xe4, 0xde, 0xff, 0xdc, 0xe0, 0xd7, 0xff, 0xdb, 0xdb, 0xce, 0xff, 0xdc, 0xdd,
+ 0xd3, 0xff, 0xdb, 0xdb, 0xce, 0xff, 0xd8, 0xd7, 0xc8, 0xff, 0xd2, 0xcf, 0xbc, 0xff, 0xd3, 0xd0,
+ 0xbd, 0xff, 0xd9, 0xd9, 0xcc, 0xff, 0xd5, 0xd4, 0xc3, 0xff, 0xc2, 0xba, 0xa3, 0xff, 0x73, 0x64,
+ 0x49, 0xff, 0x72, 0x63, 0x48, 0xff, 0x71, 0x62, 0x47, 0xff, 0x6d, 0x5d, 0x43, 0xff, 0x6b, 0x5b,
+ 0x41, 0xff, 0x77, 0x67, 0x4b, 0xff, 0x89, 0x78, 0x59, 0xff, 0x99, 0x89, 0x69, 0xff, 0xaf, 0xa3,
+ 0x82, 0xff, 0xaa, 0x9b, 0x79, 0xff, 0xa8, 0x99, 0x76, 0xff, 0xbc, 0xb2, 0x92, 0xff, 0xcd, 0xc8,
+ 0xb1, 0xff, 0xd7, 0xd8, 0xcb, 0xff, 0xc2, 0xbf, 0xb2, 0xff, 0xbc, 0xb5, 0xa5, 0xff, 0xd3, 0xd3,
+ 0xc7, 0xff, 0xdb, 0xdf, 0xd7, 0xff, 0xdb, 0xe2, 0xdc, 0xff, 0xdc, 0xe2, 0xdb, 0xff, 0xdc, 0xe4,
+ 0xde, 0xff, 0xdc, 0xe3, 0xdc, 0xff, 0xdc, 0xdf, 0xd5, 0xff, 0xda, 0xda, 0xcb, 0xff, 0xdc, 0xdc,
+ 0xd1, 0xff, 0xda, 0xdb, 0xcd, 0xff, 0xd7, 0xd6, 0xc6, 0xff, 0xd1, 0xcd, 0xb7, 0xff, 0xd7, 0xd8,
+ 0xc8, 0xff, 0xd9, 0xd9, 0xcb, 0xff, 0xd5, 0xd5, 0xc4, 0xff, 0xd1, 0xce, 0xba, 0xff, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/flash_html.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/flash_html.h
new file mode 100644
index 0000000..f0da6a0
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/flash_html.h
@@ -0,0 +1,118 @@
+#pragma once
+
+const uint8_t flash_html[] = {
+ 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x3c,
+ 0x68, 0x74, 0x6d, 0x6c, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x3d, 0x65, 0x6e, 0x20, 0x64, 0x61, 0x74,
+ 0x61, 0x2d, 0x74, 0x68, 0x65, 0x6d, 0x65, 0x3d, 0x64, 0x61, 0x72, 0x6b, 0x3e, 0x3c, 0x68, 0x65,
+ 0x61, 0x64, 0x3e, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74,
+ 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x20, 0x2f, 0x3e, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x6e,
+ 0x61, 0x6d, 0x65, 0x3d, 0x76, 0x69, 0x65, 0x77, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x63, 0x6f, 0x6e,
+ 0x74, 0x65, 0x6e, 0x74, 0x3d, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x64, 0x65, 0x76, 0x69,
+ 0x63, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61,
+ 0x6c, 0x2d, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x3d, 0x31, 0x2c, 0x20, 0x73, 0x68, 0x72, 0x69, 0x6e,
+ 0x6b, 0x2d, 0x74, 0x6f, 0x2d, 0x66, 0x69, 0x74, 0x3d, 0x6e, 0x6f, 0x22, 0x20, 0x2f, 0x3e, 0x3c,
+ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x50, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x4f, 0x53,
+ 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x3c, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x72, 0x65,
+ 0x6c, 0x3d, 0x69, 0x63, 0x6f, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x69, 0x6d, 0x61, 0x67,
+ 0x65, 0x2f, 0x78, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x66, 0x61,
+ 0x76, 0x69, 0x63, 0x6f, 0x6e, 0x2e, 0x69, 0x63, 0x6f, 0x20, 0x2f, 0x3e, 0x3c, 0x6c, 0x69, 0x6e,
+ 0x6b, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x70, 0x69, 0x63, 0x6f, 0x2e, 0x63, 0x73, 0x73, 0x20,
+ 0x72, 0x65, 0x6c, 0x3d, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x73, 0x68, 0x65, 0x65, 0x74, 0x20, 0x2f,
+ 0x3e, 0x3c, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x6d, 0x61, 0x69, 0x6e,
+ 0x2e, 0x63, 0x73, 0x73, 0x20, 0x72, 0x65, 0x6c, 0x3d, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x73, 0x68,
+ 0x65, 0x65, 0x74, 0x20, 0x2f, 0x3e, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, 0x3c, 0x62, 0x6f,
+ 0x64, 0x79, 0x3e, 0x3c, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x63,
+ 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x3e, 0x3c, 0x66, 0x6f, 0x72, 0x6d, 0x3e, 0x3c,
+ 0x68, 0x32, 0x3e, 0x50, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x4f, 0x53, 0x3a, 0x20, 0x46,
+ 0x6c, 0x61, 0x73, 0x68, 0x20, 0x42, 0x49, 0x4f, 0x53, 0x3c, 0x2f, 0x68, 0x32, 0x3e, 0x3c, 0x6c,
+ 0x61, 0x62, 0x65, 0x6c, 0x20, 0x66, 0x6f, 0x72, 0x3d, 0x66, 0x69, 0x6c, 0x65, 0x3e, 0x3c, 0x62,
+ 0x3e, 0x46, 0x69, 0x6c, 0x65, 0x3a, 0x3c, 0x2f, 0x62, 0x3e, 0x3c, 0x2f, 0x6c, 0x61, 0x62, 0x65,
+ 0x6c, 0x3e, 0x3c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69,
+ 0x6c, 0x65, 0x20, 0x69, 0x64, 0x3d, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6f, 0x6e, 0x63, 0x68, 0x61,
+ 0x6e, 0x67, 0x65, 0x3d, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x49,
+ 0x6e, 0x66, 0x6f, 0x28, 0x29, 0x20, 0x2f, 0x3e, 0x3c, 0x62, 0x72, 0x20, 0x2f, 0x3e, 0x20, 0x3c,
+ 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x20, 0x66, 0x6f, 0x72, 0x3d, 0x6e, 0x61, 0x6d, 0x65, 0x3e, 0x3c,
+ 0x62, 0x3e, 0x4e, 0x61, 0x6d, 0x65, 0x3a, 0x3c, 0x2f, 0x62, 0x3e, 0x3c, 0x2f, 0x6c, 0x61, 0x62,
+ 0x65, 0x6c, 0x3e, 0x3c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d,
+ 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x74, 0x79, 0x70,
+ 0x65, 0x3d, 0x74, 0x65, 0x78, 0x74, 0x20, 0x6d, 0x61, 0x78, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68,
+ 0x3d, 0x34, 0x30, 0x20, 0x69, 0x64, 0x3d, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x2f, 0x3e, 0x3c, 0x62,
+ 0x72, 0x20, 0x2f, 0x3e, 0x20, 0x3c, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x20, 0x66, 0x6f, 0x72, 0x3d,
+ 0x73, 0x6c, 0x6f, 0x74, 0x73, 0x4e, 0x65, 0x65, 0x64, 0x65, 0x64, 0x3e, 0x3c, 0x62, 0x3e, 0x4e,
+ 0x65, 0x65, 0x64, 0x65, 0x64, 0x20, 0x53, 0x6c, 0x6f, 0x74, 0x73, 0x3a, 0x3c, 0x2f, 0x62, 0x3e,
+ 0x3c, 0x2f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x3e, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x69, 0x64,
+ 0x3d, 0x73, 0x6c, 0x6f, 0x74, 0x73, 0x4e, 0x65, 0x65, 0x64, 0x65, 0x64, 0x3e, 0x4e, 0x41, 0x3c,
+ 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x72, 0x20, 0x2f, 0x3e, 0x3c, 0x6c, 0x61, 0x62, 0x65,
+ 0x6c, 0x20, 0x66, 0x6f, 0x72, 0x3d, 0x66, 0x72, 0x65, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x73, 0x3e,
+ 0x3c, 0x62, 0x3e, 0x46, 0x72, 0x65, 0x65, 0x20, 0x53, 0x6c, 0x6f, 0x74, 0x73, 0x3a, 0x3c, 0x2f,
+ 0x62, 0x3e, 0x3c, 0x2f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x3e, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20,
+ 0x69, 0x64, 0x3d, 0x66, 0x72, 0x65, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x73, 0x3e, 0x30, 0x3c, 0x2f,
+ 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x72, 0x20, 0x2f, 0x3e, 0x3c, 0x6c, 0x61, 0x62, 0x65, 0x6c,
+ 0x20, 0x66, 0x6f, 0x72, 0x3d, 0x6c, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x42, 0x75, 0x74,
+ 0x74, 0x6f, 0x6e, 0x73, 0x3e, 0x3c, 0x62, 0x3e, 0x4c, 0x45, 0x44, 0x20, 0x43, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x3c, 0x2f, 0x62, 0x3e, 0x20, 0x3c, 0x73, 0x70, 0x61, 0x6e, 0x20, 0x69, 0x64, 0x3d,
+ 0x6c, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x3e, 0x4f, 0x66, 0x66, 0x3c, 0x2f, 0x73, 0x70,
+ 0x61, 0x6e, 0x3e, 0x3c, 0x2f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20,
+ 0x69, 0x64, 0x3d, 0x6c, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x42, 0x75, 0x74, 0x74, 0x6f,
+ 0x6e, 0x73, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x67, 0x72,
+ 0x69, 0x64, 0x3e, 0x20, 0x3c, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65,
+ 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x62, 0x74,
+ 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x6f, 0x66, 0x66, 0x20, 0x6f, 0x6e, 0x63, 0x6c, 0x69, 0x63, 0x6b,
+ 0x3d, 0x73, 0x65, 0x74, 0x4c, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x30, 0x29, 0x3e,
+ 0x4f, 0x66, 0x66, 0x3c, 0x2f, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x3e, 0x20, 0x3c, 0x62, 0x75,
+ 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e,
+ 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x72, 0x65,
+ 0x64, 0x20, 0x6f, 0x6e, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x3d, 0x73, 0x65, 0x74, 0x4c, 0x65, 0x64,
+ 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x31, 0x29, 0x3e, 0x52, 0x65, 0x64, 0x3c, 0x2f, 0x62, 0x75,
+ 0x74, 0x74, 0x6f, 0x6e, 0x3e, 0x20, 0x3c, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x74, 0x79,
+ 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d,
+ 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x6f, 0x6e, 0x63,
+ 0x6c, 0x69, 0x63, 0x6b, 0x3d, 0x73, 0x65, 0x74, 0x4c, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x28, 0x32, 0x29, 0x3e, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x3c, 0x2f, 0x62, 0x75, 0x74, 0x74, 0x6f,
+ 0x6e, 0x3e, 0x20, 0x3c, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d,
+ 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x62, 0x74, 0x6e,
+ 0x2d, 0x6c, 0x65, 0x64, 0x79, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x6f, 0x6e, 0x63, 0x6c, 0x69,
+ 0x63, 0x6b, 0x3d, 0x73, 0x65, 0x74, 0x4c, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x33,
+ 0x29, 0x3e, 0x59, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x3c, 0x2f, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e,
+ 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73,
+ 0x73, 0x3d, 0x67, 0x72, 0x69, 0x64, 0x3e, 0x3c, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x74,
+ 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73,
+ 0x3d, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x62, 0x6c, 0x75, 0x65, 0x20, 0x6f, 0x6e, 0x63,
+ 0x6c, 0x69, 0x63, 0x6b, 0x3d, 0x73, 0x65, 0x74, 0x4c, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x28, 0x34, 0x29, 0x3e, 0x42, 0x6c, 0x75, 0x65, 0x3c, 0x2f, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e,
+ 0x3e, 0x20, 0x3c, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62,
+ 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x62, 0x74, 0x6e, 0x2d,
+ 0x6c, 0x65, 0x64, 0x70, 0x75, 0x72, 0x70, 0x6c, 0x65, 0x20, 0x6f, 0x6e, 0x63, 0x6c, 0x69, 0x63,
+ 0x6b, 0x3d, 0x73, 0x65, 0x74, 0x4c, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x35, 0x29,
+ 0x3e, 0x50, 0x75, 0x72, 0x70, 0x6c, 0x65, 0x3c, 0x2f, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x3e,
+ 0x20, 0x3c, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75,
+ 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x62, 0x74, 0x6e, 0x2d, 0x6c,
+ 0x65, 0x64, 0x74, 0x75, 0x72, 0x71, 0x75, 0x6f, 0x69, 0x73, 0x65, 0x20, 0x6f, 0x6e, 0x63, 0x6c,
+ 0x69, 0x63, 0x6b, 0x3d, 0x73, 0x65, 0x74, 0x4c, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x28,
+ 0x36, 0x29, 0x3e, 0x54, 0x75, 0x72, 0x71, 0x75, 0x6f, 0x69, 0x73, 0x65, 0x3c, 0x2f, 0x62, 0x75,
+ 0x74, 0x74, 0x6f, 0x6e, 0x3e, 0x20, 0x3c, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x74, 0x79,
+ 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d,
+ 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x77, 0x68, 0x69, 0x74, 0x65, 0x20, 0x6f, 0x6e, 0x63,
+ 0x6c, 0x69, 0x63, 0x6b, 0x3d, 0x73, 0x65, 0x74, 0x4c, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x28, 0x37, 0x29, 0x3e, 0x57, 0x68, 0x69, 0x74, 0x65, 0x3c, 0x2f, 0x62, 0x75, 0x74, 0x74, 0x6f,
+ 0x6e, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x68,
+ 0x72, 0x20, 0x2f, 0x3e, 0x3c, 0x62, 0x72, 0x20, 0x2f, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63,
+ 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x67, 0x72, 0x69, 0x64, 0x3e, 0x3c, 0x61, 0x20, 0x72, 0x6f, 0x6c,
+ 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
+ 0x64, 0x20, 0x69, 0x64, 0x3d, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x68, 0x72, 0x65, 0x66,
+ 0x3d, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3a, 0x76, 0x6f, 0x69, 0x64,
+ 0x28, 0x30, 0x29, 0x20, 0x6f, 0x6e, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x3d, 0x75, 0x70, 0x6c, 0x6f,
+ 0x61, 0x64, 0x28, 0x29, 0x3e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x3c, 0x2f, 0x61, 0x3e, 0x20,
+ 0x3c, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x63,
+ 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, 0x68,
+ 0x72, 0x65, 0x66, 0x3d, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x42,
+ 0x61, 0x63, 0x6b, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x72,
+ 0x20, 0x2f, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x3e, 0x43, 0x6f, 0x70, 0x79, 0x72,
+ 0x69, 0x67, 0x68, 0x74, 0x20, 0x32, 0x30, 0x32, 0x34, 0x20, 0x2d, 0x20, 0x54, 0x65, 0x61, 0x6d,
+ 0x20, 0x43, 0x65, 0x72, 0x62, 0x69, 0x6f, 0x73, 0x20, 0x2b, 0x20, 0x54, 0x65, 0x61, 0x6d, 0x20,
+ 0x52, 0x65, 0x73, 0x75, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x3c, 0x2f, 0x62, 0x3e, 0x3c, 0x2f, 0x64,
+ 0x69, 0x76, 0x3e, 0x3c, 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x3e, 0x3c, 0x2f, 0x6d, 0x61, 0x69, 0x6e,
+ 0x3e, 0x3c, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x73, 0x72, 0x63, 0x3d, 0x66, 0x6c, 0x61,
+ 0x73, 0x68, 0x2e, 0x6a, 0x73, 0x3e, 0x3c, 0x2f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3e, 0x3c,
+ 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/flash_js.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/flash_js.h
new file mode 100644
index 0000000..492a519
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/flash_js.h
@@ -0,0 +1,226 @@
+#pragma once
+
+const uint8_t flash_js[] = {
+ 0x6c, 0x65, 0x74, 0x20, 0x6c, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77,
+ 0x2e, 0x6f, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
+ 0x6f, 0x6e, 0x20, 0x28, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x66,
+ 0x72, 0x65, 0x73, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x28, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x7d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20,
+ 0x67, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x28, 0x29, 0x0d, 0x0a, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x66, 0x69, 0x6c, 0x65,
+ 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x45,
+ 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x66, 0x69, 0x6c, 0x65,
+ 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x66, 0x69, 0x6c,
+ 0x65, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x22, 0x29, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
+ 0x20, 0x2d, 0x31, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x20,
+ 0x3d, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5b, 0x30, 0x5d, 0x2e,
+ 0x73, 0x69, 0x7a, 0x65, 0x3b, 0x20, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28,
+ 0x66, 0x69, 0x6c, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x29, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
+ 0x20, 0x2d, 0x31, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x20, 0x65, 0x6c, 0x73, 0x65,
+ 0x20, 0x69, 0x66, 0x20, 0x28, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x20, 0x25, 0x20,
+ 0x28, 0x32, 0x35, 0x36, 0x20, 0x2a, 0x20, 0x31, 0x30, 0x32, 0x34, 0x29, 0x20, 0x21, 0x3d, 0x20,
+ 0x30, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65,
+ 0x74, 0x75, 0x72, 0x6e, 0x20, 0x2d, 0x31, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x20,
+ 0x65, 0x6c, 0x73, 0x65, 0x20, 0x69, 0x66, 0x20, 0x28, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x69, 0x7a,
+ 0x65, 0x20, 0x3e, 0x20, 0x28, 0x31, 0x30, 0x32, 0x34, 0x20, 0x2a, 0x20, 0x31, 0x30, 0x32, 0x34,
+ 0x29, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65,
+ 0x74, 0x75, 0x72, 0x6e, 0x20, 0x2d, 0x31, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x69, 0x6c, 0x65,
+ 0x53, 0x69, 0x7a, 0x65, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x61, 0x73, 0x79, 0x6e,
+ 0x63, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x66, 0x72, 0x65,
+ 0x73, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x28, 0x29, 0x0d, 0x0a, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20,
+ 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x45, 0x6c,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x66, 0x69, 0x6c, 0x65, 0x22,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x66, 0x69, 0x6c, 0x65,
+ 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x21, 0x3d, 0x20, 0x22, 0x22, 0x29, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6e,
+ 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67,
+ 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x6e,
+ 0x61, 0x6d, 0x65, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x3d, 0x20, 0x66, 0x69, 0x6c,
+ 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5b, 0x30, 0x5d, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x2e,
+ 0x73, 0x75, 0x62, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x30, 0x2c, 0x20, 0x34, 0x30, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x28, 0x22, 0x2f, 0x61, 0x70,
+ 0x69, 0x2f, 0x66, 0x72, 0x65, 0x65, 0x73, 0x6c, 0x6f, 0x74, 0x73, 0x2e, 0x6a, 0x73, 0x6f, 0x6e,
+ 0x22, 0x29, 0x2e, 0x74, 0x68, 0x65, 0x6e, 0x28, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x72, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6a, 0x73, 0x6f,
+ 0x6e, 0x20, 0x3d, 0x20, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x2e, 0x6a, 0x73, 0x6f, 0x6e, 0x28, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x66, 0x72, 0x65, 0x65, 0x53, 0x6c,
+ 0x6f, 0x74, 0x73, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67,
+ 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x66,
+ 0x72, 0x65, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x73, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x72, 0x65, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x73, 0x2e, 0x74,
+ 0x65, 0x78, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x6a, 0x73, 0x6f,
+ 0x6e, 0x5b, 0x22, 0x66, 0x72, 0x65, 0x65, 0x73, 0x6c, 0x6f, 0x74, 0x73, 0x22, 0x5d, 0x3b, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74,
+ 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49,
+ 0x64, 0x28, 0x22, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x73, 0x6c, 0x6f, 0x74,
+ 0x73, 0x4e, 0x65, 0x65, 0x65, 0x64, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d,
+ 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79,
+ 0x49, 0x64, 0x28, 0x22, 0x73, 0x6c, 0x6f, 0x74, 0x73, 0x4e, 0x65, 0x65, 0x64, 0x65, 0x64, 0x22,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73,
+ 0x74, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x20, 0x3d, 0x20, 0x67, 0x65, 0x74,
+ 0x46, 0x69, 0x6c, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x28, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x66, 0x69, 0x6c, 0x65, 0x53,
+ 0x69, 0x7a, 0x65, 0x20, 0x3c, 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x73,
+ 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 0x64, 0x69, 0x73,
+ 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x2c, 0x20, 0x22, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
+ 0x64, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x73, 0x6c, 0x6f, 0x74, 0x73, 0x4e, 0x65, 0x65, 0x65, 0x64, 0x65, 0x64, 0x2e, 0x74,
+ 0x65, 0x78, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x22, 0x4e, 0x41,
+ 0x22, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x73, 0x6c, 0x6f, 0x74, 0x73, 0x4e,
+ 0x65, 0x65, 0x64, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x3d, 0x20, 0x66, 0x69, 0x6c,
+ 0x65, 0x53, 0x69, 0x7a, 0x65, 0x20, 0x2f, 0x20, 0x28, 0x32, 0x35, 0x36, 0x20, 0x2a, 0x20, 0x31,
+ 0x30, 0x32, 0x34, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x73, 0x6c, 0x6f, 0x74, 0x73, 0x4e, 0x65, 0x65, 0x65, 0x64, 0x65, 0x64, 0x2e,
+ 0x74, 0x65, 0x78, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x73, 0x6c,
+ 0x6f, 0x74, 0x73, 0x4e, 0x65, 0x65, 0x64, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20,
+ 0x28, 0x73, 0x6c, 0x6f, 0x74, 0x73, 0x4e, 0x65, 0x65, 0x64, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75,
+ 0x65, 0x20, 0x3e, 0x20, 0x6a, 0x73, 0x6f, 0x6e, 0x5b, 0x22, 0x66, 0x72, 0x65, 0x65, 0x73, 0x6c,
+ 0x6f, 0x74, 0x73, 0x22, 0x5d, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64,
+ 0x2e, 0x73, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 0x64,
+ 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x2c, 0x20, 0x22, 0x64, 0x69, 0x73, 0x61, 0x62,
+ 0x6c, 0x65, 0x64, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7d, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x75, 0x70,
+ 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69,
+ 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x7d, 0x29, 0x2e, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x65, 0x72, 0x72, 0x6f,
+ 0x72, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x2f, 0x2f, 0x20, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x65, 0x74, 0x4c,
+ 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x6c, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x64, 0x43, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x65, 0x64, 0x43, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x6c,
+ 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x54, 0x65, 0x78, 0x74, 0x20, 0x3d, 0x20, 0x64, 0x6f,
+ 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x6c, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x20, 0x28,
+ 0x6c, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x61, 0x73, 0x65, 0x20, 0x31, 0x3a, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x64, 0x43, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x54, 0x65, 0x78, 0x74, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65,
+ 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x22, 0x52, 0x65, 0x64, 0x22, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x61, 0x73, 0x65, 0x20, 0x32, 0x3a,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65,
+ 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x54, 0x65, 0x78, 0x74, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x43,
+ 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x22, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x22,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62,
+ 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63,
+ 0x61, 0x73, 0x65, 0x20, 0x33, 0x3a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x54, 0x65, 0x78, 0x74,
+ 0x2e, 0x74, 0x65, 0x78, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x22,
+ 0x59, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x22, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x61, 0x73, 0x65, 0x20, 0x34, 0x3a, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x64, 0x43, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x54, 0x65, 0x78, 0x74, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x43, 0x6f, 0x6e, 0x74,
+ 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x22, 0x42, 0x6c, 0x75, 0x65, 0x22, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x61, 0x73, 0x65, 0x20,
+ 0x35, 0x3a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x6c, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x54, 0x65, 0x78, 0x74, 0x2e, 0x74, 0x65, 0x78,
+ 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x22, 0x50, 0x75, 0x72, 0x70,
+ 0x6c, 0x65, 0x22, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x63, 0x61, 0x73, 0x65, 0x20, 0x36, 0x3a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x54,
+ 0x65, 0x78, 0x74, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20,
+ 0x3d, 0x20, 0x22, 0x54, 0x75, 0x72, 0x71, 0x75, 0x6f, 0x69, 0x73, 0x65, 0x22, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x72, 0x65, 0x61,
+ 0x6b, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x61, 0x73, 0x65,
+ 0x20, 0x37, 0x3a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x6c, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x54, 0x65, 0x78, 0x74, 0x2e, 0x74, 0x65,
+ 0x78, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x22, 0x57, 0x68, 0x69,
+ 0x74, 0x65, 0x22, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x3a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x54, 0x65, 0x78, 0x74, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
+ 0x20, 0x3d, 0x20, 0x22, 0x4f, 0x66, 0x66, 0x22, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d,
+ 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x66, 0x75, 0x6e,
+ 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x28, 0x29, 0x0d, 0x0a,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x70, 0x6c,
+ 0x6f, 0x61, 0x64, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67,
+ 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x75,
+ 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x75, 0x70,
+ 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x73, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74,
+ 0x65, 0x28, 0x22, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x2c, 0x20, 0x22, 0x64,
+ 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63,
+ 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74,
+ 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x73, 0x65, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69,
+ 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x2c,
+ 0x20, 0x22, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20,
+ 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x45, 0x6c,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x6e, 0x61, 0x6d, 0x65, 0x22,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x61, 0x72, 0x20, 0x64, 0x61,
+ 0x74, 0x61, 0x20, 0x3d, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x46, 0x6f, 0x72, 0x6d, 0x44, 0x61, 0x74,
+ 0x61, 0x28, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x61,
+ 0x70, 0x70, 0x65, 0x6e, 0x64, 0x28, 0x27, 0x66, 0x69, 0x6c, 0x65, 0x27, 0x2c, 0x20, 0x66, 0x69,
+ 0x6c, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5b, 0x30, 0x5d, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x28, 0x27,
+ 0x62, 0x6f, 0x64, 0x79, 0x27, 0x2c, 0x20, 0x22, 0x7b, 0x5c, 0x22, 0x6c, 0x65, 0x64, 0x43, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x5c, 0x22, 0x3a, 0x22, 0x20, 0x2b, 0x20, 0x6c, 0x65, 0x64, 0x43, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x20, 0x2b, 0x20, 0x22, 0x2c, 0x5c, 0x22, 0x62, 0x61,
+ 0x6e, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x5c, 0x22, 0x3a, 0x5c, 0x22, 0x22, 0x20, 0x2b, 0x20, 0x6e,
+ 0x61, 0x6d, 0x65, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x2b, 0x20, 0x22, 0x5c, 0x22, 0x7d,
+ 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x66,
+ 0x65, 0x74, 0x63, 0x68, 0x28, 0x22, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x75, 0x70, 0x6c, 0x6f, 0x61,
+ 0x64, 0x22, 0x2c, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d,
+ 0x65, 0x74, 0x68, 0x6f, 0x64, 0x3a, 0x20, 0x27, 0x50, 0x4f, 0x53, 0x54, 0x27, 0x2c, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x3a, 0x20, 0x64, 0x61,
+ 0x74, 0x61, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x2e, 0x74, 0x68, 0x65, 0x6e, 0x28,
+ 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x72, 0x65, 0x73, 0x70, 0x6f,
+ 0x6e, 0x73, 0x65, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x3d, 0x3d, 0x20, 0x32, 0x30,
+ 0x30, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x2e, 0x68, 0x72, 0x65, 0x66, 0x20, 0x3d, 0x20, 0x22, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78,
+ 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x7d, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x61, 0x69,
+ 0x6c, 0x75, 0x72, 0x65, 0x28, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x2e, 0x63, 0x61, 0x74, 0x63, 0x68,
+ 0x28, 0x28, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x28,
+ 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x28,
+ 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6c, 0x65, 0x72, 0x74, 0x28,
+ 0x22, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x2e, 0x22,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x75, 0x70, 0x6c, 0x6f,
+ 0x61, 0x64, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x65,
+ 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x75, 0x70,
+ 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x75, 0x70, 0x6c,
+ 0x6f, 0x61, 0x64, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62,
+ 0x75, 0x74, 0x65, 0x28, 0x22, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x3d,
+ 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x45, 0x6c, 0x65,
+ 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x72, 0x65, 0x6d, 0x6f,
+ 0x76, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x22, 0x64, 0x69, 0x73,
+ 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/index_html.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/index_html.h
new file mode 100644
index 0000000..107816e
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/index_html.h
@@ -0,0 +1,80 @@
+#pragma once
+
+const uint8_t index_html[] = {
+ 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x3c,
+ 0x68, 0x74, 0x6d, 0x6c, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x3d, 0x65, 0x6e, 0x20, 0x64, 0x61, 0x74,
+ 0x61, 0x2d, 0x74, 0x68, 0x65, 0x6d, 0x65, 0x3d, 0x64, 0x61, 0x72, 0x6b, 0x3e, 0x3c, 0x68, 0x65,
+ 0x61, 0x64, 0x3e, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74,
+ 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x20, 0x2f, 0x3e, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x6e,
+ 0x61, 0x6d, 0x65, 0x3d, 0x76, 0x69, 0x65, 0x77, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x63, 0x6f, 0x6e,
+ 0x74, 0x65, 0x6e, 0x74, 0x3d, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x64, 0x65, 0x76, 0x69,
+ 0x63, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61,
+ 0x6c, 0x2d, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x3d, 0x31, 0x2c, 0x20, 0x73, 0x68, 0x72, 0x69, 0x6e,
+ 0x6b, 0x2d, 0x74, 0x6f, 0x2d, 0x66, 0x69, 0x74, 0x3d, 0x6e, 0x6f, 0x22, 0x20, 0x2f, 0x3e, 0x3c,
+ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x50, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x4f, 0x53,
+ 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x3c, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x72, 0x65,
+ 0x6c, 0x3d, 0x69, 0x63, 0x6f, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x69, 0x6d, 0x61, 0x67,
+ 0x65, 0x2f, 0x78, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x66, 0x61,
+ 0x76, 0x69, 0x63, 0x6f, 0x6e, 0x2e, 0x69, 0x63, 0x6f, 0x20, 0x2f, 0x3e, 0x3c, 0x6c, 0x69, 0x6e,
+ 0x6b, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x70, 0x69, 0x63, 0x6f, 0x2e, 0x63, 0x73, 0x73, 0x20,
+ 0x72, 0x65, 0x6c, 0x3d, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x73, 0x68, 0x65, 0x65, 0x74, 0x20, 0x2f,
+ 0x3e, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x6d,
+ 0x61, 0x69, 0x6e, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
+ 0x6e, 0x65, 0x72, 0x3e, 0x3c, 0x66, 0x6f, 0x72, 0x6d, 0x3e, 0x3c, 0x68, 0x32, 0x3e, 0x50, 0x72,
+ 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x4f, 0x53, 0x3c, 0x2f, 0x68, 0x32, 0x3e, 0x3c, 0x64, 0x69,
+ 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x67, 0x72, 0x69, 0x64, 0x3e, 0x3c, 0x61, 0x20,
+ 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x68, 0x72, 0x65, 0x66,
+ 0x3d, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x4c, 0x61, 0x75,
+ 0x6e, 0x63, 0x68, 0x20, 0x42, 0x49, 0x4f, 0x53, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69,
+ 0x76, 0x3e, 0x3c, 0x62, 0x72, 0x20, 0x2f, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61,
+ 0x73, 0x73, 0x3d, 0x67, 0x72, 0x69, 0x64, 0x3e, 0x3c, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x3d,
+ 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x72, 0x65, 0x6d, 0x6f,
+ 0x76, 0x65, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x20, 0x42,
+ 0x49, 0x4f, 0x53, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x72,
+ 0x20, 0x2f, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x67, 0x72,
+ 0x69, 0x64, 0x3e, 0x3c, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f,
+ 0x6e, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x68, 0x74, 0x6d,
+ 0x6c, 0x3e, 0x46, 0x6c, 0x61, 0x73, 0x68, 0x20, 0x42, 0x49, 0x4f, 0x53, 0x3c, 0x2f, 0x61, 0x3e,
+ 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x72, 0x20, 0x2f, 0x3e, 0x3c, 0x64, 0x69, 0x76,
+ 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x67, 0x72, 0x69, 0x64, 0x3e, 0x3c, 0x61, 0x20, 0x72,
+ 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d,
+ 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x44,
+ 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69,
+ 0x76, 0x3e, 0x3c, 0x62, 0x72, 0x20, 0x2f, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61,
+ 0x73, 0x73, 0x3d, 0x67, 0x72, 0x69, 0x64, 0x3e, 0x3c, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x3d,
+ 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x63, 0x65, 0x72, 0x62,
+ 0x69, 0x6f, 0x73, 0x69, 0x6e, 0x69, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x43, 0x65, 0x72, 0x62,
+ 0x69, 0x6f, 0x73, 0x20, 0x49, 0x4e, 0x49, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76,
+ 0x3e, 0x3c, 0x62, 0x72, 0x20, 0x2f, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73,
+ 0x73, 0x3d, 0x67, 0x72, 0x69, 0x64, 0x3e, 0x3c, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62,
+ 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x6a, 0x61, 0x76, 0x61, 0x73,
+ 0x63, 0x72, 0x69, 0x70, 0x74, 0x3a, 0x76, 0x6f, 0x69, 0x64, 0x28, 0x30, 0x29, 0x20, 0x6f, 0x6e,
+ 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x3d, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x68, 0x6f, 0x74,
+ 0x28, 0x29, 0x3e, 0x54, 0x61, 0x6b, 0x65, 0x20, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x68,
+ 0x6f, 0x74, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x72, 0x20,
+ 0x2f, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x67, 0x72, 0x69,
+ 0x64, 0x3e, 0x3c, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e,
+ 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x76, 0x69, 0x65, 0x77,
+ 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x20, 0x56, 0x69, 0x65,
+ 0x77, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x72, 0x20, 0x2f,
+ 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x67, 0x72, 0x69, 0x64,
+ 0x3e, 0x3c, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3a,
+ 0x76, 0x6f, 0x69, 0x64, 0x28, 0x30, 0x29, 0x20, 0x6f, 0x6e, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x3d,
+ 0x72, 0x65, 0x62, 0x6f, 0x6f, 0x74, 0x28, 0x29, 0x3e, 0x52, 0x65, 0x62, 0x6f, 0x6f, 0x74, 0x3c,
+ 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x72, 0x20, 0x2f, 0x3e, 0x3c,
+ 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x67, 0x72, 0x69, 0x64, 0x3e, 0x3c,
+ 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x68, 0x72,
+ 0x65, 0x66, 0x3d, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3a, 0x76, 0x6f,
+ 0x69, 0x64, 0x28, 0x30, 0x29, 0x20, 0x6f, 0x6e, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x3d, 0x73, 0x68,
+ 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x28, 0x29, 0x3e, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77,
+ 0x6e, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x72, 0x20, 0x2f,
+ 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x3e, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67,
+ 0x68, 0x74, 0x20, 0x32, 0x30, 0x32, 0x34, 0x20, 0x2d, 0x20, 0x54, 0x65, 0x61, 0x6d, 0x20, 0x43,
+ 0x65, 0x72, 0x62, 0x69, 0x6f, 0x73, 0x20, 0x2b, 0x20, 0x54, 0x65, 0x61, 0x6d, 0x20, 0x52, 0x65,
+ 0x73, 0x75, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x3c, 0x2f, 0x62, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76,
+ 0x3e, 0x3c, 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x3e, 0x3c, 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x3e, 0x3c,
+ 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x73, 0x72, 0x63, 0x3d, 0x69, 0x6e, 0x64, 0x65, 0x78,
+ 0x2e, 0x6a, 0x73, 0x3e, 0x3c, 0x2f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3e, 0x3c, 0x2f, 0x62,
+ 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/index_js.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/index_js.h
new file mode 100644
index 0000000..eebe7de
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/index_js.h
@@ -0,0 +1,29 @@
+#pragma once
+
+const uint8_t index_js[] = {
+ 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73,
+ 0x63, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x68, 0x6f, 0x74, 0x28, 0x29, 0x7b, 0x61, 0x77, 0x61, 0x69,
+ 0x74, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x28, 0x22, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x63,
+ 0x72, 0x65, 0x65, 0x6e, 0x73, 0x68, 0x6f, 0x74, 0x22, 0x29, 0x2e, 0x63, 0x61, 0x74, 0x63, 0x68,
+ 0x28, 0x28, 0x29, 0x3d, 0x3e, 0x7b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x69, 0x6e,
+ 0x6e, 0x65, 0x72, 0x48, 0x54, 0x4d, 0x4c, 0x3d, 0x22, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x22, 0x7d, 0x29, 0x2e, 0x74,
+ 0x68, 0x65, 0x6e, 0x28, 0x6e, 0x3d, 0x3e, 0x6e, 0x2e, 0x62, 0x6c, 0x6f, 0x62, 0x28, 0x29, 0x29,
+ 0x2e, 0x74, 0x68, 0x65, 0x6e, 0x28, 0x6e, 0x3d, 0x3e, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x69, 0x3d,
+ 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x55, 0x52, 0x4c, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74,
+ 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x55, 0x52, 0x4c, 0x28, 0x6e, 0x29, 0x2c, 0x74, 0x3d,
+ 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45,
+ 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x61, 0x22, 0x29, 0x3b, 0x74, 0x2e, 0x68, 0x72,
+ 0x65, 0x66, 0x3d, 0x69, 0x3b, 0x74, 0x2e, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x3d,
+ 0x22, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x68, 0x6f, 0x74, 0x2e, 0x70, 0x6e, 0x67, 0x22,
+ 0x3b, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x62, 0x6f, 0x64, 0x79, 0x2e, 0x61,
+ 0x70, 0x70, 0x65, 0x6e, 0x64, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x28, 0x74, 0x29, 0x3b, 0x74, 0x2e,
+ 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x28, 0x29, 0x3b, 0x74, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65,
+ 0x28, 0x29, 0x7d, 0x29, 0x7d, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x62, 0x6f, 0x6f, 0x74, 0x28, 0x29, 0x7b, 0x61, 0x77, 0x61,
+ 0x69, 0x74, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x28, 0x22, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72,
+ 0x65, 0x62, 0x6f, 0x6f, 0x74, 0x22, 0x29, 0x7d, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x66, 0x75,
+ 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x28,
+ 0x29, 0x7b, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x28, 0x22, 0x2f,
+ 0x61, 0x70, 0x69, 0x2f, 0x73, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x22, 0x29, 0x7d
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/launch_html.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/launch_html.h
new file mode 100644
index 0000000..db0c976
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/launch_html.h
@@ -0,0 +1,42 @@
+#pragma once
+
+const uint8_t launch_html[] = {
+ 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x3c,
+ 0x68, 0x74, 0x6d, 0x6c, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x3d, 0x65, 0x6e, 0x20, 0x64, 0x61, 0x74,
+ 0x61, 0x2d, 0x74, 0x68, 0x65, 0x6d, 0x65, 0x3d, 0x64, 0x61, 0x72, 0x6b, 0x3e, 0x3c, 0x68, 0x65,
+ 0x61, 0x64, 0x3e, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74,
+ 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x20, 0x2f, 0x3e, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x6e,
+ 0x61, 0x6d, 0x65, 0x3d, 0x76, 0x69, 0x65, 0x77, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x63, 0x6f, 0x6e,
+ 0x74, 0x65, 0x6e, 0x74, 0x3d, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x64, 0x65, 0x76, 0x69,
+ 0x63, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61,
+ 0x6c, 0x2d, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x3d, 0x31, 0x2c, 0x20, 0x73, 0x68, 0x72, 0x69, 0x6e,
+ 0x6b, 0x2d, 0x74, 0x6f, 0x2d, 0x66, 0x69, 0x74, 0x3d, 0x6e, 0x6f, 0x22, 0x20, 0x2f, 0x3e, 0x3c,
+ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x50, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x4f, 0x53,
+ 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x3c, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x72, 0x65,
+ 0x6c, 0x3d, 0x69, 0x63, 0x6f, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x69, 0x6d, 0x61, 0x67,
+ 0x65, 0x2f, 0x78, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x66, 0x61,
+ 0x76, 0x69, 0x63, 0x6f, 0x6e, 0x2e, 0x69, 0x63, 0x6f, 0x20, 0x2f, 0x3e, 0x3c, 0x6c, 0x69, 0x6e,
+ 0x6b, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x70, 0x69, 0x63, 0x6f, 0x2e, 0x63, 0x73, 0x73, 0x20,
+ 0x72, 0x65, 0x6c, 0x3d, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x73, 0x68, 0x65, 0x65, 0x74, 0x20, 0x2f,
+ 0x3e, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x6d,
+ 0x61, 0x69, 0x6e, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
+ 0x6e, 0x65, 0x72, 0x3e, 0x3c, 0x66, 0x6f, 0x72, 0x6d, 0x3e, 0x3c, 0x68, 0x32, 0x3e, 0x50, 0x72,
+ 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x4f, 0x53, 0x3a, 0x20, 0x4c, 0x61, 0x75, 0x6e, 0x63, 0x68,
+ 0x20, 0x42, 0x49, 0x4f, 0x53, 0x3c, 0x2f, 0x68, 0x32, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x3e, 0x3c,
+ 0x73, 0x70, 0x61, 0x6e, 0x20, 0x69, 0x64, 0x3d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3e,
+ 0x50, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x57, 0x61, 0x69, 0x74, 0x2e, 0x2e, 0x2e, 0x3c, 0x2f,
+ 0x73, 0x70, 0x61, 0x6e, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x72, 0x20, 0x2f,
+ 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x67, 0x72, 0x69, 0x64,
+ 0x3e, 0x3c, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20,
+ 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3e,
+ 0x42, 0x61, 0x63, 0x6b, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62,
+ 0x72, 0x20, 0x2f, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x3e, 0x43, 0x6f, 0x70, 0x79,
+ 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x32, 0x30, 0x32, 0x34, 0x20, 0x2d, 0x20, 0x54, 0x65, 0x61,
+ 0x6d, 0x20, 0x43, 0x65, 0x72, 0x62, 0x69, 0x6f, 0x73, 0x20, 0x2b, 0x20, 0x54, 0x65, 0x61, 0x6d,
+ 0x20, 0x52, 0x65, 0x73, 0x75, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x3c, 0x2f, 0x62, 0x3e, 0x3c, 0x2f,
+ 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x3e, 0x3c, 0x2f, 0x6d, 0x61, 0x69,
+ 0x6e, 0x3e, 0x3c, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x73, 0x72, 0x63, 0x3d, 0x6c, 0x61,
+ 0x75, 0x6e, 0x63, 0x68, 0x2e, 0x6a, 0x73, 0x3e, 0x3c, 0x2f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+ 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/launch_js.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/launch_js.h
new file mode 100644
index 0000000..fa4bc2f
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/launch_js.h
@@ -0,0 +1,121 @@
+#pragma once
+
+const uint8_t launch_js[] = {
+ 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x6f, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x3d, 0x20,
+ 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x67, 0x65, 0x74, 0x42, 0x61, 0x6e, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x28, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x7d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x66,
+ 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x67, 0x65, 0x74, 0x42, 0x61, 0x6e, 0x6b, 0x49,
+ 0x6e, 0x66, 0x6f, 0x28, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x77, 0x61,
+ 0x69, 0x74, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x28, 0x22, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x62,
+ 0x61, 0x6e, 0x6b, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x6a, 0x73, 0x6f, 0x6e, 0x22, 0x29, 0x2e, 0x74,
+ 0x68, 0x65, 0x6e, 0x28, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6a, 0x73, 0x6f, 0x6e, 0x20, 0x3d, 0x20,
+ 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x6a,
+ 0x73, 0x6f, 0x6e, 0x28, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x6f, 0x64,
+ 0x79, 0x20, 0x3d, 0x20, 0x22, 0x22, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x6c, 0x65, 0x74, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x30, 0x3b,
+ 0x20, 0x69, 0x20, 0x3c, 0x20, 0x6a, 0x73, 0x6f, 0x6e, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68,
+ 0x3b, 0x20, 0x69, 0x2b, 0x2b, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x6a, 0x73, 0x6f, 0x6e, 0x5b, 0x69,
+ 0x5d, 0x2e, 0x73, 0x6c, 0x6f, 0x74, 0x73, 0x20, 0x3e, 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x6f, 0x64, 0x79, 0x20, 0x2b, 0x3d, 0x20, 0x22,
+ 0x3c, 0x70, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x5c, 0x22,
+ 0x67, 0x72, 0x69, 0x64, 0x5c, 0x22, 0x3e, 0x3c, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x5c,
+ 0x22, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5c, 0x22, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x5c,
+ 0x22, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3a, 0x76, 0x6f, 0x69, 0x64,
+ 0x28, 0x30, 0x29, 0x5c, 0x22, 0x20, 0x6f, 0x6e, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x3d, 0x5c, 0x22,
+ 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x42, 0x61, 0x6e, 0x6b, 0x28, 0x22, 0x20, 0x2b, 0x20, 0x6a,
+ 0x73, 0x6f, 0x6e, 0x5b, 0x69, 0x5d, 0x2e, 0x69, 0x64, 0x20, 0x2b, 0x20, 0x22, 0x29, 0x5c, 0x22,
+ 0x3e, 0x22, 0x20, 0x2b, 0x20, 0x6a, 0x73, 0x6f, 0x6e, 0x5b, 0x69, 0x5d, 0x2e, 0x6e, 0x61, 0x6d,
+ 0x65, 0x20, 0x2b, 0x20, 0x22, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c,
+ 0x2f, 0x70, 0x3e, 0x22, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
+ 0x42, 0x6f, 0x64, 0x79, 0x20, 0x2b, 0x3d, 0x20, 0x22, 0x3c, 0x70, 0x3e, 0x3c, 0x64, 0x69, 0x76,
+ 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x5c, 0x22, 0x67, 0x72, 0x69, 0x64, 0x5c, 0x22, 0x3e,
+ 0x3c, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x5c, 0x22, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e,
+ 0x5c, 0x22, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x5c, 0x22, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63,
+ 0x72, 0x69, 0x70, 0x74, 0x3a, 0x76, 0x6f, 0x69, 0x64, 0x28, 0x30, 0x29, 0x5c, 0x22, 0x20, 0x6f,
+ 0x6e, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x3d, 0x5c, 0x22, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x54,
+ 0x73, 0x6f, 0x70, 0x28, 0x29, 0x5c, 0x22, 0x3e, 0x54, 0x53, 0x4f, 0x50, 0x3c, 0x2f, 0x61, 0x3e,
+ 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x2f, 0x70, 0x3e, 0x22, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74,
+ 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67,
+ 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x63,
+ 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x69, 0x6e, 0x6e, 0x65, 0x72,
+ 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x6f,
+ 0x64, 0x79, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x2e, 0x63, 0x61, 0x74, 0x63,
+ 0x68, 0x28, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
+ 0x74, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x65, 0x74,
+ 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x63, 0x6f, 0x6e,
+ 0x74, 0x65, 0x6e, 0x74, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x48, 0x54,
+ 0x4d, 0x4c, 0x20, 0x3d, 0x20, 0x22, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20,
+ 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x22, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x66,
+ 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x42, 0x61,
+ 0x6e, 0x6b, 0x28, 0x69, 0x64, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61,
+ 0x77, 0x61, 0x69, 0x74, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x28, 0x22, 0x2f, 0x61, 0x70, 0x69,
+ 0x2f, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x62, 0x61, 0x6e, 0x6b, 0x3f, 0x22, 0x20, 0x2b, 0x20,
+ 0x69, 0x64, 0x29, 0x2e, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20,
+ 0x3d, 0x3e, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f,
+ 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x48, 0x54, 0x4d, 0x4c, 0x20,
+ 0x3d, 0x20, 0x22, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6e,
+ 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x22, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x2e, 0x74,
+ 0x68, 0x65, 0x6e, 0x28, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x3d, 0x3e, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x72,
+ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x3d,
+ 0x3d, 0x20, 0x32, 0x30, 0x30, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
+ 0x74, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x65, 0x74,
+ 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x63, 0x6f, 0x6e,
+ 0x74, 0x65, 0x6e, 0x74, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x69, 0x6e, 0x6e,
+ 0x65, 0x72, 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x3d, 0x20, 0x22, 0x4c, 0x61, 0x75, 0x6e, 0x63, 0x68,
+ 0x69, 0x6e, 0x67, 0x2e, 0x2e, 0x2e, 0x22, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x7d, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65,
+ 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x65,
+ 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x63, 0x6f,
+ 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x69, 0x6e,
+ 0x6e, 0x65, 0x72, 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x3d, 0x20, 0x22, 0x46, 0x61, 0x69, 0x6c, 0x65,
+ 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x2e, 0x22, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x66, 0x75,
+ 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x54, 0x73, 0x6f,
+ 0x70, 0x28, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x77, 0x61, 0x69, 0x74,
+ 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x28, 0x22, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x6c, 0x61, 0x75,
+ 0x6e, 0x63, 0x68, 0x74, 0x73, 0x6f, 0x70, 0x22, 0x29, 0x2e, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28,
+ 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x69, 0x6e, 0x6e, 0x65,
+ 0x72, 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x3d, 0x20, 0x22, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x22, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x7d, 0x29, 0x2e, 0x74, 0x68, 0x65, 0x6e, 0x28, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+ 0x73, 0x65, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x69, 0x66, 0x20, 0x28, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x73, 0x74,
+ 0x61, 0x74, 0x75, 0x73, 0x20, 0x3d, 0x3d, 0x20, 0x32, 0x30, 0x30, 0x29, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20,
+ 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49,
+ 0x64, 0x28, 0x22, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65,
+ 0x6e, 0x74, 0x2e, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x3d, 0x20, 0x22,
+ 0x4c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x2e, 0x2e, 0x2e, 0x22, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d,
+ 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79,
+ 0x49, 0x64, 0x28, 0x22, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74,
+ 0x65, 0x6e, 0x74, 0x2e, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x3d, 0x20,
+ 0x22, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x61, 0x75, 0x6e, 0x63,
+ 0x68, 0x2e, 0x22, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x3b, 0x0d, 0x0a, 0x7d
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/main_css.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/main_css.h
new file mode 100644
index 0000000..24333b0
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/main_css.h
@@ -0,0 +1,107 @@
+#pragma once
+
+const uint8_t main_css[] = {
+ 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x6f, 0x66, 0x66, 0x7b, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x23, 0x66, 0x66, 0x66, 0x3b, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x34, 0x30, 0x34, 0x30, 0x34, 0x30, 0x3b,
+ 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x30, 0x30,
+ 0x30, 0x7d, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x6f, 0x66, 0x66, 0x3a, 0x68, 0x6f,
+ 0x76, 0x65, 0x72, 0x2c, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x6f, 0x66, 0x66, 0x3a,
+ 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2c, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x6f, 0x66,
+ 0x66, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65,
+ 0x64, 0x6f, 0x66, 0x66, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x7b, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x23, 0x66, 0x66, 0x66, 0x3b, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x32, 0x30, 0x32, 0x30, 0x32, 0x30, 0x3b,
+ 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x30, 0x30,
+ 0x30, 0x7d, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x72, 0x65, 0x64, 0x7b, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x61, 0x61, 0x30, 0x61, 0x30,
+ 0x30, 0x3b, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23,
+ 0x30, 0x30, 0x30, 0x7d, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x72, 0x65, 0x64, 0x3a,
+ 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x72, 0x65,
+ 0x64, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2c, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64,
+ 0x72, 0x65, 0x64, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x2e, 0x62, 0x74, 0x6e, 0x2d,
+ 0x6c, 0x65, 0x64, 0x72, 0x65, 0x64, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x7b, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x64, 0x34, 0x30, 0x63, 0x30,
+ 0x30, 0x3b, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23,
+ 0x30, 0x30, 0x30, 0x7d, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x67, 0x72, 0x65, 0x65,
+ 0x6e, 0x7b, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x32,
+ 0x38, 0x39, 0x61, 0x32, 0x33, 0x3b, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x23, 0x30, 0x30, 0x30, 0x7d, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64,
+ 0x67, 0x72, 0x65, 0x65, 0x6e, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x2e, 0x62, 0x74, 0x6e,
+ 0x2d, 0x6c, 0x65, 0x64, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2c,
+ 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x3a, 0x61, 0x63,
+ 0x74, 0x69, 0x76, 0x65, 0x2c, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x67, 0x72, 0x65,
+ 0x65, 0x6e, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x7b, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x23, 0x30, 0x30, 0x30, 0x3b, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x33, 0x32, 0x63, 0x31, 0x32, 0x63, 0x3b, 0x62, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x30, 0x30, 0x30, 0x7d,
+ 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x79, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x7b, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x63, 0x63, 0x61, 0x34,
+ 0x30, 0x30, 0x3b, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x23, 0x30, 0x30, 0x30, 0x7d, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x79, 0x65, 0x6c,
+ 0x6c, 0x6f, 0x77, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c,
+ 0x65, 0x64, 0x79, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2c, 0x2e,
+ 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x79, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x3a, 0x61, 0x63,
+ 0x74, 0x69, 0x76, 0x65, 0x2c, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x79, 0x65, 0x6c,
+ 0x6c, 0x6f, 0x77, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x7b, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x66, 0x66, 0x63, 0x64, 0x30, 0x30, 0x3b, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x30, 0x30, 0x30,
+ 0x7d, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x62, 0x6c, 0x75, 0x65, 0x7b, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x34, 0x33, 0x35, 0x38, 0x63,
+ 0x63, 0x3b, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23,
+ 0x30, 0x30, 0x30, 0x7d, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x62, 0x6c, 0x75, 0x65,
+ 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x62,
+ 0x6c, 0x75, 0x65, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2c, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c,
+ 0x65, 0x64, 0x62, 0x6c, 0x75, 0x65, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x2e, 0x62,
+ 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x62, 0x6c, 0x75, 0x65, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76,
+ 0x65, 0x7b, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x66, 0x66, 0x66, 0x3b, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x35,
+ 0x32, 0x36, 0x65, 0x66, 0x66, 0x3b, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x23, 0x30, 0x30, 0x30, 0x7d, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64,
+ 0x70, 0x75, 0x72, 0x70, 0x6c, 0x65, 0x7b, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x30, 0x30,
+ 0x30, 0x3b, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x23, 0x36, 0x36, 0x33, 0x66, 0x61, 0x31, 0x3b, 0x62, 0x6f, 0x72, 0x64, 0x65,
+ 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x30, 0x30, 0x30, 0x7d, 0x2e, 0x62, 0x74,
+ 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x70, 0x75, 0x72, 0x70, 0x6c, 0x65, 0x3a, 0x68, 0x6f, 0x76, 0x65,
+ 0x72, 0x2c, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x70, 0x75, 0x72, 0x70, 0x6c, 0x65,
+ 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2c, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x70,
+ 0x75, 0x72, 0x70, 0x6c, 0x65, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x2e, 0x62, 0x74,
+ 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x70, 0x75, 0x72, 0x70, 0x6c, 0x65, 0x2e, 0x61, 0x63, 0x74, 0x69,
+ 0x76, 0x65, 0x7b, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x62, 0x61,
+ 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23,
+ 0x37, 0x66, 0x34, 0x66, 0x63, 0x39, 0x3b, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x30, 0x30, 0x30, 0x7d, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65,
+ 0x64, 0x74, 0x75, 0x72, 0x71, 0x75, 0x6f, 0x69, 0x73, 0x65, 0x7b, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x30, 0x30, 0x39, 0x36, 0x61, 0x65, 0x3b, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x30, 0x30, 0x30,
+ 0x7d, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x74, 0x75, 0x72, 0x71, 0x75, 0x6f, 0x69,
+ 0x73, 0x65, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65,
+ 0x64, 0x74, 0x75, 0x72, 0x71, 0x75, 0x6f, 0x69, 0x73, 0x65, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73,
+ 0x2c, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x74, 0x75, 0x72, 0x71, 0x75, 0x6f, 0x69,
+ 0x73, 0x65, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c,
+ 0x65, 0x64, 0x74, 0x75, 0x72, 0x71, 0x75, 0x6f, 0x69, 0x73, 0x65, 0x2e, 0x61, 0x63, 0x74, 0x69,
+ 0x76, 0x65, 0x7b, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x62, 0x61,
+ 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23,
+ 0x30, 0x30, 0x62, 0x63, 0x64, 0x39, 0x3b, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x30, 0x30, 0x30, 0x7d, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65,
+ 0x64, 0x77, 0x68, 0x69, 0x74, 0x65, 0x7b, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x30, 0x30,
+ 0x30, 0x3b, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x23, 0x63, 0x30, 0x63, 0x30, 0x63, 0x30, 0x3b, 0x62, 0x6f, 0x72, 0x64, 0x65,
+ 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x30, 0x30, 0x30, 0x7d, 0x2e, 0x62, 0x74,
+ 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x77, 0x68, 0x69, 0x74, 0x65, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72,
+ 0x2c, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x77, 0x68, 0x69, 0x74, 0x65, 0x3a, 0x66,
+ 0x6f, 0x63, 0x75, 0x73, 0x2c, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c, 0x65, 0x64, 0x77, 0x68, 0x69,
+ 0x74, 0x65, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x2e, 0x62, 0x74, 0x6e, 0x2d, 0x6c,
+ 0x65, 0x64, 0x77, 0x68, 0x69, 0x74, 0x65, 0x2e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x7b, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x23, 0x66, 0x30, 0x66, 0x30,
+ 0x66, 0x30, 0x3b, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x23, 0x30, 0x30, 0x30, 0x7d
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/pico_css.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/pico_css.h
new file mode 100644
index 0000000..94fe7e9
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/pico_css.h
@@ -0,0 +1,5726 @@
+#pragma once
+
+const uint8_t pico_css[] = {
+ 0x3a, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66,
+ 0x6f, 0x6e, 0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x20, 0x73, 0x79, 0x73, 0x74,
+ 0x65, 0x6d, 0x2d, 0x75, 0x69, 0x2c, 0x2d, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2d, 0x73, 0x79, 0x73,
+ 0x74, 0x65, 0x6d, 0x2c, 0x22, 0x53, 0x65, 0x67, 0x6f, 0x65, 0x20, 0x55, 0x49, 0x22, 0x2c, 0x22,
+ 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x6f, 0x22, 0x2c, 0x22, 0x55, 0x62, 0x75, 0x6e, 0x74, 0x75, 0x22,
+ 0x2c, 0x22, 0x43, 0x61, 0x6e, 0x74, 0x61, 0x72, 0x65, 0x6c, 0x6c, 0x22, 0x2c, 0x22, 0x4e, 0x6f,
+ 0x74, 0x6f, 0x20, 0x53, 0x61, 0x6e, 0x73, 0x22, 0x2c, 0x73, 0x61, 0x6e, 0x73, 0x2d, 0x73, 0x65,
+ 0x72, 0x69, 0x66, 0x2c, 0x22, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x20, 0x45, 0x6d, 0x6f, 0x6a, 0x69, 0x22, 0x2c, 0x22, 0x53, 0x65, 0x67, 0x6f, 0x65, 0x20, 0x55,
+ 0x49, 0x20, 0x45, 0x6d, 0x6f, 0x6a, 0x69, 0x22, 0x2c, 0x22, 0x53, 0x65, 0x67, 0x6f, 0x65, 0x20,
+ 0x55, 0x49, 0x20, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x22, 0x2c, 0x22, 0x4e, 0x6f, 0x74, 0x6f,
+ 0x20, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x45, 0x6d, 0x6f, 0x6a, 0x69, 0x22, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x3a, 0x20, 0x31, 0x2e, 0x35, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66,
+ 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x34, 0x30, 0x30, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a,
+ 0x65, 0x3a, 0x20, 0x31, 0x36, 0x70, 0x78, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x30,
+ 0x2e, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x70, 0x78,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65,
+ 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x33, 0x70, 0x78, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x31, 0x72, 0x65,
+ 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x74, 0x79, 0x70, 0x6f, 0x67, 0x72,
+ 0x61, 0x70, 0x68, 0x79, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72,
+ 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3a, 0x20, 0x31, 0x2e, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63,
+ 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3a, 0x20, 0x63, 0x61,
+ 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67,
+ 0x29, 0x20, 0x2a, 0x20, 0x32, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72,
+ 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73,
+ 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x67, 0x72, 0x69, 0x64, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72,
+ 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x67, 0x72, 0x69, 0x64, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f,
+ 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70,
+ 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3a, 0x20,
+ 0x30, 0x2e, 0x37, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61,
+ 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x3a,
+ 0x20, 0x31, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x61,
+ 0x76, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e,
+ 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3a, 0x20, 0x31, 0x72, 0x65, 0x6d,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x61, 0x76, 0x2d, 0x65, 0x6c, 0x65,
+ 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72,
+ 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x3a, 0x20, 0x30, 0x2e, 0x35, 0x72, 0x65, 0x6d, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6e, 0x61, 0x76, 0x2d, 0x6c, 0x69, 0x6e, 0x6b,
+ 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61,
+ 0x6c, 0x3a, 0x20, 0x30, 0x2e, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x2d, 0x6e, 0x61, 0x76, 0x2d, 0x6c, 0x69, 0x6e, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69,
+ 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x3a, 0x20, 0x30,
+ 0x2e, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f,
+ 0x72, 0x6d, 0x2d, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65,
+ 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74,
+ 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x30, 0x2e, 0x32,
+ 0x73, 0x20, 0x65, 0x61, 0x73, 0x65, 0x2d, 0x69, 0x6e, 0x2d, 0x6f, 0x75, 0x74, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x2d, 0x6f, 0x76, 0x65, 0x72,
+ 0x6c, 0x61, 0x79, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x64, 0x72, 0x6f, 0x70, 0x2d, 0x66, 0x69, 0x6c,
+ 0x74, 0x65, 0x72, 0x3a, 0x20, 0x62, 0x6c, 0x75, 0x72, 0x28, 0x30, 0x2e, 0x32, 0x35, 0x72, 0x65,
+ 0x6d, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20,
+ 0x28, 0x6d, 0x69, 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x35, 0x37, 0x36, 0x70, 0x78,
+ 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74,
+ 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31, 0x37, 0x70, 0x78, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20,
+ 0x28, 0x6d, 0x69, 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x37, 0x36, 0x38, 0x70, 0x78,
+ 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74,
+ 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31, 0x38, 0x70, 0x78, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20,
+ 0x28, 0x6d, 0x69, 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x39, 0x39, 0x32, 0x70, 0x78,
+ 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74,
+ 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31, 0x39, 0x70, 0x78, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20,
+ 0x28, 0x6d, 0x69, 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x31, 0x32, 0x30, 0x30, 0x70,
+ 0x78, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x72, 0x6f, 0x6f, 0x74, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x6e,
+ 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x32, 0x30, 0x70, 0x78, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61,
+ 0x20, 0x28, 0x6d, 0x69, 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x35, 0x37, 0x36, 0x70,
+ 0x78, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x3e,
+ 0x20, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x3e, 0x20,
+ 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2c, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x3e, 0x20, 0x6d,
+ 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2d,
+ 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c,
+ 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61,
+ 0x63, 0x69, 0x6e, 0x67, 0x29, 0x20, 0x2a, 0x20, 0x32, 0x2e, 0x35, 0x29, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61,
+ 0x20, 0x28, 0x6d, 0x69, 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x37, 0x36, 0x38, 0x70,
+ 0x78, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x3e,
+ 0x20, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x3e, 0x20,
+ 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2c, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x3e, 0x20, 0x6d,
+ 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2d,
+ 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c,
+ 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61,
+ 0x63, 0x69, 0x6e, 0x67, 0x29, 0x20, 0x2a, 0x20, 0x33, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20, 0x28,
+ 0x6d, 0x69, 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x39, 0x39, 0x32, 0x70, 0x78, 0x29,
+ 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x3e, 0x20, 0x66,
+ 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x3e, 0x20, 0x68, 0x65,
+ 0x61, 0x64, 0x65, 0x72, 0x2c, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x3e, 0x20, 0x6d, 0x61, 0x69,
+ 0x6e, 0x2c, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x70,
+ 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3a, 0x20,
+ 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69,
+ 0x6e, 0x67, 0x29, 0x20, 0x2a, 0x20, 0x33, 0x2e, 0x35, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20, 0x28,
+ 0x6d, 0x69, 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x31, 0x32, 0x30, 0x30, 0x70, 0x78,
+ 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x3e, 0x20,
+ 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x3e, 0x20, 0x68,
+ 0x65, 0x61, 0x64, 0x65, 0x72, 0x2c, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x3e, 0x20, 0x6d, 0x61,
+ 0x69, 0x6e, 0x2c, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x73,
+ 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3a,
+ 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63,
+ 0x69, 0x6e, 0x67, 0x29, 0x20, 0x2a, 0x20, 0x34, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d,
+ 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20, 0x28, 0x6d,
+ 0x69, 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x35, 0x37, 0x36, 0x70, 0x78, 0x29, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63,
+ 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f,
+ 0x6e, 0x74, 0x61, 0x6c, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x20, 0x2a, 0x20, 0x31, 0x2e, 0x32, 0x35,
+ 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40,
+ 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20, 0x28, 0x6d, 0x69, 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68,
+ 0x3a, 0x37, 0x36, 0x38, 0x70, 0x78, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61,
+ 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e,
+ 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x3a, 0x20, 0x63, 0x61,
+ 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67,
+ 0x29, 0x20, 0x2a, 0x20, 0x31, 0x2e, 0x35, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d,
+ 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20, 0x28, 0x6d, 0x69,
+ 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x39, 0x39, 0x32, 0x70, 0x78, 0x29, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+ 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e,
+ 0x74, 0x61, 0x6c, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x20, 0x2a, 0x20, 0x31, 0x2e, 0x37, 0x35, 0x29,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6d,
+ 0x65, 0x64, 0x69, 0x61, 0x20, 0x28, 0x6d, 0x69, 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a,
+ 0x31, 0x32, 0x30, 0x30, 0x70, 0x78, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61,
+ 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e,
+ 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x3a, 0x20, 0x63, 0x61,
+ 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67,
+ 0x29, 0x20, 0x2a, 0x20, 0x32, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x20, 0x3e, 0x20, 0x61, 0x72, 0x74,
+ 0x69, 0x63, 0x6c, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74,
+ 0x69, 0x63, 0x61, 0x6c, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x20, 0x2a, 0x20, 0x32, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x70, 0x61,
+ 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x0d,
+ 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20, 0x28, 0x6d, 0x69,
+ 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x35, 0x37, 0x36, 0x70, 0x78, 0x29, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x20, 0x3e, 0x20, 0x61,
+ 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e,
+ 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63,
+ 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x20,
+ 0x2a, 0x20, 0x32, 0x2e, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67,
+ 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x3a, 0x20, 0x63, 0x61, 0x6c,
+ 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29,
+ 0x20, 0x2a, 0x20, 0x31, 0x2e, 0x32, 0x35, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d,
+ 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20, 0x28, 0x6d, 0x69,
+ 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x37, 0x36, 0x38, 0x70, 0x78, 0x29, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x20, 0x3e, 0x20, 0x61,
+ 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e,
+ 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63,
+ 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x20,
+ 0x2a, 0x20, 0x33, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68,
+ 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x20, 0x2a,
+ 0x20, 0x31, 0x2e, 0x35, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x61, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x74, 0x65,
+ 0x78, 0x74, 0x2d, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x6e,
+ 0x6f, 0x6e, 0x65, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x2e,
+ 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x2c, 0x20, 0x61, 0x2e, 0x73, 0x65, 0x63, 0x6f,
+ 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x3a, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x65, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65,
+ 0x3a, 0x20, 0x30, 0x2e, 0x38, 0x37, 0x35, 0x65, 0x6d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x68, 0x31, 0x2c, 0x20, 0x68, 0x32, 0x2c, 0x20, 0x68, 0x33, 0x2c, 0x20, 0x68, 0x34, 0x2c, 0x20,
+ 0x68, 0x35, 0x2c, 0x20, 0x68, 0x36, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x37, 0x30, 0x30,
+ 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x68, 0x31, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x32, 0x72,
+ 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x74, 0x79, 0x70, 0x6f, 0x67,
+ 0x72, 0x61, 0x70, 0x68, 0x79, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65,
+ 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3a, 0x20, 0x33, 0x72, 0x65, 0x6d, 0x0d, 0x0a, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x68, 0x32, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66,
+ 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31, 0x2e, 0x37, 0x35, 0x72, 0x65,
+ 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x74, 0x79, 0x70, 0x6f, 0x67, 0x72,
+ 0x61, 0x70, 0x68, 0x79, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72,
+ 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3a, 0x20, 0x32, 0x2e, 0x36, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x0d,
+ 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x68, 0x33, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31, 0x2e, 0x35,
+ 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x74, 0x79, 0x70, 0x6f,
+ 0x67, 0x72, 0x61, 0x70, 0x68, 0x79, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76,
+ 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3a, 0x20, 0x32, 0x2e, 0x32, 0x35, 0x72, 0x65, 0x6d,
+ 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x68, 0x34, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31, 0x2e,
+ 0x32, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x74, 0x79,
+ 0x70, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x79, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67,
+ 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3a, 0x20, 0x31, 0x2e, 0x38, 0x37, 0x34,
+ 0x72, 0x65, 0x6d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x68, 0x35, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a,
+ 0x20, 0x31, 0x2e, 0x31, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x2d, 0x74, 0x79, 0x70, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x79, 0x2d, 0x73, 0x70, 0x61,
+ 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3a, 0x20, 0x31,
+ 0x2e, 0x36, 0x38, 0x37, 0x35, 0x72, 0x65, 0x6d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x5b,
+ 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x2c, 0x20,
+ 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x5d, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x64,
+ 0x74, 0x68, 0x3a, 0x20, 0x32, 0x70, 0x78, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78,
+ 0x5d, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x5d, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x33, 0x70, 0x78, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x66, 0x6f, 0x6f, 0x74, 0x20, 0x74, 0x64,
+ 0x2c, 0x20, 0x74, 0x66, 0x6f, 0x6f, 0x74, 0x20, 0x74, 0x68, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x61,
+ 0x64, 0x20, 0x74, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x61, 0x64, 0x20, 0x74, 0x68, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x77,
+ 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x33, 0x70, 0x78, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x74, 0x68, 0x65, 0x61, 0x64, 0x2c, 0x74, 0x66, 0x6f, 0x6f, 0x74,
+ 0x29, 0x20, 0x3e, 0x20, 0x2a, 0x20, 0x3e, 0x20, 0x74, 0x64, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x30,
+ 0x2e, 0x38, 0x37, 0x35, 0x65, 0x6d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x63, 0x6f, 0x64,
+ 0x65, 0x2c, 0x20, 0x6b, 0x62, 0x64, 0x2c, 0x20, 0x70, 0x72, 0x65, 0x2c, 0x20, 0x73, 0x61, 0x6d,
+ 0x70, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d,
+ 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x20, 0x22, 0x4d, 0x65, 0x6e, 0x6c, 0x6f, 0x22, 0x2c,
+ 0x22, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x61, 0x73, 0x22, 0x2c, 0x22, 0x52, 0x6f, 0x62, 0x6f,
+ 0x74, 0x6f, 0x20, 0x4d, 0x6f, 0x6e, 0x6f, 0x22, 0x2c, 0x22, 0x55, 0x62, 0x75, 0x6e, 0x74, 0x75,
+ 0x20, 0x4d, 0x6f, 0x6e, 0x6f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x2c, 0x22, 0x4e, 0x6f, 0x74,
+ 0x6f, 0x20, 0x4d, 0x6f, 0x6e, 0x6f, 0x22, 0x2c, 0x22, 0x4f, 0x78, 0x79, 0x67, 0x65, 0x6e, 0x20,
+ 0x4d, 0x6f, 0x6e, 0x6f, 0x22, 0x2c, 0x22, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x4d, 0x6f, 0x6e, 0x6f, 0x22, 0x2c, 0x6d, 0x6f, 0x6e, 0x6f, 0x73, 0x70, 0x61, 0x63,
+ 0x65, 0x2c, 0x22, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x45,
+ 0x6d, 0x6f, 0x6a, 0x69, 0x22, 0x2c, 0x22, 0x53, 0x65, 0x67, 0x6f, 0x65, 0x20, 0x55, 0x49, 0x20,
+ 0x45, 0x6d, 0x6f, 0x6a, 0x69, 0x22, 0x2c, 0x22, 0x53, 0x65, 0x67, 0x6f, 0x65, 0x20, 0x55, 0x49,
+ 0x20, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x22, 0x2c, 0x22, 0x4e, 0x6f, 0x74, 0x6f, 0x20, 0x43,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x45, 0x6d, 0x6f, 0x6a, 0x69, 0x22, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x6b, 0x62, 0x64, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66,
+ 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x62, 0x6f, 0x6c, 0x64,
+ 0x65, 0x72, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x3a, 0x72, 0x6f, 0x6f, 0x74, 0x3a, 0x6e,
+ 0x6f, 0x74, 0x28, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x68, 0x65, 0x6d, 0x65, 0x3d, 0x64,
+ 0x61, 0x72, 0x6b, 0x5d, 0x29, 0x2c, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x68, 0x65,
+ 0x6d, 0x65, 0x3d, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x66, 0x66, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35,
+ 0x2c, 0x20, 0x32, 0x30, 0x25, 0x2c, 0x20, 0x33, 0x32, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x68, 0x31, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73,
+ 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x33, 0x30, 0x25, 0x2c, 0x20, 0x31, 0x35, 0x25, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x68, 0x32, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x23, 0x32, 0x34, 0x33, 0x33, 0x33, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x68, 0x33, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c,
+ 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x32, 0x35, 0x25, 0x2c, 0x20, 0x32, 0x33, 0x25, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x68, 0x34, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x20, 0x23, 0x33, 0x37, 0x34, 0x39, 0x35, 0x36, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x2d, 0x68, 0x35, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28,
+ 0x32, 0x30, 0x35, 0x2c, 0x20, 0x32, 0x30, 0x25, 0x2c, 0x20, 0x33, 0x32, 0x25, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x68, 0x36, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x20, 0x23, 0x34, 0x64, 0x36, 0x30, 0x36, 0x64, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73,
+ 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x31, 0x30, 0x25, 0x2c, 0x20, 0x35, 0x30, 0x25, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c,
+ 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x32, 0x30, 0x25, 0x2c, 0x20, 0x39, 0x34, 0x25, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x3a,
+ 0x20, 0x68, 0x73, 0x6c, 0x28, 0x31, 0x39, 0x35, 0x2c, 0x20, 0x38, 0x35, 0x25, 0x2c, 0x20, 0x34,
+ 0x31, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d,
+ 0x61, 0x72, 0x79, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28, 0x31,
+ 0x39, 0x35, 0x2c, 0x20, 0x39, 0x30, 0x25, 0x2c, 0x20, 0x33, 0x32, 0x25, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x66, 0x6f,
+ 0x63, 0x75, 0x73, 0x3a, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x31, 0x36, 0x2c, 0x20, 0x31, 0x34,
+ 0x39, 0x2c, 0x20, 0x31, 0x39, 0x33, 0x2c, 0x20, 0x30, 0x2e, 0x31, 0x32, 0x35, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x69,
+ 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x3a, 0x20, 0x23, 0x66, 0x66, 0x66, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x3a, 0x20,
+ 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x31, 0x35, 0x25, 0x2c, 0x20, 0x34, 0x31,
+ 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e,
+ 0x64, 0x61, 0x72, 0x79, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28,
+ 0x32, 0x30, 0x35, 0x2c, 0x20, 0x32, 0x30, 0x25, 0x2c, 0x20, 0x33, 0x32, 0x25, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79,
+ 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x3a, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x38, 0x39, 0x2c,
+ 0x20, 0x31, 0x30, 0x37, 0x2c, 0x20, 0x31, 0x32, 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x31, 0x32, 0x35,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64,
+ 0x61, 0x72, 0x79, 0x2d, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x3a, 0x20, 0x23, 0x66, 0x66,
+ 0x66, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61,
+ 0x73, 0x74, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x33, 0x30, 0x25,
+ 0x2c, 0x20, 0x31, 0x35, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63,
+ 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x23,
+ 0x30, 0x30, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74,
+ 0x72, 0x61, 0x73, 0x74, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x3a, 0x20, 0x72, 0x67, 0x62, 0x61,
+ 0x28, 0x38, 0x39, 0x2c, 0x20, 0x31, 0x30, 0x37, 0x2c, 0x20, 0x31, 0x32, 0x30, 0x2c, 0x20, 0x30,
+ 0x2e, 0x31, 0x32, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f,
+ 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x2d, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x3a, 0x20,
+ 0x23, 0x66, 0x66, 0x66, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6d, 0x61, 0x72,
+ 0x6b, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x66, 0x66, 0x32, 0x63, 0x61, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x6d, 0x61, 0x72, 0x6b, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x23, 0x35, 0x34, 0x33, 0x61, 0x32, 0x36, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x69, 0x6e, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x33, 0x38, 0x38, 0x65,
+ 0x33, 0x63, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x64, 0x65, 0x6c, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x63, 0x36, 0x32, 0x38, 0x32, 0x38, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x71, 0x75, 0x6f, 0x74, 0x65,
+ 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65,
+ 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x2d, 0x66, 0x6f, 0x6f, 0x74,
+ 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2d, 0x62, 0x6f, 0x78, 0x2d,
+ 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x3a, 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x20, 0x72, 0x67,
+ 0x62, 0x61, 0x28, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2d, 0x68, 0x6f,
+ 0x76, 0x65, 0x72, 0x2d, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x3a, 0x20,
+ 0x30, 0x20, 0x30, 0x20, 0x30, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x30, 0x2c, 0x20, 0x30, 0x2c,
+ 0x20, 0x30, 0x2c, 0x20, 0x30, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66,
+ 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x63, 0x6b,
+ 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x74, 0x72,
+ 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c,
+ 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x31, 0x34, 0x25, 0x2c, 0x20, 0x36, 0x38, 0x25, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65,
+ 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x70, 0x6c,
+ 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d,
+ 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d,
+ 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72,
+ 0x69, 0x6d, 0x61, 0x72, 0x79, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66,
+ 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x66, 0x6f, 0x63, 0x75,
+ 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70,
+ 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2d, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2d, 0x62, 0x61, 0x63, 0x6b,
+ 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73,
+ 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x31, 0x38, 0x25, 0x2c, 0x20, 0x38, 0x36, 0x25, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2d, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c,
+ 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x31, 0x34, 0x25, 0x2c, 0x20, 0x36, 0x38, 0x25, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65,
+ 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2d, 0x6f, 0x70,
+ 0x61, 0x63, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x30, 0x2e, 0x35, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d,
+ 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x63, 0x36, 0x32, 0x38, 0x32, 0x38, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x76,
+ 0x65, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x23, 0x64, 0x33, 0x32, 0x66, 0x32, 0x66, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x69, 0x6e, 0x76,
+ 0x61, 0x6c, 0x69, 0x64, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x32, 0x31, 0x31, 0x2c, 0x20, 0x34, 0x37, 0x2c, 0x20,
+ 0x34, 0x37, 0x2c, 0x20, 0x30, 0x2e, 0x31, 0x32, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d,
+ 0x76, 0x61, 0x6c, 0x69, 0x64, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x33, 0x38, 0x38, 0x65, 0x33, 0x63, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74,
+ 0x2d, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x62, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x34, 0x33, 0x61,
+ 0x30, 0x34, 0x37, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d,
+ 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x2d, 0x66,
+ 0x6f, 0x63, 0x75, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x72, 0x67, 0x62, 0x61,
+ 0x28, 0x36, 0x37, 0x2c, 0x20, 0x31, 0x36, 0x30, 0x2c, 0x20, 0x37, 0x31, 0x2c, 0x20, 0x30, 0x2e,
+ 0x31, 0x32, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x73, 0x77, 0x69,
+ 0x74, 0x63, 0x68, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x31,
+ 0x36, 0x25, 0x2c, 0x20, 0x37, 0x37, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x69, 0x6e, 0x76,
+ 0x65, 0x72, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x73, 0x77,
+ 0x69, 0x74, 0x63, 0x68, 0x2d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x2d, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30,
+ 0x35, 0x2c, 0x20, 0x31, 0x38, 0x25, 0x2c, 0x20, 0x38, 0x36, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x76,
+ 0x65, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x31, 0x36, 0x25, 0x2c, 0x20, 0x37, 0x37,
+ 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65,
+ 0x2d, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x74, 0x68, 0x75, 0x6d, 0x62,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65,
+ 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x2d, 0x68, 0x6f, 0x76,
+ 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x74,
+ 0x68, 0x75, 0x6d, 0x62, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2d,
+ 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2d, 0x72, 0x6f, 0x77, 0x2d, 0x73, 0x74, 0x72, 0x69, 0x70, 0x70,
+ 0x65, 0x64, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x36, 0x66, 0x38, 0x66, 0x39, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28,
+ 0x32, 0x30, 0x35, 0x2c, 0x20, 0x32, 0x30, 0x25, 0x2c, 0x20, 0x39, 0x34, 0x25, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f,
+ 0x64, 0x65, 0x2d, 0x6b, 0x62, 0x64, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63,
+ 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2d, 0x6b, 0x62, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x2d,
+ 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2d, 0x74, 0x61, 0x67, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x20, 0x68, 0x73, 0x6c, 0x28, 0x33, 0x33, 0x30, 0x2c, 0x20, 0x34, 0x30, 0x25, 0x2c, 0x20, 0x35,
+ 0x30, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x64, 0x65,
+ 0x2d, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x20, 0x68, 0x73, 0x6c, 0x28, 0x31, 0x38, 0x35, 0x2c, 0x20, 0x34, 0x30, 0x25, 0x2c, 0x20, 0x34,
+ 0x30, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x64, 0x65,
+ 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73,
+ 0x6c, 0x28, 0x34, 0x30, 0x2c, 0x20, 0x32, 0x30, 0x25, 0x2c, 0x20, 0x35, 0x30, 0x25, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2d, 0x63, 0x6f, 0x6d,
+ 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28,
+ 0x32, 0x30, 0x35, 0x2c, 0x20, 0x31, 0x34, 0x25, 0x2c, 0x20, 0x36, 0x38, 0x25, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6f, 0x6e,
+ 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65,
+ 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6f, 0x6e, 0x2d, 0x63, 0x6c, 0x6f, 0x73, 0x65,
+ 0x2d, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6f, 0x6e, 0x2d, 0x6f,
+ 0x70, 0x65, 0x6e, 0x2d, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x61,
+ 0x72, 0x64, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x61, 0x72, 0x64, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x75,
+ 0x74, 0x65, 0x64, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x61, 0x72, 0x64, 0x2d, 0x62,
+ 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x3a, 0x20, 0x30, 0x2e, 0x30, 0x31, 0x34,
+ 0x35, 0x72, 0x65, 0x6d, 0x20, 0x30, 0x2e, 0x30, 0x32, 0x39, 0x72, 0x65, 0x6d, 0x20, 0x30, 0x2e,
+ 0x31, 0x37, 0x34, 0x72, 0x65, 0x6d, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x32, 0x37, 0x2c, 0x20,
+ 0x34, 0x30, 0x2c, 0x20, 0x35, 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x31, 0x36, 0x39, 0x38, 0x29,
+ 0x2c, 0x30, 0x2e, 0x30, 0x33, 0x33, 0x35, 0x72, 0x65, 0x6d, 0x20, 0x30, 0x2e, 0x30, 0x36, 0x37,
+ 0x72, 0x65, 0x6d, 0x20, 0x30, 0x2e, 0x34, 0x30, 0x32, 0x72, 0x65, 0x6d, 0x20, 0x72, 0x67, 0x62,
+ 0x61, 0x28, 0x32, 0x37, 0x2c, 0x20, 0x34, 0x30, 0x2c, 0x20, 0x35, 0x30, 0x2c, 0x20, 0x30, 0x2e,
+ 0x30, 0x32, 0x34, 0x29, 0x2c, 0x30, 0x2e, 0x30, 0x36, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x20, 0x30,
+ 0x2e, 0x31, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x20, 0x30, 0x2e, 0x37, 0x35, 0x72, 0x65, 0x6d, 0x20,
+ 0x72, 0x67, 0x62, 0x61, 0x28, 0x32, 0x37, 0x2c, 0x20, 0x34, 0x30, 0x2c, 0x20, 0x35, 0x30, 0x2c,
+ 0x20, 0x30, 0x2e, 0x30, 0x33, 0x29, 0x2c, 0x30, 0x2e, 0x31, 0x31, 0x32, 0x35, 0x72, 0x65, 0x6d,
+ 0x20, 0x30, 0x2e, 0x32, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x20, 0x31, 0x2e, 0x33, 0x35, 0x72, 0x65,
+ 0x6d, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x32, 0x37, 0x2c, 0x20, 0x34, 0x30, 0x2c, 0x20, 0x35,
+ 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x33, 0x36, 0x29, 0x2c, 0x30, 0x2e, 0x32, 0x30, 0x38, 0x35,
+ 0x72, 0x65, 0x6d, 0x20, 0x30, 0x2e, 0x34, 0x31, 0x37, 0x72, 0x65, 0x6d, 0x20, 0x32, 0x2e, 0x35,
+ 0x30, 0x32, 0x72, 0x65, 0x6d, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x32, 0x37, 0x2c, 0x20, 0x34,
+ 0x30, 0x2c, 0x20, 0x35, 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x34, 0x33, 0x30, 0x32, 0x29, 0x2c,
+ 0x30, 0x2e, 0x35, 0x72, 0x65, 0x6d, 0x20, 0x31, 0x72, 0x65, 0x6d, 0x20, 0x36, 0x72, 0x65, 0x6d,
+ 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x32, 0x37, 0x2c, 0x20, 0x34, 0x30, 0x2c, 0x20, 0x35, 0x30,
+ 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x36, 0x29, 0x2c, 0x30, 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x2e,
+ 0x30, 0x36, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x32, 0x37, 0x2c,
+ 0x20, 0x34, 0x30, 0x2c, 0x20, 0x35, 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x31, 0x35, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x61, 0x72, 0x64, 0x2d, 0x73, 0x65, 0x63,
+ 0x74, 0x69, 0x6f, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, 0x66, 0x62,
+ 0x66, 0x63, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x64, 0x72, 0x6f, 0x70, 0x64,
+ 0x6f, 0x77, 0x6e, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x62, 0x66, 0x62, 0x66, 0x63, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x64, 0x72, 0x6f, 0x70, 0x64, 0x6f, 0x77, 0x6e, 0x2d, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x65, 0x31,
+ 0x65, 0x36, 0x65, 0x62, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x64, 0x72, 0x6f,
+ 0x70, 0x64, 0x6f, 0x77, 0x6e, 0x2d, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77,
+ 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x61, 0x72, 0x64, 0x2d, 0x62, 0x6f, 0x78,
+ 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x64, 0x72, 0x6f, 0x70, 0x64, 0x6f, 0x77, 0x6e, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x64, 0x72, 0x6f, 0x70, 0x64, 0x6f, 0x77, 0x6e, 0x2d, 0x68,
+ 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20,
+ 0x32, 0x30, 0x25, 0x2c, 0x20, 0x39, 0x34, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x2d, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x2d, 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x2d,
+ 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x32, 0x31, 0x33, 0x2c, 0x20, 0x32, 0x32, 0x30, 0x2c,
+ 0x20, 0x32, 0x32, 0x36, 0x2c, 0x20, 0x30, 0x2e, 0x37, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2d, 0x62, 0x61, 0x63, 0x6b,
+ 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73,
+ 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x31, 0x38, 0x25, 0x2c, 0x20, 0x38, 0x36, 0x25, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73,
+ 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70,
+ 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x73, 0x70, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x2d,
+ 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x30, 0x2e, 0x35, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x2d, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74,
+ 0x72, 0x61, 0x73, 0x74, 0x2d, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x63, 0x68, 0x65, 0x63, 0x6b,
+ 0x62, 0x6f, 0x78, 0x3a, 0x20, 0x75, 0x72, 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69,
+ 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43,
+ 0x73, 0x76, 0x67, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a,
+ 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30,
+ 0x30, 0x2f, 0x73, 0x76, 0x67, 0x27, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34,
+ 0x27, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69,
+ 0x65, 0x77, 0x42, 0x6f, 0x78, 0x3d, 0x27, 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34,
+ 0x27, 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x3d, 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74,
+ 0x72, 0x6f, 0x6b, 0x65, 0x3d, 0x27, 0x72, 0x67, 0x62, 0x28, 0x32, 0x35, 0x35, 0x2c, 0x20, 0x32,
+ 0x35, 0x35, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65,
+ 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x34, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b,
+ 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63, 0x61, 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69,
+ 0x6e, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x70,
+ 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x3d, 0x27,
+ 0x32, 0x30, 0x20, 0x36, 0x20, 0x39, 0x20, 0x31, 0x37, 0x20, 0x34, 0x20, 0x31, 0x32, 0x27, 0x25,
+ 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33,
+ 0x45, 0x25, 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x63, 0x68, 0x65, 0x76, 0x72,
+ 0x6f, 0x6e, 0x3a, 0x20, 0x75, 0x72, 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d,
+ 0x61, 0x67, 0x65, 0x2f, 0x73, 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73,
+ 0x76, 0x67, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30,
+ 0x2f, 0x73, 0x76, 0x67, 0x27, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27,
+ 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65,
+ 0x77, 0x42, 0x6f, 0x78, 0x3d, 0x27, 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27,
+ 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x3d, 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72,
+ 0x6f, 0x6b, 0x65, 0x3d, 0x27, 0x72, 0x67, 0x62, 0x28, 0x36, 0x35, 0x2c, 0x20, 0x38, 0x34, 0x2c,
+ 0x20, 0x39, 0x38, 0x29, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77, 0x69, 0x64,
+ 0x74, 0x68, 0x3d, 0x27, 0x32, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69,
+ 0x6e, 0x65, 0x63, 0x61, 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20, 0x73, 0x74,
+ 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d, 0x27, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x70, 0x6f, 0x6c, 0x79, 0x6c,
+ 0x69, 0x6e, 0x65, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x3d, 0x27, 0x36, 0x20, 0x39, 0x20,
+ 0x31, 0x32, 0x20, 0x31, 0x35, 0x20, 0x31, 0x38, 0x20, 0x39, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33,
+ 0x43, 0x2f, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43,
+ 0x2f, 0x73, 0x76, 0x67, 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x63, 0x68, 0x65, 0x76, 0x72, 0x6f, 0x6e, 0x2d, 0x62,
+ 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x3a, 0x20, 0x75, 0x72, 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61,
+ 0x3a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25,
+ 0x33, 0x43, 0x73, 0x76, 0x67, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32,
+ 0x30, 0x30, 0x30, 0x2f, 0x73, 0x76, 0x67, 0x27, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27,
+ 0x32, 0x34, 0x27, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20,
+ 0x76, 0x69, 0x65, 0x77, 0x42, 0x6f, 0x78, 0x3d, 0x27, 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20,
+ 0x32, 0x34, 0x27, 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x3d, 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20,
+ 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x3d, 0x27, 0x72, 0x67, 0x62, 0x28, 0x32, 0x35, 0x35, 0x2c,
+ 0x20, 0x32, 0x35, 0x35, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f,
+ 0x6b, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x27, 0x20, 0x73, 0x74, 0x72,
+ 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63, 0x61, 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75,
+ 0x6e, 0x64, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a,
+ 0x6f, 0x69, 0x6e, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33,
+ 0x43, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73,
+ 0x3d, 0x27, 0x36, 0x20, 0x39, 0x20, 0x31, 0x32, 0x20, 0x31, 0x35, 0x20, 0x31, 0x38, 0x20, 0x39,
+ 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65,
+ 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x63, 0x68, 0x65,
+ 0x76, 0x72, 0x6f, 0x6e, 0x2d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2d, 0x69, 0x6e, 0x76, 0x65,
+ 0x72, 0x73, 0x65, 0x3a, 0x20, 0x75, 0x72, 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69,
+ 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43,
+ 0x73, 0x76, 0x67, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a,
+ 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30,
+ 0x30, 0x2f, 0x73, 0x76, 0x67, 0x27, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34,
+ 0x27, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69,
+ 0x65, 0x77, 0x42, 0x6f, 0x78, 0x3d, 0x27, 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34,
+ 0x27, 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x3d, 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74,
+ 0x72, 0x6f, 0x6b, 0x65, 0x3d, 0x27, 0x72, 0x67, 0x62, 0x28, 0x32, 0x35, 0x35, 0x2c, 0x20, 0x32,
+ 0x35, 0x35, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65,
+ 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b,
+ 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63, 0x61, 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69,
+ 0x6e, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x70,
+ 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x3d, 0x27,
+ 0x36, 0x20, 0x39, 0x20, 0x31, 0x32, 0x20, 0x31, 0x35, 0x20, 0x31, 0x38, 0x20, 0x39, 0x27, 0x25,
+ 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33,
+ 0x45, 0x25, 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x63, 0x6c, 0x6f, 0x73, 0x65,
+ 0x3a, 0x20, 0x75, 0x72, 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d, 0x61, 0x67,
+ 0x65, 0x2f, 0x73, 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73, 0x76, 0x67,
+ 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
+ 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30, 0x2f, 0x73,
+ 0x76, 0x67, 0x27, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x68,
+ 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65, 0x77, 0x42,
+ 0x6f, 0x78, 0x3d, 0x27, 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27, 0x20, 0x66,
+ 0x69, 0x6c, 0x6c, 0x3d, 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b,
+ 0x65, 0x3d, 0x27, 0x72, 0x67, 0x62, 0x28, 0x31, 0x31, 0x35, 0x2c, 0x20, 0x31, 0x33, 0x30, 0x2c,
+ 0x20, 0x31, 0x34, 0x30, 0x29, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77, 0x69,
+ 0x64, 0x74, 0x68, 0x3d, 0x27, 0x34, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c,
+ 0x69, 0x6e, 0x65, 0x63, 0x61, 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20, 0x73,
+ 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d, 0x27,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x6c, 0x69, 0x6e, 0x65,
+ 0x20, 0x78, 0x31, 0x3d, 0x27, 0x31, 0x38, 0x27, 0x20, 0x79, 0x31, 0x3d, 0x27, 0x36, 0x27, 0x20,
+ 0x78, 0x32, 0x3d, 0x27, 0x36, 0x27, 0x20, 0x79, 0x32, 0x3d, 0x27, 0x31, 0x38, 0x27, 0x25, 0x33,
+ 0x45, 0x25, 0x33, 0x43, 0x2f, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x6c,
+ 0x69, 0x6e, 0x65, 0x20, 0x78, 0x31, 0x3d, 0x27, 0x36, 0x27, 0x20, 0x79, 0x31, 0x3d, 0x27, 0x36,
+ 0x27, 0x20, 0x78, 0x32, 0x3d, 0x27, 0x31, 0x38, 0x27, 0x20, 0x79, 0x32, 0x3d, 0x27, 0x31, 0x38,
+ 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25,
+ 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x75,
+ 0x72, 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73,
+ 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73, 0x76, 0x67, 0x20, 0x78, 0x6d,
+ 0x6c, 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e,
+ 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30, 0x2f, 0x73, 0x76, 0x67, 0x27,
+ 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x68, 0x65, 0x69, 0x67,
+ 0x68, 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65, 0x77, 0x42, 0x6f, 0x78, 0x3d,
+ 0x27, 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27, 0x20, 0x66, 0x69, 0x6c, 0x6c,
+ 0x3d, 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x3d, 0x27,
+ 0x72, 0x67, 0x62, 0x28, 0x36, 0x35, 0x2c, 0x20, 0x38, 0x34, 0x2c, 0x20, 0x39, 0x38, 0x29, 0x27,
+ 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32,
+ 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63, 0x61, 0x70,
+ 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d,
+ 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27,
+ 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x72, 0x65, 0x63, 0x74, 0x20, 0x78, 0x3d, 0x27, 0x33, 0x27,
+ 0x20, 0x79, 0x3d, 0x27, 0x34, 0x27, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x31, 0x38,
+ 0x27, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x27, 0x31, 0x38, 0x27, 0x20, 0x72, 0x78,
+ 0x3d, 0x27, 0x32, 0x27, 0x20, 0x72, 0x79, 0x3d, 0x27, 0x32, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33,
+ 0x43, 0x2f, 0x72, 0x65, 0x63, 0x74, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x6c, 0x69, 0x6e, 0x65,
+ 0x20, 0x78, 0x31, 0x3d, 0x27, 0x31, 0x36, 0x27, 0x20, 0x79, 0x31, 0x3d, 0x27, 0x32, 0x27, 0x20,
+ 0x78, 0x32, 0x3d, 0x27, 0x31, 0x36, 0x27, 0x20, 0x79, 0x32, 0x3d, 0x27, 0x36, 0x27, 0x25, 0x33,
+ 0x45, 0x25, 0x33, 0x43, 0x2f, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x6c,
+ 0x69, 0x6e, 0x65, 0x20, 0x78, 0x31, 0x3d, 0x27, 0x38, 0x27, 0x20, 0x79, 0x31, 0x3d, 0x27, 0x32,
+ 0x27, 0x20, 0x78, 0x32, 0x3d, 0x27, 0x38, 0x27, 0x20, 0x79, 0x32, 0x3d, 0x27, 0x36, 0x27, 0x25,
+ 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43,
+ 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x78, 0x31, 0x3d, 0x27, 0x33, 0x27, 0x20, 0x79, 0x31, 0x3d, 0x27,
+ 0x31, 0x30, 0x27, 0x20, 0x78, 0x32, 0x3d, 0x27, 0x32, 0x31, 0x27, 0x20, 0x79, 0x32, 0x3d, 0x27,
+ 0x31, 0x30, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33,
+ 0x45, 0x25, 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c,
+ 0x69, 0x64, 0x3a, 0x20, 0x75, 0x72, 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d,
+ 0x61, 0x67, 0x65, 0x2f, 0x73, 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73,
+ 0x76, 0x67, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30,
+ 0x2f, 0x73, 0x76, 0x67, 0x27, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27,
+ 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65,
+ 0x77, 0x42, 0x6f, 0x78, 0x3d, 0x27, 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27,
+ 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x3d, 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72,
+ 0x6f, 0x6b, 0x65, 0x3d, 0x27, 0x72, 0x67, 0x62, 0x28, 0x31, 0x39, 0x38, 0x2c, 0x20, 0x34, 0x30,
+ 0x2c, 0x20, 0x34, 0x30, 0x29, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77, 0x69,
+ 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c,
+ 0x69, 0x6e, 0x65, 0x63, 0x61, 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20, 0x73,
+ 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d, 0x27,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x63, 0x69, 0x72, 0x63,
+ 0x6c, 0x65, 0x20, 0x63, 0x78, 0x3d, 0x27, 0x31, 0x32, 0x27, 0x20, 0x63, 0x79, 0x3d, 0x27, 0x31,
+ 0x32, 0x27, 0x20, 0x72, 0x3d, 0x27, 0x31, 0x30, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f,
+ 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x6c, 0x69, 0x6e, 0x65,
+ 0x20, 0x78, 0x31, 0x3d, 0x27, 0x31, 0x32, 0x27, 0x20, 0x79, 0x31, 0x3d, 0x27, 0x38, 0x27, 0x20,
+ 0x78, 0x32, 0x3d, 0x27, 0x31, 0x32, 0x27, 0x20, 0x79, 0x32, 0x3d, 0x27, 0x31, 0x32, 0x27, 0x25,
+ 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43,
+ 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x78, 0x31, 0x3d, 0x27, 0x31, 0x32, 0x27, 0x20, 0x79, 0x31, 0x3d,
+ 0x27, 0x31, 0x36, 0x27, 0x20, 0x78, 0x32, 0x3d, 0x27, 0x31, 0x32, 0x2e, 0x30, 0x31, 0x27, 0x20,
+ 0x79, 0x32, 0x3d, 0x27, 0x31, 0x36, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x6c, 0x69,
+ 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25, 0x33, 0x45, 0x22,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x6d,
+ 0x69, 0x6e, 0x75, 0x73, 0x3a, 0x20, 0x75, 0x72, 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a,
+ 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33,
+ 0x43, 0x73, 0x76, 0x67, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70,
+ 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30,
+ 0x30, 0x30, 0x2f, 0x73, 0x76, 0x67, 0x27, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32,
+ 0x34, 0x27, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76,
+ 0x69, 0x65, 0x77, 0x42, 0x6f, 0x78, 0x3d, 0x27, 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32,
+ 0x34, 0x27, 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x3d, 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73,
+ 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x3d, 0x27, 0x72, 0x67, 0x62, 0x28, 0x32, 0x35, 0x35, 0x2c, 0x20,
+ 0x32, 0x35, 0x35, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b,
+ 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x34, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f,
+ 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63, 0x61, 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f,
+ 0x69, 0x6e, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43,
+ 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x78, 0x31, 0x3d, 0x27, 0x35, 0x27, 0x20, 0x79, 0x31, 0x3d, 0x27,
+ 0x31, 0x32, 0x27, 0x20, 0x78, 0x32, 0x3d, 0x27, 0x31, 0x39, 0x27, 0x20, 0x79, 0x32, 0x3d, 0x27,
+ 0x31, 0x32, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33,
+ 0x45, 0x25, 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x73, 0x65, 0x61, 0x72, 0x63,
+ 0x68, 0x3a, 0x20, 0x75, 0x72, 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d, 0x61,
+ 0x67, 0x65, 0x2f, 0x73, 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73, 0x76,
+ 0x67, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
+ 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30, 0x2f,
+ 0x73, 0x76, 0x67, 0x27, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20,
+ 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65, 0x77,
+ 0x42, 0x6f, 0x78, 0x3d, 0x27, 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27, 0x20,
+ 0x66, 0x69, 0x6c, 0x6c, 0x3d, 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f,
+ 0x6b, 0x65, 0x3d, 0x27, 0x72, 0x67, 0x62, 0x28, 0x36, 0x35, 0x2c, 0x20, 0x38, 0x34, 0x2c, 0x20,
+ 0x39, 0x38, 0x29, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74,
+ 0x68, 0x3d, 0x27, 0x32, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e,
+ 0x65, 0x63, 0x61, 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20, 0x73, 0x74, 0x72,
+ 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d, 0x27, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65,
+ 0x20, 0x63, 0x78, 0x3d, 0x27, 0x31, 0x31, 0x27, 0x20, 0x63, 0x79, 0x3d, 0x27, 0x31, 0x31, 0x27,
+ 0x20, 0x72, 0x3d, 0x27, 0x38, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x63, 0x69, 0x72,
+ 0x63, 0x6c, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x78, 0x31,
+ 0x3d, 0x27, 0x32, 0x31, 0x27, 0x20, 0x79, 0x31, 0x3d, 0x27, 0x32, 0x31, 0x27, 0x20, 0x78, 0x32,
+ 0x3d, 0x27, 0x31, 0x36, 0x2e, 0x36, 0x35, 0x27, 0x20, 0x79, 0x32, 0x3d, 0x27, 0x31, 0x36, 0x2e,
+ 0x36, 0x35, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33,
+ 0x45, 0x25, 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x74, 0x69, 0x6d, 0x65, 0x3a,
+ 0x20, 0x75, 0x72, 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d, 0x61, 0x67, 0x65,
+ 0x2f, 0x73, 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73, 0x76, 0x67, 0x20,
+ 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77,
+ 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30, 0x2f, 0x73, 0x76,
+ 0x67, 0x27, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x68, 0x65,
+ 0x69, 0x67, 0x68, 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65, 0x77, 0x42, 0x6f,
+ 0x78, 0x3d, 0x27, 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27, 0x20, 0x66, 0x69,
+ 0x6c, 0x6c, 0x3d, 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65,
+ 0x3d, 0x27, 0x72, 0x67, 0x62, 0x28, 0x36, 0x35, 0x2c, 0x20, 0x38, 0x34, 0x2c, 0x20, 0x39, 0x38,
+ 0x29, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d,
+ 0x27, 0x32, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63,
+ 0x61, 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b,
+ 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x20, 0x63,
+ 0x78, 0x3d, 0x27, 0x31, 0x32, 0x27, 0x20, 0x63, 0x79, 0x3d, 0x27, 0x31, 0x32, 0x27, 0x20, 0x72,
+ 0x3d, 0x27, 0x31, 0x30, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x63, 0x69, 0x72, 0x63,
+ 0x6c, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65,
+ 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x3d, 0x27, 0x31, 0x32, 0x20, 0x36, 0x20, 0x31, 0x32,
+ 0x20, 0x31, 0x32, 0x20, 0x31, 0x36, 0x20, 0x31, 0x34, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43,
+ 0x2f, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f,
+ 0x73, 0x76, 0x67, 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x3a, 0x20, 0x75, 0x72, 0x6c,
+ 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x76, 0x67,
+ 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73, 0x76, 0x67, 0x20, 0x78, 0x6d, 0x6c, 0x6e,
+ 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33,
+ 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30, 0x2f, 0x73, 0x76, 0x67, 0x27, 0x20, 0x77,
+ 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74,
+ 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65, 0x77, 0x42, 0x6f, 0x78, 0x3d, 0x27, 0x30,
+ 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27, 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x3d, 0x27,
+ 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x3d, 0x27, 0x72, 0x67,
+ 0x62, 0x28, 0x35, 0x36, 0x2c, 0x20, 0x31, 0x34, 0x32, 0x2c, 0x20, 0x36, 0x30, 0x29, 0x27, 0x20,
+ 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x33, 0x27,
+ 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63, 0x61, 0x70, 0x3d,
+ 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c,
+ 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x25,
+ 0x33, 0x45, 0x25, 0x33, 0x43, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x6f,
+ 0x69, 0x6e, 0x74, 0x73, 0x3d, 0x27, 0x32, 0x30, 0x20, 0x36, 0x20, 0x39, 0x20, 0x31, 0x37, 0x20,
+ 0x34, 0x20, 0x31, 0x32, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x70, 0x6f, 0x6c, 0x79,
+ 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25, 0x33,
+ 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2d,
+ 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x3a, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x0d, 0x0a, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20,
+ 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x28, 0x70, 0x72, 0x65, 0x66,
+ 0x65, 0x72, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65,
+ 0x3a, 0x64, 0x61, 0x72, 0x6b, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x72,
+ 0x6f, 0x6f, 0x74, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x68,
+ 0x65, 0x6d, 0x65, 0x5d, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x31, 0x31, 0x31, 0x39, 0x31, 0x66, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x31, 0x36, 0x25, 0x2c, 0x20, 0x37, 0x37,
+ 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x68,
+ 0x31, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35,
+ 0x2c, 0x20, 0x32, 0x30, 0x25, 0x2c, 0x20, 0x39, 0x34, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x68, 0x32, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x20, 0x23, 0x65, 0x31, 0x65, 0x36, 0x65, 0x62, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x68, 0x33, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x31, 0x38, 0x25, 0x2c, 0x20, 0x38, 0x36,
+ 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x68,
+ 0x34, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x63, 0x38, 0x64, 0x31, 0x64, 0x38,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x68, 0x35, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20,
+ 0x31, 0x36, 0x25, 0x2c, 0x20, 0x37, 0x37, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x68, 0x36, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x23, 0x61, 0x66, 0x62, 0x62, 0x63, 0x34, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x20, 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x31, 0x30, 0x25, 0x2c, 0x20, 0x35,
+ 0x30, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x31, 0x66, 0x32, 0x64, 0x33, 0x38, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x3a,
+ 0x20, 0x68, 0x73, 0x6c, 0x28, 0x31, 0x39, 0x35, 0x2c, 0x20, 0x38, 0x35, 0x25, 0x2c, 0x20, 0x34,
+ 0x31, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x68,
+ 0x73, 0x6c, 0x28, 0x31, 0x39, 0x35, 0x2c, 0x20, 0x38, 0x30, 0x25, 0x2c, 0x20, 0x35, 0x30, 0x25,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x70, 0x72,
+ 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x3a, 0x20, 0x72, 0x67, 0x62,
+ 0x61, 0x28, 0x31, 0x36, 0x2c, 0x20, 0x31, 0x34, 0x39, 0x2c, 0x20, 0x31, 0x39, 0x33, 0x2c, 0x20,
+ 0x30, 0x2e, 0x32, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73,
+ 0x65, 0x3a, 0x20, 0x23, 0x66, 0x66, 0x66, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x3a, 0x20, 0x68,
+ 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x31, 0x35, 0x25, 0x2c, 0x20, 0x34, 0x31, 0x25,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x73, 0x65,
+ 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x68,
+ 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x31, 0x30, 0x25, 0x2c, 0x20, 0x35, 0x30, 0x25,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x73, 0x65,
+ 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x3a, 0x20, 0x72,
+ 0x67, 0x62, 0x61, 0x28, 0x31, 0x31, 0x35, 0x2c, 0x20, 0x31, 0x33, 0x30, 0x2c, 0x20, 0x31, 0x34,
+ 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x32, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2d, 0x69,
+ 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x3a, 0x20, 0x23, 0x66, 0x66, 0x66, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73,
+ 0x74, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x32, 0x30, 0x25, 0x2c,
+ 0x20, 0x39, 0x34, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72,
+ 0x3a, 0x20, 0x23, 0x66, 0x66, 0x66, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x2d, 0x66, 0x6f, 0x63, 0x75,
+ 0x73, 0x3a, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x31, 0x31, 0x35, 0x2c, 0x20, 0x31, 0x33, 0x30,
+ 0x2c, 0x20, 0x31, 0x34, 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x32, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73,
+ 0x74, 0x2d, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6d, 0x61, 0x72, 0x6b,
+ 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x23, 0x64, 0x31, 0x63, 0x32, 0x38, 0x34, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6d, 0x61, 0x72, 0x6b, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x23, 0x31, 0x31, 0x31, 0x39, 0x31, 0x66, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x69, 0x6e, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x20, 0x23, 0x33, 0x38, 0x38, 0x65, 0x33, 0x63, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x64, 0x65, 0x6c, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x20, 0x23, 0x63, 0x36, 0x32, 0x38, 0x32, 0x38, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x2d,
+ 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x2d, 0x66,
+ 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x75, 0x74, 0x74,
+ 0x6f, 0x6e, 0x2d, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x3a, 0x20, 0x30,
+ 0x20, 0x30, 0x20, 0x30, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20,
+ 0x30, 0x2c, 0x20, 0x30, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x2d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x62,
+ 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x3a, 0x20, 0x30, 0x20, 0x30, 0x20, 0x30,
+ 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f,
+ 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x31, 0x31,
+ 0x31, 0x39, 0x31, 0x66, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x33, 0x37, 0x34,
+ 0x39, 0x35, 0x36, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72,
+ 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68,
+ 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d,
+ 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d,
+ 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65,
+ 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d,
+ 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61,
+ 0x72, 0x79, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x66, 0x6f, 0x63,
+ 0x75, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d,
+ 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64,
+ 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x32, 0x35, 0x25, 0x2c,
+ 0x20, 0x32, 0x33, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x64,
+ 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x32,
+ 0x30, 0x25, 0x2c, 0x20, 0x33, 0x32, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x2d, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2d, 0x6f, 0x70, 0x61, 0x63, 0x69,
+ 0x74, 0x79, 0x3a, 0x20, 0x30, 0x2e, 0x35, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74,
+ 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x62, 0x37, 0x31, 0x63, 0x31, 0x63, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d,
+ 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x2d,
+ 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x63, 0x36, 0x32, 0x38, 0x32, 0x38, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x2d, 0x66, 0x6f,
+ 0x63, 0x75, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28,
+ 0x31, 0x39, 0x38, 0x2c, 0x20, 0x34, 0x30, 0x2c, 0x20, 0x34, 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x32,
+ 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66,
+ 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x76, 0x61, 0x6c, 0x69,
+ 0x64, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x23, 0x32, 0x65, 0x37, 0x64, 0x33, 0x32, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74,
+ 0x2d, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x62, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x33, 0x38, 0x38,
+ 0x65, 0x33, 0x63, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x76, 0x61, 0x6c,
+ 0x69, 0x64, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x72, 0x67, 0x62, 0x61, 0x28, 0x35, 0x36, 0x2c, 0x20, 0x31, 0x34, 0x32, 0x2c, 0x20, 0x36, 0x30,
+ 0x2c, 0x20, 0x30, 0x2e, 0x32, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x33, 0x37,
+ 0x34, 0x39, 0x35, 0x36, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x69, 0x6e, 0x76,
+ 0x65, 0x72, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x2d, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64,
+ 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x72, 0x61,
+ 0x6e, 0x67, 0x65, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x20, 0x23, 0x32, 0x34, 0x33, 0x33, 0x33, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x61, 0x63, 0x74, 0x69,
+ 0x76, 0x65, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x20, 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x32, 0x35, 0x25, 0x2c, 0x20, 0x32,
+ 0x33, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x2d, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x72, 0x61,
+ 0x6e, 0x67, 0x65, 0x2d, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x72, 0x61,
+ 0x6e, 0x67, 0x65, 0x2d, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65, 0x63,
+ 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d,
+ 0x74, 0x68, 0x75, 0x6d, 0x62, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72,
+ 0x79, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x74,
+ 0x61, 0x62, 0x6c, 0x65, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2d, 0x72,
+ 0x6f, 0x77, 0x2d, 0x73, 0x74, 0x72, 0x69, 0x70, 0x70, 0x65, 0x64, 0x2d, 0x62, 0x61, 0x63, 0x6b,
+ 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x72, 0x67,
+ 0x62, 0x61, 0x28, 0x31, 0x31, 0x35, 0x2c, 0x20, 0x31, 0x33, 0x30, 0x2c, 0x20, 0x31, 0x34, 0x30,
+ 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x31, 0x38, 0x32, 0x33,
+ 0x32, 0x63, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63,
+ 0x6f, 0x64, 0x65, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2d, 0x6b,
+ 0x62, 0x64, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72,
+ 0x61, 0x73, 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2d, 0x6b, 0x62, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x2d,
+ 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2d, 0x74, 0x61, 0x67, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28, 0x33, 0x33, 0x30, 0x2c, 0x20, 0x33, 0x30,
+ 0x25, 0x2c, 0x20, 0x35, 0x30, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2d, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74,
+ 0x79, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28, 0x31, 0x38, 0x35,
+ 0x2c, 0x20, 0x33, 0x30, 0x25, 0x2c, 0x20, 0x35, 0x30, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2d, 0x76, 0x61, 0x6c,
+ 0x75, 0x65, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28, 0x34, 0x30,
+ 0x2c, 0x20, 0x31, 0x30, 0x25, 0x2c, 0x20, 0x35, 0x30, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2d, 0x63, 0x6f, 0x6d,
+ 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x34, 0x64, 0x36,
+ 0x30, 0x36, 0x64, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6f, 0x6e, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x75,
+ 0x74, 0x65, 0x64, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x61, 0x63,
+ 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6f, 0x6e, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x73,
+ 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69,
+ 0x6f, 0x6e, 0x2d, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x2d, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6f, 0x6e, 0x2d, 0x6f, 0x70, 0x65, 0x6e, 0x2d,
+ 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x61,
+ 0x72, 0x64, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x31, 0x34, 0x31, 0x65, 0x32, 0x36, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x61, 0x72, 0x64, 0x2d, 0x62, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x63, 0x61, 0x72, 0x64, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x61, 0x72, 0x64, 0x2d, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68,
+ 0x61, 0x64, 0x6f, 0x77, 0x3a, 0x20, 0x30, 0x2e, 0x30, 0x31, 0x34, 0x35, 0x72, 0x65, 0x6d, 0x20,
+ 0x30, 0x2e, 0x30, 0x32, 0x39, 0x72, 0x65, 0x6d, 0x20, 0x30, 0x2e, 0x31, 0x37, 0x34, 0x72, 0x65,
+ 0x6d, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20,
+ 0x30, 0x2e, 0x30, 0x31, 0x36, 0x39, 0x38, 0x29, 0x2c, 0x30, 0x2e, 0x30, 0x33, 0x33, 0x35, 0x72,
+ 0x65, 0x6d, 0x20, 0x30, 0x2e, 0x30, 0x36, 0x37, 0x72, 0x65, 0x6d, 0x20, 0x30, 0x2e, 0x34, 0x30,
+ 0x32, 0x72, 0x65, 0x6d, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20,
+ 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x32, 0x34, 0x29, 0x2c, 0x30, 0x2e, 0x30, 0x36, 0x32, 0x35,
+ 0x72, 0x65, 0x6d, 0x20, 0x30, 0x2e, 0x31, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x20, 0x30, 0x2e, 0x37,
+ 0x35, 0x72, 0x65, 0x6d, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20,
+ 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x33, 0x29, 0x2c, 0x30, 0x2e, 0x31, 0x31, 0x32, 0x35, 0x72,
+ 0x65, 0x6d, 0x20, 0x30, 0x2e, 0x32, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x20, 0x31, 0x2e, 0x33, 0x35,
+ 0x72, 0x65, 0x6d, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30,
+ 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x33, 0x36, 0x29, 0x2c, 0x30, 0x2e, 0x32, 0x30, 0x38, 0x35, 0x72,
+ 0x65, 0x6d, 0x20, 0x30, 0x2e, 0x34, 0x31, 0x37, 0x72, 0x65, 0x6d, 0x20, 0x32, 0x2e, 0x35, 0x30,
+ 0x32, 0x72, 0x65, 0x6d, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20,
+ 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x34, 0x33, 0x30, 0x32, 0x29, 0x2c, 0x30, 0x2e, 0x35, 0x72,
+ 0x65, 0x6d, 0x20, 0x31, 0x72, 0x65, 0x6d, 0x20, 0x36, 0x72, 0x65, 0x6d, 0x20, 0x72, 0x67, 0x62,
+ 0x61, 0x28, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x36, 0x29,
+ 0x2c, 0x30, 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x2e, 0x30, 0x36, 0x32, 0x35, 0x72, 0x65, 0x6d,
+ 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30,
+ 0x2e, 0x30, 0x31, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x2d, 0x63, 0x61, 0x72, 0x64, 0x2d, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x6e, 0x69,
+ 0x6e, 0x67, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x31, 0x38, 0x32, 0x33, 0x32, 0x63, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x64, 0x72, 0x6f, 0x70, 0x64, 0x6f, 0x77,
+ 0x6e, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x33, 0x30, 0x25,
+ 0x2c, 0x20, 0x31, 0x35, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x64, 0x72, 0x6f, 0x70, 0x64, 0x6f, 0x77, 0x6e, 0x2d, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x32, 0x34, 0x33, 0x33, 0x33,
+ 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x64, 0x72,
+ 0x6f, 0x70, 0x64, 0x6f, 0x77, 0x6e, 0x2d, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f,
+ 0x77, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x61, 0x72, 0x64, 0x2d, 0x62, 0x6f,
+ 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x64, 0x72, 0x6f, 0x70, 0x64, 0x6f, 0x77, 0x6e, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x64,
+ 0x72, 0x6f, 0x70, 0x64, 0x6f, 0x77, 0x6e, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x62, 0x61,
+ 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x72, 0x67, 0x62, 0x61, 0x28, 0x33, 0x36, 0x2c, 0x20, 0x35, 0x31, 0x2c, 0x20, 0x36, 0x32, 0x2c,
+ 0x20, 0x30, 0x2e, 0x37, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x2d, 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79,
+ 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x33, 0x36, 0x2c, 0x20, 0x35, 0x31, 0x2c, 0x20,
+ 0x36, 0x32, 0x2c, 0x20, 0x30, 0x2e, 0x38, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2d, 0x62, 0x61,
+ 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x23, 0x32, 0x34, 0x33, 0x33, 0x33, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72,
+ 0x79, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6c,
+ 0x6f, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x73, 0x70, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x2d, 0x6f,
+ 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x30, 0x2e, 0x35, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x2d,
+ 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x74, 0x6f,
+ 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x2d, 0x69, 0x6e, 0x76, 0x65,
+ 0x72, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x3a, 0x20,
+ 0x75, 0x72, 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f,
+ 0x73, 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73, 0x76, 0x67, 0x20, 0x78,
+ 0x6d, 0x6c, 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77,
+ 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30, 0x2f, 0x73, 0x76, 0x67,
+ 0x27, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x68, 0x65, 0x69,
+ 0x67, 0x68, 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65, 0x77, 0x42, 0x6f, 0x78,
+ 0x3d, 0x27, 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27, 0x20, 0x66, 0x69, 0x6c,
+ 0x6c, 0x3d, 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x3d,
+ 0x27, 0x72, 0x67, 0x62, 0x28, 0x32, 0x35, 0x35, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x2c, 0x20, 0x32,
+ 0x35, 0x35, 0x29, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74,
+ 0x68, 0x3d, 0x27, 0x34, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e,
+ 0x65, 0x63, 0x61, 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20, 0x73, 0x74, 0x72,
+ 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d, 0x27, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69,
+ 0x6e, 0x65, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x3d, 0x27, 0x32, 0x30, 0x20, 0x36, 0x20,
+ 0x39, 0x20, 0x31, 0x37, 0x20, 0x34, 0x20, 0x31, 0x32, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43,
+ 0x2f, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f,
+ 0x73, 0x76, 0x67, 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x63, 0x68, 0x65, 0x76, 0x72, 0x6f,
+ 0x6e, 0x3a, 0x20, 0x75, 0x72, 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d, 0x61,
+ 0x67, 0x65, 0x2f, 0x73, 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73, 0x76,
+ 0x67, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
+ 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30, 0x2f,
+ 0x73, 0x76, 0x67, 0x27, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20,
+ 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65, 0x77,
+ 0x42, 0x6f, 0x78, 0x3d, 0x27, 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27, 0x20,
+ 0x66, 0x69, 0x6c, 0x6c, 0x3d, 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f,
+ 0x6b, 0x65, 0x3d, 0x27, 0x72, 0x67, 0x62, 0x28, 0x31, 0x36, 0x32, 0x2c, 0x20, 0x31, 0x37, 0x35,
+ 0x2c, 0x20, 0x31, 0x38, 0x35, 0x29, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77,
+ 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d,
+ 0x6c, 0x69, 0x6e, 0x65, 0x63, 0x61, 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20,
+ 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d,
+ 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x70, 0x6f, 0x6c,
+ 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x3d, 0x27, 0x36, 0x20,
+ 0x39, 0x20, 0x31, 0x32, 0x20, 0x31, 0x35, 0x20, 0x31, 0x38, 0x20, 0x39, 0x27, 0x25, 0x33, 0x45,
+ 0x25, 0x33, 0x43, 0x2f, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25,
+ 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x63, 0x68, 0x65,
+ 0x76, 0x72, 0x6f, 0x6e, 0x2d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x3a, 0x20, 0x75, 0x72, 0x6c,
+ 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x76, 0x67,
+ 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73, 0x76, 0x67, 0x20, 0x78, 0x6d, 0x6c, 0x6e,
+ 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33,
+ 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30, 0x2f, 0x73, 0x76, 0x67, 0x27, 0x20, 0x77,
+ 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74,
+ 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65, 0x77, 0x42, 0x6f, 0x78, 0x3d, 0x27, 0x30,
+ 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27, 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x3d, 0x27,
+ 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x3d, 0x27, 0x72, 0x67,
+ 0x62, 0x28, 0x32, 0x35, 0x35, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29,
+ 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27,
+ 0x32, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63, 0x61,
+ 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65,
+ 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x20,
+ 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x3d, 0x27, 0x36, 0x20, 0x39, 0x20, 0x31, 0x32, 0x20, 0x31,
+ 0x35, 0x20, 0x31, 0x38, 0x20, 0x39, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x70, 0x6f,
+ 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67,
+ 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x63, 0x68, 0x65, 0x76, 0x72, 0x6f, 0x6e, 0x2d, 0x62,
+ 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2d, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x3a, 0x20, 0x75,
+ 0x72, 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73,
+ 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73, 0x76, 0x67, 0x20, 0x78, 0x6d,
+ 0x6c, 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e,
+ 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30, 0x2f, 0x73, 0x76, 0x67, 0x27,
+ 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x68, 0x65, 0x69, 0x67,
+ 0x68, 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65, 0x77, 0x42, 0x6f, 0x78, 0x3d,
+ 0x27, 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27, 0x20, 0x66, 0x69, 0x6c, 0x6c,
+ 0x3d, 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x3d, 0x27,
+ 0x72, 0x67, 0x62, 0x28, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x29, 0x27, 0x20, 0x73, 0x74,
+ 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x27, 0x20, 0x73,
+ 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63, 0x61, 0x70, 0x3d, 0x27, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e,
+ 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x25, 0x33, 0x45,
+ 0x25, 0x33, 0x43, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x6f, 0x69, 0x6e,
+ 0x74, 0x73, 0x3d, 0x27, 0x36, 0x20, 0x39, 0x20, 0x31, 0x32, 0x20, 0x31, 0x35, 0x20, 0x31, 0x38,
+ 0x20, 0x39, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69,
+ 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25, 0x33, 0x45, 0x22,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x69, 0x63,
+ 0x6f, 0x6e, 0x2d, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x3a, 0x20, 0x75, 0x72, 0x6c, 0x28, 0x22, 0x64,
+ 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x76, 0x67, 0x2b, 0x78, 0x6d,
+ 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73, 0x76, 0x67, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3d, 0x27,
+ 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72,
+ 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30, 0x2f, 0x73, 0x76, 0x67, 0x27, 0x20, 0x77, 0x69, 0x64, 0x74,
+ 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x27, 0x32,
+ 0x34, 0x27, 0x20, 0x76, 0x69, 0x65, 0x77, 0x42, 0x6f, 0x78, 0x3d, 0x27, 0x30, 0x20, 0x30, 0x20,
+ 0x32, 0x34, 0x20, 0x32, 0x34, 0x27, 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x3d, 0x27, 0x6e, 0x6f, 0x6e,
+ 0x65, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x3d, 0x27, 0x72, 0x67, 0x62, 0x28, 0x31,
+ 0x31, 0x35, 0x2c, 0x20, 0x31, 0x33, 0x30, 0x2c, 0x20, 0x31, 0x34, 0x30, 0x29, 0x27, 0x20, 0x73,
+ 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x34, 0x27, 0x20,
+ 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63, 0x61, 0x70, 0x3d, 0x27,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69,
+ 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x25, 0x33,
+ 0x45, 0x25, 0x33, 0x43, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x78, 0x31, 0x3d, 0x27, 0x31, 0x38, 0x27,
+ 0x20, 0x79, 0x31, 0x3d, 0x27, 0x36, 0x27, 0x20, 0x78, 0x32, 0x3d, 0x27, 0x36, 0x27, 0x20, 0x79,
+ 0x32, 0x3d, 0x27, 0x31, 0x38, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x6c, 0x69, 0x6e,
+ 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x78, 0x31, 0x3d, 0x27,
+ 0x36, 0x27, 0x20, 0x79, 0x31, 0x3d, 0x27, 0x36, 0x27, 0x20, 0x78, 0x32, 0x3d, 0x27, 0x31, 0x38,
+ 0x27, 0x20, 0x79, 0x32, 0x3d, 0x27, 0x31, 0x38, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f,
+ 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25, 0x33,
+ 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x75, 0x72, 0x6c, 0x28, 0x22,
+ 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x76, 0x67, 0x2b, 0x78,
+ 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73, 0x76, 0x67, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3d,
+ 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f,
+ 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30, 0x2f, 0x73, 0x76, 0x67, 0x27, 0x20, 0x77, 0x69, 0x64,
+ 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x27,
+ 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65, 0x77, 0x42, 0x6f, 0x78, 0x3d, 0x27, 0x30, 0x20, 0x30,
+ 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27, 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x3d, 0x27, 0x6e, 0x6f,
+ 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x3d, 0x27, 0x72, 0x67, 0x62, 0x28,
+ 0x31, 0x36, 0x32, 0x2c, 0x20, 0x31, 0x37, 0x35, 0x2c, 0x20, 0x31, 0x38, 0x35, 0x29, 0x27, 0x20,
+ 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x27,
+ 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63, 0x61, 0x70, 0x3d,
+ 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c,
+ 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x25,
+ 0x33, 0x45, 0x25, 0x33, 0x43, 0x72, 0x65, 0x63, 0x74, 0x20, 0x78, 0x3d, 0x27, 0x33, 0x27, 0x20,
+ 0x79, 0x3d, 0x27, 0x34, 0x27, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x31, 0x38, 0x27,
+ 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x27, 0x31, 0x38, 0x27, 0x20, 0x72, 0x78, 0x3d,
+ 0x27, 0x32, 0x27, 0x20, 0x72, 0x79, 0x3d, 0x27, 0x32, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43,
+ 0x2f, 0x72, 0x65, 0x63, 0x74, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x6c, 0x69, 0x6e, 0x65, 0x20,
+ 0x78, 0x31, 0x3d, 0x27, 0x31, 0x36, 0x27, 0x20, 0x79, 0x31, 0x3d, 0x27, 0x32, 0x27, 0x20, 0x78,
+ 0x32, 0x3d, 0x27, 0x31, 0x36, 0x27, 0x20, 0x79, 0x32, 0x3d, 0x27, 0x36, 0x27, 0x25, 0x33, 0x45,
+ 0x25, 0x33, 0x43, 0x2f, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x6c, 0x69,
+ 0x6e, 0x65, 0x20, 0x78, 0x31, 0x3d, 0x27, 0x38, 0x27, 0x20, 0x79, 0x31, 0x3d, 0x27, 0x32, 0x27,
+ 0x20, 0x78, 0x32, 0x3d, 0x27, 0x38, 0x27, 0x20, 0x79, 0x32, 0x3d, 0x27, 0x36, 0x27, 0x25, 0x33,
+ 0x45, 0x25, 0x33, 0x43, 0x2f, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x6c,
+ 0x69, 0x6e, 0x65, 0x20, 0x78, 0x31, 0x3d, 0x27, 0x33, 0x27, 0x20, 0x79, 0x31, 0x3d, 0x27, 0x31,
+ 0x30, 0x27, 0x20, 0x78, 0x32, 0x3d, 0x27, 0x32, 0x31, 0x27, 0x20, 0x79, 0x32, 0x3d, 0x27, 0x31,
+ 0x30, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45,
+ 0x25, 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x69, 0x6e,
+ 0x76, 0x61, 0x6c, 0x69, 0x64, 0x3a, 0x20, 0x75, 0x72, 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61,
+ 0x3a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25,
+ 0x33, 0x43, 0x73, 0x76, 0x67, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32,
+ 0x30, 0x30, 0x30, 0x2f, 0x73, 0x76, 0x67, 0x27, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27,
+ 0x32, 0x34, 0x27, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20,
+ 0x76, 0x69, 0x65, 0x77, 0x42, 0x6f, 0x78, 0x3d, 0x27, 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20,
+ 0x32, 0x34, 0x27, 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x3d, 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20,
+ 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x3d, 0x27, 0x72, 0x67, 0x62, 0x28, 0x31, 0x38, 0x33, 0x2c,
+ 0x20, 0x32, 0x38, 0x2c, 0x20, 0x32, 0x38, 0x29, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65,
+ 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b,
+ 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63, 0x61, 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69,
+ 0x6e, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x63,
+ 0x69, 0x72, 0x63, 0x6c, 0x65, 0x20, 0x63, 0x78, 0x3d, 0x27, 0x31, 0x32, 0x27, 0x20, 0x63, 0x79,
+ 0x3d, 0x27, 0x31, 0x32, 0x27, 0x20, 0x72, 0x3d, 0x27, 0x31, 0x30, 0x27, 0x25, 0x33, 0x45, 0x25,
+ 0x33, 0x43, 0x2f, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x6c,
+ 0x69, 0x6e, 0x65, 0x20, 0x78, 0x31, 0x3d, 0x27, 0x31, 0x32, 0x27, 0x20, 0x79, 0x31, 0x3d, 0x27,
+ 0x38, 0x27, 0x20, 0x78, 0x32, 0x3d, 0x27, 0x31, 0x32, 0x27, 0x20, 0x79, 0x32, 0x3d, 0x27, 0x31,
+ 0x32, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45,
+ 0x25, 0x33, 0x43, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x78, 0x31, 0x3d, 0x27, 0x31, 0x32, 0x27, 0x20,
+ 0x79, 0x31, 0x3d, 0x27, 0x31, 0x36, 0x27, 0x20, 0x78, 0x32, 0x3d, 0x27, 0x31, 0x32, 0x2e, 0x30,
+ 0x31, 0x27, 0x20, 0x79, 0x32, 0x3d, 0x27, 0x31, 0x36, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43,
+ 0x2f, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25,
+ 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x6d, 0x69, 0x6e, 0x75, 0x73, 0x3a, 0x20, 0x75, 0x72, 0x6c,
+ 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x76, 0x67,
+ 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73, 0x76, 0x67, 0x20, 0x78, 0x6d, 0x6c, 0x6e,
+ 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33,
+ 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30, 0x2f, 0x73, 0x76, 0x67, 0x27, 0x20, 0x77,
+ 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74,
+ 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65, 0x77, 0x42, 0x6f, 0x78, 0x3d, 0x27, 0x30,
+ 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27, 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x3d, 0x27,
+ 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x3d, 0x27, 0x72, 0x67,
+ 0x62, 0x28, 0x32, 0x35, 0x35, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29,
+ 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27,
+ 0x34, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63, 0x61,
+ 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65,
+ 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x78, 0x31, 0x3d, 0x27,
+ 0x35, 0x27, 0x20, 0x79, 0x31, 0x3d, 0x27, 0x31, 0x32, 0x27, 0x20, 0x78, 0x32, 0x3d, 0x27, 0x31,
+ 0x39, 0x27, 0x20, 0x79, 0x32, 0x3d, 0x27, 0x31, 0x32, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43,
+ 0x2f, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25,
+ 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x3a, 0x20, 0x75, 0x72,
+ 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x76,
+ 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73, 0x76, 0x67, 0x20, 0x78, 0x6d, 0x6c,
+ 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77,
+ 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30, 0x2f, 0x73, 0x76, 0x67, 0x27, 0x20,
+ 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65, 0x77, 0x42, 0x6f, 0x78, 0x3d, 0x27,
+ 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27, 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x3d,
+ 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x3d, 0x27, 0x72,
+ 0x67, 0x62, 0x28, 0x31, 0x36, 0x32, 0x2c, 0x20, 0x31, 0x37, 0x35, 0x2c, 0x20, 0x31, 0x38, 0x35,
+ 0x29, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d,
+ 0x27, 0x32, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63,
+ 0x61, 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b,
+ 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x20, 0x63,
+ 0x78, 0x3d, 0x27, 0x31, 0x31, 0x27, 0x20, 0x63, 0x79, 0x3d, 0x27, 0x31, 0x31, 0x27, 0x20, 0x72,
+ 0x3d, 0x27, 0x38, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x63, 0x69, 0x72, 0x63, 0x6c,
+ 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x78, 0x31, 0x3d, 0x27,
+ 0x32, 0x31, 0x27, 0x20, 0x79, 0x31, 0x3d, 0x27, 0x32, 0x31, 0x27, 0x20, 0x78, 0x32, 0x3d, 0x27,
+ 0x31, 0x36, 0x2e, 0x36, 0x35, 0x27, 0x20, 0x79, 0x32, 0x3d, 0x27, 0x31, 0x36, 0x2e, 0x36, 0x35,
+ 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25,
+ 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x74, 0x69, 0x6d,
+ 0x65, 0x3a, 0x20, 0x75, 0x72, 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d, 0x61,
+ 0x67, 0x65, 0x2f, 0x73, 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73, 0x76,
+ 0x67, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
+ 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30, 0x2f,
+ 0x73, 0x76, 0x67, 0x27, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20,
+ 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65, 0x77,
+ 0x42, 0x6f, 0x78, 0x3d, 0x27, 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27, 0x20,
+ 0x66, 0x69, 0x6c, 0x6c, 0x3d, 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f,
+ 0x6b, 0x65, 0x3d, 0x27, 0x72, 0x67, 0x62, 0x28, 0x31, 0x36, 0x32, 0x2c, 0x20, 0x31, 0x37, 0x35,
+ 0x2c, 0x20, 0x31, 0x38, 0x35, 0x29, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77,
+ 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d,
+ 0x6c, 0x69, 0x6e, 0x65, 0x63, 0x61, 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20,
+ 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d,
+ 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x63, 0x69, 0x72,
+ 0x63, 0x6c, 0x65, 0x20, 0x63, 0x78, 0x3d, 0x27, 0x31, 0x32, 0x27, 0x20, 0x63, 0x79, 0x3d, 0x27,
+ 0x31, 0x32, 0x27, 0x20, 0x72, 0x3d, 0x27, 0x31, 0x30, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43,
+ 0x2f, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x70, 0x6f, 0x6c,
+ 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x3d, 0x27, 0x31, 0x32,
+ 0x20, 0x36, 0x20, 0x31, 0x32, 0x20, 0x31, 0x32, 0x20, 0x31, 0x36, 0x20, 0x31, 0x34, 0x27, 0x25,
+ 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33,
+ 0x45, 0x25, 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x76,
+ 0x61, 0x6c, 0x69, 0x64, 0x3a, 0x20, 0x75, 0x72, 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a,
+ 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33,
+ 0x43, 0x73, 0x76, 0x67, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70,
+ 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30,
+ 0x30, 0x30, 0x2f, 0x73, 0x76, 0x67, 0x27, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32,
+ 0x34, 0x27, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76,
+ 0x69, 0x65, 0x77, 0x42, 0x6f, 0x78, 0x3d, 0x27, 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32,
+ 0x34, 0x27, 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x3d, 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73,
+ 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x3d, 0x27, 0x72, 0x67, 0x62, 0x28, 0x34, 0x36, 0x2c, 0x20, 0x31,
+ 0x32, 0x35, 0x2c, 0x20, 0x35, 0x30, 0x29, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d,
+ 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x33, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65,
+ 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63, 0x61, 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27,
+ 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e,
+ 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x70, 0x6f,
+ 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x3d, 0x27, 0x32,
+ 0x30, 0x20, 0x36, 0x20, 0x39, 0x20, 0x31, 0x37, 0x20, 0x34, 0x20, 0x31, 0x32, 0x27, 0x25, 0x33,
+ 0x45, 0x25, 0x33, 0x43, 0x2f, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45,
+ 0x25, 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2d, 0x73, 0x63, 0x68,
+ 0x65, 0x6d, 0x65, 0x3a, 0x20, 0x64, 0x61, 0x72, 0x6b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d,
+ 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x68, 0x65,
+ 0x6d, 0x65, 0x3d, 0x64, 0x61, 0x72, 0x6b, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x31, 0x31, 0x31, 0x39, 0x31, 0x66, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28, 0x32,
+ 0x30, 0x35, 0x2c, 0x20, 0x31, 0x36, 0x25, 0x2c, 0x20, 0x37, 0x37, 0x25, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x68, 0x31, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x32, 0x30, 0x25, 0x2c, 0x20, 0x39, 0x34,
+ 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x68, 0x32, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x65, 0x31, 0x65, 0x36, 0x65, 0x62, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x68, 0x33, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68,
+ 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x31, 0x38, 0x25, 0x2c, 0x20, 0x38, 0x36, 0x25,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x68, 0x34, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x63, 0x38, 0x64, 0x31, 0x64, 0x38, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x68, 0x35, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73,
+ 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x31, 0x36, 0x25, 0x2c, 0x20, 0x37, 0x37, 0x25, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x68, 0x36, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x23, 0x61, 0x66, 0x62, 0x62, 0x63, 0x34, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x31, 0x30, 0x25, 0x2c, 0x20, 0x35, 0x30,
+ 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64,
+ 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23,
+ 0x31, 0x66, 0x32, 0x64, 0x33, 0x38, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x70,
+ 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30, 0x34, 0x2c,
+ 0x20, 0x37, 0x30, 0x25, 0x2c, 0x20, 0x33, 0x30, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72,
+ 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28, 0x31, 0x39, 0x35, 0x2c, 0x20, 0x38, 0x35, 0x25, 0x2c, 0x20,
+ 0x34, 0x31, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x70, 0x72, 0x69,
+ 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x3a, 0x20, 0x72, 0x67, 0x62, 0x61,
+ 0x28, 0x31, 0x36, 0x2c, 0x20, 0x31, 0x34, 0x39, 0x2c, 0x20, 0x31, 0x39, 0x33, 0x2c, 0x20, 0x30,
+ 0x2e, 0x32, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x70, 0x72, 0x69,
+ 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x3a, 0x20, 0x23, 0x66,
+ 0x66, 0x66, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e,
+ 0x64, 0x61, 0x72, 0x79, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x31,
+ 0x35, 0x25, 0x2c, 0x20, 0x34, 0x31, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72,
+ 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x31, 0x30, 0x25, 0x2c, 0x20,
+ 0x35, 0x30, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x73, 0x65, 0x63,
+ 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x3a, 0x20, 0x72, 0x67,
+ 0x62, 0x61, 0x28, 0x31, 0x31, 0x35, 0x2c, 0x20, 0x31, 0x33, 0x30, 0x2c, 0x20, 0x31, 0x34, 0x30,
+ 0x2c, 0x20, 0x30, 0x2e, 0x32, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2d, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73,
+ 0x65, 0x3a, 0x20, 0x23, 0x66, 0x66, 0x66, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30,
+ 0x35, 0x2c, 0x20, 0x32, 0x30, 0x25, 0x2c, 0x20, 0x39, 0x34, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x2d, 0x68, 0x6f,
+ 0x76, 0x65, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x66, 0x66, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73,
+ 0x3a, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x31, 0x31, 0x35, 0x2c, 0x20, 0x31, 0x33, 0x30, 0x2c,
+ 0x20, 0x31, 0x34, 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x32, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x2d, 0x69, 0x6e, 0x76,
+ 0x65, 0x72, 0x73, 0x65, 0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x6d, 0x61, 0x72, 0x6b, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75,
+ 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x64, 0x31, 0x63, 0x32, 0x38,
+ 0x34, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6d, 0x61, 0x72, 0x6b, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x31, 0x31, 0x31, 0x39, 0x31, 0x66, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x69, 0x6e, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x20, 0x23, 0x33, 0x38, 0x38, 0x65, 0x33, 0x63, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x64, 0x65, 0x6c, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x63, 0x36, 0x32,
+ 0x38, 0x32, 0x38, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63,
+ 0x6b, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64,
+ 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x71, 0x75, 0x6f, 0x74,
+ 0x65, 0x2d, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x75, 0x74, 0x74, 0x6f,
+ 0x6e, 0x2d, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x3a, 0x20, 0x30, 0x20,
+ 0x30, 0x20, 0x30, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30,
+ 0x2c, 0x20, 0x30, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x75, 0x74,
+ 0x74, 0x6f, 0x6e, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68,
+ 0x61, 0x64, 0x6f, 0x77, 0x3a, 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x20, 0x72, 0x67, 0x62, 0x61,
+ 0x28, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x31, 0x31, 0x31, 0x39, 0x31, 0x66, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74,
+ 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23,
+ 0x33, 0x37, 0x34, 0x39, 0x35, 0x36, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66,
+ 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65,
+ 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x75,
+ 0x74, 0x65, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d,
+ 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66,
+ 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x63, 0x6b,
+ 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72,
+ 0x69, 0x6d, 0x61, 0x72, 0x79, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66,
+ 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x66, 0x6f, 0x63, 0x75,
+ 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70,
+ 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2d, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2d, 0x62, 0x61, 0x63, 0x6b,
+ 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73,
+ 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x32, 0x35, 0x25, 0x2c, 0x20, 0x32, 0x33, 0x25, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2d, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c,
+ 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x32, 0x30, 0x25, 0x2c, 0x20, 0x33, 0x32, 0x25, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65,
+ 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2d, 0x6f, 0x70,
+ 0x61, 0x63, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x30, 0x2e, 0x35, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d,
+ 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x62, 0x37, 0x31, 0x63, 0x31, 0x63, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x76,
+ 0x65, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x23, 0x63, 0x36, 0x32, 0x38, 0x32, 0x38, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x69, 0x6e, 0x76,
+ 0x61, 0x6c, 0x69, 0x64, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x31, 0x39, 0x38, 0x2c, 0x20, 0x34, 0x30, 0x2c, 0x20,
+ 0x34, 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x32, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x76,
+ 0x61, 0x6c, 0x69, 0x64, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x23, 0x32, 0x65, 0x37, 0x64, 0x33, 0x32, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d,
+ 0x76, 0x61, 0x6c, 0x69, 0x64, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x62, 0x6f, 0x72,
+ 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x33, 0x38, 0x38, 0x65,
+ 0x33, 0x63, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d,
+ 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x2d, 0x66, 0x6f,
+ 0x63, 0x75, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28,
+ 0x35, 0x36, 0x2c, 0x20, 0x31, 0x34, 0x32, 0x2c, 0x20, 0x36, 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x32,
+ 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x73, 0x77, 0x69, 0x74, 0x63,
+ 0x68, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x33, 0x37, 0x34, 0x39, 0x35, 0x36, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2d,
+ 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x2d,
+ 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x32, 0x34,
+ 0x33, 0x33, 0x33, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x72, 0x61, 0x6e,
+ 0x67, 0x65, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c,
+ 0x20, 0x32, 0x35, 0x25, 0x2c, 0x20, 0x32, 0x33, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x2d, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x72, 0x61, 0x6e,
+ 0x67, 0x65, 0x2d, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x74,
+ 0x68, 0x75, 0x6d, 0x62, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72,
+ 0x79, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x2d, 0x61, 0x63, 0x74,
+ 0x69, 0x76, 0x65, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x2d, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65,
+ 0x64, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2d, 0x72, 0x6f,
+ 0x77, 0x2d, 0x73, 0x74, 0x72, 0x69, 0x70, 0x70, 0x65, 0x64, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x72, 0x67, 0x62,
+ 0x61, 0x28, 0x31, 0x31, 0x35, 0x2c, 0x20, 0x31, 0x33, 0x30, 0x2c, 0x20, 0x31, 0x34, 0x30, 0x2c,
+ 0x20, 0x30, 0x2e, 0x30, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63,
+ 0x6f, 0x64, 0x65, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x31, 0x38, 0x32, 0x33, 0x32, 0x63, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x64,
+ 0x65, 0x2d, 0x6b, 0x62, 0x64, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f,
+ 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x63, 0x6f, 0x64, 0x65, 0x2d, 0x6b, 0x62, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x2d, 0x69,
+ 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x63, 0x6f, 0x64, 0x65, 0x2d, 0x74, 0x61, 0x67, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x68, 0x73, 0x6c, 0x28, 0x33, 0x33, 0x30, 0x2c, 0x20, 0x33, 0x30, 0x25, 0x2c, 0x20, 0x35, 0x30,
+ 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2d,
+ 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x68, 0x73, 0x6c, 0x28, 0x31, 0x38, 0x35, 0x2c, 0x20, 0x33, 0x30, 0x25, 0x2c, 0x20, 0x35, 0x30,
+ 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2d,
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x73, 0x6c,
+ 0x28, 0x34, 0x30, 0x2c, 0x20, 0x31, 0x30, 0x25, 0x2c, 0x20, 0x35, 0x30, 0x25, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2d, 0x63, 0x6f, 0x6d, 0x6d,
+ 0x65, 0x6e, 0x74, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x34, 0x64, 0x36, 0x30,
+ 0x36, 0x64, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x61, 0x63, 0x63, 0x6f, 0x72,
+ 0x64, 0x69, 0x6f, 0x6e, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6f, 0x6e, 0x2d, 0x61,
+ 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61,
+ 0x72, 0x79, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x61, 0x63, 0x63, 0x6f,
+ 0x72, 0x64, 0x69, 0x6f, 0x6e, 0x2d, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x2d, 0x73, 0x75, 0x6d, 0x6d,
+ 0x61, 0x72, 0x79, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6f, 0x6e, 0x2d, 0x6f, 0x70, 0x65, 0x6e, 0x2d, 0x73,
+ 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x61, 0x72, 0x64, 0x2d, 0x62, 0x61,
+ 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x23, 0x31, 0x34, 0x31, 0x65, 0x32, 0x36, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x63, 0x61, 0x72, 0x64, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x61, 0x72, 0x64, 0x2d, 0x62, 0x61,
+ 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x61, 0x72, 0x64, 0x2d, 0x62, 0x6f, 0x78,
+ 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x3a, 0x20, 0x30, 0x2e, 0x30, 0x31, 0x34, 0x35, 0x72,
+ 0x65, 0x6d, 0x20, 0x30, 0x2e, 0x30, 0x32, 0x39, 0x72, 0x65, 0x6d, 0x20, 0x30, 0x2e, 0x31, 0x37,
+ 0x34, 0x72, 0x65, 0x6d, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20,
+ 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x31, 0x36, 0x39, 0x38, 0x29, 0x2c, 0x30, 0x2e, 0x30, 0x33,
+ 0x33, 0x35, 0x72, 0x65, 0x6d, 0x20, 0x30, 0x2e, 0x30, 0x36, 0x37, 0x72, 0x65, 0x6d, 0x20, 0x30,
+ 0x2e, 0x34, 0x30, 0x32, 0x72, 0x65, 0x6d, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x30, 0x2c, 0x20,
+ 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x32, 0x34, 0x29, 0x2c, 0x30, 0x2e, 0x30,
+ 0x36, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x20, 0x30, 0x2e, 0x31, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x20,
+ 0x30, 0x2e, 0x37, 0x35, 0x72, 0x65, 0x6d, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x30, 0x2c, 0x20,
+ 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x33, 0x29, 0x2c, 0x30, 0x2e, 0x31, 0x31,
+ 0x32, 0x35, 0x72, 0x65, 0x6d, 0x20, 0x30, 0x2e, 0x32, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x20, 0x31,
+ 0x2e, 0x33, 0x35, 0x72, 0x65, 0x6d, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x30, 0x2c, 0x20, 0x30,
+ 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x33, 0x36, 0x29, 0x2c, 0x30, 0x2e, 0x32, 0x30,
+ 0x38, 0x35, 0x72, 0x65, 0x6d, 0x20, 0x30, 0x2e, 0x34, 0x31, 0x37, 0x72, 0x65, 0x6d, 0x20, 0x32,
+ 0x2e, 0x35, 0x30, 0x32, 0x72, 0x65, 0x6d, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x30, 0x2c, 0x20,
+ 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x34, 0x33, 0x30, 0x32, 0x29, 0x2c, 0x30,
+ 0x2e, 0x35, 0x72, 0x65, 0x6d, 0x20, 0x31, 0x72, 0x65, 0x6d, 0x20, 0x36, 0x72, 0x65, 0x6d, 0x20,
+ 0x72, 0x67, 0x62, 0x61, 0x28, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2e,
+ 0x30, 0x36, 0x29, 0x2c, 0x30, 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x2e, 0x30, 0x36, 0x32, 0x35,
+ 0x72, 0x65, 0x6d, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30,
+ 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x31, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x63, 0x61, 0x72, 0x64, 0x2d, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x6e, 0x69, 0x6e,
+ 0x67, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x31, 0x38, 0x32, 0x33, 0x32, 0x63, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x64, 0x72, 0x6f, 0x70, 0x64, 0x6f, 0x77, 0x6e, 0x2d, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x68,
+ 0x73, 0x6c, 0x28, 0x32, 0x30, 0x35, 0x2c, 0x20, 0x33, 0x30, 0x25, 0x2c, 0x20, 0x31, 0x35, 0x25,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x64, 0x72, 0x6f, 0x70, 0x64, 0x6f,
+ 0x77, 0x6e, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x20, 0x23, 0x32, 0x34, 0x33, 0x33, 0x33, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x64, 0x72, 0x6f, 0x70, 0x64, 0x6f, 0x77, 0x6e, 0x2d, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68,
+ 0x61, 0x64, 0x6f, 0x77, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x61, 0x72, 0x64,
+ 0x2d, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x64, 0x72, 0x6f, 0x70, 0x64, 0x6f, 0x77, 0x6e, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x64, 0x72, 0x6f, 0x70, 0x64, 0x6f,
+ 0x77, 0x6e, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28,
+ 0x33, 0x36, 0x2c, 0x20, 0x35, 0x31, 0x2c, 0x20, 0x36, 0x32, 0x2c, 0x20, 0x30, 0x2e, 0x37, 0x35,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x2d,
+ 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75,
+ 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x33,
+ 0x36, 0x2c, 0x20, 0x35, 0x31, 0x2c, 0x20, 0x36, 0x32, 0x2c, 0x20, 0x30, 0x2e, 0x38, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73,
+ 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x23, 0x32, 0x34, 0x33, 0x33, 0x33, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x6e,
+ 0x67, 0x2d, 0x73, 0x70, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x2d, 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74,
+ 0x79, 0x3a, 0x20, 0x30, 0x2e, 0x35, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x74,
+ 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63,
+ 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x2d, 0x69,
+ 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x3a, 0x20, 0x75,
+ 0x72, 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73,
+ 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73, 0x76, 0x67, 0x20, 0x78, 0x6d,
+ 0x6c, 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e,
+ 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30, 0x2f, 0x73, 0x76, 0x67, 0x27,
+ 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x68, 0x65, 0x69, 0x67,
+ 0x68, 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65, 0x77, 0x42, 0x6f, 0x78, 0x3d,
+ 0x27, 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27, 0x20, 0x66, 0x69, 0x6c, 0x6c,
+ 0x3d, 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x3d, 0x27,
+ 0x72, 0x67, 0x62, 0x28, 0x32, 0x35, 0x35, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x2c, 0x20, 0x32, 0x35,
+ 0x35, 0x29, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68,
+ 0x3d, 0x27, 0x34, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65,
+ 0x63, 0x61, 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f,
+ 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d, 0x27, 0x72, 0x6f, 0x75,
+ 0x6e, 0x64, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e,
+ 0x65, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x3d, 0x27, 0x32, 0x30, 0x20, 0x36, 0x20, 0x39,
+ 0x20, 0x31, 0x37, 0x20, 0x34, 0x20, 0x31, 0x32, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f,
+ 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x73,
+ 0x76, 0x67, 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x63, 0x68, 0x65, 0x76, 0x72, 0x6f, 0x6e, 0x3a, 0x20, 0x75, 0x72,
+ 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x76,
+ 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73, 0x76, 0x67, 0x20, 0x78, 0x6d, 0x6c,
+ 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77,
+ 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30, 0x2f, 0x73, 0x76, 0x67, 0x27, 0x20,
+ 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65, 0x77, 0x42, 0x6f, 0x78, 0x3d, 0x27,
+ 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27, 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x3d,
+ 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x3d, 0x27, 0x72,
+ 0x67, 0x62, 0x28, 0x31, 0x36, 0x32, 0x2c, 0x20, 0x31, 0x37, 0x35, 0x2c, 0x20, 0x31, 0x38, 0x35,
+ 0x29, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d,
+ 0x27, 0x32, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63,
+ 0x61, 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b,
+ 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65,
+ 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x3d, 0x27, 0x36, 0x20, 0x39, 0x20, 0x31, 0x32, 0x20,
+ 0x31, 0x35, 0x20, 0x31, 0x38, 0x20, 0x39, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x70,
+ 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x73, 0x76,
+ 0x67, 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x69,
+ 0x63, 0x6f, 0x6e, 0x2d, 0x63, 0x68, 0x65, 0x76, 0x72, 0x6f, 0x6e, 0x2d, 0x62, 0x75, 0x74, 0x74,
+ 0x6f, 0x6e, 0x3a, 0x20, 0x75, 0x72, 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d,
+ 0x61, 0x67, 0x65, 0x2f, 0x73, 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73,
+ 0x76, 0x67, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30,
+ 0x2f, 0x73, 0x76, 0x67, 0x27, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27,
+ 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65,
+ 0x77, 0x42, 0x6f, 0x78, 0x3d, 0x27, 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27,
+ 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x3d, 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72,
+ 0x6f, 0x6b, 0x65, 0x3d, 0x27, 0x72, 0x67, 0x62, 0x28, 0x32, 0x35, 0x35, 0x2c, 0x20, 0x32, 0x35,
+ 0x35, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d,
+ 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65,
+ 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63, 0x61, 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27,
+ 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e,
+ 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x70, 0x6f,
+ 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x3d, 0x27, 0x36,
+ 0x20, 0x39, 0x20, 0x31, 0x32, 0x20, 0x31, 0x35, 0x20, 0x31, 0x38, 0x20, 0x39, 0x27, 0x25, 0x33,
+ 0x45, 0x25, 0x33, 0x43, 0x2f, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45,
+ 0x25, 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x63, 0x68, 0x65, 0x76, 0x72, 0x6f,
+ 0x6e, 0x2d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2d, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65,
+ 0x3a, 0x20, 0x75, 0x72, 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d, 0x61, 0x67,
+ 0x65, 0x2f, 0x73, 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73, 0x76, 0x67,
+ 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
+ 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30, 0x2f, 0x73,
+ 0x76, 0x67, 0x27, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x68,
+ 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65, 0x77, 0x42,
+ 0x6f, 0x78, 0x3d, 0x27, 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27, 0x20, 0x66,
+ 0x69, 0x6c, 0x6c, 0x3d, 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b,
+ 0x65, 0x3d, 0x27, 0x72, 0x67, 0x62, 0x28, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x29, 0x27,
+ 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32,
+ 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63, 0x61, 0x70,
+ 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d,
+ 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27,
+ 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x70,
+ 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x3d, 0x27, 0x36, 0x20, 0x39, 0x20, 0x31, 0x32, 0x20, 0x31, 0x35,
+ 0x20, 0x31, 0x38, 0x20, 0x39, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x70, 0x6f, 0x6c,
+ 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25,
+ 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x69, 0x63, 0x6f,
+ 0x6e, 0x2d, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x3a, 0x20, 0x75, 0x72, 0x6c, 0x28, 0x22, 0x64, 0x61,
+ 0x74, 0x61, 0x3a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c,
+ 0x2c, 0x25, 0x33, 0x43, 0x73, 0x76, 0x67, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3d, 0x27, 0x68,
+ 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67,
+ 0x2f, 0x32, 0x30, 0x30, 0x30, 0x2f, 0x73, 0x76, 0x67, 0x27, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68,
+ 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x27, 0x32, 0x34,
+ 0x27, 0x20, 0x76, 0x69, 0x65, 0x77, 0x42, 0x6f, 0x78, 0x3d, 0x27, 0x30, 0x20, 0x30, 0x20, 0x32,
+ 0x34, 0x20, 0x32, 0x34, 0x27, 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x3d, 0x27, 0x6e, 0x6f, 0x6e, 0x65,
+ 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x3d, 0x27, 0x72, 0x67, 0x62, 0x28, 0x31, 0x31,
+ 0x35, 0x2c, 0x20, 0x31, 0x33, 0x30, 0x2c, 0x20, 0x31, 0x34, 0x30, 0x29, 0x27, 0x20, 0x73, 0x74,
+ 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x34, 0x27, 0x20, 0x73,
+ 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63, 0x61, 0x70, 0x3d, 0x27, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e,
+ 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x25, 0x33, 0x45,
+ 0x25, 0x33, 0x43, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x78, 0x31, 0x3d, 0x27, 0x31, 0x38, 0x27, 0x20,
+ 0x79, 0x31, 0x3d, 0x27, 0x36, 0x27, 0x20, 0x78, 0x32, 0x3d, 0x27, 0x36, 0x27, 0x20, 0x79, 0x32,
+ 0x3d, 0x27, 0x31, 0x38, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x6c, 0x69, 0x6e, 0x65,
+ 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x78, 0x31, 0x3d, 0x27, 0x36,
+ 0x27, 0x20, 0x79, 0x31, 0x3d, 0x27, 0x36, 0x27, 0x20, 0x78, 0x32, 0x3d, 0x27, 0x31, 0x38, 0x27,
+ 0x20, 0x79, 0x32, 0x3d, 0x27, 0x31, 0x38, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x6c,
+ 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25, 0x33, 0x45,
+ 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d,
+ 0x64, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x75, 0x72, 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a,
+ 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33,
+ 0x43, 0x73, 0x76, 0x67, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70,
+ 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30,
+ 0x30, 0x30, 0x2f, 0x73, 0x76, 0x67, 0x27, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32,
+ 0x34, 0x27, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76,
+ 0x69, 0x65, 0x77, 0x42, 0x6f, 0x78, 0x3d, 0x27, 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32,
+ 0x34, 0x27, 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x3d, 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73,
+ 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x3d, 0x27, 0x72, 0x67, 0x62, 0x28, 0x31, 0x36, 0x32, 0x2c, 0x20,
+ 0x31, 0x37, 0x35, 0x2c, 0x20, 0x31, 0x38, 0x35, 0x29, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b,
+ 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f,
+ 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63, 0x61, 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f,
+ 0x69, 0x6e, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43,
+ 0x72, 0x65, 0x63, 0x74, 0x20, 0x78, 0x3d, 0x27, 0x33, 0x27, 0x20, 0x79, 0x3d, 0x27, 0x34, 0x27,
+ 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x31, 0x38, 0x27, 0x20, 0x68, 0x65, 0x69, 0x67,
+ 0x68, 0x74, 0x3d, 0x27, 0x31, 0x38, 0x27, 0x20, 0x72, 0x78, 0x3d, 0x27, 0x32, 0x27, 0x20, 0x72,
+ 0x79, 0x3d, 0x27, 0x32, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x72, 0x65, 0x63, 0x74,
+ 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x78, 0x31, 0x3d, 0x27, 0x31,
+ 0x36, 0x27, 0x20, 0x79, 0x31, 0x3d, 0x27, 0x32, 0x27, 0x20, 0x78, 0x32, 0x3d, 0x27, 0x31, 0x36,
+ 0x27, 0x20, 0x79, 0x32, 0x3d, 0x27, 0x36, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x6c,
+ 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x78, 0x31,
+ 0x3d, 0x27, 0x38, 0x27, 0x20, 0x79, 0x31, 0x3d, 0x27, 0x32, 0x27, 0x20, 0x78, 0x32, 0x3d, 0x27,
+ 0x38, 0x27, 0x20, 0x79, 0x32, 0x3d, 0x27, 0x36, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f,
+ 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x78,
+ 0x31, 0x3d, 0x27, 0x33, 0x27, 0x20, 0x79, 0x31, 0x3d, 0x27, 0x31, 0x30, 0x27, 0x20, 0x78, 0x32,
+ 0x3d, 0x27, 0x32, 0x31, 0x27, 0x20, 0x79, 0x32, 0x3d, 0x27, 0x31, 0x30, 0x27, 0x25, 0x33, 0x45,
+ 0x25, 0x33, 0x43, 0x2f, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x73,
+ 0x76, 0x67, 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x3a, 0x20, 0x75, 0x72,
+ 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x76,
+ 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73, 0x76, 0x67, 0x20, 0x78, 0x6d, 0x6c,
+ 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77,
+ 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30, 0x2f, 0x73, 0x76, 0x67, 0x27, 0x20,
+ 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65, 0x77, 0x42, 0x6f, 0x78, 0x3d, 0x27,
+ 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27, 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x3d,
+ 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x3d, 0x27, 0x72,
+ 0x67, 0x62, 0x28, 0x31, 0x38, 0x33, 0x2c, 0x20, 0x32, 0x38, 0x2c, 0x20, 0x32, 0x38, 0x29, 0x27,
+ 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32,
+ 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63, 0x61, 0x70,
+ 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d,
+ 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27,
+ 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x20, 0x63, 0x78, 0x3d,
+ 0x27, 0x31, 0x32, 0x27, 0x20, 0x63, 0x79, 0x3d, 0x27, 0x31, 0x32, 0x27, 0x20, 0x72, 0x3d, 0x27,
+ 0x31, 0x30, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65,
+ 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x78, 0x31, 0x3d, 0x27, 0x31,
+ 0x32, 0x27, 0x20, 0x79, 0x31, 0x3d, 0x27, 0x38, 0x27, 0x20, 0x78, 0x32, 0x3d, 0x27, 0x31, 0x32,
+ 0x27, 0x20, 0x79, 0x32, 0x3d, 0x27, 0x31, 0x32, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f,
+ 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x78,
+ 0x31, 0x3d, 0x27, 0x31, 0x32, 0x27, 0x20, 0x79, 0x31, 0x3d, 0x27, 0x31, 0x36, 0x27, 0x20, 0x78,
+ 0x32, 0x3d, 0x27, 0x31, 0x32, 0x2e, 0x30, 0x31, 0x27, 0x20, 0x79, 0x32, 0x3d, 0x27, 0x31, 0x36,
+ 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25,
+ 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x6d, 0x69, 0x6e, 0x75, 0x73, 0x3a, 0x20,
+ 0x75, 0x72, 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f,
+ 0x73, 0x76, 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73, 0x76, 0x67, 0x20, 0x78,
+ 0x6d, 0x6c, 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77,
+ 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30, 0x2f, 0x73, 0x76, 0x67,
+ 0x27, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x68, 0x65, 0x69,
+ 0x67, 0x68, 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65, 0x77, 0x42, 0x6f, 0x78,
+ 0x3d, 0x27, 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27, 0x20, 0x66, 0x69, 0x6c,
+ 0x6c, 0x3d, 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x3d,
+ 0x27, 0x72, 0x67, 0x62, 0x28, 0x32, 0x35, 0x35, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x2c, 0x20, 0x32,
+ 0x35, 0x35, 0x29, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74,
+ 0x68, 0x3d, 0x27, 0x34, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e,
+ 0x65, 0x63, 0x61, 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20, 0x73, 0x74, 0x72,
+ 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d, 0x27, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x78,
+ 0x31, 0x3d, 0x27, 0x35, 0x27, 0x20, 0x79, 0x31, 0x3d, 0x27, 0x31, 0x32, 0x27, 0x20, 0x78, 0x32,
+ 0x3d, 0x27, 0x31, 0x39, 0x27, 0x20, 0x79, 0x32, 0x3d, 0x27, 0x31, 0x32, 0x27, 0x25, 0x33, 0x45,
+ 0x25, 0x33, 0x43, 0x2f, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x73,
+ 0x76, 0x67, 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x3a, 0x20, 0x75, 0x72, 0x6c,
+ 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x76, 0x67,
+ 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73, 0x76, 0x67, 0x20, 0x78, 0x6d, 0x6c, 0x6e,
+ 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33,
+ 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30, 0x2f, 0x73, 0x76, 0x67, 0x27, 0x20, 0x77,
+ 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74,
+ 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65, 0x77, 0x42, 0x6f, 0x78, 0x3d, 0x27, 0x30,
+ 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27, 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x3d, 0x27,
+ 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x3d, 0x27, 0x72, 0x67,
+ 0x62, 0x28, 0x31, 0x36, 0x32, 0x2c, 0x20, 0x31, 0x37, 0x35, 0x2c, 0x20, 0x31, 0x38, 0x35, 0x29,
+ 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27,
+ 0x32, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63, 0x61,
+ 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65,
+ 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x20, 0x63, 0x78,
+ 0x3d, 0x27, 0x31, 0x31, 0x27, 0x20, 0x63, 0x79, 0x3d, 0x27, 0x31, 0x31, 0x27, 0x20, 0x72, 0x3d,
+ 0x27, 0x38, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65,
+ 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x78, 0x31, 0x3d, 0x27, 0x32,
+ 0x31, 0x27, 0x20, 0x79, 0x31, 0x3d, 0x27, 0x32, 0x31, 0x27, 0x20, 0x78, 0x32, 0x3d, 0x27, 0x31,
+ 0x36, 0x2e, 0x36, 0x35, 0x27, 0x20, 0x79, 0x32, 0x3d, 0x27, 0x31, 0x36, 0x2e, 0x36, 0x35, 0x27,
+ 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33,
+ 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x74, 0x69, 0x6d, 0x65, 0x3a, 0x20, 0x75, 0x72,
+ 0x6c, 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x76,
+ 0x67, 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73, 0x76, 0x67, 0x20, 0x78, 0x6d, 0x6c,
+ 0x6e, 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77,
+ 0x33, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30, 0x2f, 0x73, 0x76, 0x67, 0x27, 0x20,
+ 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65, 0x77, 0x42, 0x6f, 0x78, 0x3d, 0x27,
+ 0x30, 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27, 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x3d,
+ 0x27, 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x3d, 0x27, 0x72,
+ 0x67, 0x62, 0x28, 0x31, 0x36, 0x32, 0x2c, 0x20, 0x31, 0x37, 0x35, 0x2c, 0x20, 0x31, 0x38, 0x35,
+ 0x29, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d,
+ 0x27, 0x32, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63,
+ 0x61, 0x70, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b,
+ 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x63, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x20, 0x63,
+ 0x78, 0x3d, 0x27, 0x31, 0x32, 0x27, 0x20, 0x63, 0x79, 0x3d, 0x27, 0x31, 0x32, 0x27, 0x20, 0x72,
+ 0x3d, 0x27, 0x31, 0x30, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x63, 0x69, 0x72, 0x63,
+ 0x6c, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65,
+ 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x3d, 0x27, 0x31, 0x32, 0x20, 0x36, 0x20, 0x31, 0x32,
+ 0x20, 0x31, 0x32, 0x20, 0x31, 0x36, 0x20, 0x31, 0x34, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43,
+ 0x2f, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f,
+ 0x73, 0x76, 0x67, 0x25, 0x33, 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x3a, 0x20, 0x75, 0x72, 0x6c,
+ 0x28, 0x22, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x73, 0x76, 0x67,
+ 0x2b, 0x78, 0x6d, 0x6c, 0x2c, 0x25, 0x33, 0x43, 0x73, 0x76, 0x67, 0x20, 0x78, 0x6d, 0x6c, 0x6e,
+ 0x73, 0x3d, 0x27, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33,
+ 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x32, 0x30, 0x30, 0x30, 0x2f, 0x73, 0x76, 0x67, 0x27, 0x20, 0x77,
+ 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74,
+ 0x3d, 0x27, 0x32, 0x34, 0x27, 0x20, 0x76, 0x69, 0x65, 0x77, 0x42, 0x6f, 0x78, 0x3d, 0x27, 0x30,
+ 0x20, 0x30, 0x20, 0x32, 0x34, 0x20, 0x32, 0x34, 0x27, 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x3d, 0x27,
+ 0x6e, 0x6f, 0x6e, 0x65, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x3d, 0x27, 0x72, 0x67,
+ 0x62, 0x28, 0x34, 0x36, 0x2c, 0x20, 0x31, 0x32, 0x35, 0x2c, 0x20, 0x35, 0x30, 0x29, 0x27, 0x20,
+ 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x27, 0x33, 0x27,
+ 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x63, 0x61, 0x70, 0x3d,
+ 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6b, 0x65, 0x2d, 0x6c,
+ 0x69, 0x6e, 0x65, 0x6a, 0x6f, 0x69, 0x6e, 0x3d, 0x27, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x27, 0x25,
+ 0x33, 0x45, 0x25, 0x33, 0x43, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x6f,
+ 0x69, 0x6e, 0x74, 0x73, 0x3d, 0x27, 0x32, 0x30, 0x20, 0x36, 0x20, 0x39, 0x20, 0x31, 0x37, 0x20,
+ 0x34, 0x20, 0x31, 0x32, 0x27, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x70, 0x6f, 0x6c, 0x79,
+ 0x6c, 0x69, 0x6e, 0x65, 0x25, 0x33, 0x45, 0x25, 0x33, 0x43, 0x2f, 0x73, 0x76, 0x67, 0x25, 0x33,
+ 0x45, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2d,
+ 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x3a, 0x20, 0x64, 0x61, 0x72, 0x6b, 0x0d, 0x0a, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f,
+ 0x78, 0x5d, 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x5d,
+ 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5d, 0x2c, 0x20,
+ 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x61, 0x63, 0x63, 0x65, 0x6e, 0x74, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x29, 0x0d, 0x0a, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x2a, 0x2c, 0x20, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x3a,
+ 0x3a, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62,
+ 0x6f, 0x78, 0x2d, 0x73, 0x69, 0x7a, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65,
+ 0x72, 0x2d, 0x62, 0x6f, 0x78, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b,
+ 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x3a, 0x20, 0x6e,
+ 0x6f, 0x2d, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x3a,
+ 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x3a, 0x3a, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65,
+ 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x64, 0x65, 0x63,
+ 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x2d,
+ 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x0d, 0x0a,
+ 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x3a, 0x77, 0x68, 0x65, 0x72, 0x65, 0x28, 0x3a, 0x72, 0x6f, 0x6f,
+ 0x74, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69,
+ 0x74, 0x2d, 0x74, 0x61, 0x70, 0x2d, 0x68, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65,
+ 0x6e, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74,
+ 0x2d, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x2d, 0x61, 0x64, 0x6a, 0x75, 0x73,
+ 0x74, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x6d,
+ 0x6f, 0x7a, 0x2d, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x2d, 0x61, 0x64, 0x6a,
+ 0x75, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x74, 0x65, 0x78, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x2d, 0x61, 0x64, 0x6a, 0x75, 0x73, 0x74,
+ 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67,
+ 0x68, 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77,
+ 0x65, 0x69, 0x67, 0x68, 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e,
+ 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f,
+ 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c,
+ 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79,
+ 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x66, 0x61, 0x6d,
+ 0x69, 0x6c, 0x79, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d,
+ 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6d,
+ 0x69, 0x7a, 0x65, 0x4c, 0x65, 0x67, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2d, 0x77, 0x72, 0x61,
+ 0x70, 0x3a, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x2d, 0x77, 0x6f, 0x72, 0x64, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x3a, 0x20, 0x64, 0x65, 0x66, 0x61,
+ 0x75, 0x6c, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x6d, 0x6f, 0x7a, 0x2d, 0x74,
+ 0x61, 0x62, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x34, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x6f, 0x2d, 0x74, 0x61, 0x62, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x34, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x61, 0x62, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20,
+ 0x34, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x62, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30,
+ 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20,
+ 0x3e, 0x20, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x3e,
+ 0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2c, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x3e, 0x20,
+ 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x72, 0x69, 0x67,
+ 0x68, 0x74, 0x3a, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x20,
+ 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70,
+ 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74,
+ 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20, 0x30, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2c, 0x20, 0x2e, 0x63,
+ 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2d, 0x66, 0x6c, 0x75, 0x69, 0x64, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30,
+ 0x25, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x72,
+ 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x20, 0x61, 0x75,
+ 0x74, 0x6f, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
+ 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70,
+ 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64,
+ 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20, 0x28, 0x6d, 0x69, 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74,
+ 0x68, 0x3a, 0x35, 0x37, 0x36, 0x70, 0x78, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a,
+ 0x20, 0x35, 0x31, 0x30, 0x70, 0x78, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20,
+ 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64,
+ 0x69, 0x6e, 0x67, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20,
+ 0x28, 0x6d, 0x69, 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x37, 0x36, 0x38, 0x70, 0x78,
+ 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
+ 0x6e, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d,
+ 0x61, 0x78, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x37, 0x30, 0x30, 0x70, 0x78, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6d, 0x65,
+ 0x64, 0x69, 0x61, 0x20, 0x28, 0x6d, 0x69, 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x39,
+ 0x39, 0x32, 0x70, 0x78, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x63, 0x6f,
+ 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x39, 0x32,
+ 0x30, 0x70, 0x78, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20, 0x28, 0x6d, 0x69, 0x6e, 0x2d, 0x77, 0x69, 0x64,
+ 0x74, 0x68, 0x3a, 0x31, 0x32, 0x30, 0x30, 0x70, 0x78, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x2d, 0x77, 0x69, 0x64, 0x74,
+ 0x68, 0x3a, 0x20, 0x31, 0x31, 0x33, 0x30, 0x70, 0x78, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d,
+ 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74,
+ 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+ 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61,
+ 0x6c, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x2e, 0x67, 0x72, 0x69, 0x64, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x67, 0x72, 0x69, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x75, 0x6d,
+ 0x6e, 0x2d, 0x67, 0x61, 0x70, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x67, 0x72, 0x69,
+ 0x64, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f,
+ 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x67, 0x72, 0x69, 0x64,
+ 0x2d, 0x72, 0x6f, 0x77, 0x2d, 0x67, 0x61, 0x70, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x67, 0x72, 0x69, 0x64, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72,
+ 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73,
+ 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x67, 0x72, 0x69, 0x64, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x67, 0x72, 0x69, 0x64, 0x2d, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x3a, 0x20, 0x31, 0x66, 0x72, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20, 0x28, 0x6d, 0x69, 0x6e, 0x2d, 0x77, 0x69,
+ 0x64, 0x74, 0x68, 0x3a, 0x39, 0x39, 0x32, 0x70, 0x78, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x2e, 0x67, 0x72, 0x69, 0x64, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x67, 0x72, 0x69, 0x64, 0x2d, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x3a, 0x20, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74,
+ 0x28, 0x61, 0x75, 0x74, 0x6f, 0x2d, 0x66, 0x69, 0x74, 0x2c, 0x6d, 0x69, 0x6e, 0x6d, 0x61, 0x78,
+ 0x28, 0x30, 0x25, 0x2c, 0x31, 0x66, 0x72, 0x29, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d,
+ 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x2e, 0x67, 0x72, 0x69, 0x64, 0x20, 0x3e, 0x20, 0x2a,
+ 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x69, 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74,
+ 0x68, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x66, 0x69, 0x67, 0x75, 0x72,
+ 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79,
+ 0x3a, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61,
+ 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61,
+ 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f,
+ 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2d, 0x78, 0x3a, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x0d,
+ 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65,
+ 0x20, 0x66, 0x69, 0x67, 0x63, 0x61, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20,
+ 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69,
+ 0x6e, 0x67, 0x29, 0x20, 0x2a, 0x20, 0x2e, 0x35, 0x29, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x62, 0x2c, 0x20, 0x73, 0x74, 0x72,
+ 0x6f, 0x6e, 0x67, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d,
+ 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x62, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x0d, 0x0a,
+ 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x75, 0x62, 0x2c, 0x20, 0x73, 0x75, 0x70, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x72,
+ 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f,
+ 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x2e, 0x37, 0x35, 0x65, 0x6d, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74,
+ 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63,
+ 0x61, 0x6c, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69,
+ 0x6e, 0x65, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x75, 0x62, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x2d, 0x2e, 0x32, 0x35,
+ 0x65, 0x6d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x75, 0x70, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x2d, 0x2e, 0x35, 0x65, 0x6d, 0x0d, 0x0a,
+ 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2c, 0x20, 0x62, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x2c, 0x20, 0x64, 0x6c, 0x2c, 0x20, 0x66, 0x69,
+ 0x67, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x2c, 0x20, 0x6f, 0x6c, 0x2c, 0x20,
+ 0x70, 0x2c, 0x20, 0x70, 0x72, 0x65, 0x2c, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2c, 0x20, 0x75,
+ 0x6c, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d,
+ 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72,
+ 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x74, 0x79, 0x70, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x79, 0x2d, 0x73, 0x70, 0x61,
+ 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66,
+ 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61,
+ 0x6c, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69,
+ 0x67, 0x68, 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d,
+ 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f,
+ 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66,
+ 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x6e, 0x6b, 0x5d, 0x2c, 0x20, 0x61, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72,
+ 0x65, 0x6e, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e,
+ 0x65, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x74, 0x65, 0x78,
+ 0x74, 0x2d, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d,
+ 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74,
+ 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e,
+ 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c,
+ 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x2d, 0x77, 0x65,
+ 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61,
+ 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69,
+ 0x6f, 0x6e, 0x29, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69,
+ 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f,
+ 0x6e, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74,
+ 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e,
+ 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c,
+ 0x74, 0x65, 0x78, 0x74, 0x2d, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e,
+ 0x29, 0x2c, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x2d,
+ 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x64, 0x65, 0x63, 0x6f,
+ 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61,
+ 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x6e, 0x6b, 0x5d, 0x3a, 0x69,
+ 0x73, 0x28, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5d,
+ 0x2c, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c,
+ 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x2c, 0x20, 0x61, 0x3a, 0x69, 0x73, 0x28, 0x5b, 0x61,
+ 0x72, 0x69, 0x61, 0x2d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5d, 0x2c, 0x3a, 0x68, 0x6f,
+ 0x76, 0x65, 0x72, 0x2c, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x3a, 0x66, 0x6f, 0x63,
+ 0x75, 0x73, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72,
+ 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x64, 0x65,
+ 0x63, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x6c,
+ 0x69, 0x6e, 0x65, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x6e, 0x6b, 0x5d, 0x3a, 0x66, 0x6f,
+ 0x63, 0x75, 0x73, 0x2c, 0x20, 0x61, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b,
+ 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x6e, 0x6b, 0x5d, 0x2e, 0x73, 0x65, 0x63, 0x6f, 0x6e,
+ 0x64, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x61, 0x2e, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72,
+ 0x79, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f,
+ 0x6e, 0x64, 0x61, 0x72, 0x79, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c,
+ 0x69, 0x6e, 0x6b, 0x5d, 0x2e, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x3a, 0x69,
+ 0x73, 0x28, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5d,
+ 0x2c, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c,
+ 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x2c, 0x20, 0x61, 0x2e, 0x73, 0x65, 0x63, 0x6f, 0x6e,
+ 0x64, 0x61, 0x72, 0x79, 0x3a, 0x69, 0x73, 0x28, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x63, 0x75,
+ 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5d, 0x2c, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x3a, 0x61,
+ 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f,
+ 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x29, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x6e, 0x6b, 0x5d, 0x2e, 0x73,
+ 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2c, 0x20,
+ 0x61, 0x2e, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x3a, 0x66, 0x6f, 0x63, 0x75,
+ 0x73, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e,
+ 0x64, 0x61, 0x72, 0x79, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x72,
+ 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x6e, 0x6b, 0x5d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61,
+ 0x73, 0x74, 0x2c, 0x20, 0x61, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73,
+ 0x74, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x6e, 0x6b, 0x5d,
+ 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x3a, 0x69, 0x73, 0x28, 0x5b, 0x61, 0x72,
+ 0x69, 0x61, 0x2d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5d, 0x2c, 0x3a, 0x68, 0x6f, 0x76,
+ 0x65, 0x72, 0x2c, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x3a, 0x66, 0x6f, 0x63, 0x75,
+ 0x73, 0x29, 0x2c, 0x20, 0x61, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x3a, 0x69,
+ 0x73, 0x28, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5d,
+ 0x2c, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c,
+ 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x2d, 0x68,
+ 0x6f, 0x76, 0x65, 0x72, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x72, 0x6f, 0x6c,
+ 0x65, 0x3d, 0x6c, 0x69, 0x6e, 0x6b, 0x5d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74,
+ 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2c, 0x20, 0x61, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61,
+ 0x73, 0x74, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73,
+ 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x68, 0x31, 0x2c, 0x20, 0x68, 0x32, 0x2c, 0x20, 0x68, 0x33, 0x2c, 0x20, 0x68, 0x34, 0x2c, 0x20,
+ 0x68, 0x35, 0x2c, 0x20, 0x68, 0x36, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61,
+ 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x79, 0x70, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68,
+ 0x79, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63,
+ 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67,
+ 0x68, 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73,
+ 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d,
+ 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74,
+ 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66,
+ 0x6f, 0x6e, 0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x68, 0x31, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x68, 0x31, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x68, 0x32, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x68, 0x32, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x68, 0x33, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x68, 0x33, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x68, 0x34, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x68, 0x34, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d,
+ 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x68, 0x35, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x68,
+ 0x35, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x68,
+ 0x36, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x68, 0x36, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x3a, 0x77, 0x68, 0x65, 0x72, 0x65, 0x28, 0x61,
+ 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x71, 0x75, 0x6f, 0x74,
+ 0x65, 0x2c, 0x64, 0x6c, 0x2c, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x2c, 0x66, 0x6f, 0x72, 0x6d,
+ 0x2c, 0x6f, 0x6c, 0x2c, 0x70, 0x2c, 0x70, 0x72, 0x65, 0x2c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2c,
+ 0x75, 0x6c, 0x29, 0x20, 0x7e, 0x20, 0x3a, 0x69, 0x73, 0x28, 0x68, 0x31, 0x2c, 0x68, 0x32, 0x2c,
+ 0x68, 0x33, 0x2c, 0x68, 0x34, 0x2c, 0x68, 0x35, 0x2c, 0x68, 0x36, 0x29, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x79, 0x70, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x79,
+ 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61,
+ 0x6c, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x69, 0x6e,
+ 0x67, 0x73, 0x2c, 0x20, 0x68, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x79, 0x70, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68,
+ 0x79, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63,
+ 0x61, 0x6c, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x68,
+ 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x3e, 0x20, 0x2a, 0x2c, 0x20, 0x68, 0x67, 0x72,
+ 0x6f, 0x75, 0x70, 0x20, 0x3e, 0x20, 0x2a, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d,
+ 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x3e, 0x20, 0x3a, 0x6c,
+ 0x61, 0x73, 0x74, 0x2d, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x2c, 0x20, 0x68, 0x67, 0x72, 0x6f, 0x75,
+ 0x70, 0x20, 0x3e, 0x20, 0x3a, 0x6c, 0x61, 0x73, 0x74, 0x2d, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20,
+ 0x75, 0x6e, 0x73, 0x65, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31, 0x72, 0x65, 0x6d, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x66,
+ 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x20, 0x75, 0x6e, 0x73, 0x65, 0x74, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x70, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x79, 0x70, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x79, 0x2d,
+ 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c,
+ 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x29,
+ 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x3a, 0x77, 0x68, 0x65, 0x72, 0x65, 0x28, 0x64, 0x6c,
+ 0x2c, 0x6f, 0x6c, 0x2c, 0x75, 0x6c, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70,
+ 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x30, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x6c, 0x65,
+ 0x66, 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e,
+ 0x67, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74,
+ 0x2d, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x69, 0x6e, 0x6c,
+ 0x69, 0x6e, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d,
+ 0x65, 0x6e, 0x64, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64,
+ 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x65, 0x6e, 0x64, 0x3a,
+ 0x20, 0x30, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x77, 0x68,
+ 0x65, 0x72, 0x65, 0x28, 0x64, 0x6c, 0x2c, 0x6f, 0x6c, 0x2c, 0x75, 0x6c, 0x29, 0x20, 0x6c, 0x69,
+ 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67,
+ 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x79, 0x70, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x79,
+ 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61,
+ 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x2e, 0x32, 0x35, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x77, 0x68, 0x65, 0x72, 0x65, 0x28, 0x64,
+ 0x6c, 0x2c, 0x6f, 0x6c, 0x2c, 0x75, 0x6c, 0x29, 0x20, 0x3a, 0x69, 0x73, 0x28, 0x64, 0x6c, 0x2c,
+ 0x6f, 0x6c, 0x2c, 0x75, 0x6c, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x74, 0x6f, 0x70,
+ 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x79, 0x70,
+ 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x79, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d,
+ 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x2e, 0x32, 0x35, 0x29,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x75, 0x6c, 0x20, 0x6c, 0x69,
+ 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x2d, 0x73, 0x74, 0x79,
+ 0x6c, 0x65, 0x3a, 0x20, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x6d, 0x61, 0x72, 0x6b, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64,
+ 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x2e, 0x31, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x20, 0x2e, 0x32,
+ 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x6d, 0x61, 0x72, 0x6b, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75,
+ 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x61, 0x72,
+ 0x6b, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76,
+ 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x62,
+ 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x62, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x74, 0x79, 0x70, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x79, 0x2d, 0x73, 0x70,
+ 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20,
+ 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x69, 0x67,
+ 0x68, 0x74, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x20, 0x2e, 0x32, 0x35, 0x72,
+ 0x65, 0x6d, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77,
+ 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x73, 0x74, 0x61,
+ 0x72, 0x74, 0x3a, 0x20, 0x30, 0x2e, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x20, 0x73, 0x6f, 0x6c, 0x69,
+ 0x64, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x71, 0x75, 0x6f,
+ 0x74, 0x65, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x69, 0x6e,
+ 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20, 0x30, 0x2e, 0x32, 0x35,
+ 0x72, 0x65, 0x6d, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65,
+ 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x65, 0x6e,
+ 0x64, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x2d, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x65, 0x6e, 0x64, 0x3a,
+ 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x20, 0x66, 0x6f, 0x6f, 0x74, 0x65,
+ 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72,
+ 0x67, 0x69, 0x6e, 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x79, 0x70, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x79, 0x2d, 0x73,
+ 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29,
+ 0x20, 0x2a, 0x20, 0x2e, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x2d, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x61, 0x62, 0x62, 0x72, 0x5b, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x5d, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f,
+ 0x6d, 0x3a, 0x20, 0x31, 0x70, 0x78, 0x20, 0x64, 0x6f, 0x74, 0x74, 0x65, 0x64, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x65, 0x6c, 0x70, 0x0d, 0x0a, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x69, 0x6e, 0x73, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x69, 0x6e, 0x73, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74,
+ 0x2d, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x6e, 0x6f, 0x6e,
+ 0x65, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x64, 0x65, 0x6c, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x64, 0x65, 0x6c, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x3a, 0x3a, 0x2d, 0x6d, 0x6f, 0x7a, 0x2d, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x0d,
+ 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x3a, 0x3a, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x0d,
+ 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x3a, 0x77, 0x68, 0x65, 0x72, 0x65, 0x28, 0x61, 0x75, 0x64,
+ 0x69, 0x6f, 0x2c, 0x63, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x2c, 0x69, 0x66, 0x72, 0x61, 0x6d, 0x65,
+ 0x2c, 0x69, 0x6d, 0x67, 0x2c, 0x73, 0x76, 0x67, 0x2c, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x29, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x2d,
+ 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x0d, 0x0a, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2c, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6f,
+ 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a,
+ 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x0d, 0x0a, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x3a, 0x6e, 0x6f,
+ 0x74, 0x28, 0x5b, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x73, 0x5d, 0x29, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79,
+ 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x3a, 0x77, 0x68, 0x65, 0x72, 0x65, 0x28, 0x69, 0x66, 0x72, 0x61,
+ 0x6d, 0x65, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65,
+ 0x72, 0x2d, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x0d, 0x0a, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x69, 0x6d, 0x67, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d,
+ 0x61, 0x78, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x61, 0x75, 0x74,
+ 0x6f, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x73,
+ 0x74, 0x79, 0x6c, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x3a, 0x77, 0x68, 0x65, 0x72, 0x65, 0x28, 0x73, 0x76, 0x67, 0x3a, 0x6e, 0x6f, 0x74, 0x28,
+ 0x5b, 0x66, 0x69, 0x6c, 0x6c, 0x5d, 0x29, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x66, 0x69, 0x6c, 0x6c, 0x3a, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x76, 0x67, 0x3a, 0x6e, 0x6f, 0x74,
+ 0x28, 0x3a, 0x72, 0x6f, 0x6f, 0x74, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f,
+ 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x3a, 0x20, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x0d,
+ 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x3a, 0x20, 0x76, 0x69,
+ 0x73, 0x69, 0x62, 0x6c, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74,
+ 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x20, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x74, 0x72, 0x61, 0x6e,
+ 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x2c,
+ 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5d, 0x2c, 0x20, 0x5b,
+ 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x2c, 0x20, 0x62, 0x75,
+ 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62,
+ 0x6b, 0x69, 0x74, 0x2d, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x3a, 0x20,
+ 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x62, 0x75, 0x74,
+ 0x74, 0x6f, 0x6e, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c,
+ 0x61, 0x79, 0x3a, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x0d,
+ 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74,
+ 0x6f, 0x6e, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c,
+ 0x61, 0x79, 0x3a, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x64, 0x65, 0x63, 0x6f,
+ 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x0d, 0x0a, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d,
+ 0x2c, 0x20, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b,
+ 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x2c, 0x20, 0x69, 0x6e,
+ 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5d, 0x2c,
+ 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d,
+ 0x69, 0x74, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72,
+ 0x79, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2d,
+ 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x3a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2d, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68,
+ 0x61, 0x64, 0x6f, 0x77, 0x2c, 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x20, 0x72, 0x67, 0x62, 0x61,
+ 0x28, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x29, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d,
+ 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c,
+ 0x29, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65,
+ 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72,
+ 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72,
+ 0x64, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65,
+ 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x3a, 0x20, 0x30, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x61,
+ 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77,
+ 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64,
+ 0x6f, 0x77, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67,
+ 0x68, 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73,
+ 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e,
+ 0x3a, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63,
+ 0x75, 0x72, 0x73, 0x6f, 0x72, 0x3a, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a,
+ 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69,
+ 0x6f, 0x6e, 0x29, 0x2c, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f,
+ 0x6e, 0x29, 0x2c, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74,
+ 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x62, 0x6f, 0x78, 0x2d, 0x73,
+ 0x68, 0x61, 0x64, 0x6f, 0x77, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e,
+ 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x3a,
+ 0x69, 0x73, 0x28, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74,
+ 0x5d, 0x2c, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65,
+ 0x2c, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e,
+ 0x3a, 0x69, 0x73, 0x28, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
+ 0x74, 0x5d, 0x2c, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76,
+ 0x65, 0x2c, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74,
+ 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x3a, 0x69, 0x73,
+ 0x28, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5d, 0x2c,
+ 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x3a,
+ 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79,
+ 0x70, 0x65, 0x3d, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5d, 0x3a, 0x69, 0x73, 0x28, 0x5b, 0x61, 0x72,
+ 0x69, 0x61, 0x2d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5d, 0x2c, 0x3a, 0x68, 0x6f, 0x76,
+ 0x65, 0x72, 0x2c, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x3a, 0x66, 0x6f, 0x63, 0x75,
+ 0x73, 0x29, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73,
+ 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x3a, 0x69, 0x73, 0x28, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d,
+ 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5d, 0x2c, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c,
+ 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x68, 0x6f, 0x76,
+ 0x65, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x68, 0x6f, 0x76, 0x65,
+ 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62,
+ 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x62, 0x6f,
+ 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x2c, 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x20,
+ 0x72, 0x67, 0x62, 0x61, 0x28, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x29,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61,
+ 0x72, 0x79, 0x2d, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d,
+ 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2c, 0x20, 0x62,
+ 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x70,
+ 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x3a,
+ 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70,
+ 0x65, 0x3d, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5d, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2c, 0x20,
+ 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69,
+ 0x74, 0x5d, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77,
+ 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2d, 0x68,
+ 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x2c,
+ 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x30, 0x2c, 0x20, 0x30,
+ 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x29, 0x29, 0x2c, 0x30, 0x20, 0x30, 0x20, 0x30, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x77, 0x69, 0x64,
+ 0x74, 0x68, 0x29, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72,
+ 0x79, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x3a, 0x69, 0x73, 0x28, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2c, 0x69, 0x6e,
+ 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d,
+ 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74,
+ 0x6f, 0x6e, 0x5d, 0x2c, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e,
+ 0x5d, 0x29, 0x2e, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x69, 0x6e,
+ 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5d, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72,
+ 0x79, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72,
+ 0x79, 0x2d, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x3a, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72,
+ 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x69, 0x73, 0x28, 0x62,
+ 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65,
+ 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74,
+ 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x2c, 0x5b, 0x72, 0x6f, 0x6c,
+ 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x29, 0x2e, 0x73, 0x65, 0x63, 0x6f, 0x6e,
+ 0x64, 0x61, 0x72, 0x79, 0x3a, 0x69, 0x73, 0x28, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x63, 0x75,
+ 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5d, 0x2c, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x3a, 0x61,
+ 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x2c, 0x20, 0x69,
+ 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5d,
+ 0x3a, 0x69, 0x73, 0x28, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
+ 0x74, 0x5d, 0x2c, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76,
+ 0x65, 0x2c, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73,
+ 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64,
+ 0x61, 0x72, 0x79, 0x2d, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x29, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x69, 0x73, 0x28, 0x62,
+ 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65,
+ 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74,
+ 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x2c, 0x5b, 0x72, 0x6f, 0x6c,
+ 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x29, 0x2e, 0x73, 0x65, 0x63, 0x6f, 0x6e,
+ 0x64, 0x61, 0x72, 0x79, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75,
+ 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5d, 0x3a, 0x66, 0x6f,
+ 0x63, 0x75, 0x73, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x3a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2d,
+ 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x2c, 0x20, 0x30, 0x20, 0x30, 0x20,
+ 0x30, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20,
+ 0x30, 0x29, 0x29, 0x2c, 0x30, 0x20, 0x30, 0x20, 0x30, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2d, 0x66,
+ 0x6f, 0x63, 0x75, 0x73, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x3a, 0x69, 0x73, 0x28, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74,
+ 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x2c, 0x69, 0x6e,
+ 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d,
+ 0x2c, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x29, 0x2e,
+ 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61,
+ 0x73, 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63,
+ 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x2d, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x29,
+ 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x69, 0x73, 0x28, 0x62,
+ 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65,
+ 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74,
+ 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x2c, 0x5b, 0x72, 0x6f, 0x6c,
+ 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
+ 0x61, 0x73, 0x74, 0x3a, 0x69, 0x73, 0x28, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x63, 0x75, 0x72,
+ 0x72, 0x65, 0x6e, 0x74, 0x5d, 0x2c, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x3a, 0x61, 0x63,
+ 0x74, 0x69, 0x76, 0x65, 0x2c, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72,
+ 0x61, 0x73, 0x74, 0x2d, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x29, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x69, 0x73, 0x28, 0x62,
+ 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65,
+ 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74,
+ 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x2c, 0x5b, 0x72, 0x6f, 0x6c,
+ 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
+ 0x61, 0x73, 0x74, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f,
+ 0x77, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2d,
+ 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77,
+ 0x2c, 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x20, 0x72, 0x67, 0x62, 0x61, 0x28, 0x30, 0x2c, 0x20,
+ 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x29, 0x29, 0x2c, 0x30, 0x20, 0x30, 0x20, 0x30, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x77, 0x69,
+ 0x64, 0x74, 0x68, 0x29, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72,
+ 0x61, 0x73, 0x74, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x3a, 0x69, 0x73, 0x28, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2c,
+ 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69,
+ 0x74, 0x5d, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75,
+ 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x2c, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74,
+ 0x6f, 0x6e, 0x5d, 0x29, 0x2e, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x2c, 0x20, 0x69, 0x6e,
+ 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5d, 0x2e,
+ 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x29, 0x0d, 0x0a, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x69, 0x73, 0x28, 0x62, 0x75, 0x74, 0x74, 0x6f,
+ 0x6e, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62,
+ 0x6d, 0x69, 0x74, 0x5d, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d,
+ 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x2c, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75,
+ 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x29, 0x2e, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x3a, 0x69,
+ 0x73, 0x28, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5d,
+ 0x2c, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c,
+ 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74,
+ 0x79, 0x70, 0x65, 0x3d, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5d, 0x2e, 0x6f, 0x75, 0x74, 0x6c, 0x69,
+ 0x6e, 0x65, 0x3a, 0x69, 0x73, 0x28, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x63, 0x75, 0x72, 0x72,
+ 0x65, 0x6e, 0x74, 0x5d, 0x2c, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x3a, 0x61, 0x63, 0x74,
+ 0x69, 0x76, 0x65, 0x2c, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73,
+ 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x29, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x69, 0x73,
+ 0x28, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79,
+ 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74,
+ 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x2c, 0x5b, 0x72,
+ 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x29, 0x2e, 0x6f, 0x75, 0x74,
+ 0x6c, 0x69, 0x6e, 0x65, 0x2e, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2c, 0x20,
+ 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x65, 0x73, 0x65, 0x74,
+ 0x5d, 0x2e, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x29, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3a, 0x69, 0x73, 0x28, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2c, 0x69, 0x6e, 0x70, 0x75,
+ 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x2c, 0x69,
+ 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e,
+ 0x5d, 0x2c, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x29,
+ 0x2e, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x2e, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61,
+ 0x72, 0x79, 0x3a, 0x69, 0x73, 0x28, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x63, 0x75, 0x72, 0x72,
+ 0x65, 0x6e, 0x74, 0x5d, 0x2c, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x3a, 0x61, 0x63, 0x74,
+ 0x69, 0x76, 0x65, 0x2c, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x2c, 0x20, 0x69, 0x6e, 0x70,
+ 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5d, 0x2e, 0x6f,
+ 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x3a, 0x69, 0x73, 0x28, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d,
+ 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5d, 0x2c, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c,
+ 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65,
+ 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x29, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x3a, 0x69, 0x73, 0x28, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2c, 0x69, 0x6e, 0x70, 0x75,
+ 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x2c, 0x69,
+ 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e,
+ 0x5d, 0x2c, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x29,
+ 0x2e, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73,
+ 0x74, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6e, 0x74,
+ 0x72, 0x61, 0x73, 0x74, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x69, 0x73, 0x28, 0x62, 0x75, 0x74, 0x74,
+ 0x6f, 0x6e, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x75,
+ 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65,
+ 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x2c, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62,
+ 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x29, 0x2e, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x2e,
+ 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x3a, 0x69, 0x73, 0x28, 0x5b, 0x61, 0x72, 0x69,
+ 0x61, 0x2d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5d, 0x2c, 0x3a, 0x68, 0x6f, 0x76, 0x65,
+ 0x72, 0x2c, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73,
+ 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x29, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x3a, 0x77,
+ 0x68, 0x65, 0x72, 0x65, 0x28, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2c, 0x5b, 0x74, 0x79, 0x70,
+ 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d,
+ 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x65,
+ 0x73, 0x65, 0x74, 0x5d, 0x2c, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f,
+ 0x6e, 0x5d, 0x29, 0x5b, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5d, 0x2c, 0x20, 0x3a,
+ 0x77, 0x68, 0x65, 0x72, 0x65, 0x28, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x65, 0x74, 0x5b, 0x64,
+ 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5d, 0x29, 0x20, 0x3a, 0x69, 0x73, 0x28, 0x62, 0x75,
+ 0x74, 0x74, 0x6f, 0x6e, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69,
+ 0x74, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d,
+ 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5d, 0x2c, 0x5b, 0x72,
+ 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x29, 0x2c, 0x20, 0x61, 0x5b,
+ 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x3a, 0x6e, 0x6f, 0x74,
+ 0x28, 0x5b, 0x68, 0x72, 0x65, 0x66, 0x5d, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x2e, 0x35, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73,
+ 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x69, 0x6e, 0x70,
+ 0x75, 0x74, 0x2c, 0x20, 0x6f, 0x70, 0x74, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x2c, 0x20, 0x73, 0x65,
+ 0x6c, 0x65, 0x63, 0x74, 0x2c, 0x20, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a,
+ 0x20, 0x31, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65,
+ 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6c,
+ 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x20, 0x69,
+ 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74,
+ 0x74, 0x65, 0x72, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x69, 0x6e, 0x68,
+ 0x65, 0x72, 0x69, 0x74, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x69, 0x6e, 0x70, 0x75, 0x74,
+ 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77,
+ 0x3a, 0x20, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65,
+ 0x78, 0x74, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x6e, 0x6f,
+ 0x6e, 0x65, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x6c, 0x65, 0x67, 0x65, 0x6e, 0x64, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68,
+ 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64,
+ 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x65, 0x3a, 0x20,
+ 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x65, 0x78,
+ 0x74, 0x61, 0x72, 0x65, 0x61, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x76, 0x65,
+ 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x3a, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78,
+ 0x5d, 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x5d, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20,
+ 0x30, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x3a, 0x3a, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69,
+ 0x74, 0x2d, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x2d, 0x73, 0x70, 0x69, 0x6e, 0x2d, 0x62, 0x75, 0x74,
+ 0x74, 0x6f, 0x6e, 0x2c, 0x20, 0x3a, 0x3a, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x6f,
+ 0x75, 0x74, 0x65, 0x72, 0x2d, 0x73, 0x70, 0x69, 0x6e, 0x2d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e,
+ 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20,
+ 0x61, 0x75, 0x74, 0x6f, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x5b, 0x74, 0x79, 0x70, 0x65,
+ 0x3d, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e,
+ 0x63, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x6f, 0x66, 0x66, 0x73,
+ 0x65, 0x74, 0x3a, 0x20, 0x2d, 0x32, 0x70, 0x78, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5d,
+ 0x3a, 0x3a, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68,
+ 0x2d, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x61,
+ 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x3a, 0x3a, 0x2d, 0x77, 0x65, 0x62,
+ 0x6b, 0x69, 0x74, 0x2d, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x2d,
+ 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77,
+ 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65,
+ 0x3a, 0x20, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66,
+ 0x6f, 0x6e, 0x74, 0x3a, 0x20, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x0d, 0x0a, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x3a, 0x3a, 0x2d, 0x6d, 0x6f, 0x7a, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2d,
+ 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64,
+ 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x2d, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65,
+ 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x3a, 0x2d, 0x6d, 0x6f, 0x7a, 0x2d, 0x66, 0x6f, 0x63,
+ 0x75, 0x73, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75,
+ 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x3a,
+ 0x2d, 0x6d, 0x6f, 0x7a, 0x2d, 0x75, 0x69, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f,
+ 0x77, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x3a, 0x3a,
+ 0x2d, 0x6d, 0x73, 0x2d, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x0d,
+ 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69, 0x6c, 0x65,
+ 0x5d, 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5d, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20,
+ 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x77,
+ 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x69, 0x6e,
+ 0x70, 0x75, 0x74, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68,
+ 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61,
+ 0x64, 0x69, 0x6f, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x6e, 0x67, 0x65,
+ 0x5d, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74,
+ 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x31, 0x72, 0x65, 0x6d, 0x20, 0x2a, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x29,
+ 0x20, 0x2b, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65,
+ 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x32, 0x20, 0x2b, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68,
+ 0x29, 0x20, 0x2a, 0x20, 0x32, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x66, 0x69, 0x65,
+ 0x6c, 0x64, 0x73, 0x65, 0x74, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72,
+ 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72,
+ 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x65, 0x74, 0x20, 0x6c,
+ 0x65, 0x67, 0x65, 0x6e, 0x64, 0x2c, 0x20, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a,
+ 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20,
+ 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69,
+ 0x6e, 0x67, 0x29, 0x20, 0x2a, 0x20, 0x2e, 0x32, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74,
+ 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x6c, 0x61, 0x62,
+ 0x65, 0x6c, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x2c, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74,
+ 0x29, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x69, 0x6e, 0x70,
+ 0x75, 0x74, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65,
+ 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64,
+ 0x69, 0x6f, 0x5d, 0x29, 0x2c, 0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x2c, 0x20, 0x74, 0x65,
+ 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69,
+ 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x69, 0x6e, 0x70, 0x75, 0x74, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d,
+ 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d,
+ 0x72, 0x61, 0x64, 0x69, 0x6f, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x6e,
+ 0x67, 0x65, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69, 0x6c, 0x65, 0x5d, 0x29,
+ 0x2c, 0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x2c, 0x20, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72,
+ 0x65, 0x61, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69,
+ 0x74, 0x2d, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x3a, 0x20, 0x6e, 0x6f,
+ 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x6d, 0x6f, 0x7a, 0x2d, 0x61, 0x70,
+ 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x3a,
+ 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64,
+ 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d,
+ 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d,
+ 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61,
+ 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29,
+ 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x73, 0x65,
+ 0x6c, 0x65, 0x63, 0x74, 0x2c, 0x20, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75,
+ 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d,
+ 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d,
+ 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f,
+ 0x77, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x3a, 0x20, 0x30, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f,
+ 0x77, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74,
+ 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e,
+ 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x62,
+ 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x77, 0x68, 0x65, 0x72, 0x65, 0x28, 0x73, 0x65, 0x6c,
+ 0x65, 0x63, 0x74, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x29, 0x3a, 0x69, 0x73,
+ 0x28, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29,
+ 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x74, 0x79, 0x70,
+ 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d,
+ 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x65,
+ 0x73, 0x65, 0x74, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b,
+ 0x62, 0x6f, 0x78, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69, 0x6f,
+ 0x5d, 0x2c, 0x5b, 0x72, 0x65, 0x61, 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x5d, 0x29, 0x3a, 0x69, 0x73,
+ 0x28, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29,
+ 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x61,
+ 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x77, 0x68, 0x65, 0x72, 0x65,
+ 0x28, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61,
+ 0x29, 0x3a, 0x69, 0x73, 0x28, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x3a, 0x66, 0x6f,
+ 0x63, 0x75, 0x73, 0x29, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x3a, 0x6e, 0x6f, 0x74, 0x28,
+ 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x2c, 0x5b, 0x74,
+ 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70,
+ 0x65, 0x3d, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5d, 0x2c, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x73,
+ 0x77, 0x69, 0x74, 0x63, 0x68, 0x5d, 0x2c, 0x5b, 0x72, 0x65, 0x61, 0x64, 0x6f, 0x6e, 0x6c, 0x79,
+ 0x5d, 0x29, 0x3a, 0x69, 0x73, 0x28, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x3a, 0x66,
+ 0x6f, 0x63, 0x75, 0x73, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d,
+ 0x65, 0x6e, 0x74, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65,
+ 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x3a, 0x6e, 0x6f, 0x74,
+ 0x28, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x2c, 0x5b,
+ 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x2c, 0x5b, 0x74, 0x79,
+ 0x70, 0x65, 0x3d, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d,
+ 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69, 0x6c,
+ 0x65, 0x5d, 0x2c, 0x5b, 0x72, 0x65, 0x61, 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x5d, 0x29, 0x3a, 0x66,
+ 0x6f, 0x63, 0x75, 0x73, 0x2c, 0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x3a, 0x66, 0x6f, 0x63,
+ 0x75, 0x73, 0x2c, 0x20, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x3a, 0x66, 0x6f, 0x63,
+ 0x75, 0x73, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x3a, 0x20, 0x30, 0x20, 0x30, 0x20,
+ 0x30, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x2d,
+ 0x77, 0x69, 0x64, 0x74, 0x68, 0x29, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72,
+ 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x77, 0x68, 0x65, 0x72, 0x65, 0x28, 0x66, 0x69, 0x65, 0x6c,
+ 0x64, 0x73, 0x65, 0x74, 0x5b, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5d, 0x29, 0x20,
+ 0x3a, 0x69, 0x73, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x74,
+ 0x79, 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70,
+ 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d,
+ 0x72, 0x65, 0x73, 0x65, 0x74, 0x5d, 0x29, 0x2c, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x2c, 0x74,
+ 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x29, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x3a,
+ 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74,
+ 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x2c,
+ 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5d, 0x29, 0x5b, 0x64, 0x69,
+ 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5d, 0x2c, 0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x5b,
+ 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5d, 0x2c, 0x20, 0x74, 0x65, 0x78, 0x74, 0x61,
+ 0x72, 0x65, 0x61, 0x5b, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5d, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d,
+ 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d,
+ 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64,
+ 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79,
+ 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65,
+ 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2d, 0x6f, 0x70,
+ 0x61, 0x63, 0x69, 0x74, 0x79, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x3a,
+ 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x3a, 0x77, 0x68, 0x65, 0x72, 0x65, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x73, 0x65, 0x6c,
+ 0x65, 0x63, 0x74, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x29, 0x3a, 0x6e, 0x6f,
+ 0x74, 0x28, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78,
+ 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x5d, 0x2c, 0x5b,
+ 0x74, 0x79, 0x70, 0x65, 0x3d, 0x64, 0x61, 0x74, 0x65, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65,
+ 0x3d, 0x64, 0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x2d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5d,
+ 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x5d, 0x2c, 0x5b, 0x74,
+ 0x79, 0x70, 0x65, 0x3d, 0x74, 0x69, 0x6d, 0x65, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d,
+ 0x77, 0x65, 0x65, 0x6b, 0x5d, 0x29, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x69, 0x6e, 0x76, 0x61,
+ 0x6c, 0x69, 0x64, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64,
+ 0x69, 0x6e, 0x67, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a,
+ 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x20, 0x2b, 0x20, 0x31, 0x2e, 0x35, 0x72, 0x65, 0x6d, 0x29,
+ 0x20, 0x21, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6e, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a,
+ 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65,
+ 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x73, 0x74, 0x61,
+ 0x72, 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65,
+ 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68,
+ 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x20, 0x21, 0x69, 0x6d, 0x70, 0x6f,
+ 0x72, 0x74, 0x61, 0x6e, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64,
+ 0x69, 0x6e, 0x67, 0x2d, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74,
+ 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65,
+ 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72,
+ 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x20, 0x21, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74,
+ 0x61, 0x6e, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69,
+ 0x74, 0x2d, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x65, 0x6e, 0x64, 0x3a, 0x20, 0x63,
+ 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65,
+ 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68,
+ 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x20, 0x2b, 0x20, 0x31, 0x2e, 0x35,
+ 0x72, 0x65, 0x6d, 0x29, 0x20, 0x21, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6e, 0x74, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x69, 0x6e,
+ 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x65, 0x6e, 0x64, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f,
+ 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x20, 0x2b, 0x20, 0x31, 0x2e, 0x35, 0x72, 0x65, 0x6d, 0x29, 0x20,
+ 0x21, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6e, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x73, 0x69,
+ 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x72, 0x69, 0x67,
+ 0x68, 0x74, 0x20, 0x2e, 0x37, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a,
+ 0x20, 0x31, 0x72, 0x65, 0x6d, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x72, 0x65, 0x70, 0x65,
+ 0x61, 0x74, 0x3a, 0x20, 0x6e, 0x6f, 0x2d, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x0d, 0x0a, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x3a, 0x77, 0x68, 0x65, 0x72, 0x65, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74,
+ 0x2c, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61,
+ 0x29, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63,
+ 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69,
+ 0x6f, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x64, 0x61, 0x74, 0x65, 0x5d, 0x2c, 0x5b,
+ 0x74, 0x79, 0x70, 0x65, 0x3d, 0x64, 0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x2d, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x6d, 0x6f, 0x6e, 0x74, 0x68,
+ 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x74, 0x69, 0x6d, 0x65, 0x5d, 0x2c, 0x5b, 0x74,
+ 0x79, 0x70, 0x65, 0x3d, 0x77, 0x65, 0x65, 0x6b, 0x5d, 0x29, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d,
+ 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x3d, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x5d, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x2d, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x69, 0x63,
+ 0x6f, 0x6e, 0x2d, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x3a, 0x77, 0x68, 0x65, 0x72, 0x65, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x73, 0x65, 0x6c,
+ 0x65, 0x63, 0x74, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x29, 0x3a, 0x6e, 0x6f,
+ 0x74, 0x28, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78,
+ 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x5d, 0x2c, 0x5b,
+ 0x74, 0x79, 0x70, 0x65, 0x3d, 0x64, 0x61, 0x74, 0x65, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65,
+ 0x3d, 0x64, 0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x2d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5d,
+ 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x5d, 0x2c, 0x5b, 0x74,
+ 0x79, 0x70, 0x65, 0x3d, 0x74, 0x69, 0x6d, 0x65, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d,
+ 0x77, 0x65, 0x65, 0x6b, 0x5d, 0x29, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x69, 0x6e, 0x76, 0x61,
+ 0x6c, 0x69, 0x64, 0x3d, 0x74, 0x72, 0x75, 0x65, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x69, 0x6d, 0x61, 0x67,
+ 0x65, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x69, 0x6e,
+ 0x76, 0x61, 0x6c, 0x69, 0x64, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x3a, 0x77, 0x68,
+ 0x65, 0x72, 0x65, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74,
+ 0x2c, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x29, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d,
+ 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x3d, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x5d, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d,
+ 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x2d, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x77, 0x68, 0x65, 0x72, 0x65, 0x28, 0x69, 0x6e,
+ 0x70, 0x75, 0x74, 0x2c, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x61,
+ 0x72, 0x65, 0x61, 0x29, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69,
+ 0x64, 0x3d, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x5d, 0x3a, 0x69, 0x73, 0x28, 0x3a, 0x61, 0x63, 0x74,
+ 0x69, 0x76, 0x65, 0x2c, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72,
+ 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x2d,
+ 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x29, 0x20, 0x21, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6e, 0x74, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x78, 0x2d,
+ 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x3a, 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74,
+ 0x68, 0x29, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x2d, 0x66, 0x6f, 0x63, 0x75,
+ 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x20, 0x21, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74,
+ 0x61, 0x6e, 0x74, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x3a, 0x77,
+ 0x68, 0x65, 0x72, 0x65, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x73, 0x65, 0x6c, 0x65, 0x63,
+ 0x74, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x29, 0x5b, 0x61, 0x72, 0x69, 0x61,
+ 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x3d, 0x74, 0x72, 0x75, 0x65, 0x5d, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d,
+ 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64,
+ 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a,
+ 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3a, 0x77, 0x68, 0x65, 0x72, 0x65, 0x28,
+ 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x2c, 0x74, 0x65, 0x78,
+ 0x74, 0x61, 0x72, 0x65, 0x61, 0x29, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x69, 0x6e, 0x76, 0x61,
+ 0x6c, 0x69, 0x64, 0x3d, 0x74, 0x72, 0x75, 0x65, 0x5d, 0x3a, 0x69, 0x73, 0x28, 0x3a, 0x61, 0x63,
+ 0x74, 0x69, 0x76, 0x65, 0x2c, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f,
+ 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c,
+ 0x69, 0x64, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x20, 0x21, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61,
+ 0x6e, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62,
+ 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x3a, 0x20, 0x30, 0x20, 0x30, 0x20, 0x30,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x77,
+ 0x69, 0x64, 0x74, 0x68, 0x29, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d,
+ 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64,
+ 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x20, 0x21, 0x69,
+ 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6e, 0x74, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x5b, 0x64, 0x69, 0x72, 0x3d, 0x72, 0x74, 0x6c, 0x5d, 0x20, 0x3a, 0x77, 0x68,
+ 0x65, 0x72, 0x65, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74,
+ 0x2c, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x29, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x5b,
+ 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x2c, 0x5b,
+ 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x5d, 0x29, 0x3a, 0x69, 0x73, 0x28,
+ 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5d, 0x2c, 0x5b,
+ 0x61, 0x72, 0x69, 0x61, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x3d, 0x74, 0x72, 0x75,
+ 0x65, 0x5d, 0x2c, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64,
+ 0x3d, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x5d, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x73, 0x69, 0x74,
+ 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x6c, 0x65, 0x66, 0x74,
+ 0x20, 0x2e, 0x37, 0x35, 0x72, 0x65, 0x6d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x69, 0x6e,
+ 0x70, 0x75, 0x74, 0x3a, 0x3a, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x69, 0x6e, 0x70,
+ 0x75, 0x74, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x2c, 0x20,
+ 0x69, 0x6e, 0x70, 0x75, 0x74, 0x3a, 0x3a, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64,
+ 0x65, 0x72, 0x2c, 0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x3a, 0x69, 0x6e, 0x76, 0x61, 0x6c,
+ 0x69, 0x64, 0x2c, 0x20, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x3a, 0x3a, 0x2d, 0x77,
+ 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2d, 0x70, 0x6c, 0x61, 0x63,
+ 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x2c, 0x20, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65,
+ 0x61, 0x3a, 0x3a, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d,
+ 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79,
+ 0x3a, 0x20, 0x31, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x3a,
+ 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62,
+ 0x6f, 0x78, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x5d,
+ 0x29, 0x2c, 0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x2c, 0x20, 0x74, 0x65, 0x78, 0x74, 0x61,
+ 0x72, 0x65, 0x61, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69,
+ 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x3a, 0x3a, 0x2d, 0x6d, 0x73, 0x2d, 0x65,
+ 0x78, 0x70, 0x61, 0x6e, 0x64, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65,
+ 0x6e, 0x74, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x6d, 0x75, 0x6c,
+ 0x74, 0x69, 0x70, 0x6c, 0x65, 0x5d, 0x2c, 0x5b, 0x73, 0x69, 0x7a, 0x65, 0x5d, 0x29, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e,
+ 0x67, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74,
+ 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e,
+ 0x74, 0x61, 0x6c, 0x29, 0x20, 0x2b, 0x20, 0x31, 0x2e, 0x35, 0x72, 0x65, 0x6d, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
+ 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72,
+ 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e,
+ 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d,
+ 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f,
+ 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x73,
+ 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d,
+ 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67,
+ 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x70,
+ 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x65, 0x6e, 0x64, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63,
+ 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d,
+ 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69,
+ 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x20, 0x2b, 0x20, 0x31, 0x2e, 0x35, 0x72, 0x65, 0x6d,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64,
+ 0x69, 0x6e, 0x67, 0x2d, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x65, 0x6e, 0x64, 0x3a, 0x20,
+ 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d,
+ 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d,
+ 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x20, 0x2b, 0x20, 0x31, 0x2e,
+ 0x35, 0x72, 0x65, 0x6d, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x69, 0x6d, 0x61, 0x67, 0x65,
+ 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x63, 0x68, 0x65,
+ 0x76, 0x72, 0x6f, 0x6e, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x73, 0x69, 0x74,
+ 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x72, 0x69, 0x67, 0x68,
+ 0x74, 0x20, 0x2e, 0x37, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x73, 0x69,
+ 0x7a, 0x65, 0x3a, 0x20, 0x31, 0x72, 0x65, 0x6d, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75,
+ 0x6e, 0x64, 0x2d, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x3a, 0x20, 0x6e, 0x6f, 0x2d, 0x72, 0x65,
+ 0x70, 0x65, 0x61, 0x74, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x5b,
+ 0x64, 0x69, 0x72, 0x3d, 0x72, 0x74, 0x6c, 0x5d, 0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x3a,
+ 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x5d, 0x2c, 0x5b,
+ 0x73, 0x69, 0x7a, 0x65, 0x5d, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61,
+ 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f,
+ 0x6e, 0x3a, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x2e,
+ 0x37, 0x35, 0x72, 0x65, 0x6d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x3a, 0x77, 0x68, 0x65,
+ 0x72, 0x65, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x2c,
+ 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x2c, 0x2e, 0x67, 0x72, 0x69, 0x64, 0x29, 0x20,
+ 0x2b, 0x20, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64,
+ 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x74, 0x6f, 0x70,
+ 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61,
+ 0x63, 0x69, 0x6e, 0x67, 0x29, 0x20, 0x2a, 0x20, 0x2d, 0x2e, 0x37, 0x35, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f,
+ 0x6d, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x20, 0x3e, 0x20,
+ 0x3a, 0x77, 0x68, 0x65, 0x72, 0x65, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x73, 0x65, 0x6c,
+ 0x65, 0x63, 0x74, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x29, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x74, 0x6f, 0x70, 0x3a,
+ 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63,
+ 0x69, 0x6e, 0x67, 0x29, 0x20, 0x2a, 0x20, 0x2e, 0x32, 0x35, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78,
+ 0x5d, 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x5d, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x61,
+ 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x6d, 0x6f, 0x7a, 0x2d, 0x61, 0x70, 0x70, 0x65, 0x61,
+ 0x72, 0x61, 0x6e, 0x63, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x3a, 0x20, 0x6e, 0x6f,
+ 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20,
+ 0x31, 0x2e, 0x32, 0x35, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x68, 0x65, 0x69,
+ 0x67, 0x68, 0x74, 0x3a, 0x20, 0x31, 0x2e, 0x32, 0x35, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x2d, 0x2e,
+ 0x31, 0x32, 0x35, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67,
+ 0x69, 0x6e, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x2e, 0x33, 0x37, 0x35, 0x65, 0x6d,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65,
+ 0x66, 0x74, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62,
+ 0x6b, 0x69, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74,
+ 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e,
+ 0x2d, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20, 0x30,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x6d,
+ 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x65, 0x6e, 0x64, 0x3a, 0x20, 0x2e, 0x33, 0x37, 0x35, 0x65,
+ 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x69,
+ 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x65, 0x6e, 0x64, 0x3a, 0x20, 0x2e, 0x33, 0x37, 0x35, 0x65,
+ 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x77,
+ 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x69, 0x6e, 0x68, 0x65, 0x72,
+ 0x69, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61,
+ 0x6c, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x3a, 0x20, 0x70, 0x6f,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x3a,
+ 0x3a, 0x2d, 0x6d, 0x73, 0x2d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70,
+ 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x5d, 0x3a, 0x3a, 0x2d, 0x6d, 0x73, 0x2d, 0x63, 0x68,
+ 0x65, 0x63, 0x6b, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64,
+ 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65,
+ 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x3a, 0x63, 0x68, 0x65, 0x63, 0x6b,
+ 0x65, 0x64, 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62,
+ 0x6f, 0x78, 0x5d, 0x3a, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x3a, 0x61, 0x63, 0x74, 0x69,
+ 0x76, 0x65, 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62,
+ 0x6f, 0x78, 0x5d, 0x3a, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x3a, 0x66, 0x6f, 0x63, 0x75,
+ 0x73, 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x5d, 0x3a,
+ 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72,
+ 0x61, 0x64, 0x69, 0x6f, 0x5d, 0x3a, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x3a, 0x61, 0x63,
+ 0x74, 0x69, 0x76, 0x65, 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69,
+ 0x6f, 0x5d, 0x3a, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73,
+ 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x61,
+ 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65,
+ 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70,
+ 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x69, 0x6d, 0x61,
+ 0x67, 0x65, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x63,
+ 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x70, 0x6f,
+ 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x2e, 0x37, 0x35, 0x65, 0x6d, 0x20,
+ 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62,
+ 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74,
+ 0x3a, 0x20, 0x6e, 0x6f, 0x2d, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d,
+ 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x20, 0x7e, 0x20, 0x6c, 0x61, 0x62, 0x65,
+ 0x6c, 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x5d, 0x20,
+ 0x7e, 0x20, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x69, 0x6e, 0x6c, 0x69,
+ 0x6e, 0x65, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a,
+ 0x20, 0x2e, 0x33, 0x37, 0x35, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a,
+ 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x75, 0x72,
+ 0x73, 0x6f, 0x72, 0x3a, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65,
+ 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x3a, 0x69, 0x6e, 0x64, 0x65, 0x74,
+ 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72,
+ 0x69, 0x6d, 0x61, 0x72, 0x79, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x6d, 0x69, 0x6e, 0x75, 0x73, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75,
+ 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x65, 0x6e,
+ 0x74, 0x65, 0x72, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61,
+ 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x2e,
+ 0x37, 0x35, 0x65, 0x6d, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x72,
+ 0x65, 0x70, 0x65, 0x61, 0x74, 0x3a, 0x20, 0x6e, 0x6f, 0x2d, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x5b, 0x74, 0x79, 0x70, 0x65,
+ 0x3d, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x35, 0x30,
+ 0x25, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x74, 0x79, 0x70,
+ 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x5d, 0x3a, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64,
+ 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x5d, 0x3a, 0x63,
+ 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x20, 0x5b,
+ 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x5d, 0x3a, 0x63, 0x68, 0x65, 0x63,
+ 0x6b, 0x65, 0x64, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70,
+ 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x2e, 0x33, 0x35, 0x65, 0x6d, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75,
+ 0x6e, 0x64, 0x2d, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63,
+ 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x73, 0x77,
+ 0x69, 0x74, 0x63, 0x68, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62,
+ 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2d, 0x62, 0x61,
+ 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x77, 0x69, 0x74,
+ 0x63, 0x68, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69,
+ 0x64, 0x74, 0x68, 0x3a, 0x20, 0x32, 0x2e, 0x32, 0x35, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x31, 0x2e, 0x32, 0x35, 0x65, 0x6d,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x64, 0x74,
+ 0x68, 0x29, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73,
+ 0x3a, 0x20, 0x31, 0x2e, 0x32, 0x35, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62,
+ 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c,
+ 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x31, 0x2e, 0x32, 0x35,
+ 0x65, 0x6d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x74, 0x79,
+ 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x5b, 0x72, 0x6f, 0x6c,
+ 0x65, 0x3d, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x5d, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2d, 0x62, 0x61, 0x63, 0x6b,
+ 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x77,
+ 0x69, 0x74, 0x63, 0x68, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b,
+ 0x62, 0x6f, 0x78, 0x5d, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68,
+ 0x5d, 0x3a, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73,
+ 0x77, 0x69, 0x74, 0x63, 0x68, 0x2d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x2d, 0x62, 0x61,
+ 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x2d, 0x62,
+ 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b,
+ 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x5b, 0x72,
+ 0x6f, 0x6c, 0x65, 0x3d, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x5d, 0x3a, 0x62, 0x65, 0x66, 0x6f,
+ 0x72, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69,
+ 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x63, 0x61,
+ 0x6c, 0x63, 0x28, 0x31, 0x2e, 0x32, 0x35, 0x65, 0x6d, 0x20, 0x2d, 0x20, 0x28, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29,
+ 0x20, 0x2a, 0x20, 0x32, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72,
+ 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x35, 0x30, 0x25, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f,
+ 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x22, 0x22, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20,
+ 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x20, 0x2e, 0x31, 0x73, 0x20, 0x65, 0x61, 0x73, 0x65, 0x2d,
+ 0x69, 0x6e, 0x2d, 0x6f, 0x75, 0x74, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b,
+ 0x62, 0x6f, 0x78, 0x5d, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68,
+ 0x5d, 0x3a, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+ 0x69, 0x6d, 0x61, 0x67, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x74,
+ 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x5b, 0x72, 0x6f,
+ 0x6c, 0x65, 0x3d, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x5d, 0x3a, 0x63, 0x68, 0x65, 0x63, 0x6b,
+ 0x65, 0x64, 0x3a, 0x3a, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e,
+ 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x31, 0x2e, 0x31, 0x32,
+ 0x35, 0x65, 0x6d, 0x20, 0x2d, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74,
+ 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20, 0x63,
+ 0x61, 0x6c, 0x63, 0x28, 0x31, 0x2e, 0x31, 0x32, 0x35, 0x65, 0x6d, 0x20, 0x2d, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68,
+ 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x73,
+ 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x31, 0x2e, 0x31, 0x32, 0x35,
+ 0x65, 0x6d, 0x20, 0x2d, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65,
+ 0x72, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x3a,
+ 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x69, 0x6e, 0x76,
+ 0x61, 0x6c, 0x69, 0x64, 0x3d, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x5d, 0x2c, 0x20, 0x5b, 0x74, 0x79,
+ 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x5b, 0x61, 0x72, 0x69,
+ 0x61, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x3d, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x5d,
+ 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78,
+ 0x5d, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x5d, 0x3a, 0x63,
+ 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x69, 0x6e, 0x76, 0x61,
+ 0x6c, 0x69, 0x64, 0x3d, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x5d, 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70,
+ 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x5b, 0x72, 0x6f, 0x6c, 0x65,
+ 0x3d, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x5d, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x69, 0x6e,
+ 0x76, 0x61, 0x6c, 0x69, 0x64, 0x3d, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x5d, 0x2c, 0x20, 0x5b, 0x74,
+ 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x5d, 0x3a, 0x63, 0x68, 0x65, 0x63, 0x6b,
+ 0x65, 0x64, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x3d,
+ 0x66, 0x61, 0x6c, 0x73, 0x65, 0x5d, 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61,
+ 0x64, 0x69, 0x6f, 0x5d, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69,
+ 0x64, 0x3d, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f,
+ 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x76, 0x61, 0x6c, 0x69, 0x64,
+ 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b,
+ 0x62, 0x6f, 0x78, 0x5d, 0x3a, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x5b, 0x61, 0x72, 0x69,
+ 0x61, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x3d, 0x74, 0x72, 0x75, 0x65, 0x5d, 0x2c,
+ 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d,
+ 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x3d, 0x74, 0x72,
+ 0x75, 0x65, 0x5d, 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b,
+ 0x62, 0x6f, 0x78, 0x5d, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68,
+ 0x5d, 0x3a, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x69,
+ 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x3d, 0x74, 0x72, 0x75, 0x65, 0x5d, 0x2c, 0x20, 0x5b, 0x74,
+ 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x5b, 0x72, 0x6f,
+ 0x6c, 0x65, 0x3d, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x5d, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d,
+ 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x3d, 0x74, 0x72, 0x75, 0x65, 0x5d, 0x2c, 0x20, 0x5b,
+ 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x5d, 0x3a, 0x63, 0x68, 0x65, 0x63,
+ 0x6b, 0x65, 0x64, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64,
+ 0x3d, 0x74, 0x72, 0x75, 0x65, 0x5d, 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61,
+ 0x64, 0x69, 0x6f, 0x5d, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69,
+ 0x64, 0x3d, 0x74, 0x72, 0x75, 0x65, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72,
+ 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69,
+ 0x64, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x5b, 0x74,
+ 0x79, 0x70, 0x65, 0x3d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5d, 0x3a, 0x3a, 0x2d, 0x77, 0x65, 0x62,
+ 0x6b, 0x69, 0x74, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2d, 0x73, 0x77, 0x61, 0x74, 0x63, 0x68,
+ 0x2d, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5d, 0x3a, 0x3a, 0x2d,
+ 0x6d, 0x6f, 0x7a, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2d, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20,
+ 0x30, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x5d, 0x3a, 0x3a, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x2d, 0x73, 0x77, 0x61, 0x74, 0x63, 0x68, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a,
+ 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x29, 0x20, 0x2a, 0x20, 0x2e, 0x35, 0x29,
+ 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x5d, 0x3a, 0x3a, 0x2d, 0x6d, 0x6f, 0x7a, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2d,
+ 0x73, 0x77, 0x61, 0x74, 0x63, 0x68, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x63, 0x61, 0x6c,
+ 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72,
+ 0x61, 0x64, 0x69, 0x75, 0x73, 0x29, 0x20, 0x2a, 0x20, 0x2e, 0x35, 0x29, 0x0d, 0x0a, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x74, 0x79,
+ 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x2c, 0x5b, 0x74, 0x79,
+ 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d,
+ 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69, 0x6c,
+ 0x65, 0x5d, 0x29, 0x3a, 0x69, 0x73, 0x28, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x64, 0x61, 0x74,
+ 0x65, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x64, 0x61, 0x74, 0x65, 0x74, 0x69, 0x6d,
+ 0x65, 0x2d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x6d,
+ 0x6f, 0x6e, 0x74, 0x68, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x74, 0x69, 0x6d, 0x65,
+ 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x77, 0x65, 0x65, 0x6b, 0x5d, 0x29, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x70, 0x6f, 0x73,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x30, 0x2e, 0x37, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74,
+ 0x68, 0x3a, 0x20, 0x31, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61,
+ 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x63, 0x61, 0x6c,
+ 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x77, 0x69, 0x64,
+ 0x74, 0x68, 0x29, 0x20, 0x2b, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e,
+ 0x2d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x69, 0x6d, 0x61,
+ 0x67, 0x65, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x64,
+ 0x61, 0x74, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20,
+ 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75,
+ 0x6e, 0x64, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x69,
+ 0x63, 0x6f, 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x2d, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x3a, 0x20, 0x6e, 0x6f, 0x2d, 0x72, 0x65, 0x70, 0x65,
+ 0x61, 0x74, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x3a, 0x6e,
+ 0x6f, 0x74, 0x28, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f,
+ 0x78, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x5d, 0x2c,
+ 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5d, 0x2c, 0x5b, 0x74, 0x79,
+ 0x70, 0x65, 0x3d, 0x66, 0x69, 0x6c, 0x65, 0x5d, 0x29, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x74,
+ 0x69, 0x6d, 0x65, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b,
+ 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x3a, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x74, 0x69, 0x6d, 0x65, 0x29, 0x0d, 0x0a,
+ 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x64, 0x61, 0x74, 0x65, 0x5d,
+ 0x3a, 0x3a, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x63, 0x61, 0x6c, 0x65, 0x6e, 0x64,
+ 0x61, 0x72, 0x2d, 0x70, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x2d, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61,
+ 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x64, 0x61, 0x74, 0x65, 0x74,
+ 0x69, 0x6d, 0x65, 0x2d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5d, 0x3a, 0x3a, 0x2d, 0x77, 0x65, 0x62,
+ 0x6b, 0x69, 0x74, 0x2d, 0x63, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x61, 0x72, 0x2d, 0x70, 0x69, 0x63,
+ 0x6b, 0x65, 0x72, 0x2d, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x5b,
+ 0x74, 0x79, 0x70, 0x65, 0x3d, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x5d, 0x3a, 0x3a, 0x2d, 0x77, 0x65,
+ 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x63, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x61, 0x72, 0x2d, 0x70, 0x69,
+ 0x63, 0x6b, 0x65, 0x72, 0x2d, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x2c, 0x20,
+ 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x74, 0x69, 0x6d, 0x65, 0x5d, 0x3a, 0x3a, 0x2d, 0x77, 0x65,
+ 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x63, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x61, 0x72, 0x2d, 0x70, 0x69,
+ 0x63, 0x6b, 0x65, 0x72, 0x2d, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x2c, 0x20,
+ 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x77, 0x65, 0x65, 0x6b, 0x5d, 0x3a, 0x3a, 0x2d, 0x77, 0x65,
+ 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x63, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x61, 0x72, 0x2d, 0x70, 0x69,
+ 0x63, 0x6b, 0x65, 0x72, 0x2d, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x72, 0x69, 0x67, 0x68,
+ 0x74, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x69, 0x63,
+ 0x6f, 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29, 0x20, 0x2a, 0x20, 0x2d, 0x31, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66,
+ 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x70, 0x6f,
+ 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x70,
+ 0x61, 0x63, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x5b,
+ 0x64, 0x69, 0x72, 0x3d, 0x72, 0x74, 0x6c, 0x5d, 0x20, 0x3a, 0x69, 0x73, 0x28, 0x5b, 0x74, 0x79,
+ 0x70, 0x65, 0x3d, 0x64, 0x61, 0x74, 0x65, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x64,
+ 0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x2d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5d, 0x2c, 0x5b,
+ 0x74, 0x79, 0x70, 0x65, 0x3d, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70,
+ 0x65, 0x3d, 0x74, 0x69, 0x6d, 0x65, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x77, 0x65,
+ 0x65, 0x6b, 0x5d, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74,
+ 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x0d, 0x0a, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x2d, 0x6d, 0x6f, 0x7a, 0x2d, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65,
+ 0x6e, 0x74, 0x20, 0x75, 0x72, 0x6c, 0x2d, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x28, 0x29, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x64, 0x61, 0x74,
+ 0x65, 0x5d, 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x64, 0x61, 0x74, 0x65, 0x74, 0x69,
+ 0x6d, 0x65, 0x2d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5d, 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65,
+ 0x3d, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x5d, 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x74,
+ 0x69, 0x6d, 0x65, 0x5d, 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x77, 0x65, 0x65, 0x6b,
+ 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64,
+ 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73,
+ 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61,
+ 0x6c, 0x29, 0x20, 0x21, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6e, 0x74, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75,
+ 0x6e, 0x64, 0x2d, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x20, 0x21,
+ 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6e, 0x74, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d,
+ 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69, 0x6c,
+ 0x65, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64,
+ 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61,
+ 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20, 0x2a,
+ 0x20, 0x2e, 0x35, 0x29, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72,
+ 0x64, 0x65, 0x72, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72,
+ 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x20,
+ 0x30, 0x20, 0x30, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x74,
+ 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69, 0x6c, 0x65, 0x5d, 0x3a, 0x3a, 0x66, 0x69, 0x6c, 0x65, 0x2d,
+ 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2d, 0x69, 0x6e,
+ 0x76, 0x65, 0x72, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x63,
+ 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e,
+ 0x67, 0x29, 0x2f, 0x20, 0x32, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x20, 0x30, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69,
+ 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20,
+ 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67,
+ 0x69, 0x6e, 0x2d, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a,
+ 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65,
+ 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x65, 0x6e, 0x64, 0x3a,
+ 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63,
+ 0x69, 0x6e, 0x67, 0x29, 0x2f, 0x20, 0x32, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65,
+ 0x2d, 0x65, 0x6e, 0x64, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x2f, 0x20, 0x32, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a,
+ 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d,
+ 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67,
+ 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x2e, 0x35, 0x29,
+ 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d,
+ 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67,
+ 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x2e,
+ 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72,
+ 0x64, 0x65, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65,
+ 0x72, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72,
+ 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x74, 0x6c, 0x69,
+ 0x6e, 0x65, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75,
+ 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77,
+ 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x6e,
+ 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31,
+ 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69,
+ 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69,
+ 0x67, 0x6e, 0x3a, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x3a, 0x20, 0x70, 0x6f, 0x69,
+ 0x6e, 0x74, 0x65, 0x72, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74,
+ 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x62, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74,
+ 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e,
+ 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69, 0x6c, 0x65, 0x5d, 0x3a,
+ 0x3a, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2d, 0x62,
+ 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x3a, 0x69, 0x73, 0x28, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c,
+ 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61,
+ 0x72, 0x79, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65,
+ 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x29, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69, 0x6c, 0x65, 0x5d, 0x3a, 0x3a, 0x2d, 0x77,
+ 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x75, 0x70, 0x6c, 0x6f, 0x61,
+ 0x64, 0x2d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65,
+ 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61,
+ 0x72, 0x79, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65, 0x63,
+ 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2d, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e,
+ 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x2f, 0x20, 0x32, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e,
+ 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69,
+ 0x6e, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x69, 0x6e, 0x6c, 0x69,
+ 0x6e, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x6d, 0x61,
+ 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x65, 0x6e, 0x64, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x2f, 0x20, 0x32,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67,
+ 0x69, 0x6e, 0x2d, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x65, 0x6e, 0x64, 0x3a, 0x20, 0x63,
+ 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e,
+ 0x67, 0x29, 0x2f, 0x20, 0x32, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63,
+ 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x2e, 0x35, 0x29, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f,
+ 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x2e, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68,
+ 0x29, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64,
+ 0x69, 0x75, 0x73, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65,
+ 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x3a, 0x20, 0x30, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x78,
+ 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62,
+ 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e,
+ 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67,
+ 0x68, 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x68,
+ 0x65, 0x69, 0x67, 0x68, 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x63, 0x65, 0x6e,
+ 0x74, 0x65, 0x72, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x75,
+ 0x72, 0x73, 0x6f, 0x72, 0x3a, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d,
+ 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x62, 0x61, 0x63, 0x6b,
+ 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69,
+ 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f,
+ 0x6e, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61,
+ 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74,
+ 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f,
+ 0x6e, 0x29, 0x2c, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69, 0x6c, 0x65, 0x5d, 0x3a, 0x3a, 0x2d,
+ 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x75, 0x70, 0x6c, 0x6f,
+ 0x61, 0x64, 0x2d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x3a, 0x69, 0x73, 0x28, 0x3a, 0x68, 0x6f,
+ 0x76, 0x65, 0x72, 0x2c, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x3a, 0x66, 0x6f, 0x63,
+ 0x75, 0x73, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65, 0x63,
+ 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2d, 0x68, 0x6f, 0x76, 0x65,
+ 0x72, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69, 0x6c, 0x65, 0x5d,
+ 0x3a, 0x3a, 0x2d, 0x6d, 0x73, 0x2d, 0x62, 0x72, 0x6f, 0x77, 0x73, 0x65, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65, 0x63,
+ 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2d, 0x69, 0x6e, 0x76, 0x65, 0x72,
+ 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61,
+ 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63,
+ 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x2f,
+ 0x20, 0x32, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61,
+ 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x69, 0x6e,
+ 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x69,
+ 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x65, 0x6e, 0x64, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x2f, 0x20,
+ 0x32, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64,
+ 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70,
+ 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20,
+ 0x2a, 0x20, 0x2e, 0x35, 0x29, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70,
+ 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c,
+ 0x29, 0x20, 0x2a, 0x20, 0x2e, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29, 0x20, 0x73, 0x6f,
+ 0x6c, 0x69, 0x64, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61,
+ 0x64, 0x69, 0x75, 0x73, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61,
+ 0x64, 0x6f, 0x77, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x78, 0x2d, 0x73,
+ 0x68, 0x61, 0x64, 0x6f, 0x77, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66,
+ 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69,
+ 0x7a, 0x65, 0x3a, 0x20, 0x31, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78,
+ 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72,
+ 0x3a, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x6d, 0x73, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69,
+ 0x6f, 0x6e, 0x3a, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69,
+ 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x62, 0x6f,
+ 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74,
+ 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a,
+ 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69,
+ 0x6f, 0x6e, 0x29, 0x2c, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f,
+ 0x6e, 0x29, 0x2c, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74,
+ 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x62, 0x6f, 0x78, 0x2d, 0x73,
+ 0x68, 0x61, 0x64, 0x6f, 0x77, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e,
+ 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d,
+ 0x66, 0x69, 0x6c, 0x65, 0x5d, 0x3a, 0x3a, 0x2d, 0x6d, 0x73, 0x2d, 0x62, 0x72, 0x6f, 0x77, 0x73,
+ 0x65, 0x3a, 0x69, 0x73, 0x28, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x3a, 0x61, 0x63, 0x74,
+ 0x69, 0x76, 0x65, 0x2c, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2d, 0x68,
+ 0x6f, 0x76, 0x65, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64,
+ 0x61, 0x72, 0x79, 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72,
+ 0x61, 0x6e, 0x67, 0x65, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65,
+ 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x3a,
+ 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x6d, 0x6f, 0x7a,
+ 0x2d, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x6e,
+ 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e,
+ 0x63, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x77,
+ 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x31, 0x2e, 0x32, 0x35, 0x72, 0x65, 0x6d,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x3a, 0x20, 0x30, 0x20, 0x30, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5d, 0x3a, 0x3a, 0x2d,
+ 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x75,
+ 0x6e, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x2d, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31,
+ 0x30, 0x30, 0x25, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x68, 0x65,
+ 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x2e, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61,
+ 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x72, 0x61, 0x6e,
+ 0x67, 0x65, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b,
+ 0x69, 0x74, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x62,
+ 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e,
+ 0x29, 0x2c, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74,
+ 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e,
+ 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64,
+ 0x6f, 0x77, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74,
+ 0x69, 0x6f, 0x6e, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5d, 0x3a,
+ 0x3a, 0x2d, 0x6d, 0x6f, 0x7a, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x74, 0x72, 0x61, 0x63,
+ 0x6b, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64,
+ 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x2e, 0x32, 0x35, 0x72, 0x65,
+ 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x6d, 0x6f, 0x7a, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a,
+ 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69,
+ 0x6f, 0x6e, 0x29, 0x2c, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72,
+ 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68,
+ 0x61, 0x64, 0x6f, 0x77, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x6e, 0x67, 0x65,
+ 0x5d, 0x3a, 0x3a, 0x2d, 0x6d, 0x73, 0x2d, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31,
+ 0x30, 0x30, 0x25, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x68, 0x65,
+ 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x2e, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61,
+ 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x72, 0x61, 0x6e,
+ 0x67, 0x65, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x6d, 0x73, 0x2d, 0x74,
+ 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x62, 0x6f,
+ 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74,
+ 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a,
+ 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69,
+ 0x6f, 0x6e, 0x29, 0x2c, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b,
+ 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5d, 0x3a, 0x3a, 0x2d, 0x77, 0x65,
+ 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x2d, 0x74, 0x68, 0x75, 0x6d,
+ 0x62, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65,
+ 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x3a,
+ 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x2e, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a,
+ 0x20, 0x31, 0x2e, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x2d,
+ 0x2e, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x32, 0x70, 0x78, 0x20, 0x73, 0x6f, 0x6c, 0x69,
+ 0x64, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x74, 0x68,
+ 0x75, 0x6d, 0x62, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x35, 0x30, 0x25, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x75,
+ 0x72, 0x73, 0x6f, 0x72, 0x3a, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d,
+ 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x62, 0x61, 0x63, 0x6b,
+ 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x74,
+ 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74,
+ 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a,
+ 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69,
+ 0x6f, 0x6e, 0x29, 0x2c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x74,
+ 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5d, 0x3a, 0x3a, 0x2d, 0x6d, 0x6f, 0x7a,
+ 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d,
+ 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68,
+ 0x3a, 0x20, 0x31, 0x2e, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x31, 0x2e, 0x32, 0x35,
+ 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61,
+ 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x2d, 0x2e, 0x35, 0x72, 0x65, 0x6d,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65,
+ 0x72, 0x3a, 0x20, 0x32, 0x70, 0x78, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x2d, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61,
+ 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x35, 0x30, 0x25, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x72, 0x61, 0x6e, 0x67,
+ 0x65, 0x2d, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x3a,
+ 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x2d, 0x6d, 0x6f, 0x7a, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69,
+ 0x6f, 0x6e, 0x3a, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f,
+ 0x6e, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61,
+ 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x74, 0x72, 0x61, 0x6e,
+ 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e,
+ 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x6e, 0x67,
+ 0x65, 0x5d, 0x3a, 0x3a, 0x2d, 0x6d, 0x73, 0x2d, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74,
+ 0x2d, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x6e,
+ 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74,
+ 0x68, 0x3a, 0x20, 0x31, 0x2e, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x31, 0x2e, 0x32,
+ 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d,
+ 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x2d, 0x2e, 0x35, 0x72, 0x65,
+ 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x3a, 0x20, 0x32, 0x70, 0x78, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x2d,
+ 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72,
+ 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x35, 0x30, 0x25, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x72, 0x61, 0x6e,
+ 0x67, 0x65, 0x2d, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72,
+ 0x3a, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x2d, 0x6d, 0x73, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69,
+ 0x6f, 0x6e, 0x3a, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f,
+ 0x6e, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61,
+ 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x74, 0x72, 0x61, 0x6e,
+ 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e,
+ 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x6e, 0x67,
+ 0x65, 0x5d, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2c, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d,
+ 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5d, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d,
+ 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65,
+ 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65,
+ 0x2d, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x2d,
+ 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65,
+ 0x3d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5d, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x72, 0x61, 0x6e, 0x67,
+ 0x65, 0x2d, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x74, 0x68, 0x75, 0x6d, 0x62,
+ 0x2d, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5d, 0x3a, 0x61, 0x63,
+ 0x74, 0x69, 0x76, 0x65, 0x3a, 0x3a, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x73, 0x6c,
+ 0x69, 0x64, 0x65, 0x72, 0x2d, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66,
+ 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x28, 0x31, 0x2e, 0x32, 0x35, 0x29,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x6e,
+ 0x67, 0x65, 0x5d, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x3a, 0x3a, 0x2d, 0x6d, 0x6f, 0x7a,
+ 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e,
+ 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x28, 0x31, 0x2e, 0x32,
+ 0x35, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72,
+ 0x61, 0x6e, 0x67, 0x65, 0x5d, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x3a, 0x3a, 0x2d, 0x6d,
+ 0x73, 0x2d, 0x74, 0x68, 0x75, 0x6d, 0x62, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d,
+ 0x3a, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x28, 0x31, 0x2e, 0x32, 0x35, 0x29, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x69, 0x6e, 0x70, 0x75,
+ 0x74, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63,
+ 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69,
+ 0x6f, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5d, 0x2c,
+ 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69, 0x6c, 0x65, 0x5d, 0x29, 0x5b, 0x74, 0x79, 0x70,
+ 0x65, 0x3d, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
+ 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d,
+ 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74,
+ 0x61, 0x6c, 0x29, 0x20, 0x2b, 0x20, 0x31, 0x2e, 0x37, 0x35, 0x72, 0x65, 0x6d, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x69, 0x6e, 0x6c,
+ 0x69, 0x6e, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a,
+ 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x20, 0x2b, 0x20, 0x31, 0x2e, 0x37, 0x35, 0x72, 0x65, 0x6d,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72,
+ 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x69, 0x6d, 0x61,
+ 0x67, 0x65, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x73,
+ 0x65, 0x61, 0x72, 0x63, 0x68, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e,
+ 0x3a, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x31, 0x2e,
+ 0x31, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31, 0x72,
+ 0x65, 0x6d, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61,
+ 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x3a,
+ 0x20, 0x6e, 0x6f, 0x2d, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x5b,
+ 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x2c, 0x5b,
+ 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70,
+ 0x65, 0x3d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66,
+ 0x69, 0x6c, 0x65, 0x5d, 0x29, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x65, 0x61, 0x72, 0x63,
+ 0x68, 0x5d, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5d,
+ 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62,
+ 0x6b, 0x69, 0x74, 0x2d, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x73, 0x74, 0x61, 0x72,
+ 0x74, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f,
+ 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69,
+ 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x20, 0x2b,
+ 0x20, 0x31, 0x2e, 0x37, 0x35, 0x72, 0x65, 0x6d, 0x29, 0x20, 0x21, 0x69, 0x6d, 0x70, 0x6f, 0x72,
+ 0x74, 0x61, 0x6e, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70,
+ 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x73, 0x74,
+ 0x61, 0x72, 0x74, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61,
+ 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29,
+ 0x20, 0x2b, 0x20, 0x31, 0x2e, 0x37, 0x35, 0x72, 0x65, 0x6d, 0x29, 0x20, 0x21, 0x69, 0x6d, 0x70,
+ 0x6f, 0x72, 0x74, 0x61, 0x6e, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x73, 0x69,
+ 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x6c, 0x65, 0x66,
+ 0x74, 0x20, 0x31, 0x2e, 0x31, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x2c, 0x63, 0x65, 0x6e, 0x74, 0x65,
+ 0x72, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x2e, 0x37, 0x35, 0x72, 0x65, 0x6d, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x70,
+ 0x75, 0x74, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65,
+ 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64,
+ 0x69, 0x6f, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5d,
+ 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69, 0x6c, 0x65, 0x5d, 0x29, 0x5b, 0x74, 0x79,
+ 0x70, 0x65, 0x3d, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5d, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d,
+ 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x3d, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x5d, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x29, 0x2c, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x29,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69,
+ 0x6e, 0x70, 0x75, 0x74, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63,
+ 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72,
+ 0x61, 0x64, 0x69, 0x6f, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x6e, 0x67,
+ 0x65, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69, 0x6c, 0x65, 0x5d, 0x29, 0x5b,
+ 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5d, 0x5b, 0x61, 0x72, 0x69,
+ 0x61, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x3d, 0x74, 0x72, 0x75, 0x65, 0x5d, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x3a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x29, 0x2c,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c,
+ 0x69, 0x64, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x5b, 0x74,
+ 0x79, 0x70, 0x65, 0x3d, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5d, 0x3a, 0x3a, 0x2d, 0x77, 0x65,
+ 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2d, 0x63, 0x61, 0x6e, 0x63,
+ 0x65, 0x6c, 0x2d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x61,
+ 0x6e, 0x63, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x0d, 0x0a, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x5b, 0x64, 0x69, 0x72, 0x3d, 0x72, 0x74, 0x6c, 0x5d, 0x20, 0x3a, 0x77,
+ 0x68, 0x65, 0x72, 0x65, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0x3a, 0x6e, 0x6f, 0x74, 0x28,
+ 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x2c,
+ 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x5d, 0x2c, 0x5b, 0x74, 0x79,
+ 0x70, 0x65, 0x3d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d,
+ 0x66, 0x69, 0x6c, 0x65, 0x5d, 0x29, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x65, 0x61, 0x72,
+ 0x63, 0x68, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20,
+ 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x31, 0x2e, 0x31,
+ 0x32, 0x35, 0x72, 0x65, 0x6d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x5b, 0x64, 0x69, 0x72, 0x3d, 0x72, 0x74, 0x6c, 0x5d, 0x20, 0x3a, 0x77, 0x68, 0x65, 0x72, 0x65,
+ 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x74, 0x79, 0x70,
+ 0x65, 0x3d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70,
+ 0x65, 0x3d, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72,
+ 0x61, 0x6e, 0x67, 0x65, 0x5d, 0x2c, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x66, 0x69, 0x6c, 0x65,
+ 0x5d, 0x29, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5d, 0x5b,
+ 0x61, 0x72, 0x69, 0x61, 0x2d, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5d, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x65,
+ 0x6e, 0x74, 0x65, 0x72, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x31, 0x2e, 0x31, 0x32, 0x35,
+ 0x72, 0x65, 0x6d, 0x2c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20,
+ 0x2e, 0x37, 0x35, 0x72, 0x65, 0x6d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x3a, 0x77, 0x68, 0x65, 0x72, 0x65, 0x28, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x29, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30,
+ 0x25, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x3a, 0x20, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x70, 0x73,
+ 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x73,
+ 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x74, 0x65, 0x78, 0x74, 0x2d, 0x69, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x30, 0x0d, 0x0a,
+ 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63,
+ 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x2f,
+ 0x20, 0x32, 0x29, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e,
+ 0x67, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d,
+ 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29, 0x20, 0x73, 0x6f, 0x6c, 0x69,
+ 0x64, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2d, 0x62, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74,
+ 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66,
+ 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20,
+ 0x6c, 0x65, 0x66, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d,
+ 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0d, 0x0a, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x74, 0x66, 0x6f, 0x6f, 0x74, 0x20, 0x74, 0x64, 0x2c, 0x20, 0x74, 0x66, 0x6f,
+ 0x6f, 0x74, 0x20, 0x74, 0x68, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72,
+ 0x64, 0x65, 0x72, 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29, 0x20, 0x73, 0x6f, 0x6c,
+ 0x69, 0x64, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2d, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d,
+ 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b,
+ 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x67, 0x72, 0x69, 0x64, 0x5d, 0x20, 0x74, 0x62, 0x6f, 0x64, 0x79,
+ 0x20, 0x74, 0x72, 0x3a, 0x6e, 0x74, 0x68, 0x2d, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x28, 0x6f, 0x64,
+ 0x64, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2d, 0x72, 0x6f, 0x77, 0x2d, 0x73, 0x74, 0x72, 0x69,
+ 0x70, 0x70, 0x65, 0x64, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x63, 0x6f, 0x64,
+ 0x65, 0x2c, 0x20, 0x6b, 0x62, 0x64, 0x2c, 0x20, 0x70, 0x72, 0x65, 0x2c, 0x20, 0x73, 0x61, 0x6d,
+ 0x70, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69,
+ 0x7a, 0x65, 0x3a, 0x20, 0x2e, 0x38, 0x37, 0x35, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x29,
+ 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x70, 0x72, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x6d, 0x73, 0x2d, 0x6f, 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2d, 0x73,
+ 0x74, 0x79, 0x6c, 0x65, 0x3a, 0x20, 0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x72, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x3a, 0x20,
+ 0x61, 0x75, 0x74, 0x6f, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x63, 0x6f, 0x64, 0x65, 0x2c,
+ 0x20, 0x6b, 0x62, 0x64, 0x2c, 0x20, 0x70, 0x72, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64,
+ 0x69, 0x75, 0x73, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x64,
+ 0x65, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65,
+ 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74,
+ 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c,
+ 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x69, 0x6e, 0x69, 0x74,
+ 0x69, 0x61, 0x6c, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x20,
+ 0x6b, 0x62, 0x64, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c,
+ 0x61, 0x79, 0x3a, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20,
+ 0x2e, 0x33, 0x37, 0x35, 0x72, 0x65, 0x6d, 0x20, 0x2e, 0x35, 0x72, 0x65, 0x6d, 0x0d, 0x0a, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x70, 0x72, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64,
+ 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f,
+ 0x6d, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77,
+ 0x2d, 0x78, 0x3a, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x70, 0x72, 0x65, 0x20, 0x3e, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79,
+ 0x3a, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x20,
+ 0x30, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f,
+ 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31, 0x34, 0x70, 0x78, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69,
+ 0x67, 0x68, 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x2d,
+ 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x62, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x64,
+ 0x65, 0x2d, 0x74, 0x61, 0x67, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x69, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2d, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74,
+ 0x79, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66,
+ 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61,
+ 0x6c, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x75, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d,
+ 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65,
+ 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x65, 0x6d, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e,
+ 0x74, 0x2d, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x0d,
+ 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x6b, 0x62, 0x64, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2d, 0x6b, 0x62,
+ 0x64, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x64, 0x65, 0x2d, 0x6b, 0x62, 0x64, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x65, 0x72,
+ 0x74, 0x69, 0x63, 0x61, 0x6c, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x62, 0x61, 0x73,
+ 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x68, 0x72, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x30, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x30, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x74, 0x6f, 0x70,
+ 0x3a, 0x20, 0x31, 0x70, 0x78, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x5b, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x5d, 0x2c, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x6c,
+ 0x61, 0x74, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c,
+ 0x61, 0x79, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x20, 0x21, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74,
+ 0x61, 0x6e, 0x74, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x63, 0x61, 0x6e, 0x76, 0x61, 0x73,
+ 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a,
+ 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x0d, 0x0a, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x62, 0x6c, 0x6f, 0x63,
+ 0x6b, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62,
+ 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61,
+ 0x63, 0x69, 0x6e, 0x67, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64,
+ 0x69, 0x6e, 0x67, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x64,
+ 0x74, 0x68, 0x29, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6f, 0x6e, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72,
+ 0x79, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e,
+ 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x31, 0x72, 0x65, 0x6d, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x2d, 0x73, 0x74,
+ 0x79, 0x6c, 0x65, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x3a,
+ 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73,
+ 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x72, 0x6f,
+ 0x6c, 0x65, 0x5d, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6f, 0x6e, 0x2d, 0x63, 0x6c, 0x6f, 0x73, 0x65,
+ 0x2d, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x20, 0x73, 0x75,
+ 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x3a, 0x3a, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x64,
+ 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x2d, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73,
+ 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79,
+ 0x3a, 0x3a, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a,
+ 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x74, 0x61,
+ 0x69, 0x6c, 0x73, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x3a, 0x3a, 0x2d, 0x6d, 0x6f,
+ 0x7a, 0x2d, 0x6c, 0x69, 0x73, 0x74, 0x2d, 0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x73,
+ 0x74, 0x2d, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x6e, 0x6f,
+ 0x6e, 0x65, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73,
+ 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64,
+ 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74,
+ 0x68, 0x3a, 0x20, 0x31, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x31, 0x72,
+ 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d,
+ 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2c, 0x31, 0x72, 0x65, 0x6d, 0x29, 0x20,
+ 0x2a, 0x20, 0x30, 0x2e, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x69, 0x6e, 0x6c, 0x69,
+ 0x6e, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2c, 0x31, 0x72, 0x65,
+ 0x6d, 0x29, 0x20, 0x2a, 0x20, 0x2e, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3a, 0x20, 0x72, 0x69,
+ 0x67, 0x68, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x72, 0x6f, 0x74,
+ 0x61, 0x74, 0x65, 0x28, 0x2d, 0x39, 0x30, 0x64, 0x65, 0x67, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x63, 0x68, 0x65, 0x76, 0x72, 0x6f, 0x6e, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61,
+ 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f,
+ 0x6e, 0x3a, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61,
+ 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31,
+ 0x72, 0x65, 0x6d, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2d, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x3a, 0x20, 0x6e, 0x6f, 0x2d, 0x72, 0x65, 0x70,
+ 0x65, 0x61, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x22, 0x22, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e,
+ 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72,
+ 0x6d, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69,
+ 0x6f, 0x6e, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c,
+ 0x73, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f,
+ 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x20, 0x73, 0x75, 0x6d, 0x6d,
+ 0x61, 0x72, 0x79, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x72,
+ 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x29, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x61, 0x63, 0x63,
+ 0x6f, 0x72, 0x64, 0x69, 0x6f, 0x6e, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x73, 0x75,
+ 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x20, 0x73,
+ 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74,
+ 0x6f, 0x6e, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78,
+ 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x20,
+ 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74,
+ 0x74, 0x6f, 0x6e, 0x5d, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x68,
+ 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x31, 0x72, 0x65, 0x6d,
+ 0x20, 0x2a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65,
+ 0x69, 0x67, 0x68, 0x74, 0x2c, 0x31, 0x2e, 0x35, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x63, 0x68, 0x65, 0x76, 0x72, 0x6f,
+ 0x6e, 0x2d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x20,
+ 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74,
+ 0x74, 0x6f, 0x6e, 0x5d, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x2e, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e,
+ 0x65, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x73, 0x74, 0x3a, 0x3a, 0x61, 0x66, 0x74,
+ 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x2d, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x69, 0x63,
+ 0x6f, 0x6e, 0x2d, 0x63, 0x68, 0x65, 0x76, 0x72, 0x6f, 0x6e, 0x2d, 0x62, 0x75, 0x74, 0x74, 0x6f,
+ 0x6e, 0x2d, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5b, 0x6f, 0x70, 0x65, 0x6e, 0x5d, 0x20, 0x3e,
+ 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f,
+ 0x6d, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70,
+ 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c,
+ 0x73, 0x5b, 0x6f, 0x70, 0x65, 0x6e, 0x5d, 0x20, 0x3e, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72,
+ 0x79, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x5d, 0x29, 0x3a, 0x6e, 0x6f,
+ 0x74, 0x28, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6f, 0x6e, 0x2d,
+ 0x6f, 0x70, 0x65, 0x6e, 0x2d, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c,
+ 0x73, 0x5b, 0x6f, 0x70, 0x65, 0x6e, 0x5d, 0x20, 0x3e, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72,
+ 0x79, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72,
+ 0x6d, 0x3a, 0x20, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x28, 0x30, 0x29, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x5b, 0x64, 0x69, 0x72, 0x3d,
+ 0x72, 0x74, 0x6c, 0x5d, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x20, 0x73, 0x75, 0x6d,
+ 0x6d, 0x61, 0x72, 0x79, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74,
+ 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x0d, 0x0a, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x64, 0x69, 0x72, 0x3d, 0x72, 0x74, 0x6c,
+ 0x5d, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72,
+ 0x79, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3a, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x6c,
+ 0x65, 0x66, 0x74, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x61, 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d,
+ 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76,
+ 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72,
+ 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75,
+ 0x73, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x61, 0x72, 0x64, 0x2d,
+ 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64,
+ 0x6f, 0x77, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x61, 0x72, 0x64, 0x2d, 0x62,
+ 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x20, 0x3e, 0x20, 0x66,
+ 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x20, 0x3e,
+ 0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a,
+ 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63,
+ 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f,
+ 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x2d, 0x31, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66,
+ 0x74, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69,
+ 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x2d, 0x31, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a,
+ 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63,
+ 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63,
+ 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x2e, 0x36, 0x36, 0x29, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68,
+ 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x61, 0x72,
+ 0x64, 0x2d, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x2d, 0x62, 0x61,
+ 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x72,
+ 0x74, 0x69, 0x63, 0x6c, 0x65, 0x20, 0x3e, 0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e,
+ 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76,
+ 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x2d, 0x31, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d,
+ 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74,
+ 0x69, 0x63, 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x64, 0x74,
+ 0x68, 0x29, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63,
+ 0x61, 0x72, 0x64, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x2d, 0x74, 0x6f, 0x70, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2d, 0x72, 0x61, 0x64,
+ 0x69, 0x75, 0x73, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65,
+ 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x74, 0x6f, 0x70, 0x2d, 0x6c,
+ 0x65, 0x66, 0x74, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x29,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61,
+ 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x20, 0x3e, 0x20, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69,
+ 0x6e, 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69,
+ 0x63, 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d,
+ 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x63, 0x61,
+ 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x73,
+ 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29,
+ 0x20, 0x2a, 0x20, 0x2d, 0x31, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29,
+ 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x61, 0x72,
+ 0x64, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2d, 0x72, 0x61,
+ 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x62, 0x6f, 0x74, 0x74,
+ 0x6f, 0x6d, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64,
+ 0x69, 0x75, 0x73, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x3a,
+ 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x73, 0x63,
+ 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x72, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x30,
+ 0x70, 0x78, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20,
+ 0x66, 0x6c, 0x65, 0x78, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7a, 0x2d, 0x69, 0x6e, 0x64,
+ 0x65, 0x78, 0x3a, 0x20, 0x39, 0x39, 0x39, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x6f,
+ 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x66, 0x69, 0x78, 0x65, 0x64, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6c,
+ 0x69, 0x67, 0x6e, 0x2d, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x3a, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65,
+ 0x72, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, 0x2d,
+ 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x69, 0x6e, 0x68,
+ 0x65, 0x72, 0x69, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x69, 0x6e, 0x2d, 0x77,
+ 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x69, 0x6e, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61,
+ 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61,
+ 0x63, 0x69, 0x6e, 0x67, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62,
+ 0x6b, 0x69, 0x74, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x64, 0x72, 0x6f, 0x70, 0x2d, 0x66, 0x69, 0x6c,
+ 0x74, 0x65, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x6f, 0x64, 0x61, 0x6c,
+ 0x2d, 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x64, 0x72, 0x6f,
+ 0x70, 0x2d, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x62, 0x61, 0x63, 0x6b, 0x64, 0x72, 0x6f, 0x70, 0x2d, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x2d, 0x6f, 0x76, 0x65,
+ 0x72, 0x6c, 0x61, 0x79, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x64, 0x72, 0x6f, 0x70, 0x2d, 0x66, 0x69,
+ 0x6c, 0x74, 0x65, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b,
+ 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x2d, 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61,
+ 0x79, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x20, 0x61,
+ 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x6d, 0x61, 0x78, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x63, 0x61,
+ 0x6c, 0x63, 0x28, 0x31, 0x30, 0x30, 0x76, 0x68, 0x20, 0x2d, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x20, 0x2a, 0x20, 0x32, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f,
+ 0x77, 0x3a, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20, 0x28, 0x6d, 0x69, 0x6e, 0x2d, 0x77, 0x69,
+ 0x64, 0x74, 0x68, 0x3a, 0x35, 0x37, 0x36, 0x70, 0x78, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x20, 0x61, 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65,
+ 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x2d,
+ 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x35, 0x31, 0x30, 0x70, 0x78, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61,
+ 0x20, 0x28, 0x6d, 0x69, 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x37, 0x36, 0x38, 0x70,
+ 0x78, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67,
+ 0x20, 0x61, 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x37,
+ 0x30, 0x30, 0x70, 0x78, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x20, 0x61, 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65,
+ 0x20, 0x3e, 0x20, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x64, 0x69, 0x61, 0x6c, 0x6f,
+ 0x67, 0x20, 0x61, 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x20, 0x3e, 0x20, 0x68, 0x65, 0x61, 0x64,
+ 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e,
+ 0x67, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74,
+ 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x2e, 0x35, 0x29, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d,
+ 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x20, 0x61, 0x72, 0x74,
+ 0x69, 0x63, 0x6c, 0x65, 0x20, 0x3e, 0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x2e, 0x63,
+ 0x6c, 0x6f, 0x73, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3a,
+ 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x20, 0x61, 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x20,
+ 0x3e, 0x20, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x74, 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x72, 0x69, 0x67, 0x68,
+ 0x74, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x61, 0x6c,
+ 0x6f, 0x67, 0x20, 0x61, 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x20, 0x3e, 0x20, 0x66, 0x6f, 0x6f,
+ 0x74, 0x65, 0x72, 0x20, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e,
+ 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72,
+ 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x20, 0x61, 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x20, 0x3e,
+ 0x20, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x20, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75,
+ 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x3a, 0x66, 0x69, 0x72, 0x73, 0x74,
+ 0x2d, 0x6f, 0x66, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d,
+ 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x20, 0x2a, 0x20, 0x2e, 0x35, 0x29, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x64, 0x69,
+ 0x61, 0x6c, 0x6f, 0x67, 0x20, 0x61, 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x20, 0x70, 0x3a, 0x6c,
+ 0x61, 0x73, 0x74, 0x2d, 0x6f, 0x66, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x20, 0x61, 0x72, 0x74, 0x69, 0x63, 0x6c,
+ 0x65, 0x20, 0x2e, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x72, 0x65, 0x6d,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x31,
+ 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e,
+ 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76,
+ 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x2d, 0x2e, 0x35, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74,
+ 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x79, 0x70, 0x6f, 0x67,
+ 0x72, 0x61, 0x70, 0x68, 0x79, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65,
+ 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61,
+ 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x2d, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x69, 0x63,
+ 0x6f, 0x6e, 0x2d, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x73, 0x69, 0x74,
+ 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x73, 0x69, 0x7a,
+ 0x65, 0x3a, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x31, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x72, 0x65,
+ 0x70, 0x65, 0x61, 0x74, 0x3a, 0x20, 0x6e, 0x6f, 0x2d, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x2e,
+ 0x35, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69,
+ 0x6f, 0x6e, 0x3a, 0x20, 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x0d, 0x0a, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x20, 0x61,
+ 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x20, 0x2e, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x3a, 0x69, 0x73,
+ 0x28, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5d, 0x2c,
+ 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x3a,
+ 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x31, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x3a, 0x6e, 0x6f,
+ 0x74, 0x28, 0x5b, 0x6f, 0x70, 0x65, 0x6e, 0x5d, 0x29, 0x2c, 0x20, 0x64, 0x69, 0x61, 0x6c, 0x6f,
+ 0x67, 0x5b, 0x6f, 0x70, 0x65, 0x6e, 0x3d, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x5d, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x6e, 0x6f,
+ 0x6e, 0x65, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x2e, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x2d,
+ 0x69, 0x73, 0x2d, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70,
+ 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x72, 0x2d, 0x77, 0x69,
+ 0x64, 0x74, 0x68, 0x2c, 0x30, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x76, 0x65,
+ 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x3a, 0x20, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x65, 0x76, 0x65, 0x6e,
+ 0x74, 0x73, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74,
+ 0x6f, 0x75, 0x63, 0x68, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x6e, 0x6f, 0x6e,
+ 0x65, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x6d, 0x6f, 0x64,
+ 0x61, 0x6c, 0x2d, 0x69, 0x73, 0x2d, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x64, 0x69, 0x61, 0x6c, 0x6f,
+ 0x67, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x6f, 0x69,
+ 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x3a, 0x20, 0x61, 0x75, 0x74,
+ 0x6f, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x3a, 0x77, 0x68, 0x65,
+ 0x72, 0x65, 0x28, 0x2e, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x2d, 0x69, 0x73, 0x2d, 0x6f, 0x70, 0x65,
+ 0x6e, 0x69, 0x6e, 0x67, 0x2c, 0x2e, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x2d, 0x69, 0x73, 0x2d, 0x63,
+ 0x6c, 0x6f, 0x73, 0x69, 0x6e, 0x67, 0x29, 0x20, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2c, 0x20,
+ 0x3a, 0x77, 0x68, 0x65, 0x72, 0x65, 0x28, 0x2e, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x2d, 0x69, 0x73,
+ 0x2d, 0x6f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x2c, 0x2e, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x2d,
+ 0x69, 0x73, 0x2d, 0x63, 0x6c, 0x6f, 0x73, 0x69, 0x6e, 0x67, 0x29, 0x20, 0x64, 0x69, 0x61, 0x6c,
+ 0x6f, 0x67, 0x20, 0x3e, 0x20, 0x61, 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x64, 0x75,
+ 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x2e, 0x32, 0x73, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x74, 0x69, 0x6d, 0x69,
+ 0x6e, 0x67, 0x2d, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x65, 0x61, 0x73,
+ 0x65, 0x2d, 0x69, 0x6e, 0x2d, 0x6f, 0x75, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61,
+ 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x66, 0x69, 0x6c, 0x6c, 0x2d, 0x6d, 0x6f,
+ 0x64, 0x65, 0x3a, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x3a,
+ 0x77, 0x68, 0x65, 0x72, 0x65, 0x28, 0x2e, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x2d, 0x69, 0x73, 0x2d,
+ 0x6f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x2c, 0x2e, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x2d, 0x69,
+ 0x73, 0x2d, 0x63, 0x6c, 0x6f, 0x73, 0x69, 0x6e, 0x67, 0x29, 0x20, 0x64, 0x69, 0x61, 0x6c, 0x6f,
+ 0x67, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x2d, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x2e, 0x38, 0x73,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x20, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x2d, 0x6f, 0x76, 0x65,
+ 0x72, 0x6c, 0x61, 0x79, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3a,
+ 0x77, 0x68, 0x65, 0x72, 0x65, 0x28, 0x2e, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x2d, 0x69, 0x73, 0x2d,
+ 0x6f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x2c, 0x2e, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x2d, 0x69,
+ 0x73, 0x2d, 0x63, 0x6c, 0x6f, 0x73, 0x69, 0x6e, 0x67, 0x29, 0x20, 0x64, 0x69, 0x61, 0x6c, 0x6f,
+ 0x67, 0x20, 0x3e, 0x20, 0x61, 0x72, 0x74, 0x69, 0x63, 0x6c, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x2d, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x2e, 0x32, 0x73, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d,
+ 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x20, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x2e, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x2d, 0x69, 0x73, 0x2d,
+ 0x63, 0x6c, 0x6f, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2c, 0x20,
+ 0x2e, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x2d, 0x69, 0x73, 0x2d, 0x63, 0x6c, 0x6f, 0x73, 0x69, 0x6e,
+ 0x67, 0x20, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x20, 0x3e, 0x20, 0x61, 0x72, 0x74, 0x69, 0x63,
+ 0x6c, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x2d, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x30, 0x73, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x64, 0x69,
+ 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65,
+ 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6b, 0x65, 0x79, 0x66, 0x72, 0x61, 0x6d, 0x65,
+ 0x73, 0x20, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x2d, 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x62,
+ 0x61, 0x63, 0x6b, 0x64, 0x72, 0x6f, 0x70, 0x2d, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x3a, 0x20,
+ 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62,
+ 0x61, 0x63, 0x6b, 0x64, 0x72, 0x6f, 0x70, 0x2d, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x3a, 0x20,
+ 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62,
+ 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a,
+ 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6b, 0x65, 0x79, 0x66, 0x72,
+ 0x61, 0x6d, 0x65, 0x73, 0x20, 0x6d, 0x6f, 0x64, 0x61, 0x6c, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x74, 0x72, 0x61,
+ 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65, 0x59, 0x28, 0x2d, 0x31, 0x30, 0x30, 0x25, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79,
+ 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x3a, 0x77, 0x68, 0x65, 0x72, 0x65, 0x28, 0x6e, 0x61, 0x76, 0x20, 0x6c, 0x69, 0x29, 0x3a,
+ 0x3a, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66,
+ 0x6c, 0x6f, 0x61, 0x74, 0x3a, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x22, 0xe2, 0x80, 0x8b, 0x22, 0x0d,
+ 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x6e, 0x61, 0x76, 0x2c, 0x20, 0x6e, 0x61, 0x76, 0x20, 0x75,
+ 0x6c, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79,
+ 0x3a, 0x20, 0x66, 0x6c, 0x65, 0x78, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x6e, 0x61, 0x76,
+ 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, 0x2d,
+ 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2d, 0x62,
+ 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x6e, 0x61, 0x76, 0x20, 0x6f, 0x6c, 0x2c, 0x20, 0x6e, 0x61, 0x76, 0x20, 0x75, 0x6c, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e,
+ 0x2d, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x3a, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d,
+ 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x30, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x2d, 0x73, 0x74,
+ 0x79, 0x6c, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x61, 0x76, 0x20,
+ 0x6f, 0x6c, 0x3a, 0x66, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x6f, 0x66, 0x2d, 0x74, 0x79, 0x70, 0x65,
+ 0x2c, 0x20, 0x6e, 0x61, 0x76, 0x20, 0x75, 0x6c, 0x3a, 0x66, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x6f,
+ 0x66, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66,
+ 0x74, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x61,
+ 0x76, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e,
+ 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20,
+ 0x2d, 0x31, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x61, 0x76, 0x20, 0x6f, 0x6c,
+ 0x3a, 0x6c, 0x61, 0x73, 0x74, 0x2d, 0x6f, 0x66, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x2c, 0x20, 0x6e,
+ 0x61, 0x76, 0x20, 0x75, 0x6c, 0x3a, 0x6c, 0x61, 0x73, 0x74, 0x2d, 0x6f, 0x66, 0x2d, 0x74, 0x79,
+ 0x70, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20,
+ 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x61, 0x76, 0x2d, 0x65,
+ 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68,
+ 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x2d, 0x31, 0x29,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x6e, 0x61, 0x76, 0x20, 0x6c, 0x69, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x69, 0x6e,
+ 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
+ 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x61, 0x76, 0x2d, 0x65, 0x6c, 0x65, 0x6d,
+ 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74,
+ 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x61, 0x76, 0x2d,
+ 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d,
+ 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x61,
+ 0x76, 0x20, 0x6c, 0x69, 0x20, 0x3e, 0x20, 0x2a, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e,
+ 0x67, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x61, 0x76, 0x20, 0x3a, 0x77, 0x68, 0x65, 0x72,
+ 0x65, 0x28, 0x61, 0x2c, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x6e, 0x6b, 0x5d, 0x29,
+ 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70,
+ 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x62, 0x6c, 0x6f, 0x63,
+ 0x6b, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67,
+ 0x69, 0x6e, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e,
+ 0x61, 0x76, 0x2d, 0x6c, 0x69, 0x6e, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d,
+ 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x2d, 0x31, 0x29, 0x20,
+ 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x61, 0x76, 0x2d, 0x6c,
+ 0x69, 0x6e, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69,
+ 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x2d, 0x31, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a,
+ 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x61, 0x76, 0x2d, 0x6c, 0x69, 0x6e, 0x6b, 0x2d,
+ 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c,
+ 0x29, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x61, 0x76, 0x2d, 0x6c, 0x69, 0x6e, 0x6b,
+ 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e,
+ 0x74, 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75,
+ 0x73, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78,
+ 0x74, 0x2d, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x6e, 0x6f,
+ 0x6e, 0x65, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x61, 0x76, 0x20, 0x3a, 0x77, 0x68, 0x65, 0x72, 0x65, 0x28,
+ 0x61, 0x2c, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x6e, 0x6b, 0x5d, 0x29, 0x3a, 0x69,
+ 0x73, 0x28, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5d,
+ 0x2c, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c,
+ 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x64, 0x65, 0x63, 0x6f,
+ 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6e,
+ 0x61, 0x76, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x3d, 0x62, 0x72,
+ 0x65, 0x61, 0x64, 0x63, 0x72, 0x75, 0x6d, 0x62, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x2d, 0x69, 0x74, 0x65, 0x6d, 0x73,
+ 0x3a, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x65,
+ 0x6e, 0x74, 0x3a, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x61, 0x76, 0x5b,
+ 0x61, 0x72, 0x69, 0x61, 0x2d, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x3d, 0x62, 0x72, 0x65, 0x61, 0x64,
+ 0x63, 0x72, 0x75, 0x6d, 0x62, 0x5d, 0x20, 0x75, 0x6c, 0x20, 0x6c, 0x69, 0x3a, 0x6e, 0x6f, 0x74,
+ 0x28, 0x3a, 0x66, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x29, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77,
+ 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x73, 0x74, 0x61,
+ 0x72, 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x61, 0x76, 0x2d, 0x6c, 0x69,
+ 0x6e, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a,
+ 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x69, 0x6e, 0x6c, 0x69,
+ 0x6e, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x6e, 0x61, 0x76, 0x2d, 0x6c, 0x69, 0x6e, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67,
+ 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x6e, 0x61, 0x76, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x6c, 0x61, 0x62, 0x65,
+ 0x6c, 0x3d, 0x62, 0x72, 0x65, 0x61, 0x64, 0x63, 0x72, 0x75, 0x6d, 0x62, 0x5d, 0x20, 0x75, 0x6c,
+ 0x20, 0x6c, 0x69, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x3a, 0x6c, 0x61, 0x73, 0x74, 0x2d, 0x63, 0x68,
+ 0x69, 0x6c, 0x64, 0x29, 0x20, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x6f, 0x73, 0x69,
+ 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x64,
+ 0x74, 0x68, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e,
+ 0x61, 0x76, 0x2d, 0x6c, 0x69, 0x6e, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d,
+ 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x32, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x73, 0x74,
+ 0x61, 0x72, 0x74, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x6e, 0x61, 0x76, 0x2d, 0x6c, 0x69, 0x6e, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67,
+ 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x2f, 0x20, 0x32, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d,
+ 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x73, 0x74, 0x61,
+ 0x72, 0x74, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e,
+ 0x61, 0x76, 0x2d, 0x6c, 0x69, 0x6e, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d,
+ 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x2f, 0x20, 0x32, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f,
+ 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x22, 0x2f, 0x22, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x63, 0x65, 0x6e,
+ 0x74, 0x65, 0x72, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x61, 0x76, 0x5b, 0x61, 0x72,
+ 0x69, 0x61, 0x2d, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x3d, 0x62, 0x72, 0x65, 0x61, 0x64, 0x63, 0x72,
+ 0x75, 0x6d, 0x62, 0x5d, 0x20, 0x61, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x63, 0x75, 0x72, 0x72,
+ 0x65, 0x6e, 0x74, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e,
+ 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78,
+ 0x74, 0x2d, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x6e, 0x6f,
+ 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x3a,
+ 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x61, 0x76, 0x20, 0x5b, 0x72, 0x6f, 0x6c,
+ 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x72, 0x69, 0x67, 0x68,
+ 0x74, 0x3a, 0x20, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74,
+ 0x3a, 0x20, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x6e, 0x61, 0x76, 0x2d, 0x6c, 0x69, 0x6e, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63,
+ 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x61, 0x76, 0x2d, 0x6c, 0x69, 0x6e, 0x6b, 0x2d, 0x73, 0x70, 0x61,
+ 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x61, 0x73, 0x69, 0x64, 0x65,
+ 0x20, 0x6c, 0x69, 0x2c, 0x20, 0x61, 0x73, 0x69, 0x64, 0x65, 0x20, 0x6e, 0x61, 0x76, 0x2c, 0x20,
+ 0x61, 0x73, 0x69, 0x64, 0x65, 0x20, 0x6f, 0x6c, 0x2c, 0x20, 0x61, 0x73, 0x69, 0x64, 0x65, 0x20,
+ 0x75, 0x6c, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61,
+ 0x79, 0x3a, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x61,
+ 0x73, 0x69, 0x64, 0x65, 0x20, 0x6c, 0x69, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70,
+ 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x6e, 0x61, 0x76, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73,
+ 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29,
+ 0x20, 0x2a, 0x20, 0x2e, 0x35, 0x29, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x61, 0x76,
+ 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67,
+ 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x0d, 0x0a, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x73, 0x69, 0x64, 0x65, 0x20, 0x6c, 0x69, 0x20,
+ 0x61, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73,
+ 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x73, 0x69, 0x64, 0x65, 0x20,
+ 0x6c, 0x69, 0x20, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5d,
+ 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67,
+ 0x69, 0x6e, 0x3a, 0x20, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x5b, 0x64, 0x69, 0x72, 0x3d, 0x72, 0x74, 0x6c, 0x5d, 0x20,
+ 0x6e, 0x61, 0x76, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x3d, 0x62,
+ 0x72, 0x65, 0x61, 0x64, 0x63, 0x72, 0x75, 0x6d, 0x62, 0x5d, 0x20, 0x75, 0x6c, 0x20, 0x6c, 0x69,
+ 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x3a, 0x6c, 0x61, 0x73, 0x74, 0x2d, 0x63, 0x68, 0x69, 0x6c, 0x64,
+ 0x29, 0x20, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x22, 0x5c, 0x5c, 0x22, 0x0d, 0x0a,
+ 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x69, 0x6e,
+ 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a,
+ 0x20, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e,
+ 0x63, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x6d, 0x6f, 0x7a, 0x2d, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x3a, 0x20,
+ 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c,
+ 0x61, 0x79, 0x3a, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x61, 0x6e, 0x63,
+ 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69,
+ 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x2e, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f,
+ 0x6d, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70,
+ 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x20, 0x2a, 0x20, 0x2e, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x3a, 0x20, 0x68, 0x69, 0x64,
+ 0x64, 0x65, 0x6e, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x6f, 0x67,
+ 0x72, 0x65, 0x73, 0x73, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65,
+ 0x73, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x3a, 0x2d, 0x77,
+ 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2d, 0x62,
+ 0x61, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b,
+ 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x20, 0x30, 0x20, 0x30, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65,
+ 0x73, 0x73, 0x5b, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5d, 0x3a, 0x3a, 0x2d, 0x77, 0x65, 0x62, 0x6b,
+ 0x69, 0x74, 0x2d, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2d, 0x76, 0x61, 0x6c, 0x75,
+ 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2d, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x3a, 0x2d, 0x6d, 0x6f,
+ 0x7a, 0x2d, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2d, 0x62, 0x61, 0x72, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28,
+ 0x2d, 0x2d, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6d, 0x65, 0x64,
+ 0x69, 0x61, 0x20, 0x28, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x73, 0x2d, 0x72, 0x65, 0x64, 0x75,
+ 0x63, 0x65, 0x64, 0x2d, 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x6e, 0x6f, 0x2d, 0x70, 0x72,
+ 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x69, 0x6e, 0x64, 0x65, 0x74, 0x65,
+ 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2d, 0x62, 0x61,
+ 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x20,
+ 0x6c, 0x69, 0x6e, 0x65, 0x61, 0x72, 0x2d, 0x67, 0x72, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x74, 0x28,
+ 0x74, 0x6f, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2c, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70,
+ 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x20, 0x33,
+ 0x30, 0x25, 0x2c, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73,
+ 0x73, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x29, 0x20, 0x33, 0x30, 0x25, 0x29, 0x20, 0x74, 0x6f, 0x70, 0x20, 0x6c, 0x65, 0x66,
+ 0x74, 0x2f, 0x31, 0x35, 0x30, 0x25, 0x20, 0x31, 0x35, 0x30, 0x25, 0x20, 0x6e, 0x6f, 0x2d, 0x72,
+ 0x65, 0x70, 0x65, 0x61, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,
+ 0x65, 0x73, 0x73, 0x2d, 0x69, 0x6e, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74,
+ 0x65, 0x20, 0x31, 0x73, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x61, 0x72, 0x20, 0x69, 0x6e, 0x66, 0x69,
+ 0x6e, 0x69, 0x74, 0x65, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x3a,
+ 0x69, 0x6e, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x5b, 0x76, 0x61,
+ 0x6c, 0x75, 0x65, 0x5d, 0x3a, 0x3a, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x70, 0x72,
+ 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b,
+ 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x74, 0x72,
+ 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x69, 0x6e, 0x64, 0x65, 0x74, 0x65, 0x72,
+ 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x3a, 0x3a, 0x2d, 0x6d, 0x6f, 0x7a, 0x2d, 0x70, 0x72, 0x6f,
+ 0x67, 0x72, 0x65, 0x73, 0x73, 0x2d, 0x62, 0x61, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73,
+ 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20, 0x28,
+ 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x73, 0x2d, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x64, 0x2d,
+ 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x6e, 0x6f, 0x2d, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72,
+ 0x65, 0x6e, 0x63, 0x65, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x64, 0x69,
+ 0x72, 0x3d, 0x72, 0x74, 0x6c, 0x5d, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x3a,
+ 0x69, 0x6e, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x72, 0x65,
+ 0x76, 0x65, 0x72, 0x73, 0x65, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x40, 0x6b, 0x65, 0x79, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x20, 0x70, 0x72,
+ 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x2d, 0x69, 0x6e, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69,
+ 0x6e, 0x61, 0x74, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x30, 0x25, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x32,
+ 0x30, 0x30, 0x25, 0x20, 0x30, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x25, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x70,
+ 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x2d, 0x32, 0x30, 0x30, 0x25, 0x20, 0x30,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x64, 0x65,
+ 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d,
+ 0x2c, 0x20, 0x6c, 0x69, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a,
+ 0x20, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5b, 0x72, 0x6f, 0x6c, 0x65,
+ 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x20, 0x2b,
+ 0x20, 0x75, 0x6c, 0x2c, 0x20, 0x6c, 0x69, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73,
+ 0x74, 0x5d, 0x20, 0x3e, 0x20, 0x75, 0x6c, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x66, 0x6c, 0x65, 0x78,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7a, 0x2d, 0x69, 0x6e, 0x64,
+ 0x65, 0x78, 0x3a, 0x20, 0x39, 0x39, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x61, 0x62, 0x73, 0x6f, 0x6c,
+ 0x75, 0x74, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x6f,
+ 0x70, 0x3a, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x65, 0x78, 0x2d, 0x64, 0x69, 0x72, 0x65,
+ 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20,
+ 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64,
+ 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29, 0x20, 0x73, 0x6f, 0x6c,
+ 0x69, 0x64, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x64, 0x72, 0x6f, 0x70, 0x64, 0x6f, 0x77,
+ 0x6e, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x74,
+ 0x6f, 0x70, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a,
+ 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72,
+ 0x64, 0x65, 0x72, 0x2d, 0x74, 0x6f, 0x70, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x72, 0x61, 0x64,
+ 0x69, 0x75, 0x73, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x64, 0x72, 0x6f, 0x70, 0x64, 0x6f, 0x77,
+ 0x6e, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f,
+ 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x63, 0x61, 0x72, 0x64, 0x2d, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x64, 0x72, 0x6f, 0x70, 0x64, 0x6f, 0x77, 0x6e,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x65, 0x3a, 0x20, 0x6e,
+ 0x6f, 0x77, 0x72, 0x61, 0x70, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5b,
+ 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61,
+ 0x72, 0x79, 0x20, 0x2b, 0x20, 0x75, 0x6c, 0x20, 0x6c, 0x69, 0x2c, 0x20, 0x6c, 0x69, 0x5b, 0x72,
+ 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20, 0x3e, 0x20, 0x75, 0x6c, 0x20, 0x6c,
+ 0x69, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69,
+ 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e,
+ 0x67, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f,
+ 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69,
+ 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x2e,
+ 0x35, 0x29, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f,
+ 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x2d, 0x73, 0x74, 0x79,
+ 0x6c, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d,
+ 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x20, 0x2b, 0x20,
+ 0x75, 0x6c, 0x20, 0x6c, 0x69, 0x3a, 0x66, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x6f, 0x66, 0x2d, 0x74,
+ 0x79, 0x70, 0x65, 0x2c, 0x20, 0x6c, 0x69, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73,
+ 0x74, 0x5d, 0x20, 0x3e, 0x20, 0x75, 0x6c, 0x20, 0x6c, 0x69, 0x3a, 0x66, 0x69, 0x72, 0x73, 0x74,
+ 0x2d, 0x6f, 0x66, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67,
+ 0x69, 0x6e, 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d,
+ 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c,
+ 0x29, 0x20, 0x2a, 0x20, 0x2e, 0x35, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5b, 0x72, 0x6f,
+ 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79,
+ 0x20, 0x2b, 0x20, 0x75, 0x6c, 0x20, 0x6c, 0x69, 0x3a, 0x6c, 0x61, 0x73, 0x74, 0x2d, 0x6f, 0x66,
+ 0x2d, 0x74, 0x79, 0x70, 0x65, 0x2c, 0x20, 0x6c, 0x69, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c,
+ 0x69, 0x73, 0x74, 0x5d, 0x20, 0x3e, 0x20, 0x75, 0x6c, 0x20, 0x6c, 0x69, 0x3a, 0x6c, 0x61, 0x73,
+ 0x74, 0x2d, 0x6f, 0x66, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72,
+ 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63,
+ 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d,
+ 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74,
+ 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x2e, 0x35, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c,
+ 0x73, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20, 0x73, 0x75, 0x6d,
+ 0x6d, 0x61, 0x72, 0x79, 0x20, 0x2b, 0x20, 0x75, 0x6c, 0x20, 0x6c, 0x69, 0x20, 0x61, 0x2c, 0x20,
+ 0x6c, 0x69, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20, 0x3e, 0x20,
+ 0x75, 0x6c, 0x20, 0x6c, 0x69, 0x20, 0x61, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c,
+ 0x61, 0x79, 0x3a, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67,
+ 0x69, 0x6e, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66,
+ 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63,
+ 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20,
+ 0x2d, 0x2e, 0x35, 0x29, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61,
+ 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29,
+ 0x20, 0x2a, 0x20, 0x2d, 0x31, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
+ 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72,
+ 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e,
+ 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x2e, 0x35,
+ 0x29, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65,
+ 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72,
+ 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x66,
+ 0x6c, 0x6f, 0x77, 0x3a, 0x20, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x64, 0x72, 0x6f, 0x70, 0x64,
+ 0x6f, 0x77, 0x6e, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78,
+ 0x74, 0x2d, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x6e, 0x6f,
+ 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x6f, 0x76, 0x65, 0x72, 0x66, 0x6c,
+ 0x6f, 0x77, 0x3a, 0x20, 0x65, 0x6c, 0x6c, 0x69, 0x70, 0x73, 0x69, 0x73, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64,
+ 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74,
+ 0x5d, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x20, 0x2b, 0x20, 0x75, 0x6c, 0x20, 0x6c,
+ 0x69, 0x20, 0x61, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x20, 0x6c, 0x69, 0x5b, 0x72, 0x6f,
+ 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20, 0x3e, 0x20, 0x75, 0x6c, 0x20, 0x6c, 0x69,
+ 0x20, 0x61, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x64, 0x72, 0x6f, 0x70, 0x64, 0x6f, 0x77, 0x6e,
+ 0x2d, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d,
+ 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x3a, 0x3a, 0x61,
+ 0x66, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x6c, 0x69, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69,
+ 0x73, 0x74, 0x5d, 0x20, 0x3e, 0x20, 0x61, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61,
+ 0x79, 0x3a, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x72, 0x65, 0x6d, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a,
+ 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x31, 0x72, 0x65, 0x6d, 0x20, 0x2a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x2c, 0x31,
+ 0x2e, 0x35, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x73, 0x74,
+ 0x61, 0x72, 0x74, 0x3a, 0x20, 0x30, 0x2e, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x69, 0x6e, 0x6c,
+ 0x69, 0x6e, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20, 0x2e, 0x35, 0x72, 0x65, 0x6d,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74,
+ 0x3a, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x72, 0x6f, 0x74,
+ 0x61, 0x74, 0x65, 0x28, 0x30, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x73, 0x69,
+ 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x63, 0x65, 0x6e, 0x74,
+ 0x65, 0x72, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x31, 0x72,
+ 0x65, 0x6d, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x72, 0x65, 0x70,
+ 0x65, 0x61, 0x74, 0x3a, 0x20, 0x6e, 0x6f, 0x2d, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
+ 0x3a, 0x20, 0x22, 0x22, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x64,
+ 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74,
+ 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
+ 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x0d, 0x0a, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5b,
+ 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61,
+ 0x72, 0x79, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61,
+ 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x30, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69,
+ 0x73, 0x74, 0x5d, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x3a, 0x6e, 0x6f, 0x74, 0x28,
+ 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x5d, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x63,
+ 0x61, 0x6c, 0x63, 0x28, 0x31, 0x72, 0x65, 0x6d, 0x20, 0x2a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x29, 0x20, 0x2b, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69,
+ 0x63, 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x32, 0x20, 0x2b, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29, 0x20, 0x2a,
+ 0x20, 0x32, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70,
+ 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a,
+ 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29,
+ 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72,
+ 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64,
+ 0x69, 0x75, 0x73, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65,
+ 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75,
+ 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65,
+ 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64,
+ 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69,
+ 0x67, 0x68, 0x74, 0x3a, 0x20, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x75, 0x72, 0x73, 0x6f,
+ 0x72, 0x3a, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74,
+ 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e,
+ 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x72,
+ 0x28, 0x2d, 0x2d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x2c, 0x62,
+ 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5b, 0x72, 0x6f,
+ 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79,
+ 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x5d, 0x29, 0x3a, 0x61, 0x63, 0x74,
+ 0x69, 0x76, 0x65, 0x2c, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5b, 0x72, 0x6f, 0x6c,
+ 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x3a,
+ 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x5d, 0x29, 0x3a, 0x66, 0x6f, 0x63, 0x75,
+ 0x73, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x62, 0x6f, 0x72,
+ 0x64, 0x65, 0x72, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63,
+ 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73,
+ 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20, 0x73, 0x75, 0x6d, 0x6d,
+ 0x61, 0x72, 0x79, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x5d, 0x29, 0x3a,
+ 0x66, 0x6f, 0x63, 0x75, 0x73, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x78, 0x2d, 0x73, 0x68, 0x61,
+ 0x64, 0x6f, 0x77, 0x3a, 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5b, 0x72, 0x6f,
+ 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x5b, 0x6f, 0x70, 0x65, 0x6e, 0x5d, 0x20, 0x73,
+ 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x2d,
+ 0x72, 0x69, 0x67, 0x68, 0x74, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x30, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x72, 0x61, 0x64,
+ 0x69, 0x75, 0x73, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73,
+ 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x5b, 0x6f, 0x70, 0x65, 0x6e,
+ 0x5d, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x3a, 0x3a, 0x62, 0x65, 0x66, 0x6f, 0x72,
+ 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7a, 0x2d,
+ 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3a, 0x20, 0x31, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a,
+ 0x20, 0x66, 0x69, 0x78, 0x65, 0x64, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a,
+ 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x20, 0x30,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62,
+ 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x3a, 0x20, 0x30, 0x20, 0x30, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e,
+ 0x74, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x22, 0x22, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x3a, 0x20, 0x64,
+ 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x6e, 0x61, 0x76, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73,
+ 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20, 0x73, 0x75, 0x6d, 0x6d,
+ 0x61, 0x72, 0x79, 0x2c, 0x20, 0x6e, 0x61, 0x76, 0x20, 0x6c, 0x69, 0x5b, 0x72, 0x6f, 0x6c, 0x65,
+ 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20, 0x61, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x66, 0x6c, 0x65, 0x78, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x6c,
+ 0x74, 0x72, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x61, 0x76,
+ 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69,
+ 0x73, 0x74, 0x5d, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x20, 0x2b, 0x20, 0x75, 0x6c,
+ 0x2c, 0x20, 0x6e, 0x61, 0x76, 0x20, 0x6c, 0x69, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69,
+ 0x73, 0x74, 0x5d, 0x20, 0x3e, 0x20, 0x75, 0x6c, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x6d, 0x69, 0x6e, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x2d,
+ 0x6d, 0x6f, 0x7a, 0x2d, 0x66, 0x69, 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x69, 0x6e, 0x2d, 0x77, 0x69,
+ 0x64, 0x74, 0x68, 0x3a, 0x20, 0x66, 0x69, 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65,
+ 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x29, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x6e, 0x61, 0x76, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5b, 0x72, 0x6f, 0x6c,
+ 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x20,
+ 0x2b, 0x20, 0x75, 0x6c, 0x20, 0x6c, 0x69, 0x20, 0x61, 0x2c, 0x20, 0x6e, 0x61, 0x76, 0x20, 0x6c,
+ 0x69, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20, 0x3e, 0x20, 0x75,
+ 0x6c, 0x20, 0x6c, 0x69, 0x20, 0x61, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64,
+ 0x69, 0x75, 0x73, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x61, 0x76, 0x20, 0x64, 0x65, 0x74,
+ 0x61, 0x69, 0x6c, 0x73, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20,
+ 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x6e, 0x61, 0x76, 0x20, 0x64, 0x65, 0x74,
+ 0x61, 0x69, 0x6c, 0x73, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20,
+ 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x72, 0x6f, 0x6c,
+ 0x65, 0x5d, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x68,
+ 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x61, 0x76, 0x2d, 0x6c, 0x69, 0x6e, 0x6b, 0x2d, 0x73, 0x70,
+ 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20,
+ 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x61, 0x76, 0x2d, 0x6c, 0x69, 0x6e, 0x6b, 0x2d, 0x73,
+ 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61,
+ 0x6c, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x6e, 0x61, 0x76,
+ 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69,
+ 0x73, 0x74, 0x5d, 0x5b, 0x6f, 0x70, 0x65, 0x6e, 0x5d, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72,
+ 0x79, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d,
+ 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x29, 0x0d, 0x0a, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x6e, 0x61, 0x76, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5b, 0x72,
+ 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72,
+ 0x79, 0x20, 0x2b, 0x20, 0x75, 0x6c, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61,
+ 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x6d, 0x61, 0x72,
+ 0x67, 0x69, 0x6e, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65,
+ 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x6e, 0x61, 0x76, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5b, 0x72, 0x6f, 0x6c, 0x65,
+ 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x5b, 0x72,
+ 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x6e, 0x6b, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20,
+ 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x61, 0x76, 0x2d, 0x6c,
+ 0x69, 0x6e, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74,
+ 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x2d, 0x31, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74,
+ 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x61, 0x76, 0x20,
+ 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73,
+ 0x74, 0x5d, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d,
+ 0x6c, 0x69, 0x6e, 0x6b, 0x5d, 0x20, 0x2b, 0x20, 0x75, 0x6c, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x74, 0x6f, 0x70,
+ 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x61, 0x76,
+ 0x2d, 0x6c, 0x69, 0x6e, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65,
+ 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x29, 0x20, 0x2b, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69,
+ 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20,
+ 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x61, 0x76, 0x2d, 0x6c,
+ 0x69, 0x6e, 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69,
+ 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x2d, 0x31, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x69,
+ 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20, 0x63, 0x61, 0x6c,
+ 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x61, 0x76, 0x2d, 0x6c, 0x69, 0x6e, 0x6b,
+ 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e,
+ 0x74, 0x61, 0x6c, 0x29, 0x20, 0x2a, 0x20, 0x2d, 0x31, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x6c, 0x69, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73,
+ 0x74, 0x5d, 0x20, 0x61, 0x3a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x7e, 0x20, 0x75, 0x6c,
+ 0x2c, 0x20, 0x6c, 0x69, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20,
+ 0x61, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x20, 0x7e, 0x20, 0x75, 0x6c, 0x2c, 0x20, 0x6c, 0x69,
+ 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x3a, 0x68, 0x6f, 0x76, 0x65,
+ 0x72, 0x20, 0x3e, 0x20, 0x75, 0x6c, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69,
+ 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x66, 0x6c, 0x65, 0x78, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x6c, 0x69, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20,
+ 0x3e, 0x20, 0x75, 0x6c, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70,
+ 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63,
+ 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x61, 0x76, 0x2d, 0x6c, 0x69, 0x6e, 0x6b, 0x2d,
+ 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c,
+ 0x29, 0x20, 0x2b, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6f, 0x75, 0x74, 0x6c, 0x69, 0x6e,
+ 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x73,
+ 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x6e, 0x61, 0x76, 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61,
+ 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29,
+ 0x20, 0x2d, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x61, 0x76, 0x2d, 0x6c, 0x69, 0x6e,
+ 0x6b, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f,
+ 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72,
+ 0x67, 0x69, 0x6e, 0x2d, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74,
+ 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x61, 0x76,
+ 0x2d, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67,
+ 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x29, 0x20, 0x2d, 0x20, 0x76,
+ 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6e, 0x61, 0x76, 0x2d, 0x6c, 0x69, 0x6e, 0x6b, 0x2d, 0x73, 0x70,
+ 0x61, 0x63, 0x69, 0x6e, 0x67, 0x2d, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c,
+ 0x29, 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x6c, 0x69, 0x5b, 0x72, 0x6f, 0x6c, 0x65,
+ 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20, 0x3e, 0x20, 0x61, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x2d, 0x63, 0x68, 0x65, 0x76, 0x72, 0x6f, 0x6e, 0x29, 0x0d, 0x0a,
+ 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x20, 0x3e, 0x20, 0x64, 0x65, 0x74,
+ 0x61, 0x69, 0x6c, 0x73, 0x5b, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x6c, 0x69, 0x73, 0x74, 0x5d, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x74, 0x6f,
+ 0x70, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70,
+ 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x20, 0x2a, 0x20, 0x2e, 0x32, 0x35, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f,
+ 0x6d, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67,
+ 0x29, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x62, 0x75,
+ 0x73, 0x79, 0x3d, 0x74, 0x72, 0x75, 0x65, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x3a, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73,
+ 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x61, 0x72, 0x69, 0x61,
+ 0x2d, 0x62, 0x75, 0x73, 0x79, 0x3d, 0x74, 0x72, 0x75, 0x65, 0x5d, 0x3a, 0x6e, 0x6f, 0x74, 0x28,
+ 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x2c, 0x74, 0x65, 0x78,
+ 0x74, 0x61, 0x72, 0x65, 0x61, 0x2c, 0x68, 0x74, 0x6d, 0x6c, 0x29, 0x3a, 0x3a, 0x62, 0x65, 0x66,
+ 0x6f, 0x72, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64,
+ 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x62,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77,
+ 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x31, 0x65, 0x6d, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x3a, 0x20, 0x2e, 0x31, 0x38, 0x37, 0x35, 0x65, 0x6d, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x20,
+ 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61,
+ 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x31, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74,
+ 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72,
+ 0x65, 0x6e, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f,
+ 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x22, 0x22, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x2d, 0x61, 0x6c, 0x69,
+ 0x67, 0x6e, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63,
+ 0x61, 0x6c, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x2d, 0x2e, 0x31, 0x32, 0x35, 0x65,
+ 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6e, 0x69, 0x6d,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x73, 0x70, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x20, 0x2e,
+ 0x37, 0x35, 0x73, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x61, 0x72, 0x20, 0x69, 0x6e, 0x66, 0x69, 0x6e,
+ 0x69, 0x74, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x70,
+ 0x61, 0x63, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x6c, 0x6f, 0x61,
+ 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x73, 0x70, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x2d, 0x6f, 0x70, 0x61,
+ 0x63, 0x69, 0x74, 0x79, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x62, 0x75, 0x73, 0x79, 0x3d, 0x74,
+ 0x72, 0x75, 0x65, 0x5d, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x73,
+ 0x65, 0x6c, 0x65, 0x63, 0x74, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x2c, 0x68,
+ 0x74, 0x6d, 0x6c, 0x29, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x3a, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x29,
+ 0x3a, 0x3a, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74,
+ 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61,
+ 0x63, 0x69, 0x6e, 0x67, 0x29, 0x20, 0x2a, 0x20, 0x2e, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66,
+ 0x74, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d,
+ 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x73, 0x74,
+ 0x61, 0x72, 0x74, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x73,
+ 0x74, 0x61, 0x72, 0x74, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x2d, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2d, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e,
+ 0x2d, 0x65, 0x6e, 0x64, 0x3a, 0x20, 0x63, 0x61, 0x6c, 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d,
+ 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29, 0x20, 0x2a, 0x20, 0x2e, 0x35, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e,
+ 0x2d, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2d, 0x65, 0x6e, 0x64, 0x3a, 0x20, 0x63, 0x61, 0x6c,
+ 0x63, 0x28, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x29,
+ 0x20, 0x2a, 0x20, 0x2e, 0x35, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x62, 0x75, 0x73, 0x79, 0x3d,
+ 0x74, 0x72, 0x75, 0x65, 0x5d, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2c,
+ 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x2c,
+ 0x68, 0x74, 0x6d, 0x6c, 0x29, 0x3a, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67,
+ 0x6e, 0x3a, 0x20, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x61, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x62, 0x75, 0x73, 0x79, 0x3d,
+ 0x74, 0x72, 0x75, 0x65, 0x5d, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5b, 0x61, 0x72,
+ 0x69, 0x61, 0x2d, 0x62, 0x75, 0x73, 0x79, 0x3d, 0x74, 0x72, 0x75, 0x65, 0x5d, 0x2c, 0x20, 0x69,
+ 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e,
+ 0x5d, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x62, 0x75, 0x73, 0x79, 0x3d, 0x74, 0x72, 0x75, 0x65,
+ 0x5d, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x72, 0x65,
+ 0x73, 0x65, 0x74, 0x5d, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x62, 0x75, 0x73, 0x79, 0x3d, 0x74,
+ 0x72, 0x75, 0x65, 0x5d, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5b, 0x74, 0x79, 0x70, 0x65,
+ 0x3d, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5d, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x62, 0x75,
+ 0x73, 0x79, 0x3d, 0x74, 0x72, 0x75, 0x65, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x3a, 0x20,
+ 0x6e, 0x6f, 0x6e, 0x65, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6b, 0x65, 0x79, 0x66,
+ 0x72, 0x61, 0x6d, 0x65, 0x73, 0x20, 0x73, 0x70, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x6f, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x72, 0x6f,
+ 0x74, 0x61, 0x74, 0x65, 0x28, 0x33, 0x36, 0x30, 0x64, 0x65, 0x67, 0x29, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d,
+ 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69,
+ 0x76, 0x65, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x64, 0x61,
+ 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x3a, 0x6e, 0x6f, 0x74, 0x28,
+ 0x61, 0x2c, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65,
+ 0x72, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x31, 0x70, 0x78, 0x20, 0x64, 0x6f,
+ 0x74, 0x74, 0x65, 0x64, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74,
+ 0x65, 0x78, 0x74, 0x2d, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20,
+ 0x6e, 0x6f, 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63,
+ 0x75, 0x72, 0x73, 0x6f, 0x72, 0x3a, 0x20, 0x68, 0x65, 0x6c, 0x70, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d,
+ 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x2c,
+ 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x3a,
+ 0x3a, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x2c, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74,
+ 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x70, 0x6c, 0x61,
+ 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x74, 0x6f, 0x70, 0x5d, 0x3a, 0x3a, 0x61, 0x66, 0x74,
+ 0x65, 0x72, 0x2c, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69,
+ 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x3d, 0x74, 0x6f, 0x70, 0x5d, 0x3a, 0x3a, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61,
+ 0x79, 0x3a, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x7a, 0x2d, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3a, 0x20, 0x39, 0x39, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f,
+ 0x6e, 0x3a, 0x20, 0x61, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x31, 0x30,
+ 0x30, 0x25, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x66,
+ 0x74, 0x3a, 0x20, 0x35, 0x30, 0x25, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x2e, 0x32, 0x35, 0x72, 0x65, 0x6d,
+ 0x20, 0x2e, 0x35, 0x72, 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x6f, 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x3a, 0x20, 0x68, 0x69, 0x64, 0x64, 0x65,
+ 0x6e, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e,
+ 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65,
+ 0x28, 0x2d, 0x35, 0x30, 0x25, 0x2c, 0x2d, 0x2e, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d,
+ 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x62, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x29, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70,
+ 0x2d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e,
+ 0x74, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x61, 0x74, 0x74, 0x72, 0x28, 0x64, 0x61, 0x74, 0x61, 0x2d,
+ 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d,
+ 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x74,
+ 0x79, 0x6c, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x3a, 0x20, 0x76, 0x61, 0x72, 0x28, 0x2d, 0x2d, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65,
+ 0x69, 0x67, 0x68, 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x2e, 0x38, 0x37, 0x35, 0x72,
+ 0x65, 0x6d, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78,
+ 0x74, 0x2d, 0x64, 0x65, 0x63, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x6e, 0x6f,
+ 0x6e, 0x65, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x78,
+ 0x74, 0x2d, 0x6f, 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x3a, 0x20, 0x65, 0x6c, 0x6c, 0x69,
+ 0x70, 0x73, 0x69, 0x73, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77,
+ 0x68, 0x69, 0x74, 0x65, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x77, 0x72,
+ 0x61, 0x70, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x70, 0x61,
+ 0x63, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73,
+ 0x3a, 0x20, 0x6e, 0x6f, 0x6e, 0x65, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74,
+ 0x69, 0x70, 0x5d, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x5b, 0x64, 0x61, 0x74,
+ 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d,
+ 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x74, 0x6f, 0x70, 0x5d, 0x3a, 0x3a,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a,
+ 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65, 0x28, 0x2d, 0x35, 0x30, 0x25, 0x2c,
+ 0x30, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72,
+ 0x64, 0x65, 0x72, 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x2e, 0x33, 0x72, 0x65, 0x6d, 0x20, 0x73,
+ 0x6f, 0x6c, 0x69, 0x64, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x2e, 0x33, 0x72,
+ 0x65, 0x6d, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61,
+ 0x72, 0x65, 0x6e, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62,
+ 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x20, 0x2e, 0x33, 0x72, 0x65,
+ 0x6d, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72,
+ 0x65, 0x6e, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x30, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73,
+ 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x22, 0x22, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x76, 0x61,
+ 0x72, 0x28, 0x2d, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x2d, 0x62, 0x61, 0x63, 0x6b,
+ 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x64, 0x61, 0x74,
+ 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d,
+ 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d,
+ 0x5d, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d,
+ 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x70, 0x6c,
+ 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x5d, 0x3a,
+ 0x3a, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x61,
+ 0x75, 0x74, 0x6f, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72,
+ 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61,
+ 0x74, 0x65, 0x28, 0x2d, 0x35, 0x30, 0x25, 0x2c, 0x2e, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x29, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x64,
+ 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74,
+ 0x61, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x62, 0x6f, 0x74, 0x74,
+ 0x6f, 0x6d, 0x5d, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20,
+ 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65, 0x28, 0x2d, 0x35, 0x30, 0x25, 0x2c, 0x2d,
+ 0x2e, 0x33, 0x72, 0x65, 0x6d, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x2e, 0x33, 0x72, 0x65, 0x6d, 0x20, 0x73,
+ 0x6f, 0x6c, 0x69, 0x64, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65,
+ 0x72, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x2e, 0x33, 0x72, 0x65, 0x6d, 0x20,
+ 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69,
+ 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x3d, 0x6c, 0x65, 0x66, 0x74, 0x5d, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x2c, 0x20,
+ 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64,
+ 0x61, 0x74, 0x61, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x6c, 0x65,
+ 0x66, 0x74, 0x5d, 0x3a, 0x3a, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x35, 0x30, 0x25, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a,
+ 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x20, 0x61, 0x75, 0x74,
+ 0x6f, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e,
+ 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65,
+ 0x28, 0x2d, 0x2e, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x2c, 0x2d, 0x35, 0x30, 0x25, 0x29, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x64, 0x61,
+ 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74, 0x61,
+ 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x6c, 0x65, 0x66, 0x74, 0x5d,
+ 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x74, 0x72, 0x61,
+ 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65, 0x28, 0x2e, 0x33, 0x72, 0x65, 0x6d, 0x2c, 0x2d, 0x35, 0x30,
+ 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72,
+ 0x64, 0x65, 0x72, 0x3a, 0x20, 0x2e, 0x33, 0x72, 0x65, 0x6d, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64,
+ 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x6c, 0x65,
+ 0x66, 0x74, 0x3a, 0x20, 0x2e, 0x33, 0x72, 0x65, 0x6d, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x64,
+ 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74,
+ 0x61, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x72, 0x69, 0x67, 0x68,
+ 0x74, 0x5d, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61,
+ 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x70,
+ 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x5d, 0x3a,
+ 0x3a, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x35, 0x30, 0x25, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x61, 0x75, 0x74,
+ 0x6f, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x74, 0x74,
+ 0x6f, 0x6d, 0x3a, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72,
+ 0x6d, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65, 0x28, 0x2e, 0x32, 0x35,
+ 0x72, 0x65, 0x6d, 0x2c, 0x2d, 0x35, 0x30, 0x25, 0x29, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f,
+ 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x70, 0x6c, 0x61, 0x63,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x5d, 0x3a, 0x61, 0x66, 0x74,
+ 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72,
+ 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61,
+ 0x74, 0x65, 0x28, 0x2d, 0x2e, 0x33, 0x72, 0x65, 0x6d, 0x2c, 0x2d, 0x35, 0x30, 0x25, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
+ 0x3a, 0x20, 0x2e, 0x33, 0x72, 0x65, 0x6d, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x20, 0x74, 0x72,
+ 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74,
+ 0x3a, 0x20, 0x2e, 0x33, 0x72, 0x65, 0x6d, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x64, 0x61, 0x74,
+ 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73,
+ 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74,
+ 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x3a, 0x3a, 0x62,
+ 0x65, 0x66, 0x6f, 0x72, 0x65, 0x2c, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f,
+ 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x3a, 0x3a, 0x61, 0x66, 0x74,
+ 0x65, 0x72, 0x2c, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69,
+ 0x70, 0x5d, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x3a, 0x3a, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65,
+ 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x70, 0x61, 0x63,
+ 0x69, 0x74, 0x79, 0x3a, 0x20, 0x31, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20, 0x28, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x3a, 0x68,
+ 0x6f, 0x76, 0x65, 0x72, 0x29, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x28, 0x70, 0x6f, 0x69, 0x6e, 0x74,
+ 0x65, 0x72, 0x3a, 0x66, 0x69, 0x6e, 0x65, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x3a, 0x68,
+ 0x6f, 0x76, 0x65, 0x72, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x5b, 0x64, 0x61,
+ 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x3a, 0x68, 0x6f, 0x76, 0x65,
+ 0x72, 0x3a, 0x3a, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x2c, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61,
+ 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x70,
+ 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x5d,
+ 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x5b,
+ 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64, 0x61,
+ 0x74, 0x61, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x62, 0x6f, 0x74,
+ 0x74, 0x6f, 0x6d, 0x5d, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x3a, 0x3a, 0x62, 0x65, 0x66, 0x6f,
+ 0x72, 0x65, 0x2c, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69,
+ 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x3d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x5d, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x20,
+ 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x3a, 0x66,
+ 0x6f, 0x63, 0x75, 0x73, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x5b, 0x64, 0x61,
+ 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74, 0x61,
+ 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x62, 0x6f, 0x74, 0x74, 0x6f,
+ 0x6d, 0x5d, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74,
+ 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x3a, 0x3a, 0x62,
+ 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x64, 0x75, 0x72, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x2e, 0x32, 0x73, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x6e, 0x61, 0x6d,
+ 0x65, 0x3a, 0x20, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x2d, 0x73, 0x6c, 0x69, 0x64, 0x65,
+ 0x2d, 0x74, 0x6f, 0x70, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70,
+ 0x5d, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x2c, 0x20,
+ 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64,
+ 0x61, 0x74, 0x61, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x62, 0x6f,
+ 0x74, 0x74, 0x6f, 0x6d, 0x5d, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x3a, 0x3a, 0x61, 0x66, 0x74,
+ 0x65, 0x72, 0x2c, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69,
+ 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x3d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x5d, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x20,
+ 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x3a, 0x66,
+ 0x6f, 0x63, 0x75, 0x73, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x20, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x2d, 0x63,
+ 0x61, 0x72, 0x65, 0x74, 0x2d, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x2d, 0x74, 0x6f, 0x70, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x64, 0x61,
+ 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74, 0x61,
+ 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x62, 0x6f, 0x74, 0x74, 0x6f,
+ 0x6d, 0x5d, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x2c,
+ 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b,
+ 0x64, 0x61, 0x74, 0x61, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x62,
+ 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x5d, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x3a, 0x3a, 0x62, 0x65,
+ 0x66, 0x6f, 0x72, 0x65, 0x2c, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c,
+ 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d,
+ 0x65, 0x6e, 0x74, 0x3d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x5d, 0x3a, 0x68, 0x6f, 0x76, 0x65,
+ 0x72, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d,
+ 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x70, 0x6c,
+ 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x5d, 0x3a,
+ 0x68, 0x6f, 0x76, 0x65, 0x72, 0x3a, 0x3a, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x2d, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x2e, 0x32, 0x73,
+ 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6e, 0x69, 0x6d, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x20, 0x74, 0x6f, 0x6f, 0x6c, 0x74,
+ 0x69, 0x70, 0x2d, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x64,
+ 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74,
+ 0x61, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x62, 0x6f, 0x74, 0x74,
+ 0x6f, 0x6d, 0x5d, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x2c, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d,
+ 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d,
+ 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x5d, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x3a, 0x3a, 0x61,
+ 0x66, 0x74, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x20,
+ 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x2d, 0x63, 0x61, 0x72, 0x65, 0x74, 0x2d, 0x73, 0x6c,
+ 0x69, 0x64, 0x65, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74,
+ 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x70, 0x6c, 0x61,
+ 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x6c, 0x65, 0x66, 0x74, 0x5d, 0x3a, 0x66, 0x6f, 0x63,
+ 0x75, 0x73, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61,
+ 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x70,
+ 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x6c, 0x65, 0x66, 0x74, 0x5d, 0x3a, 0x66,
+ 0x6f, 0x63, 0x75, 0x73, 0x3a, 0x3a, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x2c, 0x20, 0x5b, 0x64,
+ 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74,
+ 0x61, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x6c, 0x65, 0x66, 0x74,
+ 0x5d, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x2c, 0x20,
+ 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64,
+ 0x61, 0x74, 0x61, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x6c, 0x65,
+ 0x66, 0x74, 0x5d, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x3a, 0x3a, 0x62, 0x65, 0x66, 0x6f, 0x72,
+ 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6e, 0x69,
+ 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a,
+ 0x20, 0x2e, 0x32, 0x73, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61,
+ 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x20, 0x74,
+ 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x2d, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x2d, 0x6c, 0x65, 0x66,
+ 0x74, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64,
+ 0x61, 0x74, 0x61, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x6c, 0x65,
+ 0x66, 0x74, 0x5d, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x2c, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d,
+ 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d,
+ 0x6c, 0x65, 0x66, 0x74, 0x5d, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x3a, 0x3a, 0x61, 0x66, 0x74,
+ 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6e,
+ 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x20, 0x74, 0x6f,
+ 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x2d, 0x63, 0x61, 0x72, 0x65, 0x74, 0x2d, 0x73, 0x6c, 0x69, 0x64,
+ 0x65, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74,
+ 0x69, 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x3d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x5d, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x3a,
+ 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f,
+ 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x70, 0x6c, 0x61, 0x63,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x5d, 0x3a, 0x66, 0x6f, 0x63,
+ 0x75, 0x73, 0x3a, 0x3a, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x2c, 0x20, 0x5b, 0x64, 0x61, 0x74,
+ 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d,
+ 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x5d,
+ 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x5b,
+ 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b, 0x64, 0x61,
+ 0x74, 0x61, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x72, 0x69, 0x67,
+ 0x68, 0x74, 0x5d, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x3a, 0x3a, 0x62, 0x65, 0x66, 0x6f, 0x72,
+ 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6e, 0x69,
+ 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a,
+ 0x20, 0x2e, 0x32, 0x73, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61,
+ 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x3a, 0x20, 0x74,
+ 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x2d, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x2d, 0x72, 0x69, 0x67,
+ 0x68, 0x74, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x5d, 0x5b,
+ 0x64, 0x61, 0x74, 0x61, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x3d, 0x72,
+ 0x69, 0x67, 0x68, 0x74, 0x5d, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x3a, 0x3a, 0x61, 0x66, 0x74,
+ 0x65, 0x72, 0x2c, 0x20, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69,
+ 0x70, 0x5d, 0x5b, 0x64, 0x61, 0x74, 0x61, 0x2d, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e,
+ 0x74, 0x3d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x5d, 0x3a, 0x68, 0x6f, 0x76, 0x65, 0x72, 0x3a, 0x3a,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x3a,
+ 0x20, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x2d, 0x63, 0x61, 0x72, 0x65, 0x74, 0x2d, 0x73,
+ 0x6c, 0x69, 0x64, 0x65, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6b, 0x65, 0x79, 0x66, 0x72, 0x61, 0x6d,
+ 0x65, 0x73, 0x20, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x2d, 0x73, 0x6c, 0x69, 0x64, 0x65,
+ 0x2d, 0x74, 0x6f, 0x70, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x72, 0x6f, 0x6d,
+ 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e,
+ 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65,
+ 0x28, 0x2d, 0x35, 0x30, 0x25, 0x2c, 0x2e, 0x37, 0x35, 0x72, 0x65, 0x6d, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3a,
+ 0x20, 0x30, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x74, 0x6f, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74,
+ 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c,
+ 0x61, 0x74, 0x65, 0x28, 0x2d, 0x35, 0x30, 0x25, 0x2c, 0x2d, 0x2e, 0x32, 0x35, 0x72, 0x65, 0x6d,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x70, 0x61, 0x63,
+ 0x69, 0x74, 0x79, 0x3a, 0x20, 0x31, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6b, 0x65, 0x79, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x20, 0x74,
+ 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x2d, 0x63, 0x61, 0x72, 0x65, 0x74, 0x2d, 0x73, 0x6c, 0x69,
+ 0x64, 0x65, 0x2d, 0x74, 0x6f, 0x70, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x72,
+ 0x6f, 0x6d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x70,
+ 0x61, 0x63, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x35, 0x30, 0x25, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a,
+ 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65, 0x28, 0x2d, 0x35, 0x30, 0x25, 0x2c,
+ 0x2d, 0x2e, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x6f, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66,
+ 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65, 0x28, 0x2d,
+ 0x35, 0x30, 0x25, 0x2c, 0x30, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x31, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6b, 0x65, 0x79, 0x66, 0x72, 0x61,
+ 0x6d, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x2d, 0x73, 0x6c, 0x69, 0x64,
+ 0x65, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73,
+ 0x6c, 0x61, 0x74, 0x65, 0x28, 0x2d, 0x35, 0x30, 0x25, 0x2c, 0x2d, 0x2e, 0x37, 0x35, 0x72, 0x65,
+ 0x6d, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x70, 0x61,
+ 0x63, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x6f, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x74,
+ 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65, 0x28, 0x2d, 0x35, 0x30, 0x25, 0x2c, 0x2e, 0x32,
+ 0x35, 0x72, 0x65, 0x6d, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x31, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6b, 0x65, 0x79, 0x66, 0x72, 0x61, 0x6d,
+ 0x65, 0x73, 0x20, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x2d, 0x63, 0x61, 0x72, 0x65, 0x74,
+ 0x2d, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x30, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x35, 0x30,
+ 0x25, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61,
+ 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74,
+ 0x65, 0x28, 0x2d, 0x35, 0x30, 0x25, 0x2c, 0x2d, 0x2e, 0x35, 0x72, 0x65, 0x6d, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79,
+ 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x74, 0x6f, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73,
+ 0x6c, 0x61, 0x74, 0x65, 0x28, 0x2d, 0x35, 0x30, 0x25, 0x2c, 0x2d, 0x2e, 0x33, 0x72, 0x65, 0x6d,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x70, 0x61, 0x63,
+ 0x69, 0x74, 0x79, 0x3a, 0x20, 0x31, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6b, 0x65, 0x79, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x20, 0x74,
+ 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x2d, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x2d, 0x6c, 0x65, 0x66,
+ 0x74, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f,
+ 0x72, 0x6d, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65, 0x28, 0x2e, 0x37,
+ 0x35, 0x72, 0x65, 0x6d, 0x2c, 0x2d, 0x35, 0x30, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x30, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x6f,
+ 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e,
+ 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65,
+ 0x28, 0x2d, 0x2e, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x2c, 0x2d, 0x35, 0x30, 0x25, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79,
+ 0x3a, 0x20, 0x31, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x40, 0x6b, 0x65, 0x79, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x6f, 0x6c,
+ 0x74, 0x69, 0x70, 0x2d, 0x63, 0x61, 0x72, 0x65, 0x74, 0x2d, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x2d,
+ 0x6c, 0x65, 0x66, 0x74, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x72, 0x6f, 0x6d,
+ 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x70, 0x61, 0x63,
+ 0x69, 0x74, 0x79, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x35, 0x30, 0x25, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x74,
+ 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65, 0x28, 0x2e, 0x30, 0x35, 0x72, 0x65, 0x6d, 0x2c,
+ 0x2d, 0x35, 0x30, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x6f, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d,
+ 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65, 0x28, 0x2e, 0x33, 0x72, 0x65,
+ 0x6d, 0x2c, 0x2d, 0x35, 0x30, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x31, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6b, 0x65, 0x79, 0x66, 0x72,
+ 0x61, 0x6d, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x2d, 0x73, 0x6c, 0x69,
+ 0x64, 0x65, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73,
+ 0x6c, 0x61, 0x74, 0x65, 0x28, 0x2d, 0x2e, 0x37, 0x35, 0x72, 0x65, 0x6d, 0x2c, 0x2d, 0x35, 0x30,
+ 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x70, 0x61,
+ 0x63, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x6f, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x74,
+ 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65, 0x28, 0x2e, 0x32, 0x35, 0x72, 0x65, 0x6d, 0x2c,
+ 0x2d, 0x35, 0x30, 0x25, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x31, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6b, 0x65, 0x79, 0x66, 0x72, 0x61, 0x6d,
+ 0x65, 0x73, 0x20, 0x74, 0x6f, 0x6f, 0x6c, 0x74, 0x69, 0x70, 0x2d, 0x63, 0x61, 0x72, 0x65, 0x74,
+ 0x2d, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x3a, 0x20, 0x30, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x35, 0x30, 0x25,
+ 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e,
+ 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65,
+ 0x28, 0x2d, 0x2e, 0x30, 0x35, 0x72, 0x65, 0x6d, 0x2c, 0x2d, 0x35, 0x30, 0x25, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79,
+ 0x3a, 0x20, 0x30, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x74, 0x6f, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x3a, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73,
+ 0x6c, 0x61, 0x74, 0x65, 0x28, 0x2d, 0x2e, 0x33, 0x72, 0x65, 0x6d, 0x2c, 0x2d, 0x35, 0x30, 0x25,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x70, 0x61, 0x63,
+ 0x69, 0x74, 0x79, 0x3a, 0x20, 0x31, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
+ 0x6c, 0x73, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x75, 0x72, 0x73, 0x6f,
+ 0x72, 0x3a, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x3d,
+ 0x74, 0x72, 0x75, 0x65, 0x5d, 0x2c, 0x20, 0x5b, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64,
+ 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x3a,
+ 0x20, 0x6e, 0x6f, 0x74, 0x2d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x0d, 0x0a, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x3d,
+ 0x66, 0x61, 0x6c, 0x73, 0x65, 0x5d, 0x5b, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x5d, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x69,
+ 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x3d, 0x66, 0x61,
+ 0x6c, 0x73, 0x65, 0x5d, 0x5b, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x5d, 0x3a, 0x6e, 0x6f, 0x74,
+ 0x28, 0x3a, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x63, 0x6c, 0x69, 0x70, 0x3a, 0x20, 0x72, 0x65, 0x63, 0x74, 0x28, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x61, 0x62, 0x73, 0x6f,
+ 0x6c, 0x75, 0x74, 0x65, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x5b,
+ 0x74, 0x61, 0x62, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x2c, 0x20, 0x61, 0x2c, 0x20, 0x61, 0x72,
+ 0x65, 0x61, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75,
+ 0x74, 0x2c, 0x20, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74,
+ 0x2c, 0x20, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x74, 0x65, 0x78, 0x74, 0x61,
+ 0x72, 0x65, 0x61, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x6d, 0x73, 0x2d, 0x74,
+ 0x6f, 0x75, 0x63, 0x68, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x6d, 0x61, 0x6e,
+ 0x69, 0x70, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x5b, 0x64, 0x69, 0x72, 0x3d, 0x72, 0x74, 0x6c, 0x5d, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x72, 0x74, 0x6c, 0x0d,
+ 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x40, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x20, 0x28, 0x70, 0x72,
+ 0x65, 0x66, 0x65, 0x72, 0x73, 0x2d, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x64, 0x2d, 0x6d, 0x6f,
+ 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x29, 0x20, 0x7b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x3a, 0x6e, 0x6f, 0x74, 0x28, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x62,
+ 0x75, 0x73, 0x79, 0x3d, 0x74, 0x72, 0x75, 0x65, 0x5d, 0x29, 0x2c, 0x20, 0x3a, 0x6e, 0x6f, 0x74,
+ 0x28, 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x62, 0x75, 0x73, 0x79, 0x3d, 0x74, 0x72, 0x75, 0x65,
+ 0x5d, 0x29, 0x3a, 0x3a, 0x61, 0x66, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x3a, 0x6e, 0x6f, 0x74, 0x28,
+ 0x5b, 0x61, 0x72, 0x69, 0x61, 0x2d, 0x62, 0x75, 0x73, 0x79, 0x3d, 0x74, 0x72, 0x75, 0x65, 0x5d,
+ 0x29, 0x3a, 0x3a, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
+ 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x69, 0x6e, 0x69, 0x74,
+ 0x69, 0x61, 0x6c, 0x20, 0x21, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6e, 0x74, 0x3b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x2d, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x31, 0x6d, 0x73,
+ 0x20, 0x21, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6e, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d,
+ 0x64, 0x65, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x2d, 0x31, 0x6d, 0x73, 0x20, 0x21, 0x69, 0x6d, 0x70,
+ 0x6f, 0x72, 0x74, 0x61, 0x6e, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x69, 0x74, 0x65, 0x72, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x3a, 0x20, 0x31, 0x20, 0x21, 0x69,
+ 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6e, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x2d, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69,
+ 0x6f, 0x72, 0x3a, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x20, 0x21, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74,
+ 0x61, 0x6e, 0x74, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72,
+ 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x3a, 0x20,
+ 0x30, 0x73, 0x20, 0x21, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6e, 0x74, 0x3b, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69,
+ 0x6f, 0x6e, 0x2d, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x30, 0x73, 0x20,
+ 0x21, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6e, 0x74, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/remoteview_html.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/remoteview_html.h
new file mode 100644
index 0000000..ceaed8e
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/remoteview_html.h
@@ -0,0 +1,49 @@
+#pragma once
+
+const uint8_t remoteview_html[] = {
+ 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x3c,
+ 0x68, 0x74, 0x6d, 0x6c, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x3d, 0x65, 0x6e, 0x20, 0x64, 0x61, 0x74,
+ 0x61, 0x2d, 0x74, 0x68, 0x65, 0x6d, 0x65, 0x3d, 0x64, 0x61, 0x72, 0x6b, 0x3e, 0x3c, 0x68, 0x65,
+ 0x61, 0x64, 0x3e, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74,
+ 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x20, 0x2f, 0x3e, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x6e,
+ 0x61, 0x6d, 0x65, 0x3d, 0x76, 0x69, 0x65, 0x77, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x63, 0x6f, 0x6e,
+ 0x74, 0x65, 0x6e, 0x74, 0x3d, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x64, 0x65, 0x76, 0x69,
+ 0x63, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61,
+ 0x6c, 0x2d, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x3d, 0x31, 0x2c, 0x20, 0x73, 0x68, 0x72, 0x69, 0x6e,
+ 0x6b, 0x2d, 0x74, 0x6f, 0x2d, 0x66, 0x69, 0x74, 0x3d, 0x6e, 0x6f, 0x22, 0x20, 0x2f, 0x3e, 0x3c,
+ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x50, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x4f, 0x53,
+ 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x3c, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x72, 0x65,
+ 0x6c, 0x3d, 0x69, 0x63, 0x6f, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x69, 0x6d, 0x61, 0x67,
+ 0x65, 0x2f, 0x78, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x66, 0x61,
+ 0x76, 0x69, 0x63, 0x6f, 0x6e, 0x2e, 0x69, 0x63, 0x6f, 0x20, 0x2f, 0x3e, 0x3c, 0x6c, 0x69, 0x6e,
+ 0x6b, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x70, 0x69, 0x63, 0x6f, 0x2e, 0x63, 0x73, 0x73, 0x20,
+ 0x72, 0x65, 0x6c, 0x3d, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x73, 0x68, 0x65, 0x65, 0x74, 0x20, 0x2f,
+ 0x3e, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x6d,
+ 0x61, 0x69, 0x6e, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
+ 0x6e, 0x65, 0x72, 0x3e, 0x3c, 0x66, 0x6f, 0x72, 0x6d, 0x3e, 0x3c, 0x68, 0x32, 0x3e, 0x50, 0x72,
+ 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x4f, 0x53, 0x3a, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65,
+ 0x20, 0x56, 0x69, 0x65, 0x77, 0x3c, 0x2f, 0x68, 0x32, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x3e, 0x3c,
+ 0x73, 0x70, 0x61, 0x6e, 0x20, 0x69, 0x64, 0x3d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3e,
+ 0x50, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x57, 0x61, 0x69, 0x74, 0x2e, 0x2e, 0x2e, 0x3c, 0x2f,
+ 0x73, 0x70, 0x61, 0x6e, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x72, 0x20, 0x2f,
+ 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x67, 0x72, 0x69, 0x64,
+ 0x3e, 0x3c, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3a,
+ 0x76, 0x6f, 0x69, 0x64, 0x28, 0x30, 0x29, 0x20, 0x6f, 0x6e, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x3d,
+ 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x68, 0x6f, 0x74, 0x28, 0x29, 0x3e, 0x52, 0x65, 0x66,
+ 0x72, 0x65, 0x73, 0x68, 0x20, 0x56, 0x69, 0x65, 0x77, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64,
+ 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x72, 0x20, 0x2f, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c,
+ 0x61, 0x73, 0x73, 0x3d, 0x67, 0x72, 0x69, 0x64, 0x3e, 0x3c, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65,
+ 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x73, 0x65,
+ 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x69, 0x6e, 0x64,
+ 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x42, 0x61, 0x63, 0x6b, 0x3c, 0x2f, 0x61, 0x3e,
+ 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x72, 0x20, 0x2f, 0x3e, 0x3c, 0x64, 0x69, 0x76,
+ 0x3e, 0x3c, 0x62, 0x3e, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x32, 0x30,
+ 0x32, 0x34, 0x20, 0x2d, 0x20, 0x54, 0x65, 0x61, 0x6d, 0x20, 0x43, 0x65, 0x72, 0x62, 0x69, 0x6f,
+ 0x73, 0x20, 0x2b, 0x20, 0x54, 0x65, 0x61, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x75, 0x72, 0x67, 0x65,
+ 0x6e, 0x74, 0x3c, 0x2f, 0x62, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x2f, 0x66, 0x6f,
+ 0x72, 0x6d, 0x3e, 0x3c, 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x3e, 0x3c, 0x73, 0x63, 0x72, 0x69, 0x70,
+ 0x74, 0x20, 0x73, 0x72, 0x63, 0x3d, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x76, 0x69, 0x65, 0x77,
+ 0x2e, 0x6a, 0x73, 0x3e, 0x3c, 0x2f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3e, 0x3c, 0x2f, 0x62,
+ 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/remoteview_js.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/remoteview_js.h
new file mode 100644
index 0000000..2e1258e
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/remoteview_js.h
@@ -0,0 +1,29 @@
+#pragma once
+
+const uint8_t remoteview_js[] = {
+ 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73,
+ 0x63, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x68, 0x6f, 0x74, 0x28, 0x29, 0x7b, 0x61, 0x77, 0x61, 0x69,
+ 0x74, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x28, 0x22, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x63,
+ 0x72, 0x65, 0x65, 0x6e, 0x73, 0x68, 0x6f, 0x74, 0x22, 0x29, 0x2e, 0x63, 0x61, 0x74, 0x63, 0x68,
+ 0x28, 0x28, 0x29, 0x3d, 0x3e, 0x7b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x69, 0x6e,
+ 0x6e, 0x65, 0x72, 0x48, 0x54, 0x4d, 0x4c, 0x3d, 0x22, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x22, 0x7d, 0x29, 0x2e, 0x74,
+ 0x68, 0x65, 0x6e, 0x28, 0x6e, 0x3d, 0x3e, 0x6e, 0x2e, 0x62, 0x6c, 0x6f, 0x62, 0x28, 0x29, 0x29,
+ 0x2e, 0x74, 0x68, 0x65, 0x6e, 0x28, 0x6e, 0x3d, 0x3e, 0x7b, 0x76, 0x61, 0x72, 0x20, 0x72, 0x3d,
+ 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x55, 0x52, 0x4c, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74,
+ 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x55, 0x52, 0x4c, 0x28, 0x6e, 0x29, 0x2c, 0x74, 0x3d,
+ 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45,
+ 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x69, 0x6d, 0x67, 0x22, 0x29, 0x3b, 0x74, 0x2e,
+ 0x73, 0x72, 0x63, 0x3d, 0x72, 0x3b, 0x74, 0x2e, 0x61, 0x6c, 0x74, 0x3d, 0x22, 0x53, 0x63, 0x72,
+ 0x65, 0x65, 0x6e, 0x73, 0x68, 0x6f, 0x74, 0x22, 0x3b, 0x74, 0x2e, 0x73, 0x74, 0x79, 0x6c, 0x65,
+ 0x3d, 0x22, 0x6d, 0x61, 0x78, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30,
+ 0x25, 0x3b, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x22,
+ 0x3b, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x69, 0x3d, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e,
+ 0x74, 0x2e, 0x67, 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x64,
+ 0x28, 0x22, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x29, 0x3b, 0x69, 0x2e, 0x69, 0x6e,
+ 0x6e, 0x65, 0x72, 0x48, 0x54, 0x4d, 0x4c, 0x3d, 0x22, 0x22, 0x3b, 0x69, 0x2e, 0x61, 0x70, 0x70,
+ 0x65, 0x6e, 0x64, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x28, 0x74, 0x29, 0x7d, 0x29, 0x7d, 0x77, 0x69,
+ 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x6f, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x3d, 0x66, 0x75, 0x6e, 0x63,
+ 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x7b, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x68, 0x6f,
+ 0x74, 0x28, 0x29, 0x7d, 0x3b
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/remove_html.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/remove_html.h
new file mode 100644
index 0000000..736f155
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/remove_html.h
@@ -0,0 +1,42 @@
+#pragma once
+
+const uint8_t remove_html[] = {
+ 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x3c,
+ 0x68, 0x74, 0x6d, 0x6c, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x3d, 0x65, 0x6e, 0x20, 0x64, 0x61, 0x74,
+ 0x61, 0x2d, 0x74, 0x68, 0x65, 0x6d, 0x65, 0x3d, 0x64, 0x61, 0x72, 0x6b, 0x3e, 0x3c, 0x68, 0x65,
+ 0x61, 0x64, 0x3e, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74,
+ 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x20, 0x2f, 0x3e, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x6e,
+ 0x61, 0x6d, 0x65, 0x3d, 0x76, 0x69, 0x65, 0x77, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x63, 0x6f, 0x6e,
+ 0x74, 0x65, 0x6e, 0x74, 0x3d, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x64, 0x65, 0x76, 0x69,
+ 0x63, 0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61,
+ 0x6c, 0x2d, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x3d, 0x31, 0x2c, 0x20, 0x73, 0x68, 0x72, 0x69, 0x6e,
+ 0x6b, 0x2d, 0x74, 0x6f, 0x2d, 0x66, 0x69, 0x74, 0x3d, 0x6e, 0x6f, 0x22, 0x20, 0x2f, 0x3e, 0x3c,
+ 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x50, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x4f, 0x53,
+ 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x3c, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x72, 0x65,
+ 0x6c, 0x3d, 0x69, 0x63, 0x6f, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x69, 0x6d, 0x61, 0x67,
+ 0x65, 0x2f, 0x78, 0x2d, 0x69, 0x63, 0x6f, 0x6e, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x66, 0x61,
+ 0x76, 0x69, 0x63, 0x6f, 0x6e, 0x2e, 0x69, 0x63, 0x6f, 0x20, 0x2f, 0x3e, 0x3c, 0x6c, 0x69, 0x6e,
+ 0x6b, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x70, 0x69, 0x63, 0x6f, 0x2e, 0x63, 0x73, 0x73, 0x20,
+ 0x72, 0x65, 0x6c, 0x3d, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x73, 0x68, 0x65, 0x65, 0x74, 0x20, 0x2f,
+ 0x3e, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x6d,
+ 0x61, 0x69, 0x6e, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
+ 0x6e, 0x65, 0x72, 0x3e, 0x3c, 0x66, 0x6f, 0x72, 0x6d, 0x3e, 0x3c, 0x68, 0x32, 0x3e, 0x50, 0x72,
+ 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x4f, 0x53, 0x3a, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
+ 0x20, 0x42, 0x49, 0x4f, 0x53, 0x3c, 0x2f, 0x68, 0x32, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x3e, 0x3c,
+ 0x73, 0x70, 0x61, 0x6e, 0x20, 0x69, 0x64, 0x3d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3e,
+ 0x50, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x57, 0x61, 0x69, 0x74, 0x2e, 0x2e, 0x2e, 0x3c, 0x2f,
+ 0x73, 0x70, 0x61, 0x6e, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x72, 0x20, 0x2f,
+ 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x67, 0x72, 0x69, 0x64,
+ 0x3e, 0x3c, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x3d, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20,
+ 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x20,
+ 0x68, 0x72, 0x65, 0x66, 0x3d, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3e,
+ 0x42, 0x61, 0x63, 0x6b, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62,
+ 0x72, 0x20, 0x2f, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x62, 0x3e, 0x43, 0x6f, 0x70, 0x79,
+ 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x32, 0x30, 0x32, 0x34, 0x20, 0x2d, 0x20, 0x54, 0x65, 0x61,
+ 0x6d, 0x20, 0x43, 0x65, 0x72, 0x62, 0x69, 0x6f, 0x73, 0x20, 0x2b, 0x20, 0x54, 0x65, 0x61, 0x6d,
+ 0x20, 0x52, 0x65, 0x73, 0x75, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x3c, 0x2f, 0x62, 0x3e, 0x3c, 0x2f,
+ 0x64, 0x69, 0x76, 0x3e, 0x3c, 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x3e, 0x3c, 0x2f, 0x6d, 0x61, 0x69,
+ 0x6e, 0x3e, 0x3c, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x73, 0x72, 0x63, 0x3d, 0x72, 0x65,
+ 0x6d, 0x6f, 0x76, 0x65, 0x2e, 0x6a, 0x73, 0x3e, 0x3c, 0x2f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+ 0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/remove_js.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/remove_js.h
new file mode 100644
index 0000000..a285d6b
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Assets/Web/remove_js.h
@@ -0,0 +1,68 @@
+#pragma once
+
+const uint8_t remove_js[] = {
+ 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x6f, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x3d, 0x20,
+ 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x67, 0x65, 0x74, 0x42, 0x61, 0x6e, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x28, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x7d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x66,
+ 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x67, 0x65, 0x74, 0x42, 0x61, 0x6e, 0x6b, 0x49,
+ 0x6e, 0x66, 0x6f, 0x28, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x77,
+ 0x61, 0x69, 0x74, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x28, 0x22, 0x2f, 0x61, 0x70, 0x69, 0x2f,
+ 0x62, 0x61, 0x6e, 0x6b, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x6a, 0x73, 0x6f, 0x6e, 0x22, 0x29, 0x2e,
+ 0x74, 0x68, 0x65, 0x6e, 0x28, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f,
+ 0x6e, 0x73, 0x65, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6a, 0x73, 0x6f, 0x6e, 0x20, 0x3d,
+ 0x20, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e,
+ 0x6a, 0x73, 0x6f, 0x6e, 0x28, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x6f,
+ 0x64, 0x79, 0x20, 0x3d, 0x20, 0x22, 0x22, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x6c, 0x65, 0x74, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x30,
+ 0x3b, 0x20, 0x69, 0x20, 0x3c, 0x20, 0x6a, 0x73, 0x6f, 0x6e, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74,
+ 0x68, 0x3b, 0x20, 0x69, 0x2b, 0x2b, 0x29, 0x20, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x6a, 0x73, 0x6f, 0x6e, 0x5b,
+ 0x69, 0x5d, 0x2e, 0x73, 0x6c, 0x6f, 0x74, 0x73, 0x20, 0x3e, 0x20, 0x30, 0x29, 0x20, 0x7b, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x6f, 0x64, 0x79, 0x20, 0x2b, 0x3d, 0x20,
+ 0x22, 0x3c, 0x70, 0x3e, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x5c,
+ 0x22, 0x67, 0x72, 0x69, 0x64, 0x5c, 0x22, 0x3e, 0x3c, 0x61, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x3d,
+ 0x5c, 0x22, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5c, 0x22, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d,
+ 0x5c, 0x22, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3a, 0x76, 0x6f, 0x69,
+ 0x64, 0x28, 0x30, 0x29, 0x5c, 0x22, 0x20, 0x6f, 0x6e, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x3d, 0x5c,
+ 0x22, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x42, 0x61, 0x6e, 0x6b, 0x28, 0x22, 0x20, 0x2b, 0x20,
+ 0x6a, 0x73, 0x6f, 0x6e, 0x5b, 0x69, 0x5d, 0x2e, 0x69, 0x64, 0x20, 0x2b, 0x20, 0x22, 0x29, 0x5c,
+ 0x22, 0x3e, 0x22, 0x20, 0x2b, 0x20, 0x6a, 0x73, 0x6f, 0x6e, 0x5b, 0x69, 0x5d, 0x2e, 0x6e, 0x61,
+ 0x6d, 0x65, 0x20, 0x2b, 0x20, 0x22, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e,
+ 0x3c, 0x2f, 0x70, 0x3e, 0x22, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x63, 0x6f,
+ 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74,
+ 0x2e, 0x67, 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28,
+ 0x22, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x69, 0x6e, 0x6e,
+ 0x65, 0x72, 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
+ 0x42, 0x6f, 0x64, 0x79, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x22, 0x20, 0x3f, 0x20, 0x22, 0x4e, 0x6f,
+ 0x20, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x22, 0x20, 0x3a,
+ 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x6f, 0x64, 0x79, 0x3b, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x2e, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x65, 0x72,
+ 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20,
+ 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x45, 0x6c,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x63, 0x6f, 0x6e, 0x74, 0x65,
+ 0x6e, 0x74, 0x22, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63,
+ 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x48, 0x54, 0x4d, 0x4c,
+ 0x20, 0x3d, 0x20, 0x22, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f,
+ 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x22, 0x0d, 0x0a, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x66,
+ 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x42, 0x61,
+ 0x6e, 0x6b, 0x28, 0x69, 0x64, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61,
+ 0x77, 0x61, 0x69, 0x74, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x28, 0x22, 0x2f, 0x61, 0x70, 0x69,
+ 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x62, 0x61, 0x6e, 0x6b, 0x3f, 0x22, 0x20, 0x2b, 0x20,
+ 0x69, 0x64, 0x29, 0x2e, 0x74, 0x68, 0x65, 0x6e, 0x28, 0x28, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x7b,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x67, 0x65, 0x74, 0x42, 0x61, 0x6e,
+ 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x28, 0x29, 0x3b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29,
+ 0x2e, 0x63, 0x61, 0x74, 0x63, 0x68, 0x28, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x3e, 0x20,
+ 0x7b, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65,
+ 0x6e, 0x74, 0x2e, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x3d, 0x20, 0x22,
+ 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
+ 0x74, 0x2e, 0x22, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x3b, 0x0d, 0x0a, 0x7d
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayDriver.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayDriver.cpp
new file mode 100644
index 0000000..f48a218
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayDriver.cpp
@@ -0,0 +1,31 @@
+#include "displayDriver.h"
+
+void displayDriver::setAddress(uint8_t address)
+{
+ mAddress = address;
+}
+
+uint8_t displayDriver::getAddressValue()
+{
+ return mAddress;
+}
+
+void displayDriver::setBankValue(uint8_t bank)
+{
+ mBank = bank;
+}
+
+uint8_t displayDriver::getBankValue()
+{
+ return mBank;
+}
+
+void displayDriver::setSpiValue(uint8_t spi)
+{
+ mSpi = spi;
+}
+
+uint8_t displayDriver::getSpiValue()
+{
+ return mSpi;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayDriver.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayDriver.h
new file mode 100644
index 0000000..ba0bcaa
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayDriver.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#include "..\xboxinternals.h"
+#include "..\globalDefines.h"
+#include "..\utils.h"
+#include "..\settingsManager.h"
+
+class displayDriver
+{
+public:
+ virtual bool isSpi2Par() = 0;
+ virtual char* getModel() = 0;
+ virtual void init() = 0;
+ virtual void printMessage(const char* message) = 0;
+ virtual void setCursorPosition(uint8_t row, uint8_t col) = 0;
+ virtual void getSupport(bool& lcdInfo, bool& backlight, bool& contrast) = 0;
+ virtual void setBacklight(uint8_t backlight) = 0;
+ virtual void setContrast(uint8_t contrast) = 0;
+ virtual uint8_t getI2cAddressCount() = 0;
+ virtual uint8_t getI2cAddress(uint8_t index) = 0;
+
+ void setAddress(uint8_t address);
+ uint8_t getAddressValue();
+ void setBankValue(uint8_t bank);
+ uint8_t getBankValue();
+ void setSpiValue(uint8_t spi);
+ uint8_t getSpiValue();
+private:
+ uint8_t mAddress;
+ uint8_t mBank;
+ uint8_t mSpi;
+};
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayFactory.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayFactory.cpp
new file mode 100644
index 0000000..8bb5c51
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayFactory.cpp
@@ -0,0 +1,50 @@
+#include "displayFactory.h"
+
+displayDriver* displayFactory::getDisplay(displayVariant variant)
+{
+ if (variant == displayVariantLCDXXXXLPC)
+ {
+ return displayLCDXXXXLPC::getInstance();
+ }
+ else if (variant == displayVariantLCDXXXXModxo)
+ {
+ return displayLCDXXXXModxo::getInstance();
+ }
+ else if (variant == displayVariantHD44780LPC)
+ {
+ return displayHD44780LPC::getInstance();
+ }
+ else if (variant == displayVariantHD44780Modxo)
+ {
+ return displayHD44780Modxo::getInstance();
+ }
+ else if (variant == displayVariantSPI2PARModxo)
+ {
+ return displaySPI2PARModxo::getInstance();
+ }
+ else if (variant == displayVariantHD44780Aladdin)
+ {
+ return displayHD44780Aladdin::getInstance();
+ }
+ else if (variant == displayVariantSPI2PARAladdin)
+ {
+ return displaySPI2PARAladdin::getInstance();
+ }
+ else if (variant == displayVariantSPI2PARSmartxx)
+ {
+ return displaySPI2PARSmartxx::getInstance();
+ }
+ else if (variant == displayVariantHD44780Xecuter)
+ {
+ return displayHD44780Xecuter::getInstance();
+ }
+ else if (variant == displayVariantSPI2PARXenium)
+ {
+ return displaySPI2PARXenium::getInstance();
+ }
+ else if (variant == displayVariantSPI2PARXtremium)
+ {
+ return displaySPI2PARXtremium::getInstance();
+ }
+ return NULL;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayFactory.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayFactory.h
new file mode 100644
index 0000000..207ed05
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayFactory.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include "displayDriver.h"
+#include "displayLCDXXXXLPC.h"
+#include "displayLCDXXXXModxo.h"
+#include "displayHD44780LPC.h"
+#include "displayHD44780Modxo.h"
+#include "displaySPI2PARModxo.h"
+#include "displayHD44780Aladdin.h"
+#include "displaySPI2PARAladdin.h"
+#include "displaySPI2PARSmartxx.h"
+#include "displayHD44780Xecuter.h"
+#include "displaySPI2PARXenium.h"
+#include "displaySPI2PARXtremium.h"
+
+enum displayVariant
+{
+ displayVariantLCDXXXXLPC,
+ displayVariantLCDXXXXModxo,
+ displayVariantHD44780LPC,
+ displayVariantHD44780Modxo,
+ displayVariantSPI2PARModxo,
+ displayVariantHD44780Aladdin,
+ displayVariantSPI2PARAladdin,
+ displayVariantSPI2PARSmartxx,
+ displayVariantHD44780Xecuter,
+ displayVariantSPI2PARXenium,
+ displayVariantSPI2PARXtremium,
+};
+
+class displayFactory
+{
+public:
+ static displayDriver* getDisplay(displayVariant variant);
+};
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780Aladdin.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780Aladdin.cpp
new file mode 100644
index 0000000..2fa6cd4
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780Aladdin.cpp
@@ -0,0 +1,114 @@
+#include "displayHD44780Aladdin.h"
+
+static displayDriver* mInstance = NULL;
+
+displayDriver* displayHD44780Aladdin::getInstance()
+{
+ if (mInstance == NULL)
+ {
+ mInstance = new displayHD44780Aladdin();
+ }
+ return mInstance;
+}
+
+bool displayHD44780Aladdin::isSpi2Par()
+{
+ return false;
+}
+
+char* displayHD44780Aladdin::getModel()
+{
+ return strdup("HD44780");
+}
+
+void displayHD44780Aladdin::init()
+{
+ utils::ioOutputByte(ALADDIN_REGISTER_IO, ALADDIN_DISP_EN5V);
+ writeValue(0x33, 0);
+ Sleep(ALADDIN_LCD_DELAY);
+ writeValue(0x32, 0);
+ Sleep(ALADDIN_LCD_DELAY);
+ writeValue(ALADDIN_DISP_FUNCTION_SET | ALADDIN_DISP_N_FLAG | ALADDIN_DISP_RE_FLAG, ALADDIN_DISP_CMD);
+ Sleep(ALADDIN_LCD_DELAY);
+ writeValue(ALADDIN_DISP_SEGRAM_SET, ALADDIN_DISP_CMD);
+ Sleep(ALADDIN_LCD_DELAY);
+ writeValue(ALADDIN_DISP_EXT_CONTROL | ALADDIN_DISP_NW_FLAG, ALADDIN_DISP_CMD);
+ Sleep(ALADDIN_LCD_DELAY);
+ writeValue(ALADDIN_DISP_FUNCTION_SET | ALADDIN_DISP_N_FLAG, ALADDIN_DISP_CMD);
+ Sleep(ALADDIN_LCD_DELAY);
+ writeValue(ALADDIN_DISP_CONTROL | ALADDIN_DISP_D_FLAG, ALADDIN_DISP_CMD);
+ Sleep(ALADDIN_LCD_DELAY);
+ writeValue(ALADDIN_DISP_CLEAR, ALADDIN_DISP_CMD);
+ Sleep(ALADDIN_LCD_DELAY);
+ writeValue(ALADDIN_DISP_ENTRY_MODE_SET | ALADDIN_DISP_ID_FLAG, ALADDIN_DISP_CMD);
+ Sleep(ALADDIN_LCD_DELAY);
+ writeValue(ALADDIN_DISP_HOME, ALADDIN_DISP_CMD);
+ Sleep(ALADDIN_LCD_DELAY);
+ utils::ioOutputByte(ALADDIN_REGISTER_LCD_BL, (int)(settingsManager::getLcdBacklight(true) * 1.27f));
+ utils::ioOutputByte(ALADDIN_REGISTER_LCD_CT, (int)(settingsManager::getLcdContrast(true) * 0.64f));
+ Sleep(ALADDIN_LCD_DELAY);
+}
+
+void displayHD44780Aladdin::printMessage(const char* message)
+{
+ for (int i = 0; i < (int)strlen(message); ++i)
+ {
+ writeValue(message[i], ALADDIN_DISP_DAT);
+ }
+}
+
+void displayHD44780Aladdin::setCursorPosition(uint8_t row, uint8_t col)
+{
+ int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
+ uint8_t cursor = ALADDIN_DISP_DDRAM_SET | (col + row_offsets[row]);
+ writeValue(cursor, ALADDIN_DISP_CMD);
+ Sleep(ALADDIN_LCD_DELAY);
+}
+
+void displayHD44780Aladdin::getSupport(bool& lcdInfo, bool& backlight, bool& contrast)
+{
+ lcdInfo = false;
+ backlight = true;
+ contrast = true;
+}
+
+void displayHD44780Aladdin::setBacklight(uint8_t backlight)
+{
+ utils::ioOutputByte(ALADDIN_REGISTER_LCD_BL, (int)(backlight * 1.27f));
+ Sleep(ALADDIN_LCD_DELAY);
+}
+
+void displayHD44780Aladdin::setContrast(uint8_t contrast)
+{
+ utils::ioOutputByte(ALADDIN_REGISTER_LCD_CT, (int)(contrast * 0.64f));
+ Sleep(ALADDIN_LCD_DELAY);
+}
+
+uint8_t displayHD44780Aladdin::getI2cAddressCount()
+{
+ return 0;
+}
+
+uint8_t displayHD44780Aladdin::getI2cAddress(uint8_t index)
+{
+ return 0;
+}
+
+// Private
+
+void displayHD44780Aladdin::writeValue(uint8_t value, uint8_t command)
+{
+ uint8_t oDataHigh = (value >> 2) & 0x28;
+ oDataHigh |= (value >> 0) & 0x50;
+ utils::ioOutputByte(ALADDIN_REGISTER_DISP_O, command | oDataHigh);
+ utils::ioOutputByte(ALADDIN_REGISTER_DISP_O, command | ALADDIN_DISP_CON_E | oDataHigh);
+ utils::ioOutputByte(ALADDIN_REGISTER_DISP_O, command | oDataHigh);
+ Sleep(ALADDIN_LCD_DELAY);
+
+ uint8_t oDataLow = (value << 2) & 0x28;
+ oDataLow |= (value << 4) & 0x50;
+ utils::ioOutputByte(ALADDIN_REGISTER_DISP_O, command | oDataLow);
+ utils::ioOutputByte(ALADDIN_REGISTER_DISP_O, command | ALADDIN_DISP_CON_E | oDataLow);
+ utils::ioOutputByte(ALADDIN_REGISTER_DISP_O, command | oDataLow);
+ Sleep(ALADDIN_LCD_DELAY);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780Aladdin.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780Aladdin.h
new file mode 100644
index 0000000..17081cd
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780Aladdin.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "displayDriver.h"
+
+class displayHD44780Aladdin : displayDriver
+{
+public:
+ static displayDriver* getInstance();
+ bool isSpi2Par();
+ char* getModel();
+ void init();
+ void printMessage(const char* message);
+ void setCursorPosition(uint8_t row, uint8_t col);
+ void getSupport(bool& lcdInfo, bool& backlight, bool& contrast);
+ void setBacklight(uint8_t backlight);
+ void setContrast(uint8_t contrast);
+ uint8_t getI2cAddressCount();
+ uint8_t getI2cAddress(uint8_t index);
+private:
+ void writeValue(uint8_t value, uint8_t command);
+};
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780LPC.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780LPC.cpp
new file mode 100644
index 0000000..e438f6f
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780LPC.cpp
@@ -0,0 +1,112 @@
+#include "displayHD44780LPC.h"
+
+static displayDriver* mInstance = NULL;
+
+displayDriver* displayHD44780LPC::getInstance()
+{
+ if (mInstance == NULL)
+ {
+ mInstance = new displayHD44780LPC();
+ }
+ return mInstance;
+}
+
+bool displayHD44780LPC::isSpi2Par()
+{
+ return false;
+}
+
+char* displayHD44780LPC::getModel()
+{
+ return strdup("HD44780");
+}
+
+void displayHD44780LPC::init()
+{
+ uint8_t address = getI2cAddress(getAddressValue());
+
+ HalWriteSMBusByte(address << 1, 0x80, 0x2a);
+ HalWriteSMBusByte(address << 1, 0x80, 0x71);
+ HalWriteSMBusByte(address << 1, 0x40, 0x00);
+ HalWriteSMBusByte(address << 1, 0x80, 0x28);
+ HalWriteSMBusByte(address << 1, 0x80, 0x08);
+ HalWriteSMBusByte(address << 1, 0x80, 0x2a);
+ HalWriteSMBusByte(address << 1, 0x80, 0x79);
+ HalWriteSMBusByte(address << 1, 0x80, 0xd5);
+ HalWriteSMBusByte(address << 1, 0x80, 0x70);
+ HalWriteSMBusByte(address << 1, 0x80, 0x78);
+ HalWriteSMBusByte(address << 1, 0x80, 0x08 | 0x01); //0x01 is 3-4 rows
+ HalWriteSMBusByte(address << 1, 0x80, 0x06);
+ HalWriteSMBusByte(address << 1, 0x80, 0x72);
+ HalWriteSMBusByte(address << 1, 0x40, 0x00);
+ HalWriteSMBusByte(address << 1, 0x80, 0x2a);
+ HalWriteSMBusByte(address << 1, 0x80, 0x79);
+ HalWriteSMBusByte(address << 1, 0x80, 0xda);
+ HalWriteSMBusByte(address << 1, 0x80, 0x10);
+ HalWriteSMBusByte(address << 1, 0x80, 0xdc);
+ HalWriteSMBusByte(address << 1, 0x80, 0x00);
+ HalWriteSMBusByte(address << 1, 0x80, 0x81);
+ HalWriteSMBusByte(address << 1, 0x80, (uint8_t)(settingsManager::getLcdContrast(true) * 2.55f));
+ HalWriteSMBusByte(address << 1, 0x80, 0xd9);
+ HalWriteSMBusByte(address << 1, 0x80, 0xf1);
+ HalWriteSMBusByte(address << 1, 0x80, 0xdb);
+ HalWriteSMBusByte(address << 1, 0x80, 0x40);
+ HalWriteSMBusByte(address << 1, 0x80, 0x78);
+ HalWriteSMBusByte(address << 1, 0x80, 0x28);
+ HalWriteSMBusByte(address << 1, 0x80, 0x01);
+ HalWriteSMBusByte(address << 1, 0x80, 0x80);
+ HalWriteSMBusByte(address << 1, 0x80, 0x08 | 0x04);
+}
+
+void displayHD44780LPC::printMessage(const char* message)
+{
+ uint8_t address = getI2cAddress(getAddressValue());
+
+ for (int i = 0; i < (int)strlen(message); ++i)
+ {
+ HalWriteSMBusByte(address << 1, 0x40, message[i]);
+ }
+}
+
+void displayHD44780LPC::setCursorPosition(uint8_t row, uint8_t col)
+{
+ uint8_t address = getI2cAddress(getAddressValue());
+
+ int row_offsets[] = { 0x00, 0x20, 0x40, 0x60 };
+ uint8_t cursor = 0x80 | (col + row_offsets[row]);
+ HalWriteSMBusByte(address << 1, 0x80, cursor);
+}
+
+void displayHD44780LPC::getSupport(bool& lcdInfo, bool& backlight, bool& contrast)
+{
+ lcdInfo = false;
+ backlight = false;
+ contrast = true;
+}
+
+void displayHD44780LPC::setBacklight(uint8_t backlight)
+{
+}
+
+void displayHD44780LPC::setContrast(uint8_t contrast)
+{
+ uint8_t address = getI2cAddress(getAddressValue());
+
+ HalWriteSMBusByte(address << 1, 0x80, 0x2A);
+ HalWriteSMBusByte(address << 1, 0x80, 0x79);
+ HalWriteSMBusByte(address << 1, 0x80, 0x81);
+ HalWriteSMBusByte(address << 1, 0x80, (uint8_t)(contrast * 2.55f));
+ HalWriteSMBusByte(address << 1, 0x80, 0x78);
+ HalWriteSMBusByte(address << 1, 0x80, 0x28);
+}
+
+uint8_t displayHD44780LPC::getI2cAddressCount()
+{
+ return 16;
+}
+
+uint8_t displayHD44780LPC::getI2cAddress(uint8_t index)
+{
+ int lcdAddressArray[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F };
+ return lcdAddressArray[index];
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780LPC.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780LPC.h
new file mode 100644
index 0000000..5387f78
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780LPC.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include "displayDriver.h"
+
+class displayHD44780LPC : displayDriver
+{
+public:
+ static displayDriver* getInstance();
+ bool isSpi2Par();
+ char* getModel();
+ void init();
+ void printMessage(const char* message);
+ void setCursorPosition(uint8_t row, uint8_t col);
+ void getSupport(bool& lcdInfo, bool& backlight, bool& contrast);
+ void setBacklight(uint8_t backlight);
+ void setContrast(uint8_t contrast);
+ uint8_t getI2cAddressCount();
+ uint8_t getI2cAddress(uint8_t index);
+};
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780Modxo.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780Modxo.cpp
new file mode 100644
index 0000000..3ac4b60
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780Modxo.cpp
@@ -0,0 +1,139 @@
+#include "displayHD44780Modxo.h"
+
+static displayDriver* mInstance = NULL;
+
+displayDriver* displayHD44780Modxo::getInstance()
+{
+ if (mInstance == NULL)
+ {
+ mInstance = new displayHD44780Modxo();
+ }
+ return mInstance;
+}
+
+bool displayHD44780Modxo::isSpi2Par()
+{
+ return false;
+}
+
+char* displayHD44780Modxo::getModel()
+{
+ return strdup("HD44780");
+}
+
+void displayHD44780Modxo::init()
+{
+ uint8_t address = getI2cAddress(getAddressValue());
+
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_SET_CLK);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, 100);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_I2C);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, address);
+
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_SET_I2C_PREFIX);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_COMMAND_MODE);
+
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x2a);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x71);
+
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_SET_I2C_PREFIX);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_DATA_MODE);
+
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x00);
+
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_SET_I2C_PREFIX);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_COMMAND_MODE);
+
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x28);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x08);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x2a);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x79);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0xd5);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x70);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x78);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x08 | 0x01); //0x01 is 3-4 rows
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x06);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x72);
+
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_SET_I2C_PREFIX);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_DATA_MODE);
+
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x00);
+
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_SET_I2C_PREFIX);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_COMMAND_MODE);
+
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x2a);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x79);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0xda);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x10);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0xdc);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x00);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x81);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, (uint8_t)(settingsManager::getLcdContrast(true) * 2.55f));
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0xd9);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0xf1);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0xdb);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x40);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x78);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x28);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x01);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x80);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x08 | 0x04);
+}
+
+void displayHD44780Modxo::printMessage(const char* message)
+{
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_SET_I2C_PREFIX);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_DATA_MODE);
+
+ for (int i = 0; i < (int)strlen(message); ++i)
+ {
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, message[i]);
+ }
+}
+
+void displayHD44780Modxo::setCursorPosition(uint8_t row, uint8_t col)
+{
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_SET_I2C_PREFIX);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_COMMAND_MODE);
+
+ int row_offsets[] = { 0x00, 0x20, 0x40, 0x60 };
+ uint8_t cursor = 0x80 | (col + row_offsets[row]);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, cursor);
+}
+
+void displayHD44780Modxo::getSupport(bool& lcdInfo, bool& backlight, bool& contrast)
+{
+ lcdInfo = false;
+ backlight = false;
+ contrast = true;
+}
+
+void displayHD44780Modxo::setBacklight(uint8_t contrast)
+{
+}
+
+void displayHD44780Modxo::setContrast(uint8_t contrast)
+{
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_SET_I2C_PREFIX);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_COMMAND_MODE);
+
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x2A);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x79);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x81);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, (uint8_t)(contrast * 2.55f));
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x78);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, 0x28);
+}
+
+uint8_t displayHD44780Modxo::getI2cAddressCount()
+{
+ return 16;
+}
+
+uint8_t displayHD44780Modxo::getI2cAddress(uint8_t index)
+{
+ int lcdAddressArray[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F };
+ return lcdAddressArray[index];
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780Modxo.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780Modxo.h
new file mode 100644
index 0000000..125c235
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780Modxo.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include "displayDriver.h"
+
+class displayHD44780Modxo : displayDriver
+{
+public:
+ static displayDriver* getInstance();
+ bool isSpi2Par();
+ char* getModel();
+ void init();
+ void printMessage(const char* message);
+ void setCursorPosition(uint8_t row, uint8_t col);
+ void getSupport(bool& lcdInfo, bool& backlight, bool& contrast);
+ void setBacklight(uint8_t backlight);
+ void setContrast(uint8_t contrast);
+ uint8_t getI2cAddressCount();
+ uint8_t getI2cAddress(uint8_t index);
+};
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780Xecuter.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780Xecuter.cpp
new file mode 100644
index 0000000..622bda5
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780Xecuter.cpp
@@ -0,0 +1,116 @@
+#include "displayHD44780Xecuter.h"
+
+static displayDriver* mInstance = NULL;
+
+displayDriver* displayHD44780Xecuter::getInstance()
+{
+ if (mInstance == NULL)
+ {
+ mInstance = new displayHD44780Xecuter();
+ }
+ return mInstance;
+}
+
+bool displayHD44780Xecuter::isSpi2Par()
+{
+ return false;
+}
+
+char* displayHD44780Xecuter::getModel()
+{
+ return strdup("HD44780");
+}
+
+void displayHD44780Xecuter::init()
+{
+ utils::ioOutputByte(XECUTER_REGISTER_DISP_O_DAT, 0);
+ utils::ioOutputByte(XECUTER_REGISTER_DISP_O_CMD, 0);
+ utils::ioOutputByte(XECUTER_REGISTER_DISP_O_DIR_DAT, 0xFF);
+ utils::ioOutputByte(XECUTER_REGISTER_DISP_O_DIR_CMD, 0x07);
+
+ writeValue(XECUTER_DISP_FUNCTION_SET | XECUTER_DISP_DL_FLAG, XECUTER_DISP_INI);
+ Sleep(XECUTER_LCD_DELAY);
+ writeValue(XECUTER_DISP_FUNCTION_SET | XECUTER_DISP_DL_FLAG, XECUTER_DISP_INI);
+ Sleep(XECUTER_LCD_DELAY);
+ writeValue(XECUTER_DISP_FUNCTION_SET | XECUTER_DISP_DL_FLAG, XECUTER_DISP_INI);
+ Sleep(XECUTER_LCD_DELAY);
+ writeValue(XECUTER_DISP_FUNCTION_SET, XECUTER_DISP_INI);
+ Sleep(XECUTER_LCD_DELAY);
+ writeValue(XECUTER_DISP_FUNCTION_SET | XECUTER_DISP_N_FLAG, XECUTER_DISP_CMD);
+ Sleep(XECUTER_LCD_DELAY);
+ writeValue(XECUTER_DISP_CONTROL | XECUTER_DISP_D_FLAG, XECUTER_DISP_CMD);
+ Sleep(XECUTER_LCD_DELAY);
+ writeValue(XECUTER_DISP_CLEAR, XECUTER_DISP_CMD);
+ Sleep(XECUTER_LCD_DELAY);
+ writeValue(XECUTER_DISP_ENTRY_MODE_SET | XECUTER_DISP_ID_FLAG,XECUTER_DISP_CMD);
+ Sleep(XECUTER_LCD_DELAY);
+ utils::ioOutputByte(XECUTER_REGISTER_DISP_O_LIGHT, (int)(settingsManager::getLcdBacklight(true) * 1.27f));
+ Sleep(XECUTER_LCD_DELAY);
+}
+
+void displayHD44780Xecuter::printMessage(const char* message)
+{
+ for (int i = 0; i < (int)strlen(message); ++i)
+ {
+ writeValue(message[i], XECUTER_DISP_DAT);
+ }
+}
+
+void displayHD44780Xecuter::setCursorPosition(uint8_t row, uint8_t col)
+{
+ int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
+ uint8_t cursor = XECUTER_DISP_DDRAM_SET | (col + row_offsets[row]);
+ writeValue(cursor, XECUTER_DISP_CMD);
+ Sleep(XECUTER_LCD_DELAY);
+}
+
+void displayHD44780Xecuter::getSupport(bool& lcdInfo, bool& backlight, bool& contrast)
+{
+ lcdInfo = false;
+ backlight = true;
+ contrast = false;
+}
+
+void displayHD44780Xecuter::setBacklight(uint8_t backlight)
+{
+ utils::ioOutputByte(XECUTER_REGISTER_DISP_O_LIGHT, (int)(backlight * 1.27f));
+ Sleep(XECUTER_LCD_DELAY);
+}
+
+void displayHD44780Xecuter::setContrast(uint8_t contrast)
+{
+}
+
+uint8_t displayHD44780Xecuter::getI2cAddressCount()
+{
+ return 0;
+}
+
+uint8_t displayHD44780Xecuter::getI2cAddress(uint8_t index)
+{
+ return 0;
+}
+
+// Private
+
+void displayHD44780Xecuter::writeValue(uint8_t value, uint8_t command)
+{
+ uint8_t cmd = 0;
+ if (command & XECUTER_DISP_DAT)
+ {
+ cmd |= XECUTER_DISP_CON_RS;
+ }
+
+ utils::ioOutputByte(XECUTER_REGISTER_DISP_O_DAT, value & 0xF0);
+ utils::ioOutputByte(XECUTER_REGISTER_DISP_O_CMD, cmd);
+ utils::ioOutputByte(XECUTER_REGISTER_DISP_O_CMD, XECUTER_DISP_CON_E | cmd);
+ utils::ioOutputByte(XECUTER_REGISTER_DISP_O_CMD, cmd);
+
+ if ((command & XECUTER_DISP_INI) == 0)
+ {
+ utils::ioOutputByte(XECUTER_REGISTER_DISP_O_DAT, (value << 4) & 0xF0);
+ utils::ioOutputByte(XECUTER_REGISTER_DISP_O_CMD, cmd);
+ utils::ioOutputByte(XECUTER_REGISTER_DISP_O_CMD, XECUTER_DISP_CON_E | cmd);
+ utils::ioOutputByte(XECUTER_REGISTER_DISP_O_CMD, cmd);
+ }
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780Xecuter.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780Xecuter.h
new file mode 100644
index 0000000..9dc408e
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayHD44780Xecuter.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "displayDriver.h"
+
+class displayHD44780Xecuter : displayDriver
+{
+public:
+ static displayDriver* getInstance();
+ bool isSpi2Par();
+ char* getModel();
+ void init();
+ void printMessage(const char* message);
+ void setCursorPosition(uint8_t row, uint8_t col);
+ void getSupport(bool& lcdInfo, bool& backlight, bool& contrast);
+ void setBacklight(uint8_t backlight);
+ void setContrast(uint8_t contrast);
+ uint8_t getI2cAddressCount();
+ uint8_t getI2cAddress(uint8_t index);
+private:
+ void writeValue(uint8_t value, uint8_t command);
+};
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayLCDXXXXLPC.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayLCDXXXXLPC.cpp
new file mode 100644
index 0000000..7d4a115
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayLCDXXXXLPC.cpp
@@ -0,0 +1,130 @@
+#include "displayLCDXXXXLPC.h"
+
+static displayDriver* mInstance = NULL;
+
+displayDriver* displayLCDXXXXLPC::getInstance()
+{
+ if (mInstance == NULL)
+ {
+ mInstance = new displayLCDXXXXLPC();
+ }
+ return mInstance;
+}
+
+bool displayLCDXXXXLPC::isSpi2Par()
+{
+ return false;
+}
+
+char* displayLCDXXXXLPC::getModel()
+{
+ return strdup("LCDXXXX");
+}
+
+void displayLCDXXXXLPC::init()
+{
+ uint8_t address = getI2cAddress(getAddressValue());
+
+ write4bits(address, 0x03 << 4);
+ utils::uSleep(4500);
+ write4bits(address, 0x03 << 4);
+ utils::uSleep(4500);
+ write4bits(address, 0x03 << 4);
+ utils::uSleep(4500);
+ write4bits(address, 0x02 << 4);
+ command(address, 0x20 | 0x08);
+ command(address, 0x08 | 0x04);
+ command(address, 0x01);
+ utils::uSleep(2000);
+ command(address, 0x04 | 0x02);
+ command(address, 0x02);
+ utils::uSleep(2000);
+}
+
+void displayLCDXXXXLPC::printMessage(const char* message)
+{
+ uint8_t address = getI2cAddress(getAddressValue());
+
+ for (int i = 0; i < (int)strlen(message); ++i)
+ {
+ writeChar(address, message[i]);
+ }
+}
+
+void displayLCDXXXXLPC::setCursorPosition(uint8_t row, uint8_t col)
+{
+ uint8_t address = getI2cAddress(getAddressValue());
+
+ int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
+ uint8_t cursor = 0x80 | (col + row_offsets[row]);
+ command(address, cursor);
+}
+
+void displayLCDXXXXLPC::getSupport(bool& lcdInfo, bool& backlight, bool& contrast)
+{
+ lcdInfo = false;
+ backlight = false;
+ contrast = false;
+}
+
+void displayLCDXXXXLPC::setBacklight(uint8_t backlight)
+{
+}
+
+void displayLCDXXXXLPC::setContrast(uint8_t contrast)
+{
+}
+
+uint8_t displayLCDXXXXLPC::getI2cAddressCount()
+{
+ return 16;
+}
+
+uint8_t displayLCDXXXXLPC::getI2cAddress(uint8_t index)
+{
+ int lcdAddressArray[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F };
+ return lcdAddressArray[index];
+}
+
+//Private
+
+void displayLCDXXXXLPC::expanderWrite(uint8_t address, uint8_t value)
+{
+ uint8_t bl = 0x08;
+ HalWriteSMBusValue(address << 1, 0, 0xff, (value | bl));
+}
+
+void displayLCDXXXXLPC::pulseEnable(uint8_t address, uint8_t value)
+{
+ uint8_t En = 0x04;
+
+ expanderWrite(address, value | En);
+ utils::uSleep(1);
+
+ expanderWrite(address, value & ~En);
+ utils::uSleep(50);
+}
+
+void displayLCDXXXXLPC::write4bits(uint8_t address, uint8_t value)
+{
+ expanderWrite(address, value);
+ pulseEnable(address, value);
+}
+
+void displayLCDXXXXLPC::send(uint8_t address, uint8_t value, uint8_t mode)
+{
+ uint8_t highnib = value & 0xf0;
+ uint8_t lownib = (value << 4) & 0xf0;
+ write4bits(address, (highnib) | mode);
+ write4bits(address, (lownib) | mode);
+}
+
+void displayLCDXXXXLPC::command(uint8_t address, uint8_t value)
+{
+ send(address, value, 0);
+}
+
+void displayLCDXXXXLPC::writeChar(uint8_t address, uint8_t value)
+{
+ send(address, value, 1);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayLCDXXXXLPC.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayLCDXXXXLPC.h
new file mode 100644
index 0000000..01d3207
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayLCDXXXXLPC.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "displayDriver.h"
+
+class displayLCDXXXXLPC : displayDriver
+{
+public:
+ static displayDriver* getInstance();
+ bool isSpi2Par();
+ char* getModel();
+ void init();
+ void printMessage(const char* message);
+ void setCursorPosition(uint8_t row, uint8_t col);
+ void getSupport(bool& lcdInfo, bool& backlight, bool& contrast);
+ void setBacklight(uint8_t backlight);
+ void setContrast(uint8_t contrast);
+ uint8_t getI2cAddressCount();
+ uint8_t getI2cAddress(uint8_t index);
+private:
+ void expanderWrite(uint8_t address, uint8_t value);
+ void pulseEnable(uint8_t address, uint8_t value);
+ void write4bits(uint8_t address, uint8_t value);
+ void send(uint8_t address, uint8_t value, uint8_t mode);
+ void command(uint8_t address, uint8_t value);
+ void writeChar(uint8_t address, uint8_t value);
+};
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayLCDXXXXModxo.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayLCDXXXXModxo.cpp
new file mode 100644
index 0000000..3780c53
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayLCDXXXXModxo.cpp
@@ -0,0 +1,134 @@
+#include "displayLCDXXXXModxo.h"
+
+static displayDriver* mInstance = NULL;
+
+displayDriver* displayLCDXXXXModxo::getInstance()
+{
+ if (mInstance == NULL)
+ {
+ mInstance = new displayLCDXXXXModxo();
+ }
+ return mInstance;
+}
+
+bool displayLCDXXXXModxo::isSpi2Par()
+{
+ return false;
+}
+
+char* displayLCDXXXXModxo::getModel()
+{
+ return strdup("LCDXXXX");
+}
+
+void displayLCDXXXXModxo::init()
+{
+ uint8_t address = getI2cAddress(getAddressValue());
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_SET_CLK);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, 100);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_REMOVE_I2C_PREFIX);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_I2C);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, address);
+ utils::uSleep(2000);
+
+ write4bits(0x03 << 4);
+ utils::uSleep(4500);
+ write4bits(0x03 << 4);
+ utils::uSleep(4500);
+ write4bits(0x03 << 4);
+ utils::uSleep(4500);
+ write4bits(0x02 << 4);
+ command(0x20 | 0x08);
+ command(0x08 | 0x04);
+ command(0x01);
+ utils::uSleep(2000);
+ command(0x04 | 0x02);
+ command(0x02);
+ utils::uSleep(2000);
+}
+
+void displayLCDXXXXModxo::printMessage(const char* message)
+{
+ for (int i = 0; i < (int)strlen(message); ++i)
+ {
+ writeChar(message[i]);
+ }
+}
+
+void displayLCDXXXXModxo::setCursorPosition(uint8_t row, uint8_t col)
+{
+ int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
+ uint8_t cursor = 0x80 | (col + row_offsets[row]);
+ command(cursor);
+}
+
+void displayLCDXXXXModxo::getSupport(bool& lcdInfo, bool& backlight, bool& contrast)
+{
+ lcdInfo = false;
+ backlight = false;
+ contrast = false;
+}
+
+void displayLCDXXXXModxo::setBacklight(uint8_t backlight)
+{
+}
+
+void displayLCDXXXXModxo::setContrast(uint8_t contrast)
+{
+}
+
+uint8_t displayLCDXXXXModxo::getI2cAddressCount()
+{
+ return 16;
+}
+
+uint8_t displayLCDXXXXModxo::getI2cAddress(uint8_t index)
+{
+ int lcdAddressArray[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F };
+ return lcdAddressArray[index];
+}
+
+
+//Private
+
+void displayLCDXXXXModxo::expanderWrite(uint8_t value)
+{
+ uint8_t bl = 0x08;
+ uint8_t data = (uint8_t)(value | bl);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, data);
+}
+
+void displayLCDXXXXModxo::pulseEnable(uint8_t value)
+{
+ uint8_t En = 0x04;
+
+ expanderWrite(value | En);
+ utils::uSleep(1);
+
+ expanderWrite(value & ~En);
+ utils::uSleep(50);
+}
+
+void displayLCDXXXXModxo::write4bits(uint8_t value)
+{
+ expanderWrite(value);
+ pulseEnable(value);
+}
+
+void displayLCDXXXXModxo::send(uint8_t value, uint8_t mode)
+{
+ uint8_t highnib = value & 0xf0;
+ uint8_t lownib = (value << 4) & 0xf0;
+ write4bits((highnib) | mode);
+ write4bits((lownib) | mode);
+}
+
+void displayLCDXXXXModxo::command(uint8_t value)
+{
+ send(value, 0);
+}
+
+void displayLCDXXXXModxo::writeChar(uint8_t value)
+{
+ send(value, 1);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayLCDXXXXModxo.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayLCDXXXXModxo.h
new file mode 100644
index 0000000..eecf447
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displayLCDXXXXModxo.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "displayDriver.h"
+
+class displayLCDXXXXModxo : displayDriver
+{
+public:
+ static displayDriver* getInstance();
+ bool isSpi2Par();
+ char* getModel();
+ void init();
+ void printMessage(const char* message);
+ void setCursorPosition(uint8_t row, uint8_t col);
+ void getSupport(bool& lcdInfo, bool& backlight, bool& contrast);
+ void setBacklight(uint8_t backlight);
+ void setContrast(uint8_t contrast);
+ uint8_t getI2cAddressCount();
+ uint8_t getI2cAddress(uint8_t index);
+private:
+ void expanderWrite(uint8_t value);
+ void pulseEnable(uint8_t value);
+ void write4bits(uint8_t value);
+ void send(uint8_t val, uint8_t mode);
+ void command(uint8_t value);
+ void writeChar(uint8_t value);
+};
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARAladdin.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARAladdin.cpp
new file mode 100644
index 0000000..e5634e9
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARAladdin.cpp
@@ -0,0 +1,135 @@
+#include "displaySPI2PARAladdin.h"
+
+static displayDriver* mInstance = NULL;
+
+displayDriver* displaySPI2PARAladdin::getInstance()
+{
+ if (mInstance == NULL)
+ {
+ mInstance = new displaySPI2PARAladdin();
+ }
+ return mInstance;
+}
+
+bool displaySPI2PARAladdin::isSpi2Par()
+{
+ return true;
+}
+
+char* displaySPI2PARAladdin::getModel()
+{
+ return strdup("SPI2PAR");
+}
+
+void displaySPI2PARAladdin::init()
+{
+ utils::ioOutputByte(ALADDIN_REGISTER_IO, ALADDIN_DISP_EN5V);
+
+ writeValue(SPI2PAR_SHOWDISPLAY);
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_FORMFEED);
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_HIDECURSOR);
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_SCROLLOFF);
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_WRAPOFF);
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_SETBACKLIGHT);
+ writeValue(settingsManager::getLcdBacklight(true));
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_SETCONTRAST);
+ writeValue(settingsManager::getLcdContrast(true));
+ utils::uSleep(2000);
+}
+
+void displaySPI2PARAladdin::printMessage(const char* message)
+{
+ for (int i = 0; i < (int)strlen(message); ++i)
+ {
+ writeValue(message[i]);
+ utils::uSleep(2000);
+ }
+}
+
+void displaySPI2PARAladdin::setCursorPosition(uint8_t row, uint8_t col)
+{
+ writeValue(SPI2PAR_SETCURSORPOSITION);
+ writeValue(col);
+ writeValue(row);
+ utils::uSleep(2000);
+}
+
+void displaySPI2PARAladdin::getSupport(bool& lcdInfo, bool& backlight, bool& contrast)
+{
+ lcdInfo = false;
+ backlight = true;
+ contrast = true;
+}
+
+void displaySPI2PARAladdin::setBacklight(uint8_t backlight)
+{
+ writeValue(SPI2PAR_SETBACKLIGHT);
+ writeValue(backlight);
+ utils::uSleep(2000);
+}
+
+void displaySPI2PARAladdin::setContrast(uint8_t contrast)
+{
+ writeValue(SPI2PAR_SETCONTRAST);
+ writeValue(contrast);
+ utils::uSleep(2000);
+}
+
+uint8_t displaySPI2PARAladdin::getI2cAddressCount()
+{
+ return 0;
+}
+
+uint8_t displaySPI2PARAladdin::getI2cAddress(uint8_t index)
+{
+ return 0;
+}
+
+// Private
+
+void displaySPI2PARAladdin::writeValue(uint8_t value)
+{
+ uint8_t spi = getSpiValue();
+
+ spi |= ALADDIN_SPI_CLK_BIT;
+ spi &= ~ALADDIN_SPI_CS_BIT;
+ utils::ioOutputByte(ALADDIN_REGISTER_DISP_O, spi);
+ utils::uSleep(0x1);
+
+ uint8_t i = 8;
+ do
+ {
+ if ((value & 0x80) > 0)
+ {
+ spi |= ALADDIN_SPI_MOSI_BIT;
+ }
+ else
+ {
+ spi &= ~ALADDIN_SPI_MOSI_BIT;
+ }
+
+ spi &= ~ALADDIN_SPI_CLK_BIT;
+ utils::ioOutputByte(ALADDIN_REGISTER_DISP_O, spi);
+ utils::uSleep(0x1);
+
+ spi |= ALADDIN_SPI_CLK_BIT;
+ utils::ioOutputByte(ALADDIN_REGISTER_DISP_O, spi);
+ utils::uSleep(0x1);
+
+ value = value << 1;
+ i--;
+ }
+ while (i > 0);
+
+ spi |= ALADDIN_SPI_CS_BIT;
+ utils::ioOutputByte(ALADDIN_REGISTER_DISP_O, spi);
+ utils::uSleep(0x1);
+
+ setSpiValue(spi);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARAladdin.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARAladdin.h
new file mode 100644
index 0000000..e7655cc
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARAladdin.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "displayDriver.h"
+
+//D7 = CLK
+//D6 = MOSI
+//D5 = CS
+
+//WriteToIO(XBLAST_IO, (GenPurposeIOs.GPO3 << 7) | (GenPurposeIOs.GPO2 << 6) | (GenPurposeIOs.GPO1 << 5) | (GenPurposeIOs.GPO0 << 4) | GenPurposeIOs.EN_5V);
+
+class displaySPI2PARAladdin : displayDriver
+{
+public:
+ static displayDriver* getInstance();
+ bool isSpi2Par();
+ char* getModel();
+ void init();
+ void printMessage(const char* message);
+ void setCursorPosition(uint8_t row, uint8_t col);
+ void getSupport(bool& lcdInfo, bool& backlight, bool& contrast);
+ void setBacklight(uint8_t backlight);
+ void setContrast(uint8_t contrast);
+ uint8_t getI2cAddressCount();
+ uint8_t getI2cAddress(uint8_t index);
+private:
+ void writeValue(uint8_t value);
+};
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARModxo.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARModxo.cpp
new file mode 100644
index 0000000..560cccb
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARModxo.cpp
@@ -0,0 +1,97 @@
+#include "displaySPI2PARModxo.h"
+
+static displayDriver* mInstance = NULL;
+
+displayDriver* displaySPI2PARModxo::getInstance()
+{
+ if (mInstance == NULL)
+ {
+ mInstance = new displaySPI2PARModxo();
+ }
+ return mInstance;
+}
+
+bool displaySPI2PARModxo::isSpi2Par()
+{
+ return true;
+}
+
+char* displaySPI2PARModxo::getModel()
+{
+ return strdup("SPI2PAR");
+}
+
+void displaySPI2PARModxo::init()
+{
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_SET_CLK);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, 10);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_SET_SPI_MODE);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, 3);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, MODXO_LCD_SPI);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_COMMAND, 0);
+
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, SPI2PAR_SHOWDISPLAY);
+ utils::uSleep(2000);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, SPI2PAR_FORMFEED);
+ utils::uSleep(2000);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, SPI2PAR_HIDECURSOR);
+ utils::uSleep(2000);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, SPI2PAR_SCROLLOFF);
+ utils::uSleep(2000);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, SPI2PAR_WRAPOFF);
+ utils::uSleep(2000);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, SPI2PAR_SETBACKLIGHT);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, settingsManager::getLcdBacklight(true));
+ utils::uSleep(2000);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, SPI2PAR_SETCONTRAST);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, settingsManager::getLcdContrast(true));
+ utils::uSleep(2000);
+}
+
+void displaySPI2PARModxo::printMessage(const char* message)
+{
+ for (int i = 0; i < (int)strlen(message); ++i)
+ {
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, message[i]);
+ utils::uSleep(2000);
+ }
+}
+
+void displaySPI2PARModxo::setCursorPosition(uint8_t row, uint8_t col)
+{
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, SPI2PAR_SETCURSORPOSITION);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, col);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, row);
+ utils::uSleep(2000);
+}
+
+void displaySPI2PARModxo::getSupport(bool& lcdInfo, bool& backlight, bool& contrast)
+{
+ lcdInfo = false;
+ backlight = true;
+ contrast = true;
+}
+
+void displaySPI2PARModxo::setBacklight(uint8_t backlight)
+{
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, SPI2PAR_SETBACKLIGHT);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, backlight);
+ utils::uSleep(2000);
+}
+
+void displaySPI2PARModxo::setContrast(uint8_t contrast)
+{
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, SPI2PAR_SETCONTRAST);
+ utils::ioOutputByte(MODXO_REGISTER_LCD_DATA, contrast);
+ utils::uSleep(2000);
+}
+
+uint8_t displaySPI2PARModxo::getI2cAddressCount()
+{
+ return 0;
+}
+
+uint8_t displaySPI2PARModxo::getI2cAddress(uint8_t index)
+{
+ return 0;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARModxo.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARModxo.h
new file mode 100644
index 0000000..68416d7
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARModxo.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include "displayDriver.h"
+
+class displaySPI2PARModxo : displayDriver
+{
+public:
+ static displayDriver* getInstance();
+ bool isSpi2Par();
+ char* getModel();
+ void init();
+ void printMessage(const char* message);
+ void setCursorPosition(uint8_t row, uint8_t col);
+ void getSupport(bool& lcdInfo, bool& backlight, bool& contrast);
+ void setBacklight(uint8_t backlight);
+ void setContrast(uint8_t contrast);
+ uint8_t getI2cAddressCount();
+ uint8_t getI2cAddress(uint8_t index);
+};
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARSmartxx.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARSmartxx.cpp
new file mode 100644
index 0000000..c1e93d5
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARSmartxx.cpp
@@ -0,0 +1,136 @@
+#include "displaySPI2PARSmartxx.h"
+
+static displayDriver* mInstance = NULL;
+
+displayDriver* displaySPI2PARSmartxx::getInstance()
+{
+ if (mInstance == NULL)
+ {
+ mInstance = new displaySPI2PARSmartxx();
+ }
+ return mInstance;
+}
+
+bool displaySPI2PARSmartxx::isSpi2Par()
+{
+ return true;
+}
+
+char* displaySPI2PARSmartxx::getModel()
+{
+ return strdup("SPI2PAR");
+}
+
+void displaySPI2PARSmartxx::init()
+{
+ writeValue(SPI2PAR_SHOWDISPLAY);
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_FORMFEED);
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_HIDECURSOR);
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_SCROLLOFF);
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_WRAPOFF);
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_SETBACKLIGHT);
+ writeValue(settingsManager::getLcdBacklight(true));
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_SETCONTRAST);
+ writeValue(settingsManager::getLcdContrast(true));
+ utils::uSleep(2000);
+}
+
+void displaySPI2PARSmartxx::printMessage(const char* message)
+{
+ for (int i = 0; i < (int)strlen(message); ++i)
+ {
+ writeValue(message[i]);
+ utils::uSleep(2000);
+ }
+}
+
+void displaySPI2PARSmartxx::setCursorPosition(uint8_t row, uint8_t col)
+{
+ writeValue(SPI2PAR_SETCURSORPOSITION);
+ writeValue(col);
+ writeValue(row);
+ utils::uSleep(2000);
+}
+
+void displaySPI2PARSmartxx::getSupport(bool& lcdInfo, bool& backlight, bool& contrast)
+{
+ lcdInfo = false;
+ backlight = true;
+ contrast = true;
+}
+
+void displaySPI2PARSmartxx::setBacklight(uint8_t backlight)
+{
+ writeValue(SPI2PAR_SETBACKLIGHT);
+ writeValue(backlight);
+ utils::uSleep(2000);
+}
+
+void displaySPI2PARSmartxx::setContrast(uint8_t contrast)
+{
+ writeValue(SPI2PAR_SETCONTRAST);
+ writeValue(contrast);
+ utils::uSleep(2000);
+}
+
+uint8_t displaySPI2PARSmartxx::getI2cAddressCount()
+{
+ return 0;
+}
+
+uint8_t displaySPI2PARSmartxx::getI2cAddress(uint8_t index)
+{
+ return 0;
+}
+
+// Private
+
+void displaySPI2PARSmartxx::writeValue(uint8_t value)
+{
+ uint8_t spi = getSpiValue();
+ uint8_t bank = getBankValue();
+
+ spi |= SMARTXX_SPI_CLK_BIT;
+ spi &= ~SMARTXX_SPI_CS_BIT;
+ utils::ioOutputByte(SMARTXX_REGISTER_BANKING, (spi | bank));
+ utils::uSleep(0x1c);
+
+ uint8_t i = 8;
+ do
+ {
+ utils::uSleep(0x1c);
+
+ if ((value & 0x80) > 0)
+ {
+ spi |= SMARTXX_SPI_MOSI_BIT;
+ }
+ else
+ {
+ spi &= ~SMARTXX_SPI_MOSI_BIT;
+ }
+ utils::ioOutputByte(SMARTXX_REGISTER_BANKING, (spi | bank));
+
+ spi &= ~SMARTXX_SPI_CLK_BIT;
+ utils::ioOutputByte(SMARTXX_REGISTER_BANKING, (spi | bank));
+ utils::uSleep(0x1c);
+
+ spi |= SMARTXX_SPI_CLK_BIT;
+ utils::ioOutputByte(SMARTXX_REGISTER_BANKING, (spi | bank));
+
+ value = value << 1;
+ i--;
+ }
+ while (i > 0);
+
+ spi |= SMARTXX_SPI_CS_BIT;
+ utils::ioOutputByte(SMARTXX_REGISTER_BANKING, (spi | bank));
+ utils::uSleep(0x1c);
+
+ setSpiValue(spi);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARSmartxx.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARSmartxx.h
new file mode 100644
index 0000000..17fd25a
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARSmartxx.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "displayDriver.h"
+
+class displaySPI2PARSmartxx : displayDriver
+{
+public:
+ static displayDriver* getInstance();
+ bool isSpi2Par();
+ char* getModel();
+ void init();
+ void printMessage(const char* message);
+ void setCursorPosition(uint8_t row, uint8_t col);
+ void getSupport(bool& lcdInfo, bool& backlight, bool& contrast);
+ void setBacklight(uint8_t backlight);
+ void setContrast(uint8_t contrast);
+ uint8_t getI2cAddressCount();
+ uint8_t getI2cAddress(uint8_t index);
+private:
+ void writeValue(uint8_t value);
+};
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARXenium.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARXenium.cpp
new file mode 100644
index 0000000..f257fb0
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARXenium.cpp
@@ -0,0 +1,131 @@
+#include "displaySPI2PARXenium.h"
+
+static displayDriver* mInstance = NULL;
+
+displayDriver* displaySPI2PARXenium::getInstance()
+{
+ if (mInstance == NULL)
+ {
+ mInstance = new displaySPI2PARXenium();
+ }
+ return mInstance;
+}
+
+bool displaySPI2PARXenium::isSpi2Par()
+{
+ return true;
+}
+
+char* displaySPI2PARXenium::getModel()
+{
+ return strdup("SPI2PAR");
+}
+
+void displaySPI2PARXenium::init()
+{
+ writeValue(SPI2PAR_SHOWDISPLAY);
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_FORMFEED);
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_HIDECURSOR);
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_SCROLLOFF);
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_WRAPOFF);
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_SETBACKLIGHT);
+ writeValue(settingsManager::getLcdBacklight(true));
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_SETCONTRAST);
+ writeValue(settingsManager::getLcdContrast(true));
+ utils::uSleep(2000);
+}
+
+void displaySPI2PARXenium::printMessage(const char* message)
+{
+ for (int i = 0; i < (int)strlen(message); ++i)
+ {
+ writeValue(message[i]);
+ utils::uSleep(2000);
+ }
+}
+
+void displaySPI2PARXenium::setCursorPosition(uint8_t row, uint8_t col)
+{
+ writeValue(SPI2PAR_SETCURSORPOSITION);
+ writeValue(col);
+ writeValue(row);
+ utils::uSleep(2000);
+}
+
+void displaySPI2PARXenium::getSupport(bool& lcdInfo, bool& backlight, bool& contrast)
+{
+ lcdInfo = true;
+ backlight = true;
+ contrast = true;
+}
+
+void displaySPI2PARXenium::setBacklight(uint8_t backlight)
+{
+ writeValue(SPI2PAR_SETBACKLIGHT);
+ writeValue(backlight);
+ utils::uSleep(2000);
+}
+
+void displaySPI2PARXenium::setContrast(uint8_t contrast)
+{
+ writeValue(SPI2PAR_SETCONTRAST);
+ writeValue(contrast);
+ utils::uSleep(2000);
+}
+
+uint8_t displaySPI2PARXenium::getI2cAddressCount()
+{
+ return 0;
+}
+
+uint8_t displaySPI2PARXenium::getI2cAddress(uint8_t index)
+{
+ return 0;
+}
+
+// Private
+
+void displaySPI2PARXenium::writeValue(uint8_t value)
+{
+ uint8_t spi = getSpiValue();
+ uint8_t bank = getBankValue();
+
+ spi |= XENIUM_SPI_CLK_BIT;
+ utils::ioOutputByte(XENIUM_REGISTER_BANKING, (spi | bank));
+ utils::uSleep(0x1c);
+
+ uint8_t i = 8;
+ do
+ {
+ utils::uSleep(0x1c);
+
+ if ((value & 0x80) > 0)
+ {
+ spi |= XENIUM_SPI_MOSI_BIT;
+ }
+ else
+ {
+ spi &= ~XENIUM_SPI_MOSI_BIT;
+ }
+ utils::ioOutputByte(XENIUM_REGISTER_BANKING, (spi | bank));
+
+ spi &= ~XENIUM_SPI_CLK_BIT;
+ utils::ioOutputByte(XENIUM_REGISTER_BANKING, (spi | bank));
+ utils::uSleep(0x1c);
+
+ spi |= XENIUM_SPI_CLK_BIT;
+ utils::ioOutputByte(XENIUM_REGISTER_BANKING, (spi | bank));
+
+ value = value << 1;
+ i--;
+ }
+ while (i > 0);
+
+ setSpiValue(spi);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARXenium.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARXenium.h
new file mode 100644
index 0000000..2bc2a37
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARXenium.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "displayDriver.h"
+
+class displaySPI2PARXenium : displayDriver
+{
+public:
+ static displayDriver* getInstance();
+ bool isSpi2Par();
+ char* getModel();
+ void init();
+ void printMessage(const char* message);
+ void setCursorPosition(uint8_t row, uint8_t col);
+ void getSupport(bool& lcdInfo, bool& backlight, bool& contrast);
+ void setBacklight(uint8_t backlight);
+ void setContrast(uint8_t contrast);
+ uint8_t getI2cAddressCount();
+ uint8_t getI2cAddress(uint8_t index);
+private:
+ void writeValue(uint8_t value);
+};
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARXtremium.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARXtremium.cpp
new file mode 100644
index 0000000..2f13310
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARXtremium.cpp
@@ -0,0 +1,131 @@
+#include "displaySPI2PARXtremium.h"
+
+static displayDriver* mInstance = NULL;
+
+displayDriver* displaySPI2PARXtremium::getInstance()
+{
+ if (mInstance == NULL)
+ {
+ mInstance = new displaySPI2PARXtremium();
+ }
+ return mInstance;
+}
+
+bool displaySPI2PARXtremium::isSpi2Par()
+{
+ return true;
+}
+
+char* displaySPI2PARXtremium::getModel()
+{
+ return strdup("SPI2PAR");
+}
+
+void displaySPI2PARXtremium::init()
+{
+ writeValue(SPI2PAR_SHOWDISPLAY);
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_FORMFEED);
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_HIDECURSOR);
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_SCROLLOFF);
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_WRAPOFF);
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_SETBACKLIGHT);
+ writeValue(settingsManager::getLcdBacklight(true));
+ utils::uSleep(2000);
+ writeValue(SPI2PAR_SETCONTRAST);
+ writeValue(settingsManager::getLcdContrast(true));
+ utils::uSleep(2000);
+}
+
+void displaySPI2PARXtremium::printMessage(const char* message)
+{
+ for (int i = 0; i < (int)strlen(message); ++i)
+ {
+ writeValue(message[i]);
+ utils::uSleep(2000);
+ }
+}
+
+void displaySPI2PARXtremium::setCursorPosition(uint8_t row, uint8_t col)
+{
+ writeValue(SPI2PAR_SETCURSORPOSITION);
+ writeValue(col);
+ writeValue(row);
+ utils::uSleep(2000);
+}
+
+void displaySPI2PARXtremium::getSupport(bool& lcdInfo, bool& backlight, bool& contrast)
+{
+ lcdInfo = true;
+ backlight = true;
+ contrast = true;
+}
+
+void displaySPI2PARXtremium::setBacklight(uint8_t backlight)
+{
+ writeValue(SPI2PAR_SETBACKLIGHT);
+ writeValue(backlight);
+ utils::uSleep(2000);
+}
+
+void displaySPI2PARXtremium::setContrast(uint8_t contrast)
+{
+ writeValue(SPI2PAR_SETCONTRAST);
+ writeValue(contrast);
+ utils::uSleep(2000);
+}
+
+uint8_t displaySPI2PARXtremium::getI2cAddressCount()
+{
+ return 0;
+}
+
+uint8_t displaySPI2PARXtremium::getI2cAddress(uint8_t index)
+{
+ return 0;
+}
+
+// Private
+
+void displaySPI2PARXtremium::writeValue(uint8_t value)
+{
+ uint8_t spi = getSpiValue();
+ uint8_t bank = getBankValue();
+
+ spi |= XTREMIUM_SPI_CLK_BIT;
+ utils::ioOutputByte(XTREMIUM_REGISTER_BANKING, (spi | bank));
+ utils::uSleep(0x1c);
+
+ uint8_t i = 8;
+ do
+ {
+ utils::uSleep(0x1c);
+
+ if ((value & 0x80) > 0)
+ {
+ spi |= XTREMIUM_SPI_MOSI_BIT;
+ }
+ else
+ {
+ spi &= ~XTREMIUM_SPI_MOSI_BIT;
+ }
+ utils::ioOutputByte(XTREMIUM_REGISTER_BANKING, (spi | bank));
+
+ spi &= ~XTREMIUM_SPI_CLK_BIT;
+ utils::ioOutputByte(XTREMIUM_REGISTER_BANKING, (spi | bank));
+ utils::uSleep(0x1c);
+
+ spi |= XTREMIUM_SPI_CLK_BIT;
+ utils::ioOutputByte(XTREMIUM_REGISTER_BANKING, (spi | bank));
+
+ value = value << 1;
+ i--;
+ }
+ while (i > 0);
+
+ setSpiValue(spi);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARXtremium.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARXtremium.h
new file mode 100644
index 0000000..db46dbd
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/DisplayDrivers/displaySPI2PARXtremium.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "displayDriver.h"
+
+class displaySPI2PARXtremium : displayDriver
+{
+public:
+ static displayDriver* getInstance();
+ bool isSpi2Par();
+ char* getModel();
+ void init();
+ void printMessage(const char* message);
+ void setCursorPosition(uint8_t row, uint8_t col);
+ void getSupport(bool& lcdInfo, bool& backlight, bool& contrast);
+ void setBacklight(uint8_t backlight);
+ void setContrast(uint8_t contrast);
+ uint8_t getI2cAddressCount();
+ uint8_t getI2cAddress(uint8_t index);
+private:
+ void writeValue(uint8_t value);
+};
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Plugins/PEProcess.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Plugins/PEProcess.cpp
new file mode 100644
index 0000000..0ba0569
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Plugins/PEProcess.cpp
@@ -0,0 +1,373 @@
+#include "PEProcess.h"
+#include "PESymbol.h"
+
+#include "..\utils.h"
+#include "..\fileSystem.h"
+#include "..\xboxInternals.h"
+
+#include
+#include
+
+PEObject_t* PEProcess::PE_Alloc()
+{
+ PEObject_t* PEObject = (PEObject_t*)malloc(sizeof(PEObject_t));
+ if (!PEObject)
+ {
+ return NULL;
+ }
+ PEObject->HModule = NULL;
+ PEObject->DOSHeader = NULL;
+ PEObject->NTHeader = NULL;
+ PEObject->SectionHeader = NULL;
+ PEObject->ExportTable = NULL;
+ PEObject->ImportTable = NULL;
+ PEObject->ImageSize = 0;
+ return PEObject;
+}
+
+void PEProcess::PE_Free(PEObject_t* PEObject)
+{
+ if (PEObject->HModule != NULL)
+ {
+ _aligned_free(PEObject->HModule);
+ }
+ PEObject->HModule = NULL;
+ PEObject->DOSHeader = NULL;
+ PEObject->NTHeader = NULL;
+ PEObject->SectionHeader = NULL;
+ PEObject->ExportTable = NULL;
+ PEObject->ImportTable = NULL;
+ PEObject->ImageSize = 0;
+ free(PEObject);
+}
+
+PEObject_t* PEProcess::PE_Load(const char* filepath)
+{
+ std::ifstream file(filepath, std::ios::binary);
+ if (!file.is_open())
+ {
+ utils::debugPrint("PE Loader: Unable to open image file.\n");
+ return NULL;
+ }
+
+ char* filename = fileSystem::getFileName(filepath);
+
+ PEObject_t* PEObject = NULL;
+
+ PEObject = PE_Alloc();
+ if (PEObject == NULL)
+ {
+ utils::debugPrint("PE Loader [%s]: Unable to allocate context.\n", filename);
+ file.close();
+ return NULL;
+ }
+
+ file.seekg(0, std::ios::end);
+ std::streampos fileSize = file.tellg();
+ file.seekg(0, std::ios::beg);
+
+ PEObject->ImageSize = fileSize;
+
+ PEObject->DOSHeader = (XIMAGE_DOS_HEADER*)malloc(sizeof(XIMAGE_DOS_HEADER));
+ if (PEObject->DOSHeader == NULL) {
+ utils::debugPrint("PE Loader [%s]: \n\tUnable to allocate memory for DOSHeader [0x%08x bytes].\n", filename, sizeof(XIMAGE_DOS_HEADER));
+ free(PEObject);
+ file.close();
+ return NULL;
+ }
+
+ file.read((char*)PEObject->DOSHeader, sizeof(XIMAGE_DOS_HEADER));
+ if (PEObject->DOSHeader->e_magic != IMAGE_DOS_SIGNATURE) {
+ utils::debugPrint("PE Loader [%s]: \n\tInvalid DOS signature 0x%04x.\n", filename, PEObject->DOSHeader->e_magic);
+ free(PEObject->DOSHeader);
+ free(PEObject);
+ file.close();
+ return NULL;
+ }
+
+ PEObject->NTHeader = (XIMAGE_NT_HEADERS32*)malloc(sizeof(XIMAGE_NT_HEADERS32));
+ if (PEObject->NTHeader == NULL) {
+ utils::debugPrint("PE Loader [%s]: \n\tUnable to allocate memory for NTHeader [0x%08x bytes].\n", filename, sizeof(XIMAGE_NT_HEADERS32));
+ free(PEObject->DOSHeader);
+ free(PEObject);
+ file.close();
+ return NULL;
+ }
+
+ file.seekg(PEObject->DOSHeader->e_lfanew, std::ios::beg);
+ file.read((char*)PEObject->NTHeader, sizeof(XIMAGE_NT_HEADERS32));
+ if (PEObject->NTHeader->Signature != IMAGE_NT_SIGNATURE) {
+ utils::debugPrint("PE Loader [%s]: \n\tInvalid NT signature 0x%08x.\n", filename, PEObject->NTHeader->Signature);
+ free(PEObject->NTHeader);
+ free(PEObject->DOSHeader);
+ free(PEObject);
+ file.close();
+ return NULL;
+ }
+
+ PEObject->HModule = _aligned_malloc(PEObject->NTHeader->OptionalHeader.SizeOfImage, 0x10000);
+ if (PEObject->HModule == NULL) {
+ utils::debugPrint("PE Loader [%s]: \n\tUnable to allocate aligned memory for HModule [0x%08x bytes].\n", filename, PEObject->NTHeader->OptionalHeader.SizeOfImage);
+ free(PEObject->NTHeader);
+ free(PEObject->DOSHeader);
+ free(PEObject);
+ file.close();
+ return NULL;
+ }
+
+ memset(PEObject->HModule, 0, PEObject->NTHeader->OptionalHeader.SizeOfImage);
+
+ file.seekg(0, std::ios::beg);
+ file.read((char*)PEObject->HModule, PEObject->NTHeader->OptionalHeader.SizeOfHeaders);
+
+ utils::debugPrint("PE Loader [%s]: Image 0x%08x.\n", filename, (uint32_t)PEObject->HModule);
+
+ free(PEObject->DOSHeader);
+ PEObject->DOSHeader = (XIMAGE_DOS_HEADER*)PEObject->HModule;
+
+ free(PEObject->NTHeader);
+ PEObject->NTHeader = (XIMAGE_NT_HEADERS32*)((char*)PEObject->HModule + PEObject->DOSHeader->e_lfanew);
+
+ if (PEObject->NTHeader->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)
+ {
+ utils::debugPrint("PE Loader [%s]: \n\tInvalid archetecture 0x%04x.\n", filename, PEObject->NTHeader->FileHeader.Machine);
+ }
+
+ if ((PEObject->NTHeader->FileHeader.Characteristics & IMAGE_FILE_DLL) == 0)
+ {
+ utils::debugPrint("PE Loader [%s]: \n\tFile is not a DLL.\n", filename);
+ }
+
+ //This was changed to int64
+ PEObject->SectionHeader = (XIMAGE_SECTION_HEADER*)(((uint32_t)&PEObject->NTHeader->OptionalHeader) + PEObject->NTHeader->FileHeader.SizeOfOptionalHeader);
+ for (int i = 0; i < PEObject->NTHeader->FileHeader.NumberOfSections; i++)
+ {
+ utils::debugPrint("PE Loader [%s]: Section header found '%s'.\n", filename, PEObject->SectionHeader[i].Name);
+ if (PEObject->SectionHeader[i].SizeOfRawData)
+ {
+ file.seekg(PEObject->SectionHeader[i].PointerToRawData, std::ios::beg);
+ file.read(((char*)PEObject->HModule) + PEObject->SectionHeader[i].VirtualAddress, PEObject->SectionHeader[i].SizeOfRawData);
+ }
+ }
+
+ PE_Export(PEObject, filename);
+ PE_Import(PEObject, filename);
+ PE_BaseReloc(PEObject, filename);
+
+ file.close();
+ return PEObject;
+}
+
+int32_t PEProcess::PE_Export(PEObject_t* PEObject, const char* library)
+{
+ uint32_t VirtualAddress = PEObject->NTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
+ if (VirtualAddress == 0)
+ {
+ return 0;
+ }
+
+ PEObject->ExportTable = (XIMAGE_EXPORT_DIRECTORY*)((char*)PEObject->HModule + VirtualAddress);
+ uint32_t* ExportNameTable = (uint32_t*)((char*)PEObject->HModule + PEObject->ExportTable->AddressOfNames);
+ uint16_t* ExportOrdinalTable = (uint16_t*)((char*)PEObject->HModule + PEObject->ExportTable->AddressOfNameOrdinals);
+ uint32_t* ExportAddressTable = (uint32_t*)((char*)PEObject->HModule + PEObject->ExportTable->AddressOfFunctions);
+ for (uint32_t x = 0; x < PEObject->ExportTable->NumberOfNames; x++) {
+ char* SymStr = (char*)PEObject->HModule + ExportNameTable[x];
+ uint32_t* SymVal = (uint32_t*)((char*)PEObject->HModule + ExportAddressTable[ExportOrdinalTable[x]]);
+ PESymbol::AddSymbol(library, SymStr, ExportOrdinalTable[x], SymVal);
+ }
+
+ return 1;
+}
+
+int32_t PEProcess::PE_Import(PEObject_t* PEObject, const char* filename)
+{
+ uint32_t VirtualAddress = PEObject->NTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
+
+ if (VirtualAddress == 0) return 0;
+ PEObject->ImportTable = (XIMAGE_IMPORT_DIRECTORY*)((char*)PEObject->HModule + VirtualAddress);
+ for (uint32_t x = 0; PEObject->ImportTable[x].ImportLookupTable != 0; x++) {
+ uint32_t* ILT = (uint32_t*)((char*)PEObject->HModule + PEObject->ImportTable[x].ImportLookupTable);
+ uint32_t* IAT = (uint32_t*)((char*)PEObject->HModule + PEObject->ImportTable[x].ImportAddressTable);
+ utils::debugPrint("PE Loader [%s]: \n\tDLL Reference: %s\n", filename, (char*)PEObject->HModule+PEObject->ImportTable[x].Name);
+ for (uint32_t y = 0; ILT[y] != 0; y++) {
+ if (ILT[y] & IMAGE_ORDINAL_FLAG32) {
+ IAT[y] = PESymbol::ResolveImportByOrdinal(filename, (char*)PEObject->HModule + PEObject->ImportTable[x].Name, ILT[y] & (~IMAGE_ORDINAL_FLAG32));
+ utils::debugPrint("\t\tImport by Ordinal 0x%08x : 0x%08x\n", ILT[y]&(~IMAGE_ORDINAL_FLAG32), IAT[y]);
+ }
+ else {
+ char* ImportStr = (char*)PEObject->HModule + (ILT[y] & (~IMAGE_ORDINAL_FLAG32)) + 2;
+ IAT[y] = PESymbol::ResolveImportByName(filename, (char*)PEObject->HModule + PEObject->ImportTable[x].Name, ImportStr);
+ utils::debugPrint("\t\tImport by String %s : 0x%08x\n", ImportStr, IAT[y]);
+ }
+ }
+ }
+
+ return 1;
+}
+
+uint32_t PEProcess::PE_BaseReloc(PEObject_t* PEObject, const char* filename)
+{
+ uint32_t VirtualAddress = PEObject->NTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
+ uint32_t DirectorySize = PEObject->NTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
+ uint32_t Delta = (uint32_t)PEObject->HModule - PEObject->NTHeader->OptionalHeader.ImageBase;
+
+ if (VirtualAddress == 0)
+ {
+ return 0;
+ }
+
+ if (Delta == 0)
+ {
+ return 1;
+ }
+
+ for (uint32_t x = 0; x < DirectorySize;)
+ {
+ XIMAGE_BASE_RELOCATION* BaseReloc = (XIMAGE_BASE_RELOCATION*)((char*)PEObject->HModule + VirtualAddress + x);
+ uint32_t Offset = (uint32_t)PEObject->HModule + BaseReloc->VirtualAddress;
+ if (BaseReloc->SizeOfBlock)
+ {
+ for (uint32_t y = 0; y < BaseReloc->SizeOfBlock - 8; y += 2)
+ {
+ XIMAGE_BASE_RELOC_FIXUP* Fixup = (XIMAGE_BASE_RELOC_FIXUP*)((char*)BaseReloc + sizeof(XIMAGE_BASE_RELOCATION) + y);
+ switch (Fixup[0].Type)
+ {
+ case IMAGE_REL_BASED_HIGH:
+ {
+ uint16_t* Victim = (uint16_t*)(Offset + Fixup[0].Offset);
+ uint32_t TEMP;
+ TEMP = Victim[0] << 16;
+ TEMP += Delta;
+ Victim[0] = (uint16_t)(TEMP >> 16);
+ break;
+ }
+ case IMAGE_REL_BASED_LOW:
+ {
+ uint16_t* Victim = (uint16_t*)(Offset + Fixup[0].Offset);
+ uint32_t TEMP;
+ TEMP = Victim[0];
+ TEMP += Delta;
+ Victim[0] = (uint16_t)(TEMP & 0xffff);
+ break;
+ }
+ case IMAGE_REL_BASED_HIGHLOW:
+ {
+ uint32_t* Victim = (uint32_t*)(Offset + Fixup[0].Offset);
+ Victim[0] += Delta;
+ break; }
+ case IMAGE_REL_BASED_HIGHADJ:
+ {
+ uint32_t* Victim = (uint32_t*)(Offset + Fixup[0].Offset);
+ Victim[0] += Delta;
+ break;
+ }
+ case IMAGE_REL_BASED_DIR64:
+ {
+ __int64* Victim = (__int64*)(Offset + Fixup[0].Offset);
+ Victim[0] += Delta;
+ break;
+ }
+ }
+ }
+ }
+ x += BaseReloc->SizeOfBlock;
+ if (BaseReloc->SizeOfBlock % 4)
+ {
+ x += 4 - (BaseReloc->SizeOfBlock % 4);
+ }
+ }
+
+ return 1;
+}
+
+void* PEProcess::PE_GetSym(PEObject_t* PEObject, const char* Function)
+{
+ if ((!PEObject) || (!PEObject->HModule) || (!PEObject->ExportTable))
+ {
+ return NULL;
+ }
+
+ uint32_t* ExportNameTable = (uint32_t*)((char*)PEObject->HModule + PEObject->ExportTable->AddressOfNames);
+ uint16_t* ExportOrdinalTable = (uint16_t*)((char*)PEObject->HModule + PEObject->ExportTable->AddressOfNameOrdinals);
+ uint32_t* ExportAddressTable = (uint32_t*)((char*)PEObject->HModule + PEObject->ExportTable->AddressOfFunctions);
+ for (uint32_t i = 0; i < PEObject->ExportTable->NumberOfNames; i++)
+ {
+ char* Str = (char*)PEObject->HModule + ExportNameTable[i];
+ if (!strcmp(Function, Str))
+ {
+ return ((char*)PEObject->HModule + ExportAddressTable[ExportOrdinalTable[i]]);
+ }
+ }
+ return NULL;
+}
+
+
+
+char* PEProcess::getPluginName(const char* filePath)
+{
+ char* buffer = NULL;
+
+ void (*NXEMain)(char*, uint32_t) = NULL;
+
+ PEObject_t* peObject = PEProcess::PE_Load(filePath);
+ if (!peObject)
+ {
+ goto done;
+ }
+ NXEMain = (void(__cdecl*)(char*, uint32_t))PEProcess::PE_GetSym(peObject, "getPluginName");
+ if (!NXEMain)
+ {
+ goto done;
+ }
+
+ buffer = (char*)malloc(40);
+ NXEMain(buffer, 40);
+
+done:
+
+ if (peObject)
+ {
+ PEProcess::PE_Free(peObject);
+ }
+
+ return buffer;
+}
+
+int32_t PEProcess::PE_Run(const char* filePath, PEParam_t* params)
+{
+ int (*NXEMain)(int, char**) = NULL;
+
+ PEObject_t* peObject = PEProcess::PE_Load(filePath);
+ if (!peObject)
+ {
+ goto done;
+ }
+ NXEMain = (int(__cdecl*)(int, char**))PEProcess::PE_GetSym(peObject, "main");
+ if (!NXEMain)
+ {
+ goto done;
+ }
+
+ return (unsigned long)NXEMain(params->argc, params->argv);
+
+done:
+
+ if (peObject)
+ {
+ PEProcess::PE_Free(peObject);
+ }
+
+ if (params)
+ {
+ for (int i = 0; i < params->argc; i++)
+ {
+ if (params->argv[i])
+ {
+ free(params->argv[i]);
+ }
+ }
+ free(params);
+ }
+
+ return -1;
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Plugins/PEProcess.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Plugins/PEProcess.h
new file mode 100644
index 0000000..90411e6
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Plugins/PEProcess.h
@@ -0,0 +1,193 @@
+#pragma once
+
+#include "..\xboxInternals.h"
+
+#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
+#define IMAGE_SIZEOF_SHORT_NAME 8
+
+#pragma pack(push, 1)
+
+typedef struct XIMAGE_DOS_HEADER { // DOS .EXE header
+ uint16_t e_magic; // Magic number
+ uint16_t e_cblp; // uchars on last page of file
+ uint16_t e_cp; // Pages in file
+ uint16_t e_crlc; // Relocations
+ uint16_t e_cparhdr; // Size of header in paragraphs
+ uint16_t e_minalloc; // Minimum extra paragraphs needed
+ uint16_t e_maxalloc; // Maximum extra paragraphs needed
+ uint16_t e_ss; // Initial (relative) SS value
+ uint16_t e_sp; // Initial SP value
+ uint16_t e_csum; // Checksum
+ uint16_t e_ip; // Initial IP value
+ uint16_t e_cs; // Initial (relative) CS value
+ uint16_t e_lfarlc; // File address of relocation table
+ uint16_t e_ovno; // Overlay number
+ uint16_t e_res[4]; // Reserved ushorts
+ uint16_t e_oemid; // OEM identifier (for e_oeminfo)
+ uint16_t e_oeminfo; // OEM information; e_oemid specific
+ uint16_t e_res2[10]; // Reserved ushorts
+ int32_t e_lfanew; // File address of new exe header
+} XIMAGE_DOS_HEADER;
+
+typedef struct XIMAGE_FILE_HEADER {
+ uint16_t Machine;
+ uint16_t NumberOfSections;
+ uint32_t TimeDateStamp;
+ uint32_t PointerToSymbolTable;
+ uint32_t NumberOfSymbols;
+ uint16_t SizeOfOptionalHeader;
+ uint16_t Characteristics;
+} XIMAGE_FILE_HEADER;
+
+#define IMAGE_DOS_SIGNATURE 0x5A4D
+#define IMAGE_NT_SIGNATURE 0x00004550
+#define IMAGE_FILE_MACHINE_I386 0x014c
+#define IMAGE_FILE_DLL 0x2000
+#define IMAGE_DIRECTORY_ENTRY_EXPORT 0
+#define IMAGE_DIRECTORY_ENTRY_IMPORT 1
+#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5
+#define IMAGE_REL_BASED_HIGH 1
+#define IMAGE_REL_BASED_LOW 2
+#define IMAGE_REL_BASED_HIGHLOW 3
+#define IMAGE_REL_BASED_HIGHADJ 4
+#define IMAGE_REL_BASED_DIR64 10
+#define IMAGE_ORDINAL_FLAG32 0x80000000
+
+#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
+#define IMAGE_SIZEOF_SHORT_NAME 8
+
+typedef struct XIMAGE_DATA_DIRECTORY {
+ uint32_t VirtualAddress;
+ uint32_t Size;
+} XIMAGE_DATA_DIRECTORY;
+
+typedef struct XIMAGE_OPTIONAL_HEADER {
+ //
+ // Standard fields.
+ //
+
+ uint16_t Magic;
+ uint8_t MajorLinkerVersion;
+ uint8_t MinorLinkerVersion;
+ uint32_t SizeOfCode;
+ uint32_t SizeOfInitializedData;
+ uint32_t SizeOfUninitializedData;
+ uint32_t AddressOfEntryPoint;
+ uint32_t BaseOfCode;
+ uint32_t BaseOfData;
+
+ //
+ // NT additional fields.
+ //
+
+ uint32_t ImageBase;
+ uint32_t SectionAlignment;
+ uint32_t FileAlignment;
+ uint16_t MajorOperatingSystemVersion;
+ uint16_t MinorOperatingSystemVersion;
+ uint16_t MajorImageVersion;
+ uint16_t MinorImageVersion;
+ uint16_t MajorSubsystemVersion;
+ uint16_t MinorSubsystemVersion;
+ uint32_t Win32VersionValue;
+ uint32_t SizeOfImage;
+ uint32_t SizeOfHeaders;
+ uint32_t CheckSum;
+ uint16_t Subsystem;
+ uint16_t DllCharacteristics;
+ uint32_t SizeOfStackReserve;
+ uint32_t SizeOfStackCommit;
+ uint32_t SizeOfHeapReserve;
+ uint32_t SizeOfHeapCommit;
+ uint32_t LoaderFlags;
+ uint32_t NumberOfRvaAndSizes;
+ XIMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
+} XIMAGE_OPTIONAL_HEADER32;
+
+typedef struct XIMAGE_NT_HEADERS32 {
+ uint32_t Signature;
+ XIMAGE_FILE_HEADER FileHeader;
+ XIMAGE_OPTIONAL_HEADER32 OptionalHeader;
+} XIMAGE_NT_HEADERS32;
+
+typedef struct XIMAGE_EXPORT_DIRECTORY {
+ uint32_t Characteristics;
+ uint32_t TimeDateStamp;
+ uint16_t MajorVersion;
+ uint16_t MinorVersion;
+ uint32_t Name;
+ uint32_t Base;
+ uint32_t NumberOfFunctions;
+ uint32_t NumberOfNames;
+ uint32_t AddressOfFunctions; // RVA from base of image
+ uint32_t AddressOfNames; // RVA from base of image
+ uint32_t AddressOfNameOrdinals; // RVA from base of image
+} XIMAGE_EXPORT_DIRECTORY;
+
+typedef struct XIMAGE_SECTION_HEADER {
+ uint8_t Name[IMAGE_SIZEOF_SHORT_NAME];
+ union {
+ uint32_t PhysicalAddress;
+ uint32_t VirtualSize;
+ } Misc;
+ uint32_t VirtualAddress;
+ uint32_t SizeOfRawData;
+ uint32_t PointerToRawData;
+ uint32_t PointerToRelocations;
+ uint32_t PointerToLinenumbers;
+ uint16_t NumberOfRelocations;
+ uint16_t NumberOfLinenumbers;
+ uint32_t Characteristics;
+} XIMAGE_SECTION_HEADER;
+
+typedef struct XIMAGE_IMPORT_DIRECTORY {
+ uint32_t ImportLookupTable;
+ uint32_t TimeDateStamp;
+ uint32_t ForwarderChain;
+ uint32_t Name;
+ uint32_t ImportAddressTable;
+} XIMAGE_IMPORT_DIRECTORY;
+
+typedef struct XIMAGE_BASE_RELOCATION {
+ uint32_t VirtualAddress;
+ uint32_t SizeOfBlock;
+} XIMAGE_BASE_RELOCATION;
+
+typedef struct XIMAGE_BASE_RELOC_FIXUP {
+ uint16_t Offset : 12;
+ uint16_t Type : 4;
+} XIMAGE_BASE_RELOC_FIXUP;
+
+typedef struct PEObject_t
+{
+ void* HModule;
+ XIMAGE_DOS_HEADER* DOSHeader;
+ XIMAGE_NT_HEADERS32* NTHeader;
+ XIMAGE_SECTION_HEADER* SectionHeader;
+ XIMAGE_EXPORT_DIRECTORY* ExportTable;
+ XIMAGE_IMPORT_DIRECTORY* ImportTable;
+ uint32_t ImageSize;
+} PEObject_t;
+
+typedef struct PEParam_t {
+ int argc;
+ char** argv;
+} PEEParam_t;
+
+#pragma pack(pop)
+
+class PEProcess
+{
+public:
+ static PEObject_t* PE_Alloc();
+ static void PE_Free(PEObject_t* PEObject);
+ static PEObject_t* PE_Load(const char* filepath);
+ static int32_t PE_Export(PEObject_t* PEObject, const char* filename);
+ static int32_t PE_Import(PEObject_t* PEObject, const char* filename);
+ static uint32_t PE_BaseReloc(PEObject_t* PEObject, const char* filename);
+ static void* PE_GetSym(PEObject_t* PEObject, const char* Function);
+
+ static char* getPluginName(const char* filePath);
+ static int32_t PE_Run(const char* filePath, PEParam_t* params);
+};
+
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Plugins/PESymbol.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Plugins/PESymbol.cpp
new file mode 100644
index 0000000..480c547
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Plugins/PESymbol.cpp
@@ -0,0 +1,232 @@
+#include "PESymbol.h"
+#include "PEProcess.h"
+
+#include "..\utils.h"
+#include "..\xboxInternals.h"
+
+#include
+#include
+
+static LibraryEntry_t* ImportableSymbols;
+
+LibraryEntry_t* PESymbol::AddLibrary(const char* filename)
+{
+ LibraryEntry_t* NL = (LibraryEntry_t*)malloc(sizeof(LibraryEntry_t));
+ if (!NL)
+ {
+ return NULL;
+ }
+
+ NL->Name = strdup(filename);
+ NL->Next = NULL;
+ NL->SymTab = NULL;
+ NL->Ready = 0;
+
+ // Check if libraries have been added yet.
+ if (ImportableSymbols == NULL)
+ {
+ ImportableSymbols = NL;
+ }
+ else
+ {
+ for (LibraryEntry_t* CL = ImportableSymbols; CL != NULL; CL = CL->Next)
+ {
+ if (CL->Next == NULL)
+ {
+ CL->Next = NL;
+ break;
+ }
+ }
+ }
+
+ // If we get here then shit has happened.
+ return NL;
+}
+
+LibraryEntry_t* PESymbol::FindLibrary(const char* filename)
+{
+ LibraryEntry_t* CL;
+
+ // Check if libraries have been added yet.
+ if (ImportableSymbols == NULL) {
+ return NULL;
+ }
+
+ // Atleast one library added, check to see if this one has been.
+ for (CL = ImportableSymbols; CL != NULL; CL = CL->Next)
+ {
+ if ((CL->Name != NULL) && (!_stricmp(CL->Name, filename)))
+ {
+ return CL;
+ }
+ }
+
+ // Requested library not found.
+ return NULL;
+}
+
+LibraryEntry_t* PESymbol::FindOrAddLibrary(const char* filename)
+{
+ LibraryEntry_t* RV = FindLibrary(filename);
+ if (RV == NULL)
+ {
+ RV = AddLibrary(filename);
+ utils::debugPrint("Library [%s]: Added.\n", filename);
+ }
+
+ return RV;
+}
+
+SymbolEntry_t* PESymbol::AddSymbol(const char* filename, const char* Name, uint32_t Ordinal, void* Symbol)
+{
+ LibraryEntry_t* LT = FindOrAddLibrary(filename);
+
+ if (LT->SymTab == NULL)
+ {
+ LT->SymTab = (SymbolEntry_t*)malloc(sizeof(SymbolEntry_t));
+ LT->SymTab->Name = strdup(Name);
+ LT->SymTab->Ordinal = Ordinal;
+ LT->SymTab->Symbol = Symbol;
+ LT->SymTab->Next = NULL;
+ return LT->SymTab;
+ }
+ else
+ {
+ SymbolEntry_t* CF;
+ for (CF = LT->SymTab; CF != NULL; CF = CF->Next)
+ {
+ if (CF->Next == NULL)
+ {
+ CF->Next = (SymbolEntry_t*)malloc(sizeof(SymbolEntry_t));
+ CF = CF->Next;
+ if (CF)
+ {
+ CF->Name = strdup(Name);
+ CF->Ordinal = Ordinal;
+ CF->Symbol = Symbol;
+ CF->Next = NULL;
+ }
+ return CF;
+ }
+ }
+ }
+
+ // If we get here then shit has happened.
+ return NULL;
+}
+
+void PESymbol::UnresolvedSymbolCalled()
+{
+ utils::debugPrint("An unresolved symbol was called.\n");
+}
+
+uint32_t PESymbol::ResolveImportByOrdinal(const char* Filename, const char* Library, uint32_t Ordinal)
+{
+ SymbolEntry_t* CF;
+ LibraryEntry_t* IL = FindLibrary(Library);
+ if (IL == NULL)
+ {
+ goto Unresolved;
+ }
+
+ for (CF = IL->SymTab; CF != NULL; CF = CF->Next)
+ {
+ if (Ordinal == CF->Ordinal)
+ {
+ return (uint32_t)CF->Symbol;
+ }
+ }
+
+Unresolved:
+ utils::debugPrint("Unable to resolve ordinal '%lu' from library '%s' for '%s'.\n", Ordinal, Library, Filename);
+ return (uint32_t)UnresolvedSymbolCalled;
+}
+
+void PESymbol::RemoveLibrary(const char* library)
+{
+ LibraryEntry_t * PL = NULL;
+ for (LibraryEntry_t* CL = ImportableSymbols; CL != NULL; CL = CL->Next)
+ {
+ if ((CL->Name != NULL) && (!_stricmp(CL->Name, library)))
+ {
+ if (PL)
+ {
+ PL->Next = CL->Next;
+ }
+ else ImportableSymbols = CL->Next;
+ free(CL->Name);
+ if (CL->SymTab)
+ {
+ SymbolEntry_t* NE = NULL;
+ for (SymbolEntry_t* CE = CL->SymTab; CE != NULL; CE = NE)
+ {
+ SymbolEntry_t* NE = CE->Next;
+ if (CE)
+ {
+ if (CE->Name)
+ {
+ free(CE->Name);
+ }
+ free(CE);
+ }
+ }
+ }
+ }
+ PL = CL;
+ }
+}
+
+LibraryEntry_t* PESymbol::FindOrLoadLibrary(const char* library)
+{
+ LibraryEntry_t* RV = FindLibrary(library);
+ if (RV == NULL)
+ {
+ char* fp = (char*)malloc(strlen("HDD0-E:\\Root\\Libs\\") + strlen(library) + 2);
+ strcpy(fp, "HDD0-E:\\Root\\Libs\\");
+ strcat(fp, library);
+
+ utils::debugPrint("Library [%s]: %s Loading\n", library, fp);
+
+ PEObject_t* lib = PEProcess::PE_Load(fp);
+ if (lib)
+ {
+ RV = FindLibrary(library);
+ RV->Object = lib;
+ RV->Ready = 1;
+ }
+ else
+ {
+ RemoveLibrary(library);
+ }
+ free(fp);
+ }
+
+ return RV;
+}
+
+uint32_t PESymbol::ResolveImportByName(const char* filename, const char* library, const char* symbol)
+{
+ SymbolEntry_t* CF;
+ LibraryEntry_t* IL = FindOrLoadLibrary(library);
+ if (IL == NULL)
+ {
+ goto Unresolved;
+ }
+
+ while (!IL->Ready)
+ {
+ //Sleep(10);
+ }
+
+ for (CF = IL->SymTab; CF != NULL; CF = CF->Next)
+ {
+ if (!strcmp(symbol, CF->Name))
+ {
+ return (uint32_t)CF->Symbol;
+ }
+ }
+
+Unresolved:
+ utils::debugPrint("Unable to resolve symbol '%s' from library '%s' for '%s'.\n", symbol, library, filename);
+ return (uint32_t)UnresolvedSymbolCalled;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Plugins/PESymbol.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Plugins/PESymbol.h
new file mode 100644
index 0000000..6e75f6f
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Plugins/PESymbol.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include "..\xboxInternals.h"
+
+typedef struct SymbolSetup_t {
+ char* Library;
+ char* Name;
+ uint32_t Ordinal;
+ void* Symbol;
+} SymbolSetup_t;
+
+typedef struct SymbolEntry_t {
+ char* Name;
+ uint32_t Ordinal;
+ void* Symbol;
+ struct SymbolEntry_t* Next;
+} SymbolEntry_t;
+
+typedef struct LibraryEntry_t {
+ char* Name;
+ SymbolEntry_t* SymTab;
+ struct LibraryEntry_t* Next;
+ void* Object;
+ int Ready;
+} LibraryEntry_t;
+
+class PESymbol
+{
+public:
+ static LibraryEntry_t* AddLibrary(const char* filename);
+ static LibraryEntry_t* FindLibrary(const char* filename);
+ static LibraryEntry_t* FindOrAddLibrary(const char* filename);
+ static SymbolEntry_t* AddSymbol(const char* filename, const char* name, uint32_t ordinal, void* symbol);
+ static void UnresolvedSymbolCalled();
+ static uint32_t ResolveImportByOrdinal(const char* filename, const char* library, uint32_t ordinal);
+ static LibraryEntry_t* FindOrLoadLibrary(const char* library);
+ static void RemoveLibrary(const char* Library);
+ static uint32_t ResolveImportByName(const char* filename, const char* library, const char* symbol);
+};
+
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/PrometheOSXbe.vcproj b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/PrometheOSXbe.vcproj
new file mode 100644
index 0000000..a4b13b9
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/PrometheOSXbe.vcproj
@@ -0,0 +1,2561 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/audioSettingsScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/audioSettingsScene.cpp
new file mode 100644
index 0000000..b11a650
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/audioSettingsScene.cpp
@@ -0,0 +1,172 @@
+#include "audioSettingsScene.h"
+#include "sceneManager.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\inputManager.h"
+#include "..\ssfn.h"
+#include "..\xboxConfig.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\theme.h"
+
+audioSettingsScene::audioSettingsScene()
+{
+ mSelectedControl = 0;
+ if (xboxConfig::getAudioModeStereo() == true)
+ {
+ mSelectedControl = 1;
+ }
+ if (xboxConfig::getAudioModeSurround() == true)
+ {
+ mSelectedControl = 2;
+ }
+}
+
+void audioSettingsScene::update()
+{
+ // Back Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene();
+ return;
+ }
+
+ // Select Actions
+
+ if (inputManager::buttonPressed(ButtonA))
+ {
+ if (mSelectedControl == 0)
+ {
+ xboxConfig::setAudioMode(XC_AUDIO_FLAGS_MONO);
+ }
+ else if (mSelectedControl == 1)
+ {
+ xboxConfig::setAudioMode(XC_AUDIO_FLAGS_STEREO);
+ }
+ else if (mSelectedControl == 2)
+ {
+ xboxConfig::setAudioMode(XC_AUDIO_FLAGS_SURROUND);
+ }
+ else if (mSelectedControl == 3)
+ {
+ xboxConfig::setAudioAC3(false);
+ }
+ else if (mSelectedControl == 4)
+ {
+ xboxConfig::setAudioAC3(true);
+ }
+ else if (mSelectedControl == 5)
+ {
+ xboxConfig::setAudioDTS(false);
+ }
+ else if (mSelectedControl == 6)
+ {
+ xboxConfig::setAudioDTS(true);
+ }
+ }
+
+ // Left Actions
+
+ if (inputManager::buttonPressed(ButtonDpadLeft))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 2)
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : 2;
+ }
+ else if (mSelectedControl >= 3 && mSelectedControl <= 4)
+ {
+ mSelectedControl = mSelectedControl > 3 ? mSelectedControl - 1 : 4;
+ }
+ else if (mSelectedControl >= 5 && mSelectedControl <= 6)
+ {
+ mSelectedControl = mSelectedControl > 5 ? mSelectedControl - 1 : 6;
+ }
+ }
+
+ // Right Actions
+
+ if (inputManager::buttonPressed(ButtonDpadRight))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 2)
+ {
+ mSelectedControl = mSelectedControl < 2 ? mSelectedControl + 1 : 0;
+ }
+ else if (mSelectedControl >= 3 && mSelectedControl <= 4)
+ {
+ mSelectedControl = mSelectedControl < 4 ? mSelectedControl + 1 : 3;
+ }
+ else if (mSelectedControl >= 5 && mSelectedControl <= 6)
+ {
+ mSelectedControl = mSelectedControl < 6 ? mSelectedControl + 1 : 5;
+ }
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 2)
+ {
+ mSelectedControl = 3;
+ }
+ else if (mSelectedControl >= 3 && mSelectedControl <= 4)
+ {
+ mSelectedControl += 2;
+ }
+ else if (mSelectedControl >= 5 && mSelectedControl <= 6)
+ {
+ mSelectedControl = 0;
+ }
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 2)
+ {
+ mSelectedControl = 5;
+ }
+ else if (mSelectedControl >= 3 && mSelectedControl <= 4)
+ {
+ mSelectedControl = 0;
+ }
+ else if (mSelectedControl >= 5 && mSelectedControl <= 6)
+ {
+ mSelectedControl -= 2;
+ }
+ }
+}
+
+void audioSettingsScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Audio settings...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ int xPos = 117;
+ int yPos = (context::getBufferHeight() - (30 + 45 + 30 + 45 + 30 + 30)) / 2;
+ yPos += theme::getCenterOffset();
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "Audio Mode", theme::getTextColor(), xPos, yPos);
+ yPos += 30;
+ component::button(mSelectedControl == 0, xboxConfig::getAudioModeMono(), "Mono", xPos, yPos, 160, 30);
+ component::button(mSelectedControl == 1, xboxConfig::getAudioModeStereo(), "Stereo", xPos + 164, yPos, 160, 30);
+ component::button(mSelectedControl == 2, xboxConfig::getAudioModeSurround(), "Surround", xPos + (164 * 2), yPos, 160, 30);
+ yPos += 45;
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "Dolby Digital (AC3)", theme::getTextColor(), xPos, yPos);
+ yPos += 30;
+ component::button(mSelectedControl == 3, xboxConfig::getAudioAC3() == false, "Disabled", xPos, yPos, 241, 30);
+ component::button(mSelectedControl == 4, xboxConfig::getAudioAC3() == true, "Enabled", xPos + 245, yPos, 241, 30);
+ yPos += 45;
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "DTS", theme::getTextColor(), xPos, yPos);
+ yPos += 30;
+ component::button(mSelectedControl == 5, xboxConfig::getAudioDTS() == false, "Disabled", xPos, yPos, 241, 30);
+ component::button(mSelectedControl == 6, xboxConfig::getAudioDTS() == true, "Enabled", xPos + 245, yPos, 241, 30);
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Select", theme::getFooterTextColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/audioSettingsScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/audioSettingsScene.h
new file mode 100644
index 0000000..f71e1be
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/audioSettingsScene.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "scene.h"
+
+class audioSettingsScene : public scene
+{
+public:
+ audioSettingsScene();
+ void update();
+ void render();
+private:
+ int mSelectedControl;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/audioVideoOptionsScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/audioVideoOptionsScene.cpp
new file mode 100644
index 0000000..b3c8861
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/audioVideoOptionsScene.cpp
@@ -0,0 +1,147 @@
+#include "audioVideoOptionsScene.h"
+#include "sceneManager.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxConfig.h"
+#include "..\theme.h"
+#include "..\fileSystem.h"
+
+audioVideoOptionsScene::audioVideoOptionsScene()
+{
+ mSelectedControl = 0;
+}
+
+void audioVideoOptionsScene::update()
+{
+ // Exit Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene();
+ return;
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ mSelectedControl = mSelectedControl < 2? mSelectedControl + 1 : 0;
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : 2;
+ }
+
+ // Left Trigger
+
+ if (inputManager::buttonPressed(ButtonTriggerLeft) || inputManager::buttonPressed(ButtonX))
+ {
+ if (mSelectedControl == 0)
+ {
+ uint8_t musicVolume = settingsManager::getMusicVolume();
+ musicVolume = (musicVolume >= 5) ? (musicVolume - 5) : 100;
+ settingsManager::setMusicVolume(musicVolume);
+ return;
+ }
+
+ if (mSelectedControl == 1)
+ {
+ uint8_t soundVolume = settingsManager::getSoundVolume();
+ soundVolume = (soundVolume >= 5) ? (soundVolume - 5) : 100;
+ settingsManager::setSoundVolume(soundVolume);
+ return;
+ }
+
+ if (mSelectedControl == 2)
+ {
+ bool vgaEnable = settingsManager::getVgaEnable();
+ settingsManager::setVgaEnable(!vgaEnable);
+ return;
+ }
+ }
+
+ // Right Trigger
+
+ if (inputManager::buttonPressed(ButtonTriggerRight) || inputManager::buttonPressed(ButtonY))
+ {
+ if (mSelectedControl == 0)
+ {
+ uint8_t musicVolume = settingsManager::getMusicVolume();
+ musicVolume = (musicVolume >= 100) ? 0 : (musicVolume + 5);
+ settingsManager::setMusicVolume(musicVolume);
+ return;
+ }
+
+ if (mSelectedControl == 1)
+ {
+ uint8_t soundVolume = settingsManager::getSoundVolume();
+ soundVolume = (soundVolume >= 100) ? 0 : (soundVolume + 5);
+ settingsManager::setSoundVolume(soundVolume);
+ return;
+ }
+
+ if (mSelectedControl == 2)
+ {
+ bool vgaEnable = settingsManager::getVgaEnable();
+ settingsManager::setVgaEnable(!vgaEnable);
+ return;
+ }
+ }
+}
+
+void audioVideoOptionsScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Audio/Video Options...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ char* musicVolume = stringUtility::formatString("Music Volume: %i%%", settingsManager::getMusicVolume());
+ char* soundVolume = stringUtility::formatString("Sound Volume: %i%%", settingsManager::getSoundVolume());
+ char* vgaEnable = stringUtility::formatString("VGA Enabled: %s", settingsManager::getVgaEnable() == true ? "Yes" : "No");
+
+ pointerVector* menuItems = new pointerVector(false);
+ menuItems->add(strdup(musicVolume));
+ menuItems->add(strdup(soundVolume));
+ menuItems->add(strdup(vgaEnable));
+
+ int32_t maxItems = 7;
+
+ int32_t start = 0;
+ if ((int32_t)menuItems->count() >= maxItems)
+ {
+ start = min(max(mSelectedControl - (maxItems / 2), 0), (int32_t)menuItems->count() - maxItems);
+ }
+
+ int32_t itemCount = min(start + maxItems, (int32_t)menuItems->count()) - start;
+ if (itemCount > 0)
+ {
+ uint32_t yPos = (context::getBufferHeight() - ((itemCount * 40) - 10)) / 2;
+ yPos += theme::getCenterOffset();
+
+ for (int32_t i = 0; i < itemCount; i++)
+ {
+ uint32_t index = start + i;
+ char* menuText = menuItems->get(index);
+ component::button(mSelectedControl == index, false, menuText, 193, yPos, 322, 30);
+ yPos += 40;
+ }
+ }
+
+ free(vgaEnable);
+ free(soundVolume);
+ free(musicVolume);
+
+ delete(menuItems);
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA3\xC2\xA4 or \xC2\xB2\xC2\xB3 Change Value", theme::getFooterTextColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/audioVideoOptionsScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/audioVideoOptionsScene.h
new file mode 100644
index 0000000..3dd12dc
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/audioVideoOptionsScene.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "scene.h"
+#include "sceneManager.h"
+
+class audioVideoOptionsScene : public scene
+{
+public:
+ audioVideoOptionsScene();
+ void update();
+ void render();
+private:
+ int mSelectedControl;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/autoBootScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/autoBootScene.cpp
new file mode 100644
index 0000000..5a0a68e
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/autoBootScene.cpp
@@ -0,0 +1,107 @@
+#include "autoBootScene.h"
+#include "sceneManager.h"
+#include "mainScene.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxConfig.h"
+#include "..\theme.h"
+#include "..\driveManager.h"
+#include "..\Threads\countdown.h"
+
+autoBootScene::autoBootScene()
+{
+ utils::setLedStates(SMC_LED_STATES_RED_STATE0 | SMC_LED_STATES_RED_STATE1 | SMC_LED_STATES_RED_STATE2 | SMC_LED_STATES_RED_STATE3);
+ countdown::startThread(settingsManager::getAutoBootDelay() * 1000);
+}
+
+void autoBootScene::update()
+{
+ uint32_t trayState = 0;
+ uint32_t ejectCount = 0x11223344;
+ HalReadSMCTrayState(&trayState, &ejectCount);
+ bool safeMode = (trayState == SMC_TRAY_STATE_UNLOADING || ejectCount > 0);
+
+ // Exit Action
+
+ if (inputManager::buttonPressed(ButtonA))
+ {
+ continueBoot();
+ }
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ safeMode = true;
+ }
+
+ if (safeMode == true)
+ {
+ countdown::closeThread();
+ HalWriteSMBusByte(SMC_SLAVE_ADDRESS, 0x0C, 1);
+
+ utils::setLedStates(SMC_LED_STATES_GREEN_STATE0 | SMC_LED_STATES_GREEN_STATE1 | SMC_LED_STATES_GREEN_STATE2 | SMC_LED_STATES_GREEN_STATE3);
+ sceneManager::popScene();
+ }
+}
+
+void autoBootScene::render()
+{
+ pointerVector* banks = settingsManager::getBankInfos();
+
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Auto booting...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ int yPos = (context::getBufferHeight() - (40 + 44)) / 2;
+ yPos += theme::getCenterOffset();
+
+ for (uint32_t i = 0; i < banks->count(); i++)
+ {
+ bankDetails* bank = banks->get(i);
+ if (bank->autoBoot == false)
+ {
+ continue;
+ }
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), bank->name, theme::getTextColor(), horizAlignmentCenter, 40, yPos, 640);
+ }
+
+ yPos += 40;
+
+ char* progress = stringUtility::formatString("Booting in %.1f seconds", countdown::getTimeRemaining() / 1000.0f);
+ component::textBox(progress, false, false, horizAlignmentCenter, 193, yPos, 322, 44);
+ free(progress);
+
+ delete(banks);
+
+ if (countdown::getTimeRemaining() == 0)
+ {
+ continueBoot();
+ }
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Continue", theme::getFooterTextColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Cancel", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
+
+void autoBootScene::continueBoot() {
+ countdown::closeThread();
+
+ pointerVector* banks = settingsManager::getBankInfos();
+
+ for (uint32_t i = 0; i < banks->count(); i++)
+ {
+ bankDetails* bank = banks->get(i);
+ if (bank->slots > 0 && bank->autoBoot == true)
+ {
+ utils::setLedStates(SMC_LED_STATES_GREEN_STATE0 | SMC_LED_STATES_GREEN_STATE1 | SMC_LED_STATES_GREEN_STATE2 | SMC_LED_STATES_GREEN_STATE3);
+ settingsManager::launchBank(bank->id);
+ break;
+ }
+ }
+
+ delete(banks);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/autoBootScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/autoBootScene.h
new file mode 100644
index 0000000..288e0c4
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/autoBootScene.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "scene.h"
+
+class autoBootScene : public scene
+{
+public:
+ autoBootScene();
+ void update();
+ void render();
+ void continueBoot();
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/backupEepromScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/backupEepromScene.cpp
new file mode 100644
index 0000000..9662a3d
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/backupEepromScene.cpp
@@ -0,0 +1,91 @@
+#include "backupEepromScene.h"
+#include "sceneManager.h"
+#include "mainScene.h"
+#include "removeScene.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxConfig.h"
+#include "..\theme.h"
+#include "..\fileSystem.h"
+#include "..\XKUtils\XKEEPROM.h"
+
+backupEepromScene::backupEepromScene()
+{
+ mProgress = strdup("Ready");
+ mDone = false;
+}
+
+backupEepromScene::~backupEepromScene()
+{
+ free(mProgress);
+}
+
+void backupEepromScene::update()
+{
+ // Exit Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene();
+ return;
+ }
+
+ // Select Actions
+
+ if (inputManager::buttonPressed(ButtonA) && mDone == false)
+ {
+ free(mProgress);
+ if (fileSystem::directoryCreate("HDD0-E:\\PrometheOS") == true && fileSystem::directoryCreate("HDD0-E:\\PrometheOS\\Backup") == true && fileSystem::directoryCreate("HDD0-E:\\PrometheOS\\Backup\\EEPROMs") == true)
+ {
+ XKEEPROM* eeprom = new XKEEPROM();
+ eeprom->ReadFromXBOX();
+ char* serialString = xboxConfig::getSerialString();
+ char* versionString = xboxConfig::getXboxVersionString();
+ char* fileVersionString = stringUtility::replace(versionString, "/", "-");
+ char* filePath = stringUtility::formatString("HDD0-E:\\PrometheOS\\Backup\\EEPROMs\\%s %s.bin", fileVersionString, serialString);
+ if (eeprom->WriteToBINFile(filePath) == true)
+ {
+ mProgress = strdup("Backup completed");
+ }
+ else
+ {
+ mProgress = strdup("Backup failed");
+ }
+ delete(eeprom);
+ }
+ else
+ {
+ mProgress = strdup("Backup failed");
+ }
+ mDone = true;
+ }
+}
+
+void backupEepromScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Backup EEPROM...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ int yPos = (context::getBufferHeight() - (40 + 44)) / 2;
+ yPos += theme::getCenterOffset();
+
+ drawing::drawBitmapString(context::getBitmapFontMedium(), "Status", theme::getHeaderTextColor(), 193, yPos);
+
+ yPos += 40;
+
+ component::textBox(mProgress, false, false, horizAlignmentCenter, 193, yPos, 322, 44);
+
+ if (mDone == false)
+ {
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Backup", theme::getFooterTextColor(), 40, theme::getFooterY());
+ }
+
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/backupEepromScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/backupEepromScene.h
new file mode 100644
index 0000000..3ceecf5
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/backupEepromScene.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "scene.h"
+
+class backupEepromScene : public scene
+{
+public:
+ backupEepromScene();
+ ~backupEepromScene();
+ void update();
+ void render();
+private:
+ char* mProgress;
+ bool mDone;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/bootOptionsScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/bootOptionsScene.cpp
new file mode 100644
index 0000000..17dba06
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/bootOptionsScene.cpp
@@ -0,0 +1,166 @@
+#include "bootOptionsScene.h"
+#include "sceneManager.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxConfig.h"
+#include "..\theme.h"
+#include "..\fileSystem.h"
+
+bootOptionsScene::bootOptionsScene()
+{
+ mSelectedControl = 0;
+}
+
+void bootOptionsScene::update()
+{
+ // Exit Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene();
+ return;
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ mSelectedControl = mSelectedControl < 1 ? mSelectedControl + 1 : 0;
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : 1;
+ }
+
+ // Left Trigger
+
+ if (inputManager::buttonPressed(ButtonTriggerLeft) || inputManager::buttonPressed(ButtonX))
+ {
+ if (mSelectedControl == 0)
+ {
+ uint8_t splshDelay = settingsManager::getSplashDelay();
+ if (splshDelay > 0)
+ {
+ splshDelay--;
+ }
+ else
+ {
+ splshDelay = 15;
+ }
+ settingsManager::setSplashDelay(splshDelay);
+ return;
+ }
+
+ if (mSelectedControl == 1)
+ {
+ uint8_t autoBootDelay = settingsManager::getAutoBootDelay();
+ if (autoBootDelay > 5)
+ {
+ autoBootDelay -= 5;
+ }
+ else if (autoBootDelay > 0)
+ {
+ autoBootDelay--;
+ }
+ else
+ {
+ autoBootDelay = 30;
+ }
+ settingsManager::setAutoBootDelay(autoBootDelay);
+ return;
+ }
+ }
+
+ // Right Trigger
+
+ if (inputManager::buttonPressed(ButtonTriggerRight) || inputManager::buttonPressed(ButtonY))
+ {
+ if (mSelectedControl == 0)
+ {
+ uint8_t splashDelay = settingsManager::getSplashDelay();
+ if (splashDelay >= 15)
+ {
+ splashDelay = 0;
+ }
+ else
+ {
+ splashDelay++;
+ }
+ settingsManager::setSplashDelay(splashDelay);
+ return;
+ }
+
+ if (mSelectedControl == 1)
+ {
+ uint8_t autoBootDelay = settingsManager::getAutoBootDelay();
+ if (autoBootDelay >= 30)
+ {
+ autoBootDelay = 0;
+ }
+ else if (autoBootDelay >= 5)
+ {
+ autoBootDelay += 5;
+ }
+ else
+ {
+ autoBootDelay++;
+ }
+ settingsManager::setAutoBootDelay(autoBootDelay);
+ return;
+ }
+ }
+}
+
+void bootOptionsScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Boot Options...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ char* splashDelay = stringUtility::formatString("Splash Boot Delay: %i Seconds", settingsManager::getSplashDelay());
+ char* autoBootDelay = stringUtility::formatString("Auto Boot Delay: %i Seconds", settingsManager::getAutoBootDelay());
+
+ pointerVector* menuItems = new pointerVector(false);
+ menuItems->add(strdup(splashDelay));
+ menuItems->add(strdup(autoBootDelay));
+
+ int32_t maxItems = 7;
+
+ int32_t start = 0;
+ if ((int32_t)menuItems->count() >= maxItems)
+ {
+ start = min(max(mSelectedControl - (maxItems / 2), 0), (int32_t)menuItems->count() - maxItems);
+ }
+
+ int32_t itemCount = min(start + maxItems, (int32_t)menuItems->count()) - start;
+ if (itemCount > 0)
+ {
+ uint32_t yPos = (context::getBufferHeight() - ((itemCount * 40) - 10)) / 2;
+ yPos += theme::getCenterOffset();
+
+ for (int32_t i = 0; i < itemCount; i++)
+ {
+ uint32_t index = start + i;
+ char* menuText = menuItems->get(index);
+ component::button(mSelectedControl == index, false, menuText, 193, yPos, 322, 30);
+ yPos += 40;
+ }
+ }
+
+ free(autoBootDelay);
+ free(splashDelay);
+
+ delete(menuItems);
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA3\xC2\xA4 or \xC2\xB2\xC2\xB3 Change Value", theme::getFooterTextColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/bootOptionsScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/bootOptionsScene.h
new file mode 100644
index 0000000..a402338
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/bootOptionsScene.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "scene.h"
+#include "sceneManager.h"
+
+class bootOptionsScene : public scene
+{
+public:
+ bootOptionsScene();
+ void update();
+ void render();
+private:
+ int mSelectedControl;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/cerbiosIniEditorScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/cerbiosIniEditorScene.cpp
new file mode 100644
index 0000000..4ca8b40
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/cerbiosIniEditorScene.cpp
@@ -0,0 +1,718 @@
+#include "cerbiosIniEditorScene.h"
+#include "keyboardScene.h"
+#include "frontLedSelectorScene.h"
+#include "sceneManager.h"
+#include "scene.h"
+#include "filePickerScene.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxConfig.h"
+#include "..\theme.h"
+#include "..\fileSystem.h"
+#include "..\cerbiosIniHelper.h"
+
+void cerbiosIniEditorScene::onPathClosingCallback(sceneResult result, void* context, scene* scene)
+{
+ cerbiosIniEditorScene* self = (cerbiosIniEditorScene*)context;
+ if (result == sceneResultCancelled)
+ {
+ self->mShowingFilePicker = false;
+ return;
+ }
+
+ char* path = NULL;
+
+ if(self->mShowingFilePicker) {
+ self->mShowingFilePicker = false;
+ self->mNeedsSave = true;
+ filePickerScene* closingScene = (filePickerScene*)scene;
+ path = closingScene->getFilePath();
+ }
+ else
+ {
+ keyboardScene* closingScene = (keyboardScene*)scene;
+ path = closingScene->getText();
+ }
+
+ if (self->mSelectedControl == 3)
+ {
+ strcpy(self->mConfig.CdPath1, path);
+ free(self->mShortCdPath1);
+ self->mShortCdPath1 = self->shortenString(path);
+ }
+ else if (self->mSelectedControl == 4)
+ {
+ strcpy(self->mConfig.CdPath2, path);
+ free(self->mShortCdPath2);
+ self->mShortCdPath2 = self->shortenString(path);
+ }
+ else if (self->mSelectedControl == 5)
+ {
+ strcpy(self->mConfig.CdPath3, path);
+ free(self->mShortCdPath3);
+ self->mShortCdPath3 = self->shortenString(path);
+ }
+ else if (self->mSelectedControl == 6)
+ {
+ strcpy(self->mConfig.DashPath1, path);
+ free(self->mShortDashPath1);
+ self->mShortDashPath1 = self->shortenString(path);
+ }
+ else if (self->mSelectedControl == 7)
+ {
+ strcpy(self->mConfig.DashPath2, path);
+ free(self->mShortDashPath2);
+ self->mShortDashPath2 = self->shortenString(path);
+ }
+ else if (self->mSelectedControl == 8)
+ {
+ strcpy(self->mConfig.DashPath3, path);
+ free(self->mShortDashPath3);
+ self->mShortDashPath3 = self->shortenString(path);
+ }
+ else if (self->mSelectedControl == 9)
+ {
+ strcpy(self->mConfig.BootAnimPath, path);
+ free(self->mShortBootAnimPath);
+ self->mShortBootAnimPath = self->shortenString(path);
+ }
+
+ free(path);
+}
+
+void cerbiosIniEditorScene::onFrontLedClosingCallback(sceneResult result, void* context, scene* scene)
+{
+ cerbiosIniEditorScene* self = (cerbiosIniEditorScene*)context;
+ if (result == sceneResultCancelled)
+ {
+ return;
+ }
+
+ frontLedSelectorScene* closingScene = (frontLedSelectorScene*)scene;
+ char* ledSequence = closingScene->getLedSequence();
+ self->mConfig.FrontLed[0] = ledSequence[0];
+ self->mConfig.FrontLed[1] = ledSequence[1];
+ self->mConfig.FrontLed[2] = ledSequence[2];
+ self->mConfig.FrontLed[3] = ledSequence[3];
+ free(ledSequence);
+}
+
+cerbiosIniEditorScene::cerbiosIniEditorScene()
+{
+ mConfig = cerbiosIniHelper::loadConfig();
+ mConfig.FanSpeed = mConfig.FanSpeed;
+ mShortCdPath1 = shortenString(mConfig.CdPath1);
+ mShortCdPath2 = shortenString(mConfig.CdPath2);
+ mShortCdPath3 = shortenString(mConfig.CdPath3);
+ mShortDashPath1 = shortenString(mConfig.DashPath1);
+ mShortDashPath2 = shortenString(mConfig.DashPath2);
+ mShortDashPath3 = shortenString(mConfig.DashPath3);
+ mShortBootAnimPath = shortenString(mConfig.BootAnimPath);
+ mSelectedControl = 0;
+ mHasFilePicker = false;
+ mNeedsSave = false;
+ mShowingFilePicker = false;
+ mShowingInfo = false;
+ mMaxOptionCount = 18;
+}
+
+cerbiosIniEditorScene::~cerbiosIniEditorScene()
+{
+ free(mShortCdPath1);
+ free(mShortCdPath2);
+ free(mShortCdPath3);
+ free(mShortDashPath1);
+ free(mShortDashPath2);
+ free(mShortDashPath3);
+ free(mShortBootAnimPath);
+}
+
+void cerbiosIniEditorScene::update()
+{
+ // Exit Action
+
+ if(mShowingInfo) {
+ if (inputManager::buttonPressed(ButtonB)) {
+ mShowingInfo = false;
+ }
+ return;
+ }
+
+ if (inputManager::buttonPressed(ButtonBlack)) {
+ mShowingInfo = true;
+ return;
+ }
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene();
+ return;
+ }
+
+ // Defaults Actions
+
+ if (inputManager::buttonPressed(ButtonY))
+ {
+ cerbiosIniHelper::setConfigDefault(&mConfig);
+ mNeedsSave = true;
+ }
+
+ // Save Actions
+
+ if (mNeedsSave == true && inputManager::buttonPressed(ButtonX))
+ {
+ char* buffer = (char*)malloc(65536);
+ cerbiosIniHelper::buildConfig(&mConfig, buffer);
+ cerbiosIniHelper::saveConfig(buffer);
+ free(buffer);
+ mNeedsSave = false;
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ mSelectedControl = mSelectedControl < mMaxOptionCount ? mSelectedControl + 1 : 0;
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : mMaxOptionCount;
+ }
+
+ // Left Trigger
+
+ if (inputManager::buttonPressed(ButtonA) || inputManager::buttonPressed(ButtonTriggerLeft))
+ {
+ if (mSelectedControl == 0)
+ {
+ mConfig.DriveSetup = (mConfig.DriveSetup > 0) ? (mConfig.DriveSetup - 1) : 3;
+ }
+ else if (mSelectedControl == 1)
+ {
+ mConfig.AVCheck = (mConfig.AVCheck == 0) ? 1 : 0;
+ }
+ else if (mSelectedControl == 2)
+ {
+ mConfig.Debug = (mConfig.Debug == 0) ? 1 : 0;
+ }
+ else if (mSelectedControl == 3)
+ {
+ sceneManager::pushScene(new sceneContainer(sceneItemGenericScene, new keyboardScene(99, "Please enter path...", "CD Path 1:", mConfig.CdPath1), "", this, onPathClosingCallback));
+ }
+ else if (mSelectedControl == 4)
+ {
+ sceneManager::pushScene(new sceneContainer(sceneItemGenericScene, new keyboardScene(99, "Please enter path...", "CD Path 2:", mConfig.CdPath2), "", this, onPathClosingCallback));
+ }
+ else if (mSelectedControl == 5)
+ {
+ sceneManager::pushScene(new sceneContainer(sceneItemGenericScene, new keyboardScene(99, "Please enter path...", "CD Path 3:", mConfig.CdPath3), "", this, onPathClosingCallback));
+ }
+ else if (mSelectedControl == 6)
+ {
+ sceneManager::pushScene(new sceneContainer(sceneItemGenericScene, new keyboardScene(99, "Please enter path...", "Dash Path 1:", mConfig.DashPath1), "", this, onPathClosingCallback));
+ }
+ else if (mSelectedControl == 7)
+ {
+ sceneManager::pushScene(new sceneContainer(sceneItemGenericScene, new keyboardScene(99, "Please enter path...", "Dash Path 2:", mConfig.DashPath2), "", this, onPathClosingCallback));
+ }
+ else if (mSelectedControl == 8)
+ {
+ sceneManager::pushScene(new sceneContainer(sceneItemGenericScene, new keyboardScene(99, "Please enter path...", "Dash Path 3:", mConfig.DashPath3), "", this, onPathClosingCallback));
+ }
+ else if (mSelectedControl == 9)
+ {
+ sceneManager::pushScene(new sceneContainer(sceneItemGenericScene, new keyboardScene(99, "Please enter path...", "Boot Anim Path:", mConfig.BootAnimPath), "", this, onPathClosingCallback));
+ }
+ else if (mSelectedControl == 10)
+ {
+ sceneManager::pushScene(new sceneContainer(sceneItemGenericScene, new frontLedSelectorScene(mConfig.FrontLed), "", this, onFrontLedClosingCallback));
+ }
+ else if (mSelectedControl == 11)
+ {
+ mConfig.FanSpeed = (mConfig.FanSpeed > 0) ? (mConfig.FanSpeed - 10) : 100;
+ }
+ else if (mSelectedControl == 12)
+ {
+ mConfig.UdmaModeMaster = (mConfig.UdmaModeMaster > 0) ? (mConfig.UdmaModeMaster - 1) : 6;
+ }
+ else if (mSelectedControl == 13)
+ {
+ mConfig.UdmaModeSlave = (mConfig.UdmaModeSlave > 0) ? (mConfig.UdmaModeSlave - 1) : 6;
+ }
+ else if (mSelectedControl == 14)
+ {
+ mConfig.Force480p = (mConfig.Force480p == 0) ? 1 : 0;
+ }
+ else if (mSelectedControl == 15)
+ {
+ mConfig.ForceVGA = (mConfig.ForceVGA == 0) ? 1 : 0;
+ }
+ else if (mSelectedControl == 16)
+ {
+ mConfig.RtcEnable = (mConfig.RtcEnable == 0) ? 1 : 0;
+ }
+ else if (mSelectedControl == 17)
+ {
+ mConfig.BlockDashUpdate = (mConfig.BlockDashUpdate == 0) ? 1 : 0;
+ }
+ else if (mSelectedControl == 18)
+ {
+ mConfig.ResetOnEject = (mConfig.ResetOnEject == 0) ? 1 : 0;
+ }
+ mNeedsSave = true;
+ }
+
+ // Right Trigger
+
+ if (inputManager::buttonPressed(ButtonTriggerRight))
+ {
+ if (mSelectedControl == 0)
+ {
+ mConfig.DriveSetup = (mConfig.DriveSetup >= 3) ? 0 : (mConfig.DriveSetup + 1);
+ }
+ else if (mSelectedControl == 1)
+ {
+ mConfig.AVCheck = (mConfig.AVCheck == 0) ? 1 : 0;
+ }
+ else if (mSelectedControl == 2)
+ {
+ mConfig.Debug = (mConfig.Debug == 0) ? 1 : 0;
+ }
+ else if (mSelectedControl == 3)
+ {
+ sceneManager::pushScene(new sceneContainer(sceneItemGenericScene, new keyboardScene(99, "Please enter path...", "CD Path 1:", mConfig.CdPath1), "", this, onPathClosingCallback));
+ }
+ else if (mSelectedControl == 4)
+ {
+ sceneManager::pushScene(new sceneContainer(sceneItemGenericScene, new keyboardScene(99, "Please enter path...", "CD Path 2:", mConfig.CdPath2), "", this, onPathClosingCallback));
+ }
+ else if (mSelectedControl == 5)
+ {
+ sceneManager::pushScene(new sceneContainer(sceneItemGenericScene, new keyboardScene(99, "Please enter path...", "CD Path 3:", mConfig.CdPath3), "", this, onPathClosingCallback));
+ }
+ else if (mSelectedControl == 6)
+ {
+ sceneManager::pushScene(new sceneContainer(sceneItemGenericScene, new keyboardScene(99, "Please enter path...", "Dash Path 1:", mConfig.DashPath1), "", this, onPathClosingCallback));
+ }
+ else if (mSelectedControl == 7)
+ {
+ sceneManager::pushScene(new sceneContainer(sceneItemGenericScene, new keyboardScene(99, "Please enter path...", "Dash Path 2:", mConfig.DashPath2), "", this, onPathClosingCallback));
+ }
+ else if (mSelectedControl == 8)
+ {
+ sceneManager::pushScene(new sceneContainer(sceneItemGenericScene, new keyboardScene(99, "Please enter path...", "Dash Path 3:", mConfig.DashPath3), "", this, onPathClosingCallback));
+ }
+ else if (mSelectedControl == 9)
+ {
+ sceneManager::pushScene(new sceneContainer(sceneItemGenericScene, new keyboardScene(99, "Please enter path...", "Boot Anim Path:", mConfig.BootAnimPath), "", this, onPathClosingCallback));
+ }
+ else if (mSelectedControl == 10)
+ {
+ sceneManager::pushScene(new sceneContainer(sceneItemGenericScene, new frontLedSelectorScene(mConfig.FrontLed), "", this, onFrontLedClosingCallback));
+ }
+ else if (mSelectedControl == 11)
+ {
+ mConfig.FanSpeed = (mConfig.FanSpeed >= 100) ? 0 : (mConfig.FanSpeed + 10);
+ }
+ else if (mSelectedControl == 12)
+ {
+ mConfig.UdmaModeMaster = (mConfig.UdmaModeMaster >= 6) ? 0 : (mConfig.UdmaModeMaster + 1);
+ }
+ else if (mSelectedControl == 13)
+ {
+ mConfig.UdmaModeSlave = (mConfig.UdmaModeSlave >= 6) ? 0 : (mConfig.UdmaModeSlave + 1);
+ }
+ else if (mSelectedControl == 14)
+ {
+ mConfig.Force480p = (mConfig.Force480p == 0) ? 1 : 0;
+ }
+ else if (mSelectedControl == 15)
+ {
+ mConfig.ForceVGA = (mConfig.ForceVGA == 0) ? 1 : 0;
+ }
+ else if (mSelectedControl == 16)
+ {
+ mConfig.RtcEnable = (mConfig.RtcEnable == 0) ? 1 : 0;
+ }
+ else if (mSelectedControl == 17)
+ {
+ mConfig.BlockDashUpdate = (mConfig.BlockDashUpdate == 0) ? 1 : 0;
+ }
+ else if (mSelectedControl == 18)
+ {
+ mConfig.ResetOnEject = (mConfig.ResetOnEject == 0) ? 1 : 0;
+ }
+ mNeedsSave = true;
+ }
+
+ if (mHasFilePicker && inputManager::buttonPressed(ButtonWhite)) {
+ mShowingFilePicker = true;
+ sceneContainer* container = new sceneContainer(sceneItemGenericScene, new filePickerScene(filePickerTypeXbe, true, true), "", this, onPathClosingCallback);
+ sceneManager::pushScene(container);
+ }
+}
+
+char* cerbiosIniEditorScene::getOptionInfo(int selectedControl) {
+ char *infoStr;
+ switch(selectedControl) {
+ case 0: {
+ infoStr = "Drive Setup (DriveSetup):\n"
+ "\n"
+ "Xbox drive setup.\n"
+ "\n"
+ "0 = HDD & DVD - Stock setup, DVD drive must be connected or bios\n"
+ " will fail to boot.\n"
+ "1 = HDD & No DVD (Legacy) - Allows bios to boot if no DVD drive\n"
+ " is connected.\n"
+ "2 = HDD & No DVD (Modern) - Removes DVD drive detect code\n"
+ " entirely, bios boots faster. DVD drive no longer detected by apps.\n"
+ "3 = Dual HDD - Allows 2nd HDD to connected in-place of DVD\n"
+ " drive, HDD mode jumper must be set to slave.\n"
+ "Default = 1";
+ } break;
+
+ case 1: {
+ infoStr = "AV Check (AVCheck):\n"
+ "\n"
+ "Check for AV cable on bios boot. Flashes yellow and\n"
+ "green and halts system if no AV cable is connected.\n"
+ "\n"
+ "True = Check for AV cable on boot\n"
+ "False = Skip AV cable check on boot\n"
+ "Default = True";
+ } break;
+
+ case 2: {
+ infoStr = "Debug (Debug):\n"
+ "\n"
+ "Will check for and boot into C:\\xshell.xbe (XDK Launcher) and\n"
+ "allows to debug apps. Will look for and load E:\\xbdm.dll (enables\n"
+ "network communication with XDK on PC with Visual Studio).\n"
+ "\n"
+ "True = Allows booting into XDK Launcher and to debug apps.\n"
+ "False = Will not boot C:\\xshell.xbe and will not load E:\\xbdm.dll\n"
+ "Default = False";
+ } break;
+
+ case 3:
+ case 4:
+ case 5: {
+ infoStr = "CD Path 1/2/3 (CdPath1, CdPath2, CdPath3):\n"
+ "\n"
+ "List of XBEs to look for and load if a DVD disc is detected in\n"
+ "D: drive on bios boot. Will always fallback to D:\\default.xbe\n"
+ "\n"
+ "Default = (all blank)";
+ } break;
+
+ case 6:
+ case 7:
+ case 8: {
+ infoStr = "Dash Path 1/2/3 (DashPath1, DashPath2, DashPath3):\n"
+ "\n"
+ "List of dashboard XBEs to look for and load on bios boot. Since\n"
+ "Cerbios 2.4.2, allows dual-hdd prefixes (HDD0, HDD1), example:\n"
+ "HDD0-C:\\evoxdash.xbe. Will always fallback to C:\\xboxdash.xbe\n"
+ "\n"
+ "Defaults:\n"
+ " DashPath1 = C:\\evoxdash.xbe\n"
+ " DashPath2 = C:\\avalaunch.xbe\n"
+ " DashPath3 = C:\\nexgen.xbe";
+ } break;
+
+ case 9: {
+ infoStr = "Boot Anim Path (BootAnimPath):\n"
+ "\n"
+ "Optional splash animation that plays during bios boot.\n"
+ "Will always fallback to C:\\BootAnims\\Xbox\\BootAnim.xbe if found.\n"
+ "\n"
+ "Default = C:\\BootAnims\\Xbox\\BootAnim.xbe";
+ } break;
+
+ case 10: {
+ infoStr = "Front Led (FrontLed):\n"
+ "\n"
+ "Custom front eject button LED colors set during boot, split into\n"
+ "4 phases. The pattern will continue to cycle until another application\n"
+ "takes control of the LEDs.\n"
+ "LED Ring Color code: G = Green, R = Red, A = Amber, O = Off\n"
+ "\n"
+ "Default = GGGG";
+ } break;
+
+ case 11: {
+ infoStr = "Fan Speed (FanSpeed):\n"
+ "\n"
+ "Custom fan speed (in percent) set during boot.\n"
+ "0 = Auto, 10-100 = Manual Control, Supports increments of 10\n"
+ "\n"
+ "Default = 0";
+ } break;
+
+ case 12:
+ case 13: {
+ infoStr = "UDMA Mode (UdmaMode, UdmaModeMaster, UdmaModeSlave):\n"
+ "\n"
+ "Set HDD UDMA mode on boot. SATA adapters always require 80-Wire\n"
+ "IDE cable. Since Cerbios 2.4.2, also allows setting UDMA mode for the\n"
+ "slave HDD when DriveSetup = 3 (Dual HDD mode). Modes:\n"
+ "0 = Auto (Startech Adapter)\n"
+ "1 = Auto (Generic Adapter)\n"
+ "2 = UDMA 2 (Default / Stock)\n"
+ "3 = UDMA 3 (requires 80-Wire cable)\n"
+ "4 = UDMA 4 (requires 80-Wire cable)\n"
+ "5 = UDMA 5 (requires 80-Wire cable)\n"
+ "6 = UDMA 6 (requires 80-Wire cable, Experimental)\n"
+ "Default = 2";
+ } break;
+
+ case 14: {
+ infoStr = "Force 480p (Force480p):\n"
+ "\n"
+ "Force games and apps to use 480p HD video mode. Component cable\n"
+ "required. 720p and 1080i modes are unaffected. PAL AV modes also\n"
+ "unaffected. 480p option must be enabled in MS Dashboard. Only\n"
+ "supported on NTSC consoles.\n"
+ "\n"
+ "True = Force 480p option enabled\n"
+ "False = Stock setup, no forcing to 480p will happen\n"
+ "Default = False";
+ } break;
+
+ case 15: {
+ infoStr = "Force VGA (ForceVGA):\n"
+ "\n"
+ "Force games and apps to output VGA video signal (RGsB). An\n"
+ "appropriate cable or adapter is required and an appropriate\n"
+ "(SoG, Sync-on-Green) monitor is required, depending on the\n"
+ "cable used. This option automatically enables Force480p option.\n"
+ "1.6 revision consoles are unsupported.\n"
+ "\n"
+ "True = Force VGA video output\n"
+ "False = Stock setup, no forcing VGA output will happen\n"
+ "Default = False";
+ } break;
+
+ case 16: {
+ infoStr = "RTC Enable (RtcEnable):\n"
+ "\n"
+ "Enables automatic clock syncing with an appropriate external\n"
+ "battery-backed RTC module connected to the xbox's SMBUS.\n"
+ "Requires Cerbios 2.4.0 or higher, or PrometheOS 1.4.0 or higher.\n"
+ "Currently supported modules: DS3231\n"
+ "\n"
+ "True = Sync clock on bios boot\n"
+ "False = Stock setup, no clock syncing will happen\n"
+ "Default = False";
+ } break;
+
+ case 17: {
+ infoStr = "Block Dash Update (BlockDashUpdate):\n"
+ "\n"
+ "Prevents some XBL games from updating the MS Dashboard, which\n"
+ "can break softmod installs. Only really useful for softmods running\n"
+ "Cerbios 2.4.0 or higher in BFM mode.\n"
+ "\n"
+ "True = Dashboard update blocking enabled\n"
+ "False = Stock setup, no blocking will occur\n"
+ "Default = False";
+ } break;
+
+ case 18: {
+ infoStr = "Reset on Eject (ResetOnEject):\n"
+ "\n"
+ "Restores orignal stock functionality of resetting the xbox when the\n"
+ "DVD tray is ejected. This will reload your choosen dashboard.\n"
+ "\n"
+ "True = Stock reset functionality enabled\n"
+ "False = Ignores reset command when the tray is eject\n"
+ "Default = False";
+ } break;
+
+ default: {
+ infoStr = "NO INFO AVAILABLE FOR THIS OPTION";
+ }
+ }
+ return infoStr;
+}
+
+void cerbiosIniEditorScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Cerbios INI Editor...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ const char* driveModes[] = { "HDD & DVD", "HDD & No DVD (Legacy)", "HDD & No DVD (Modern)", "Dual HDD" };
+ const char* bools[] = { "False", "True" };
+ const char* udmaModes[] = { "Auto (Startech Adapter)", "Auto (Generic Adapter)", "UDMA 2 (Default / Stock)", "UDMA 3 (Ultra DMA 80-Conductor)", "UDMA 4 (Ultra DMA 80-Conductor)", "UDMA 5 (Ultra DMA 80-Conductor)", "UDMA 6 (Experimental)" };
+ const char* fanSpeeds[] = { "Auto", "10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%" };
+
+ int32_t maxItems = 7;
+ int32_t menuItems = mMaxOptionCount + 1;
+
+ int32_t start = 0;
+ if (menuItems >= maxItems)
+ {
+ start = min(max(mSelectedControl - (maxItems / 2), 0), menuItems - maxItems);
+ }
+
+ int32_t itemCount = min(start + maxItems, menuItems) - start;
+ if (itemCount > 0)
+ {
+ uint32_t yPos = (context::getBufferHeight() - ((itemCount * 40) - 10)) / 2;
+ yPos += theme::getCenterOffset();
+
+ for (int32_t i = 0; i < itemCount; i++)
+ {
+ uint32_t index = start + i;
+ if (index == 0)
+ {
+ component::splitButton(mSelectedControl == index, false, "Drive Setup:", 165, driveModes[mConfig.DriveSetup], 40, yPos, 640, 30);
+ }
+ else if (index == 1)
+ {
+ component::splitButton(mSelectedControl == index, false, "AV Check:", 165, bools[mConfig.AVCheck], 40, yPos, 640, 30);
+ }
+ else if (index == 2)
+ {
+ component::splitButton(mSelectedControl == index, false, "Debug:", 165, bools[mConfig.Debug], 40, yPos, 640, 30);
+ }
+ else if (index == 3)
+ {
+ component::splitButton(mSelectedControl == index, false, "CD Path 1:", 165, mShortCdPath1, 40, yPos, 640, 30);
+ }
+ else if (index == 4)
+ {
+ component::splitButton(mSelectedControl == index, false, "CD Path 2:", 165, mShortCdPath2, 40, yPos, 640, 30);
+ }
+ else if (index == 5)
+ {
+ component::splitButton(mSelectedControl == index, false, "CD Path 3:", 165, mShortCdPath3, 40, yPos, 640, 30);
+ }
+ else if (index == 6)
+ {
+ component::splitButton(mSelectedControl == index, false, "Dash Path 1:", 165, mShortDashPath1, 40, yPos, 640, 30);
+ }
+ else if (index == 7)
+ {
+ component::splitButton(mSelectedControl == index, false, "Dash Path 2:", 165, mShortDashPath2, 40, yPos, 640, 30);
+ }
+ else if (index == 8)
+ {
+ component::splitButton(mSelectedControl == index, false, "Dash Path 3:", 165, mShortDashPath3, 40, yPos, 640, 30);
+ }
+ else if (index == 9)
+ {
+ component::splitButton(mSelectedControl == index, false, "Boot Anim Path:", 165, mShortBootAnimPath, 40, yPos, 640, 30);
+ }
+ else if (index == 10)
+ {
+ component::splitButton(mSelectedControl == index, false, "Front Led:", 165, mConfig.FrontLed, 40, yPos, 640, 30);
+ }
+ else if (index == 11)
+ {
+ component::splitButton(mSelectedControl == index, false, "Fan Speed:", 165, fanSpeeds[mConfig.FanSpeed / 10], 40, yPos, 640, 30);
+ }
+ else if (index == 12)
+ {
+ component::splitButton(mSelectedControl == index, false, "Udma Master:", 165, udmaModes[mConfig.UdmaModeMaster], 40, yPos, 640, 30);
+ }
+ else if (index == 13)
+ {
+ component::splitButton(mSelectedControl == index, false, "Udma Slave:", 165, udmaModes[mConfig.UdmaModeSlave], 40, yPos, 640, 30);
+ }
+ else if (index == 14)
+ {
+ component::splitButton(mSelectedControl == index, false, "Force 480p:", 165, bools[mConfig.Force480p], 40, yPos, 640, 30);
+ }
+ else if (index == 15)
+ {
+ component::splitButton(mSelectedControl == index, false, "Force VGA:", 165, bools[mConfig.ForceVGA], 40, yPos, 640, 30);
+ }
+ else if (index == 16)
+ {
+ component::splitButton(mSelectedControl == index, false, "Rtc Enable:", 165, bools[mConfig.RtcEnable], 40, yPos, 640, 30);
+ }
+ else if (index == 17)
+ {
+ component::splitButton(mSelectedControl == index, false, "Block Dash Update:", 165, bools[mConfig.BlockDashUpdate], 40, yPos, 640, 30);
+ }
+ else if (index == 18)
+ {
+ component::splitButton(mSelectedControl == index, false, "Reset On Eject:", 165, bools[mConfig.ResetOnEject], 40, yPos, 640, 30);
+ }
+
+ yPos += 40;
+ }
+ }
+
+ mHasFilePicker = false;
+ switch(mSelectedControl) {
+ case 3: case 4: case 5:
+ case 6: case 7: case 8:
+ case 9: {
+ mHasFilePicker = true;
+ } break;
+ }
+
+ uint32_t yPos = (context::getBufferHeight() - ((itemCount * 40) - 10)) / 2;
+ yPos += theme::getCenterOffset();
+
+ if(mShowingInfo) {
+ char *infoStr = getOptionInfo(mSelectedControl);
+ component::textBox(infoStr, true, false, horizAlignmentLeft, 60, yPos + 5, 600, 260, true, true);
+ }
+
+ if(!mShowingInfo) {
+ const char* baseBtns = "\xC2\xA1 or \xC2\xB2\xC2\xB3 Change Value, \xC2\xA4 Defaults";
+ const char* filePkrBtn = ", \xC2\xB5 Browse";
+ const char* saveBtn = ", \xC2\xA3 Save";
+
+ char* buttons = stringUtility::formatString(
+ "%s%s%s",
+ baseBtns,
+ mHasFilePicker ? filePkrBtn : "",
+ mNeedsSave ? saveBtn : ""
+ );
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), buttons, theme::getFooterTextColor(), 40, theme::getFooterY());
+ free(buttons);
+ }
+
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), mShowingInfo ? "\xC2\xA2 Back" : "\xC2\xB6 Info \xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
+
+char* cerbiosIniEditorScene::shortenString(const char* value)
+{
+ int textWidth;
+ int textHeight;
+ drawing::measureBitmapString(context::getBitmapFontSmall(), value, &textWidth, &textHeight);
+
+ char* temp = strdup(value);
+
+ int maxWidth = (640 - 165) - 20;
+ if (textWidth >= maxWidth)
+ {
+ for (int i = 0; i < (int)strlen(value); i++)
+ {
+ free(temp);
+ temp = stringUtility::formatString("...%s", value + i);
+ drawing::measureBitmapString(context::getBitmapFontSmall(), temp, &textWidth, &textHeight);
+ if (textWidth < maxWidth)
+ {
+ break;
+ }
+ }
+ }
+
+ return temp;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/cerbiosIniEditorScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/cerbiosIniEditorScene.h
new file mode 100644
index 0000000..c72408f
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/cerbiosIniEditorScene.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include "scene.h"
+#include "sceneManager.h"
+
+#include "..\cerbiosIniHelper.h"
+
+class cerbiosIniEditorScene : public scene
+{
+public:
+ cerbiosIniEditorScene();
+ ~cerbiosIniEditorScene();
+ void update();
+ void render();
+ char* shortenString(const char* value);
+private:
+ int mSelectedControl;
+ int mMaxOptionCount;
+ bool mNeedsSave;
+ bool mHasFilePicker;
+ bool mShowingFilePicker;
+ bool mShowingInfo;
+ cerbiosConfig mConfig;
+ char* mShortCdPath1;
+ char* mShortCdPath2;
+ char* mShortCdPath3;
+ char* mShortDashPath1;
+ char* mShortDashPath2;
+ char* mShortDashPath3;
+ char* mShortBootAnimPath;
+ char* getOptionInfo(int selectedControl);
+ static void onPathClosingCallback(sceneResult result, void* context, scene* scene);
+ static void onFrontLedClosingCallback(sceneResult result, void* context, scene* scene);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/dlcSignerScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/dlcSignerScene.cpp
new file mode 100644
index 0000000..a678a22
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/dlcSignerScene.cpp
@@ -0,0 +1,756 @@
+#include "dlcSignerScene.h"
+#include "sceneManager.h"
+#include "filePickerScene.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxInternals.h"
+#include "..\driveManager.h"
+#include "..\fileSystem.h"
+#include "..\theme.h"
+#include "..\Threads\driveMounter.h"
+
+#define XBEBaseAddress 0x00010000
+#define XBEMagic 0x58424548
+#define XCSFMagic 0x46534358
+#define SHA_CONTEXT_SIZE 116
+#define SHA_DIGEST_SIZE 20
+
+dlcSignerScene::dlcSignerScene()
+{
+ driveMounter::startThread(false);
+
+ mCurrentSceneId = 0;
+ mSearchResults = new pointerVector(true);
+ mFilesFound = 0;
+}
+
+dlcSignerScene::~dlcSignerScene()
+{
+ freeSearchResults(mSearchResults);
+ delete(mSearchResults);
+}
+
+void dlcSignerScene::update()
+{
+ if (mCurrentSceneId == 0)
+ {
+ if (driveMounter::completed() == true)
+ {
+ driveMounter::closeThread();
+ mCurrentSceneId = 1;
+ return;
+ }
+ return;
+ }
+
+ if (mCurrentSceneId == 1)
+ {
+ BOOL searchSucceeded = searchContentMetaFiles(mFilesFound, mSearchResults);
+ mCurrentSceneId = searchSucceeded ? 2 : 5;
+ return;
+ }
+
+ if (mCurrentSceneId == 2)
+ {
+ if (inputManager::buttonPressed(ButtonA))
+ {
+ mOnlySignIfInvalid = FALSE;
+ mCurrentSceneId = 3;
+ signContent(mSearchResults);
+ return;
+ }
+
+ if (inputManager::buttonPressed(ButtonY))
+ {
+ mOnlySignIfInvalid = TRUE;
+ mCurrentSceneId = 3;
+ signContent(mSearchResults);
+ return;
+ }
+ }
+
+ if (mCurrentSceneId == 3)
+ {
+ mCurrentSceneId = 4;
+ }
+
+ // Back Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene();
+ return;
+ }
+}
+
+void dlcSignerScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "DLC / Update Signer...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+
+ int yPos = (context::getBufferHeight() - (40 + 44)) / 2;
+ yPos += theme::getCenterOffset();
+
+ drawing::drawBitmapString(context::getBitmapFontMedium(), "Status", theme::getHeaderTextColor(), 40, yPos);
+
+ yPos += 40;
+
+ bool showContinue = false;
+ if (mCurrentSceneId == 0)
+ {
+ component::textBox("Mounting Drives...", false, false, horizAlignmentCenter, 40, yPos, 640, 44);
+ }
+ else if (mCurrentSceneId == 1)
+ {
+ component::textBox("Scanning...", false, false, horizAlignmentCenter, 40, yPos, 640, 44);
+ }
+ else if (mCurrentSceneId == 2)
+ {
+ if (mSearchResults->count() > 0)
+ {
+ char* progress = stringUtility::formatString("Found %d folders containing a total of %d content packages.", mSearchResults->count(), mFilesFound);
+ component::textBox(progress, false, false, horizAlignmentCenter, 40, yPos, 640, 44);
+ free(progress);
+ }
+ else
+ {
+ component::textBox("Search completed. No content packages found", false, false, horizAlignmentCenter, 40, yPos, 640, 44);
+ }
+ }
+ else if (mCurrentSceneId == 3)
+ {
+ component::textBox("Signing...", false, false, horizAlignmentCenter, 40, yPos, 640, 44);
+ }
+ else if (mCurrentSceneId == 4)
+ {
+ char* progress = stringUtility::formatString("Signing complete. %d files signed, %d failed, %d skipped", mNumFilesSigned, mNumFilesFailed, mNumFilesSkipped);
+ component::textBox(progress, false, false, horizAlignmentCenter, 40, yPos, 640, 44);
+ free(progress);
+ }
+ else if (mCurrentSceneId == 5)
+ {
+ component::textBox("Failed", false, false, horizAlignmentCenter, 40, yPos, 640, 44);
+ }
+
+ if (mCurrentSceneId == 2 && mSearchResults->count() > 0)
+ {
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Sign All, \xC2\xA4 Sign Only Invalid", theme::getFooterTextColor(), 40, theme::getFooterY());
+ }
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+
+}
+
+void dlcSignerScene::signContent(pointerVector* SearchResults)
+{
+ BOOL Error_FileAccess = FALSE;
+ BOOL Error_BadFileSize = FALSE;
+ BOOL Error_BadHeaderSize = FALSE;
+ BOOL Error_BadMagic = FALSE;
+
+ BOOL Warn_SkippedBecauseValid = FALSE;
+ BOOL Warn_IsSimpleContent = FALSE;
+
+ mNumFilesSigned = 0;
+ mNumFilesFailed = 0;
+ mNumFilesSkipped = 0;
+ mWarningSimpleContentFiles = 0;
+
+ const PCHAR TitleDataRegion = "T:\\"; //symlink of TitleId specific TDATA folder
+ const PCHAR UserDataRegion = "U:\\"; //symlink of TitleId specific UDATA folder
+
+ for(DWORD SearchResultIndex = 0; SearchResultIndex < SearchResults->count(); SearchResultIndex++) {
+
+ SearchResult* CurrentSearchResult = SearchResults->get(SearchResultIndex);
+ if (CurrentSearchResult->FileCount == 0)
+ continue;
+
+ setAlternateTitleId(CurrentSearchResult->TitleId);
+
+ CHAR AlternateTitleDriveLetter = { 0 };
+ XMountAlternateTitle(TitleDataRegion, CurrentSearchResult->TitleId, &AlternateTitleDriveLetter);
+
+ for(DWORD FileIndex = 0; FileIndex < CurrentSearchResult->Files->count(); FileIndex++) {
+
+ PCHAR CurrentFile = CurrentSearchResult->Files->get(FileIndex);
+
+ if (!signContentMeta(CurrentFile, CurrentSearchResult->TitleId, mOnlySignIfInvalid,
+ Error_FileAccess, Error_BadFileSize, Error_BadHeaderSize, Error_BadMagic, Warn_SkippedBecauseValid, Warn_IsSimpleContent))
+ {
+ if (Error_FileAccess || Error_BadFileSize || Error_BadHeaderSize || Error_BadMagic)
+ mNumFilesFailed++;
+
+ if (Warn_SkippedBecauseValid)
+ mNumFilesSkipped++;
+
+ }
+ else
+ {
+
+ mNumFilesSigned++;
+
+ if (Warn_IsSimpleContent && (strlen(CurrentFile) > 0))
+ {
+ mWarningSimpleContentFiles++;
+ }
+
+ }
+
+ }
+
+ XUnmountAlternateTitle(AlternateTitleDriveLetter);
+ }
+}
+
+BOOL dlcSignerScene::searchContentMetaFiles(DWORD &TotalFiles, pointerVector* Results)
+{
+ /*
+ 1. Mount E:\ partition
+ 2. Search E:\TDATA\ for valid TitleId folders and build list of TitleId folders
+ 3. Loop all TitleId's, overwrite AlternateTitleId in XBE header memory with current TitleId from loop, and mount AlternateTitle drive W:\
+ 4. Search W:\ for $C and $U folders
+ 5. If W:\$C exists, search W:\$C for valid OfferId folders and build list of OfferId folders
+ 6. Grab ContentMeta.xbx from all OfferId folders in W:\$C if exists
+ 7. Grab ContentMeta.xbx from W:\$U if exists
+ */
+
+ const PCHAR TitleDataRegion = "T:\\"; //symlink of TitleId specific TDATA folder
+ const PCHAR UserDataRegion = "U:\\"; //symlink of TitleId specific UDATA folder
+
+ WIN32_FIND_DATA SearchContext;
+ HANDLE SearchHandle;
+
+ PCHAR SearchCriteria = (PCHAR)malloc(MAX_PATH);
+ ZeroMemory(SearchCriteria, MAX_PATH);
+
+ sprintf(SearchCriteria, "HDD0-E:\\TDATA\\*");
+
+ if ((SearchHandle = FindFirstFile(SearchCriteria, &SearchContext)) == INVALID_HANDLE_VALUE) {
+ /*if (ConsoleIsInitialized())
+ {
+ ConsoleWriteLine(L" ERROR: Failed to access E:\\ or E:\\TDATA is empty");
+ }*/
+ free(SearchCriteria);
+ return FALSE;
+ }
+
+ BYTE* TitleIds = (BYTE*)malloc((2048 * 4)); // there's ~1000 games for the Xbox (+ breathing room + homebrew titles)
+ ZeroMemory(TitleIds, (2048 * 4));
+ DWORD CurrentTitleId = 0;
+ DWORD TitleIdCount = 0;
+
+ if ((strlen(SearchContext.cFileName) == 8) &&
+ ValidHexString(SearchContext.cFileName, 8) &&
+ ((SearchContext.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY))
+ {
+
+ CopyHexToBytes(SearchContext.cFileName, 8, (BYTE*)&CurrentTitleId, TRUE); // convert hex to uint32, reverse to little endian
+
+ if (CurrentTitleId != 0 && CurrentTitleId != 0xFFFFFFFF) {
+ *(DWORD*)(TitleIds + (TitleIdCount * 4)) = CurrentTitleId; //store title id
+ TitleIdCount++;
+ }
+ }
+
+ while(FindNextFile(SearchHandle, &SearchContext)) {
+
+ if ((strlen(SearchContext.cFileName) == 8) &&
+ ValidHexString(SearchContext.cFileName, 8) &&
+ ((SearchContext.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY))
+ {
+ CopyHexToBytes(SearchContext.cFileName, 8, (BYTE*)&CurrentTitleId, TRUE); // convert hex to uint32, reverse to little endian
+
+ if (CurrentTitleId != 0 && CurrentTitleId != 0xFFFFFFFF) {
+ *(DWORD*)(TitleIds + (TitleIdCount * 4)) = CurrentTitleId; //store title id
+ TitleIdCount++;
+ }
+ }
+ }
+
+ FindClose(SearchHandle);
+
+ if (TitleIdCount == 0) {
+
+ free(SearchCriteria);
+ free(TitleIds);
+
+ //if (ConsoleIsInitialized())
+ // ConsoleWriteLine(L" ERROR: No valid content folders found");
+
+ return FALSE;
+ }
+
+ //for some unicode formatting
+ PWCHAR PrintBuffer = (PWCHAR)malloc((125 * sizeof(WCHAR)));
+
+ CHAR AlternateTitleDriveLetter = { 0 };
+
+ //Results = new pointerVector;
+
+ for(DWORD i = 0; i < TitleIdCount; i++) {
+
+ if (getAlternateTitleId() != *(DWORD*)(TitleIds + (i * 4))) {
+
+ if (AlternateTitleDriveLetter != '\0') {
+ XUnmountAlternateTitle(AlternateTitleDriveLetter);
+ AlternateTitleDriveLetter = '\0';
+ }
+
+ if (*(DWORD*)(TitleIds + (i * 4)) == 0)
+ continue;
+
+ setAlternateTitleId(*(DWORD*)(TitleIds + (i * 4))); //write title id into XBE header to trick XAPI into giving access when asking to mount
+ XMountAlternateTitle(TitleDataRegion, *(DWORD*)(TitleIds + (i * 4)), &AlternateTitleDriveLetter); //mount alternate title id, pass T:\\ to force mounting to W:\\ drive
+ }
+
+ BOOL ContentFolderExists = FALSE;
+ BOOL UpdateFolderExists = FALSE;
+
+ ZeroMemory(SearchCriteria, MAX_PATH);
+ sprintf(SearchCriteria, "%c:\\$c", AlternateTitleDriveLetter);
+
+ if ((SearchHandle = FindFirstFile(SearchCriteria, &SearchContext)) != INVALID_HANDLE_VALUE) {
+
+ ContentFolderExists = TRUE;
+ FindClose(SearchHandle);
+ }
+
+ ZeroMemory(SearchCriteria, MAX_PATH);
+ sprintf(SearchCriteria, "%c:\\$u", AlternateTitleDriveLetter);
+
+ if ((SearchHandle = FindFirstFile(SearchCriteria, &SearchContext)) != INVALID_HANDLE_VALUE) {
+
+ UpdateFolderExists = TRUE;
+ FindClose(SearchHandle);
+ }
+
+ if (!ContentFolderExists && !UpdateFolderExists)
+ continue;
+
+
+ //begin file search
+
+ SearchResult* Result = new SearchResult;
+ Result->TitleId = *(DWORD*)(TitleIds + (i * 4));
+ Result->FileCount = 0;
+ Result->Files = new pointerVector(false);
+
+ if (ContentFolderExists) {
+
+ ZeroMemory(SearchCriteria, MAX_PATH);
+ sprintf(SearchCriteria, "%c:\\$c\\ContentMeta.xbx", AlternateTitleDriveLetter);
+
+ //check if a ContentMeta file exists in the root of $C (not usually)
+ if ((SearchHandle = FindFirstFile(SearchCriteria, &SearchContext)) != INVALID_HANDLE_VALUE) {
+
+ PCHAR File = (PCHAR)malloc(MAX_PATH);
+ ZeroMemory(File, MAX_PATH);
+
+ sprintf(File, "%c:\\$c\\ContentMeta.xbx", AlternateTitleDriveLetter);
+
+ Result->Files->add(File);
+ Result->FileCount++;
+
+ FindClose(SearchHandle);
+ }
+
+ //check for offerid folders
+
+ PCHAR OfferIds = (PCHAR)malloc(16 * 100); //allocate for 100 offerid folders (overkill)
+ DWORD OfferIdsCount = 0;
+
+ ZeroMemory(SearchCriteria, MAX_PATH);
+ sprintf(SearchCriteria, "%c:\\$c\\*", AlternateTitleDriveLetter);
+
+ if ((SearchHandle = FindFirstFile(SearchCriteria, &SearchContext)) != INVALID_HANDLE_VALUE) {
+
+ if ((strlen(SearchContext.cFileName) == 16) &&
+ ValidHexString(SearchContext.cFileName, 16) &&
+ ((SearchContext.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY))
+ {
+
+ sprintf((OfferIds + OfferIdsCount), SearchContext.cFileName);
+ OfferIdsCount++;
+ }
+
+ while(FindNextFile(SearchHandle, &SearchContext)) {
+
+ if ((strlen(SearchContext.cFileName) == 16) &&
+ ValidHexString(SearchContext.cFileName, 16) &&
+ ((SearchContext.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY))
+
+ {
+ sprintf((OfferIds + (OfferIdsCount * 16)), SearchContext.cFileName);
+ OfferIdsCount++;
+ }
+
+ }
+
+ FindClose(SearchHandle);
+
+ }
+
+ //search for ContentMeta.xbx files within offerid folders
+
+ if (OfferIdsCount > 0) {
+
+ for(DWORD i = 0; i < OfferIdsCount; i++) {
+
+ ZeroMemory(SearchCriteria, MAX_PATH);
+ sprintf(SearchCriteria, "%c:\\$c\\%.16s\\ContentMeta.xbx", AlternateTitleDriveLetter, (OfferIds + (i * 16)));
+
+ if ((SearchHandle = FindFirstFile(SearchCriteria, &SearchContext)) != INVALID_HANDLE_VALUE) {
+
+ PCHAR File = (PCHAR)malloc(MAX_PATH);
+ ZeroMemory(File, MAX_PATH);
+
+ sprintf(File, "%c:\\$c\\%.16s\\ContentMeta.xbx", AlternateTitleDriveLetter, (OfferIds + (i * 16)));
+
+ Result->Files->add(File);
+ Result->FileCount++;
+
+ FindClose(SearchHandle);
+
+ }
+
+ }
+
+ }
+
+ free(OfferIds);
+
+ }
+
+ if (UpdateFolderExists) {
+
+ ZeroMemory(SearchCriteria, MAX_PATH);
+ sprintf(SearchCriteria, "%c:\\$u\\ContentMeta.xbx", AlternateTitleDriveLetter);
+
+ if ((SearchHandle = FindFirstFile(SearchCriteria, &SearchContext)) != INVALID_HANDLE_VALUE) {
+
+ PCHAR File = (PCHAR)malloc(MAX_PATH);
+ ZeroMemory(File, MAX_PATH);
+
+ sprintf(File, "%c:\\$u\\ContentMeta.xbx", AlternateTitleDriveLetter);
+
+ Result->Files->add(File);
+ Result->FileCount++;
+
+ FindClose(SearchHandle);
+ }
+
+ }
+
+ Results->add(Result);
+ TotalFiles += Result->FileCount;
+ }
+
+ if (AlternateTitleDriveLetter != '\0')
+ {
+ XUnmountAlternateTitle(AlternateTitleDriveLetter);
+ }
+
+ free(SearchCriteria);
+ free(TitleIds);
+ free(PrintBuffer);
+
+ return TRUE;
+}
+
+VOID dlcSignerScene::freeSearchResults(pointerVector* Results) {
+
+ for(DWORD result_index = 0; result_index < Results->count(); result_index++)
+ {
+ SearchResult* result = Results->get(result_index);
+ if (result)
+ {
+ if (result->Files)
+ {
+ delete result->Files;
+ }
+ }
+ }
+}
+
+BOOL dlcSignerScene::signContentMeta(PCHAR File, DWORD TitleId, BOOL OnlySignIfInvalid, BOOL &FailedToAccessFile, BOOL &BadFileSize, BOOL &BadHeaderSize, BOOL &WasInvalidMagic, BOOL &WasSkippedBecauseValid, BOOL &WasSimpleContentMeta)
+{
+ FailedToAccessFile = FALSE;
+ BadFileSize = FALSE;
+ WasInvalidMagic = FALSE;
+ WasSkippedBecauseValid = FALSE;
+ WasSimpleContentMeta = FALSE;
+
+ if (!File)
+ {
+ return FALSE;
+ }
+
+ const DWORD MinimumHeaderSize = 0x6C;
+ BOOL UseTitleIdFromMetadata = (TitleId == 0 || TitleId == 0xFFFFFFFF);
+
+ HANDLE FileHandle = NULL;
+ if ((FileHandle = CreateFile(File, GENERIC_ALL, GENERIC_ALL, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) == INVALID_HANDLE_VALUE) {
+ FailedToAccessFile = TRUE;
+ return FALSE;
+ }
+
+ DWORD FileSize = GetFileSize(FileHandle, NULL);
+ if (FileSize < MinimumHeaderSize)
+ {
+ BadFileSize = TRUE;
+ CloseHandle(FileHandle);
+ return FALSE;
+ }
+
+ PBYTE FileBuffer = (PBYTE)malloc(FileSize);
+
+ DWORD BytesRead = 0;
+ if (!ReadFile(FileHandle, FileBuffer, FileSize, &BytesRead, NULL) || BytesRead != FileSize) {
+
+ FailedToAccessFile = TRUE;
+ CloseHandle(FileHandle);
+ free(FileBuffer);
+ return FALSE;
+ }
+
+ if (*(DWORD*)(FileBuffer + 0x14) != XCSFMagic) {
+
+ WasInvalidMagic = TRUE;
+ CloseHandle(FileHandle);
+ free(FileBuffer);
+ return FALSE;
+ }
+
+ DWORD HeaderSize = *(DWORD*)(FileBuffer + 0x18);
+ if (HeaderSize < MinimumHeaderSize)
+ {
+ BadHeaderSize = TRUE;
+ CloseHandle(FileHandle);
+ free(FileBuffer);
+ return FALSE;
+ }
+
+ DWORD InternalTitleId = 0;
+ if (UseTitleIdFromMetadata)
+ {
+ InternalTitleId = *(DWORD*)(FileBuffer + 0x24);
+ }
+
+ PBYTE Signature = (PBYTE)malloc(SHA_DIGEST_SIZE);
+ calculateContentHeaderSignature((UseTitleIdFromMetadata ? InternalTitleId : TitleId), (FileBuffer + 0x14), (HeaderSize - 0x14), Signature);
+
+ BOOL SignaturesMatch = (memcmp(FileBuffer, Signature, SHA_DIGEST_SIZE) == 0);
+
+ if (OnlySignIfInvalid && SignaturesMatch)
+ {
+ WasSkippedBecauseValid = TRUE;
+ CloseHandle(FileHandle);
+ free(FileBuffer);
+ free(Signature);
+ return FALSE;
+ }
+
+ SetFilePointer(FileHandle, 0, NULL, FILE_BEGIN);
+
+ DWORD BytesWritten = 0;
+ if (!WriteFile(FileHandle, Signature, SHA_DIGEST_SIZE, &BytesWritten, NULL) || BytesWritten != SHA_DIGEST_SIZE) {
+
+ FailedToAccessFile = TRUE;
+ CloseHandle(FileHandle);
+ free(FileBuffer);
+ free(Signature);
+ return FALSE;
+ }
+
+ FlushFileBuffers(FileHandle);
+ CloseHandle(FileHandle);
+
+ free(FileBuffer);
+ free(Signature);
+
+ if ((strstr(File, "$c") != NULL) || (strstr(File, "$C") != NULL))
+ {
+ if (HeaderSize == MinimumHeaderSize)
+ {
+ WasSimpleContentMeta = TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+BOOL dlcSignerScene::calculateContentHeaderSignature(DWORD TitleId, PBYTE buffer, DWORD length, PBYTE result)
+{
+ if (buffer && length > 0 && result)
+ {
+ PBYTE ContentKey = (PBYTE)malloc(SHA_DIGEST_SIZE);
+ //calc content key (HMAC SHA1 hash of TitleId bytes using XboxHDKey as the key)
+ XcHMAC(&XboxHDKey[0], 0x10, (PBYTE)&TitleId, 4, NULL, NULL, ContentKey);
+ //calc signature (HMAC SHA1 hash of supplied data using "content key" as the key)
+ XcHMAC(ContentKey, SHA_DIGEST_SIZE, buffer, length, NULL, NULL, result);
+ free(ContentKey);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+DWORD dlcSignerScene::getAlternateTitleId()
+{
+ //NOTE: only using the first alternate title id, it's possible to use up to 16 total
+ //NOTE(feudalnate): might be a good idea to cache the alternate title id's address instead of fetching every time
+
+ DWORD CertificateAddress = *(DWORD*)(XBEBaseAddress + 0x118); //get certificate address from XBE header
+ DWORD AlternateTitleIdsAddress = (CertificateAddress + 0x5C); //alternate titleids are located 0x5C from beginning of certificate (in all cert. revisions)
+
+ return *(DWORD*)AlternateTitleIdsAddress;
+}
+
+VOID dlcSignerScene::setAlternateTitleId(DWORD AlternateTitleId)
+{
+ DWORD CertificateAddress = *(DWORD*)(XBEBaseAddress + 0x118);
+ DWORD AlternateTitleIdsAddress = (CertificateAddress + 0x5C);
+
+ *(DWORD*)AlternateTitleIdsAddress = AlternateTitleId;
+}
+
+BOOL dlcSignerScene::checkXBEHeader()
+{
+ if (memoryPageWritable((LPVOID)XBEBaseAddress))
+ {
+ if (*(DWORD*)XBEBaseAddress == XBEMagic)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+BOOL dlcSignerScene::memoryPageWritable(LPVOID Address)
+{
+
+ /*
+ WinNT memory page protection flags (one or more will _always_ be set)
+
+ PAGE_NOACCESS 0x01
+ PAGE_READONLY 0x02
+ PAGE_READWRITE 0x04
+ PAGE_WRITECOPY 0x08
+ PAGE_EXECUTE 0x10
+ PAGE_EXECUTE_READ 0x20
+ PAGE_EXECUTE_READWRITE 0x40
+ PAGE_EXECUTE_WRITECOPY 0x80
+ PAGE_GUARD 0x100
+ PAGE_NOCACHE 0x200
+ PAGE_WRITECOMBINE 0x400
+ */
+
+ DWORD Flags = XQueryMemoryProtect(Address);
+
+ if ( (Flags == 0) || ((Flags & PAGE_GUARD) == PAGE_GUARD) || ((Flags & PAGE_NOACCESS) == PAGE_NOACCESS) )
+ {
+ return FALSE;
+ }
+ if ( ((Flags & PAGE_READWRITE) == PAGE_READWRITE) || ((Flags & PAGE_EXECUTE_READWRITE) == PAGE_EXECUTE_READWRITE) )
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL dlcSignerScene::ValidHexString(CHAR* string, DWORD length) {
+
+ //this could be done better/faster
+
+ if (!string || length == 0 || (length % 2) != 0)
+ return FALSE;
+
+ const CHAR* valid_chars = "0123456789abcdefABCDEF";
+ const DWORD valid_chars_len = 22;
+
+ BOOL valid;
+ CHAR c, v;
+ for(DWORD i = 0; i < length; i++) {
+
+ valid = FALSE;
+ c = *(CHAR*)(string + i);
+
+ for(DWORD x = 0; x < valid_chars_len; x++) {
+
+ v = *(CHAR*)(valid_chars + x);
+
+ if (c == v) {
+ valid = TRUE;
+ break;
+ }
+
+ }
+
+ if (!valid)
+ return FALSE;
+
+ }
+
+ return TRUE;
+}
+
+VOID dlcSignerScene::CopyHexToBytes(CHAR* string, DWORD length, BYTE* buffer, BOOL reverse)
+{
+
+ if (string && length > 0 && (length % 2) == 0 && buffer) {
+
+ CHAR c;
+ BYTE b;
+
+ DWORD buffer_index = 0;
+
+ for(DWORD i = 0; i < length; i += 2) {
+
+ //first nibble
+ c = *(CHAR*)(string + i);
+
+ if (c >= '0' && c <= '9')
+ b = (BYTE)((c - '0') << 4);
+ else if (c >= 'A' && c <= 'F')
+ b = (BYTE)((c - 'A' + 10) << 4);
+ else
+ b = (BYTE)((c - 'a' + 10) << 4);
+
+ //second nibble
+ c = *(CHAR*)(string + (i + 1));
+
+ if (c >= '0' && c <= '9')
+ b = (BYTE)(b | (c - '0'));
+ else if (c >= 'A' && c <= 'F')
+ b = (BYTE)(b | (c - 'A' + 10));
+ else
+ b = (BYTE)(b | (c - 'a' + 10));
+
+ *(BYTE*)(buffer + buffer_index) = b;
+ buffer_index++;
+ }
+
+ if (reverse) {
+
+ DWORD x = 0;
+ DWORD y = (length / 2);
+
+ while (x < y) {
+ b = *(BYTE*)(buffer + x);
+ *(BYTE*)(buffer + x) = *(BYTE*)(buffer + (y - 1));
+ *(BYTE*)(buffer + (y - 1)) = b;
+ x++;
+ y--;
+ }
+
+ }
+
+ }
+}
+
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/dlcSignerScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/dlcSignerScene.h
new file mode 100644
index 0000000..47208a2
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/dlcSignerScene.h
@@ -0,0 +1,42 @@
+#pragma once
+
+#include "scene.h"
+
+#include "..\pointerVector.h"
+#include "..\xboxInternals.h"
+
+struct SearchResult {
+ DWORD TitleId;
+ DWORD FileCount;
+ pointerVector* Files;
+};
+
+class dlcSignerScene : public scene
+{
+public:
+ dlcSignerScene();
+ ~dlcSignerScene();
+ void update();
+ void render();
+private:
+ uint32_t mCurrentSceneId;
+ pointerVector* mSearchResults;
+ DWORD mFilesFound;
+ BOOL mOnlySignIfInvalid;
+ DWORD mWarningSimpleContentFiles;
+ DWORD mNumFilesSigned;
+ DWORD mNumFilesFailed;
+ DWORD mNumFilesSkipped;
+
+ void signContent(pointerVector* SearchResults);
+ BOOL searchContentMetaFiles(DWORD &TotalFiles, pointerVector* Results);
+ VOID freeSearchResults(pointerVector* Results);
+ BOOL signContentMeta(PCHAR File, DWORD TitleId, BOOL OnlySignIfInvalid, BOOL &FailedToAccessFile, BOOL &BadFileSize, BOOL &BadHeaderSize, BOOL &WasInvalidMagic, BOOL &WasSkippedBecauseValid, BOOL &WasSimpleContentMeta);
+ BOOL calculateContentHeaderSignature(DWORD TitleId, PBYTE buffer, DWORD length, PBYTE result);
+ DWORD getAlternateTitleId();
+ VOID setAlternateTitleId(DWORD AlternateTitleId);
+ BOOL checkXBEHeader();
+ BOOL memoryPageWritable(LPVOID Address);
+ BOOL ValidHexString(CHAR* string, DWORD length);
+ VOID CopyHexToBytes(CHAR* string, DWORD length, BYTE* buffer, BOOL reverse);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/editFlowScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/editFlowScene.cpp
new file mode 100644
index 0000000..58b6769
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/editFlowScene.cpp
@@ -0,0 +1,100 @@
+#include "editFlowScene.h"
+#include "sceneManager.h"
+#include "launchScene.h"
+#include "removeScene.h"
+#include "editScene.h"
+#include "flashBankScene.h"
+#include "audioSettingsScene.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxInternals.h"
+#include "..\fileSystem.h"
+
+void editFlowScene::onEditClosingCallback(sceneResult result, void* context, scene* scene)
+{
+ editFlowScene* self = (editFlowScene*)context;
+ if (result == sceneResultCancelled)
+ {
+ self->mCurrentSceneId = 3;
+ return;
+ }
+ editScene* closingScene = (editScene*)scene;
+ self->mBankId = closingScene->getBankId();
+ self->mCurrentSceneId = 1;
+}
+
+void editFlowScene::onKeyboardClosingCallback(sceneResult result, void* context, scene* scene)
+{
+ editFlowScene* self = (editFlowScene*)context;
+ if (result == sceneResultCancelled)
+ {
+ self->mCurrentSceneId = 3;
+ return;
+ }
+ keyboardScene* closingScene = (keyboardScene*)scene;
+ self->mBankName = closingScene->getText();
+ self->mCurrentSceneId = context::getModchip()->getSupportInfo(true).supportsLed == true ? 2 : 3;
+}
+
+void editFlowScene::onLedColorClosingCallback(sceneResult result, void* context, scene* scene)
+{
+ editFlowScene* self = (editFlowScene*)context;
+ if (result == sceneResultCancelled)
+ {
+ self->mCurrentSceneId = 3;
+ return;
+ }
+ ledColorSelectorScene* closingScene = (ledColorSelectorScene*)scene;
+ settingsManager::editBank(self->mBankId, self->mBankName, closingScene->getLedColor());
+ self->mCurrentSceneId = 3;
+}
+
+editFlowScene::editFlowScene()
+{
+ mCurrentSceneId = 0;
+ mBankId = 0;
+ mBankName = NULL;
+}
+
+void editFlowScene::update()
+{
+ if (mCurrentSceneId == 0)
+ {
+ sceneContainer* container = new sceneContainer(sceneItemGenericScene, new editScene(), "", this, onEditClosingCallback);
+ sceneManager::pushScene(container);
+ return;
+ }
+
+ if (mCurrentSceneId == 1)
+ {
+ bankInfo bank = settingsManager::getBankInfo(mBankId);
+ char* bankName = strdup(bank.name);
+ sceneContainer* container = new sceneContainer(sceneItemGenericScene, new keyboardScene(63, "Please enter a bank name...", "Bank Name:", bankName), "", this, onKeyboardClosingCallback);
+ free(bankName);
+ sceneManager::pushScene(container);
+ return;
+ }
+
+ if (mCurrentSceneId == 2)
+ {
+ sceneContainer* container = new sceneContainer(sceneItemGenericScene, new ledColorSelectorScene(), "", this, onLedColorClosingCallback);
+ sceneManager::pushScene(container);
+ return;
+ }
+
+ if (mCurrentSceneId == 3)
+ {
+ sceneManager::popScene();
+ }
+}
+
+void editFlowScene::render()
+{
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/editFlowScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/editFlowScene.h
new file mode 100644
index 0000000..0ed3f52
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/editFlowScene.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "scene.h"
+#include "editScene.h"
+#include "keyboardScene.h"
+#include "ledColorSelectorScene.h"
+#include "flashBankScene.h"
+
+#include "..\xboxInternals.h"
+
+class editFlowScene : public scene
+{
+public:
+ editFlowScene();
+ void update();
+ void render();
+private:
+ uint32_t mCurrentSceneId;
+ uint8_t mBankId;
+ char* mBankName;
+ static void onEditClosingCallback(sceneResult result, void* context, scene* scene);
+ static void onKeyboardClosingCallback(sceneResult result, void* context, scene* scene);
+ static void onLedColorClosingCallback(sceneResult result, void* context, scene* scene);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/editScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/editScene.cpp
new file mode 100644
index 0000000..ef4ad05
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/editScene.cpp
@@ -0,0 +1,113 @@
+#include "editScene.h"
+#include "sceneManager.h"
+#include "audioSettingsScene.h"
+#include "videoSettingsScene.h"
+#include "mainScene.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\alignment.h"
+#include "..\theme.h"
+
+editScene::editScene()
+{
+ mSelectedControl = 0;
+ mBanks = settingsManager::getBankInfos();
+ mBankId = 0;
+}
+
+editScene::~editScene()
+{
+ delete(mBanks);
+}
+
+void editScene::update()
+{
+ // Exit Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene(sceneResultCancelled);
+ return;
+ }
+
+ // Select Actions
+
+ if (inputManager::buttonPressed(ButtonA))
+ {
+ for (uint32_t i = 0; i < mBanks->count(); i++)
+ {
+ if (mSelectedControl != i)
+ {
+ continue;
+ }
+ mBankId = (uint8_t)i;
+ sceneManager::popScene(sceneResultDone);
+ return;
+ }
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ mSelectedControl = mSelectedControl < (int)(mBanks->count() - 1) ? mSelectedControl + 1 : 0;
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : (int)(mBanks->count() - 1);
+ }
+}
+
+void editScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Please select a bank to edit...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ int32_t maxItems = 7;
+
+ int32_t start = 0;
+ if ((int32_t)mBanks->count() >= maxItems)
+ {
+ start = min(max(mSelectedControl - (maxItems / 2), 0), (int32_t)mBanks->count() - maxItems);
+ }
+
+ int32_t itemCount = min(start + maxItems, (int32_t)mBanks->count()) - start;
+ if (itemCount > 0)
+ {
+ uint32_t yPos = (context::getBufferHeight() - ((itemCount * 40) - 10)) / 2;
+ yPos += theme::getCenterOffset();
+
+ for (int32_t i = 0; i < itemCount; i++)
+ {
+ uint32_t index = start + i;
+ bankDetails* bank = mBanks->get(index);
+ component::button(mSelectedControl == index, false, bank->name, 40, yPos, 640, 30);
+ yPos += 40;
+ }
+ }
+ else
+ {
+ int yPos = ((context::getBufferHeight() - 44) / 2);
+ yPos += theme::getCenterOffset();
+
+ component::textBox("No items", false, false, horizAlignmentCenter, 40, yPos, 640, 44);
+ }
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Select", theme::getFooterTextColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Cancel", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
+
+uint8_t editScene::getBankId()
+{
+ return mBankId;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/editScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/editScene.h
new file mode 100644
index 0000000..3f001f6
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/editScene.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "scene.h"
+
+#include "..\pointerVector.h"
+#include "..\settingsManager.h"
+
+class editScene : public scene
+{
+public:
+ editScene();
+ ~editScene();
+ void update();
+ void render();
+ uint8_t getBankId();
+private:
+ int mSelectedControl;
+ pointerVector* mBanks;
+ uint8_t mBankId;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/filePickerScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/filePickerScene.cpp
new file mode 100644
index 0000000..e05edbe
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/filePickerScene.cpp
@@ -0,0 +1,318 @@
+#include "filePickerScene.h"
+#include "sceneManager.h"
+#include "audioSettingsScene.h"
+#include "videoSettingsScene.h"
+#include "mainScene.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\driveManager.h"
+#include "..\fileSystem.h"
+#include "..\pointerVector.h"
+#include "..\theme.h"
+#include "..\Threads\driveMounter.h"
+
+pointerVector* filePickerScene::getFileInfoDetails()
+{
+ if (strlen(mCurrentPath) == 0)
+ {
+ pointerVector* fileInfoDetails = new pointerVector(true);
+ for (uint32_t i = 0; i < mMountedDrives->count(); i++)
+ {
+ if(mHideMMU) {
+ char* mountPoint = stringUtility::formatString("%s:", mMountedDrives->get(i));
+ char* mountAlias = driveManager::convertMountPointToMountPointAlias(mountPoint);
+ free(mountPoint);
+
+ if (stringUtility::startsWith(mountAlias, "MMU", true)) {
+ free(mountAlias);
+ continue;
+ }
+ free(mountAlias);
+ }
+
+ char* mountPoint = mMountedDrives->get(i);
+ fileSystem::FileInfoDetail* fileInfoDetail = new fileSystem::FileInfoDetail();
+ fileInfoDetail->path = stringUtility::formatString("%s:", mountPoint);
+ fileInfoDetail->isDirectory = true;
+ fileInfoDetail->isFile = false;
+ fileInfoDetails->add(fileInfoDetail);
+ }
+ return fileInfoDetails;
+ }
+
+ pointerVector* result = fileSystem::fileGetFileInfoDetails(mCurrentPath);
+ if (result != NULL)
+ {
+ for (int32_t i = (int32_t)result->count() - 1; i >= 0; i--)
+ {
+ fileSystem::FileInfoDetail* fileInfoDetail = result->get(i);
+
+ bool valid = fileInfoDetail->isDirectory;
+ if (fileInfoDetail->isFile)
+ {
+ if (mFilePickerType == filePickerTypeBios)
+ {
+ valid = context::getModchip()->isValidBankSize(fileInfoDetail->size);
+ }
+ else if (mFilePickerType == filePickerTypeEeprom)
+ {
+ valid = fileInfoDetail->size == 256;
+ }
+ else if (mFilePickerType == filePickerTypeUpdate)
+ {
+ valid = context::getModchip()->isValidFlashSize(false, fileInfoDetail->size);
+ }
+ else if (mFilePickerType == filePickerTypeUpdateRecovery)
+ {
+ valid = context::getModchip()->isValidFlashSize(true, fileInfoDetail->size);
+ }
+ else if (mFilePickerType == filePickerTypeXbe)
+ {
+ char* ext = fileSystem::getExtension(fileInfoDetail->path);
+ valid = stricmp(ext, ".xbe") == 0;
+ free(ext);
+ }
+ }
+
+ if (valid == false)
+ {
+ result->remove(i);
+ }
+ }
+ }
+
+ return result;
+}
+
+filePickerScene::filePickerScene(filePickerType filePickerType, bool useDevPath, bool hideMMU)
+{
+ driveMounter::startThread(false);
+
+ mHideMMU = hideMMU;
+ mUseDevPath = useDevPath;
+ mInitialized = false;
+ mFilePickerType = filePickerType;
+ mSelectedControl = 0;
+ mScrollPosition = 0;
+ mMountedDrives = NULL;
+ mCurrentPath = NULL;
+ mFileInfoDetails = NULL;
+ mFilePath = NULL;
+}
+
+filePickerScene::~filePickerScene()
+{
+ delete(mMountedDrives);
+ free(mCurrentPath);
+ delete(mFileInfoDetails);
+ free(mFilePath);
+}
+
+void filePickerScene::update()
+{
+ if (mInitialized == false)
+ {
+ if (driveMounter::completed() == true)
+ {
+ bool exists = false;
+ driveMounter::closeThread();
+ mMountedDrives = driveManager::getMountedDrives();
+
+ bool biosFolderExists = false;
+ mCurrentPath = strdup("");
+ //mCurrentPath = fileSystem::directoryExists("C:\\Bios", biosFolderExists) && biosFolderExists == true ? strdup("C:\\Bios") : strdup("");
+ mFileInfoDetails = getFileInfoDetails();
+ mInitialized = true;
+ }
+ return;
+ }
+
+ // Cancel Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene(sceneResultCancelled);
+ return;
+ }
+
+ // Parent Path
+
+ if (inputManager::buttonPressed(ButtonX))
+ {
+ char* newPath = fileSystem::getDirectory(mCurrentPath);
+ free(mCurrentPath);
+ mCurrentPath = newPath;
+
+ delete(mFileInfoDetails);
+ mFileInfoDetails = getFileInfoDetails();
+ mSelectedControl = 0;
+ mScrollPosition = 0;
+ }
+
+ // Select Actions
+
+ if (inputManager::buttonPressed(ButtonA))
+ {
+ if (mFileInfoDetails != NULL)
+ {
+ for (uint32_t i = 0; i < mFileInfoDetails->count(); i++)
+ {
+ if (mSelectedControl != i)
+ {
+ continue;
+ }
+
+ fileSystem::FileInfoDetail* fileInfoDetail = mFileInfoDetails->get(i);
+ if (fileInfoDetail->isDirectory)
+ {
+ char* newPath = strdup(fileInfoDetail->path);
+ free(mCurrentPath);
+ mCurrentPath = newPath;
+
+ delete(mFileInfoDetails);
+ mFileInfoDetails = getFileInfoDetails();
+ mSelectedControl = 0;
+ mScrollPosition = 0;
+ break;
+ }
+ else if (fileInfoDetail->isFile)
+ {
+ if(mUseDevPath) {
+ char* drvLtr = fileSystem::getDriveLetter(fileInfoDetail->path);
+ char* drvPart = driveManager::getDrivePartition(drvLtr);
+ char* rootPath = fileSystem::getRootPath(fileInfoDetail->path);
+
+ mFilePath = stringUtility::formatString("%s%s", drvPart, rootPath);
+
+ free(rootPath);
+ free(drvPart);
+ free(drvLtr);
+ } else {
+ mFilePath = strdup(fileInfoDetail->path);
+ }
+ sceneManager::popScene(sceneResultDone);
+ return;
+ }
+ }
+ }
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ if (mFileInfoDetails != NULL)
+ {
+ mSelectedControl = mSelectedControl < (int)(mFileInfoDetails->count() - 1) ? mSelectedControl + 1 : 0;
+ }
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ if (mFileInfoDetails != NULL)
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : (int)(mFileInfoDetails->count() - 1);
+ }
+ }
+}
+
+void filePickerScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+
+ if (mFilePickerType == filePickerTypeBios)
+ {
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Please select BIOS to flash...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+ }
+ else if (mFilePickerType == filePickerTypeEeprom)
+ {
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Please select Eeprom to flash...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+ }
+ else if (mFilePickerType == filePickerTypeUpdate)
+ {
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Please select PrometheOS to flash...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+ }
+ else if (mFilePickerType == filePickerTypeUpdateRecovery)
+ {
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Please select Recovery to flash...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+ }
+ else if (mFilePickerType == filePickerTypeXbe)
+ {
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Please select XBE...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+ }
+
+ if (mInitialized == false)
+ {
+ component::textBox("Please Wait...", false, false, horizAlignmentCenter, 40, 218, 640, 44);
+ }
+ else if (mFileInfoDetails != NULL)
+ {
+ int32_t maxItems = 7;
+
+ int32_t start = 0;
+ if ((int32_t)mFileInfoDetails->count() >= maxItems)
+ {
+ start = min(max(mSelectedControl - (maxItems / 2), 0), (int32_t)mFileInfoDetails->count() - maxItems);
+ }
+
+ int32_t itemCount = min(start + maxItems, (int32_t)mFileInfoDetails->count()) - start;
+ if (itemCount > 0)
+ {
+ int32_t yPos = (context::getBufferHeight() - ((itemCount * 40) - 10)) / 2;
+ yPos += theme::getCenterOffset();
+
+ for (int32_t i = 0; i < itemCount; i++)
+ {
+ uint32_t index = start + i;
+ fileSystem::FileInfoDetail* fileInfoDetail = mFileInfoDetails->get(index);
+
+ if (strlen(mCurrentPath) == 0)
+ {
+ char* tempFileName = fileSystem::getFileName(fileInfoDetail->path);
+ char* fileName = driveManager::convertMountPointToMountPointAlias(tempFileName);
+ component::fileButton(mSelectedControl == index, false, fileInfoDetail->isFile, fileName, 40, yPos, 640, 30);
+ free(fileName);
+ free(tempFileName);
+ }
+ else
+ {
+ char* fileName = fileSystem::getFileName(fileInfoDetail->path);
+ component::fileButton(mSelectedControl == index, false, fileInfoDetail->isFile, fileName, 40, yPos, 640, 30);
+ free(fileName);
+ }
+
+ yPos += 40;
+ }
+ }
+ else
+ {
+ int yPos = ((context::getBufferHeight() - 44) / 2);
+ yPos += theme::getCenterOffset();
+
+ component::textBox("No items", false, false, horizAlignmentCenter, 40, yPos, 640, 44);
+ }
+ }
+ else
+ {
+ int yPos = ((context::getBufferHeight() - 44) / 2);
+ yPos += theme::getCenterOffset();
+
+ component::textBox("No items", false, false, horizAlignmentCenter, 40, yPos, 640, 44);
+ }
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Select \xC2\xA3 Parent", mInitialized ? theme::getFooterTextColor() : theme::getTextDisabledColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Cancel", mInitialized ? theme::getFooterTextColor() : theme::getTextDisabledColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
+
+char* filePickerScene::getFilePath()
+{
+ return strdup(mFilePath);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/filePickerScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/filePickerScene.h
new file mode 100644
index 0000000..9249885
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/filePickerScene.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "scene.h"
+
+#include "..\pointerVector.h"
+#include "..\fileSystem.h"
+
+enum filePickerType
+{
+ filePickerTypeBios = 0,
+ filePickerTypeEeprom = 1,
+ filePickerTypeUpdate = 2,
+ filePickerTypeUpdateRecovery = 3,
+ filePickerTypeXbe = 4
+};
+
+class filePickerScene : public scene
+{
+public:
+ filePickerScene(filePickerType filePickerType, bool useDevPath = false, bool hideMMU = false);
+ ~filePickerScene();
+ void update();
+ void render();
+ char* getFilePath();
+private:
+ pointerVector* getFileInfoDetails();
+private:
+ bool mInitialized;
+ bool mUseDevPath;
+ bool mHideMMU;
+ filePickerType mFilePickerType;
+ int mSelectedControl;
+ int mScrollPosition;
+ pointerVector* mMountedDrives;
+ char* mCurrentPath;
+ pointerVector* mFileInfoDetails;
+ char* mFilePath;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashBackupScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashBackupScene.cpp
new file mode 100644
index 0000000..302b19c
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashBackupScene.cpp
@@ -0,0 +1,114 @@
+#include "flashBackupScene.h"
+#include "sceneManager.h"
+
+#include "..\drawing.h"
+#include "..\ssfn.h"
+#include "..\component.h"
+#include "..\fileSystem.h"
+#include "..\utils.h"
+#include "..\theme.h"
+#include "..\stringUtility.h"
+#include "..\Threads\flashBackup.h"
+
+flashBackupScene::flashBackupScene(bool recovery)
+{
+ mProgress = strdup("");
+ mDone = false;
+ flashBackup::startThread(recovery);
+}
+
+flashBackupScene::~flashBackupScene()
+{
+ free(mProgress);
+}
+
+void flashBackupScene::update()
+{
+ // Back Action
+
+ if (mDone == true)
+ {
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene(sceneResultDone);
+ }
+ return;
+ }
+
+ processResponse(flashBackup::getResponse());
+ if (flashBackup::completed() == true)
+ {
+ flashBackup::closeThread();
+ mDone = true;
+ }
+}
+
+void flashBackupScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Please wait...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ int yPos = (context::getBufferHeight() - (40 + 44)) / 2;
+ yPos += theme::getCenterOffset();
+
+ drawing::drawBitmapString(context::getBitmapFontMedium(), "Status", theme::getHeaderTextColor(), 193, yPos);
+
+ yPos += 40;
+
+ component::textBox(mProgress, false, false, horizAlignmentCenter, 193, yPos, 322, 44);
+
+ if (mDone == true)
+ {
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+ }
+}
+
+void flashBackupScene::setProgress(const char* message)
+{
+ free(mProgress);
+ mProgress = strdup(message);
+}
+
+void flashBackupScene::processResponse(flashBackup::flashBackupResponse response)
+{
+ uint32_t currentStep;
+ uint32_t totalSteps;
+ flashBackup::getProgress(currentStep, totalSteps);
+
+ if (response == flashBackup::flashBackupResponseNone)
+ {
+ setProgress("");
+ }
+ else if (response == flashBackup::flashBackupProcessing)
+ {
+ setProgress("Processing");
+ }
+ else if (response == flashBackup::flashBackupFailedToCreateDirectory)
+ {
+ setProgress("Failed to create file");
+ }
+ else if (response == flashBackup::flashBackupFailedToCreateFile)
+ {
+ setProgress("Failed to create file");
+ }
+ else if (response == flashBackup::flashBackupFailedToWriteFile)
+ {
+ setProgress("Failed to write to file");
+ }
+ else if (response == flashBackup::flashBackupReading)
+ {
+ char* progress = stringUtility::formatString("Step %i of %i - Reading", currentStep, totalSteps);
+ setProgress(progress);
+ free(progress);
+ }
+ else if (response == flashBackup::flashBackupWriting)
+ {
+ char* progress = stringUtility::formatString("Step %i of %i - Writing", currentStep, totalSteps);
+ setProgress(progress);
+ free(progress);
+ }
+ else if (response == flashBackup::flashBackupDone)
+ {
+ setProgress("Done");
+ }
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashBackupScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashBackupScene.h
new file mode 100644
index 0000000..08ff65c
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashBackupScene.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "scene.h"
+
+#include "..\utils.h"
+#include "..\Threads\flashBackup.h"
+#include "..\xboxInternals.h"
+
+class flashBackupScene : public scene
+{
+public:
+ flashBackupScene(bool recovery);
+ ~flashBackupScene();
+ void update();
+ void render();
+private:
+ void setProgress(const char* message);
+ void processResponse(flashBackup::flashBackupResponse response);
+private:
+ bool mDone;
+ char* mProgress;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashBankScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashBankScene.cpp
new file mode 100644
index 0000000..ff7a7c7
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashBankScene.cpp
@@ -0,0 +1,114 @@
+#include "flashBankScene.h"
+#include "sceneManager.h"
+
+#include "..\drawing.h"
+#include "..\ssfn.h"
+#include "..\component.h"
+#include "..\fileSystem.h"
+#include "..\utils.h"
+#include "..\settingsManager.h"
+#include "..\theme.h"
+#include "..\Threads\flashBank.h"
+
+flashBankScene::flashBankScene(const char* filePath, const char* bankName, uint8_t ledColor)
+{
+ mProgress = strdup("");
+ mDone = false;
+ flashBank::startThread(filePath, bankName, ledColor);
+}
+
+flashBankScene::~flashBankScene()
+{
+ free(mProgress);
+}
+
+void flashBankScene::update()
+{
+ // Back Action
+
+ if (mDone == true && inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene(sceneResultDone);
+ return;
+ }
+
+ if (mDone == false)
+ {
+ processResponse(flashBank::getResponse());
+ if (flashBank::completed() == true)
+ {
+ flashBank::closeThread();
+ mDone = true;
+ }
+ }
+}
+
+void flashBankScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Please wait...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ int yPos = (context::getBufferHeight() - (40 + 44)) / 2;
+ yPos += theme::getCenterOffset();
+
+ drawing::drawBitmapString(context::getBitmapFontMedium(), "Status", theme::getHeaderTextColor(), 193, yPos);
+
+ yPos += 40;
+
+ component::textBox(mProgress, false, false, horizAlignmentCenter, 193, yPos, 322, 44);
+
+ if (mDone == true)
+ {
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+ }
+}
+
+void flashBankScene::setProgress(const char* message)
+{
+ free(mProgress);
+ mProgress = strdup(message);
+}
+
+void flashBankScene::processResponse(flashBank::flashBankResponse response)
+{
+ if (response == flashBank::flashBankResponseNone)
+ {
+ setProgress("");
+ }
+ else if (response == flashBank::flashBankProcessing)
+ {
+ setProgress("Processing");
+ }
+ else if (response == flashBank::flashBankFailedToLoadFile)
+ {
+ setProgress("Failed to load file");
+ }
+ else if (response == flashBank::flashBankOptimizing)
+ {
+ setProgress("Optimizing");
+ }
+ else if (response == flashBank::flashBankNotEnoughSlots)
+ {
+ setProgress("Not enough slots");
+ }
+ else if (response == flashBank::flashBankErasing)
+ {
+ setProgress("Erasing");
+ }
+ else if (response == flashBank::flashBankWriting)
+ {
+ setProgress("Writing");
+ }
+ else if (response == flashBank::flashBankVerifying)
+ {
+ setProgress("Verifying");
+ }
+ else if (response == flashBank::flashBankVerificationFailed)
+ {
+ setProgress("Verification failed");
+ }
+ else if (response == flashBank::flashBankDone)
+ {
+ setProgress("Done");
+ }
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashBankScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashBankScene.h
new file mode 100644
index 0000000..e3b867c
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashBankScene.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "scene.h"
+
+#include "..\utils.h"
+#include "..\Threads\flashBank.h"
+#include "..\xboxInternals.h"
+
+class flashBankScene : public scene
+{
+public:
+ flashBankScene(const char* filePath, const char* bankName, uint8_t ledColor);
+ ~flashBankScene();
+ void update();
+ void render();
+private:
+ void setProgress(const char* message);
+ void processResponse(flashBank::flashBankResponse response);
+private:
+ bool mDone;
+ char* mProgress;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashFlowScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashFlowScene.cpp
new file mode 100644
index 0000000..3152e3a
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashFlowScene.cpp
@@ -0,0 +1,118 @@
+#include "flashFlowScene.h"
+#include "keyboardScene.h"
+#include "sceneManager.h"
+#include "launchScene.h"
+#include "removeScene.h"
+#include "filePickerScene.h"
+#include "ledColorSelectorScene.h"
+#include "flashBankScene.h"
+#include "audioSettingsScene.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxInternals.h"
+#include "..\fileSystem.h"
+
+void flashFlowScene::onFilePickerClosingCallback(sceneResult result, void* context, scene* scene)
+{
+ flashFlowScene* self = (flashFlowScene*)context;
+ if (result == sceneResultCancelled)
+ {
+ self->mCurrentSceneId = 4;
+ return;
+ }
+ filePickerScene* closingScene = (filePickerScene*)scene;
+ self->mFilePath = closingScene->getFilePath();
+ self->mCurrentSceneId = 1;
+}
+
+void flashFlowScene::onKeyboardClosingCallback(sceneResult result, void* context, scene* scene)
+{
+ flashFlowScene* self = (flashFlowScene*)context;
+ if (result == sceneResultCancelled)
+ {
+ self->mCurrentSceneId = 4;
+ return;
+ }
+ keyboardScene* closingScene = (keyboardScene*)scene;
+ self->mBankName = closingScene->getText();
+ self->mCurrentSceneId = context::getModchip()->getSupportInfo(true).supportsLed == true ? 2 : 3;
+}
+
+void flashFlowScene::onLedColorClosingCallback(sceneResult result, void* context, scene* scene)
+{
+ flashFlowScene* self = (flashFlowScene*)context;
+ if (result == sceneResultCancelled)
+ {
+ self->mCurrentSceneId = 4;
+ return;
+ }
+ ledColorSelectorScene* closingScene = (ledColorSelectorScene*)scene;
+ self->mLedColor = closingScene->getLedColor();
+ self->mCurrentSceneId = 3;
+}
+
+void flashFlowScene::onFlashBankClosingCallback(sceneResult result, void* context, scene* scene)
+{
+ flashFlowScene* self = (flashFlowScene*)context;
+ self->mCurrentSceneId = 4;
+}
+
+flashFlowScene::flashFlowScene()
+{
+ mCurrentSceneId = 0;
+ mFilePath = NULL;
+ mBankName = NULL;
+ mLedColor = 0;
+}
+
+flashFlowScene::~flashFlowScene()
+{
+ free(mFilePath);
+}
+
+void flashFlowScene::update()
+{
+ if (mCurrentSceneId == 0)
+ {
+ sceneContainer* container = new sceneContainer(sceneItemGenericScene, new filePickerScene(filePickerTypeBios), "", this, onFilePickerClosingCallback);
+ sceneManager::pushScene(container);
+ return;
+ }
+
+ if (mCurrentSceneId == 1)
+ {
+ char* fileName = fileSystem::getFileNameWithoutExtension(mFilePath);
+ sceneContainer* container = new sceneContainer(sceneItemGenericScene, new keyboardScene(63, "Please enter a bank name...", "Bank Name:", fileName), "", this, onKeyboardClosingCallback);
+ sceneManager::pushScene(container);
+ return;
+ }
+
+ if (mCurrentSceneId == 2)
+ {
+ sceneContainer* container = new sceneContainer(sceneItemGenericScene, new ledColorSelectorScene(), "", this, onLedColorClosingCallback);
+ sceneManager::pushScene(container);
+ return;
+ }
+
+ if (mCurrentSceneId == 3)
+ {
+ sceneContainer* container = new sceneContainer(sceneItemGenericScene, new flashBankScene(mFilePath, mBankName, mLedColor), "", this, onFlashBankClosingCallback);
+ sceneManager::pushScene(container);
+ }
+
+ if (mCurrentSceneId == 4)
+ {
+ sceneManager::popScene();
+ }
+}
+
+void flashFlowScene::render()
+{
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashFlowScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashFlowScene.h
new file mode 100644
index 0000000..ba3bac9
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashFlowScene.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "scene.h"
+#include "filePickerScene.h"
+#include "keyboardScene.h"
+#include "ledColorSelectorScene.h"
+#include "flashBankScene.h"
+
+#include "..\xboxInternals.h"
+
+class flashFlowScene : public scene
+{
+public:
+ flashFlowScene();
+ ~flashFlowScene();
+ void update();
+ void render();
+private:
+ uint32_t mCurrentSceneId;
+ char* mFilePath;
+ char* mBankName;
+ uint8_t mLedColor;
+ static void onFilePickerClosingCallback(sceneResult result, void* context, scene* scene);
+ static void onKeyboardClosingCallback(sceneResult result, void* context, scene* scene);
+ static void onLedColorClosingCallback(sceneResult result, void* context, scene* scene);
+ static void onFlashBankClosingCallback(sceneResult result, void* context, scene* scene);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashUpdateFlowScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashUpdateFlowScene.cpp
new file mode 100644
index 0000000..bc003d8
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashUpdateFlowScene.cpp
@@ -0,0 +1,72 @@
+#include "flashUpdateFlowScene.h"
+#include "sceneManager.h"
+#include "filePickerScene.h"
+#include "flashUpdateScene.h"
+#include "audioSettingsScene.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxInternals.h"
+#include "..\fileSystem.h"
+
+void flashUpdateFlowScene::onFilePickerClosingCallback(sceneResult result, void* context, scene* scene)
+{
+ flashUpdateFlowScene* self = (flashUpdateFlowScene*)context;
+ if (result == sceneResultCancelled)
+ {
+ self->mCurrentSceneId = 2;
+ return;
+ }
+ filePickerScene* closingScene = (filePickerScene*)scene;
+ self->mFilePath = closingScene->getFilePath();
+ self->mCurrentSceneId = 1;
+}
+
+void flashUpdateFlowScene::onRFlashUpdateClosingCallback(sceneResult result, void* context, scene* scene)
+{
+ flashUpdateFlowScene* self = (flashUpdateFlowScene*)context;
+ self->mCurrentSceneId = 2;
+}
+
+flashUpdateFlowScene::flashUpdateFlowScene(bool recovery)
+{
+ mCurrentSceneId = 0;
+ mRecovery = recovery;
+ mFilePath = NULL;
+}
+
+flashUpdateFlowScene::~flashUpdateFlowScene()
+{
+ free(mFilePath);
+}
+
+void flashUpdateFlowScene::update()
+{
+ if (mCurrentSceneId == 0)
+ {
+ sceneContainer* container = new sceneContainer(sceneItemGenericScene, new filePickerScene(mRecovery ? filePickerTypeUpdateRecovery : filePickerTypeUpdate), "", this, onFilePickerClosingCallback);
+ sceneManager::pushScene(container);
+ return;
+ }
+
+ if (mCurrentSceneId == 1)
+ {
+ sceneContainer* container = new sceneContainer(sceneItemGenericScene, new flashUpdateScene(mRecovery, mFilePath), "", this, onFilePickerClosingCallback);
+ sceneManager::pushScene(container);
+ return;
+ }
+
+ if (mCurrentSceneId == 2)
+ {
+ sceneManager::popScene();
+ }
+}
+
+void flashUpdateFlowScene::render()
+{
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashUpdateFlowScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashUpdateFlowScene.h
new file mode 100644
index 0000000..f939b10
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashUpdateFlowScene.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "scene.h"
+
+#include "..\xboxInternals.h"
+
+class flashUpdateFlowScene : public scene
+{
+public:
+ flashUpdateFlowScene(bool recovery);
+ ~flashUpdateFlowScene();
+ void update();
+ void render();
+private:
+ uint32_t mCurrentSceneId;
+ bool mRecovery;
+ char* mFilePath;
+ static void onFilePickerClosingCallback(sceneResult result, void* context, scene* scene);
+ static void onRFlashUpdateClosingCallback(sceneResult result, void* context, scene* scene);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashUpdateScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashUpdateScene.cpp
new file mode 100644
index 0000000..6e7aef6
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashUpdateScene.cpp
@@ -0,0 +1,183 @@
+#include "flashUpdateScene.h"
+#include "sceneManager.h"
+
+#include "..\drawing.h"
+#include "..\ssfn.h"
+#include "..\component.h"
+#include "..\fileSystem.h"
+#include "..\utils.h"
+#include "..\theme.h"
+#include "..\stringUtility.h"
+#include "..\Threads\flashUpdate.h"
+
+flashUpdateScene::flashUpdateScene(bool recovery, const char* filePath)
+{
+ mProgress = strdup("Ready");
+ mStarted = false;
+ mDone = false;
+ mFailed = false;
+ mFilePath = strdup(filePath);
+ mRecovery = recovery;
+ mUpdate = true;
+}
+
+flashUpdateScene::~flashUpdateScene()
+{
+ free(mProgress);
+ free(mFilePath);
+}
+
+void flashUpdateScene::update()
+{
+ if (mStarted == false)
+ {
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene(sceneResultCancelled);
+ return;
+ }
+ else if (inputManager::buttonPressed(ButtonX))
+ {
+ mStarted = true;
+ flashUpdate::startThread(mRecovery, mUpdate, mFilePath);
+ }
+ else if (inputManager::buttonPressed(ButtonY))
+ {
+ mUpdate = !mUpdate;
+ }
+ return;
+ }
+
+ // Back Action
+
+ if (mDone == true)
+ {
+ if (mFailed == false && inputManager::buttonPressed(ButtonB))
+ {
+#ifndef TOOLS
+ if (mRecovery == true)
+ {
+ sceneManager::popScene(sceneResultDone);
+ return;
+ }
+ else
+ {
+ utils::reboot();
+ }
+#else
+ sceneManager::popScene(sceneResultDone);
+#endif
+ }
+ else if (mFailed == true && inputManager::buttonPressed(ButtonB))
+ {
+ mDone = false;
+ mFailed = false;
+ flashUpdate::startThread(mRecovery, mUpdate, mFilePath);
+ }
+ return;
+ }
+
+
+ if (mDone == false)
+ {
+ processResponse(flashUpdate::getResponse());
+ if (flashUpdate::completed() == true)
+ {
+ flashUpdate::closeThread();
+ mDone = true;
+ }
+ }
+}
+
+void flashUpdateScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Please wait...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ int yPos = (context::getBufferHeight() - (40 + 44)) / 2;
+ yPos += theme::getCenterOffset();
+
+ drawing::drawBitmapString(context::getBitmapFontMedium(), "Status", theme::getHeaderTextColor(), 193, yPos);
+
+ yPos += 40;
+
+ component::textBox(mProgress, false, false, horizAlignmentCenter, 193, yPos, 322, 44);
+
+ if (mStarted == false)
+ {
+ char* options = stringUtility::formatString("\xC2\xA3 To Confirm Update \xC2\xA4 Toggle Update/Restore (%s)", mUpdate ? "Update" : "Restore");
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), options, theme::getFooterTextColor(), horizAlignmentLeft, 40, theme::getFooterY(), 640);
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+ free(options);
+ }
+ else if (mDone == true)
+ {
+#ifndef TOOLS
+ if (mRecovery == true)
+ {
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), mFailed == true ? "\xC2\xA2 Retry" : "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+ }
+ else
+ {
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), mFailed == true ? "\xC2\xA2 Retry" : "\xC2\xA2 Reboot", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+ }
+#else
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), mFailed == true ? "\xC2\xA2 Retry" : "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+#endif
+ }
+}
+
+void flashUpdateScene::setProgress(const char* message)
+{
+ free(mProgress);
+ mProgress = strdup(message);
+}
+
+void flashUpdateScene::processResponse(flashUpdate::flashUpdateResponse response)
+{
+ uint32_t currentStep;
+ uint32_t totalSteps;
+ flashUpdate::getProgress(currentStep, totalSteps);
+
+ if (response == flashUpdate::flashUpdateResponseNone)
+ {
+ setProgress("");
+ }
+ else if (response == flashUpdate::flashUpdateProcessing)
+ {
+ setProgress("Processing");
+ }
+ else if (response == flashUpdate::flashUpdateFailedToLoadFile)
+ {
+ setProgress("Failed to load file");
+ }
+ else if (response == flashUpdate::flashUpdateErasing)
+ {
+ char* progress = stringUtility::formatString("Step %i of %i - Erasing", currentStep, totalSteps);
+ setProgress(progress);
+ free(progress);
+ }
+ else if (response == flashUpdate::flashUpdateWriting)
+ {
+ char* progress = stringUtility::formatString("Step %i of %i - Writing", currentStep, totalSteps);
+ setProgress(progress);
+ free(progress);
+ }
+ else if (response == flashUpdate::flashUpdateVerifying)
+ {
+ char* progress = stringUtility::formatString("Step %i of %i - Verifying", currentStep, totalSteps);
+ setProgress(progress);
+ free(progress);
+ }
+ else if (response == flashUpdate::flashUpdateVerificationFailed)
+ {
+ mFailed = true;
+ char* progress = stringUtility::formatString("Step %i of %i - Failed", currentStep, totalSteps);
+ setProgress(progress);
+ free(progress);
+ }
+ else if (response == flashUpdate::flashUpdateDone)
+ {
+ setProgress("Done");
+ }
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashUpdateScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashUpdateScene.h
new file mode 100644
index 0000000..d98a923
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/flashUpdateScene.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "scene.h"
+
+#include "..\utils.h"
+#include "..\Threads\flashUpdate.h"
+#include "..\xboxInternals.h"
+
+class flashUpdateScene : public scene
+{
+public:
+ flashUpdateScene(bool recovery, const char* filePath);
+ ~flashUpdateScene();
+ void update();
+ void render();
+private:
+ void setProgress(const char* message);
+ void processResponse(flashUpdate::flashUpdateResponse response);
+private:
+ bool mStarted;
+ bool mDone;
+ bool mFailed;
+ char* mProgress;
+ char* mFilePath;
+ bool mRecovery;
+ bool mUpdate;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/formatDriveScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/formatDriveScene.cpp
new file mode 100644
index 0000000..f7184d3
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/formatDriveScene.cpp
@@ -0,0 +1,151 @@
+#include "formatDriveScene.h"
+#include "sceneManager.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxConfig.h"
+#include "..\theme.h"
+#include "..\timeUtility.h"
+#include "..\harddrive.h"
+#include "..\Threads\hddFormat.h"
+#include "..\Threads\hddInfo.h"
+#include "..\XKUtils\XKHDD.h"
+
+formatDriveScene::formatDriveScene(int32_t harddrive)
+{
+ mHarddrive = harddrive;
+ mCounter = 0;
+ mProgress = strdup("Please wait...");
+ mIdeModel = strdup("Unknown");
+ mIdeSerial = strdup("Unknown");
+ mProcessing = false;
+ mInitialized = false;
+ mAllowFormat = false;
+ hddInfo::startThread(!!harddrive);
+}
+
+formatDriveScene::~formatDriveScene()
+{
+ free(mProgress);
+ free(mIdeModel);
+ free(mIdeSerial);
+}
+
+void formatDriveScene::update()
+{
+ if (mInitialized == false)
+ {
+ return;
+ }
+
+ // Exit Action
+
+ if (mProcessing == false && inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene();
+ return;
+ }
+
+ if(!mAllowFormat) {
+ return;
+ }
+
+ if (inputManager::buttonPressed(ButtonA))
+ {
+ if (mCounter >= 0 && mCounter < 1)
+ {
+ free(mProgress);
+ mProgress = strdup("Please Confirm again...");
+ mCounter++;
+ return;
+ }
+ }
+
+ if (mCounter == 1 && inputManager::buttonPressed(ButtonX)) {
+ mCounter++;
+ return;
+ }
+
+ if (mCounter == 2)
+ {
+ mProcessing = true;
+ hddFormat::startThread(mHarddrive);
+ free(mProgress);
+ mProgress = strdup("Please wait...");
+ mCounter++;
+ return;
+ }
+
+ if (mCounter == 3 && hddFormat::completed() == true)
+ {
+ mProcessing = false;
+ free(mProgress);
+ hddFormat::hddFormatResponse response = hddFormat::getResponse();
+ mProgress = strdup(response == hddFormat::hddFormatResponseFailure ? "Format failed." : "Format success.");
+ mCounter = 0;
+ return;
+ }
+}
+
+void formatDriveScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ char* title = stringUtility::formatString("Format %s Drive...", mHarddrive == 0 ? "Primary" : "Secondary");
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), title, theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+ free(title);
+
+ int yPos = (context::getBufferHeight() - (30 + 30 + 40 + 44)) / 2;
+ yPos += theme::getCenterOffset();
+
+ char* ideModel = stringUtility::formatString("Model: %s", mIdeModel);
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), ideModel, theme::getTextColor(), horizAlignmentCenter, 40, yPos, 640);
+ free(ideModel);
+
+ yPos += 30;
+
+ char* ideSerial = stringUtility::formatString("Serial: %s", mIdeSerial);
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), ideSerial, theme::getTextColor(), horizAlignmentCenter, 40, yPos, 640);
+ free(ideSerial);
+
+ yPos += 30;
+
+ drawing::drawBitmapString(context::getBitmapFontMedium(), "Status", theme::getHeaderTextColor(), 193, yPos);
+
+ yPos += 40;
+
+ if (mInitialized == false)
+ {
+ if (hddInfo::completed() == true)
+ {
+ free(mIdeModel);
+ free(mIdeSerial);
+ mIdeModel = hddInfo::getModel();
+ mIdeSerial = hddInfo::getSerial();
+ hddInfo::closeThread();
+ mInitialized = true;
+ mAllowFormat = hddInfo::getResponse() != hddInfo::hddInfoResponseTimeout;
+
+ free(mProgress);
+ if(mAllowFormat) {
+ mProgress = strdup("Please Confirm...");
+ }
+ else {
+ mProgress = strdup("Unable to detect HDD");
+ }
+ }
+ }
+
+ component::textBox(mProgress, false, false, horizAlignmentCenter, 193, yPos, 322, 44);
+
+ if(!mProcessing) {
+ drawing::drawBitmapString(context::getBitmapFontSmall(), mCounter == 1 ? "\xC2\xA3 Confirm Again" : "\xC2\xA1 Confirm", mInitialized && mAllowFormat ? theme::getFooterTextColor() : theme::getTextDisabledColor(), 40, theme::getFooterY());
+ }
+
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", mProcessing == false && mInitialized ? theme::getFooterTextColor() : theme::getTextDisabledColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/formatDriveScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/formatDriveScene.h
new file mode 100644
index 0000000..6882bb4
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/formatDriveScene.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "scene.h"
+#include "sceneManager.h"
+
+#include "../pointerMap.h"
+
+class formatDriveScene : public scene
+{
+public:
+ formatDriveScene(int32_t harddrive);
+ ~formatDriveScene();
+ void update();
+ void render();
+private:
+ int32_t mHarddrive;
+ int32_t mCounter;
+ char* mProgress;
+ bool mProcessing;
+ bool mNeedsReboot;
+ char* mIdeModel;
+ char* mIdeSerial;
+ bool mInitialized;
+ bool mAllowFormat;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/frontLedSelectorScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/frontLedSelectorScene.cpp
new file mode 100644
index 0000000..bb8010b
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/frontLedSelectorScene.cpp
@@ -0,0 +1,190 @@
+#include "frontLedSelectorScene.h"
+#include "sceneManager.h"
+#include "launchScene.h"
+#include "removeScene.h"
+#include "audioSettingsScene.h"
+#include "mainScene.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxInternals.h"
+#include "..\theme.h"
+
+frontLedSelectorScene::frontLedSelectorScene(const char* ledSequence)
+{
+ mSelectedControl = 0;
+ mLedSequence[0] = ledSequence[0];
+ mLedSequence[1] = ledSequence[1];
+ mLedSequence[2] = ledSequence[2];
+ mLedSequence[3] = ledSequence[3];
+}
+
+void frontLedSelectorScene::update()
+{
+ // Cancel Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene(sceneResultDone);
+ return;
+ }
+
+ // Select Actions
+
+ if (inputManager::buttonPressed(ButtonA))
+ {
+ const char colors[5] = { "GRAO" };
+ if (mSelectedControl >= 0 && mSelectedControl <= 3)
+ {
+ mLedSequence[0] = colors[mSelectedControl];
+ }
+ else if (mSelectedControl >= 4 && mSelectedControl <= 7)
+ {
+ mLedSequence[1] = colors[mSelectedControl - 4];
+ }
+ else if (mSelectedControl >= 8 && mSelectedControl <= 11)
+ {
+ mLedSequence[2] = colors[mSelectedControl - 8];
+ }
+ else if (mSelectedControl >= 12 && mSelectedControl <= 15)
+ {
+ mLedSequence[3] = colors[mSelectedControl - 12];
+ }
+ }
+
+ // Left Actions
+
+ if (inputManager::buttonPressed(ButtonDpadLeft))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 3)
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : 3;
+ }
+ else if (mSelectedControl >= 4 && mSelectedControl <= 7)
+ {
+ mSelectedControl = mSelectedControl > 4 ? mSelectedControl - 1 : 7;
+ }
+ else if (mSelectedControl >= 8 && mSelectedControl <= 11)
+ {
+ mSelectedControl = mSelectedControl > 8 ? mSelectedControl - 1 : 11;
+ }
+ else if (mSelectedControl >= 12 && mSelectedControl <= 15)
+ {
+ mSelectedControl = mSelectedControl > 12 ? mSelectedControl - 1 : 15;
+ }
+ }
+
+ // Right Actions
+
+ if (inputManager::buttonPressed(ButtonDpadRight))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 3)
+ {
+ mSelectedControl = mSelectedControl < 3 ? mSelectedControl + 1 : 0;
+ }
+ else if (mSelectedControl >= 4 && mSelectedControl <= 7)
+ {
+ mSelectedControl = mSelectedControl < 7 ? mSelectedControl + 1 : 4;
+ }
+ else if (mSelectedControl >= 8 && mSelectedControl <= 11)
+ {
+ mSelectedControl = mSelectedControl < 11 ? mSelectedControl + 1 : 8;
+ }
+ else if (mSelectedControl >= 12 && mSelectedControl <= 15)
+ {
+ mSelectedControl = mSelectedControl < 15 ? mSelectedControl + 1 : 12;
+ }
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 3)
+ {
+ mSelectedControl += 4;
+ }
+ else if (mSelectedControl >= 4 && mSelectedControl <= 7)
+ {
+ mSelectedControl += 4;
+ }
+ else if (mSelectedControl >= 8 && mSelectedControl <= 11)
+ {
+ mSelectedControl += 4;
+ }
+ else if (mSelectedControl >= 12 && mSelectedControl <= 15)
+ {
+ mSelectedControl -= 12;
+ }
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 3)
+ {
+ mSelectedControl += 12;
+ }
+ else if (mSelectedControl >= 4 && mSelectedControl <= 7)
+ {
+ mSelectedControl -= 4;
+ }
+ else if (mSelectedControl >= 8 && mSelectedControl <= 11)
+ {
+ mSelectedControl -= 4;
+ }
+ else if (mSelectedControl >= 12 && mSelectedControl <= 15)
+ {
+ mSelectedControl -= 4;
+ }
+ }
+}
+
+void frontLedSelectorScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Please select a Front LED Colors...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ int32_t ledX = 112;
+ int32_t ledY = (context::getBufferHeight() - (4 * 48) - 4) / 2;
+ ledY += theme::getCenterOffset();
+
+ component::text("State 1:", false, horizAlignmentLeft, ledX + (100 * 0), ledY + (48 * 0), 96, 44);
+ component::button(mSelectedControl == 0, mLedSequence[0] == 'G', "Green", ledX + (100 * 1), ledY + (48 * 0), 96, 44);
+ component::button(mSelectedControl == 1, mLedSequence[0] == 'R', "Red", ledX + (100 * 2), ledY + (48 * 0), 96, 44);
+ component::button(mSelectedControl == 2, mLedSequence[0] == 'A', "Amber", ledX + (100 * 3), ledY + (48 * 0), 96, 44);
+ component::button(mSelectedControl == 3, mLedSequence[0] == 'O', "Off", ledX + (100 * 4), ledY + (48 * 0), 96, 44);
+
+ component::text("State 2:", false, horizAlignmentLeft, ledX + (100 * 0), ledY + (48 * 1), 96, 44);
+ component::button(mSelectedControl == 4, mLedSequence[1] == 'G', "Green", ledX + (100 * 1), ledY + (48 * 1), 96, 44);
+ component::button(mSelectedControl == 5, mLedSequence[1] == 'R', "Red", ledX + (100 * 2), ledY + (48 * 1), 96, 44);
+ component::button(mSelectedControl == 6, mLedSequence[1] == 'A', "Amber", ledX + (100 * 3), ledY + (48 * 1), 96, 44);
+ component::button(mSelectedControl == 7, mLedSequence[1] == 'O', "Off", ledX + (100 * 4), ledY + (48 * 1), 96, 44);
+
+ component::text("State 3:", false, horizAlignmentLeft, ledX + (100 * 0), ledY + (48 * 2), 96, 44);
+ component::button(mSelectedControl == 8, mLedSequence[2] == 'G', "Green", ledX + (100 * 1), ledY + (48 * 2), 96, 44);
+ component::button(mSelectedControl == 9, mLedSequence[2] == 'R', "Red", ledX + (100 * 2), ledY + (48 * 2), 96, 44);
+ component::button(mSelectedControl == 10, mLedSequence[2] == 'A', "Amber", ledX + (100 * 3), ledY + (48 * 2), 96, 44);
+ component::button(mSelectedControl == 11, mLedSequence[2] == 'O', "Off", ledX + (100 * 4), ledY + (48 * 2), 96, 44);
+
+ component::text("State 4:", false, horizAlignmentLeft, ledX + (100 * 0), ledY + (48 * 3), 96, 44);
+ component::button(mSelectedControl == 12, mLedSequence[3] == 'G', "Green", ledX + (100 * 1), ledY + (48 * 3), 96, 44);
+ component::button(mSelectedControl == 13, mLedSequence[3] == 'R', "Red", ledX + (100 * 2), ledY + (48 * 3), 96, 44);
+ component::button(mSelectedControl == 14, mLedSequence[3] == 'A', "Amber", ledX + (100 * 3), ledY + (48 * 3), 96, 44);
+ component::button(mSelectedControl == 15, mLedSequence[3] == 'O', "Off", ledX + (100 * 4), ledY + (48 * 3), 96, 44);
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Select", theme::getFooterTextColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
+
+char* frontLedSelectorScene::getLedSequence()
+{
+ return stringUtility::formatString("%c%c%c%c", mLedSequence[0], mLedSequence[1], mLedSequence[2], mLedSequence[3]);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/frontLedSelectorScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/frontLedSelectorScene.h
new file mode 100644
index 0000000..f8ec57f
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/frontLedSelectorScene.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "scene.h"
+
+#include "..\xboxInternals.h"
+
+class frontLedSelectorScene : public scene
+{
+public:
+ frontLedSelectorScene(const char* ledSequence);
+ void update();
+ void render();
+ char* getLedSequence();
+private:
+ int mSelectedControl;
+ char mLedSequence[4];
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hddLockUnlockScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hddLockUnlockScene.cpp
new file mode 100644
index 0000000..8684222
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hddLockUnlockScene.cpp
@@ -0,0 +1,231 @@
+#include "hddLockUnlockScene.h"
+#include "sceneManager.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\audioPlayer.h"
+#include "..\hdmiDevice.h"
+#include "..\ftpServer.h"
+#include "..\stringUtility.h"
+#include "..\xboxConfig.h"
+#include "..\theme.h"
+#include "..\Threads\hddLockUnlock.h"
+#include "..\Threads\hddInfo.h"
+
+hddLockUnlockScene::hddLockUnlockScene()
+{
+ audioPlayer::pause(true);
+ mStep = -1;
+ mProgress = strdup("Please wait...");
+ mIdeModel = strdup("Unknown");
+ mIdeSerial = strdup("Unknown");
+ mFailed = false;
+ mInitialized = false;
+ hddInfo::startThread();
+}
+
+hddLockUnlockScene::~hddLockUnlockScene()
+{
+ free(mProgress);
+ free(mIdeModel);
+ free(mIdeSerial);
+}
+
+void hddLockUnlockScene::update()
+{
+ if (mInitialized == false || mStep != -1)
+ {
+ return;
+ }
+
+ // Exit Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ audioPlayer::pause(false);
+ sceneManager::popScene();
+ return;
+ }
+
+ // Lock / Unlock Action
+
+ if (mFailed == false && inputManager::buttonPressed(ButtonA) && mStep == -1)
+ {
+ mStep = 0;
+ }
+}
+
+void hddLockUnlockScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "HDD Lock / Unlock...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ int yPos = (context::getBufferHeight() - (30 + 30 + 40 + 44)) / 2;
+ yPos += theme::getCenterOffset();
+
+ char* ideModel = stringUtility::formatString("Model: %s", mIdeModel);
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), ideModel, theme::getTextColor(), horizAlignmentCenter, 40, yPos, 640);
+ free(ideModel);
+
+ yPos += 30;
+
+ char* ideSerial = stringUtility::formatString("Serial: %s", mIdeSerial);
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), ideSerial, theme::getTextColor(), horizAlignmentCenter, 40, yPos, 640);
+ free(ideSerial);
+
+ yPos += 30;
+
+ drawing::drawBitmapString(context::getBitmapFontMedium(), "Status", theme::getHeaderTextColor(), 193, yPos);
+
+ yPos += 40;
+
+ if (mInitialized == false)
+ {
+ if (hddInfo::completed() == true)
+ {
+ hddInfo::hddInfoResponse response = hddInfo::getResponse();
+ if (response == hddInfo::hddInfoResponseFailureEeprom)
+ {
+ setProgress("Unable to get info");
+ mFailed = true;
+ }
+ else if (response == hddInfo::hddInfoResponseLocked)
+ {
+ setProgress("Locked");
+ mHddLocked = true;
+ }
+ else if (response == hddInfo::hddInfoResponseUnlocked)
+ {
+ setProgress("Unlocked");
+ mHddLocked = false;
+ }
+ free(mIdeModel);
+ free(mIdeSerial);
+ mIdeModel = hddInfo::getModel();
+ mIdeSerial = hddInfo::getSerial();
+ hddInfo::closeThread();
+ mInitialized = true;
+ }
+ }
+ else if (mHddLocked)
+ {
+ if (mStep == 0)
+ {
+ setProgress("Unlocking...");
+ mStep = 1;
+ }
+ else if (mStep == 1)
+ {
+ hddLockUnlock::startThread(hddLockUnlock::hddLockUnlockActionUnlock);
+ mStep = 2;
+ }
+ else if (mStep == 2)
+ {
+ processResponse(hddLockUnlock::getResponse());
+ if (hddLockUnlock::completed() == true)
+ {
+ hddLockUnlock::hddLockUnlockResponse response = hddLockUnlock::getResponse();
+ if (response == hddLockUnlock::hddLockUnlockResponseUnlockedVsc)
+ {
+ hddLockUnlock::closeThread();
+ ftpServer::close();
+ sceneManager::pushScene(sceneItemHddPasswordScene);
+ return;
+ }
+ hddLockUnlock::closeThread();
+ mStep = -1;
+ }
+ }
+ }
+ else
+ {
+ if (mStep == 0)
+ {
+ setProgress("Locking...");
+ mStep = 1;
+ }
+ else if (mStep == 1)
+ {
+ hddLockUnlock::startThread(hddLockUnlock::hddLockUnlockActionLock);
+ mStep = 2;
+ }
+ else if (mStep == 2)
+ {
+ processResponse(hddLockUnlock::getResponse());
+ if (hddLockUnlock::completed() == true)
+ {
+ hddLockUnlock::closeThread();
+ mStep = -1;
+ }
+ }
+ }
+
+ component::textBox(mProgress, false, false, horizAlignmentCenter, 193, yPos, 322, 44);
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Toggle HDD Lock", mInitialized ? theme::getFooterTextColor() : theme::getTextDisabledColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Cancel", mStep == -1 ? theme::getFooterTextColor() : theme::getTextDisabledColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
+
+void hddLockUnlockScene::setProgress(const char* message)
+{
+ free(mProgress);
+ mProgress = strdup(message);
+}
+
+void hddLockUnlockScene::processResponse(hddLockUnlock::hddLockUnlockResponse response)
+{
+ if (response == hddLockUnlock::hddLockUnlockResponseNone)
+ {
+ setProgress("");
+ }
+ else if (response == hddLockUnlock::hddLockUnlockResponseUnlocked)
+ {
+ setProgress("Unlocked");
+ mHddLocked = false;
+ }
+ else if (response == hddLockUnlock::hddLockUnlockResponseFailedToUnlock)
+ {
+ setProgress("Failed to unlock HDD");
+ }
+ else if (response == hddLockUnlock::hddLockUnlockResponseAlreadyUnlocked)
+ {
+ setProgress("Already unlocked");
+ }
+ else if (response == hddLockUnlock::hddLockUnlockResponseLocked)
+ {
+ setProgress("Locked");
+ mHddLocked = true;
+ }
+ else if (response == hddLockUnlock::hddLockUnlockResponseFailedToLock)
+ {
+ setProgress("Failed to lock HDD");
+ }
+ else if (response == hddLockUnlock::hddLockUnlockResponseAlreadyLocked)
+ {
+ setProgress("Already locked");
+ }
+ else if (response == hddLockUnlock::hddLockUnlockResponseLockingNotSupported)
+ {
+ setProgress("Locking not supported");
+ }
+ else if (response == hddLockUnlock::hddLockUnlockResponseFailureEeprom)
+ {
+ setProgress("Unable to decrypt EEPROM");
+ }
+ else if (response == hddLockUnlock::hddLockUnlockResponseUnlocking)
+ {
+ setProgress("Unlocking...");
+ }
+ else if (response == hddLockUnlock::hddLockUnlockResponseUnlockingVsc)
+ {
+ setProgress("VSC Unlocking...");
+ }
+ else if (response == hddLockUnlock::hddLockUnlockResponseLocking)
+ {
+ setProgress("Locking...");
+ }
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hddLockUnlockScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hddLockUnlockScene.h
new file mode 100644
index 0000000..f53ba91
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hddLockUnlockScene.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "scene.h"
+
+#include "..\Threads\hddLockUnlock.h"
+
+class hddLockUnlockScene : public scene
+{
+public:
+ hddLockUnlockScene();
+ ~hddLockUnlockScene();
+ void update();
+ void render();
+private:
+ void setProgress(const char* message);
+ void processResponse(hddLockUnlock::hddLockUnlockResponse response);
+private:
+ bool mHddLocked;
+ int mStep;
+ char* mProgress;
+ char* mIdeModel;
+ char* mIdeSerial;
+ bool mFailed;
+ bool mInitialized;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hddPasswordScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hddPasswordScene.cpp
new file mode 100644
index 0000000..6219bc1
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hddPasswordScene.cpp
@@ -0,0 +1,102 @@
+#include "hddPasswordScene.h"
+#include "sceneManager.h"
+
+#include "..\theme.h"
+#include "..\utils.h"
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\inputManager.h"
+#include "..\stringUtility.h"
+#include "..\hdmiSettingsManager.h"
+#include "..\hdmiDevice.h"
+
+hddPasswordScene::hddPasswordScene()
+{
+ mSelectedControl = 0;
+}
+
+void hddPasswordScene::update()
+{
+ // Back Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ utils::reboot();
+ }
+}
+
+void hddPasswordScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "VSC HDD Password...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ int yPos = (context::getBufferHeight() - (50 + 30 + 30 + 30 + 70 + 30 + 60)) / 2;
+ yPos += theme::getCenterOffset();
+
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "** HDD UNLOCKED, COPY THESE DETAILS AND KEEP SAFE **", theme::getTextColor(), horizAlignmentCenter, 40, yPos, 640);
+ yPos += 50;
+ char* driveModel = context::getDriveModel();
+ char* driveModelString = stringUtility::formatString("Model: %s", driveModel);
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), driveModelString, theme::getTextColor(), horizAlignmentCenter, 40, yPos, 640);
+ free(driveModelString);
+ free(driveModel);
+ yPos += 30;
+ char* driveSerial = context::getDriveSerial();
+ char* driveSerialString = stringUtility::formatString("Serial: %s", driveSerial);
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), driveSerialString, theme::getTextColor(), horizAlignmentCenter, 40, yPos, 640);
+ free(driveSerialString);
+ free(driveSerial);
+ yPos += 30;
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "Master Password", theme::getTextColor(), 40, yPos);
+ yPos += 30;
+ utils::dataContainer* password1String = new utils::dataContainer(16);
+ utils::dataContainer* password2String = new utils::dataContainer(16);
+ if (context::getMasterPassword() != NULL)
+ {
+ for (int i = 0; i < 16; i++)
+ {
+ uint8_t char1 = (uint8_t)context::getMasterPassword()->data[i];
+ uint8_t char2 = (uint8_t)context::getMasterPassword()->data[i + 16];
+
+ char* hex1 = stringUtility::formatString("%02x", char1);
+ char* hex2 = stringUtility::formatString("%02x", char2);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), hex1, theme::getFooterTextColor(), 40 + (i * 22), yPos);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), hex2, theme::getFooterTextColor(), 40 + (i * 22), yPos + 30);
+ free(hex2);
+ free(hex1);
+
+ password1String->data[i] = (char1 < 0x20 || char1 > 0x7e) ? 0x20 : (char)char1;
+ password2String->data[i] = (char1 < 0x20 || char1 > 0x7e) ? 0x20 : (char)char2;
+ }
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), password1String->data, theme::getFooterTextColor(), horizAlignmentRight, 40, yPos, 640);
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), password2String->data, theme::getFooterTextColor(), horizAlignmentRight, 40, yPos + 30, 640);
+ }
+ yPos += 70;
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "User Password", theme::getTextColor(), 40, yPos);
+ yPos += 30;
+ if (context::getUserPassword() != NULL)
+ {
+ for (int i = 0; i < 16; i++)
+ {
+ uint8_t char1 = (uint8_t)context::getUserPassword()->data[i];
+ uint8_t char2 = (uint8_t)context::getUserPassword()->data[i + 16];
+
+ char* hex1 = stringUtility::formatString("%02x", char1);
+ char* hex2 = stringUtility::formatString("%02x", char2);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), hex1, theme::getFooterTextColor(), 40 + (i * 22), yPos);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), hex2, theme::getFooterTextColor(), 40 + (i * 22), yPos + 30);
+ free(hex2);
+ free(hex1);
+
+ password1String->data[i] = (char1 < 0x20 || char1 > 0x7e) ? 0x20 : (char)char1;
+ password2String->data[i] = (char1 < 0x20 || char1 > 0x7e) ? 0x20 : (char)char2;
+ }
+
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), password1String->data, theme::getFooterTextColor(), horizAlignmentRight, 40, yPos, 640);
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), password2String->data, theme::getFooterTextColor(), horizAlignmentRight, 40, yPos + 30, 640);
+ }
+ delete(password1String);
+ delete(password2String);
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Reboot", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hddPasswordScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hddPasswordScene.h
new file mode 100644
index 0000000..fce1f0e
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hddPasswordScene.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "scene.h"
+
+class hddPasswordScene : public scene
+{
+public:
+ hddPasswordScene();
+ void update();
+ void render();
+private:
+ int mSelectedControl;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hdmiAdvancedScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hdmiAdvancedScene.cpp
new file mode 100644
index 0000000..a025c1d
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hdmiAdvancedScene.cpp
@@ -0,0 +1,167 @@
+#include "hdmiAdvancedScene.h"
+#include "sceneManager.h"
+
+#include "..\theme.h"
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\inputManager.h"
+#include "..\hdmiSettingsManager.h"
+#include "..\hdmiDevice.h"
+
+hdmiAdvancedScene::hdmiAdvancedScene()
+{
+ mSelectedControl = 0;
+}
+
+void hdmiAdvancedScene::update()
+{
+ // Back Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene();
+ return;
+ }
+
+ // Select Actions
+
+ if (inputManager::buttonPressed(ButtonA))
+ {
+ hdmiSettingsState* settings = hdmiSettingsManager::getSettings();
+
+ if (mSelectedControl == 0)
+ {
+ settings->colorspace = 0;
+ hdmiSettingsManager::saveSettings();
+ }
+ else if (mSelectedControl == 1)
+ {
+ settings->colorspace = 1;
+ hdmiSettingsManager::saveSettings();
+ }
+ else if (mSelectedControl == 2)
+ {
+ settings->interpolation = 0;
+ hdmiSettingsManager::saveSettings();
+ }
+ else if (mSelectedControl == 3)
+ {
+ settings->interpolation = 1;
+ hdmiSettingsManager::saveSettings();
+ }
+ else if (mSelectedControl == 4)
+ {
+ settings->autoVideoBlank = settings->autoVideoBlank == 0 ? 1 : 0;
+ hdmiSettingsManager::saveSettings();
+ }
+ else if (mSelectedControl == 5)
+ {
+ settings->autoRegionSwitch = settings->autoRegionSwitch == 0 ? 1 : 0;
+ hdmiSettingsManager::saveSettings();
+ }
+ }
+
+ // Left Actions
+
+ if (inputManager::buttonPressed(ButtonDpadLeft))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 1)
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : 1;
+ }
+ else if (mSelectedControl >= 2 && mSelectedControl <= 3)
+ {
+ mSelectedControl = mSelectedControl > 2 ? mSelectedControl - 1 : 3;
+ }
+ }
+
+ // Right Actions
+
+ if (inputManager::buttonPressed(ButtonDpadRight))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 1)
+ {
+ mSelectedControl = mSelectedControl < 1 ? mSelectedControl + 1 : 0;
+ }
+ else if (mSelectedControl >= 2 && mSelectedControl <= 3)
+ {
+ mSelectedControl = mSelectedControl < 3 ? mSelectedControl + 1 : 2;
+ }
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 1)
+ {
+ mSelectedControl = 2;
+ }
+ else if (mSelectedControl >= 2 && mSelectedControl <= 3)
+ {
+ mSelectedControl = 4;
+ }
+ else if (mSelectedControl == 4)
+ {
+ mSelectedControl = 5;
+ }
+ else if (mSelectedControl == 5)
+ {
+ mSelectedControl = 0;
+ }
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 1)
+ {
+ mSelectedControl = 5;
+ }
+ else if (mSelectedControl >= 2 && mSelectedControl <= 3)
+ {
+ mSelectedControl = 0;
+ }
+ else if (mSelectedControl == 4)
+ {
+ mSelectedControl = 2;
+ }
+ else if (mSelectedControl == 5)
+ {
+ mSelectedControl = 4;
+ }
+ }
+}
+
+void hdmiAdvancedScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "HDMI Advanced settings...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ int xPos = 117;
+ int yPos = (context::getBufferHeight() - (30 + 40 + 30 + 40 + 30 + 40 + 30)) / 2;
+ yPos += theme::getCenterOffset();
+
+ hdmiSettingsState* settings = hdmiSettingsManager::getSettings();
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "HDMI Colorspace", theme::getTextColor(), xPos, yPos);
+ yPos += 30;
+ component::button(mSelectedControl == 0, settings->colorspace == 0, "YCBCR", xPos, yPos, 241, 30);
+ component::button(mSelectedControl == 1, settings->colorspace == 1, "RGB", xPos + 245, yPos, 241, 30);
+ yPos += 40;
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "Upscaling Interpolation", theme::getTextColor(), xPos, yPos);
+ yPos += 30;
+ component::button(mSelectedControl == 2, settings->interpolation == 0, "Bilinear", xPos, yPos, 241, 30);
+ component::button(mSelectedControl == 3, settings->interpolation == 1, "Truncate", xPos + 245, yPos, 241, 30);
+ yPos += 40;
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "Other", theme::getTextColor(), xPos, yPos);
+ yPos += 30;
+ component::button(mSelectedControl == 4, false, settings->autoVideoBlank == 1 ? "Auto Video Blanking: Enabled" : "Auto Video Blanking: Disabled", xPos, yPos, 488, 30);
+ yPos += 40;
+ component::button(mSelectedControl == 5, false, settings->autoRegionSwitch == 1 ? "Auto Region Switching: Enabled" : "Auto Region Switching: Disabled", xPos, yPos, 488, 30);
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Select", theme::getFooterTextColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hdmiAdvancedScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hdmiAdvancedScene.h
new file mode 100644
index 0000000..0daeb43
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hdmiAdvancedScene.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "scene.h"
+
+class hdmiAdvancedScene : public scene
+{
+public:
+ hdmiAdvancedScene();
+ void update();
+ void render();
+private:
+ int mSelectedControl;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hdmiInterpolationScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hdmiInterpolationScene.cpp
new file mode 100644
index 0000000..4aeab32
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hdmiInterpolationScene.cpp
@@ -0,0 +1,195 @@
+#include "hdmiInterpolationScene.h"
+#include "hdmiAdvancedScene.h"
+#include "sceneManager.h"
+
+#include "..\theme.h"
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\inputManager.h"
+#include "..\hdmiSettingsManager.h"
+#include "..\hdmiDevice.h"
+
+hdmiInterpolationScene::hdmiInterpolationScene()
+{
+ mSelectedControl = 0;
+}
+
+void hdmiInterpolationScene::update()
+{
+ // Back Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene();
+ return;
+ }
+
+ // Select Actions
+
+ if (inputManager::buttonPressed(ButtonA))
+ {
+ hdmiSettingsState* settings = hdmiSettingsManager::getSettings();
+
+ if (mSelectedControl == 0)
+ {
+ settings->interpolationScaleX = 0;
+ hdmiSettingsManager::saveSettings();
+ }
+ else if (mSelectedControl == 1)
+ {
+ settings->interpolationScaleX = 1;
+ hdmiSettingsManager::saveSettings();
+ }
+ else if (mSelectedControl == 2)
+ {
+ settings->interpolationScaleY = 0;
+ hdmiSettingsManager::saveSettings();
+ }
+ else if (mSelectedControl == 3)
+ {
+ settings->interpolationScaleY = 1;
+ hdmiSettingsManager::saveSettings();
+ }
+ else if (mSelectedControl == 4)
+ {
+ settings->interpolationWeightX = 0;
+ hdmiSettingsManager::saveSettings();
+ }
+ else if (mSelectedControl == 5)
+ {
+ settings->interpolationWeightX = 1;
+ hdmiSettingsManager::saveSettings();
+ }
+ else if (mSelectedControl == 6)
+ {
+ settings->interpolationWeightY = 0;
+ hdmiSettingsManager::saveSettings();
+ }
+ else if (mSelectedControl == 7)
+ {
+ settings->interpolationWeightY = 1;
+ hdmiSettingsManager::saveSettings();
+ }
+ }
+
+ // Left Actions
+
+ if (inputManager::buttonPressed(ButtonDpadLeft))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 1)
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : 1;
+ }
+ else if (mSelectedControl >= 2 && mSelectedControl <= 3)
+ {
+ mSelectedControl = mSelectedControl > 2 ? mSelectedControl - 1 : 3;
+ }
+ else if (mSelectedControl >= 4 && mSelectedControl <= 5)
+ {
+ mSelectedControl = mSelectedControl > 4 ? mSelectedControl - 1 : 5;
+ }
+ else if (mSelectedControl >= 6 && mSelectedControl <= 7)
+ {
+ mSelectedControl = mSelectedControl > 6 ? mSelectedControl - 1 : 7;
+ }
+ }
+
+ // Right Actions
+
+ if (inputManager::buttonPressed(ButtonDpadRight))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 1)
+ {
+ mSelectedControl = mSelectedControl < 1 ? mSelectedControl + 1 : 0;
+ }
+ else if (mSelectedControl >= 2 && mSelectedControl <= 3)
+ {
+ mSelectedControl = mSelectedControl < 3 ? mSelectedControl + 1 : 2;
+ }
+ else if (mSelectedControl >= 4 && mSelectedControl <= 5)
+ {
+ mSelectedControl = mSelectedControl < 5 ? mSelectedControl + 1 : 4;
+ }
+ else if (mSelectedControl >= 6 && mSelectedControl <= 7)
+ {
+ mSelectedControl = mSelectedControl < 7 ? mSelectedControl + 1 : 6;
+ }
+ }
+
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 1)
+ {
+ mSelectedControl = 2;
+ }
+ else if (mSelectedControl >= 2 && mSelectedControl <= 3)
+ {
+ mSelectedControl = 4;
+ }
+ else if (mSelectedControl >= 4 && mSelectedControl <= 5)
+ {
+ mSelectedControl = 6;
+ }
+ else if (mSelectedControl >= 6 && mSelectedControl <= 7)
+ {
+ mSelectedControl = 0;
+ }
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 1)
+ {
+ mSelectedControl = 6;
+ }
+ else if (mSelectedControl >= 2 && mSelectedControl <= 3)
+ {
+ mSelectedControl = 0;
+ }
+ else if (mSelectedControl >= 4 && mSelectedControl <= 5)
+ {
+ mSelectedControl = 2;
+ }
+ else if (mSelectedControl >= 6 && mSelectedControl <= 7)
+ {
+ mSelectedControl = 4;
+ }
+ }
+}
+
+void hdmiInterpolationScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "HDMI Interpolation settings...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ int xPos = 117;
+ int yPos = (context::getBufferHeight() - (30 + 40 + 40 + 30 + 40 + 30)) / 2;
+ yPos += theme::getCenterOffset();
+
+ hdmiSettingsState* settings = hdmiSettingsManager::getSettings();
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "Scale", theme::getTextColor(), xPos, yPos);
+ yPos += 30;
+ component::button(mSelectedControl == 0, settings->interpolationScaleX == 0, "X - Bilinear", xPos, yPos, 241, 30);
+ component::button(mSelectedControl == 1, settings->interpolationScaleX == 1, "X - Truncate", xPos + 245, yPos, 241, 30);
+ yPos += 40;
+ component::button(mSelectedControl == 2, settings->interpolationScaleY == 0, "Y - Bilinear", xPos, yPos, 241, 30);
+ component::button(mSelectedControl == 3, settings->interpolationScaleY == 1, "Y - Truncate", xPos + 245, yPos, 241, 30);
+ yPos += 40;
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "Weight", theme::getTextColor(), xPos, yPos);
+ yPos += 30;
+ component::button(mSelectedControl == 4, settings->interpolationWeightX == 0, "X - Bilinear", xPos, yPos, 241, 30);
+ component::button(mSelectedControl == 5, settings->interpolationWeightX == 1, "X - Truncate", xPos + 245, yPos, 241, 30);
+ yPos += 40;
+ component::button(mSelectedControl == 6, settings->interpolationWeightY == 0, "Y - Bilinear", xPos, yPos, 241, 30);
+ component::button(mSelectedControl == 7, settings->interpolationWeightY == 1, "Y - Truncate", xPos + 245, yPos, 241, 30);
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Select", theme::getFooterTextColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hdmiInterpolationScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hdmiInterpolationScene.h
new file mode 100644
index 0000000..ec069f9
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hdmiInterpolationScene.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "scene.h"
+
+class hdmiInterpolationScene : public scene
+{
+public:
+ hdmiInterpolationScene();
+ void update();
+ void render();
+private:
+ int mSelectedControl;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hdmiVideoSettingsScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hdmiVideoSettingsScene.cpp
new file mode 100644
index 0000000..9b8a972
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hdmiVideoSettingsScene.cpp
@@ -0,0 +1,171 @@
+#include "hdmiVideoSettingsScene.h"
+#include "sceneManager.h"
+
+#include "..\theme.h"
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\inputManager.h"
+#include "..\hdmiSettingsManager.h"
+#include "..\hdmiDevice.h"
+
+hdmiVideoSettingsScene::hdmiVideoSettingsScene()
+{
+ mSelectedControl = 0;
+}
+
+void hdmiVideoSettingsScene::update()
+{
+ // Back Action
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene();
+ return;
+ }
+
+ // Select Actions
+ if (inputManager::buttonPressed(ButtonA))
+ {
+ hdmiSettingsState* settings = hdmiSettingsManager::getSettings();
+
+ if (mSelectedControl == 0)
+ {
+ settings->outputResolution = 0;
+ hdmiSettingsManager::saveSettings();
+ }
+ else if (mSelectedControl == 1)
+ {
+ settings->outputResolution = 1;
+ hdmiSettingsManager::saveSettings();
+ }
+ else if (mSelectedControl == 2)
+ {
+ settings->widescreen = 0; // Set to Auto
+ hdmiSettingsManager::saveSettings();
+ }
+ else if (mSelectedControl == 3)
+ {
+ settings->widescreen = 1; // Set to Force
+ hdmiSettingsManager::saveSettings();
+ }
+ else if (mSelectedControl == 4)
+ {
+ settings->widescreen = 2; // Set to Never
+ hdmiSettingsManager::saveSettings();
+ }
+ else if (mSelectedControl == 5)
+ {
+ settings->prescaleFixDisable = settings->prescaleFixDisable == 0 ? 1 : 0;
+ hdmiSettingsManager::saveSettings();
+ }
+ else if (mSelectedControl == 6)
+ {
+ settings->disable480p169 = settings->disable480p169 == 0 ? 1 : 0;
+ hdmiSettingsManager::saveSettings();
+ }
+ }
+
+ // Left Actions
+
+ if (inputManager::buttonPressed(ButtonDpadLeft))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 1)
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : 1;
+ }
+ else if (mSelectedControl >= 2 && mSelectedControl <= 4)
+ {
+ mSelectedControl = mSelectedControl > 2 ? mSelectedControl - 1 : 4;
+ }
+ }
+
+ // Right Actions
+
+ if (inputManager::buttonPressed(ButtonDpadRight))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 1)
+ {
+ mSelectedControl = mSelectedControl < 1 ? mSelectedControl + 1 : 0;
+ }
+ else if (mSelectedControl >= 2 && mSelectedControl <= 4)
+ {
+ mSelectedControl = mSelectedControl < 4 ? mSelectedControl + 1 : 2;
+ }
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 1)
+ {
+ mSelectedControl = 2;
+ }
+ else if (mSelectedControl >= 2 && mSelectedControl <= 4)
+ {
+ mSelectedControl = 5;
+ }
+ else if (mSelectedControl == 5)
+ {
+ mSelectedControl = 6;
+ }
+ else if (mSelectedControl == 6)
+ {
+ mSelectedControl = 0;
+ }
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 1)
+ {
+ mSelectedControl = 6;
+ }
+ else if (mSelectedControl >= 2 && mSelectedControl <= 4)
+ {
+ mSelectedControl = 0;
+ }
+ else if (mSelectedControl == 5)
+ {
+ mSelectedControl = 2;
+ }
+ else if (mSelectedControl == 6)
+ {
+ mSelectedControl = 5;
+ }
+ }
+}
+
+void hdmiVideoSettingsScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "HDMI Video settings...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ hdmiSettingsState* settings = hdmiSettingsManager::getSettings();
+
+ int xPos = 117;
+ int yPos = (context::getBufferHeight() - (30 + 40 + 30 + 40 + 30 + 40 + 30)) / 2;
+ yPos += theme::getCenterOffset();
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "Target Resolution (Upscale)", theme::getTextColor(), xPos, yPos);
+ yPos += 30;
+ component::button(mSelectedControl == 0, settings->outputResolution == 0, "480p", xPos, yPos, 241, 30);
+ component::button(mSelectedControl == 1, settings->outputResolution == 1, "720p", xPos + 245, yPos, 241, 30);
+ yPos += 40;
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "4:3 Widescreen", theme::getTextColor(), xPos, yPos);
+ yPos += 30;
+ component::button(mSelectedControl == 2, settings->widescreen == 0, "Auto", xPos, yPos, 160, 30);
+ component::button(mSelectedControl == 3, settings->widescreen == 1, "Force", xPos + 164, yPos, 160, 30);
+ component::button(mSelectedControl == 4, settings->widescreen == 2, "Never", xPos + (164 * 2), yPos, 160, 30);
+ yPos += 40;
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "Other", theme::getTextColor(), xPos, yPos);
+ yPos += 30;
+ component::button(mSelectedControl == 5, false, settings->prescaleFixDisable == 0 ? "Pre-scale 480p: Enabled" : "Pre-scale 480p: Disabled", xPos, yPos, 488, 30);
+ yPos += 40;
+ component::button(mSelectedControl == 6, false, settings->disable480p169 == 0 ? "Assume 16:9 480p: Enabled" : "Assume 16:9 480p: Disabled", xPos, yPos, 488, 30);
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Select", theme::getFooterTextColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hdmiVideoSettingsScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hdmiVideoSettingsScene.h
new file mode 100644
index 0000000..ffffa97
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/hdmiVideoSettingsScene.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "scene.h"
+
+class hdmiVideoSettingsScene : public scene
+{
+public:
+ hdmiVideoSettingsScene();
+ void update();
+ void render();
+private:
+ int mSelectedControl;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/invadersScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/invadersScene.cpp
new file mode 100644
index 0000000..1728f53
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/invadersScene.cpp
@@ -0,0 +1,358 @@
+#include "invadersScene.h"
+#include "sceneManager.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxConfig.h"
+#include "..\theme.h"
+#include "..\timeUtility.h"
+
+invadersScene::invadersScene()
+{
+ mCounter = 0;
+ mPlayerScore = 0;
+ restart(0);
+}
+
+void invadersScene::update()
+{
+ // Exit Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene();
+ return;
+ }
+
+ //// Select Actions
+
+ if (mIsGameOver == true)
+ {
+ if (inputManager::buttonPressed(ButtonA))
+ {
+ restart(0);
+ }
+ return;
+ }
+
+ // Left Actions
+
+ if (inputManager::buttonDown(ButtonDpadLeft) && mPlayerX > 0)
+ {
+ mPlayerX -= 5;
+ }
+
+ // Right Actions
+
+ if (inputManager::buttonDown(ButtonDpadRight) && mPlayerX < ((mWidth * 10) - 20))
+ {
+ mPlayerX += 5;
+ }
+
+ // Fire Action
+
+ if (inputManager::buttonPressed(ButtonA) && mBulletDestroyed == true)
+ {
+ mBulletX = mPlayerX + 5;
+ mBulletY = (mHeight - 2) * 10;
+ mBulletDestroyed = false;
+ }
+
+ if (mBulletDestroyed == false)
+ {
+ mBulletY -= 5;
+ if (mBulletY < 0)
+ {
+ mBulletDestroyed = true;
+ }
+ }
+
+ int totalInvaders = 0;
+ for (int i = 0; i < 44; i++)
+ {
+ Invader* invader = &mInvaders[i];
+ if (invader->invaderDestroyed == false)
+ {
+ totalInvaders++;
+ if (mBulletDestroyed == false)
+ {
+ if ((mBulletX + 10) > invader->invaderX && mBulletX < (invader->invaderX + 20))
+ {
+ if ((mBulletY + 10) > invader->invaderY && mBulletY < (invader->invaderY + 20))
+ {
+ invader->invaderDestroyed = true;
+ mPlayerScore += invader->invaderScore;
+ mBulletDestroyed = true;
+ }
+ }
+ }
+ }
+ if (invader->bombDestroyed == false)
+ {
+ if ((invader->bombX + 10) > mPlayerX && invader->bombX < (mPlayerX + 20))
+ {
+ if ((invader->bombY + 10) > mPlayerY && invader->bombY < (mPlayerY + 10))
+ {
+ mIsGameOver = true;
+ }
+ }
+ }
+ }
+
+ if (mBulletDestroyed == false && mBossDestroyed == false)
+ {
+ if ((mBulletX + 10) > mBossX && mBulletX < (mBossX + 20))
+ {
+ if ((mBulletY + 10) > mBossY && mBulletY < (mBossY + 10))
+ {
+ mBossDestroyed = true;
+ mPlayerScore += 100;
+ mBulletDestroyed = true;
+ }
+ }
+ }
+
+ if (totalInvaders == 0 && mBossDestroyed == true)
+ {
+ restart(mLevel + 1);
+ }
+
+ int gameSpeed = 5 - min(mLevel / 2, 4);
+
+ // Move Bombs
+
+ for (int i = 0; i < 44; i++)
+ {
+ Invader* invader = &mInvaders[i];
+ if (invader->bombDestroyed == true)
+ {
+ continue;
+ }
+ invader->bombY += 5;
+ if (invader->bombY >= ((mHeight * 10) - 10))
+ {
+ invader->bombDestroyed = true;
+ }
+ }
+
+ // Move Boss
+
+ if (mBossDestroyed == false)
+ {
+ mBossX += 2;
+ if (mBossX >= ((mWidth * 10) - 20))
+ {
+ mBossDestroyed = true;
+ }
+ }
+
+ if (mIsGameOver == true && mPlayerScore > settingsManager::getInvadersHiScore())
+ {
+ settingsManager::setInvadersHiScore(mPlayerScore);
+ }
+
+ mCounter++;
+ if (mCounter < gameSpeed)
+ {
+ return;
+ }
+ mCounter = 0;
+
+ if (mBossDestroyed == true && (rand() % 500) <= mLevel)
+ {
+ mBossX = 0;
+ mBossDestroyed = false;
+ }
+
+ int32_t bombCount = 0;
+ for (int i = 0; i < 44; i++)
+ {
+ Invader* invader = &mInvaders[i];
+ if (invader->bombDestroyed == false)
+ {
+ bombCount++;
+ }
+ }
+
+ bool moveDown = false;
+ for (int i = 0; i < 44; i++)
+ {
+ Invader* invader = &mInvaders[i];
+ if (invader->invaderDestroyed == true)
+ {
+ continue;
+ }
+ invader->invaderX += mInvaderDirection;
+
+ if (invader->bombDestroyed == true)
+ {
+ if (bombCount <= mLevel && (rand() % 1000) <= mLevel)
+ {
+ invader->bombDestroyed = false;
+ invader->bombX = invader->invaderX + 5;
+ invader->bombY = invader->invaderY + 20;
+ bombCount++;
+ }
+ }
+
+ if (mInvaderDirection < 0 && invader->invaderX == 0)
+ {
+ moveDown = true;
+ }
+ else if (mInvaderDirection > 0 && invader->invaderX == ((mWidth * 10) - 20))
+ {
+ moveDown = true;
+ }
+ }
+
+ if (moveDown == true)
+ {
+ mInvaderDirection = mInvaderDirection * -1;
+ for (int i = 0; i < 44; i++)
+ {
+ Invader* invader = &mInvaders[i];
+ invader->invaderY += 10;
+ if (invader->invaderY == ((mHeight * 10) - 30))
+ {
+ mIsGameOver = true;
+ }
+ }
+ }
+}
+
+void invadersScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ char* title = stringUtility::formatString("Invaders - Level %i", mLevel + 1);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), title, theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+ free(title);
+
+ int xPos = (context::getBufferWidth() - ((mWidth + 2) * 10)) / 2;
+ int yPos = (context::getBufferHeight() - ((mHeight + 2) * 10)) / 2;
+ yPos += theme::getCenterOffset();
+
+ for (int i = 0; i < mWidth + 2; i++)
+ {
+ drawing::drawNinePatch("panel-fill", theme::getInvadersWallColor(), xPos + (i * 10), yPos, 10, 10);
+ drawing::drawNinePatch("panel-fill", theme::getInvadersWallColor(), xPos + (i * 10), yPos + (mHeight + 1) * 10, 10, 10);
+ }
+
+ for (int i = 0; i < mHeight; i++)
+ {
+ drawing::drawNinePatch("panel-fill", theme::getInvadersWallColor(), xPos, yPos + ((i + 1) * 10), 10, 10);
+ drawing::drawNinePatch("panel-fill", theme::getInvadersWallColor(), xPos + ((mWidth + 1) * 10), yPos + ((i + 1) * 10), 10, 10);
+ }
+
+ // Draw Player
+
+ int playerPosX = xPos + mPlayerX + 10;
+ int playerPosY = yPos + ((mHeight - 1) * 10) + 10;
+ drawing::drawNinePatch("panel-fill", theme::getInvadersPlayerColor(), playerPosX, playerPosY, 20, 10);
+
+ // Draw Invaders + Bombs
+
+ for (int i = 0; i < 44; i++)
+ {
+ Invader* invader = &mInvaders[i];
+
+ if (invader->invaderDestroyed == false)
+ {
+ int screenPosX = xPos + invader->invaderX + 10;
+ int screenPosY = yPos + invader->invaderY + 10;
+ drawing::drawNinePatch("panel-fill", theme::getInvadersAlienColor(), screenPosX, screenPosY, 20, 20);
+ }
+
+ if (invader->bombDestroyed == false)
+ {
+ int bombPosX = xPos + invader->bombX + 10;
+ int bombPosY = yPos + invader->bombY + 10;
+ drawing::drawNinePatch("panel-fill", theme::getInvadersAlienColor(), bombPosX, bombPosY, 10, 10);
+ }
+ }
+
+ // Draw Bullet
+
+ if (mBulletDestroyed == false)
+ {
+ int bulletPosX = xPos + mBulletX + 10;
+ int bulletPosY = yPos + mBulletY + 10;
+ drawing::drawNinePatch("panel-fill", theme::getInvadersPlayerColor(), bulletPosX, bulletPosY, 10, 10);
+ }
+
+ // Draw Boss
+
+ if (mBossDestroyed == false)
+ {
+ int bossPosX = xPos + mBossX + 10;
+ int bossPosY = yPos + mBossY + 10;
+ drawing::drawNinePatch("panel-fill", theme::getInvadersBossColor(), bossPosX, bossPosY, 20, 10);
+ }
+
+#ifndef TOOLS
+ char* score = stringUtility::formatString("Hi-Score: %i, Score: %i", settingsManager::getInvadersHiScore(), mPlayerScore);
+#else
+ char* score = stringUtility::formatString("Score: %i", mPlayerScore);
+#endif
+
+ if (mIsGameOver == true)
+ {
+ int yPosGameOver = (context::getBufferHeight() - 20) / 2;
+ yPosGameOver += theme::getCenterOffset();
+ drawing::drawBitmapStringAligned(context::getBitmapFontLarge(), "GAME OVER", theme::getTextColor(), horizAlignmentCenter, 40, yPosGameOver, 640);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Restart", theme::getFooterTextColor(), 40, theme::getFooterY());
+ }
+
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), score, theme::getFooterTextColor(), horizAlignmentCenter, 40, theme::getFooterY(), 640);
+ free(score);
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
+
+void invadersScene::restart(int32_t level)
+{
+ mWidth = 58;
+ mHeight = 26;
+ mIsGameOver = false;
+
+ if (level == 0)
+ {
+ mPlayerScore = 0;
+ }
+
+ srand((uint32_t)timeUtility::getMillisecondsNow());
+
+ mLevel = level;
+ mCounter = 0;
+
+ mBulletX = 0;
+ mBulletY = 0;
+ mBulletDestroyed = true;
+
+ mBossX = 0;
+ mBossY = 0;
+ mBossDestroyed = true;
+
+ mPlayerX = 0;
+ mPlayerY = (mHeight - 1) * 10;
+ mInvaderDirection = -1;
+ for (int y = 0; y < 4; y++)
+ {
+ for (int x = 0; x < 11; x++)
+ {
+ Invader invader;
+ invader.invaderX = 130 + (x * 30);
+ invader.invaderY = 20 + (y * 30);
+ invader.invaderScore = (5 - y) * 10;
+ invader.invaderDestroyed = false;
+ invader.bombX = 0;
+ invader.bombY = 0;
+ invader.bombDestroyed = true;
+ mInvaders[(y * 11) + x] = invader;
+ }
+ }
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/invadersScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/invadersScene.h
new file mode 100644
index 0000000..8c71ec1
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/invadersScene.h
@@ -0,0 +1,49 @@
+#pragma once
+
+#include "scene.h"
+#include "sceneManager.h"
+
+#include "../pointerMap.h"
+
+class invadersScene : public scene
+{
+public:
+
+ typedef struct Invader
+ {
+ int invaderX;
+ int invaderY;
+ int invaderScore;
+ bool invaderDestroyed;
+ int bombX;
+ int bombY;
+ bool bombDestroyed;
+ } Invader;
+
+ invadersScene();
+ void update();
+ void render();
+private:
+ void restart(int32_t level);
+private:
+ int32_t mWidth;
+ int32_t mHeight;
+ uint32_t mPlayerScore;
+
+ int32_t mBulletX;
+ int32_t mBulletY;
+ bool mBulletDestroyed;
+
+ int32_t mBossX;
+ int32_t mBossY;
+ bool mBossDestroyed;
+
+ int32_t mPlayerX;
+ int32_t mPlayerY;
+ int32_t mInvaderDirection;
+ Invader mInvaders[44];
+
+ bool mIsGameOver;
+ int32_t mLevel;
+ int32_t mCounter;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/keyboardScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/keyboardScene.cpp
new file mode 100644
index 0000000..25b09d7
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/keyboardScene.cpp
@@ -0,0 +1,438 @@
+#include "keyboardScene.h"
+#include "sceneManager.h"
+#include "launchScene.h"
+#include "removeScene.h"
+#include "audioSettingsScene.h"
+#include "mainScene.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxInternals.h"
+#include "..\theme.h"
+
+keyboardScene::keyboardScene(uint32_t maxLen, const char* title, const char* label, const char* text)
+{
+ mSelectedControl = 33;
+ mCapitals = false;
+ mSymbols = false;
+ mMaxLen = maxLen;
+ mTitle = strdup(title);
+ mLabel = strdup(label);
+ mText = strdup(text);
+ mCounter = 0;
+ mCursorPos = strlen(mText);
+ calcShortStringRange(mText, mShortTextStart, mShortTextEnd);
+}
+
+keyboardScene::~keyboardScene()
+{
+ free(mTitle);
+ free(mLabel);
+ free(mText);
+}
+
+void keyboardScene::update()
+{
+ // Cancel Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene(sceneResultCancelled);
+ return;
+ }
+
+ if (inputManager::buttonPressed(ButtonY))
+ {
+ clearText();
+ return;
+ }
+
+ // Delete Action
+
+ if (inputManager::buttonPressed(ButtonX))
+ {
+ if (mCursorPos > 0)
+ {
+ char* newText = stringUtility::removeAtIndex(mText, mCursorPos);
+ free(mText);
+ mText = newText;
+ mCursorPos--;
+ calcShortStringRange(mText, mShortTextStart, mShortTextEnd);
+ }
+ }
+
+ if (inputManager::buttonPressed(ButtonLeftThumb) || inputManager::buttonPressed(ButtonWhite))
+ {
+ mCapitals = !mCapitals;
+ if (mCapitals == true)
+ {
+ mSymbols = false;
+ }
+ }
+
+ if (inputManager::buttonPressed(ButtonRightThumb) || inputManager::buttonPressed(ButtonBlack))
+ {
+ mSymbols = !mSymbols;
+ if (mSymbols == true)
+ {
+ mCapitals = false;
+ }
+ }
+
+ // Select Actions
+
+ if (inputManager::buttonPressed(ButtonA))
+ {
+ char* keys = "0123456789abcdefghijklmnopqrstuvwxyz ";
+ if (mCapitals == true)
+ {
+ keys = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ ";
+ }
+ else if (mSymbols == true)
+ {
+ keys = "!@#$%^&*()~`-_+=[]{}\\|;:'\",.<>?/ ";
+ }
+
+ if (mSelectedControl == 0)
+ {
+ mCapitals = !mCapitals;
+ if (mCapitals == true)
+ {
+ mSymbols = false;
+ }
+ }
+ else if (mSelectedControl >= 1 && mSelectedControl <= 10)
+ {
+ char* newText = stringUtility::insertAtIndex(mText, keys[mSelectedControl - 1], mCursorPos);
+ char* trimmedTest = stringUtility::substr(newText, 0, mMaxLen);
+ free(mText);
+ free(newText);
+ mText = trimmedTest;
+ mCursorPos++;
+ calcShortStringRange(mText, mShortTextStart, mShortTextEnd);
+ }
+ else if (mSelectedControl == 11)
+ {
+ mSymbols = !mSymbols;
+ if (mSymbols == true)
+ {
+ mCapitals = false;
+ }
+ }
+ else if (mSelectedControl >= 12 && mSelectedControl <= 21)
+ {
+ char* newText = stringUtility::insertAtIndex(mText, keys[mSelectedControl - 2], mCursorPos);
+ char* trimmedTest = stringUtility::substr(newText, 0, mMaxLen);
+ free(mText);
+ free(newText);
+ mText = trimmedTest;
+ mCursorPos++;
+ calcShortStringRange(mText, mShortTextStart, mShortTextEnd);
+ }
+ else if (mSelectedControl == 22)
+ {
+ char* newText = stringUtility::removeAtIndex(mText, mCursorPos);
+ free(mText);
+ mText = newText;
+ mCursorPos--;
+ calcShortStringRange(mText, mShortTextStart, mShortTextEnd);
+ }
+ else if (mSelectedControl >= 23 && mSelectedControl <= 32)
+ {
+ char* newText = stringUtility::insertAtIndex(mText, keys[mSelectedControl - 3], mCursorPos);
+ char* trimmedTest = stringUtility::substr(newText, 0, mMaxLen);
+ free(mText);
+ free(newText);
+ mText = trimmedTest;
+ mCursorPos++;
+ calcShortStringRange(mText, mShortTextStart, mShortTextEnd);
+ }
+ else if (mSelectedControl == 33)
+ {
+ sceneManager::popScene(sceneResultDone);
+ return;
+ }
+ else if (mSelectedControl >= 34 && mSelectedControl <= 40)
+ {
+ char* newText = stringUtility::insertAtIndex(mText, keys[mSelectedControl - 4], mCursorPos);
+ char* trimmedTest = stringUtility::substr(newText, 0, mMaxLen);
+ free(mText);
+ free(newText);
+ mText = trimmedTest;
+ mCursorPos++;
+ calcShortStringRange(mText, mShortTextStart, mShortTextEnd);
+ }
+ }
+
+ // Left Actions
+
+ if (inputManager::buttonPressed(ButtonDpadLeft))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 10)
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : 10;
+ }
+ else if (mSelectedControl >= 11 && mSelectedControl <= 21)
+ {
+ mSelectedControl = mSelectedControl > 11 ? mSelectedControl - 1 : 21;
+ }
+ else if (mSelectedControl >= 22 && mSelectedControl <= 32)
+ {
+ mSelectedControl = mSelectedControl > 22 ? mSelectedControl - 1 : 32;
+ }
+ else if (mSelectedControl >= 33 && mSelectedControl <= 40)
+ {
+ mSelectedControl = mSelectedControl > 33 ? mSelectedControl - 1 : 40;
+ }
+ }
+
+ // Right Actions
+
+ if (inputManager::buttonPressed(ButtonDpadRight))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 10)
+ {
+ mSelectedControl = mSelectedControl < 10 ? mSelectedControl + 1 : 0;
+ }
+ else if (mSelectedControl >= 11 && mSelectedControl <= 21)
+ {
+ mSelectedControl = mSelectedControl < 21 ? mSelectedControl + 1 : 11;
+ }
+ else if (mSelectedControl >= 22 && mSelectedControl <= 32)
+ {
+ mSelectedControl = mSelectedControl < 32 ? mSelectedControl + 1 : 22;
+ }
+ else if (mSelectedControl >= 33 && mSelectedControl <= 40)
+ {
+ mSelectedControl = mSelectedControl < 40 ? mSelectedControl + 1 : 33;
+ }
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 10)
+ {
+ mSelectedControl += 11;
+ }
+ else if (mSelectedControl >= 11 && mSelectedControl <= 21)
+ {
+ mSelectedControl += 11;
+ }
+ else if (mSelectedControl >= 22 && mSelectedControl <= 32)
+ {
+ mSelectedControl = min(mSelectedControl + 11, 40);
+ }
+ else if (mSelectedControl >= 33 && mSelectedControl <= 40)
+ {
+ mSelectedControl = mSelectedControl - 33;
+ }
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 10)
+ {
+ mSelectedControl = 33 + min(mSelectedControl, 7);
+ }
+ else if (mSelectedControl >= 11 && mSelectedControl <= 21)
+ {
+ mSelectedControl -= 11;
+ }
+ else if (mSelectedControl >= 22 && mSelectedControl <= 32)
+ {
+ mSelectedControl -= 11;
+ }
+ else if (mSelectedControl >= 33 && mSelectedControl <= 40)
+ {
+ mSelectedControl -= 11;
+ }
+ }
+
+ // Left Trigger
+
+ if (inputManager::buttonPressed(ButtonTriggerLeft))
+ {
+ mCursorPos = mCursorPos > 0 ? mCursorPos - 1 : 0;
+ calcShortStringRange(mText, mShortTextStart, mShortTextEnd);
+ }
+
+ // Right Trigger
+
+ if (inputManager::buttonPressed(ButtonTriggerRight))
+ {
+ mCursorPos = mCursorPos < (int)strlen(mText) ? mCursorPos + 1 : strlen(mText);
+ calcShortStringRange(mText, mShortTextStart, mShortTextEnd);
+ }
+}
+
+void keyboardScene::render()
+{
+ if (mCounter == 0)
+ {
+ mCounter = 60;
+ }
+ else
+ {
+ mCounter--;
+ }
+
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), mTitle, theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ char* keys = "0123456789abcdefghijklmnopqrstuvwxyz ";
+ if (mCapitals == true)
+ {
+ keys = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ ";
+ }
+ else if (mSymbols == true)
+ {
+ keys = "!@#$%^&*()~`-_+=[]{}\\|;:'\",.<>?/ ";
+ }
+
+ int32_t keyboardX = 38;
+ int32_t keyboardY = (context::getBufferHeight() - (((4 * 48) - 4) + 30 + 64)) / 2;
+ keyboardY += theme::getCenterOffset();
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), mLabel, theme::getTextColor(), 40, keyboardY);
+
+ keyboardY += 30;
+
+ int t = strlen(mText);
+ int cursorEnd1 = mCursorPos - mShortTextStart;
+ int cursorEnd2 = max(mShortTextEnd - mCursorPos, 0);
+
+ char* leftString = stringUtility::substr(mText, mShortTextStart, mCursorPos - mShortTextStart);
+ int q = strlen(leftString);
+ char* rightString = stringUtility::substr(mText, mCursorPos, max(mShortTextEnd - mCursorPos, 0));
+ int v = strlen(rightString);
+ char* shortText = mCounter < 30 ? stringUtility::formatString("%s\xC2\xAF%s", leftString, rightString) : stringUtility::formatString("%s\xC2\xB0%s", leftString, rightString);
+ component::textBox(shortText, false, false, horizAlignmentLeft, 40, keyboardY, 640, 44);
+ free(shortText);
+
+ keyboardY += 64;
+
+ component::button(mSelectedControl == 0, mCapitals, "Caps", keyboardX, keyboardY + (48 * 0), 104, 44);
+
+ keyboardButton(mSelectedControl == 1, false, keys[0], keyboardX + 108 + (54 * 0), keyboardY + (48 * 0), 50, 44);
+ keyboardButton(mSelectedControl == 2, false, keys[1], keyboardX + 108 + (54 * 1), keyboardY + (48 * 0), 50, 44);
+ keyboardButton(mSelectedControl == 3, false, keys[2], keyboardX + 108 + (54 * 2), keyboardY + (48 * 0), 50, 44);
+ keyboardButton(mSelectedControl == 4, false, keys[3], keyboardX + 108 + (54 * 3), keyboardY + (48 * 0), 50, 44);
+ keyboardButton(mSelectedControl == 5, false, keys[4], keyboardX + 108 + (54 * 4), keyboardY + (48 * 0), 50, 44);
+ keyboardButton(mSelectedControl == 6, false, keys[5], keyboardX + 108 + (54 * 5), keyboardY + (48 * 0), 50, 44);
+ keyboardButton(mSelectedControl == 7, false, keys[6], keyboardX + 108 + (54 * 6), keyboardY + (48 * 0), 50, 44);
+ keyboardButton(mSelectedControl == 8, false, keys[7], keyboardX + 108 + (54 * 7), keyboardY + (48 * 0), 50, 44);
+ keyboardButton(mSelectedControl == 9, false, keys[8], keyboardX + 108 + (54 * 8), keyboardY + (48 * 0), 50, 44);
+ keyboardButton(mSelectedControl == 10, false, keys[9], keyboardX + 108 + (54 * 9), keyboardY + (48 * 0), 50, 44);
+
+ component::button(mSelectedControl == 11, mSymbols, "Symbol", keyboardX, keyboardY + (48 * 1), 104, 44);
+
+ keyboardButton(mSelectedControl == 12, false, keys[10], keyboardX + 108 + (54 * 0), keyboardY + (48 * 1), 50, 44);
+ keyboardButton(mSelectedControl == 13, false, keys[11], keyboardX + 108 + (54 * 1), keyboardY + (48 * 1), 50, 44);
+ keyboardButton(mSelectedControl == 14, false, keys[12], keyboardX + 108 + (54 * 2), keyboardY + (48 * 1), 50, 44);
+ keyboardButton(mSelectedControl == 15, false, keys[13], keyboardX + 108 + (54 * 3), keyboardY + (48 * 1), 50, 44);
+ keyboardButton(mSelectedControl == 16, false, keys[14], keyboardX + 108 + (54 * 4), keyboardY + (48 * 1), 50, 44);
+ keyboardButton(mSelectedControl == 17, false, keys[15], keyboardX + 108 + (54 * 5), keyboardY + (48 * 1), 50, 44);
+ keyboardButton(mSelectedControl == 18, false, keys[16], keyboardX + 108 + (54 * 6), keyboardY + (48 * 1), 50, 44);
+ keyboardButton(mSelectedControl == 19, false, keys[17], keyboardX + 108 + (54 * 7), keyboardY + (48 * 1), 50, 44);
+ keyboardButton(mSelectedControl == 20, false, keys[18], keyboardX + 108 + (54 * 8), keyboardY + (48 * 1), 50, 44);
+ keyboardButton(mSelectedControl == 21, false, keys[19], keyboardX + 108 + (54 * 9), keyboardY + (48 * 1), 50, 44);
+
+ component::button(mSelectedControl == 22, false, "Delete", keyboardX, keyboardY + (48 * 2), 104, 44);
+
+ keyboardButton(mSelectedControl == 23, false, keys[20], keyboardX + 108 + (54 * 0), keyboardY + (48 * 2), 50, 44);
+ keyboardButton(mSelectedControl == 24, false, keys[21], keyboardX + 108 + (54 * 1), keyboardY + (48 * 2), 50, 44);
+ keyboardButton(mSelectedControl == 25, false, keys[22], keyboardX + 108 + (54 * 2), keyboardY + (48 * 2), 50, 44);
+ keyboardButton(mSelectedControl == 26, false, keys[23], keyboardX + 108 + (54 * 3), keyboardY + (48 * 2), 50, 44);
+ keyboardButton(mSelectedControl == 27, false, keys[24], keyboardX + 108 + (54 * 4), keyboardY + (48 * 2), 50, 44);
+ keyboardButton(mSelectedControl == 28, false, keys[25], keyboardX + 108 + (54 * 5), keyboardY + (48 * 2), 50, 44);
+ keyboardButton(mSelectedControl == 29, false, keys[26], keyboardX + 108 + (54 * 6), keyboardY + (48 * 2), 50, 44);
+ keyboardButton(mSelectedControl == 30, false, keys[27], keyboardX + 108 + (54 * 7), keyboardY + (48 * 2), 50, 44);
+ keyboardButton(mSelectedControl == 31, false, keys[28], keyboardX + 108 + (54 * 8), keyboardY + (48 * 2), 50, 44);
+ keyboardButton(mSelectedControl == 32, false, keys[29], keyboardX + 108 + (54 * 9), keyboardY + (48 * 2), 50, 44);
+
+ component::button(mSelectedControl == 33, false, "Done", keyboardX, keyboardY + (48 * 3), 104, 44);
+
+ keyboardButton(mSelectedControl == 34, false, keys[30], keyboardX + 108 + (54 * 0), keyboardY + (48 * 3), 50, 44);
+ keyboardButton(mSelectedControl == 35, false, keys[31], keyboardX + 108 + (54 * 1), keyboardY + (48 * 3), 50, 44);
+
+ if (mSymbols)
+ {
+ component::button(mSelectedControl == 36, false, "Space", keyboardX + 108 + (54 * 2), keyboardY + (48 * 3), (54 * 8) - 4, 44);
+ }
+ else
+ {
+ keyboardButton(mSelectedControl == 36, false, keys[32], keyboardX + 108 + (54 * 2), keyboardY + (48 * 3), 50, 44);
+ keyboardButton(mSelectedControl == 37, false, keys[33], keyboardX + 108 + (54 * 3), keyboardY + (48 * 3), 50, 44);
+ keyboardButton(mSelectedControl == 38, false, keys[34], keyboardX + 108 + (54 * 4), keyboardY + (48 * 3), 50, 44);
+ keyboardButton(mSelectedControl == 39, false, keys[35], keyboardX + 108 + (54 * 5), keyboardY + (48 * 3), 50, 44);
+ component::button(mSelectedControl == 40, false, "Space", keyboardX + 108 + (54 * 6), keyboardY + (48 * 3), 212, 44);
+ }
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Select, \xC2\xA3 Delete, \xC2\xA4 Clear", theme::getFooterTextColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Cancel", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
+
+void keyboardScene::keyboardButton(bool selected, bool active, char key, int x, int y, int width, int height)
+{
+ char* keyString = stringUtility::formatString("%c", key);
+ component::button(selected, active, keyString, x, y, width, height);
+ free(keyString);
+}
+
+char* keyboardScene::getText()
+{
+ return strdup(mText);
+}
+
+void keyboardScene::clearText() {
+ free(mText);
+ mText = strdup("");
+ mCursorPos = 0;
+}
+
+void keyboardScene::calcShortStringRange(const char* value, int& startPos, int &endPos)
+{
+ int textWidth;
+ int textHeight;
+
+ int maxWidth = 640 - 30;
+
+ startPos = mCursorPos;
+ while (startPos >= 0)
+ {
+ char* leftString = stringUtility::substr(value, startPos, mCursorPos - startPos);
+ drawing::measureBitmapString(context::getBitmapFontSmall(), leftString, &textWidth, &textHeight);
+ free(leftString);
+ if (textWidth > maxWidth)
+ {
+ break;
+ }
+ startPos--;
+ }
+ startPos++;
+
+ endPos = startPos;
+ while (endPos <= (int)strlen(value))
+ {
+ char* rightString = stringUtility::substr(value, startPos, endPos - startPos);
+ drawing::measureBitmapString(context::getBitmapFontSmall(), rightString, &textWidth, &textHeight);
+ free(rightString);
+ if (textWidth > maxWidth)
+ {
+ break;
+ }
+ endPos++;
+
+ }
+ endPos--;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/keyboardScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/keyboardScene.h
new file mode 100644
index 0000000..aaef041
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/keyboardScene.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "scene.h"
+
+#include "..\xboxInternals.h"
+
+class keyboardScene : public scene
+{
+public:
+ keyboardScene(uint32_t maxLen, const char* title, const char* label, const char* text);
+ ~keyboardScene();
+ void update();
+ void render();
+ char* getText();
+ void clearText();
+ void calcShortStringRange(const char* value, int& startPos, int &endPos);
+private:
+ void keyboardButton(bool selected, bool active, char key, int x, int y, int width, int height);
+private:
+ int mSelectedControl;
+ bool mCapitals;
+ bool mSymbols;
+ uint32_t mMaxLen;
+ char* mTitle;
+ char* mLabel;
+ char* mText;
+ int mCounter;
+ int mCursorPos;
+ int mShortTextStart;
+ int mShortTextEnd;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/keypadScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/keypadScene.cpp
new file mode 100644
index 0000000..b51aec9
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/keypadScene.cpp
@@ -0,0 +1,337 @@
+#include "keypadScene.h"
+#include "sceneManager.h"
+#include "launchScene.h"
+#include "removeScene.h"
+#include "audioSettingsScene.h"
+#include "mainScene.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxInternals.h"
+#include "..\theme.h"
+
+keypadScene::keypadScene(const char* title, uint32_t address)
+{
+ mSelectedControl = 0;
+ mTitle = strdup(title);
+ if (address == 0)
+ {
+ mIp1 = strdup("");
+ mIp2 = strdup("");
+ mIp3 = strdup("");
+ mIp4 = strdup("");
+ }
+ else
+ {
+ mIp1 = stringUtility::formatString("%i", address & 0xff);
+ mIp2 = stringUtility::formatString("%i", (address >> 8) & 0xff);
+ mIp3 = stringUtility::formatString("%i", (address >> 16) & 0xff);
+ mIp4 = stringUtility::formatString("%i", (address >> 24) & 0xff);
+ }
+ mPart = 0;
+ mCounter = 0;
+}
+
+keypadScene::~keypadScene()
+{
+ free(mTitle);
+ free(mIp1);
+ free(mIp2);
+ free(mIp3);
+ free(mIp4);
+}
+
+
+void keypadScene::update()
+{
+ // Cancel Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene(sceneResultCancelled);
+ return;
+ }
+
+ // Delete Action
+
+ if (inputManager::buttonPressed(ButtonX))
+ {
+ if (mPart == 0)
+ {
+ char* ip1 = deleteChar(mIp1);
+ free(mIp1);
+ mIp1 = ip1;
+ }
+ else if (mPart == 1)
+ {
+ char* ip2 = deleteChar(mIp2);
+ free(mIp2);
+ mIp2 = ip2;
+ }
+ else if (mPart == 2)
+ {
+ char* ip3 = deleteChar(mIp3);
+ free(mIp3);
+ mIp3 = ip3;
+ }
+ else if (mPart == 3)
+ {
+ char* ip4 = deleteChar(mIp4);
+ free(mIp4);
+ mIp4 = ip4;
+ }
+ }
+
+ // Select Actions
+
+ if (inputManager::buttonPressed(ButtonA))
+ {
+ if ((mSelectedControl >= 0 && mSelectedControl <= 8) || mSelectedControl == 10)
+ {
+ uint32_t charIndex = mSelectedControl == 10 ? 9 : mSelectedControl;
+
+ if (mPart == 0)
+ {
+ char* ip1 = addChar(mIp1, charIndex);
+ if (strlen(mIp1) < 3 && strlen(ip1) == 3)
+ {
+ mPart = (mPart + 1) % 4;
+ }
+ free(mIp1);
+ mIp1 = ip1;
+ }
+ else if (mPart == 1)
+ {
+ char* ip2 = addChar(mIp2, charIndex);
+ if (strlen(mIp2) < 3 && strlen(ip2) == 3)
+ {
+ mPart = (mPart + 1) % 4;
+ }
+ free(mIp2);
+ mIp2 = ip2;
+ }
+ else if (mPart == 2)
+ {
+ char* ip3 = addChar(mIp3, charIndex);
+ if (strlen(mIp3) < 3 && strlen(ip3) == 3)
+ {
+ mPart = (mPart + 1) % 4;
+ }
+ free(mIp3);
+ mIp3 = ip3;
+ }
+ else if (mPart == 3)
+ {
+ char* ip4 = addChar(mIp4, charIndex);
+ if (strlen(mIp4) < 3 && strlen(ip4) == 3)
+ {
+ mPart = (mPart + 1) % 4;
+ }
+ free(mIp4);
+ mIp4 = ip4;
+ }
+ }
+ else if (mSelectedControl == 9)
+ {
+ if (mPart == 0)
+ {
+ char* ip1 = deleteChar(mIp1);
+ free(mIp1);
+ mIp1 = ip1;
+ }
+ else if (mPart == 1)
+ {
+ char* ip2 = deleteChar(mIp2);
+ free(mIp2);
+ mIp2 = ip2;
+ }
+ else if (mPart == 2)
+ {
+ char* ip3 = deleteChar(mIp3);
+ free(mIp3);
+ mIp3 = ip3;
+ }
+ else if (mPart == 3)
+ {
+ char* ip4 = deleteChar(mIp4);
+ free(mIp4);
+ mIp4 = ip4;
+ }
+ }
+ else if (mSelectedControl == 11)
+ {
+ sceneManager::popScene(sceneResultDone);
+ return;
+ }
+
+ }
+
+ // Left Trigger
+
+ if (inputManager::buttonPressed(ButtonTriggerLeft))
+ {
+ mPart = mPart == 0 ? 3 : mPart - 1;
+ }
+
+ // Right Trigger
+
+ if (inputManager::buttonPressed(ButtonTriggerRight))
+ {
+ mPart = mPart == 3 ? 0 : mPart + 1;
+ }
+
+ // Left Actions
+
+ if (inputManager::buttonPressed(ButtonDpadLeft))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 2)
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : 2;
+ }
+ else if (mSelectedControl >= 3 && mSelectedControl <= 5)
+ {
+ mSelectedControl = mSelectedControl > 3 ? mSelectedControl - 1 : 5;
+ }
+ else if (mSelectedControl >= 6 && mSelectedControl <= 8)
+ {
+ mSelectedControl = mSelectedControl > 6 ? mSelectedControl - 1 : 8;
+ }
+ else if (mSelectedControl >= 9 && mSelectedControl <= 11)
+ {
+ mSelectedControl = mSelectedControl > 9 ? mSelectedControl - 1 : 11;
+ }
+ }
+
+ // Right Actions
+
+ if (inputManager::buttonPressed(ButtonDpadRight))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 2)
+ {
+ mSelectedControl = mSelectedControl < 2 ? mSelectedControl + 1 : 0;
+ }
+ else if (mSelectedControl >= 3 && mSelectedControl <= 5)
+ {
+ mSelectedControl = mSelectedControl < 5 ? mSelectedControl + 1 : 3;
+ }
+ else if (mSelectedControl >= 6 && mSelectedControl <= 8)
+ {
+ mSelectedControl = mSelectedControl < 8 ? mSelectedControl + 1 : 6;
+ }
+ else if (mSelectedControl >= 9 && mSelectedControl <= 11)
+ {
+ mSelectedControl = mSelectedControl < 11 ? mSelectedControl + 1 : 9;
+ }
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 11)
+ {
+ mSelectedControl = mSelectedControl + 3 > 11 ? (mSelectedControl + 3) - 12 : mSelectedControl + 3;
+ }
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 11)
+ {
+ mSelectedControl = mSelectedControl - 3 < 0 ? (mSelectedControl - 3) + 12 : mSelectedControl - 3;
+ }
+ }
+}
+
+void keypadScene::render()
+{
+ if (mCounter == 0)
+ {
+ mCounter = 60;
+ }
+ else
+ {
+ mCounter--;
+ }
+
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), mTitle, theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ char* keys = "1234567890";
+
+ int32_t keyboardX = 264;
+ int32_t keyboardY = (context::getBufferHeight() - (((4 * 48) - 4) + 64)) / 2;
+ keyboardY += theme::getCenterOffset();
+
+ char* ip1 = mPart == 0 && mCounter < 30 ? stringUtility::formatString("%s\xC2\xAF", mIp1) : stringUtility::formatString("%s\xC2\xB0", mIp1);
+ component::textBox(ip1, false, false, horizAlignmentCenter, 225 + (70 * 0), keyboardY, 66, 44);
+ free(ip1);
+
+ char* ip2 = mPart == 1 && mCounter < 30 ? stringUtility::formatString("%s\xC2\xAF", mIp2) : stringUtility::formatString("%s\xC2\xB0", mIp2);
+ component::textBox(ip2, false, false, horizAlignmentCenter, 225 + (70 * 1), keyboardY, 66, 44);
+ free(ip2);
+
+ char* ip3 = mPart == 2 && mCounter < 30 ? stringUtility::formatString("%s\xC2\xAF", mIp3) : stringUtility::formatString("%s\xC2\xB0", mIp3);
+ component::textBox(ip3, false, false, horizAlignmentCenter, 225 + (70 * 2),keyboardY, 66, 44);
+ free(ip3);
+
+ char* ip4 = mPart == 3 && mCounter < 30 ? stringUtility::formatString("%s\xC2\xAF", mIp4) : stringUtility::formatString("%s\xC2\xB0", mIp4);
+ component::textBox(ip4, false, false, horizAlignmentCenter, 225 + (70 * 3), keyboardY, 66, 44);
+ free(ip4);
+
+ keyboardY += 64;
+
+ keyboardButton(mSelectedControl == 0, false, keys[0], keyboardX + (66 * 0), keyboardY + (48 * 0), 62, 44);
+ keyboardButton(mSelectedControl == 1, false, keys[1], keyboardX + (66 * 1), keyboardY + (48 * 0), 62, 44);
+ keyboardButton(mSelectedControl == 2, false, keys[2], keyboardX + (66 * 2), keyboardY + (48 * 0), 62, 44);
+
+ keyboardButton(mSelectedControl == 3, false, keys[3], keyboardX + (66 * 0), keyboardY + (48 * 1), 62, 44);
+ keyboardButton(mSelectedControl == 4, false, keys[4], keyboardX + (66 * 1), keyboardY + (48 * 1), 62, 44);
+ keyboardButton(mSelectedControl == 5, false, keys[5], keyboardX + (66 * 2), keyboardY + (48 * 1), 62, 44);
+
+ keyboardButton(mSelectedControl == 6, false, keys[6], keyboardX + (66 * 0), keyboardY + (48 * 2), 62, 44);
+ keyboardButton(mSelectedControl == 7, false, keys[7], keyboardX + (66 * 1), keyboardY + (48 * 2), 62, 44);
+ keyboardButton(mSelectedControl == 8, false, keys[8], keyboardX + (66 * 2), keyboardY + (48 * 2), 62, 44);
+
+ component::button(mSelectedControl == 9, false, "Del", keyboardX + (66 * 0), keyboardY + (48 * 3), 62, 44);
+ keyboardButton(mSelectedControl == 10, false, keys[9], keyboardX + (66 * 1), keyboardY + (48 * 3), 62, 44);
+ component::button(mSelectedControl == 11, false, "Done", keyboardX + (66 * 2), keyboardY + (48 * 3), 62, 44);
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Select \xC2\xA3 Delete", theme::getFooterTextColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Cancel", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
+
+char* keypadScene::addChar(char* value, int charIndex)
+{
+ const char* keys = "1234567890";
+ char* temp = stringUtility::formatString("%s%c", value, keys[charIndex]);
+ int number = stringUtility::toInt(temp);
+ char* result = (number <= 255 && strlen(temp) <= 3) ? strdup(temp) : strdup(value);
+ free(temp);
+ return result;
+}
+
+char* keypadScene::deleteChar(char* value)
+{
+ return stringUtility::substr(value, 0, max(strlen(value) - 1, 0));
+}
+
+void keypadScene::keyboardButton(bool selected, bool active, char key, int x, int y, int width, int height)
+{
+ char* keyString = stringUtility::formatString("%c", key);
+ component::button(selected, active, keyString, x, y, width, height);
+ free(keyString);
+}
+
+uint32_t keypadScene::getValue()
+{
+ return (stringUtility::toInt(mIp4) << 24) | (stringUtility::toInt(mIp3) << 16) | (stringUtility::toInt(mIp2) << 8) | stringUtility::toInt(mIp1);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/keypadScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/keypadScene.h
new file mode 100644
index 0000000..1f9eb38
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/keypadScene.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include "scene.h"
+
+#include "..\xboxInternals.h"
+
+class keypadScene : public scene
+{
+public:
+ keypadScene(const char* title, uint32_t address);
+ ~keypadScene();
+ void update();
+ void render();
+ uint32_t getValue();
+private:
+ void keyboardButton(bool selected, bool active, char key, int x, int y, int width, int height);
+ char* addChar(char* value, int charIndex);
+ char* deleteChar(char* value);
+private:
+ int mSelectedControl;
+ char* mTitle;
+ char* mIp1;
+ char* mIp2;
+ char* mIp3;
+ char* mIp4;
+ int mPart;
+ int mCounter;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/launchScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/launchScene.cpp
new file mode 100644
index 0000000..6d7987b
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/launchScene.cpp
@@ -0,0 +1,164 @@
+#include "launchScene.h"
+#include "audioSettingsScene.h"
+#include "videoSettingsScene.h"
+#include "mainScene.h"
+#include "sceneManager.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\alignment.h"
+#include "..\theme.h"
+
+launchScene::launchScene()
+{
+ mSelectedControl = 0;
+ setupBanks();
+}
+
+launchScene::~launchScene()
+{
+ delete(mBanks);
+}
+
+void launchScene::setupBanks() {
+ mBanks = settingsManager::getBankInfos();
+
+ bankDetails* tsopBank = new bankDetails();
+ tsopBank->id = (uint8_t)0;
+ tsopBank->ledColor = 0;
+ tsopBank->slots = 0;
+ tsopBank->name = strdup("TSOP");
+ tsopBank->autoBoot = false;
+ mBanks->add(tsopBank);
+
+ if (context::getModchip()->getSupportInfo(true).supportsRecovery == true)
+ {
+ bankDetails* recoveryBank = new bankDetails();
+ recoveryBank->id = (uint8_t)0;
+ recoveryBank->ledColor = 0;
+ recoveryBank->slots = 0;
+ recoveryBank->name = strdup("Recovery");
+ recoveryBank->autoBoot = false;
+ mBanks->add(recoveryBank);
+ }
+}
+
+void launchScene::update()
+{
+ // Exit Action
+
+ bool supportsRecovery = context::getModchip()->getSupportInfo(true).supportsRecovery;
+ uint32_t cnt = mBanks->count() - 1;
+ if (supportsRecovery) cnt -= 1;
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene();
+ return;
+ }
+
+ // Toggle Auto Boot Action
+
+ if (inputManager::buttonPressed(ButtonY) && (uint32_t)mSelectedControl < cnt)
+ {
+ for (uint32_t i = 0; i < cnt; i++)
+ {
+ bankDetails* bank = mBanks->get(i);
+
+ if (mSelectedControl != i)
+ {
+ bank->autoBoot = false;
+ continue;
+ }
+
+ settingsManager::toggleAutoBootBank(bank->id);
+ bank->autoBoot = settingsManager::getBankInfo(bank->id).autoBoot == 1;
+ }
+ }
+
+ // Select Actions
+
+ if (inputManager::buttonPressed(ButtonA))
+ {
+ for (uint32_t i = 0; i < cnt; i++)
+ {
+ if (mSelectedControl != i)
+ {
+ continue;
+ }
+ bankDetails* bank = mBanks->get(i);
+ settingsManager::launchBank(bank->id);
+ }
+ if (mSelectedControl == cnt)
+ {
+ settingsManager::launchTsop();
+ }
+ else if (mSelectedControl == cnt + 1)
+ {
+ settingsManager::launchRecovery();
+ }
+ }
+
+ uint32_t bankCount = cnt + 1;
+ if(supportsRecovery) bankCount += 1;
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ mSelectedControl = mSelectedControl < (int)(bankCount - 1) ? mSelectedControl + 1 : 0;
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : (int)(bankCount - 1);
+ }
+}
+
+void launchScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Please select a bank to launch...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ int32_t maxItems = 7;
+
+ int32_t start = 0;
+ if ((int32_t)mBanks->count() >= maxItems)
+ {
+ start = min(max(mSelectedControl - (maxItems / 2), 0), (int32_t)mBanks->count() - maxItems);
+ }
+
+ int32_t itemCount = min(start + maxItems, (int32_t)mBanks->count()) - start;
+ if (itemCount > 0)
+ {
+ uint32_t yPos = (context::getBufferHeight() - ((itemCount * 40) - 10)) / 2;
+ yPos += theme::getCenterOffset();
+
+ for (int32_t i = 0; i < itemCount; i++)
+ {
+ uint32_t index = start + i;
+ bankDetails* bank = mBanks->get(index);
+ char* bankName = stringUtility::formatString(bank->autoBoot ? "* %s *" : "%s", bank->name);
+ component::button(mSelectedControl == index, false, bankName, 40, yPos, 640, 30);
+ free(bankName);
+ yPos += 40;
+ }
+ }
+ else
+ {
+ int yPos = ((context::getBufferHeight() - 44) / 2);
+ yPos += theme::getCenterOffset();
+
+ component::textBox("No items", false, false, horizAlignmentCenter, 40, yPos, 640, 44);
+ }
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Select \xC2\xA4 Toggle Auto Boot", theme::getFooterTextColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Cancel", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/launchScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/launchScene.h
new file mode 100644
index 0000000..afdef7a
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/launchScene.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "scene.h"
+
+#include "..\pointerVector.h"
+#include "..\settingsManager.h"
+
+class launchScene : public scene
+{
+public:
+ launchScene();
+ ~launchScene();
+ void update();
+ void render();
+private:
+ void setupBanks();
+
+ int mSelectedControl;
+ pointerVector* mBanks;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/launcherFlowScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/launcherFlowScene.cpp
new file mode 100644
index 0000000..159102c
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/launcherFlowScene.cpp
@@ -0,0 +1,100 @@
+#include "launcherFlowScene.h"
+#include "sceneManager.h"
+#include "filePickerScene.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxInternals.h"
+#include "..\driveManager.h"
+#include "..\fileSystem.h"
+
+void launcherFlowScene::onFilePickerClosingCallback(sceneResult result, void* context, scene* scene)
+{
+ launcherFlowScene* self = (launcherFlowScene*)context;
+ if (result == sceneResultCancelled)
+ {
+ self->mCurrentSceneId = 2;
+ return;
+ }
+ filePickerScene* closingScene = (filePickerScene*)scene;
+ self->mFilePath = closingScene->getFilePath();
+ self->mCurrentSceneId = 1;
+}
+
+launcherFlowScene::launcherFlowScene()
+{
+ mCurrentSceneId = 0;
+ mFilePath = NULL;
+}
+
+launcherFlowScene::~launcherFlowScene()
+{
+ free(mFilePath);
+}
+
+void launcherFlowScene::update()
+{
+ if (mCurrentSceneId == 0)
+ {
+ sceneContainer* container = new sceneContainer(sceneItemGenericScene, new filePickerScene(filePickerTypeXbe), "", this, onFilePickerClosingCallback);
+ sceneManager::pushScene(container);
+ return;
+ }
+
+ if (mCurrentSceneId == 1)
+ {
+ if (launchXbe(mFilePath) == false)
+ {
+ mCurrentSceneId = 2;
+ return;
+ }
+ }
+
+ if (mCurrentSceneId == 2)
+ {
+ sceneManager::popScene();
+ }
+}
+
+void launcherFlowScene::render()
+{
+}
+
+bool launcherFlowScene::launchXbe(const char* path)
+{
+ int result = 0;
+
+ char* mountPointToDelete = strdup("\\??\\D:");
+ STRING sMountPointToDelete = {(USHORT)strlen(mountPointToDelete), (USHORT)strlen(mountPointToDelete) + 1, mountPointToDelete};
+ result |= IoDeleteSymbolicLink(&sMountPointToDelete);
+
+ char* mountPoint = strdup("\\??\\D:");
+ STRING sMountPoint = {(USHORT)strlen(mountPoint), (USHORT)strlen(mountPoint) + 1, mountPoint};
+ char* tempPath = fileSystem::getDirectory(path);
+ char* systemPath = driveManager::convertMountPointToSystemPath(tempPath);
+ STRING sSystemPath = {(USHORT)strlen(systemPath), (USHORT)strlen(systemPath) + 1, systemPath};
+ result |= IoCreateSymbolicLink(&sMountPoint, &sSystemPath);
+
+ if (result != 0)
+ {
+ return false;
+ }
+
+ free(mountPointToDelete);
+ free(mountPoint);
+ free(tempPath);
+ free(systemPath);
+
+ char* fileName = fileSystem::getFileName(path);
+ char* launchPath = stringUtility::formatString("D:\\%s", fileName);
+ free(fileName);
+
+ XLaunchNewImage(launchPath, NULL);
+ return false;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/launcherFlowScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/launcherFlowScene.h
new file mode 100644
index 0000000..cf8ec92
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/launcherFlowScene.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "scene.h"
+#include "filePickerScene.h"
+
+#include "..\xboxInternals.h"
+
+class launcherFlowScene : public scene
+{
+public:
+ launcherFlowScene();
+ ~launcherFlowScene();
+ void update();
+ void render();
+private:
+ uint32_t mCurrentSceneId;
+ char* mFilePath;
+ bool launchXbe(const char* path);
+ static void onFilePickerClosingCallback(sceneResult result, void* context, scene* scene);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/lcdOptionsScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/lcdOptionsScene.cpp
new file mode 100644
index 0000000..d6d1842
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/lcdOptionsScene.cpp
@@ -0,0 +1,295 @@
+#include "lcdOptionsScene.h"
+#include "sceneManager.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxConfig.h"
+#include "..\theme.h"
+#include "..\fileSystem.h"
+
+lcdOptionsScene::lcdOptionsScene()
+{
+ mSelectedControl = 0;
+}
+
+void lcdOptionsScene::update()
+{
+ // Exit Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ settingsManager::loadSettings();
+ sceneManager::popScene();
+ return;
+ }
+
+ if (settingsManager::shouldSave() && inputManager::buttonPressed(ButtonA))
+ {
+ settingsManager::saveSettings();
+ }
+
+ int32_t itemCount = 5;
+ if (context::getModchip()->getLcdModelCount(false) == 0)
+ {
+ itemCount = itemCount - 1;
+ }
+ if (context::getModchip()->getLcdAddressCount(false) == 0)
+ {
+ itemCount = itemCount - 1;
+ }
+ if (context::getModchip()->getSupportInfo(false).supportsLcdBacklight == false)
+ {
+ itemCount = itemCount - 1;
+ }
+ if (context::getModchip()->getSupportInfo(false).supportsLcdContrast == false)
+ {
+ itemCount = itemCount - 1;
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ mSelectedControl = mSelectedControl < (itemCount - 1) ? mSelectedControl + 1 : 0;
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : (itemCount - 1);
+ }
+
+ // Left Trigger
+
+ if (inputManager::buttonPressed(ButtonTriggerLeft) || inputManager::buttonPressed(ButtonX))
+ {
+ int index = 0;
+
+ if (context::getModchip()->getLcdModeCount() > 0 && mSelectedControl == index)
+ {
+ uint8_t lcdMode = settingsManager::getLcdMode(false);
+ lcdMode = lcdMode > 0 ? (lcdMode - 1) : (context::getModchip()->getLcdModeCount() - 1);
+ settingsManager::setLcdMode(lcdMode);
+ settingsManager::setLcdModel(0);
+ settingsManager::setLcdAddress(0);
+ return;
+ }
+
+ if (context::getModchip()->getLcdModelCount(false) > 0)
+ {
+ index++;
+
+ if (mSelectedControl == index)
+ {
+ uint8_t lcdModel = settingsManager::getLcdModel(false);
+ lcdModel = lcdModel > 0 ? (lcdModel - 1) : (context::getModchip()->getLcdModelCount(false) - 1);
+ settingsManager::setLcdModel(lcdModel);
+ settingsManager::setLcdAddress(0);
+ return;
+ }
+ }
+
+ if (context::getModchip()->getLcdAddressCount(false) > 0)
+ {
+ index++;
+
+ if (mSelectedControl == index)
+ {
+ uint8_t lcdAddress = settingsManager::getLcdAddress(false);
+ lcdAddress = lcdAddress > 0 ? (lcdAddress - 1) : (context::getModchip()->getLcdAddressCount(false) - 1);
+ settingsManager::setLcdAddress(lcdAddress);
+ return;
+ }
+ }
+
+ if (context::getModchip()->getSupportInfo(false).supportsLcdBacklight == true)
+ {
+ index++;
+
+ if (mSelectedControl == index)
+ {
+ uint8_t lcdBacklight = settingsManager::getLcdBacklight(false);
+ lcdBacklight = (lcdBacklight >= 4) ? (lcdBacklight - 4) : 100;
+ settingsManager::setLcdBacklight(lcdBacklight);
+ return;
+ }
+ }
+
+ if (context::getModchip()->getSupportInfo(false).supportsLcdContrast == true)
+ {
+ index++;
+
+ if (mSelectedControl == index)
+ {
+ uint8_t lcdContrast = settingsManager::getLcdContrast(false);
+ lcdContrast = (lcdContrast >= 4) ? (lcdContrast - 4) : 100;
+ settingsManager::setLcdContrast(lcdContrast);
+ return;
+ }
+ }
+ }
+
+ // Right Trigger
+
+ if (inputManager::buttonPressed(ButtonTriggerRight) || inputManager::buttonPressed(ButtonY))
+ {
+ int index = 0;
+
+ if (context::getModchip()->getLcdModeCount() > 0 && mSelectedControl == index)
+ {
+ uint8_t lcdMode = settingsManager::getLcdMode(false);
+ lcdMode = (lcdMode < (context::getModchip()->getLcdModeCount()) - 1) ? lcdMode + 1 : 0;
+ settingsManager::setLcdMode(lcdMode);
+ settingsManager::setLcdModel(0);
+ settingsManager::setLcdAddress(0);
+ return;
+ }
+
+ if (context::getModchip()->getLcdModelCount(false) > 0)
+ {
+ index++;
+
+ if (mSelectedControl == index)
+ {
+ uint8_t lcdModel = settingsManager::getLcdModel(false);
+ lcdModel = (lcdModel < (context::getModchip()->getLcdModelCount(false) - 1)) ? lcdModel + 1 : 0;
+ settingsManager::setLcdModel(lcdModel);
+ settingsManager::setLcdAddress(0);
+ return;
+ }
+ }
+
+ if (context::getModchip()->getLcdAddressCount(false) > 0)
+ {
+ index++;
+
+ if (mSelectedControl == index)
+ {
+ uint8_t lcdAddress = settingsManager::getLcdAddress(false);
+ lcdAddress = (lcdAddress < (context::getModchip()->getLcdAddressCount(false) - 1)) ? lcdAddress + 1 : 0;
+ settingsManager::setLcdAddress(lcdAddress);
+ return;
+ }
+ }
+
+ if (context::getModchip()->getSupportInfo(false).supportsLcdBacklight == true)
+ {
+ index++;
+
+ if (mSelectedControl == index)
+ {
+ uint8_t lcdBacklight = settingsManager::getLcdBacklight(false);
+ lcdBacklight = (lcdBacklight >= 100) ? 0 : (lcdBacklight + 4);
+ settingsManager::setLcdBacklight(lcdBacklight);
+ return;
+ }
+ }
+
+ if (context::getModchip()->getSupportInfo(false).supportsLcdContrast == true)
+ {
+ index++;
+
+ if (mSelectedControl == index)
+ {
+ uint8_t lcdContrast = settingsManager::getLcdContrast(false);
+ lcdContrast = (lcdContrast >= 100) ? 0 : (lcdContrast + 4);
+ settingsManager::setLcdContrast(lcdContrast);
+ return;
+ }
+ }
+ }
+}
+
+void lcdOptionsScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "LCD Options...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ uint8_t lcdMode = settingsManager::getLcdMode(false);
+ lcdMode = min(context::getModchip()->getLcdModeCount() - 1, lcdMode);
+ char* lcdModeTempString = context::getModchip()->getLcdModeString(lcdMode);
+ char* lcdModeString = stringUtility::formatString("LCD Mode: %s", lcdModeTempString);
+ free(lcdModeTempString);
+
+ uint8_t lcdModel = settingsManager::getLcdModel(false);
+ lcdModel = min(context::getModchip()->getLcdModelCount(false) - 1, lcdModel);
+ char* lcdModelTempString = context::getModchip()->getLcdModelString(false, lcdModel);
+ char* lcdModelString = stringUtility::formatString("LCD Model: %s", lcdModelTempString);
+ free(lcdModelTempString);
+
+ uint8_t lcdAddress = settingsManager::getLcdAddress(false);
+ lcdAddress = min(context::getModchip()->getLcdAddressCount(false) - 1, lcdAddress);
+ char* lcdAddressTempString = context::getModchip()->getLcdAddressString(false, lcdAddress);
+ char* lcdAddressString = stringUtility::formatString("LCD Address: %s", lcdAddressTempString);
+ free(lcdAddressTempString);
+
+ char* lcdBacklight = stringUtility::formatString("LCD Backlight: %i%%", settingsManager::getLcdBacklight(false));
+ char* lcdContrast = stringUtility::formatString("LCD Contrast: %i%%", settingsManager::getLcdContrast(false));
+
+ pointerVector* menuItems = new pointerVector(false);
+
+ menuItems->add(strdup(lcdModeString));
+
+ if (settingsManager::getLcdMode(false) > 0)
+ {
+ if (context::getModchip()->getLcdModelCount(false) > 0)
+ {
+ menuItems->add(strdup(lcdModelString));
+ }
+ if (context::getModchip()->getLcdAddressCount(false) > 0)
+ {
+ menuItems->add(strdup(lcdAddressString));
+ }
+ if (context::getModchip()->getSupportInfo(false).supportsLcdBacklight == true)
+ {
+ menuItems->add(strdup(lcdBacklight));
+ }
+ if (context::getModchip()->getSupportInfo(false).supportsLcdContrast == true)
+ {
+ menuItems->add(strdup(lcdContrast));
+ }
+ }
+
+ int32_t maxItems = 7;
+
+ int32_t start = 0;
+ if ((int32_t)menuItems->count() >= maxItems)
+ {
+ start = min(max(mSelectedControl - (maxItems / 2), 0), (int32_t)menuItems->count() - maxItems);
+ }
+
+ int32_t itemCount = min(start + maxItems, (int32_t)menuItems->count()) - start;
+ if (itemCount > 0)
+ {
+ uint32_t yPos = (context::getBufferHeight() - ((itemCount * 40) - 10)) / 2;
+ yPos += theme::getCenterOffset();
+
+ for (int32_t i = 0; i < itemCount; i++)
+ {
+ uint32_t index = start + i;
+ char* menuText = menuItems->get(index);
+ component::button(mSelectedControl == index, false, menuText, 193, yPos, 322, 30);
+ yPos += 40;
+ }
+ }
+
+ free(lcdContrast);
+ free(lcdBacklight);
+ free(lcdAddressString);
+ free(lcdModelString);
+ free(lcdModeString);
+
+ delete(menuItems);
+
+ char* options = stringUtility::formatString("\xC2\xA3\xC2\xA4 or \xC2\xB2\xC2\xB3 Change Value%s", settingsManager::shouldSave() ? " or \xC2\xA1 Apply" : "");
+ drawing::drawBitmapString(context::getBitmapFontSmall(), options, theme::getFooterTextColor(), 40, theme::getFooterY());
+ free(options);
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/lcdOptionsScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/lcdOptionsScene.h
new file mode 100644
index 0000000..3f61e49
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/lcdOptionsScene.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "scene.h"
+#include "sceneManager.h"
+
+class lcdOptionsScene : public scene
+{
+public:
+ lcdOptionsScene();
+ void update();
+ void render();
+private:
+ int mSelectedControl;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/ledColorSelectorScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/ledColorSelectorScene.cpp
new file mode 100644
index 0000000..06dd087
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/ledColorSelectorScene.cpp
@@ -0,0 +1,133 @@
+#include "ledColorSelectorScene.h"
+#include "sceneManager.h"
+#include "launchScene.h"
+#include "removeScene.h"
+#include "audioSettingsScene.h"
+#include "mainScene.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxInternals.h"
+#include "..\theme.h"
+
+ledColorSelectorScene::ledColorSelectorScene()
+{
+ mSelectedControl = 4;
+ mLedColor = mSelectedControl;
+ context::getModchip()->setLedColor(mSelectedControl);
+}
+
+void ledColorSelectorScene::update()
+{
+ // Cancel Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ context::getModchip()->setLedColor(settingsManager::getLedColor());
+ sceneManager::popScene(sceneResultCancelled);
+ return;
+ }
+
+ // Select Actions
+
+ if (inputManager::buttonPressed(ButtonA))
+ {
+ mLedColor = mSelectedControl;
+ sceneManager::popScene(sceneResultDone);
+ return;
+ }
+
+ // Left Actions
+
+ if (inputManager::buttonPressed(ButtonDpadLeft))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 3)
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : 3;
+ }
+ else if (mSelectedControl >= 4 && mSelectedControl <= 7)
+ {
+ mSelectedControl = mSelectedControl > 4 ? mSelectedControl - 1 : 7;
+ }
+ context::getModchip()->setLedColor(mSelectedControl);
+ }
+
+ // Right Actions
+
+ if (inputManager::buttonPressed(ButtonDpadRight))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 3)
+ {
+ mSelectedControl = mSelectedControl < 3 ? mSelectedControl + 1 : 0;
+ }
+ else if (mSelectedControl >= 4 && mSelectedControl <= 7)
+ {
+ mSelectedControl = mSelectedControl < 7 ? mSelectedControl + 1 : 4;
+ }
+ context::getModchip()->setLedColor(mSelectedControl);
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 3)
+ {
+ mSelectedControl += 4;
+ }
+ else if (mSelectedControl >= 4 && mSelectedControl <= 7)
+ {
+ mSelectedControl -= 4;
+ }
+ context::getModchip()->setLedColor(mSelectedControl);
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 3)
+ {
+ mSelectedControl += 4;
+ }
+ else if (mSelectedControl >= 4 && mSelectedControl <= 7)
+ {
+ mSelectedControl -= 4;
+ }
+ context::getModchip()->setLedColor(mSelectedControl);
+ }
+}
+
+void ledColorSelectorScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Please select a LED Color...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ int32_t ledX = 38;
+ int32_t ledY = (context::getBufferHeight() - (2 * 48) - 4) / 2;
+ ledY += theme::getCenterOffset();
+
+ component::ledButton(mSelectedControl == 0, 0, "Off", ledX + (162 * 0), ledY + (48 * 0), 158, 44);
+ component::ledButton(mSelectedControl == 1, 1, "Red", ledX + (162 * 1), ledY + (48 * 0), 158, 44);
+ component::ledButton(mSelectedControl == 2, 2, "Green", ledX + (162 * 2), ledY + (48 * 0), 158, 44);
+ component::ledButton(mSelectedControl == 3, 3, "Yellow", ledX + (162 * 3), ledY + (48 * 0), 158, 44);
+
+ component::ledButton(mSelectedControl == 4, 4, "Blue", ledX + (162 * 0), ledY + (48 * 1), 158, 44);
+ component::ledButton(mSelectedControl == 5, 5, "Purple", ledX + (162 * 1), ledY + (48 * 1), 158, 44);
+ component::ledButton(mSelectedControl == 6, 6, "Turquoise", ledX + (162 * 2), ledY + (48 * 1), 158, 44);
+ component::ledButton(mSelectedControl == 7, 7, "White", ledX + (162 * 3), ledY + (48 * 1), 158, 44);
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Select", theme::getFooterTextColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Cancel", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
+
+uint8_t ledColorSelectorScene::getLedColor()
+{
+ return mLedColor;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/ledColorSelectorScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/ledColorSelectorScene.h
new file mode 100644
index 0000000..48dc391
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/ledColorSelectorScene.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "scene.h"
+
+#include "..\xboxInternals.h"
+
+class ledColorSelectorScene : public scene
+{
+public:
+ ledColorSelectorScene();
+ void update();
+ void render();
+ uint8_t getLedColor();
+private:
+ int mSelectedControl;
+ uint8_t mCancelled;
+ uint8_t mLedColor;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/ledOptionsScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/ledOptionsScene.cpp
new file mode 100644
index 0000000..5f3424f
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/ledOptionsScene.cpp
@@ -0,0 +1,138 @@
+#include "ledOptionsScene.h"
+#include "sceneManager.h"
+
+#include "..\utils.h"
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxConfig.h"
+#include "..\theme.h"
+#include "..\fileSystem.h"
+
+ledOptionsScene::ledOptionsScene()
+{
+ mSelectedControl = 0;
+
+ utils::ioOutputByte(MODXO_REGISTER_NVM_CONFIG_SEL, MODXO_NVM_REGISTER_RGB_STATUS_PF);
+ uint8_t statusFormat = utils::ioInputByte(MODXO_REGISTER_NVM_CONFIG_VAL);
+ utils::ioOutputByte(MODXO_REGISTER_NVM_CONFIG_SEL, MODXO_NVM_REGISTER_RGB_STRIP1_PF);
+ uint8_t stripFormat = utils::ioInputByte(MODXO_REGISTER_NVM_CONFIG_VAL);
+
+ mStatusFormat = min(statusFormat, MODXO_PIXEL_FORMAT_GBR);
+ mStripFormat = min(stripFormat, MODXO_PIXEL_FORMAT_GBR);
+}
+
+void ledOptionsScene::update()
+{
+ // Exit Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ settingsManager::loadSettings();
+ sceneManager::popScene();
+ return;
+ }
+
+ if (settingsManager::shouldSave() && inputManager::buttonPressed(ButtonA))
+ {
+ settingsManager::saveSettings();
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ mSelectedControl = mSelectedControl < 1 ? mSelectedControl + 1 : 0;
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : 1;
+ }
+
+ // Left Trigger
+
+ if (inputManager::buttonPressed(ButtonTriggerLeft) || inputManager::buttonPressed(ButtonX))
+ {
+ if (mSelectedControl == 0)
+ {
+ mStatusFormat = mStatusFormat > 0 ? (mStatusFormat - 1) : MODXO_PIXEL_FORMAT_GBR;
+ utils::ioOutputByte(MODXO_REGISTER_NVM_CONFIG_SEL, MODXO_NVM_REGISTER_RGB_STATUS_PF);
+ utils::ioOutputByte(MODXO_REGISTER_NVM_CONFIG_VAL, mStatusFormat);
+ }
+ else if (mSelectedControl == 1)
+ {
+ mStripFormat = mStripFormat > 0 ? (mStripFormat - 1) : MODXO_PIXEL_FORMAT_GBR;
+ utils::ioOutputByte(MODXO_REGISTER_NVM_CONFIG_SEL, MODXO_NVM_REGISTER_RGB_STRIP1_PF);
+ utils::ioOutputByte(MODXO_REGISTER_NVM_CONFIG_VAL, mStripFormat);
+ }
+ }
+
+ // Right Trigger
+
+ if (inputManager::buttonPressed(ButtonTriggerRight) || inputManager::buttonPressed(ButtonY))
+ {
+ if (mSelectedControl == 0)
+ {
+ mStatusFormat = (mStatusFormat < MODXO_PIXEL_FORMAT_GBR) ? mStatusFormat + 1 : 0;
+ utils::ioOutputByte(MODXO_REGISTER_NVM_CONFIG_SEL, MODXO_NVM_REGISTER_RGB_STATUS_PF);
+ utils::ioOutputByte(MODXO_REGISTER_NVM_CONFIG_VAL, mStatusFormat);
+ }
+ else if (mSelectedControl == 1)
+ {
+ mStripFormat = (mStripFormat < MODXO_PIXEL_FORMAT_GBR) ? mStripFormat + 1 : 0;
+ utils::ioOutputByte(MODXO_REGISTER_NVM_CONFIG_SEL, MODXO_NVM_REGISTER_RGB_STRIP1_PF);
+ utils::ioOutputByte(MODXO_REGISTER_NVM_CONFIG_VAL, mStripFormat);
+ }
+ }
+}
+
+void ledOptionsScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "LED Options...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ pointerVector* menuItems = new pointerVector(false);
+
+ char* pixel_formats[] = { "GRB", "RGB", "BRG", "RBG", "BGR", "GBR" };
+
+ menuItems->add(stringUtility::formatString("Status Pixel Format: %s", pixel_formats[mStatusFormat]));
+ menuItems->add(stringUtility::formatString("Strip Pixel Format: %s", pixel_formats[mStripFormat]));
+
+ int32_t maxItems = 7;
+
+ int32_t start = 0;
+ if ((int32_t)menuItems->count() >= maxItems)
+ {
+ start = min(max(mSelectedControl - (maxItems / 2), 0), (int32_t)menuItems->count() - maxItems);
+ }
+
+ int32_t itemCount = min(start + maxItems, (int32_t)menuItems->count()) - start;
+ if (itemCount > 0)
+ {
+ uint32_t yPos = (context::getBufferHeight() - ((itemCount * 40) - 10)) / 2;
+ yPos += theme::getCenterOffset();
+
+ for (int32_t i = 0; i < itemCount; i++)
+ {
+ uint32_t index = start + i;
+ char* menuText = menuItems->get(index);
+ component::button(mSelectedControl == index, false, menuText, 193, yPos, 322, 30);
+ yPos += 40;
+ }
+ }
+
+ delete(menuItems);
+
+ char* options = stringUtility::formatString("\xC2\xA3\xC2\xA4 or \xC2\xB2\xC2\xB3 Change Value%s", settingsManager::shouldSave() ? " or \xC2\xA1 Apply" : "");
+ drawing::drawBitmapString(context::getBitmapFontSmall(), options, theme::getFooterTextColor(), 40, theme::getFooterY());
+ free(options);
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/ledOptionsScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/ledOptionsScene.h
new file mode 100644
index 0000000..8994f4f
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/ledOptionsScene.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "scene.h"
+#include "sceneManager.h"
+
+#include "..\xboxinternals.h"
+
+class ledOptionsScene : public scene
+{
+public:
+ ledOptionsScene();
+ void update();
+ void render();
+private:
+ void setLedColor(uint8_t ledColor);
+private:
+ int mSelectedControl;
+ int mStatusFormat;
+ int mStripFormat;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/mainScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/mainScene.cpp
new file mode 100644
index 0000000..916f493
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/mainScene.cpp
@@ -0,0 +1,209 @@
+#include "mainScene.h"
+#include "sceneManager.h"
+#include "menuScene.h"
+#include "launchScene.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\socketUtility.h"
+#include "..\ftpServer.h"
+#include "..\httpServer.h"
+#include "..\temperatureManager.h"
+#include "..\xboxConfig.h"
+#include "..\theme.h"
+#include "..\network.h"
+#include "..\audioPlayer.h"
+
+mainScene::mainScene()
+{
+ mSelectedControl = 0;
+}
+
+void mainScene::update()
+{
+ // Select Actions
+
+ if (inputManager::buttonPressed(ButtonA))
+ {
+
+#ifdef TOOLS
+
+ if (mSelectedControl == 0)
+ {
+ if (context::getModchipType() == modchipTypeXenium)
+ {
+ context::setModchipType(modchipTypeXecuter);
+ }
+ else if (context::getModchipType() == modchipTypeXecuter)
+ {
+ context::setModchipType(modchipTypeAladdin1mb);
+ }
+ else if (context::getModchipType() == modchipTypeAladdin1mb)
+ {
+ context::setModchipType(modchipTypeAladdin2mb);
+ }
+ else if (context::getModchipType() == modchipTypeAladdin2mb)
+ {
+ context::setModchipType(modchipTypeXchanger);
+ }
+ else if (context::getModchipType() == modchipTypeXchanger)
+ {
+ context::setModchipType(modchipTypeModxo);
+ }
+ else if (context::getModchipType() == modchipTypeModxo)
+ {
+ context::setModchipType(modchipTypeXenium);
+ }
+ }
+ else if (mSelectedControl == 1)
+ {
+ sceneManager::pushScene(sceneItemFlashToolsScene);
+ return;
+ }
+
+#else
+
+ if (mSelectedControl == 0)
+ {
+ sceneManager::pushScene(sceneItemLaunchScene);
+ return;
+ }
+ else if (mSelectedControl == 1)
+ {
+ sceneManager::pushScene(sceneItemBankManagementScene);
+ return;
+ }
+
+#endif
+
+ if (mSelectedControl == 2)
+ {
+ sceneManager::pushScene(sceneItemSystemScene);
+ return;
+ }
+ else if (mSelectedControl == 3)
+ {
+ utils::reboot();
+ return;
+ }
+ else if (mSelectedControl == 4)
+ {
+ utils::shutdown();
+ return;
+ }
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ mSelectedControl = mSelectedControl < 4 ? mSelectedControl + 1 : 0;
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : 4;
+ }
+
+ network::init();
+}
+
+void mainScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+#ifndef TOOLS
+ drawing::drawBitmapStringAligned(context::getBitmapFontLarge(), "\xC2\xA7\xC2\xA8\xC2\xA9\xC2\xAA\xC2\xAB\xC2\xAC\xC2\xAD\xC2\xAB\xC2\xA9\xC2\xAE", theme::getPrometheosColor(), theme::getPrometheosAlign(), 40, theme::getPrometheosY(), 640);
+#else
+ drawing::drawBitmapStringAligned(context::getBitmapFontLarge(), "\xC2\xA7\xC2\xA8\xC2\xA9\xC2\xAA\xC2\xAB\xC2\xAC\xC2\xAD\xC2\xAB\xC2\xA9\xC2\xAE \xC2\xAC\xC2\xA9\xC2\xA9\xC2\xB4\xC2\xAE", theme::getPrometheosColor(), theme::getPrometheosAlign(), 40, theme::getPrometheosY(), 640);
+#endif
+
+ int32_t yPos = (context::getBufferHeight() - (5 * 40) - 10) / 2;
+ yPos += theme::getCenterOffset();
+
+#ifdef TOOLS
+
+ if (context::getModchipType() == modchipTypeDummy)
+ {
+ component::button(mSelectedControl == 0, false, "Modchip: Dummy", 193, yPos, 322, 30);
+ }
+ else if (context::getModchipType() == modchipTypeXenium)
+ {
+ component::button(mSelectedControl == 0, false, "Modchip: Xenium", 193, yPos, 322, 30);
+ }
+ else if (context::getModchipType() == modchipTypeXecuter)
+ {
+ component::button(mSelectedControl == 0, false, "Modchip: Xecuter", 193, yPos, 322, 30);
+ }
+ else if (context::getModchipType() == modchipTypeAladdin1mb)
+ {
+ component::button(mSelectedControl == 0, false, "Modchip: Aladdin 1MB", 193, yPos, 322, 30);
+ }
+ else if (context::getModchipType() == modchipTypeAladdin2mb)
+ {
+ component::button(mSelectedControl == 0, false, "Modchip: Aladdin 2MB", 193, yPos, 322, 30);
+ }
+ else if (context::getModchipType() == modchipTypeXchanger)
+ {
+ component::button(mSelectedControl == 0, false, "Modchip: Xchanger", 193, yPos, 322, 30);
+ }
+ else if (context::getModchipType() == modchipTypeModxo)
+ {
+ component::button(mSelectedControl == 0, false, "Modchip: Modxo", 193, yPos, 322, 30);
+ }
+
+ yPos += 40;
+
+ component::button(mSelectedControl == 1, false, "Flash Tools", 193, yPos, 322, 30);
+
+ yPos += 40;
+
+#else
+
+ component::button(mSelectedControl == 0, false, "Launch Bank", 193, yPos, 322, 30);
+
+ yPos += 40;
+
+ component::button(mSelectedControl == 1, false, "Bank Management", 193, yPos, 322, 30);
+
+ yPos += 40;
+
+#endif
+
+ component::button(mSelectedControl == 2, false, "System", 193, yPos, 322, 30);
+
+ yPos += 40;
+
+ component::button(mSelectedControl == 3, false, "Reboot", 193, yPos, 322, 30);
+
+ yPos += 40;
+
+ component::button(mSelectedControl == 4, false, "Shutdown", 193, yPos, 322, 30);
+
+ char* currentIp = context::getCurrentIp();
+ char* ip = stringUtility::formatString("IP %s", currentIp);
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), ip, theme::getFooterTextColor(), horizAlignmentCenter, 60 + (150 * 0), theme::getFooterY(), 150);
+ free(ip);
+ free(currentIp);
+
+ char* cpuTemp = stringUtility::formatString("CPU Temp %i\xC2\xB1" "C", context::getCurrentCpuTemp());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), cpuTemp, theme::getFooterTextColor(), horizAlignmentCenter, 60 + (150 * 1), theme::getFooterY(), 150);
+ free(cpuTemp);
+
+ char* mbTemp = stringUtility::formatString("M/B Temp %i\xC2\xB1" "C", context::getCurrentMbTemp());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), mbTemp, theme::getFooterTextColor(), horizAlignmentCenter, 60 + (150 * 2), theme::getFooterY(), 150);
+ free(mbTemp);
+
+ char* memoryFormat = stringUtility::formatSize(context::getCurrentFreeMem());
+ char* memory = stringUtility::formatString("Free Mem %s", memoryFormat);
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), memory, theme::getFooterTextColor(), horizAlignmentCenter, 60 + (150 * 3), theme::getFooterY(), 150);
+ free(memory);
+ free(memoryFormat);
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/mainScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/mainScene.h
new file mode 100644
index 0000000..292c57e
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/mainScene.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "scene.h"
+
+#include "..\xboxInternals.h"
+
+class mainScene : public scene
+{
+public:
+ mainScene();
+ void update();
+ void render();
+private:
+ int mSelectedControl;
+
+ int mCounter;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/menuScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/menuScene.cpp
new file mode 100644
index 0000000..7f44958
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/menuScene.cpp
@@ -0,0 +1,320 @@
+#include "menuScene.h"
+#include "sceneManager.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxConfig.h"
+#include "..\theme.h"
+#include "..\audioPlayer.h"
+
+menuScene::menuScene(const char* title, const char* subTitle, pointerVector* sceneItems)
+{
+ mSelectedControl = 0;
+ mTitle = strdup(title);
+ mSubTitle = strdup(subTitle);
+ mSceneItems = sceneItems;
+}
+
+menuScene::~menuScene()
+{
+ free(mTitle);
+ free(mSubTitle);
+ delete(mSceneItems);
+}
+
+void menuScene::setSubTilte(const char* subTitle)
+{
+ free(mSubTitle);
+ mSubTitle = strdup(subTitle);
+}
+
+void menuScene::update()
+{
+ // Exit Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene();
+ }
+
+ // Select Actions
+
+ if (inputManager::buttonPressed(ButtonA))
+ {
+ utils::intContainer* intContainer = mSceneItems->get(mSelectedControl);
+ sceneItemEnum sceneItem = (sceneItemEnum)intContainer->value;
+ sceneManager::pushScene(sceneItem);
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ mSelectedControl = mSelectedControl < (int)(mSceneItems->count() - 1) ? mSelectedControl + 1 : 0;
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : (int)(mSceneItems->count() - 1);
+ }
+}
+
+void menuScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), mTitle, theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ int32_t maxItems = 7;
+
+ int32_t start = 0;
+ if ((int32_t)mSceneItems->count() >= maxItems)
+ {
+ start = min(max(mSelectedControl - (maxItems / 2), 0), (int32_t)mSceneItems->count() - maxItems);
+ }
+
+ int32_t itemCount = min(start + maxItems, (int32_t)mSceneItems->count()) - start;
+ if (itemCount > 0)
+ {
+ uint32_t yPos = (context::getBufferHeight() - ((itemCount * 40) - 10)) / 2;
+ yPos += theme::getCenterOffset();
+
+ for (int32_t i = 0; i < itemCount; i++)
+ {
+ uint32_t index = start + i;
+ utils::intContainer* intContainer = mSceneItems->get(index);
+ sceneItemEnum sceneItem = (sceneItemEnum)intContainer->value;
+ char* menuText = NULL;
+ if (sceneItem == sceneItemSystemScene)
+ {
+ menuText = strdup("System");
+ }
+ else if (sceneItem == sceneItemFlashToolsScene)
+ {
+ menuText = strdup("Flash Tools");
+ }
+ else if (sceneItem == sceneItemSettingsScene)
+ {
+ menuText = strdup("Settings");
+ }
+ else if (sceneItem == sceneItemGamesScene)
+ {
+ menuText = strdup("Games");
+ }
+ else if (sceneItem == sceneItemUtilitiesScene)
+ {
+ menuText = strdup("Utilities");
+ }
+ else if (sceneItem == sceneItemEepromToolsScene)
+ {
+ menuText = strdup("EEPROM Tools");
+ }
+ else if (sceneItem == sceneItemDateTimeScene)
+ {
+ bool doRtc = settingsManager::getRtcEnable() == true && xboxConfig::getHasRtcExpansion() == true;
+ menuText = strdup(doRtc ? "RTC Exapansion" : "Date Time");
+ }
+ else if (sceneItem == sceneItemFlashFlowScene)
+ {
+ menuText = strdup("Flash Bank");
+ }
+ else if (sceneItem == sceneItemRemoveScene)
+ {
+ menuText = strdup("Remove Bank");
+ }
+ else if (sceneItem == sceneItemEditFlowScene)
+ {
+ menuText = strdup("Edit Bank");
+ }
+ else if (sceneItem == sceneItemMainScene)
+ {
+ menuText = strdup("Main");
+ }
+ else if (sceneItem == sceneItemSystemInfoScene)
+ {
+ menuText = strdup("System Info");
+ }
+ else if (sceneItem == sceneItemSystemInfoSceneConsole)
+ {
+ menuText = strdup("Console");
+ }
+ else if (sceneItem == sceneItemSystemInfoSceneStorage)
+ {
+ menuText = strdup("Storage");
+ }
+ else if (sceneItem == sceneItemSystemInfoSceneAudio)
+ {
+ menuText = strdup("Audio");
+ }
+ else if (sceneItem == sceneItemSystemInfoSceneVideo)
+ {
+ menuText = strdup("Video");
+ }
+ else if (sceneItem == sceneItemSystemInfoSceneAbout)
+ {
+ menuText = strdup("About");
+ }
+ else if (sceneItem == sceneItemVideoSettingsScene)
+ {
+ menuText = strdup("Video");
+ }
+ else if (sceneItem == sceneItemAudioSettingsScene)
+ {
+ menuText = strdup("Audio");
+ }
+ else if (sceneItem == sceneItemRegionSettingsScene)
+ {
+ menuText = strdup("Region");
+ }
+ else if (sceneItem == sceneItemNetworkSettingsScene)
+ {
+ menuText = strdup("Network");
+ }
+ else if (sceneItem == sceneItemHddUnlockScene)
+ {
+ menuText = strdup("HDD Lock / Unlock");
+ }
+ else if (sceneItem == sceneItemBackupEepromScene)
+ {
+ menuText = strdup("Backup EEPROM");
+ }
+ else if (sceneItem == sceneItemRestoreEepromScene)
+ {
+ menuText = strdup("Restore EEPROM");
+ }
+ else if (sceneItem == sceneItemPrometheOsSettingsScene)
+ {
+ menuText = strdup("PrometheOS");
+ }
+ else if (sceneItem == sceneItemSkinSelectionScene)
+ {
+ menuText = strdup("Skins");
+ }
+ else if (sceneItem == sceneItemSoundPackSelectionScene)
+ {
+ menuText = strdup("Sound Packs");
+ }
+ else if (sceneItem == sceneItemSnakeScene)
+ {
+ menuText = strdup("Snake");
+ }
+ else if (sceneItem == sceneItemInvadersScene)
+ {
+ menuText = strdup("Invaders");
+ }
+ else if (sceneItem == sceneItemGeneralOptionsScene)
+ {
+ menuText = strdup("General Options");
+ }
+ else if (sceneItem == sceneItemBootOptionsScene)
+ {
+ menuText = strdup("Boot Options");
+ }
+ else if (sceneItem == sceneItemAudioVideoOptionsScene)
+ {
+ menuText = strdup("Audio/Video Options");
+ }
+ else if (sceneItem == sceneItemLcdOptionsScene)
+ {
+ menuText = strdup("LCD Options");
+ }
+ else if (sceneItem == sceneItemLedOptionsScene)
+ {
+ menuText = strdup("LED Options");
+ }
+ else if (sceneItem == sceneItemMiscellaneousOptionsScene)
+ {
+ menuText = strdup("Miscellaneous Options");
+ }
+ else if (sceneItem == sceneItemCerbiosIniEditorScene)
+ {
+ menuText = strdup("Cerbios INI Editor");
+ }
+ else if (sceneItem == sceneItemFormatDriveOptionsScene)
+ {
+ menuText = strdup("Format Drive");
+ }
+ else if (sceneItem == sceneItemFormatDrivePrimaryScene)
+ {
+ menuText = strdup("Format Drive Primary");
+ }
+ else if (sceneItem == sceneItemFormatDriveSecondaryScene)
+ {
+ menuText = strdup("Format Drive Secondary");
+ }
+ else if (sceneItem == sceneItemFlashUpdateFlowScene)
+ {
+ menuText = strdup("Update PrometheOS");
+ }
+ else if (sceneItem == sceneItemFlashBackupScene)
+ {
+ menuText = strdup("Backup PrometheOS");
+ }
+ else if (sceneItem == sceneItemFlashUpdateRecoveryFlowScene)
+ {
+ menuText = strdup("Update Recovery");
+ }
+ else if (sceneItem == sceneItemFlashBackupRecoveryScene)
+ {
+ menuText = strdup("Backup Recovery");
+ }
+ else if (sceneItem == sceneItemPrometheOsThemesScene)
+ {
+ menuText = strdup("Themes");
+ }
+ else if (sceneItem == sceneItemAVSettingsScene)
+ {
+ menuText = strdup("AV Settings");
+ }
+ else if (sceneItem == sceneItemHdmiSettingsScene)
+ {
+ menuText = strdup("Cerbios HDMI Settings");
+ }
+ else if (sceneItem == sceneItemHdmiVideoSettingsScene)
+ {
+ menuText = strdup("Video Settings");
+ }
+ else if (sceneItem == sceneItemHdmiAdvancedScene)
+ {
+ menuText = strdup("Advanced");
+ }
+ else if (sceneItem == sceneItemHdmiInterpolationScene)
+ {
+ menuText = strdup("Interpolation");
+ }
+ else if (sceneItem == sceneItemLauncherFlowScene)
+ {
+ menuText = strdup("Launch XBE");
+ }
+ else if (sceneItem == sceneItemDlcSignerScene)
+ {
+ menuText = strdup("DLC / Update Signer");
+ }
+ else
+ {
+ menuText = strdup("");
+ }
+ component::button(mSelectedControl == index, false, menuText, 193, yPos, 322, 30);
+ free(menuText);
+ yPos += 40;
+ }
+ }
+ else
+ {
+ int yPos = ((context::getBufferHeight() - 44) / 2);
+ yPos += theme::getCenterOffset();
+
+ component::textBox("No items", false, false, horizAlignmentCenter, 193, yPos, 322, 44);
+ }
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Select", theme::getFooterTextColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), mSubTitle, theme::getFooterTextColor(), horizAlignmentCenter, 40, theme::getFooterY(), 640);
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/menuScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/menuScene.h
new file mode 100644
index 0000000..f5251ba
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/menuScene.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "scene.h"
+#include "sceneManager.h"
+
+#include "../pointerMap.h"
+#include "../utils.h"
+
+class menuScene : public scene
+{
+public:
+ menuScene(const char* title, const char* subTitle, pointerVector* sceneItems);
+ ~menuScene();
+ void setSubTilte(const char* subTitle);
+ void update();
+ void render();
+private:
+ int mSelectedControl;
+ char* mTitle;
+ char* mSubTitle;
+ pointerVector* mSceneItems;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/miscellaneousOptionsScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/miscellaneousOptionsScene.cpp
new file mode 100644
index 0000000..7958277
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/miscellaneousOptionsScene.cpp
@@ -0,0 +1,218 @@
+#include "miscellaneousOptionsScene.h"
+#include "sceneManager.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxConfig.h"
+#include "..\theme.h"
+#include "..\fileSystem.h"
+
+miscellaneousOptionsScene::miscellaneousOptionsScene()
+{
+ mSelectedControl = 0;
+}
+
+void miscellaneousOptionsScene::update()
+{
+ // Exit Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene();
+ return;
+ }
+
+ int32_t itemCount = 4;
+ if (context::getModchip()->getSupportInfo(true).supportsLed == false)
+ {
+ itemCount = itemCount - 1;
+ }
+
+ if (xboxConfig::getHasRtcExpansion() == false)
+ {
+ itemCount = itemCount - 1;
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ mSelectedControl = mSelectedControl < (itemCount - 1) ? mSelectedControl + 1 : 0;
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : (itemCount - 1);
+ }
+
+ // Left Trigger
+
+ if (inputManager::buttonPressed(ButtonTriggerLeft) || inputManager::buttonPressed(ButtonX))
+ {
+ int index = 0;
+
+ if (mSelectedControl == index)
+ {
+ uint8_t minFanSpeed = settingsManager::getMinFanSpeed();
+ minFanSpeed = (minFanSpeed >= 20) ? (minFanSpeed - 10) : 100;
+ settingsManager::setMinFanSpeed(minFanSpeed);
+ return;
+ }
+
+ index++;
+
+ if (mSelectedControl == index)
+ {
+ uint8_t driveSetup = settingsManager::getDriveSetup();
+ driveSetup = (driveSetup > 0) ? (driveSetup - 1) : 3;
+ settingsManager::setDriveSetup(driveSetup);
+ return;
+ }
+
+ if (context::getModchip()->getSupportInfo(true).supportsLed == true)
+ {
+ index++;
+
+ if (mSelectedControl == index)
+ {
+ uint8_t ledColor = settingsManager::getLedColor();
+ ledColor = (ledColor >= 1) ? (ledColor - 1) : 7;
+ settingsManager::setLedColor(ledColor);
+ context::getModchip()->setLedColor(ledColor);
+ return;
+ }
+ }
+
+ if (xboxConfig::getHasRtcExpansion() == true)
+ {
+ index++;
+
+ if (mSelectedControl == index)
+ {
+ bool rtcEnable = settingsManager::getRtcEnable();
+ settingsManager::setRtcEnable(!rtcEnable);
+ return;
+ }
+ }
+ }
+
+ // Right Trigger
+
+ if (inputManager::buttonPressed(ButtonTriggerRight) || inputManager::buttonPressed(ButtonY))
+ {
+ int index = 0;
+
+ if (mSelectedControl == index)
+ {
+ uint8_t minFanSpeed = settingsManager::getMinFanSpeed();
+ minFanSpeed = (minFanSpeed >= 100) ? 10 : (minFanSpeed + 10);
+ settingsManager::setMinFanSpeed(minFanSpeed);
+ return;
+ }
+
+ index++;
+
+ if (mSelectedControl == index)
+ {
+ uint8_t driveSetup = settingsManager::getDriveSetup();
+ driveSetup = (driveSetup >= 3) ? 0 : (driveSetup + 1);
+ settingsManager::setDriveSetup(driveSetup);
+ return;
+ }
+
+ if (context::getModchip()->getSupportInfo(true).supportsLed == true)
+ {
+ index++;
+
+ if (mSelectedControl == index)
+ {
+ uint8_t ledColor = settingsManager::getLedColor();
+ ledColor = (ledColor >= 7) ? 0 : (ledColor + 1);
+ settingsManager::setLedColor(ledColor);
+ context::getModchip()->setLedColor(ledColor);
+ return;
+ }
+ }
+
+ if (xboxConfig::getHasRtcExpansion() == true)
+ {
+ index++;
+
+ if (mSelectedControl == index)
+ {
+ bool rtcEnable = settingsManager::getRtcEnable();
+ settingsManager::setRtcEnable(!rtcEnable);
+ return;
+ }
+ }
+ }
+}
+
+void miscellaneousOptionsScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Miscellaneous Options...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ const char* ledColors[] = { "Off", "Red", "Green", "Yellow", "Blue", "Purple", "Turquoise", "White" };
+ const char* driveModes[] = { "HDD & DVD", "HDD & No DVD (Legacy)", "HDD & No DVD (Modern)", "Dual HDD" };
+
+ char* minFanSpeed = stringUtility::formatString("Min Fan Speed: %i%%", settingsManager::getMinFanSpeed());
+ char* driveSetup = stringUtility::formatString("Drive Setup: %s", driveModes[settingsManager::getDriveSetup()]);
+ char* ledColor = stringUtility::formatString("LED Color: %s", ledColors[settingsManager::getLedColor()]);
+ char* rtcEnable = stringUtility::formatString("RTC Enabled: %s", settingsManager::getRtcEnable() == true ? "Yes" : "No");
+
+ pointerVector* menuItems = new pointerVector(false);
+ menuItems->add(strdup(minFanSpeed));
+ menuItems->add(strdup(driveSetup));
+
+ if (context::getModchip()->getSupportInfo(true).supportsLed == true)
+ {
+ menuItems->add(strdup(ledColor));
+ }
+
+ if (xboxConfig::getHasRtcExpansion() == true)
+ {
+ menuItems->add(strdup(rtcEnable));
+ }
+
+ int32_t maxItems = 7;
+
+ int32_t start = 0;
+ if ((int32_t)menuItems->count() >= maxItems)
+ {
+ start = min(max(mSelectedControl - (maxItems / 2), 0), (int32_t)menuItems->count() - maxItems);
+ }
+
+ int32_t itemCount = min(start + maxItems, (int32_t)menuItems->count()) - start;
+ if (itemCount > 0)
+ {
+ uint32_t yPos = (context::getBufferHeight() - ((itemCount * 40) - 10)) / 2;
+ yPos += theme::getCenterOffset();
+
+ for (int32_t i = 0; i < itemCount; i++)
+ {
+ uint32_t index = start + i;
+ char* menuText = menuItems->get(index);
+ component::button(mSelectedControl == index, false, menuText, 193, yPos, 322, 30);
+ yPos += 40;
+ }
+ }
+
+ free(rtcEnable);
+ free(ledColor);
+ free(driveSetup);
+ free(minFanSpeed);
+
+ delete(menuItems);
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA3\xC2\xA4 or \xC2\xB2\xC2\xB3 Change Value", theme::getFooterTextColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/miscellaneousOptionsScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/miscellaneousOptionsScene.h
new file mode 100644
index 0000000..5297e88
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/miscellaneousOptionsScene.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "scene.h"
+#include "sceneManager.h"
+
+class miscellaneousOptionsScene : public scene
+{
+public:
+ miscellaneousOptionsScene();
+ void update();
+ void render();
+private:
+ int mSelectedControl;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/networkSettingsScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/networkSettingsScene.cpp
new file mode 100644
index 0000000..04c025f
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/networkSettingsScene.cpp
@@ -0,0 +1,312 @@
+#include "networkSettingsScene.h"
+#include "sceneManager.h"
+#include "removeScene.h"
+#include "flashFlowScene.h"
+#include "editFlowScene.h"
+#include "keypadScene.h"
+#include "audioSettingsScene.h"
+#include "videoSettingsScene.h"
+#include "keypadScene.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxConfig.h"
+#include "..\theme.h"
+#include "..\network.h"
+
+void networkSettingsScene::onKeypadClosingCallback(sceneResult result, void* context, scene* scene)
+{
+ networkSettingsScene* self = (networkSettingsScene*)context;
+ if (result == sceneResultCancelled)
+ {
+ return;
+ }
+ keypadScene* closingScene = (keypadScene*)scene;
+ if (self->mSelectedControl == 1)
+ {
+ self->mAddress = closingScene->getValue();
+ }
+ else if (self->mSelectedControl == 2)
+ {
+ self->mSubnet = closingScene->getValue();
+ }
+ else if (self->mSelectedControl == 3)
+ {
+ self->mGateway = closingScene->getValue();
+ }
+ else if (self->mSelectedControl == 4)
+ {
+ self->mPrimaryDns = closingScene->getValue();
+ }
+ else if (self->mSelectedControl == 5)
+ {
+ self->mSecondaryDns = closingScene->getValue();
+ }
+}
+
+networkSettingsScene::networkSettingsScene()
+{
+ mSelectedControl = 0;
+ mNetworkMode = settingsManager::getNetworkMode();
+ mAddress = settingsManager::getNetworkAddress();
+ mSubnet = settingsManager::getNetworkSubnet();
+ mGateway = settingsManager::getNetworkGateway();
+ mPrimaryDns = settingsManager::getNetworkPrimaryDns();
+ mSecondaryDns = settingsManager::getNetworkSecondaryDns();
+ mRefreshNetwork = mNetworkMode != networkModeStatic;
+
+ if (mNetworkMode == networkModeStatic)
+ {
+ if (mAddress == 0)
+ {
+ mAddress = network::getAddress();
+ }
+ if (mSubnet == 0)
+ {
+ mSubnet = network::getSubnet();
+ }
+ if (mGateway == 0)
+ {
+ mGateway = network::getGateway();
+ }
+ }
+
+ if (mNetworkMode == networkModeStatic || mNetworkMode == networkModeDynamicManualDns)
+ {
+ if (mPrimaryDns == 0)
+ {
+ mPrimaryDns = network::getPrimaryDns();
+ }
+ if (mSecondaryDns == 0)
+ {
+ mSecondaryDns = network::getSecondaryDns();
+ }
+ }
+
+}
+
+void networkSettingsScene::update()
+{
+ if (mRefreshNetwork == true && network::isReady())
+ {
+ if (mNetworkMode != networkModeStatic)
+ {
+ mAddress = network::getAddress();
+ mSubnet = network::getSubnet();
+ mGateway = network::getGateway();
+ }
+ if (mNetworkMode == networkModeDynamicAutoDns)
+ {
+ mPrimaryDns = network::getPrimaryDns();
+ mSecondaryDns = network::getSecondaryDns();
+ }
+ mRefreshNetwork = false;
+ }
+
+ // Exit Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene();
+ return;
+ }
+
+ // Apply Action
+
+ if (hasNetworkChanges() && inputManager::buttonPressed(ButtonY))
+ {
+ settingsManager::setNetwork(mNetworkMode, mAddress, mSubnet, mGateway, mPrimaryDns, mSecondaryDns);
+ network::restart();
+ mRefreshNetwork = true;
+ }
+
+ // Select Action
+
+ if (inputManager::buttonPressed(ButtonA))
+ {
+ if (mSelectedControl == 0)
+ {
+ if (mNetworkMode == networkModeDynamicAutoDns)
+ {
+ mNetworkMode = networkModeDynamicManualDns;
+ }
+ else if (mNetworkMode == networkModeDynamicManualDns)
+ {
+ mNetworkMode = networkModeStatic;
+ }
+ else if (mNetworkMode == networkModeStatic)
+ {
+ mNetworkMode = networkModeDynamicAutoDns;
+ }
+ }
+ else if (mSelectedControl == 1 && mNetworkMode == networkModeStatic)
+ {
+ sceneContainer* container = new sceneContainer(sceneItemGenericScene, new keypadScene("Please enter IP...", mAddress), "", this, onKeypadClosingCallback);
+ sceneManager::pushScene(container);
+ return;
+ }
+ else if (mSelectedControl == 2 && mNetworkMode == networkModeStatic)
+ {
+ sceneContainer* container = new sceneContainer(sceneItemGenericScene, new keypadScene("Please enter Subnet...", mSubnet), "", this, onKeypadClosingCallback);
+ sceneManager::pushScene(container);
+ return;
+ }
+ else if (mSelectedControl == 3 && mNetworkMode == networkModeStatic)
+ {
+ sceneContainer* container = new sceneContainer(sceneItemGenericScene, new keypadScene("Please enter Gateway...", mGateway), "", this, onKeypadClosingCallback);
+ sceneManager::pushScene(container);
+ return;
+ }
+ else if (mSelectedControl == 4 && (mNetworkMode == networkModeStatic || mNetworkMode == networkModeDynamicManualDns))
+ {
+ sceneContainer* container = new sceneContainer(sceneItemGenericScene, new keypadScene("Please enter Primary DNS...", mPrimaryDns), "", this, onKeypadClosingCallback);
+ sceneManager::pushScene(container);
+ return;
+ }
+ else if (mSelectedControl == 5 && (mNetworkMode == networkModeStatic || mNetworkMode == networkModeDynamicManualDns))
+ {
+ sceneContainer* container = new sceneContainer(sceneItemGenericScene, new keypadScene("Please enter Secondary DNS...", mSecondaryDns), "", this, onKeypadClosingCallback);
+ sceneManager::pushScene(container);
+ return;
+ }
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ mSelectedControl = mSelectedControl < 5 ? mSelectedControl + 1 : 0;
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : 5;
+ }
+}
+
+void networkSettingsScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Network Settings...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ uint32_t yPos = (context::getBufferHeight() - ((6 * 40) - 10)) / 2;
+ yPos += theme::getCenterOffset();
+
+ if (mNetworkMode == networkModeDynamicAutoDns)
+ {
+ component::button(mSelectedControl == 0, false, "Mode: Dynamic IP (Automatic DNS)", 193, yPos, 322, 30);
+ }
+ else if (mNetworkMode == networkModeDynamicManualDns)
+ {
+ component::button(mSelectedControl == 0, false, "Mode: Dynamic IP (Manual DNS)", 193, yPos, 322, 30);
+ }
+ else if (mNetworkMode == networkModeStatic)
+ {
+ component::button(mSelectedControl == 0, false, "Mode: Static IP", 193, yPos, 322, 30);
+ }
+
+ yPos += 40;
+
+ char* ip = stringUtility::formatIp(mAddress);
+ char* ipString = stringUtility::formatString("IP Address: %s", ip);
+ if (mNetworkMode == networkModeStatic)
+ {
+ component::button(mSelectedControl == 1, false, ipString, 193, yPos, 322, 30);
+ }
+ else
+ {
+ component::textBox(ipString, mSelectedControl == 1, false, horizAlignmentCenter, 193, yPos, 322, 30);
+ }
+ free(ipString);
+ free(ip);
+
+ yPos += 40;
+
+ char* subnet = stringUtility::formatIp(mSubnet);
+ char* subnetString = stringUtility::formatString("Subnet Mask: %s", subnet);
+ if (mNetworkMode == networkModeStatic)
+ {
+ component::button(mSelectedControl == 2, false, subnetString, 193, yPos, 322, 30);
+ }
+ else
+ {
+ component::textBox(subnetString, mSelectedControl == 2, false, horizAlignmentCenter, 193, yPos, 322, 30);
+ }
+ free(subnetString);
+ free(subnet);
+
+ yPos += 40;
+
+ char* gateway = stringUtility::formatIp(mGateway);
+ char* gatewayString = stringUtility::formatString("Gateway: %s", gateway);
+ if (mNetworkMode == networkModeStatic)
+ {
+ component::button(mSelectedControl == 3, false, gatewayString, 193, yPos, 322, 30);
+ }
+ else
+ {
+ component::textBox(gatewayString, mSelectedControl == 3, false, horizAlignmentCenter, 193, yPos, 322, 30);
+ }
+ free(gatewayString);
+ free(gateway);
+
+ yPos += 40;
+
+ char* primaryDns = stringUtility::formatIp(mPrimaryDns);
+ char* primaryDnsString = stringUtility::formatString("Primary DNS: %s", primaryDns);
+ if (mNetworkMode == networkModeStatic || mNetworkMode == networkModeDynamicManualDns)
+ {
+ component::button(mSelectedControl == 4, false, primaryDnsString, 193, yPos, 322, 30);
+ }
+ else
+ {
+ component::textBox(primaryDnsString, mSelectedControl == 4, false, horizAlignmentCenter, 193, yPos, 322, 30);
+ }
+ free(primaryDnsString);
+ free(primaryDns);
+
+ yPos += 40;
+
+ char* secondaryDns = stringUtility::formatIp(mSecondaryDns);
+ char* secondaryDnsString = stringUtility::formatString("Secondary DNS: %s", secondaryDns);
+ if (mNetworkMode == networkModeStatic || mNetworkMode == networkModeDynamicManualDns)
+ {
+ component::button(mSelectedControl == 5, false, secondaryDnsString, 193, yPos, 322, 30);
+ }
+ else
+ {
+ component::textBox(secondaryDnsString, mSelectedControl == 5, false, horizAlignmentCenter, 193, yPos, 322, 30);
+ }
+ free(secondaryDnsString);
+ free(secondaryDns);
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), hasNetworkChanges() ? "\xC2\xA1 Select \xC2\xA4 Apply" : "\xC2\xA1 Select", theme::getFooterTextColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
+
+bool networkSettingsScene::hasNetworkChanges()
+{
+ bool result = mNetworkMode != settingsManager::getNetworkMode();
+ if (mNetworkMode == networkModeStatic)
+ {
+ result |=
+ (mAddress != settingsManager::getNetworkAddress()) ||
+ (mSubnet != settingsManager::getNetworkSubnet()) ||
+ (mGateway != settingsManager::getNetworkGateway());
+ }
+ if (mNetworkMode == networkModeStatic || mNetworkMode == networkModeDynamicManualDns)
+ {
+ result |=
+ (mPrimaryDns != settingsManager::getNetworkPrimaryDns()) ||
+ (mSecondaryDns != settingsManager::getNetworkSecondaryDns());
+ }
+ return result;
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/networkSettingsScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/networkSettingsScene.h
new file mode 100644
index 0000000..6b00345
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/networkSettingsScene.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "scene.h"
+#include "keypadScene.h"
+
+#include "..\xboxInternals.h"
+#include "..\settingsManager.h"
+
+class networkSettingsScene : public scene
+{
+public:
+ networkSettingsScene();
+ void update();
+ void render();
+private:
+ bool hasNetworkChanges();
+private:
+ int mSelectedControl;
+ networkModeEnum mNetworkMode;
+ uint32_t mAddress;
+ uint32_t mSubnet;
+ uint32_t mGateway;
+ uint32_t mPrimaryDns;
+ uint32_t mSecondaryDns;
+ bool mRefreshNetwork;
+ static void onKeypadClosingCallback(sceneResult result, void* context, scene* scene);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/regionSettingsScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/regionSettingsScene.cpp
new file mode 100644
index 0000000..d15b2e4
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/regionSettingsScene.cpp
@@ -0,0 +1,175 @@
+#include "regionSettingsScene.h"
+#include "sceneManager.h"
+#include "audioSettingsScene.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\inputManager.h"
+#include "..\ssfn.h"
+#include "..\xboxConfig.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\theme.h"
+
+regionSettingsScene::regionSettingsScene()
+{
+ mSelectedControl = 0;
+ if (xboxConfig::getVideoStandardNTSCJ())
+ {
+ mSelectedControl = 1;
+ }
+ else if (xboxConfig::getVideoStandardPALI50())
+ {
+ mSelectedControl = 2;
+ }
+ else if (xboxConfig::getVideoStandardPALI60())
+ {
+ mSelectedControl = 3;
+ }
+}
+
+void regionSettingsScene::update()
+{
+ // Back Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene();
+ return;
+ }
+
+ // Select Actions
+
+ if (inputManager::buttonPressed(ButtonA))
+ {
+ if (mSelectedControl == 0)
+ {
+ xboxConfig::setVideoStandardNTSCM();
+ }
+ else if (mSelectedControl == 1)
+ {
+ xboxConfig::setVideoStandardNTSCJ();
+ }
+ else if (mSelectedControl == 2)
+ {
+ xboxConfig::setVideoStandardPALI50();
+ }
+ else if (mSelectedControl == 3)
+ {
+ xboxConfig::setVideoStandardPALI60();
+ }
+ else if (mSelectedControl == 4)
+ {
+ xboxConfig::setGameRegionNorthAmerica();
+ }
+ else if (mSelectedControl == 5)
+ {
+ xboxConfig::setGameRegionJapan();
+ }
+ else if (mSelectedControl == 6)
+ {
+ xboxConfig::setGameRegionRestOfWorld();
+ }
+ else if (mSelectedControl == 7)
+ {
+ xboxConfig::setDvdRegion((xboxConfig::getDvdRegion() + 1) % 7);
+ }
+ }
+
+ // Left Actions
+
+ if (inputManager::buttonPressed(ButtonDpadLeft))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 3)
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : 3;
+ }
+ else if (mSelectedControl >= 4 && mSelectedControl <= 6)
+ {
+ mSelectedControl = mSelectedControl > 4 ? mSelectedControl - 1 : 6;
+ }
+ }
+
+ // Right Actions
+
+ if (inputManager::buttonPressed(ButtonDpadRight))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 3)
+ {
+ mSelectedControl = mSelectedControl < 3 ? mSelectedControl + 1 : 0;
+ }
+ else if (mSelectedControl >= 4 && mSelectedControl <= 6)
+ {
+ mSelectedControl = mSelectedControl < 6 ? mSelectedControl + 1 : 4;
+ }
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 3)
+ {
+ mSelectedControl = 4;
+ }
+ else if (mSelectedControl >= 4 && mSelectedControl <= 6)
+ {
+ mSelectedControl = 7;
+ }
+ else if (mSelectedControl == 7)
+ {
+ mSelectedControl = 0;
+ }
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 3)
+ {
+ mSelectedControl = 7;
+ }
+ else if (mSelectedControl >= 4 && mSelectedControl <= 6)
+ {
+ mSelectedControl = 0;
+ }
+ else if (mSelectedControl == 7)
+ {
+ mSelectedControl = 4;
+ }
+ }
+}
+
+void regionSettingsScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Region settings...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ int yPos = (context::getBufferHeight() - (30 + 40 + 30 + 40 + 30 + 30)) / 2;
+ yPos += theme::getCenterOffset();
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "Video Standard", theme::getTextColor(), 44, yPos);
+ yPos += 30;
+ component::button(mSelectedControl == 0, xboxConfig::getVideoStandardNTSCM() == true, "NTSC-M", 44 + (159 * 0), yPos, 155, 30);
+ component::button(mSelectedControl == 1, xboxConfig::getVideoStandardNTSCJ() == true, "NTSC-J", 44 + (159 * 1), yPos, 155, 30);
+ component::button(mSelectedControl == 2, xboxConfig::getVideoStandardPALI50() == true, "PAL-I (50hz)", 44 + (159 * 2), yPos, 155, 30);
+ component::button(mSelectedControl == 3, xboxConfig::getVideoStandardPALI60() == true, "PAL-I (60hz)", 44 + (159 * 3), yPos, 155, 30);
+ yPos += 40;
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "Game Region", theme::getTextColor(), 44, yPos);
+ yPos += 30;
+ component::button(mSelectedControl == 4, xboxConfig::getGameRegionNorthAmerica() == true, "North America", 44 + (212 * 0), yPos, 208, 30);
+ component::button(mSelectedControl == 5, xboxConfig::getGameRegionJapan() == true, "Japan", 44 + (212 * 1), yPos, 208, 30);
+ component::button(mSelectedControl == 6, xboxConfig::getGameRegionRestOfWorld() == true, "Rest of World", 44 + (212 * 2), yPos, 208, 30);
+ yPos += 40;
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "DVD Region", theme::getTextColor(), 44, yPos);
+ yPos += 30;
+ char* dvdRegionString = xboxConfig::getDvdRegionString();
+ component::button(mSelectedControl == 7, false, dvdRegionString, 44, yPos, 632, 30);
+ free(dvdRegionString);
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Select", theme::getFooterTextColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/regionSettingsScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/regionSettingsScene.h
new file mode 100644
index 0000000..1da0550
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/regionSettingsScene.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "scene.h"
+
+class regionSettingsScene : public scene
+{
+public:
+ regionSettingsScene();
+ void update();
+ void render();
+private:
+ bool mNeedsRefresh;
+ bool mInitialized;
+ int mSelectedControl;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/removeScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/removeScene.cpp
new file mode 100644
index 0000000..67856b4
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/removeScene.cpp
@@ -0,0 +1,107 @@
+#include "removeScene.h"
+#include "sceneManager.h"
+#include "audioSettingsScene.h"
+#include "videoSettingsScene.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\alignment.h"
+#include "..\theme.h"
+
+removeScene::removeScene()
+{
+ mSelectedControl = 0;
+ mBanks = settingsManager::getBankInfos();
+}
+
+removeScene::~removeScene()
+{
+ delete(mBanks);
+}
+
+void removeScene::update()
+{
+ // Back Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene();
+ return;
+ }
+
+ // Select Actions
+
+ if (inputManager::buttonPressed(ButtonA))
+ {
+ for (uint32_t i = 0; i < mBanks->count(); i++)
+ {
+ if (mSelectedControl != i)
+ {
+ continue;
+ }
+ bankDetails* bank = mBanks->get(i);
+ settingsManager::deleteBank(bank->id);
+ mBanks->remove(i);
+ mSelectedControl = max(min(mSelectedControl, (int)mBanks->count() - 1), 0);
+ }
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ mSelectedControl = mSelectedControl < (int)(mBanks->count() - 1) ? mSelectedControl + 1 : 0;
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : (int)(mBanks->count() - 1);
+ }
+}
+
+void removeScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Please select a bank to remove...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ int32_t maxItems = 7;
+
+ int32_t start = 0;
+ if ((int32_t)mBanks->count() >= maxItems)
+ {
+ start = min(max(mSelectedControl - (maxItems / 2), 0), (int32_t)mBanks->count() - maxItems);
+ }
+
+ int32_t itemCount = min(start + maxItems, (int32_t)mBanks->count()) - start;
+ if (itemCount > 0)
+ {
+ uint32_t yPos = (context::getBufferHeight() - ((itemCount * 40) - 10)) / 2;
+ yPos += theme::getCenterOffset();
+
+ for (int32_t i = 0; i < itemCount; i++)
+ {
+ uint32_t index = start + i;
+ bankDetails* bank = mBanks->get(index);
+ component::button(mSelectedControl == index, false, bank->name, 40, yPos, 640, 30);
+ yPos += 40;
+ }
+ }
+ else
+ {
+ int yPos = ((context::getBufferHeight() - 44) / 2);
+ yPos += theme::getCenterOffset();
+
+ component::textBox("No items", false, false, horizAlignmentCenter, 40, yPos, 640, 44);
+ }
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Select", theme::getFooterTextColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Cancel", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/removeScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/removeScene.h
new file mode 100644
index 0000000..449ee42
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/removeScene.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "scene.h"
+
+#include "..\pointerVector.h"
+#include "..\settingsManager.h"
+
+class removeScene : public scene
+{
+public:
+ removeScene();
+ ~removeScene();
+ void update();
+ void render();
+private:
+ int mSelectedControl;
+ pointerVector* mBanks;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/restoreEepromFlowScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/restoreEepromFlowScene.cpp
new file mode 100644
index 0000000..8b570dd
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/restoreEepromFlowScene.cpp
@@ -0,0 +1,71 @@
+#include "restoreEepromFlowScene.h"
+#include "sceneManager.h"
+#include "restoreEepromScene.h"
+#include "filePickerScene.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxInternals.h"
+#include "..\fileSystem.h"
+
+void restoreEepromFlowScene::onFilePickerClosingCallback(sceneResult result, void* context, scene* scene)
+{
+ restoreEepromFlowScene* self = (restoreEepromFlowScene*)context;
+ if (result == sceneResultCancelled)
+ {
+ self->mCurrentSceneId = 2;
+ return;
+ }
+ filePickerScene* closingScene = (filePickerScene*)scene;
+ self->mFilePath = closingScene->getFilePath();
+ self->mCurrentSceneId = 1;
+}
+
+void restoreEepromFlowScene::onRestoreEepromClosingCallback(sceneResult result, void* context, scene* scene)
+{
+ restoreEepromFlowScene* self = (restoreEepromFlowScene*)context;
+ self->mCurrentSceneId = 2;
+}
+
+restoreEepromFlowScene::restoreEepromFlowScene()
+{
+ mCurrentSceneId = 0;
+ mFilePath = NULL;
+}
+
+restoreEepromFlowScene::~restoreEepromFlowScene()
+{
+ free(mFilePath);
+}
+
+void restoreEepromFlowScene::update()
+{
+ if (mCurrentSceneId == 0)
+ {
+ sceneContainer* container = new sceneContainer(sceneItemGenericScene, new filePickerScene(filePickerTypeEeprom), "", this, onFilePickerClosingCallback);
+ sceneManager::pushScene(container);
+ return;
+ }
+
+ if (mCurrentSceneId == 1)
+ {
+ sceneContainer* container = new sceneContainer(sceneItemGenericScene, new restoreEepromScene(mFilePath), "", this, onRestoreEepromClosingCallback);
+ sceneManager::pushScene(container);
+ return;
+ }
+
+ if (mCurrentSceneId == 2)
+ {
+ sceneManager::popScene();
+ }
+}
+
+void restoreEepromFlowScene::render()
+{
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/restoreEepromFlowScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/restoreEepromFlowScene.h
new file mode 100644
index 0000000..66d3ad3
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/restoreEepromFlowScene.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "scene.h"
+#include "filePickerScene.h"
+#include "restoreEepromScene.h"
+
+#include "..\xboxInternals.h"
+
+class restoreEepromFlowScene : public scene
+{
+public:
+ restoreEepromFlowScene();
+ ~restoreEepromFlowScene();
+ void update();
+ void render();
+private:
+ uint32_t mCurrentSceneId;
+ char* mFilePath;
+ static void onFilePickerClosingCallback(sceneResult result, void* context, scene* scene);
+ static void onRestoreEepromClosingCallback(sceneResult result, void* context, scene* scene);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/restoreEepromScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/restoreEepromScene.cpp
new file mode 100644
index 0000000..4ddf738
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/restoreEepromScene.cpp
@@ -0,0 +1,98 @@
+#include "restoreEepromScene.h"
+#include "sceneManager.h"
+#include "audioSettingsScene.h"
+#include "videoSettingsScene.h"
+#include "mainScene.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\driveManager.h"
+#include "..\fileSystem.h"
+#include "..\pointerVector.h"
+#include "..\settingsManager.h"
+#include "..\theme.h"
+#include "..\XKUtils\XKEEPROM.h"
+
+restoreEepromScene::restoreEepromScene(const char* filePath)
+{
+ mFilePath = strdup(filePath);
+ mProgress = strdup("Ready");
+ mDone = false;
+}
+
+restoreEepromScene::~restoreEepromScene()
+{
+ free(mFilePath);
+}
+
+void restoreEepromScene::update()
+{
+ // Cancel Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ if (mDone == true)
+ {
+ utils::reboot();
+ }
+ else
+ {
+ sceneManager::popScene(sceneResultCancelled);
+ return;
+ }
+ }
+
+ // Select Actions
+
+ if (inputManager::buttonPressed(ButtonA) && mDone == false)
+ {
+ free(mProgress);
+ XKEEPROM* eeprom = new XKEEPROM();
+ if (eeprom->ReadFromBINFile(mFilePath, true) == true)
+ {
+ eeprom->WriteToXBOX();
+ mProgress = strdup("Restored");
+ }
+ else
+ {
+ mProgress = strdup("Restore failed");
+ }
+ delete(eeprom);
+ mDone = true;
+ }
+}
+
+void restoreEepromScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Restore EEPROM...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ int yPos = (context::getBufferHeight() - (30 + 40 + 44)) / 2;
+ yPos += theme::getCenterOffset();
+
+ char* fileName = fileSystem::getFileName(mFilePath);
+ char* formattedFileName = stringUtility::formatString("EEPROM: %s", fileName);
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), formattedFileName, theme::getTextColor(), horizAlignmentCenter, 40, yPos, 640);
+ free(formattedFileName);
+ free(fileName);
+
+ yPos += 30;
+
+ drawing::drawBitmapString(context::getBitmapFontMedium(), "Status", theme::getHeaderTextColor(), 193, yPos);
+
+ yPos += 40;
+
+ component::textBox(mProgress, false, false, horizAlignmentCenter, 193, yPos, 322, 44);
+
+ if (mDone == false)
+ {
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Restore", theme::getFooterTextColor(), 40, theme::getFooterY());
+ }
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), mDone == true ? "\xC2\xA2 Reboot" : "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/restoreEepromScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/restoreEepromScene.h
new file mode 100644
index 0000000..1aee7d1
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/restoreEepromScene.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "scene.h"
+
+#include "..\pointerVector.h"
+
+class restoreEepromScene : public scene
+{
+public:
+ restoreEepromScene(const char* filePath);
+ ~restoreEepromScene();
+ void update();
+ void render();
+private:
+ char* mFilePath;
+ char* mProgress;
+ bool mDone;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/rtcScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/rtcScene.cpp
new file mode 100644
index 0000000..a359355
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/rtcScene.cpp
@@ -0,0 +1,179 @@
+#include "rtcScene.h"
+#include "sceneManager.h"
+#include "audioSettingsScene.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\inputManager.h"
+#include "..\ssfn.h"
+#include "..\xboxConfig.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\theme.h"
+#include "..\rtcManager.h"
+
+rtcScene::rtcScene()
+{
+ bool doRtc = settingsManager::getRtcEnable() == true && xboxConfig::getHasRtcExpansion() == true;
+ mSelectedControl = 0;
+ mHasRtcExpansion = doRtc;
+ mShouldApply = false;
+ mDateTime = doRtc ? rtcManager::getDateTime() : rtcManager::getXboxDateTime();
+}
+
+void rtcScene::update()
+{
+ // Back Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene();
+ return;
+ }
+
+ // Select Actions
+
+ if (inputManager::buttonPressed(ButtonA))
+ {
+ if (mHasRtcExpansion == true)
+ {
+ rtcManager::setDateTime(mDateTime);
+ }
+ rtcManager::setXboxDateTime(mDateTime);
+ mDateTime = mHasRtcExpansion ? rtcManager::getDateTime() : rtcManager::getXboxDateTime();
+ mShouldApply = false;
+ }
+
+ // Left Trigger
+
+ if (inputManager::buttonPressed(ButtonTriggerLeft) || inputManager::buttonPressed(ButtonX))
+ {
+ if (mSelectedControl == 0)
+ {
+ mDateTime.dotw = mDateTime.dotw > 0 ? mDateTime.dotw - 1 : 6;
+ mShouldApply = true;
+ }
+ else if (mSelectedControl == 1)
+ {
+ mDateTime.day = mDateTime.day > 1 ? mDateTime.day - 1 : 31;
+ mShouldApply = true;
+ }
+ else if (mSelectedControl == 2)
+ {
+ mDateTime.month = mDateTime.month > 1 ? mDateTime.month - 1 : 12;
+ mShouldApply = true;
+ }
+ else if (mSelectedControl == 3)
+ {
+ mDateTime.year = mDateTime.year > 0 ? mDateTime.year - 1 : 255;
+ mShouldApply = true;
+ }
+ else if (mSelectedControl == 4)
+ {
+ mDateTime.hour = mDateTime.hour > 0 ? mDateTime.hour - 1 : 23;
+ mShouldApply = true;
+ }
+ else if (mSelectedControl == 5)
+ {
+ mDateTime.min = mDateTime.min > 0 ? mDateTime.min - 1 : 59;
+ mShouldApply = true;
+ }
+ }
+
+ // Right Trigger
+
+ if (inputManager::buttonPressed(ButtonTriggerRight) || inputManager::buttonPressed(ButtonY))
+ {
+ if (mSelectedControl == 0)
+ {
+ mDateTime.dotw = mDateTime.dotw < 6 ? mDateTime.dotw + 1 : 0;
+ mShouldApply = true;
+ }
+ else if (mSelectedControl == 1)
+ {
+ mDateTime.day = mDateTime.day < 31 ? mDateTime.day + 1 : 1;
+ mShouldApply = true;
+ }
+ else if (mSelectedControl == 2)
+ {
+ mDateTime.month = mDateTime.month < 12 ? mDateTime.month + 1 : 1;
+ mShouldApply = true;
+ }
+ else if (mSelectedControl == 3)
+ {
+ mDateTime.year = mDateTime.year < 255 ? mDateTime.year + 1 : 0;
+ mShouldApply = true;
+ }
+ else if (mSelectedControl == 4)
+ {
+ mDateTime.hour = mDateTime.hour < 23 ? mDateTime.hour + 1 : 0;
+ mShouldApply = true;
+ }
+ else if (mSelectedControl == 5)
+ {
+ mDateTime.min = mDateTime.min < 59 ? mDateTime.min + 1 : 0;
+ mShouldApply = true;
+ }
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ mSelectedControl = mSelectedControl < 5 ? mSelectedControl + 1 : 0;
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : 5;
+ }
+}
+
+void rtcScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), mHasRtcExpansion ? "RTC Expansion settings..." : "Date Time settings...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ int xPos = 117;
+ int yPos = (context::getBufferHeight() - ((6 * 40) - 10)) / 2;
+ yPos += theme::getCenterOffset();
+
+ const char* daysOfWeek[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
+ char* dayOfWeekString = stringUtility::formatString("Day Of Week: %s", daysOfWeek[mDateTime.dotw]);
+ component::button(mSelectedControl == 0, false, dayOfWeekString, 193, yPos, 322, 30);
+ free(dayOfWeekString);
+ yPos += 40;
+
+ char* dayString = stringUtility::formatString("Day: %i", mDateTime.day);
+ component::button(mSelectedControl == 1, false, dayString, 193, yPos, 322, 30);
+ free(dayString);
+ yPos += 40;
+
+ const char* months[12] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
+ char* monthString = stringUtility::formatString("Month: %s", months[mDateTime.month - 1]);
+ component::button(mSelectedControl == 2, false, monthString, 193, yPos, 322, 30);
+ free(monthString);
+ yPos += 40;
+
+ char* yearString = stringUtility::formatString("Year: %i", 2000 + mDateTime.year);
+ component::button(mSelectedControl == 3, false, yearString, 193, yPos, 322, 30);
+ free(yearString);
+ yPos += 40;
+
+ char* hourString = stringUtility::formatString("Hour (24h): %i", mDateTime.hour);
+ component::button(mSelectedControl == 4, false, hourString, 193, yPos, 322, 30);
+ free(hourString);
+ yPos += 40;
+
+ char* minString = stringUtility::formatString("Minutes: %i", mDateTime.min);
+ component::button(mSelectedControl == 5, false, minString, 193, yPos, 322, 30);
+ free(minString);
+ yPos += 40;
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), mShouldApply ? "\xC2\xA3\xC2\xA4 or \xC2\xB2\xC2\xB3 Change Value \xC2\xA1 Apply" : "\xC2\xA3\xC2\xA4 or \xC2\xB2\xC2\xB3 Change Value", theme::getFooterTextColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/rtcScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/rtcScene.h
new file mode 100644
index 0000000..a9bac1b
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/rtcScene.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "scene.h"
+
+#include "..\rtcManager.h"
+
+class rtcScene : public scene
+{
+public:
+ rtcScene();
+ void update();
+ void render();
+private:
+ int mSelectedControl;
+ bool mHasRtcExpansion;
+ bool mShouldApply;
+ rtcDateTime mDateTime;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/scene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/scene.h
new file mode 100644
index 0000000..7fbcc04
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/scene.h
@@ -0,0 +1,15 @@
+#pragma once
+
+enum sceneResult
+{
+ sceneResultNone = 0,
+ sceneResultDone = 1,
+ sceneResultCancelled = 2
+};
+
+class scene
+{
+public:
+ virtual void update() = 0;
+ virtual void render() = 0;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/sceneManager.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/sceneManager.cpp
new file mode 100644
index 0000000..e150359
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/sceneManager.cpp
@@ -0,0 +1,474 @@
+#include "scenemanager.h"
+#include "scene.h"
+#include "flashFlowScene.h"
+#include "removeScene.h"
+#include "editFlowScene.h"
+#include "mainScene.h"
+#include "systemInfoScene.h"
+#include "videoSettingsScene.h"
+#include "videoSettingsScene.h"
+#include "audioSettingsScene.h"
+#include "regionSettingsScene.h"
+#include "networkSettingsScene.h"
+#include "hddLockUnlockScene.h"
+#include "backupEepromScene.h"
+#include "restoreEepromFlowScene.h"
+#include "rtcScene.h"
+#include "menuScene.h"
+#include "skinSelectionScene.h"
+#include "soundPackSelectionScene.h"
+#include "snakeScene.h"
+#include "invadersScene.h"
+#include "launchScene.h"
+#include "autoBootScene.h"
+#include "bootOptionsScene.h"
+#include "audioVideoOptionsScene.h"
+#include "lcdOptionsScene.h"
+#include "ledOptionsScene.h"
+#include "miscellaneousOptionsScene.h"
+#include "cerbiosIniEditorScene.h"
+#include "flashUpdateFlowScene.h"
+#include "flashBackupScene.h"
+#include "hdmiVideoSettingsScene.h"
+#include "hdmiAdvancedScene.h"
+#include "hdmiInterpolationScene.h"
+#include "hddPasswordScene.h"
+#include "formatDriveScene.h"
+#include "launcherFlowScene.h"
+#include "dlcSignerScene.h"
+
+#include "..\xboxConfig.h"
+#include "..\context.h"
+#include "..\settingsManager.h"
+#include "..\stringUtility.h"
+#include "..\hdmiDevice.h"
+#include "..\pointerVector.h"
+#include "..\Threads\lcdRender.h"
+
+#include
+
+namespace
+{
+ pointerVector* mScenes = new pointerVector(true);
+}
+
+scene* sceneManager::getScene()
+{
+ sceneContainer* result = mScenes->get(mScenes->count() - 1);
+ return result->scene;
+}
+
+void sceneManager::pushScene(sceneItemEnum sceneItem)
+{
+ if (sceneItem == sceneItemMainScene)
+ {
+ char *versionSemver = settingsManager::getVersionSting(settingsManager::getVersion());
+ char *version = stringUtility::formatString("PrometheOS: V%s", versionSemver);
+ sceneContainer* container = new sceneContainer(sceneItem, new mainScene(), version);
+ free(version);
+ free(versionSemver);
+ addScene(container);
+ }
+ if (sceneItem == sceneItemSystemScene)
+ {
+ pointerVector* sceneItems = new pointerVector(true);
+ sceneItems->add(new utils::intContainer(sceneItemSystemInfoScene));
+ sceneItems->add(new utils::intContainer(sceneItemSettingsScene));
+ sceneItems->add(new utils::intContainer(sceneItemUtilitiesScene));
+ sceneItems->add(new utils::intContainer(sceneItemGamesScene));
+#ifdef TOOLS
+ sceneItems->add(new utils::intContainer(sceneItemLauncherFlowScene));
+#endif
+ sceneContainer* container = new sceneContainer(sceneItem, new menuScene("Select System option...", "", sceneItems), "System Settings");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemSettingsScene)
+ {
+ pointerVector* sceneItems = new pointerVector(true);
+ sceneItems->add(new utils::intContainer(sceneItemAVSettingsScene));
+ sceneItems->add(new utils::intContainer(sceneItemRegionSettingsScene));
+ sceneItems->add(new utils::intContainer(sceneItemNetworkSettingsScene));
+ sceneItems->add(new utils::intContainer(sceneItemDateTimeScene));
+#ifndef TOOLS
+ sceneItems->add(new utils::intContainer(sceneItemPrometheOsSettingsScene));
+#endif
+ sceneContainer* container = new sceneContainer(sceneItem, new menuScene("Select Settings option...", "", sceneItems), "Settings");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemGamesScene)
+ {
+ pointerVector* sceneItems = new pointerVector(true);
+ sceneItems->add(new utils::intContainer(sceneItemSnakeScene));
+ sceneItems->add(new utils::intContainer(sceneItemInvadersScene));
+ sceneContainer* container = new sceneContainer(sceneItem, new menuScene("Select Game option...", "", sceneItems), "Games");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemUtilitiesScene)
+ {
+ pointerVector* sceneItems = new pointerVector(true);
+#ifndef TOOLS
+ sceneItems->add(new utils::intContainer(sceneItemHddUnlockScene));
+ sceneItems->add(new utils::intContainer(sceneItemFlashToolsScene));
+#endif
+ sceneItems->add(new utils::intContainer(sceneItemEepromToolsScene));
+ sceneItems->add(new utils::intContainer(sceneItemCerbiosIniEditorScene));
+#ifndef TOOLS
+ sceneItems->add(new utils::intContainer(sceneItemFormatDriveOptionsScene));
+#endif
+ sceneItems->add(new utils::intContainer(sceneItemDlcSignerScene));
+ sceneContainer* container = new sceneContainer(sceneItem, new menuScene("Select Utility option...", "", sceneItems), "Utilities");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemFormatDriveOptionsScene)
+ {
+ pointerVector* sceneItems = new pointerVector(true);
+ sceneItems->add(new utils::intContainer(sceneItemFormatDrivePrimaryScene));
+ if (settingsManager::getDriveSetup() == 3)
+ {
+ sceneItems->add(new utils::intContainer(sceneItemFormatDriveSecondaryScene));
+ }
+ sceneContainer* container = new sceneContainer(sceneItem, new menuScene("Select Format Drive option...", "", sceneItems), "Drive Selection");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemBankManagementScene)
+ {
+ pointerVector* sceneItems = new pointerVector(true);
+ sceneItems->add(new utils::intContainer(sceneItemFlashFlowScene));
+ sceneItems->add(new utils::intContainer(sceneItemRemoveScene));
+ sceneItems->add(new utils::intContainer(sceneItemEditFlowScene));
+
+ char* subTitle = stringUtility::formatString("Free Slots %i", settingsManager::getFreeSlots());
+ sceneContainer* container = new sceneContainer(sceneItem, new menuScene("Select Bank option...", subTitle, sceneItems), "Bank Management");
+ addScene(container);
+ free(subTitle);
+ }
+ else if (sceneItem == sceneItemEepromToolsScene)
+ {
+ pointerVector* sceneItems = new pointerVector(true);
+ sceneItems->add(new utils::intContainer(sceneItemBackupEepromScene));
+ sceneItems->add(new utils::intContainer(sceneItemRestoreEepromScene));
+ sceneContainer* container = new sceneContainer(sceneItem, new menuScene("Select EEPROM option...", "", sceneItems), "EEPROM Selection");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemDateTimeScene)
+ {
+ bool doRtc = settingsManager::getRtcEnable() == true && xboxConfig::getHasRtcExpansion() == true;
+ sceneContainer* container = new sceneContainer(sceneItem, new rtcScene(), doRtc ? "RTC Exapansion" : "Date Time");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemFlashFlowScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new flashFlowScene(), "Flash Bank");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemRemoveScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new removeScene(), "Remove Bank");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemEditFlowScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new editFlowScene(), "Edit");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemSystemInfoScene)
+ {
+ pointerVector* sceneItems = new pointerVector(true);
+ sceneItems->add(new utils::intContainer(sceneItemSystemInfoSceneConsole));
+ sceneItems->add(new utils::intContainer(sceneItemSystemInfoSceneStorage));
+ sceneItems->add(new utils::intContainer(sceneItemSystemInfoSceneAudio));
+ sceneItems->add(new utils::intContainer(sceneItemSystemInfoSceneVideo));
+ sceneItems->add(new utils::intContainer(sceneItemSystemInfoSceneAbout));
+ sceneContainer* container = new sceneContainer(sceneItem, new menuScene("Select System Info option...", "", sceneItems), "System Info");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemSystemInfoSceneConsole)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new systemInfoScene(systemInfoCategoryConsole), "Console Info");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemSystemInfoSceneStorage)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new systemInfoScene(systemInfoCategoryStorage), "Storage Info");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemSystemInfoSceneAudio)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new systemInfoScene(systemInfoCategoryAudio), "Audio Info");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemSystemInfoSceneVideo)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new systemInfoScene(systemInfoCategoryVideo), "Video Info");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemSystemInfoSceneAbout)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new systemInfoScene(systemInfoCategoryAbout), "About Info");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemVideoSettingsScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new videoSettingsScene(), "Video Settings");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemAudioSettingsScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new audioSettingsScene(), "Audio Settings");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemRegionSettingsScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new regionSettingsScene(), "Region Settings");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemNetworkSettingsScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new networkSettingsScene(), "Network");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemHddUnlockScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new hddLockUnlockScene(), "HDD Lock / Unlock");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemBackupEepromScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new backupEepromScene(), "Backup EEPROM");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemRestoreEepromScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new restoreEepromFlowScene(), "Restore EEPROM");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemFlashToolsScene)
+ {
+ pointerVector* sceneItems = new pointerVector(true);
+ sceneItems->add(new utils::intContainer(sceneItemFlashUpdateFlowScene));
+ sceneItems->add(new utils::intContainer(sceneItemFlashBackupScene));
+ if (context::getModchip()->getSupportInfo(true).supportsRecovery == true)
+ {
+ sceneItems->add(new utils::intContainer(sceneItemFlashUpdateRecoveryFlowScene));
+ sceneItems->add(new utils::intContainer(sceneItemFlashBackupRecoveryScene));
+ }
+ sceneContainer* container = new sceneContainer(sceneItem, new menuScene("Select Flash Tool option...", "", sceneItems), "Flash Tools");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemPrometheOsSettingsScene)
+ {
+ pointerVector* sceneItems = new pointerVector(true);
+ sceneItems->add(new utils::intContainer(sceneItemPrometheOsThemesScene));
+ sceneItems->add(new utils::intContainer(sceneItemGeneralOptionsScene));
+ sceneContainer* container = new sceneContainer(sceneItem, new menuScene("Select PrometheOS option...", "", sceneItems), "PrometheOS");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemSkinSelectionScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new skinSelectionScene(), "Skins");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemSoundPackSelectionScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new soundPackSelectionScene(), "Sound Packs");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemSnakeScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new snakeScene(), "Snake");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemInvadersScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new invadersScene(), "Invaders");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemLaunchScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new launchScene(), "Launch Bank");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemAutoBootScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new autoBootScene(), "Auto Boot");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemGeneralOptionsScene)
+ {
+ pointerVector* sceneItems = new pointerVector(true);
+ sceneItems->add(new utils::intContainer(sceneItemBootOptionsScene));
+ sceneItems->add(new utils::intContainer(sceneItemAudioVideoOptionsScene));
+ if (context::getModchip()->getSupportInfo(true).supportsLcd == true)
+ {
+ sceneItems->add(new utils::intContainer(sceneItemLcdOptionsScene));
+ }
+ if (context::getModchipType() == modchipTypeModxo)
+ {
+ sceneItems->add(new utils::intContainer(sceneItemLedOptionsScene));
+ }
+ sceneItems->add(new utils::intContainer(sceneItemMiscellaneousOptionsScene));
+ sceneContainer* container = new sceneContainer(sceneItem, new menuScene("General Options...", "", sceneItems), "General Options");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemBootOptionsScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new bootOptionsScene(), "Boot Options");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemAudioVideoOptionsScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new audioVideoOptionsScene(), "Audio/Video Options");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemLcdOptionsScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new lcdOptionsScene(), "LCD Options");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemLedOptionsScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new ledOptionsScene(), "LED Options");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemMiscellaneousOptionsScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new miscellaneousOptionsScene(), "Miscellaneous Options");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemCerbiosIniEditorScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new cerbiosIniEditorScene(), "Cerbios INI Editor");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemFormatDrivePrimaryScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new formatDriveScene(0), "Format Primarary Drive");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemFormatDriveSecondaryScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new formatDriveScene(1), "Format Secondary Drive");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemFlashUpdateFlowScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new flashUpdateFlowScene(false), "Update PrometheOS");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemFlashBackupScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new flashBackupScene(false), "Backup PrometheOS");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemFlashUpdateRecoveryFlowScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new flashUpdateFlowScene(true), "Update Recovery");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemFlashBackupRecoveryScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new flashBackupScene(true), "Backup Recovery");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemPrometheOsThemesScene)
+ {
+ pointerVector* sceneItems = new pointerVector(true);
+ sceneItems->add(new utils::intContainer(sceneItemSkinSelectionScene));
+ sceneItems->add(new utils::intContainer(sceneItemSoundPackSelectionScene));
+ sceneContainer* container = new sceneContainer(sceneItem, new menuScene("Select PrometheOS Theme option...", "", sceneItems), "PrometheOS Themes");
+ addScene(container);
+ }
+
+ else if (sceneItem == sceneItemAVSettingsScene)
+ {
+ pointerVector* sceneItems = new pointerVector(true);
+ sceneItems->add(new utils::intContainer(sceneItemVideoSettingsScene));
+ sceneItems->add(new utils::intContainer(sceneItemAudioSettingsScene));
+ if (hdmiDevice::detectDevice() == true)
+ {
+ sceneItems->add(new utils::intContainer(sceneItemHdmiSettingsScene));
+ }
+ sceneContainer* container = new sceneContainer(sceneItem, new menuScene("Select AV Settings option...", "", sceneItems), "AV Settings");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemHdmiSettingsScene)
+ {
+ pointerVector* sceneItems = new pointerVector(true);
+ sceneItems->add(new utils::intContainer(sceneItemHdmiVideoSettingsScene));
+ sceneItems->add(new utils::intContainer(sceneItemHdmiAdvancedScene));
+ sceneItems->add(new utils::intContainer(sceneItemHdmiInterpolationScene));
+ sceneContainer* container = new sceneContainer(sceneItem, new menuScene("Select Cerbios HDMI Settings option...", "", sceneItems), "Cerbios HDMI Settings");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemHdmiVideoSettingsScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new hdmiVideoSettingsScene(), "HDMI Video Settings");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemHdmiAdvancedScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new hdmiAdvancedScene(), "HDMI Advanced");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemHdmiInterpolationScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new hdmiInterpolationScene(), "HDMI Interpolation");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemHddPasswordScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new hddPasswordScene(), "HDD Password VSC");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemLauncherFlowScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new launcherFlowScene(), "Launch XBE");
+ addScene(container);
+ }
+ else if (sceneItem == sceneItemDlcSignerScene)
+ {
+ sceneContainer* container = new sceneContainer(sceneItem, new dlcSignerScene(), "DLC / Update Signer");
+ addScene(container);
+ }
+}
+
+void sceneManager::pushScene(sceneContainer* container)
+{
+ addScene(container);
+}
+
+void sceneManager::popScene(sceneResult result)
+{
+ sceneContainer* popContainer = mScenes->get(mScenes->count() - 1);
+ if (popContainer->onSceneClosingCallback != NULL)
+ {
+ popContainer->onSceneClosingCallback(result, popContainer->context, popContainer->scene);
+ }
+
+ mScenes->remove(mScenes->count() - 1);
+
+ sceneContainer* container = mScenes->get(mScenes->count() - 1);
+ if (container->sceneItem == sceneItemBankManagementScene)
+ {
+ menuScene* menu = (menuScene*)container->scene;
+ char* subTitle = stringUtility::formatString("Free Slots %i", settingsManager::getFreeSlots());
+ menu->setSubTilte(subTitle);
+ free(subTitle);
+ }
+ else if (container->sceneItem == sceneItemDateTimeScene)
+ {
+ bool doRtc = settingsManager::getRtcEnable() == true && xboxConfig::getHasRtcExpansion() == true;
+ free(container->description);
+ container->description = strdup(strdup(doRtc ? "RTC Exapansion" : "Date Time"));
+ }
+
+ context::setCurrentTitle(container->description);
+}
+
+// Private
+
+void sceneManager::addScene(sceneContainer* sceneContainer)
+{
+ mScenes->add(sceneContainer);
+ context::setCurrentTitle(sceneContainer->description);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/sceneManager.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/sceneManager.h
new file mode 100644
index 0000000..2e362f2
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/sceneManager.h
@@ -0,0 +1,103 @@
+#pragma once
+
+#include "scene.h"
+
+#include
+
+enum sceneItemEnum
+{
+ sceneItemGenericScene,
+ sceneItemMainScene,
+ sceneItemSystemScene,
+ sceneItemSettingsScene,
+ sceneItemUtilitiesScene,
+ sceneItemBankManagementScene,
+ sceneItemEepromToolsScene,
+ sceneItemDateTimeScene,
+ sceneItemFlashFlowScene,
+ sceneItemRemoveScene,
+ sceneItemEditFlowScene,
+ sceneItemSystemInfoScene,
+ sceneItemSystemInfoSceneConsole,
+ sceneItemSystemInfoSceneStorage,
+ sceneItemSystemInfoSceneAudio,
+ sceneItemSystemInfoSceneVideo,
+ sceneItemSystemInfoSceneAbout,
+ sceneItemVideoSettingsScene,
+ sceneItemAudioSettingsScene,
+ sceneItemRegionSettingsScene,
+ sceneItemNetworkSettingsScene,
+ sceneItemHddUnlockScene,
+ sceneItemBackupEepromScene,
+ sceneItemRestoreEepromScene,
+ sceneItemFlashToolsScene,
+ sceneItemPrometheOsSettingsScene,
+ sceneItemSkinSelectionScene,
+ sceneItemSoundPackSelectionScene,
+ sceneItemSnakeScene,
+ sceneItemInvadersScene,
+ sceneItemLaunchScene,
+ sceneItemAutoBootScene,
+ sceneItemGeneralOptionsScene,
+ sceneItemBootOptionsScene,
+ sceneItemAudioVideoOptionsScene,
+ sceneItemLcdOptionsScene,
+ sceneItemLedOptionsScene,
+ sceneItemMiscellaneousOptionsScene,
+ sceneItemFlashUpdateFlowScene,
+ sceneItemFlashBackupScene,
+ sceneItemFlashUpdateRecoveryFlowScene,
+ sceneItemFlashBackupRecoveryScene,
+ sceneItemPrometheOsThemesScene,
+ sceneItemAVSettingsScene,
+ sceneItemHdmiSettingsScene,
+ sceneItemHdmiVideoSettingsScene,
+ sceneItemHdmiAdvancedScene,
+ sceneItemHdmiInterpolationScene,
+ sceneItemHddPasswordScene,
+ sceneItemGamesScene,
+ sceneItemCerbiosIniEditorScene,
+ sceneItemFormatDriveOptionsScene,
+ sceneItemFormatDrivePrimaryScene,
+ sceneItemFormatDriveSecondaryScene,
+ sceneItemLauncherFlowScene,
+ sceneItemDlcSignerScene,
+};
+
+typedef void (*SceneOnClosingCallback)(sceneResult result, void* context, scene* scene);
+
+typedef struct sceneContainer
+{
+ sceneItemEnum sceneItem;
+ scene* scene;
+ char* description;
+ void* context;
+ SceneOnClosingCallback onSceneClosingCallback;
+
+ sceneContainer(sceneItemEnum sceneItem, scene* scene, const char* description, void* context = NULL, SceneOnClosingCallback onSceneClosingCallback = NULL)
+ {
+ this->sceneItem = sceneItem;
+ this->scene = scene;
+ this->description = strdup(description);
+ this->context = context;
+ this->onSceneClosingCallback = onSceneClosingCallback;
+ }
+
+ ~sceneContainer()
+ {
+ delete(this->scene);
+ free(this->description);
+ }
+
+} sceneContainer;
+
+class sceneManager
+{
+public:
+ static scene* getScene();
+ static void pushScene(sceneItemEnum sceneItem);
+ static void pushScene(sceneContainer* container);
+ static void popScene(sceneResult result = sceneResultNone);
+private:
+ static void addScene(sceneContainer* sceneContainer);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/skinSelectionScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/skinSelectionScene.cpp
new file mode 100644
index 0000000..879722a
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/skinSelectionScene.cpp
@@ -0,0 +1,124 @@
+#include "skinSelectionScene.h"
+#include "sceneManager.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxConfig.h"
+#include "..\theme.h"
+#include "..\fileSystem.h"
+
+skinSelectionScene::skinSelectionScene()
+{
+ mMenuItems = new pointerVector(false);
+ mMenuItems->add(strdup("Random"));
+ mMenuItems->add(strdup("Default"));
+
+ char* currentSkinName = settingsManager::getSkinName();
+ mSelectedControl = stringUtility::equals(currentSkinName, "*", false) == true ? 0 : 1;
+
+ pointerVector* skins = theme::getSkins();
+ if (skins != NULL)
+ {
+ for (uint32_t i = 0; i < skins->count(); i++)
+ {
+ char* skinName = strdup(skins->get(i));
+ mMenuItems->add(skinName);
+ if (stringUtility::equals(skinName, currentSkinName, true) == true)
+ {
+ mSelectedControl = i + 2;
+ }
+ }
+ }
+ delete(skins);
+
+ free(currentSkinName);
+}
+
+skinSelectionScene::~skinSelectionScene()
+{
+ delete(mMenuItems);
+}
+
+void skinSelectionScene::update()
+{
+ // Exit Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene();
+ return;
+ }
+
+ // Select Actions
+
+ if (inputManager::buttonPressed(ButtonA))
+ {
+ if (mSelectedControl == 0)
+ {
+ theme::loadSkin("*");
+ settingsManager::setSkinName("*");
+ }
+ else if (mSelectedControl == 1)
+ {
+ theme::loadSkin("");
+ settingsManager::setSkinName("");
+ }
+ else
+ {
+ char* skinName = mMenuItems->get(mSelectedControl);
+ theme::loadSkin(skinName);
+ settingsManager::setSkinName(skinName);
+ }
+
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ mSelectedControl = mSelectedControl < (int)(mMenuItems->count() - 1) ? mSelectedControl + 1 : 0;
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : (int)(mMenuItems->count() - 1);
+ }
+}
+
+void skinSelectionScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Select Skin option...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ int32_t maxItems = 7;
+
+ int32_t start = 0;
+ if ((int32_t)mMenuItems->count() >= maxItems)
+ {
+ start = min(max(mSelectedControl - (maxItems / 2), 0), (int32_t)mMenuItems->count() - maxItems);
+ }
+
+ int32_t itemCount = min(start + maxItems, (int32_t)mMenuItems->count()) - start;
+
+ uint32_t yPos = (context::getBufferHeight() - ((itemCount * 40) - 10)) / 2;
+ yPos += theme::getCenterOffset();
+
+ for (int32_t i = 0; i < itemCount; i++)
+ {
+ uint32_t index = start + i;
+ char* skinName = mMenuItems->get(index);
+ component::button(mSelectedControl == index, false, skinName, 193, yPos, 322, 30);
+ yPos += 40;
+ }
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Select", theme::getFooterTextColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/skinSelectionScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/skinSelectionScene.h
new file mode 100644
index 0000000..1e382eb
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/skinSelectionScene.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "scene.h"
+#include "sceneManager.h"
+
+#include "../pointerMap.h"
+
+class skinSelectionScene : public scene
+{
+public:
+ skinSelectionScene();
+ ~skinSelectionScene();
+ void update();
+ void render();
+private:
+ int mSelectedControl;
+ pointerVector* mMenuItems;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/snakeScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/snakeScene.cpp
new file mode 100644
index 0000000..8926864
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/snakeScene.cpp
@@ -0,0 +1,225 @@
+#include "snakeScene.h"
+#include "sceneManager.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxConfig.h"
+#include "..\theme.h"
+
+snakeScene::snakeScene()
+{
+ mCounter = 0;
+ restart();
+}
+
+void snakeScene::update()
+{
+ // Exit Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene();
+ return;
+ }
+
+ //// Select Actions
+
+ if (mIsGameOver == true && inputManager::buttonPressed(ButtonA))
+ {
+ restart();
+ }
+
+ if (mIsGameOver == true)
+ {
+ return;
+ }
+
+ // Left Actions
+
+ if (inputManager::buttonPressed(ButtonDpadLeft) && mDirection != snakeDirectionRight)
+ {
+ mInputDirection = snakeDirectionLeft;
+ }
+
+ // Right Actions
+
+ if (inputManager::buttonPressed(ButtonDpadRight) && mDirection != snakeDirectionLeft)
+ {
+ mInputDirection = snakeDirectionRight;
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown) && mDirection != snakeDirectionUp)
+ {
+ mInputDirection = snakeDirectionDown;
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp) && mDirection != snakeDirectionDown)
+ {
+ mInputDirection = snakeDirectionUp;
+ }
+
+ mCounter++;
+ if (mCounter < 5)
+ {
+ return;
+ }
+ mCounter = 0;
+
+ mDirection = mInputDirection;
+
+ int prevX = mSnakeTailX[0];
+ int prevY = mSnakeTailY[0];
+ int prev2X, prev2Y;
+ mSnakeTailX[0] = mX;
+ mSnakeTailY[0] = mY;
+ for (int i = 1; i < mSnakeTailLen; i++) {
+ prev2X = mSnakeTailX[i];
+ prev2Y = mSnakeTailY[i];
+ mSnakeTailX[i] = prevX;
+ mSnakeTailY[i] = prevY;
+ prevX = prev2X;
+ prevY = prev2Y;
+ }
+
+ switch (mDirection)
+ {
+ case snakeDirectionLeft:
+ mX--;
+ break;
+ case snakeDirectionRight:
+ mX++;
+ break;
+ case snakeDirectionUp:
+ mY--;
+ break;
+ case snakeDirectionDown:
+ mY++;
+ break;
+ }
+
+ if (mX >= mWidth || mX < 0 || mY >= mHeight || mY < 0)
+ {
+ mIsGameOver = true;
+ }
+
+ for (int i = 0; i < mSnakeTailLen; i++)
+ {
+ if (mSnakeTailX[i] == mX && mSnakeTailY[i] == mY)
+ {
+ mIsGameOver = true;
+ }
+ }
+
+ if (mIsGameOver == true && mPlayerScore > settingsManager::getSnakeHiScore())
+ {
+ settingsManager::setSnakeHiScore(mPlayerScore);
+ }
+
+ if (mX == mFruitCordX && mY == mFruitCordY)
+ {
+ mPlayerScore += 10;
+ mFruitCordX = rand() % mWidth;
+ mFruitCordY = rand() % mHeight;
+ if (mSnakeTailLen < 100)
+ {
+ mSnakeTailLen++;
+ }
+ }
+}
+
+void snakeScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Snake", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ int xPos = (context::getBufferWidth() - ((mWidth + 2) * 10)) / 2;
+ int yPos = (context::getBufferHeight() - ((mHeight + 2) * 10)) / 2;
+ yPos += theme::getCenterOffset();
+
+ for (int i = 0; i < mWidth + 2; i++)
+ {
+ drawing::drawNinePatch("panel-fill", theme::getSnakeWallColor(), xPos + (i * 10), yPos, 10, 10);
+ drawing::drawNinePatch("panel-fill", theme::getSnakeWallColor(), xPos + (i * 10), yPos + (mHeight + 1) * 10, 10, 10);
+ }
+
+ for (int i = 0; i < mHeight; i++)
+ {
+ drawing::drawNinePatch("panel-fill", theme::getSnakeWallColor(), xPos, yPos + ((i + 1) * 10), 10, 10);
+ drawing::drawNinePatch("panel-fill", theme::getSnakeWallColor(), xPos + ((mWidth + 1) * 10), yPos + ((i + 1) * 10), 10, 10);
+ }
+
+ for (int i = 0; i < mHeight; i++) {
+ for (int j = 0; j <= mWidth; j++) {
+
+ int screenPosX = xPos + ((j + 1) * 10);
+ int screenPosY = yPos + ((i + 1) * 10);
+
+ if (i == mY && j == mX)
+ {
+ drawing::drawNinePatch("panel-fill", theme::getSnakeHeadColor(), screenPosX, screenPosY, 10, 10);
+ }
+ else if (i == mFruitCordY && j == mFruitCordX)
+ {
+ drawing::drawNinePatch("panel-fill", theme::getSnakeFoodColor(), screenPosX, screenPosY, 10, 10);
+ }
+ else
+ {
+ for (int k = 0; k < mSnakeTailLen; k++)
+ {
+ if (mSnakeTailX[k] == j && mSnakeTailY[k] == i)
+ {
+ drawing::drawNinePatch("panel-fill", theme::getSnakeTailColor(), screenPosX, screenPosY, 10, 10);
+ }
+ }
+ }
+ }
+ }
+
+#ifndef TOOLS
+ char* score = stringUtility::formatString("Hi-Score: %i, Score: %i", settingsManager::getSnakeHiScore(), mPlayerScore);
+#else
+ char* score = stringUtility::formatString("Score: %i", mPlayerScore);
+#endif
+
+ if (mIsGameOver == true)
+ {
+ int yPosGameOver = (context::getBufferHeight() - 20) / 2;
+ yPosGameOver += theme::getCenterOffset();
+ drawing::drawBitmapStringAligned(context::getBitmapFontLarge(), "GAME OVER", theme::getTextColor(), horizAlignmentCenter, 40, yPosGameOver, 640);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Restart", theme::getFooterTextColor(), 40, theme::getFooterY());
+ }
+
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), score, theme::getFooterTextColor(), horizAlignmentCenter, 40, theme::getFooterY(), 640);
+ free(score);
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
+
+void snakeScene::restart()
+{
+ mWidth = 58;
+ mHeight = 26;
+ mSnakeTailLen = 0;
+ mIsGameOver = false;
+ mInputDirection = snakeDirectionStop;
+ mDirection = snakeDirectionStop;
+ mX = mWidth / 2;
+ mY = mHeight / 2;
+ mFruitCordX = rand() % mWidth;
+ mFruitCordY = rand() % mHeight;
+ mPlayerScore = 0;
+ for (int i = 0; i < 100; i++)
+ {
+ mSnakeTailX[i] = -1;
+ mSnakeTailY[i] = -1;
+ }
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/snakeScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/snakeScene.h
new file mode 100644
index 0000000..ec8d07f
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/snakeScene.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#include "scene.h"
+#include "sceneManager.h"
+
+#include "../pointerMap.h"
+
+class snakeScene : public scene
+{
+public:
+ enum snakeDirectionEnum
+ {
+ snakeDirectionStop = 0,
+ snakeDirectionLeft = 1,
+ snakeDirectionRight = 2,
+ snakeDirectionUp = 3,
+ snakeDirectionDown = 4
+ };
+ snakeScene();
+ void update();
+ void render();
+private:
+ void restart();
+private:
+ int32_t mWidth;
+ int32_t mHeight;
+ int32_t mX;
+ int32_t mY;
+ int32_t mFruitCordX;
+ int32_t mFruitCordY;
+ uint32_t mPlayerScore;
+ int32_t mSnakeTailX[100];
+ int32_t mSnakeTailY[100];
+ int32_t mSnakeTailLen;
+ snakeDirectionEnum mInputDirection;
+ snakeDirectionEnum mDirection;
+ bool mIsGameOver;
+ int32_t mCounter;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/soundPackSelectionScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/soundPackSelectionScene.cpp
new file mode 100644
index 0000000..0275291
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/soundPackSelectionScene.cpp
@@ -0,0 +1,124 @@
+#include "soundPackSelectionScene.h"
+#include "sceneManager.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxConfig.h"
+#include "..\theme.h"
+#include "..\fileSystem.h"
+
+soundPackSelectionScene::soundPackSelectionScene()
+{
+ mMenuItems = new pointerVector(false);
+ mMenuItems->add(strdup("Random"));
+ mMenuItems->add(strdup("None"));
+
+ char* currentSoundPackName = settingsManager::getSoundPackName();
+ mSelectedControl = stringUtility::equals(currentSoundPackName, "*", false) == true ? 0 : 1;
+
+ pointerVector* soundPacks = theme::getSoundPacks();
+ if (soundPacks != NULL)
+ {
+ for (uint32_t i = 0; i < soundPacks->count(); i++)
+ {
+ char* soundPackName = strdup(soundPacks->get(i));
+ mMenuItems->add(soundPackName);
+ if (stringUtility::equals(soundPackName, currentSoundPackName, true) == true)
+ {
+ mSelectedControl = i + 2;
+ }
+ }
+ }
+ delete(soundPacks);
+
+ free(currentSoundPackName);
+}
+
+soundPackSelectionScene::~soundPackSelectionScene()
+{
+ delete(mMenuItems);
+}
+
+void soundPackSelectionScene::update()
+{
+ // Exit Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene();
+ return;
+ }
+
+ // Select Actions
+
+ if (inputManager::buttonPressed(ButtonA))
+ {
+ if (mSelectedControl == 0)
+ {
+ theme::loadSoundPack("*");
+ settingsManager::setSoundPackName("*");
+ }
+ else if (mSelectedControl == 1)
+ {
+ theme::loadSoundPack("");
+ settingsManager::setSoundPackName("");
+ }
+ else
+ {
+ char* soundPackName = mMenuItems->get(mSelectedControl);
+ theme::loadSoundPack(soundPackName);
+ settingsManager::setSoundPackName(soundPackName);
+ }
+
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ mSelectedControl = mSelectedControl < (int)(mMenuItems->count() - 1) ? mSelectedControl + 1 : 0;
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : (int)(mMenuItems->count() - 1);
+ }
+}
+
+void soundPackSelectionScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Select Sound Pack option...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ int32_t maxItems = 7;
+
+ int32_t start = 0;
+ if ((int32_t)mMenuItems->count() >= maxItems)
+ {
+ start = min(max(mSelectedControl - (maxItems / 2), 0), (int32_t)mMenuItems->count() - maxItems);
+ }
+
+ int32_t itemCount = min(start + maxItems, (int32_t)mMenuItems->count()) - start;
+
+ uint32_t yPos = (context::getBufferHeight() - ((itemCount * 40) - 10)) / 2;
+ yPos += theme::getCenterOffset();
+
+ for (int32_t i = 0; i < itemCount; i++)
+ {
+ uint32_t index = start + i;
+ char* soundPackName = mMenuItems->get(index);
+ component::button(mSelectedControl == index, false, soundPackName, 193, yPos, 322, 30);
+ yPos += 40;
+ }
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Select", theme::getFooterTextColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/soundPackSelectionScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/soundPackSelectionScene.h
new file mode 100644
index 0000000..e265bb0
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/soundPackSelectionScene.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "scene.h"
+#include "sceneManager.h"
+
+#include "../pointerMap.h"
+
+class soundPackSelectionScene : public scene
+{
+public:
+ soundPackSelectionScene();
+ ~soundPackSelectionScene();
+ void update();
+ void render();
+private:
+ int mSelectedControl;
+ pointerVector* mMenuItems;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/systemInfoScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/systemInfoScene.cpp
new file mode 100644
index 0000000..1d15a93
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/systemInfoScene.cpp
@@ -0,0 +1,247 @@
+#include "systemInfoScene.h"
+#include "sceneManager.h"
+#include "removeScene.h"
+#include "flashFlowScene.h"
+#include "editFlowScene.h"
+#include "audioSettingsScene.h"
+#include "videoSettingsScene.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\ssfn.h"
+#include "..\inputManager.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\xboxConfig.h"
+#include "..\theme.h"
+
+systemInfoScene::systemInfoScene(systemInfoCategoryEnum systemInfoCategory)
+{
+ mSelectedControl = 0;
+ mInfoItems = new pointerVector(false);
+ mSystemInfoCategory = systemInfoCategory;
+
+ if (mSystemInfoCategory == systemInfoCategoryConsole)
+ {
+ char* cpuSpeed = stringUtility::formatString("CPU: %4.2fMHz", xboxConfig::getCPUFreq());
+ mInfoItems->add(cpuSpeed);
+
+ char* xboxVersionString = xboxConfig::getXboxVersionString();
+ char* xboxVersion = stringUtility::formatString("Xbox Rev: %s", xboxVersionString);
+ mInfoItems->add(xboxVersion);
+ free(xboxVersionString);
+
+ char* totalMemory = stringUtility::formatString("RAM: %uMB", utils::getTotalPhysicalMemory() >> 20);
+ mInfoItems->add(totalMemory);
+
+ char* serialString = xboxConfig::getSerialString();
+ char* serial = stringUtility::formatString("Serial: %s", serialString);
+ mInfoItems->add(serial);
+ free(serialString);
+
+ char* macString = xboxConfig::getMacString();
+ char* mac = stringUtility::formatString("Mac: %s", macString);
+ mInfoItems->add(mac);
+ free(macString);
+
+ char* rtcExpansion = stringUtility::formatString("RTC Expansion: %s", xboxConfig::getHasRtcExpansion() ? "Detected" : "Not Detected");
+ mInfoItems->add(rtcExpansion);
+ }
+ else if (mSystemInfoCategory == systemInfoCategoryStorage)
+ {
+ const char* model = HalDiskModelNumber->Buffer ? HalDiskModelNumber->Buffer : "";
+ char* diskModelNumberString = stringUtility::trim(model, ' ');
+ char* diskModelNumber = stringUtility::formatString("HDD Model: %s", diskModelNumberString);
+ mInfoItems->add(diskModelNumber);
+ free(diskModelNumberString);
+
+ const char* serial = HalDiskSerialNumber->Buffer ? HalDiskSerialNumber->Buffer : "";
+ char* diskSerialNumberString = stringUtility::trim(serial, ' ');
+ char* diskSerialNumber = stringUtility::formatString("HDD Serial: %s", diskSerialNumberString);
+ mInfoItems->add(diskSerialNumber);
+ free(diskSerialNumberString);
+
+ // hdd model dvd model
+ }
+ else if (mSystemInfoCategory == systemInfoCategoryAudio)
+ {
+ char* audioModeString = xboxConfig::getAudioModeString();
+ char* audioMode = stringUtility::formatString("Audio Mode: %s", audioModeString);
+ mInfoItems->add(audioMode);
+ free(audioModeString);
+
+ char* ac3 = stringUtility::formatString("Dolby digital (AC3): %s", xboxConfig::getAudioAC3() ? "Enabled" : "Disabled");
+ mInfoItems->add(ac3);
+
+ char* dts = stringUtility::formatString("DTS: %s", xboxConfig::getAudioDTS() ? "Enabled" : "Disabled");
+ mInfoItems->add(dts);
+ }
+ else if (mSystemInfoCategory == systemInfoCategoryVideo)
+ {
+ char* videoStandardString = xboxConfig::getVideoStandardString();
+ char* videoStandard = stringUtility::formatString("Video Standard: %s", videoStandardString);
+ mInfoItems->add(videoStandard);
+ free(videoStandardString);
+
+ char* gameRegionString = xboxConfig::getGameRegionString();
+ char* gameRegion = stringUtility::formatString("Game Region: %s", gameRegionString);
+ mInfoItems->add(gameRegion);
+ free(gameRegionString);
+
+ char* dvdRegionString = xboxConfig::getDvdRegionString();
+ char* dvdRegion = stringUtility::formatString("DVD Region: %s", dvdRegionString);
+ mInfoItems->add(dvdRegion);
+ free(dvdRegionString);
+
+ char* avPackString = xboxConfig::getAvPackString();
+ char* avPack = stringUtility::formatString("AV Pack: %s", avPackString);
+ free(avPackString);
+
+ char* encoderString = xboxConfig::getEncoderString();
+ char* encoder = stringUtility::formatString("Encoder: %s", encoderString);
+ mInfoItems->add(encoder);
+ free(encoderString);
+
+ char* hdModString = xboxConfig::getHdModString();
+ char* hdMod = stringUtility::formatString("HD Mod: %s", hdModString);
+ mInfoItems->add(hdMod);
+ free(hdModString);
+ }
+ else if (mSystemInfoCategory == systemInfoCategoryAbout)
+ {
+ char *versionSemver = settingsManager::getVersionSting(settingsManager::getVersion());
+ char *version = stringUtility::formatString("PrometheOS: V%s", versionSemver);
+ mInfoItems->add(version);
+ free(versionSemver);
+
+ char *by = strdup("Team Cerbios + Team Resurgent");
+ mInfoItems->add(by);
+
+ char *coded = strdup("Coded By: EqUiNoX");
+ mInfoItems->add(coded);
+
+ char* skinAutthor = theme::getSkinAuthor();
+ char *author = stringUtility::formatString("Skin Author: %s", skinAutthor);
+ mInfoItems->add(author);
+ free(skinAutthor);
+
+ if (drawing::imageExists("installer-logo") == false)
+ {
+ utils::dataContainer* installerLogoData = settingsManager::getInstallerLogoData();
+ if (installerLogoData->data[0] == 'I' && installerLogoData->data[1] == 'M')
+ {
+ int width = (uint8_t)installerLogoData->data[2];
+ int height = (uint8_t)installerLogoData->data[3];
+ drawing::addImage("installer-logo", (uint8_t*)(installerLogoData->data + 4), D3DFMT_A8B8G8R8, width, height);
+ }
+ delete(installerLogoData);
+ }
+ }
+}
+
+systemInfoScene::~systemInfoScene()
+{
+ delete(mInfoItems);
+}
+
+void systemInfoScene::update()
+{
+ // Exit Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene();
+ return;
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ if (mInfoItems != NULL)
+ {
+ mSelectedControl = mSelectedControl < (int)(mInfoItems->count() - 1) ? mSelectedControl + 1 : 0;
+ }
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ if (mInfoItems != NULL)
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : (int)(mInfoItems->count() - 1);
+ }
+ }
+}
+
+void systemInfoScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+
+ if (mSystemInfoCategory == systemInfoCategoryConsole)
+ {
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "System Info: Console", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+ }
+ else if (mSystemInfoCategory == systemInfoCategoryStorage)
+ {
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "System Info: Storage", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+ }
+ else if (mSystemInfoCategory == systemInfoCategoryAudio)
+ {
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "System Info: Audio", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+ }
+ else if (mSystemInfoCategory == systemInfoCategoryVideo)
+ {
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "System Info: Video", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+ }
+ else if (mSystemInfoCategory == systemInfoCategoryAbout)
+ {
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "System Info: About", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+ }
+
+ uint32_t yPos = 96;
+
+ int32_t maxItems = 7;
+
+ int32_t start = 0;
+ if ((int32_t)mInfoItems->count() >= maxItems)
+ {
+ start = min(max(mSelectedControl - (maxItems / 2), 0), (int32_t)mInfoItems->count() - maxItems);
+ }
+
+ int32_t itemCount = min(start + maxItems, (int32_t)mInfoItems->count()) - start;
+ if (itemCount > 0)
+ {
+ uint32_t yPos = (context::getBufferHeight() - ((itemCount * 40) - 10)) / 2;
+ yPos += theme::getCenterOffset();
+
+ if (mSystemInfoCategory == systemInfoCategoryAbout && drawing::imageExists("installer-logo") == true)
+ {
+ yPos += 32;
+ drawing::drawImage("installer-logo", theme::getInstallerTint(), 271, yPos - 64, 178, 46);
+ }
+
+ for (int32_t i = 0; i < itemCount; i++)
+ {
+ uint32_t index = start + i;
+ if (index >= mInfoItems->count())
+ {
+ continue;
+ }
+ char* infoItem = mInfoItems->get(index);
+ component::textBox(infoItem, mSelectedControl == index, false, horizAlignmentCenter, 40, yPos, 640, 30);
+ yPos += 40;
+ }
+ }
+ else
+ {
+ int yPos = ((context::getBufferHeight() - 44) / 2);
+ yPos += theme::getCenterOffset();
+
+ component::textBox("No items", false, false, horizAlignmentCenter, 193, 225, 322, 44);
+ }
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/systemInfoScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/systemInfoScene.h
new file mode 100644
index 0000000..36dcdaf
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/systemInfoScene.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "scene.h"
+#include "..\pointerVector.h"
+
+enum systemInfoCategoryEnum
+{
+ systemInfoCategoryConsole = 0,
+ systemInfoCategoryStorage = 1,
+ systemInfoCategoryAudio = 2,
+ systemInfoCategoryVideo = 3,
+ systemInfoCategoryAbout = 4
+};
+
+class systemInfoScene : public scene
+{
+public:
+ systemInfoScene(systemInfoCategoryEnum systemInfoCategory);
+ ~systemInfoScene();
+ void update();
+ void render();
+private:
+ int mSelectedControl;
+ systemInfoCategoryEnum mSystemInfoCategory;
+ pointerVector* mInfoItems;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/videoSettingsScene.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/videoSettingsScene.cpp
new file mode 100644
index 0000000..53fdae6
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/videoSettingsScene.cpp
@@ -0,0 +1,149 @@
+#include "videosettingsscene.h"
+#include "sceneManager.h"
+#include "audioSettingsScene.h"
+
+#include "..\context.h"
+#include "..\drawing.h"
+#include "..\component.h"
+#include "..\inputManager.h"
+#include "..\ssfn.h"
+#include "..\xboxConfig.h"
+#include "..\settingsManager.h"
+#include "..\hdmiDevice.h"
+#include "..\stringUtility.h"
+#include "..\theme.h"
+
+videoSettingsScene::videoSettingsScene()
+{
+ mSelectedControl = 0;
+ if (xboxConfig::getVideo720p() == true)
+ {
+ mSelectedControl = 1;
+ }
+ if (xboxConfig::getVideo1080i() == true)
+ {
+ mSelectedControl = 2;
+ }
+}
+
+void videoSettingsScene::update()
+{
+ // Back Action
+
+ if (inputManager::buttonPressed(ButtonB))
+ {
+ sceneManager::popScene();
+ return;
+ }
+
+ // Select Actions
+
+ if (inputManager::buttonPressed(ButtonA))
+ {
+ if (mSelectedControl == 0)
+ {
+ xboxConfig::setVideo480p(!xboxConfig::getVideo480p());
+ }
+ else if (mSelectedControl == 1)
+ {
+ xboxConfig::setVideo720p(!xboxConfig::getVideo720p());
+ }
+ else if (mSelectedControl == 2)
+ {
+ xboxConfig::setVideo1080i(!xboxConfig::getVideo1080i());
+ }
+ else if (mSelectedControl == 3)
+ {
+ xboxConfig::setVideoAspectRatio(0);
+ }
+ else if (mSelectedControl == 4)
+ {
+ xboxConfig::setVideoAspectRatio(EEPROM_VIDEO_FLAGS_LETTERBOX);
+ }
+ else if (mSelectedControl == 5)
+ {
+ xboxConfig::setVideoAspectRatio(EEPROM_VIDEO_FLAGS_WIDESCREEN);
+ }
+ }
+
+ // Left Actions
+
+ if (inputManager::buttonPressed(ButtonDpadLeft))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 2)
+ {
+ mSelectedControl = mSelectedControl > 0 ? mSelectedControl - 1 : 2;
+ }
+ else if (mSelectedControl >= 3 && mSelectedControl <= 5)
+ {
+ mSelectedControl = mSelectedControl > 3 ? mSelectedControl - 1 : 5;
+ }
+ }
+
+ // Right Actions
+
+ if (inputManager::buttonPressed(ButtonDpadRight))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 2)
+ {
+ mSelectedControl = mSelectedControl < 2 ? mSelectedControl + 1 : 0;
+ }
+ else if (mSelectedControl >= 3 && mSelectedControl <= 5)
+ {
+ mSelectedControl = mSelectedControl < 5 ? mSelectedControl + 1 : 3;
+ }
+ }
+
+ // Down Actions
+
+ if (inputManager::buttonPressed(ButtonDpadDown))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 2)
+ {
+ mSelectedControl = 3;
+ }
+ else if (mSelectedControl >= 3 && mSelectedControl <= 5)
+ {
+ mSelectedControl = 0;
+ }
+ }
+
+ // Up Actions
+
+ if (inputManager::buttonPressed(ButtonDpadUp))
+ {
+ if (mSelectedControl >= 0 && mSelectedControl <= 2)
+ {
+ mSelectedControl = 3;
+ }
+ else if (mSelectedControl >= 3 && mSelectedControl <= 5)
+ {
+ mSelectedControl = 0;
+ }
+ }
+}
+
+void videoSettingsScene::render()
+{
+ component::panel(theme::getPanelFillColor(), theme::getPanelStrokeColor(), 16, 16, 688, 448);
+ drawing::drawBitmapStringAligned(context::getBitmapFontMedium(), "Video settings...", theme::getHeaderTextColor(), theme::getHeaderAlign(), 40, theme::getHeaderY(), 640);
+
+ int xPos = 117;
+ int yPos = (context::getBufferHeight() - (30 + 40 + 30 + 30)) / 2;
+ yPos += theme::getCenterOffset();
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "Video Modes", theme::getTextColor(), xPos, yPos);
+ yPos += 30;
+ component::button(mSelectedControl == 0, xboxConfig::getVideo480p() == true, "480p", xPos, yPos, 160, 30);
+ component::button(mSelectedControl == 1, xboxConfig::getVideo720p() == true, "720p", xPos + 164, yPos, 160, 30);
+ component::button(mSelectedControl == 2, xboxConfig::getVideo1080i() == true, "1080i", xPos + (164 * 2), yPos, 160, 30);
+ yPos += 40;
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "Aspect Ratio", theme::getTextColor(), xPos, yPos);
+ yPos += 30;
+ component::button(mSelectedControl == 3, xboxConfig::getVideoAspectRatioNormal() == true, "Normal", xPos, yPos, 160, 30);
+ component::button(mSelectedControl == 4, xboxConfig::getVideoAspectRatioLetterbox() == true, "Letterbox", xPos + 164, yPos, 160, 30);
+ component::button(mSelectedControl == 5, xboxConfig::getVideoAspectRatioWidescreen() == true, "Widescreen", xPos + (164 * 2), yPos, 160, 30);
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), "\xC2\xA1 Select", theme::getFooterTextColor(), 40, theme::getFooterY());
+ drawing::drawBitmapStringAligned(context::getBitmapFontSmall(), "\xC2\xA2 Back", theme::getFooterTextColor(), horizAlignmentRight, 40, theme::getFooterY(), 640);
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/videoSettingsScene.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/videoSettingsScene.h
new file mode 100644
index 0000000..dcb9b7e
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Scenes/videoSettingsScene.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "scene.h"
+
+class videoSettingsScene : public scene
+{
+public:
+ videoSettingsScene();
+ void update();
+ void render();
+private:
+ int mSelectedControl;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/countdown.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/countdown.cpp
new file mode 100644
index 0000000..462780a
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/countdown.cpp
@@ -0,0 +1,89 @@
+#include "countdown.h"
+
+#include "..\xboxInternals.h"
+#include "..\stringUtility.h"
+#include "..\fileSystem.h"
+#include "..\utils.h"
+#include "..\settingsManager.h"
+#include "..\timeUtility.h"
+
+namespace
+{
+ HANDLE mThread;
+ countdown::countdownData mData;
+}
+
+bool countdown::startThread(uint32_t milliseconds)
+{
+ memset(&mData, 0, sizeof(countdownData));
+ mData.milliseconds = milliseconds;
+ mData.startTime = timeUtility::getMillisecondsNow();
+
+ InitializeCriticalSection(&mData.mutex);
+
+ mThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)process, (void*)&mData, 0, NULL);
+ if (mThread == NULL) {
+ return false;
+ }
+ SetThreadPriority(mThread, THREAD_PRIORITY_HIGHEST);
+ return true;
+}
+
+bool countdown::completed()
+{
+ DWORD exitCode;
+ if (GetExitCodeThread(mThread, &exitCode))
+ {
+ if (exitCode != STILL_ACTIVE)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+uint64_t countdown::getTimeRemaining()
+{
+ uint64_t result = 0;
+ EnterCriticalSection(&mData.mutex);
+ uint64_t elapsed = mData.elapsed;
+ if (elapsed < mData.milliseconds)
+ {
+ result = mData.milliseconds - elapsed;
+ }
+ LeaveCriticalSection(&mData.mutex);
+ return result;
+}
+
+void countdown::closeThread()
+{
+ EnterCriticalSection(&mData.mutex);
+ mData.milliseconds = 0;
+ LeaveCriticalSection(&mData.mutex);
+
+ CloseHandle(mThread);
+ DeleteCriticalSection(&mData.mutex);
+}
+
+uint64_t WINAPI countdown::process(void* param)
+{
+ countdownData* data = (countdownData*)param;
+
+ EnterCriticalSection(&data->mutex);
+ uint64_t startTime = data->startTime;
+ uint64_t milliseconds = data->milliseconds;
+ LeaveCriticalSection(&data->mutex);
+
+ uint64_t elapsed = 0;
+ while (elapsed < milliseconds)
+ {
+ uint64_t timeNow = timeUtility::getMillisecondsNow();
+ elapsed = (timeNow - startTime);
+ EnterCriticalSection(&data->mutex);
+ data->elapsed = elapsed;
+ LeaveCriticalSection(&data->mutex);
+ Sleep(100);
+ }
+
+ return 0;
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/countdown.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/countdown.h
new file mode 100644
index 0000000..da67e63
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/countdown.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "..\xboxInternals.h"
+
+class countdown
+{
+public:
+
+ typedef struct countdownData {
+ uint32_t milliseconds;
+ uint64_t startTime;
+ uint64_t elapsed;
+ CRITICAL_SECTION mutex;
+ } countdownData;
+
+ static bool startThread(uint32_t milliseconds);
+ static bool completed();
+ static uint64_t getTimeRemaining();
+ static void closeThread();
+
+private:
+
+ static uint64_t WINAPI process(void* param);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/driveMounter.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/driveMounter.cpp
new file mode 100644
index 0000000..9e77cf7
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/driveMounter.cpp
@@ -0,0 +1,63 @@
+#include "driveMounter.h"
+
+#include "..\xboxInternals.h"
+#include "..\stringUtility.h"
+#include "..\driveManager.h"
+#include "..\XKUtils\XKEEPROM.h"
+#include "..\XKUtils\XKHDD.h"
+
+namespace
+{
+ HANDLE mThread;
+ driveMounter::driveMounterData mData;
+}
+
+bool driveMounter::startThread(bool onlyMountE)
+{
+ memset(&mData, 0, sizeof(driveMounterData));
+ mData.onlyMountE = onlyMountE;
+
+ InitializeCriticalSection(&mData.mutex);
+
+ mThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)process, (void*)&mData, 0, NULL);
+ if (mThread == NULL) {
+ return false;
+ }
+ SetThreadPriority(mThread, THREAD_PRIORITY_HIGHEST);
+ return true;
+}
+
+bool driveMounter::completed()
+{
+ DWORD exitCode;
+ if (GetExitCodeThread(mThread, &exitCode))
+ {
+ if (exitCode != STILL_ACTIVE)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void driveMounter::closeThread()
+{
+ CloseHandle(mThread);
+ DeleteCriticalSection(&mData.mutex);
+}
+
+uint64_t WINAPI driveMounter::process(void* param)
+{
+ driveMounterData* data = (driveMounterData*)param;
+
+ if (data->onlyMountE == true)
+ {
+ driveManager::mountDrive("HDD0-E");
+ }
+ else
+ {
+ driveManager::mountAllDrives();
+ }
+
+ return 0;
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/driveMounter.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/driveMounter.h
new file mode 100644
index 0000000..99cdf05
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/driveMounter.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "..\xboxInternals.h"
+
+class driveMounter
+{
+public:
+
+ typedef struct driveMounterData {
+ bool onlyMountE;
+ CRITICAL_SECTION mutex;
+ } driveMounterData;
+
+ static bool startThread(bool onlyMountE);
+ static bool completed();
+ static void closeThread();
+
+private:
+
+ static uint64_t WINAPI process(void* param);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/flashBackup.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/flashBackup.cpp
new file mode 100644
index 0000000..8ab4122
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/flashBackup.cpp
@@ -0,0 +1,168 @@
+#include "flashBackup.h"
+
+#include "..\xboxInternals.h"
+#include "..\context.h"
+#include "..\stringUtility.h"
+#include "..\fileSystem.h"
+#include "..\utils.h"
+
+namespace
+{
+ HANDLE mThread;
+ bool mRecovery;
+ flashBackup::flashBackupData mData;
+}
+
+bool flashBackup::startThread(bool recovery)
+{
+ mRecovery = recovery;
+ memset(&mData, 0, sizeof(flashBackupData));
+ mData.currentStep = 0;
+ mData.totalSteps = context::getModchip()->getFlashBankCount(mRecovery);
+
+ InitializeCriticalSection(&mData.mutex);
+
+ mThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)process, (void*)&mData, 0, NULL);
+ if (mThread == NULL) {
+ return false;
+ }
+ SetThreadPriority(mThread, THREAD_PRIORITY_NORMAL);
+ return true;
+}
+
+bool flashBackup::completed()
+{
+ DWORD exitCode;
+ if (GetExitCodeThread(mThread, &exitCode))
+ {
+ if (exitCode != STILL_ACTIVE)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+flashBackup::flashBackupResponse flashBackup::getResponse()
+{
+ flashBackupResponse response;
+ EnterCriticalSection(&mData.mutex);
+ response = mData.response;
+ LeaveCriticalSection(&mData.mutex);
+ return response;
+}
+
+void flashBackup::getProgress(uint32_t& currentStep, uint32_t& totalSteps)
+{
+ EnterCriticalSection(&mData.mutex);
+ currentStep = mData.currentStep;
+ totalSteps = mData.totalSteps;
+ LeaveCriticalSection(&mData.mutex);
+}
+
+void flashBackup::closeThread()
+{
+ CloseHandle(mThread);
+ DeleteCriticalSection(&mData.mutex);
+}
+
+uint64_t WINAPI flashBackup::process(void* param)
+{
+ flashBackupData* data = (flashBackupData*)param;
+ setResponse(data, flashBackupProcessing);
+
+ if (fileSystem::directoryCreate("HDD0-E:\\PrometheOS") == false || fileSystem::directoryCreate("HDD0-E:\\PrometheOS\\Backup") == false)
+ {
+ setResponse(data, flashBackupFailedToCreateDirectory);
+ return 0;
+ }
+
+ char* filePath = NULL;
+ if (mRecovery == true)
+ {
+ filePath = fileSystem::combinePath("HDD0-E:\\PrometheOS\\Backup", "Recovery.bin");
+ }
+ else if (context::getModchipType() == modchipTypeXenium)
+ {
+ filePath = fileSystem::combinePath("HDD0-E:\\PrometheOS\\Backup", "PrometheOS-Xenium.bin");
+ }
+ else if (context::getModchipType() == modchipTypeXecuter)
+ {
+ filePath = fileSystem::combinePath("HDD0-E:\\PrometheOS\\Backup", "PrometheOS-Xecuter.bin");
+ }
+ else if (context::getModchipType() == modchipTypeAladdin1mb)
+ {
+ filePath = fileSystem::combinePath("HDD0-E:\\PrometheOS\\Backup", "PrometheOS-Aladdin1mb.bin");
+ }
+ else if (context::getModchipType() == modchipTypeAladdin2mb)
+ {
+ filePath = fileSystem::combinePath("HDD0-E:\\PrometheOS\\Backup", "PrometheOS-Aladdin2mb.bin");
+ }
+ else if (context::getModchipType() == modchipTypeXchanger)
+ {
+ filePath = fileSystem::combinePath("HDD0-E:\\PrometheOS\\Backup", "PrometheOS-Xchanger.bin");
+ }
+ else if (context::getModchipType() == modchipTypeModxo)
+ {
+ filePath = fileSystem::combinePath("HDD0-E:\\PrometheOS\\Backup", "PrometheOS-Modxo.bin");
+ }
+ else
+ {
+ filePath = fileSystem::combinePath("HDD0-E:\\PrometheOS\\Backup", "PrometheOS.bin");
+ }
+
+ uint32_t fileHandle;
+ if (fileSystem::fileOpen(filePath, fileSystem::FileModeWrite, fileHandle) == false)
+ {
+ setResponse(data, flashBackupFailedToCreateFile);
+ return 0;
+ }
+
+ free(filePath);
+
+ uint8_t banks = context::getModchip()->getFlashBankCount(mRecovery);
+ for (uint8_t i = 0; i < banks; i++)
+ {
+ EnterCriticalSection(&data->mutex);
+ data->currentStep = i + 1;
+ LeaveCriticalSection(&data->mutex);
+
+ uint8_t bank = context::getModchip()->getFlashBank(mRecovery, i);
+ uint32_t bankSize = context::getModchip()->getBankSize(bank);
+ uint32_t memOffset = context::getModchip()->getBankMemOffset(bank);
+
+ fileSystem::fileSeek(fileHandle, fileSystem::FileSeekModeStart, memOffset);
+
+ setResponse(data, flashBackupReading);
+ utils::dataContainer* bankData = context::getModchip()->readBank(bank);
+
+ setResponse(data, flashBackupWriting);
+ uint32_t bytesWritten;
+ if (fileSystem::fileWrite(fileHandle, bankData->data, bankData->size, bytesWritten) == false)
+ {
+ setResponse(data, flashBackupFailedToWriteFile);
+ fileSystem::fileClose(fileHandle);
+ delete(bankData);
+ return 0;
+ }
+
+ delete(bankData);
+
+ if (mRecovery == true)
+ {
+ context::getModchip()->disableRecovery();
+ }
+ }
+
+ fileSystem::fileClose(fileHandle);
+ setResponse(data, flashBackupDone);
+
+ return 0;
+}
+
+void flashBackup::setResponse(flashBackupData* data, flashBackupResponse response)
+{
+ EnterCriticalSection(&data->mutex);
+ data->response = response;
+ LeaveCriticalSection(&data->mutex);
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/flashBackup.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/flashBackup.h
new file mode 100644
index 0000000..55446af
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/flashBackup.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include "..\xboxInternals.h"
+#include "..\modchip.h"
+
+class flashBackup
+{
+public:
+
+ enum flashBackupResponse
+ {
+ flashBackupResponseNone = 0,
+ flashBackupProcessing = 1,
+ flashBackupFailedToCreateDirectory = 2,
+ flashBackupFailedToCreateFile = 3,
+ flashBackupFailedToWriteFile = 4,
+ flashBackupReading = 5,
+ flashBackupWriting = 6,
+ flashBackupDone = 7
+ };
+
+ typedef struct flashBackupData {
+ flashBackupResponse response;
+ uint32_t currentStep;
+ uint32_t totalSteps;
+ CRITICAL_SECTION mutex;
+ } flashBackupData;
+
+ static bool startThread(bool recovery);
+ static bool completed();
+ static flashBackupResponse getResponse();
+ static void getProgress(uint32_t& currentStep, uint32_t& totalSteps);
+ static void closeThread();
+
+private:
+
+ static void setResponse(flashBackupData* data, flashBackupResponse response);
+
+ static uint64_t WINAPI process(void* param);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/flashBank.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/flashBank.cpp
new file mode 100644
index 0000000..27ebce8
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/flashBank.cpp
@@ -0,0 +1,131 @@
+#include "flashBank.h"
+
+#include "..\xboxInternals.h"
+#include "..\stringUtility.h"
+#include "..\fileSystem.h"
+#include "..\utils.h"
+#include "..\settingsManager.h"
+
+namespace
+{
+ HANDLE mThread;
+ flashBank::flashBankData mData;
+}
+
+bool flashBank::startThread(const char* filePath, const char* bankName, uint8_t ledColor)
+{
+ memset(&mData, 0, sizeof(flashBankData));
+ mData.filePath = strdup(filePath);
+ mData.bankName = strdup(bankName);
+ mData.ledColor = ledColor;
+
+ InitializeCriticalSection(&mData.mutex);
+
+ mThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)process, (void*)&mData, 0, NULL);
+ if (mThread == NULL) {
+ return false;
+ }
+ SetThreadPriority(mThread, THREAD_PRIORITY_NORMAL);
+ return true;
+}
+
+bool flashBank::completed()
+{
+ DWORD exitCode;
+ if (GetExitCodeThread(mThread, &exitCode))
+ {
+ if (exitCode != STILL_ACTIVE)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+flashBank::flashBankResponse flashBank::getResponse()
+{
+ flashBankResponse response;
+ EnterCriticalSection(&mData.mutex);
+ response = mData.response;
+ LeaveCriticalSection(&mData.mutex);
+ return response;
+}
+
+void flashBank::closeThread()
+{
+ CloseHandle(mThread);
+ DeleteCriticalSection(&mData.mutex);
+ free(mData.filePath);
+ free(mData.bankName);
+}
+
+uint64_t WINAPI flashBank::process(void* param)
+{
+ flashBankData* data = (flashBankData*)param;
+
+ setResponse(data, flashBankProcessing);
+
+ utils::dataContainer* bankData;
+
+ uint32_t fileHandle;
+ if (fileSystem::fileOpen(data->filePath, fileSystem::FileModeRead, fileHandle))
+ {
+ uint32_t fileSize;
+ if (fileSystem::fileSize(fileHandle, fileSize))
+ {
+ char* buffer = (char*)malloc(fileSize);
+ uint32_t bytesRead;
+ if (fileSystem::fileRead(fileHandle, buffer, fileSize, bytesRead) && bytesRead == fileSize)
+ {
+ bankData = new utils::dataContainer(buffer, fileSize, fileSize);
+ }
+ free(buffer);
+ }
+ fileSystem::fileClose(fileHandle);
+ }
+
+ if (bankData == NULL)
+ {
+ setResponse(data, flashBankFailedToLoadFile);
+ return 0;
+ }
+
+ setResponse(data, flashBankOptimizing);
+
+ uint8_t bankId = 0;
+
+ uint8_t slotsNeeded = (uint8_t)(bankData->size >> 18);
+ settingsManager::optimizeBanks(slotsNeeded);
+ if (settingsManager::tryGetFreeBank(slotsNeeded, bankId) == false)
+ {
+ setResponse(data, flashBankNotEnoughSlots);
+ delete(bankData);
+ return 0;
+ }
+
+ setResponse(data, flashBankErasing);
+ settingsManager::eraseBank(bankId, bankData->size);
+
+ setResponse(data, flashBankWriting);
+ settingsManager::writeBank(bankId, bankData, data->bankName, data->ledColor);
+
+ setResponse(data, flashBankVerifying);
+ if (settingsManager::verifyBank(bankId, bankData) == false)
+ {
+ setResponse(data, flashBankVerificationFailed);
+ delete(bankData);
+ return 0;
+ }
+
+ setResponse(data, flashBankDone);
+ delete(bankData);
+
+ return 0;
+}
+
+void flashBank::setResponse(flashBankData* data, flashBankResponse response)
+{
+ EnterCriticalSection(&data->mutex);
+ data->response = response;
+ LeaveCriticalSection(&data->mutex);
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/flashBank.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/flashBank.h
new file mode 100644
index 0000000..72c34f7
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/flashBank.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include "..\xboxInternals.h"
+
+class flashBank
+{
+public:
+
+ enum flashBankResponse
+ {
+ flashBankResponseNone = 0,
+ flashBankProcessing = 1,
+ flashBankFailedToLoadFile = 2,
+ flashBankOptimizing = 3,
+ flashBankNotEnoughSlots = 4,
+ flashBankErasing = 5,
+ flashBankWriting = 6,
+ flashBankVerifying = 7,
+ flashBankVerificationFailed = 8,
+ flashBankDone = 9
+ };
+
+ typedef struct flashBankData {
+ flashBankResponse response;
+ char* filePath;
+ char* bankName;
+ uint8_t ledColor;
+ CRITICAL_SECTION mutex;
+ } flashBankData;
+
+ static bool startThread(const char* filePath, const char* bankName, uint8_t ledColor);
+ static bool completed();
+ static flashBankResponse getResponse();
+ static void closeThread();
+
+private:
+
+ static void setResponse(flashBankData* data, flashBankResponse response);
+
+ static uint64_t WINAPI process(void* param);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/flashUpdate.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/flashUpdate.cpp
new file mode 100644
index 0000000..d7c9831
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/flashUpdate.cpp
@@ -0,0 +1,157 @@
+#include "flashUpdate.h"
+
+#include "..\modchip.h"
+#include "..\modchipXenium.h"
+#include "..\context.h"
+#include "..\xboxInternals.h"
+#include "..\stringUtility.h"
+#include "..\fileSystem.h"
+#include "..\utils.h"
+
+namespace
+{
+ HANDLE mThread;
+ bool mRecovery;
+ bool mUpdate;
+ flashUpdate::flashUpdateData mData;
+}
+
+bool flashUpdate::startThread(bool recovery, bool update, const char* filePath)
+{
+ mRecovery = recovery;
+ mUpdate = update;
+ memset(&mData, 0, sizeof(flashUpdateData));
+ mData.filePath = strdup(filePath);
+ mData.currentStep = 0;
+ mData.totalSteps = context::getModchip()->getFlashBankCount(mRecovery);
+
+ InitializeCriticalSection(&mData.mutex);
+
+ mThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)process, (void*)&mData, 0, NULL);
+ if (mThread == NULL) {
+ return false;
+ }
+ SetThreadPriority(mThread, THREAD_PRIORITY_NORMAL);
+ return true;
+}
+
+bool flashUpdate::completed()
+{
+ DWORD exitCode;
+ if (GetExitCodeThread(mThread, &exitCode))
+ {
+ if (exitCode != STILL_ACTIVE)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+flashUpdate::flashUpdateResponse flashUpdate::getResponse()
+{
+ flashUpdateResponse response;
+ EnterCriticalSection(&mData.mutex);
+ response = mData.response;
+ LeaveCriticalSection(&mData.mutex);
+ return response;
+}
+
+void flashUpdate::getProgress(uint32_t& currentStep, uint32_t& totalSteps)
+{
+ EnterCriticalSection(&mData.mutex);
+ currentStep = mData.currentStep;
+ totalSteps = mData.totalSteps;
+ LeaveCriticalSection(&mData.mutex);
+}
+
+void flashUpdate::closeThread()
+{
+ CloseHandle(mThread);
+ DeleteCriticalSection(&mData.mutex);
+ free(mData.filePath);
+}
+
+uint64_t WINAPI flashUpdate::process(void* param)
+{
+ flashUpdateData* data = (flashUpdateData*)param;
+
+ setResponse(data, flashUpdateProcessing);
+
+ utils::dataContainer* flashData;
+
+ uint32_t fileHandle;
+ if (fileSystem::fileOpen(data->filePath, fileSystem::FileModeRead, fileHandle))
+ {
+ uint32_t fileSize;
+ if (fileSystem::fileSize(fileHandle, fileSize))
+ {
+ char* buffer = (char*)malloc(fileSize);
+ uint32_t bytesRead;
+ if (fileSystem::fileRead(fileHandle, buffer, fileSize, bytesRead) && bytesRead == fileSize)
+ {
+ flashData = new utils::dataContainer(buffer, fileSize, fileSize);
+ }
+ free(buffer);
+ }
+ fileSystem::fileClose(fileHandle);
+ }
+
+ if (flashData == NULL)
+ {
+ setResponse(data, flashUpdateFailedToLoadFile);
+ return 0;
+ }
+
+ uint8_t banks = context::getModchip()->getFlashBankCount(mRecovery);
+ for (uint8_t i = 0; i < banks; i++)
+ {
+ EnterCriticalSection(&data->mutex);
+ data->currentStep = i + 1;
+ LeaveCriticalSection(&data->mutex);
+
+ uint8_t bank = context::getModchip()->getFlashBank(mRecovery, i);
+ uint32_t bankSize = context::getModchip()->getBankSize(bank);
+ uint32_t memOffset = context::getModchip()->getBankMemOffset(bank);
+
+ if (context::getModchip()->getFlashBankType(mRecovery, i) == bankTypeSystem || mUpdate == false)
+ {
+ setResponse(data, flashUpdateErasing);
+ context::getModchip()->eraseBank(bank);
+
+ if (memOffset < flashData->size)
+ {
+ utils::dataContainer* bankData = new utils::dataContainer(flashData->data, bankSize, bankSize);
+ memcpy(bankData->data, flashData->data + memOffset, bankSize);
+
+ setResponse(data, flashUpdateWriting);
+ context::getModchip()->writeBank(bank, bankData);
+
+ setResponse(data, flashUpdateVerifying);
+ if (context::getModchip()->verifyBank(bank, bankData) == false)
+ {
+ setResponse(data, flashUpdateVerificationFailed);
+ delete(flashData);
+ return 0;
+ }
+ }
+ }
+
+ if (mRecovery == true)
+ {
+ context::getModchip()->disableRecovery();
+ }
+ }
+
+ setResponse(data, flashUpdateDone);
+ delete(flashData);
+
+ return 0;
+}
+
+void flashUpdate::setResponse(flashUpdateData* data, flashUpdateResponse response)
+{
+ EnterCriticalSection(&data->mutex);
+ data->response = response;
+ LeaveCriticalSection(&data->mutex);
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/flashUpdate.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/flashUpdate.h
new file mode 100644
index 0000000..ff5dd70
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/flashUpdate.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include "..\xboxInternals.h"
+#include "..\modchip.h"
+
+class flashUpdate
+{
+public:
+
+ enum flashUpdateResponse
+ {
+ flashUpdateResponseNone = 0,
+ flashUpdateProcessing = 1,
+ flashUpdateFailedToLoadFile = 2,
+ flashUpdateErasing = 3,
+ flashUpdateWriting = 4,
+ flashUpdateVerifying = 5,
+ flashUpdateVerificationFailed = 6,
+ flashUpdateDone = 7
+ };
+
+ typedef struct flashUpdateData {
+ flashUpdateResponse response;
+ uint32_t currentStep;
+ uint32_t totalSteps;
+ char* filePath;
+ CRITICAL_SECTION mutex;
+ } flashUpdateData;
+
+ static bool startThread(bool recovery, bool update, const char* filePath);
+ static bool completed();
+ static flashUpdateResponse getResponse();
+ static void getProgress(uint32_t& currentStep, uint32_t& totalSteps);
+ static void closeThread();
+
+private:
+
+ static void setResponse(flashUpdateData* data, flashUpdateResponse response);
+
+ static uint64_t WINAPI process(void* param);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/hddFormat.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/hddFormat.cpp
new file mode 100644
index 0000000..7d00724
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/hddFormat.cpp
@@ -0,0 +1,67 @@
+#include "hddFormat.h"
+
+#include "..\xboxInternals.h"
+#include "..\stringUtility.h"
+#include "..\harddrive.h"
+
+namespace
+{
+ HANDLE mThread;
+ hddFormat::hddFormatData mData;
+}
+
+bool hddFormat::startThread(int32_t harddrive)
+{
+ memset(&mData, 0, sizeof(hddFormatData));
+ mData.harddrive = harddrive;
+
+ InitializeCriticalSection(&mData.mutex);
+
+ mThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)process, (void*)&mData, 0, NULL);
+ if (mThread == NULL) {
+ return false;
+ }
+ SetThreadPriority(mThread, THREAD_PRIORITY_HIGHEST);
+ return true;
+}
+
+bool hddFormat::completed()
+{
+ DWORD exitCode;
+ if (GetExitCodeThread(mThread, &exitCode))
+ {
+ if (exitCode != STILL_ACTIVE)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+hddFormat::hddFormatResponse hddFormat::getResponse()
+{
+ hddFormatResponse response;
+ EnterCriticalSection(&mData.mutex);
+ response = mData.response;
+ LeaveCriticalSection(&mData.mutex);
+ return response;
+}
+
+void hddFormat::closeThread()
+{
+ CloseHandle(mThread);
+ DeleteCriticalSection(&mData.mutex);
+}
+
+uint64_t WINAPI hddFormat::process(void* param)
+{
+ Sleep(100);
+ hddFormatData* data = (hddFormatData*)param;
+
+ bool success = harddrive::formatDrive(data->harddrive);
+ EnterCriticalSection(&data->mutex);
+ data->response = success ? hddFormatResponseDone : hddFormatResponseFailure;
+ LeaveCriticalSection(&data->mutex);
+
+ return 0;
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/hddFormat.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/hddFormat.h
new file mode 100644
index 0000000..1d0c1cc
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/hddFormat.h
@@ -0,0 +1,30 @@
+#pragma once
+
+#include "..\xboxInternals.h"
+
+class hddFormat
+{
+public:
+
+ enum hddFormatResponse
+ {
+ hddFormatResponseNone = 0,
+ hddFormatResponseDone = 1,
+ hddFormatResponseFailure = 2
+ };
+
+ typedef struct hddFormatData {
+ hddFormatResponse response;
+ int32_t harddrive;
+ CRITICAL_SECTION mutex;
+ } hddFormatData;
+
+ static bool startThread(int32_t harddrive);
+ static bool completed();
+ static hddFormatResponse getResponse();
+ static void closeThread();
+
+private:
+
+ static uint64_t WINAPI process(void* param);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/hddInfo.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/hddInfo.cpp
new file mode 100644
index 0000000..7785bb8
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/hddInfo.cpp
@@ -0,0 +1,128 @@
+#include "hddInfo.h"
+
+#include "..\xboxInternals.h"
+#include "..\stringUtility.h"
+#include "..\XKUtils\XKEEPROM.h"
+#include "..\XKUtils\XKHDD.h"
+
+namespace
+{
+ HANDLE mThread;
+ bool mHarddrive;
+ hddInfo::hddInfoData mData;
+}
+
+bool hddInfo::startThread(bool harddrive)
+{
+ memset(&mData, 0, sizeof(hddInfoData));
+
+ InitializeCriticalSection(&mData.mutex);
+ mHarddrive = harddrive;
+
+ mThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)process, (void*)&mData, 0, NULL);
+ if (mThread == NULL) {
+ return false;
+ }
+ SetThreadPriority(mThread, THREAD_PRIORITY_HIGHEST);
+ return true;
+}
+
+bool hddInfo::completed()
+{
+ DWORD exitCode;
+ if (GetExitCodeThread(mThread, &exitCode))
+ {
+ if (exitCode != STILL_ACTIVE)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+hddInfo::hddInfoResponse hddInfo::getResponse()
+{
+ hddInfoResponse response;
+ EnterCriticalSection(&mData.mutex);
+ response = mData.response;
+ LeaveCriticalSection(&mData.mutex);
+ return response;
+}
+
+char* hddInfo::getModel()
+{
+ char* model;
+ EnterCriticalSection(&mData.mutex);
+ model = mData.model == NULL ? strdup("") : strdup(mData.model);
+ LeaveCriticalSection(&mData.mutex);
+ return model;
+}
+
+char* hddInfo::getSerial()
+{
+ char* serial;
+ EnterCriticalSection(&mData.mutex);
+ serial = mData.serial == NULL ? strdup("") : strdup(mData.serial);
+ LeaveCriticalSection(&mData.mutex);
+ return serial;
+}
+
+void hddInfo::closeThread()
+{
+ CloseHandle(mThread);
+ DeleteCriticalSection(&mData.mutex);
+ free(mData.model);
+ free(mData.serial);
+}
+
+uint64_t WINAPI hddInfo::process(void* param)
+{
+ Sleep(100);
+ hddInfoData* data = (hddInfoData*)param;
+
+ hddInfoResponse response = hddInfoResponseNone;
+ char* model = NULL;
+ char* serial = NULL;
+
+ XKEEPROM* eeprom = new XKEEPROM();
+ eeprom->ReadFromXBOX();
+ if (eeprom->Decrypt())
+ {
+ XKHDD::ATA_COMMAND_OBJ hddcommand;
+ ZeroMemory(&hddcommand, sizeof(XKHDD::ATA_COMMAND_OBJ));
+ hddcommand.DATA_BUFFSIZE = 512;
+ hddcommand.IPReg.bDriveHeadReg = mHarddrive == 0 ? IDE_DEVICE_MASTER : IDE_DEVICE_SLAVE;
+ hddcommand.IPReg.bCommandReg = IDE_ATA_IDENTIFY;
+ bool resp = !!XKHDD::SendATACommand(IDE_PRIMARY_PORT, &hddcommand, IDE_COMMAND_READ);
+
+ if(resp) {
+ char* ideModel = XKHDD::GetIDEModel(hddcommand.DATA_BUFFER);
+ model = stringUtility::trim(ideModel, ' ');
+ free(ideModel);
+ char* ideSerial = XKHDD::GetIDESerial(hddcommand.DATA_BUFFER);
+ serial = stringUtility::trim(ideSerial, ' ');
+ free(ideSerial);
+ DWORD SecStatus = XKHDD::GetIDESecurityStatus(hddcommand.DATA_BUFFER);
+ response = (SecStatus & IDE_SECURITY_SUPPORTED) && (SecStatus & IDE_SECURITY_ENABLED) ? hddInfoResponseLocked : hddInfoResponseUnlocked;
+ }
+ else
+ {
+ response = hddInfoResponseTimeout;
+ }
+ }
+ else
+ {
+ response = hddInfoResponseFailureEeprom;
+ model = strdup("Unknown");
+ serial = strdup("Unknown");
+ }
+ delete(eeprom);
+
+ EnterCriticalSection(&data->mutex);
+ data->response = response;
+ data->model = model;
+ data->serial = serial;
+ LeaveCriticalSection(&data->mutex);
+
+ return 0;
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/hddInfo.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/hddInfo.h
new file mode 100644
index 0000000..79bea19
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/hddInfo.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include "..\xboxInternals.h"
+
+class hddInfo
+{
+public:
+
+ enum hddInfoResponse
+ {
+ hddInfoResponseNone = 0,
+ hddInfoResponseUnlocked = 1,
+ hddInfoResponseLocked = 2,
+ hddInfoResponseFailureEeprom = 3,
+ hddInfoResponseTimeout = 4
+ };
+
+ typedef struct hddInfoData {
+ hddInfoResponse response;
+ char* model;
+ char* serial;
+ CRITICAL_SECTION mutex;
+ } hddInfoData;
+
+ static bool startThread(bool harddrive = 0);
+ static bool completed();
+ static hddInfoResponse getResponse();
+ static char* getModel();
+ static char* getSerial();
+ static void closeThread();
+
+private:
+
+ static uint64_t WINAPI process(void* param);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/hddLockUnlock.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/hddLockUnlock.cpp
new file mode 100644
index 0000000..4ee6682
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/hddLockUnlock.cpp
@@ -0,0 +1,255 @@
+#include "hddLockUnlock.h"
+
+#include "..\utils.h"
+#include "..\context.h"
+#include "..\xboxInternals.h"
+#include "..\XKUtils\XKEEPROM.h"
+#include "..\XKUtils\XKHDD.h"
+#include "..\hddVscUnlocker.h"
+
+namespace
+{
+ HANDLE mThread;
+ hddLockUnlock::hddLockUnlockData mData;
+}
+
+bool hddLockUnlock::startThread(hddLockUnlockAction action)
+{
+ memset(&mData, 0, sizeof(hddLockUnlockData));
+ mData.action = action;
+
+ InitializeCriticalSection(&mData.mutex);
+
+ mThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)process, (void*)&mData, 0, NULL);
+ if (mThread == NULL) {
+ return false;
+ }
+ SetThreadPriority(mThread, THREAD_PRIORITY_HIGHEST);
+ return true;
+}
+
+bool hddLockUnlock::completed()
+{
+ DWORD exitCode;
+ if (GetExitCodeThread(mThread, &exitCode))
+ {
+ if (exitCode != STILL_ACTIVE)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+hddLockUnlock::hddLockUnlockResponse hddLockUnlock::getResponse()
+{
+ hddLockUnlockResponse response;
+ EnterCriticalSection(&mData.mutex);
+ response = mData.response;
+ LeaveCriticalSection(&mData.mutex);
+ return response;
+}
+
+void hddLockUnlock::setResponse(hddLockUnlock::hddLockUnlockResponse response)
+{
+ EnterCriticalSection(&mData.mutex);
+ mData.response = response;
+ LeaveCriticalSection(&mData.mutex);
+}
+
+void hddLockUnlock::closeThread()
+{
+ CloseHandle(mThread);
+ DeleteCriticalSection(&mData.mutex);
+}
+
+uint64_t WINAPI hddLockUnlock::process(void* param)
+{
+ hddLockUnlockData* data = (hddLockUnlockData*)param;
+
+ if (data->action == hddLockUnlockActionLock)
+ {
+ lockHdd();
+ }
+ else
+ {
+ unlockHdd();
+ }
+
+ return 0;
+}
+
+void hddLockUnlock::lockHdd()
+{
+ setResponse(hddLockUnlockResponseLocking);
+
+ XKEEPROM* eeprom = new XKEEPROM();
+ eeprom->ReadFromXBOX();
+
+ XKHDD::ATA_COMMAND_OBJ hddcommand;
+ UCHAR HddPass[32];
+ UCHAR MasterPassword[13] = "TEAMASSEMBLY";
+
+ XBOX_VERSION xver = eeprom->GetXBOXVersion();
+
+ if (eeprom->Decrypt())
+ {
+ ZeroMemory(&hddcommand, sizeof(XKHDD::ATA_COMMAND_OBJ));
+ hddcommand.DATA_BUFFSIZE = 0;
+ hddcommand.IPReg.bDriveHeadReg = IDE_DEVICE_MASTER;
+ hddcommand.IPReg.bCommandReg = IDE_ATA_IDENTIFY;
+ XKHDD::SendATACommand(IDE_PRIMARY_PORT, &hddcommand, IDE_COMMAND_READ);
+
+ XKEEPROM::EEPROMDATA tmpData;
+ eeprom->GetEEPROMData(&tmpData);
+ XKHDD::GenerateHDDPwd(tmpData.HDDKkey, hddcommand.DATA_BUFFER, HddPass);
+
+ DWORD SecStatus = XKHDD::GetIDESecurityStatus(hddcommand.DATA_BUFFER);
+ if ((SecStatus & IDE_SECURITY_SUPPORTED) && !(SecStatus & IDE_SECURITY_ENABLED))
+ {
+ ZeroMemory(&hddcommand, sizeof(XKHDD::ATA_COMMAND_OBJ));
+ hddcommand.DATA_BUFFSIZE = 512;
+ hddcommand.IPReg.bDriveHeadReg = IDE_DEVICE_MASTER;
+ hddcommand.IPReg.bCommandReg = IDE_ATA_SECURITY_SETPASSWORD;
+ LPBYTE HDDP = (LPBYTE)&hddcommand.DATA_BUFFER;
+ LPDWORD pMastr = (LPDWORD) HDDP;
+ *pMastr = 0x0001;
+ memcpy(HDDP+2, MasterPassword, 13);
+ XKHDD::SendATACommand(IDE_PRIMARY_PORT, &hddcommand, IDE_COMMAND_WRITE);
+
+ ZeroMemory(&hddcommand, sizeof(XKHDD::ATA_COMMAND_OBJ));
+ hddcommand.DATA_BUFFSIZE = 512;
+ hddcommand.IPReg.bDriveHeadReg = IDE_DEVICE_MASTER;
+ hddcommand.IPReg.bCommandReg = IDE_ATA_SECURITY_SETPASSWORD;
+ memcpy(HDDP+2, HddPass, 20);
+ XKHDD::SendATACommand(IDE_PRIMARY_PORT, &hddcommand, IDE_COMMAND_WRITE);
+
+ ZeroMemory(&hddcommand, sizeof(XKHDD::ATA_COMMAND_OBJ));
+ hddcommand.DATA_BUFFSIZE = 512;
+ hddcommand.IPReg.bDriveHeadReg = IDE_DEVICE_MASTER;
+ hddcommand.IPReg.bCommandReg = IDE_ATA_IDENTIFY;
+ XKHDD::SendATACommand(IDE_PRIMARY_PORT, &hddcommand, IDE_COMMAND_READ);
+ SecStatus = XKHDD::GetIDESecurityStatus(hddcommand.DATA_BUFFER);
+
+ if ((SecStatus & IDE_SECURITY_SUPPORTED) && (SecStatus & IDE_SECURITY_ENABLED))
+ {
+ setResponse(hddLockUnlockResponseLocked);
+ }
+ else
+ {
+ setResponse(hddLockUnlockResponseFailedToLock);
+ }
+ }
+ else if (!(SecStatus & IDE_SECURITY_SUPPORTED))
+ {
+ setResponse(hddLockUnlockResponseLockingNotSupported);
+ }
+ else
+ {
+ setResponse(hddLockUnlockResponseAlreadyLocked);
+ }
+ }
+ else
+ {
+ setResponse(hddLockUnlockResponseFailureEeprom);
+ }
+
+ delete(eeprom);
+}
+
+void hddLockUnlock::unlockHdd()
+{
+ setResponse(hddLockUnlockResponseUnlocking);
+
+ XKEEPROM* eeprom = new XKEEPROM();
+ eeprom->ReadFromXBOX();
+
+ XBOX_VERSION xver = eeprom->GetXBOXVersion();
+
+ XKHDD::ATA_COMMAND_OBJ hddcommand;
+ UCHAR HddPass[32];
+
+ if (eeprom->Decrypt())
+ {
+ ZeroMemory(&hddcommand, sizeof(XKHDD::ATA_COMMAND_OBJ));
+ hddcommand.DATA_BUFFSIZE = 0;
+ hddcommand.IPReg.bDriveHeadReg = IDE_DEVICE_MASTER;
+ hddcommand.IPReg.bCommandReg = IDE_ATA_IDENTIFY;
+ XKHDD::SendATACommand(IDE_PRIMARY_PORT, &hddcommand, IDE_COMMAND_READ);
+
+ XKEEPROM::EEPROMDATA tmpData;
+ eeprom->GetEEPROMData(&tmpData);
+ XKHDD::GenerateHDDPwd(tmpData.HDDKkey, hddcommand.DATA_BUFFER, HddPass);
+
+ DWORD SecStatus = XKHDD::GetIDESecurityStatus(hddcommand.DATA_BUFFER);
+ if ((SecStatus & IDE_SECURITY_SUPPORTED) && (SecStatus & IDE_SECURITY_ENABLED))
+ {
+ ZeroMemory(&hddcommand, sizeof(XKHDD::ATA_COMMAND_OBJ));
+ hddcommand.DATA_BUFFSIZE = 512;
+ hddcommand.IPReg.bDriveHeadReg = IDE_DEVICE_MASTER;
+ hddcommand.IPReg.bCommandReg = IDE_ATA_SECURITY_UNLOCK;
+ LPBYTE HDDP = (LPBYTE)&hddcommand.DATA_BUFFER;
+ memcpy(HDDP+2, HddPass, 20);
+ XKHDD::SendATACommand(IDE_PRIMARY_PORT, &hddcommand, IDE_COMMAND_WRITE);
+
+ ZeroMemory(&hddcommand, sizeof(XKHDD::ATA_COMMAND_OBJ));
+ hddcommand.DATA_BUFFSIZE = 512;
+ hddcommand.IPReg.bDriveHeadReg = IDE_DEVICE_MASTER;
+ hddcommand.IPReg.bCommandReg = IDE_ATA_SECURITY_DISABLE;
+ memcpy(HDDP+2, HddPass, 20);
+ XKHDD::SendATACommand(IDE_PRIMARY_PORT, &hddcommand, IDE_COMMAND_WRITE);
+
+ ZeroMemory(&hddcommand, sizeof(XKHDD::ATA_COMMAND_OBJ));
+ hddcommand.DATA_BUFFSIZE = 512;
+ hddcommand.IPReg.bDriveHeadReg = IDE_DEVICE_MASTER;
+ hddcommand.IPReg.bCommandReg = IDE_ATA_IDENTIFY;
+ XKHDD::SendATACommand(IDE_PRIMARY_PORT, &hddcommand, IDE_COMMAND_READ);
+ SecStatus = XKHDD::GetIDESecurityStatus(hddcommand.DATA_BUFFER);
+
+ if ((SecStatus & IDE_SECURITY_SUPPORTED) && !(SecStatus & IDE_SECURITY_ENABLED))
+ {
+ setResponse(hddLockUnlockResponseUnlocked);
+ }
+ else
+ {
+ setResponse(hddLockUnlockResponseUnlockingVsc);
+ Sleep(100);
+ hddVscUnlocker* unlocker = new hddVscUnlocker();
+ if(!unlocker->attemptVscUnlock())
+ {
+ setResponse(hddLockUnlockResponseFailedToUnlock);
+ }
+ else
+ {
+ utils::dataContainer* masterPassword = new utils::dataContainer(32);
+ unlocker->getMasterPwd((uint8_t*)masterPassword->data);
+ context::setMasterPassword(masterPassword);
+
+ utils::dataContainer* userPassword = new utils::dataContainer(32);
+ unlocker->getUserPwd((uint8_t*)userPassword->data);
+ context::setUserPassword(userPassword);
+
+ hddVscUnlocker::DRIVE_INFO driveInfo = unlocker->getDriveInfo();
+ context::setDriveModel(strdup(driveInfo.model));
+ context::setDriveSerial(strdup(driveInfo.serial));
+ free(driveInfo.firmware);
+ free(driveInfo.model);
+ free(driveInfo.serial);
+
+ setResponse(hddLockUnlockResponseUnlockedVsc);
+ }
+ delete(unlocker);
+ }
+ }
+ else
+ {
+ setResponse(hddLockUnlockResponseAlreadyUnlocked);
+ }
+ }
+ else
+ {
+ setResponse(hddLockUnlockResponseFailureEeprom);
+ }
+
+ delete(eeprom);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/hddLockUnlock.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/hddLockUnlock.h
new file mode 100644
index 0000000..99f595b
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/hddLockUnlock.h
@@ -0,0 +1,49 @@
+#pragma once
+
+#include "..\xboxInternals.h"
+
+class hddLockUnlock
+{
+public:
+
+ enum hddLockUnlockAction
+ {
+ hddLockUnlockActionLock = 0,
+ hddLockUnlockActionUnlock = 1
+ };
+
+ enum hddLockUnlockResponse
+ {
+ hddLockUnlockResponseNone = 0,
+ hddLockUnlockResponseUnlocked = 1,
+ hddLockUnlockResponseUnlockedVsc = 2,
+ hddLockUnlockResponseFailedToUnlock = 3,
+ hddLockUnlockResponseAlreadyUnlocked = 4,
+ hddLockUnlockResponseLocked = 5,
+ hddLockUnlockResponseFailedToLock = 6,
+ hddLockUnlockResponseAlreadyLocked = 7,
+ hddLockUnlockResponseLockingNotSupported = 8,
+ hddLockUnlockResponseFailureEeprom = 9,
+ hddLockUnlockResponseUnlocking = 10,
+ hddLockUnlockResponseUnlockingVsc = 11,
+ hddLockUnlockResponseLocking = 12
+ };
+
+ typedef struct hddLockUnlockData {
+ hddLockUnlockAction action;
+ hddLockUnlockResponse response;
+ CRITICAL_SECTION mutex;
+ } hddLockUnlockData;
+
+ static bool startThread(hddLockUnlockAction action);
+ static bool completed();
+ static hddLockUnlockResponse getResponse();
+ static void closeThread();
+
+private:
+
+ static uint64_t WINAPI process(void* param);
+ static void lockHdd();
+ static void unlockHdd();
+ static void setResponse(hddLockUnlock::hddLockUnlockResponse response);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/lcdRender.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/lcdRender.cpp
new file mode 100644
index 0000000..a89e54e
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/lcdRender.cpp
@@ -0,0 +1,277 @@
+#include "lcdRender.h"
+
+#include "..\xboxInternals.h"
+#include "..\stringUtility.h"
+#include "..\fileSystem.h"
+#include "..\utils.h"
+#include "..\context.h"
+#include "..\settingsManager.h"
+
+namespace
+{
+ HANDLE mThread;
+ lcdRender::lcdRenderData mData;
+}
+
+bool lcdRender::startThread()
+{
+ memset(&mData, 0, sizeof(lcdRenderData));
+ mData.requestStop = false;
+
+ InitializeCriticalSection(&mData.mutex);
+
+ mThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)process, (void*)&mData, 0, NULL);
+ if (mThread == NULL) {
+ return false;
+ }
+ SetThreadPriority(mThread, THREAD_PRIORITY_HIGHEST);
+ return true;
+}
+
+bool lcdRender::completed()
+{
+ DWORD exitCode;
+ if (GetExitCodeThread(mThread, &exitCode))
+ {
+ if (exitCode != STILL_ACTIVE)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void lcdRender::closeThread()
+{
+ EnterCriticalSection(&mData.mutex);
+ mData.requestStop = true;
+ LeaveCriticalSection(&mData.mutex);
+ CloseHandle(mThread);
+ DeleteCriticalSection(&mData.mutex);
+}
+
+void lcdRender::waitStop()
+{
+ EnterCriticalSection(&mData.mutex);
+ mData.requestStop = true;
+ LeaveCriticalSection(&mData.mutex);
+ while (completed() == false)
+ {
+ Sleep(100);
+ }
+}
+
+uint64_t WINAPI lcdRender::process(void* param)
+{
+ lcdRenderData* data = (lcdRenderData*)param;
+
+ char* titleToDisplay = strdup("");
+ char* freeMemToDisplay = strdup("");
+ char* ipToDisplay = strdup("");
+ char* fanToDisplay = strdup("");
+ char* cpuToDisplay = strdup("");
+
+ uint8_t lcdMode = settingsManager::getLcdMode(true);
+ uint8_t lcdModel = settingsManager::getLcdModel(true);
+ uint8_t lcdAddress = settingsManager::getLcdAddress(true);
+ uint8_t backlight = settingsManager::getLcdBacklight(true);
+ uint8_t contrast = settingsManager::getLcdBacklight(true);
+
+ int counter = 0;
+
+ bool initialized = false;
+ bool requestStop = false;
+ while (requestStop == false)
+ {
+ char* currentTitle = context::getCurrentTitle();
+ char* currentIp = context::getCurrentIp();
+ char* currentFreeMem = stringUtility::formatSize(context::getCurrentFreeMem());
+ char* currentFan = stringUtility::formatString("%i%%", context::getCurrentFanSpeed());
+ char* currentCpu = stringUtility::formatString("%ic", context::getCurrentCpuTemp());
+
+ //counter++;
+ //if (counter == 10)
+ //{
+ // counter = 0;
+ // utils::swapString(&titleToDisplay, "");
+ // utils::swapString(&freeMemToDisplay, "");
+ // utils::swapString(&ipToDisplay, "");
+ // utils::swapString(&fanToDisplay, "");
+ // utils::swapString(&cpuToDisplay, "");
+ //}
+
+ uint8_t currentlcdMode = settingsManager::getLcdMode(true);
+ if (currentlcdMode != lcdMode)
+ {
+ lcdMode = currentlcdMode;
+ initialized = false;
+ }
+
+ uint8_t currentLcdModel = settingsManager::getLcdModel(true);
+ if (currentLcdModel != lcdModel)
+ {
+ lcdModel = currentLcdModel;
+ initialized = false;
+ }
+
+ uint8_t currentLcdAddress = settingsManager::getLcdAddress(true);
+ if (currentLcdAddress != lcdAddress)
+ {
+ lcdAddress = currentLcdAddress;
+ initialized = false;
+ }
+
+ if (currentlcdMode > 0)
+ {
+ if (initialized == false)
+ {
+ initialized = true;
+ context::getModchip()->lcdInit();
+
+ utils::swapString(&titleToDisplay, "");
+ utils::swapString(&freeMemToDisplay, "");
+ utils::swapString(&ipToDisplay, "");
+ utils::swapString(&fanToDisplay, "");
+ utils::swapString(&cpuToDisplay, "");
+
+ context::getModchip()->lcdSetCursorPosition(0, 0);
+ char* line1 = stringUtility::formatLcdString("", 20);
+ context::getModchip()->lcdPrintMessage(line1);
+ free(line1);
+
+ context::getModchip()->lcdSetCursorPosition(1, 0);
+ char* line2 = stringUtility::formatLcdString("IP:", 20);
+ context::getModchip()->lcdPrintMessage(line2);
+ free(line2);
+
+ if (context::getModchip()->getSupportInfo(true).supportsLcdInfo == false)
+ {
+ context::getModchip()->lcdSetCursorPosition(2, 0);
+ char* line3 = stringUtility::formatLcdString("Free Mem:", 20);
+ context::getModchip()->lcdPrintMessage(line3);
+ free(line3);
+
+ context::getModchip()->lcdSetCursorPosition(3, 0);
+ char* line4 = stringUtility::formatLcdString("FAN: CPU:", 20);
+ context::getModchip()->lcdPrintMessage(line4);
+ free(line4);
+ }
+ }
+
+ if (stringUtility::equals(titleToDisplay, currentTitle, false) == false)
+ {
+ utils::swapString(&titleToDisplay, currentTitle);
+
+ context::getModchip()->lcdSetCursorPosition(0, 0);
+ char* title = stringUtility::formatLcdString(titleToDisplay, 20);
+ context::getModchip()->lcdPrintMessage(title);
+ free(title);
+ }
+
+ if (stringUtility::equals(ipToDisplay, currentIp, false) == false)
+ {
+ utils::swapString(&ipToDisplay, currentIp);
+
+ if (context::getModchip()->getDisplayDriver(true)->isSpi2Par() == true)
+ {
+ context::getModchip()->lcdSetCursorPosition(1, 0);
+ context::getModchip()->lcdPrintMessage("IP:");
+ }
+
+ context::getModchip()->lcdSetCursorPosition(1, 3);
+ char* ip = stringUtility::formatLcdString(ipToDisplay, 15);
+ context::getModchip()->lcdPrintMessage(ip);
+ free(ip);
+ }
+
+ if (context::getModchip()->getSupportInfo(true).supportsLcdInfo == false)
+ {
+ if (stringUtility::equals(freeMemToDisplay, currentFreeMem, false) == false)
+ {
+ utils::swapString(&freeMemToDisplay, currentFreeMem);
+
+ if (context::getModchip()->getDisplayDriver(true)->isSpi2Par() == true)
+ {
+ context::getModchip()->lcdSetCursorPosition(2, 0);
+ context::getModchip()->lcdPrintMessage("Free Mem:");
+ }
+
+ context::getModchip()->lcdSetCursorPosition(2, 9);
+ char* freeMem = stringUtility::formatLcdString(freeMemToDisplay, 20 - 9);
+ context::getModchip()->lcdPrintMessage(freeMem);
+ free(freeMem);
+ }
+
+ if (stringUtility::equals(fanToDisplay, currentFan, false) == false)
+ {
+ utils::swapString(&fanToDisplay, currentFan);
+
+ if (context::getModchip()->getDisplayDriver(true)->isSpi2Par() == true)
+ {
+ context::getModchip()->lcdSetCursorPosition(3, 0);
+ context::getModchip()->lcdPrintMessage("FAN:");
+ }
+
+ context::getModchip()->lcdSetCursorPosition(3, 4);
+ char* fan = stringUtility::formatLcdString(fanToDisplay, 4);
+ context::getModchip()->lcdPrintMessage(fan);
+ free(fan);
+ }
+
+ if (stringUtility::equals(cpuToDisplay, currentCpu, false) == false)
+ {
+ utils::swapString(&cpuToDisplay, currentCpu);
+
+ if (context::getModchip()->getDisplayDriver(true)->isSpi2Par() == true)
+ {
+ context::getModchip()->lcdSetCursorPosition(3, 9);
+ context::getModchip()->lcdPrintMessage("CPU:");
+ }
+
+ context::getModchip()->lcdSetCursorPosition(3, 13);
+ char* cpu = stringUtility::formatLcdString(cpuToDisplay, 3);
+ context::getModchip()->lcdPrintMessage(cpu);
+ free(cpu);
+ }
+ }
+
+ if (backlight != settingsManager::getLcdBacklight(true))
+ {
+ backlight = settingsManager::getLcdBacklight(true);
+ context::getModchip()->lcdSetBacklight(backlight);
+ }
+
+ if (contrast != settingsManager::getLcdContrast(true))
+ {
+ contrast = settingsManager::getLcdContrast(true);
+ context::getModchip()->lcdSetContrast(contrast);
+ }
+ }
+
+ utils::freeString(¤tTitle);
+ utils::freeString(¤tIp);
+ utils::freeString(¤tFreeMem);
+ utils::freeString(¤tFan);
+ utils::freeString(¤tCpu);
+
+ for (int i = 0; i < 10; i++)
+ {
+ EnterCriticalSection(&data->mutex);
+ requestStop = data->requestStop;
+ LeaveCriticalSection(&data->mutex);
+ if (requestStop == true)
+ {
+ break;
+ }
+ Sleep(100);
+ }
+ }
+
+ utils::freeString(&titleToDisplay);
+ utils::freeString(&ipToDisplay);
+ utils::freeString(&freeMemToDisplay);
+ utils::freeString(&fanToDisplay);
+ utils::freeString(&cpuToDisplay);
+
+ return 0;
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/lcdRender.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/lcdRender.h
new file mode 100644
index 0000000..fee1810
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/Threads/lcdRender.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "..\xboxInternals.h"
+
+class lcdRender
+{
+public:
+
+ typedef struct lcdRenderData {
+ bool requestStop;
+ CRITICAL_SECTION mutex;
+ } lcdRenderData;
+
+ static bool startThread();
+ static bool completed();
+ static void closeThread();
+ static void waitStop();
+
+private:
+
+ static uint64_t WINAPI process(void* param);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKCRC.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKCRC.cpp
new file mode 100644
index 0000000..a9d1ecf
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKCRC.cpp
@@ -0,0 +1,73 @@
+/*
+**********************************
+**********************************
+** BROUGHT TO YOU BY: **
+**********************************
+**********************************
+** **
+** [TEAM ASSEMBLY] **
+** **
+** www.team-assembly.com **
+** **
+******************************************************************************************************
+* This is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+******************************************************************************************************
+
+********************************************************************************************************
+** XKCRC.CPP - General CRC Class' Implementation
+********************************************************************************************************
+**
+** Containss functions to do a simple CRC check on a block of data..
+** might be more ways of elegantly doing this, but for now this has to work...
+**
+********************************************************************************************************
+
+UPDATE LOG:
+--------------------------------------------------------------------------------------------------------
+Date: 02/18/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared 0.2 for Public Release
+--------------------------------------------------------------------------------------------------------
+Date: 01/06/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared for Public Release
+--------------------------------------------------------------------------------------------------------
+
+*/
+#include "XKCRC.h"
+
+XKCRC::XKCRC(void)
+{
+}
+
+XKCRC::~XKCRC(void)
+{
+}
+
+void XKCRC::QuickCRC(UCHAR* CRCVAL, UCHAR* inData, DWORD dataLen)
+{
+ unsigned long high = 0, low = 0;
+
+ for (unsigned long i = 0; i < dataLen / sizeof(unsigned long); i++)
+ {
+ unsigned long val = ((unsigned long *)inData)[i];
+ unsigned long long sum = ((unsigned long long)high << 32) | low;
+
+ high = (unsigned long)((sum + val) >> 32);
+ low += val;
+ }
+
+ *(unsigned long *)CRCVAL = ~(high + low);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKCRC.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKCRC.h
new file mode 100644
index 0000000..f4facda
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKCRC.h
@@ -0,0 +1,69 @@
+/*
+**********************************
+**********************************
+** BROUGHT TO YOU BY: **
+**********************************
+**********************************
+** **
+** [TEAM ASSEMBLY] **
+** **
+** www.team-assembly.com **
+** **
+******************************************************************************************************
+* This is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+******************************************************************************************************
+
+********************************************************************************************************
+** XKCRC.H - General CRC Class' Header
+********************************************************************************************************
+**
+** This is the Class Header, see the .CPP file for more comments and implementation details.
+**
+********************************************************************************************************
+
+UPDATE LOG:
+--------------------------------------------------------------------------------------------------------
+Date: 02/18/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared 0.2 for Public Release
+--------------------------------------------------------------------------------------------------------
+Date: 01/06/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared for Public Release
+--------------------------------------------------------------------------------------------------------
+
+*/
+
+#pragma once
+#if defined (_WINDOWS)
+ #pragma message ("Compiling for WINDOWS: " __FILE__)
+ #include // MFC core and standard components
+#elif defined (_XBOX)
+ #pragma message ("Compiling for XBOX: " __FILE__)
+ #include
+#else
+ #error ERRR: Have to Define _WINDOWS or _XBOX !!
+#endif
+
+
+class XKCRC
+{
+public:
+ XKCRC(void);
+ virtual ~XKCRC(void);
+
+ static void QuickCRC(UCHAR* CRCVAL, UCHAR* inData, DWORD dataLen);
+
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKEEPROM.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKEEPROM.cpp
new file mode 100644
index 0000000..9f29fe5
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKEEPROM.cpp
@@ -0,0 +1,681 @@
+/*
+**********************************
+**********************************
+** BROUGHT TO YOU BY: **
+**********************************
+**********************************
+** **
+** [TEAM ASSEMBLY] **
+** **
+** www.team-assembly.com **
+** **
+******************************************************************************************************
+* This is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+******************************************************************************************************
+
+********************************************************************************************************
+** XKEEPROM.CPP - XBOX EEPROM Class' Implementation
+********************************************************************************************************
+**
+** This Class encapsulates the XBOX EEPROM strucure and many helper functions to parse,
+** Calculate CRC's and Decrypt various values in the XBOX EEPROM..
+**
+********************************************************************************************************
+
+********************************************************************************************************
+** CREDITS:
+********************************************************************************************************
+** XBOX-LINUX TEAM:
+** ---------------
+** Wow, you guys are awsome !! I bow down to your greatness !! the "Friday 13th" Middle
+** Message Hack really saved our butts !!
+** REFERENCE URL: http://xbox-linux.sourceforge.net
+**
+********************************************************************************************************
+
+UPDATE LOG:
+--------------------------------------------------------------------------------------------------------
+Date: 11/27/2004
+By: Yoshihiro
+Reason: Update for xbox 1.6
+--------------------------------------------------------------------------------------------------------
+Date: 02/18/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared 0.2 for Public Release
+--------------------------------------------------------------------------------------------------------
+Date: 01/25/2003
+By: UNDEAD [team-assembly]
+Reason: Added XBOX Specific code to read EEPROM Data from Hardware
+--------------------------------------------------------------------------------------------------------
+Date: 01/06/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared for Public Release
+--------------------------------------------------------------------------------------------------------
+
+*/
+
+#include "xkeeprom.h"
+
+#include "..\xboxInternals.h"
+#include "..\stringUtility.h"
+
+/* Default Constructor using a Blank eeprom image... */
+XKEEPROM::XKEEPROM()
+{
+ m_XBOX_Version = V1_0;
+ ZeroMemory(&m_EEPROMData, sizeof(EEPROMDATA));
+ m_EncryptedState = FALSE;
+
+}
+
+/* Constructor to specify a eeprom image to use ... */
+XKEEPROM::XKEEPROM(LPEEPROMDATA pEEPROMData, BOOL Encrypted)
+{
+ m_XBOX_Version = V_NONE;
+ memcpy(&m_EEPROMData, (LPBYTE)pEEPROMData, sizeof(EEPROMDATA));
+ m_EncryptedState = Encrypted;
+}
+
+/* Default Destructor */
+XKEEPROM::~XKEEPROM(void)
+{
+}
+
+/* Read a EEPROM image from a .BIN file.. */
+/* could be a decrypted or Enrytped.. make sure you specify correct value */
+bool XKEEPROM::ReadFromBINFile(const char* FileName, bool isEncrypted)
+{
+ //First Make sure the File exists...
+ WIN32_FIND_DATA wfd;
+ HANDLE hf = FindFirstFile(FileName, &wfd);
+ if (hf == INVALID_HANDLE_VALUE)
+ return false;
+
+ //Now Read the EEPROM Data from File..
+ BYTE Data[EEPROM_SIZE];
+ DWORD dwBytesRead = 0;
+ ZeroMemory(Data, EEPROM_SIZE);
+
+ hf = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ bool retVal = ReadFile(hf, Data, EEPROM_SIZE, &dwBytesRead, NULL) == TRUE;
+ if (retVal && (dwBytesRead >= EEPROM_SIZE))
+ {
+ memcpy(&m_EEPROMData, Data, EEPROM_SIZE);
+ m_EncryptedState = isEncrypted;
+ }
+ else
+ retVal = false;
+
+ CloseHandle(hf);
+
+ return retVal;
+}
+
+/* Write the Current EEPROM image to a .BIN file.. */
+bool XKEEPROM::WriteToBINFile(const char* fileName)
+{
+ bool retVal = false;
+ DWORD dwBytesWrote = 0;
+
+ //Only write bin file if encrypted..
+ if (m_EncryptedState)
+ {
+ HANDLE hf = CreateFile(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hf != INVALID_HANDLE_VALUE)
+ {
+ //Write EEPROM File
+ retVal = WriteFile(hf , &m_EEPROMData, EEPROM_SIZE, &dwBytesWrote, NULL) == TRUE;
+ }
+ CloseHandle(hf);
+ }
+ return retVal;
+}
+
+void XKEEPROM::ReadFromXBOX()
+{
+ ULONG type;
+ ULONG size;
+ ExQueryNonVolatileSetting(0xFFFF, &type, &m_EEPROMData, 256, &size);
+ m_EncryptedState = TRUE;
+}
+
+void XKEEPROM::WriteToXBOX()
+{
+ ULONG type = 3;
+ ULONG size = 256;
+ ExSaveNonVolatileSetting(0xFFFF, type, &m_EEPROMData, size);
+}
+
+/* Return EEPROM data for this object, Check if it is Encrypted with IsEncrypted() */
+void XKEEPROM::GetEEPROMData(LPEEPROMDATA pEEPROMData)
+{
+ memcpy(pEEPROMData, &m_EEPROMData, EEPROM_SIZE);
+}
+
+/* Set a Decrypted EEPROM image as EEPROM data for this object */
+void XKEEPROM::SetDecryptedEEPROMData(XBOX_VERSION Version, LPEEPROMDATA pEEPROMData)
+{
+ memcpy(&m_EEPROMData, pEEPROMData, EEPROM_SIZE);
+ m_EncryptedState = FALSE;
+ m_XBOX_Version = Version;
+}
+
+/* Set a encrypted EEPROM image as EEPROM data for this object */
+void XKEEPROM::SetEncryptedEEPROMData(LPEEPROMDATA pEEPROMData)
+{
+ memcpy(&m_EEPROMData, pEEPROMData, EEPROM_SIZE);
+ m_EncryptedState = TRUE;
+}
+
+/* Get current detected XBOX Version for this EEPROM */
+XBOX_VERSION XKEEPROM::GetXBOXVersion()
+{
+ return m_XBOX_Version;
+}
+
+/* Get confounder in the form of BYTES in a Hex String representation */
+void XKEEPROM::GetConfounderString(LPSTR Confounder, LPDWORD Length)
+{
+ DWORD len = CONFOUNDER_SIZE;
+ UCHAR Confounder2[0x8] = { 0x4c,0x70,0x33,0xcb,0x5b,0xb5,0x97,0xd2 };
+ //Check if this is currently an encrypted image.. if it is, then decrypt it first..
+ BOOL oldEncryptedState = m_EncryptedState;
+ if (m_EncryptedState)
+ Decrypt();
+
+ XKGeneral::BytesToHexStr((LPBYTE)&m_EEPROMData.Confounder/*Confounder2*/, len, Confounder);
+ *Length = len;
+
+ //Check if this is was an encrypted image.. if it was, then re-encrypt it..
+ if (oldEncryptedState)
+ EncryptAndCalculateCRC();
+}
+
+/* Set Confounder in the form of BYTES in a Hex String representation */
+void XKEEPROM::SetConfounderString(LPCSTR Confounder)
+{
+ const char* Confounder2 = "4c7033cb5bb597d2";
+ DWORD len = CONFOUNDER_SIZE * 2;
+ BYTE tmpData[(CONFOUNDER_SIZE * 2) + 1];
+ ZeroMemory(tmpData, len + 1);
+ memcpy(tmpData, Confounder2, min(strlen(Confounder2), len));
+
+ XKGeneral::HexStrToBytes(tmpData, &len, TRUE);
+
+ //Check if this is currently an encrypted image.. if it is, then decrypt it first..
+ BOOL oldEncryptedState = m_EncryptedState;
+ if (m_EncryptedState)
+ Decrypt();
+
+ memcpy(&m_EEPROMData.Confounder, tmpData, CONFOUNDER_SIZE);
+
+ //Check if this is was an encrypted image.. if it was, then re-encrypt it..
+ if (oldEncryptedState)
+ EncryptAndCalculateCRC();
+}
+
+/* Set HDD Key in the form of BYTES in a Hex String representation */
+void XKEEPROM::GetHDDKeyString(LPSTR HDDKey, LPDWORD Length)
+{
+ DWORD len = HDDKEY_SIZE;
+
+ //Check if this is currently an encrypted image.. if it is, then decrypt it first..
+ BOOL oldEncryptedState = m_EncryptedState;
+ if (m_EncryptedState)
+ Decrypt();
+
+ XKGeneral::BytesToHexStr((LPBYTE)&m_EEPROMData.HDDKkey, len, HDDKey);
+ *Length = len;
+
+ //Check if this is was an encrypted image.. if it was, then re-encrypt it..
+ if (oldEncryptedState)
+ EncryptAndCalculateCRC();
+
+}
+
+/* Set HDD Key in the form of BYTES in a Hex String representation */
+void XKEEPROM::SetHDDKeyString(LPCSTR HDDKey)
+{
+ DWORD len = HDDKEY_SIZE * 2;
+ BYTE tmpData[(HDDKEY_SIZE * 2) + 1];
+ ZeroMemory(tmpData, len + 1);
+ memcpy(tmpData, HDDKey, min(strlen(HDDKey), len));
+
+ XKGeneral::HexStrToBytes(tmpData, &len, TRUE);
+
+ //Check if this is currently an encrypted image.. if it is, then decrypt it first..
+ BOOL oldEncryptedState = m_EncryptedState;
+ if (m_EncryptedState)
+ Decrypt();
+
+ memcpy(&m_EEPROMData.HDDKkey, tmpData, HDDKEY_SIZE);
+
+ //Check if this is was an encrypted image.. if it was, then re-encrypt it..
+ if (oldEncryptedState)
+ EncryptAndCalculateCRC();
+
+}
+
+
+/* Get XBE Region in the form of BYTES in a Hex String representation */
+void XKEEPROM::GetXBERegionString(LPSTR XBERegion, LPDWORD Length)
+{
+ DWORD len = XBEREGION_SIZE;
+
+ //Check if this is currently an encrypted image.. if it is, then decrypt it first..
+ BOOL oldEncryptedState = m_EncryptedState;
+ if (m_EncryptedState)
+ Decrypt();
+
+ XKGeneral::BytesToHexStr((LPBYTE)&m_EEPROMData.XBERegion, len, XBERegion);
+ *Length = len;
+
+ //Check if this is was an encrypted image.. if it was, then re-encrypt it..
+ if (oldEncryptedState)
+ EncryptAndCalculateCRC();
+}
+
+/* Set XBE Region in the form of BYTES in a Hex String representation */
+void XKEEPROM::SetXBERegionString(LPCSTR XBERegion)
+{
+ DWORD len = XBEREGION_SIZE * 2;
+ BYTE tmpData[(XBEREGION_SIZE * 2) + 1];
+ ZeroMemory(tmpData, len + 1);
+ memcpy(tmpData, XBERegion, min(strlen(XBERegion), len));
+
+ XKGeneral::HexStrToBytes(tmpData, &len, TRUE);
+
+ //Check if this is currently an encrypted image.. if it is, then decrypt it first..
+ BOOL oldEncryptedState = m_EncryptedState;
+ if (m_EncryptedState)
+ Decrypt();
+
+ memcpy(&m_EEPROMData.XBERegion, tmpData, XBEREGION_SIZE);
+
+ //Check if this is was an encrypted image.. if it was, then re-encrypt it..
+ if (oldEncryptedState)
+ EncryptAndCalculateCRC();
+}
+
+/* Set XBE Region using Enum Value */
+void XKEEPROM::SetXBERegionVal(XBE_REGION RegionVal)
+{
+ //Check if this is currently an encrypted image.. if it is, then decrypt it first..
+ BOOL oldEncryptedState = m_EncryptedState;
+ if (m_EncryptedState)
+ Decrypt();
+
+ switch (RegionVal)
+ {
+ case(NORTH_AMERICA):
+ case(JAPAN):
+ case(EURO_AUSTRALIA):
+ {
+ m_EEPROMData.XBERegion[0] = RegionVal; //Only use first byte of Region...
+ break;
+ }
+ default:
+ m_EEPROMData.XBERegion[0] = NORTH_AMERICA; //If invalid,use Default of US
+ }
+
+ //Check if this is was an encrypted image.. if it was, then re-encrypt it..
+ if (oldEncryptedState)
+ EncryptAndCalculateCRC();
+}
+
+/* Get XBE Region as Enum Value */
+XBE_REGION XKEEPROM::GetXBERegionVal()
+{
+ //Check if this is currently an encrypted image.. if it is, then decrypt it first..
+ BOOL oldEncryptedState = m_EncryptedState;
+ if (m_EncryptedState)
+ Decrypt();
+
+ XBE_REGION retVal = XBE_REGION (m_EEPROMData.XBERegion[0]);
+
+ //Check if this is was an encrypted image.. if it was, then re-encrypt it..
+ if (oldEncryptedState)
+ EncryptAndCalculateCRC();
+
+ return retVal;
+}
+
+/* Get Serial Number in the form of Decimal String representation */
+char* XKEEPROM::GetSerialNumberString()
+{
+ char serial[13];
+ memcpy(serial, &m_EEPROMData.SerialNumber[0], 12);
+ serial[12]='\0';
+ return strdup(serial);
+}
+
+/* Set Serial Number in the form of Decimal String representation */
+void XKEEPROM::SetSerialNumberString(const char* SerialNumber)
+{
+ DWORD len = SERIALNUMBER_SIZE;
+ strncpy((LPSTR)&m_EEPROMData.SerialNumber, SerialNumber, len);
+
+ CalculateChecksum2();
+}
+
+/* Get MAC Address in the form of BYTES in a Hex String representation */
+char* XKEEPROM::GetMACAddressString()
+{
+ return stringUtility::formatString("%02X%02X%02X%02X%02X%02X", m_EEPROMData.MACAddress[0], m_EEPROMData.MACAddress[1], m_EEPROMData.MACAddress[2], m_EEPROMData.MACAddress[3], m_EEPROMData.MACAddress[4], m_EEPROMData.MACAddress[5]);
+}
+
+/* Set MAC Address in the form of BYTES in a Hex String representation */
+void XKEEPROM::SetMACAddressString(const char* MACAddress)
+{
+ DWORD len = MACADDRESS_SIZE * 3;
+ BYTE tmpData[(HDDKEY_SIZE * 3) + 1];
+ ZeroMemory(tmpData, len + 1);
+ memcpy(tmpData, MACAddress, min(strlen(MACAddress), len));
+
+ XKGeneral::HexStrToBytes(tmpData, &len, TRUE);
+
+ memcpy(&m_EEPROMData.MACAddress, tmpData, MACADDRESS_SIZE);
+
+ CalculateChecksum2();
+
+}
+
+/* Get Online Key in the form of BYTES in a Hex String representation */
+void XKEEPROM::GetOnlineKeyString(LPSTR OnlineKey, LPDWORD Length)
+{
+ DWORD len = ONLINEKEY_SIZE;
+
+ XKGeneral::BytesToHexStr((LPBYTE)&m_EEPROMData.OnlineKey, len, OnlineKey);
+ *Length = len;
+
+}
+
+
+/* Set Online Key in the form of BYTES in a Hex String representation */
+void XKEEPROM::SetOnlineKeyString(LPCSTR OnlineKey)
+{
+ DWORD len = ONLINEKEY_SIZE * 2;
+ BYTE tmpData[(HDDKEY_SIZE * 2) + 1];
+ ZeroMemory(tmpData, len + 1);
+ memcpy(tmpData, OnlineKey, min(strlen(OnlineKey), len));
+
+ XKGeneral::HexStrToBytes(tmpData, &len, TRUE);
+
+ memcpy(&m_EEPROMData.OnlineKey, tmpData, ONLINEKEY_SIZE);
+
+ CalculateChecksum2();
+}
+
+
+/*Set Video Standard with Enum */
+void XKEEPROM::SetDVDRegionVal(unsigned int ZoneVal)
+{
+ unsigned int* Zone = ((unsigned int*)&m_EEPROMData.DVDPlaybackKitZone);
+ *Zone = ZoneVal;
+ CalculateChecksum3();
+}
+
+
+/*Get DVD Region as Enum */
+unsigned int XKEEPROM::GetDVDRegionVal()
+{
+ uint32_t retVal = *(uint32_t*)&m_EEPROMData.DVDPlaybackKitZone;
+ return retVal;
+}
+
+
+void XKEEPROM::SetAudioFlagsVal(unsigned int AudioFlagsVal)
+{
+ unsigned int* AudioFlags = ((unsigned int*)&m_EEPROMData.AudioFlags);
+ *AudioFlags = (AudioFlagsVal & EEPROM_AUDIO_FLAGS_MASK);
+ CalculateChecksum3();
+}
+
+/*Get Video Standard as Enum */
+unsigned int XKEEPROM::GetAudioFlagsVal()
+{
+ uint32_t retVal = *(uint32_t*)&m_EEPROMData.AudioFlags;
+ return retVal;
+}
+
+/* Set Video Standard with Enum */
+void XKEEPROM::SetVideoFlagsVal(unsigned int VideoFlagsVal)
+{
+ unsigned int* VideoFlags = ((unsigned int*)&m_EEPROMData.VideoFlags);
+ *VideoFlags = (VideoFlagsVal & EEPROM_VIDEO_FLAGS_MASK);
+ CalculateChecksum3();
+}
+
+/*Get Video Standard as Enum */
+unsigned int XKEEPROM::GetVideoFlagsVal()
+{
+ uint32_t retVal = *(uint32_t*)&m_EEPROMData.VideoFlags;
+ return retVal;
+}
+
+
+/* Set Video Standard with Enum */
+void XKEEPROM::SetVideoStandardVal(unsigned int StandardVal)
+{
+ unsigned int* VidStandard = ((unsigned int*)&m_EEPROMData.VideoStandard);
+ *VidStandard = StandardVal;
+ CalculateChecksum2();
+}
+
+/*Get Video Standard as Enum */
+unsigned int XKEEPROM::GetVideoStandardVal()
+{
+ uint32_t retVal = *(uint32_t*)&m_EEPROMData.VideoStandard;
+ return retVal;
+}
+
+
+/* Encrypt the EEPROM Data for Specific XBOX Version by means of the SHA1 Middle Message hack..*/
+BOOL XKEEPROM::EncryptAndCalculateCRC(XBOX_VERSION XBOXVersion)
+{
+ if (!m_EncryptedState)
+ {
+ m_XBOX_Version = XBOXVersion;
+ return EncryptAndCalculateCRC();
+ }
+ else return FALSE;
+}
+
+/*Encrypt with Current XBOX version by means of the SHA1 Middle Message hack..*/
+BOOL XKEEPROM::EncryptAndCalculateCRC()
+{
+ BOOL retVal = FALSE;
+ UCHAR key_hash[20]; //rc4 key initializer
+
+ XKRC4 RC4Obj;
+ XKSHA1 SHA1Obj;
+
+ if (((m_XBOX_Version == V1_0) ||(m_XBOX_Version == V1_1)||(m_XBOX_Version == V1_6)) && (!m_EncryptedState))
+ {
+ //clear and re-create data_hash from decrypted data
+ ZeroMemory(&m_EEPROMData.HMAC_SHA1_Hash, 20);
+ SHA1Obj.XBOX_HMAC_SHA1(m_XBOX_Version, (UCHAR*)&m_EEPROMData.HMAC_SHA1_Hash, &m_EEPROMData.Confounder, 8, &m_EEPROMData.HDDKkey, 20, NULL);
+
+ //calculate rc4 key initializer data from eeprom key and data_hash
+ SHA1Obj.XBOX_HMAC_SHA1(m_XBOX_Version, key_hash, &m_EEPROMData.HMAC_SHA1_Hash, 20, NULL);
+
+ XKRC4::RC4KEY RC4_key;
+
+ //initialize RC4 key
+ RC4Obj.InitRC4Key(key_hash, 20, &RC4_key);
+
+ //Encrypt data (in eeprom) with generated key
+ RC4Obj.RC4EnDecrypt ((UCHAR*)&m_EEPROMData.Confounder, 8, &RC4_key);
+ RC4Obj.RC4EnDecrypt ((UCHAR*)&m_EEPROMData.HDDKkey, 20, &RC4_key);
+
+ CalculateChecksum2();
+ CalculateChecksum3();
+
+ m_EncryptedState = TRUE;
+ retVal = TRUE;
+ }
+ else
+ {
+ retVal = FALSE;
+ m_XBOX_Version = V_NONE;
+ }
+
+ return retVal;
+
+}
+
+/*Decrypt EEPROM using auto-detect by means of the SHA1 Middle Message hack..*/
+BOOL XKEEPROM::Decrypt()
+{
+ BOOL retVal = FALSE;
+ UCHAR key_hash[20]; //rc4 key initializer
+ UCHAR data_hash_confirm[20]; //20 bytes
+ UCHAR XBOX_Version = V1_0;
+
+ XKRC4 RC4Obj;
+ XKRC4::RC4KEY RC4_key;
+ XKSHA1 SHA1Obj;
+ UCHAR eepData[0x30];
+ //struct rc4_key RC4_key;
+ //Keep the Original Data, incase the function fails we can restore it..
+ ZeroMemory(eepData, 0x30);
+ memcpy(eepData, &m_EEPROMData, 0x30);
+ UCHAR Confounder[0x8] = { 0x4c,0x70,0x33,0xcb,0x5b,0xb5,0x97,0xd2 };
+
+ while (((XBOX_Version < 13) && (!retVal)) && m_EncryptedState)
+ {
+ ZeroMemory(key_hash, 20);
+ ZeroMemory(data_hash_confirm, 20);
+ memset(&RC4_key,0,sizeof(RC4_key));
+ //calculate rc4 key initializer data from eeprom key and data_hash
+ SHA1Obj.XBOX_HMAC_SHA1(XBOX_Version, key_hash, &m_EEPROMData.HMAC_SHA1_Hash, 20, NULL);
+
+ //initialize RC4 key
+ RC4Obj.InitRC4Key(key_hash, 20, &RC4_key);
+
+ //decrypt data (from eeprom) with generated key
+ RC4Obj.RC4EnDecrypt ((UCHAR*)&m_EEPROMData.Confounder, 8, &RC4_key);
+ RC4Obj.RC4EnDecrypt ((UCHAR*)&m_EEPROMData.HDDKkey, 20, &RC4_key);
+
+ //re-create data_hash from decrypted data
+ SHA1Obj.XBOX_HMAC_SHA1(XBOX_Version, data_hash_confirm, &m_EEPROMData.Confounder, 8, &m_EEPROMData.HDDKkey, 20, NULL);
+
+ //ensure retrieved data_hash matches regenerated data_hash_confirm
+ if (strncmp((const char*)&m_EEPROMData.HMAC_SHA1_Hash,(const char*)&data_hash_confirm[0],0x14))
+ {
+ //error: hash stored in eeprom[0:19] does not match
+ //hash of data which should have been used to generate it.
+
+ //The Key used was wrong.. Restore the Data back to original
+ ZeroMemory(&m_EEPROMData, 0x30);
+ memcpy(&m_EEPROMData, eepData, 0x30);
+
+ m_XBOX_Version = V_NONE;
+ retVal = FALSE;
+ XBOX_Version++;
+ }
+ else
+ {
+ m_XBOX_Version = (XBOX_VERSION)XBOX_Version;
+ m_EncryptedState = FALSE;
+ retVal = TRUE;
+
+ }
+ }
+ return retVal;
+}
+
+
+/*Decrypt With Specific RC4 Key, then detect which xbox Version is this key from*/
+BOOL XKEEPROM::Decrypt(LPBYTE EEPROM_Key)
+{
+ BOOL retVal = FALSE;
+ UCHAR key_hash[20]; //rc4 key initializer
+ UCHAR data_hash_confirm[20]; //20 bytes
+ UCHAR XBOX_Version = V1_0;
+
+ XKRC4 RC4Obj;
+ XKRC4::RC4KEY RC4_key;
+ XKSHA1 SHA1Obj;
+ UCHAR eepData[0x30];
+
+ if (m_EncryptedState) //Can only decrypt if currently encrypted..
+ {
+ //Keep the Original Data, incase the function fails we can restore it..
+ ZeroMemory(eepData, 0x30);
+ memcpy(eepData, &m_EEPROMData, 0x30);
+
+ ZeroMemory(key_hash, 20);
+ ZeroMemory(data_hash_confirm, 20);
+
+ //calculate rc4 key initializer data from eeprom key and data_hash
+ SHA1Obj.HMAC_SHA1(key_hash, EEPROM_Key, 16, (UCHAR*)&m_EEPROMData.HMAC_SHA1_Hash, 20, NULL, 0);
+
+ //initialize RC4 key
+ RC4Obj.InitRC4Key(key_hash, 20, &RC4_key);
+
+ //decrypt data (from eeprom) with generated key
+ RC4Obj.RC4EnDecrypt ((UCHAR*)&m_EEPROMData.Confounder, 8, &RC4_key);
+ RC4Obj.RC4EnDecrypt ((UCHAR*)&m_EEPROMData.HDDKkey, 20, &RC4_key);
+
+ //re-create data_hash from decrypted data
+ SHA1Obj.HMAC_SHA1(data_hash_confirm, EEPROM_Key, 16, (UCHAR*)&m_EEPROMData.Confounder, 8, (UCHAR*)&m_EEPROMData.HDDKkey, 20);
+
+ //ensure retrieved data_hash matches regenerated data_hash_confirm
+ if (strncmp((const char*)&m_EEPROMData.HMAC_SHA1_Hash,(const char*)&data_hash_confirm[0],0x14))
+ {
+ //error: hash stored in eeprom[0:19] does not match
+ //hash of data which should have been used to generate it.
+
+ //The Key used was wrong.. Restore the Data back to original
+ ZeroMemory(&m_EEPROMData, 0x30);
+ memcpy(&m_EEPROMData, eepData, 0x30);
+
+ m_XBOX_Version = V_NONE;
+ retVal = FALSE;
+ }
+ else
+ {
+ //Key supplied is indeed correct for this eeprom..
+ //Now detect Version by simply decrypting again with auto detect..
+ ZeroMemory(&m_EEPROMData, 0x30);
+ memcpy(&m_EEPROMData, eepData, 0x30);
+ m_XBOX_Version = V_NONE;
+ retVal = Decrypt();
+ }
+ }
+ return retVal;
+}
+
+//Encapsulated variable..
+BOOL XKEEPROM::IsEncrypted()
+{
+ return m_EncryptedState;
+}
+
+//Calculate Checksum2
+void XKEEPROM::CalculateChecksum2()
+{
+ //Calculate CRC for Serial, Mac, OnlineKey, video region
+ XKCRC::QuickCRC(m_EEPROMData.Checksum2, m_EEPROMData.SerialNumber, 0x2C);
+}
+
+//Calculate Checksum3
+void XKEEPROM::CalculateChecksum3()
+{
+ //calculate CRC's for time zones, time standards, language, dvd region etc.
+ XKCRC::QuickCRC(m_EEPROMData.Checksum3, m_EEPROMData.TimeZoneBias, 0x5C);
+}
+
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKEEPROM.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKEEPROM.h
new file mode 100644
index 0000000..d6bdd13
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKEEPROM.h
@@ -0,0 +1,267 @@
+/*
+**********************************
+**********************************
+** BROUGHT TO YOU BY: **
+**********************************
+**********************************
+** **
+** [TEAM ASSEMBLY] **
+** **
+** www.team-assembly.com **
+** **
+******************************************************************************************************
+* This is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+******************************************************************************************************
+
+
+********************************************************************************************************
+** XKEEPROM.H - XBOX EEPROM Class' Header
+********************************************************************************************************
+**
+** This is the Class Header, see the .CPP file for more comments and implementation details.
+**
+********************************************************************************************************
+
+********************************************************************************************************
+** CREDITS:
+********************************************************************************************************
+** XBOX-LINUX TEAM:
+** ---------------
+** Wow, you guys are awsome !! I bow down to your greatness !! the "Friday 13th" Middle
+** Message Hack really saved our butts !!
+** REFERENCE URL: http://xbox-linux.sourceforge.net
+**
+********************************************************************************************************
+
+UPDATE LOG:
+--------------------------------------------------------------------------------------------------------
+Date: 11/27/2004
+By: Yoshihiro
+Reason: Update for xbox 1.6
+--------------------------------------------------------------------------------------------------------
+Date: 02/18/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared 0.2 for Public Release
+--------------------------------------------------------------------------------------------------------
+Date: 01/25/2003
+By: UNDEAD [team-assembly]
+Reason: Added XBOX Specific code to read EEPROM Data from Hardware
+--------------------------------------------------------------------------------------------------------
+Date: 01/06/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared for Public Release
+--------------------------------------------------------------------------------------------------------
+*/
+
+#pragma once
+#if defined (_WINDOWS)
+ #pragma message ("Compiling for WINDOWS: " __FILE__)
+ #include // MFC core and standard components
+#elif defined (_XBOX)
+ #pragma message ("Compiling for XBOX: " __FILE__)
+ #include
+ #include "XKExports.h"
+#else
+ #error ERR: Have to Define _WINDOWS or _XBOX !!
+#endif
+
+#include "XKGeneral.h"
+#include "XKRC4.h"
+#include "XKSHA1.h"
+#include "XKCRC.h"
+
+
+class XKEEPROM
+{
+public:
+ //Defines for Data structure sizes..
+ #define EEPROM_SIZE 0x100
+ #define CONFOUNDER_SIZE 0x008
+ #define HDDKEY_SIZE 0x010
+ #define XBEREGION_SIZE 0x001
+ #define SERIALNUMBER_SIZE 0x00C
+ #define MACADDRESS_SIZE 0x006
+ #define ONLINEKEY_SIZE 0x010
+ #define DVDREGION_SIZE 0x001
+ #define VIDEOSTANDARD_SIZE 0x004
+
+ //EEPROM Data structe value enums
+ enum XBOX_VERSION
+ {
+ V_NONE = 0x00,
+ V1_0 = 0x0A,
+ V1_1 = 0x0B,
+ V1_6 = 0x0C
+ };
+
+ enum DVD_ZONE
+ {
+ ZONE_NONE = 0x00,
+ ZONE1 = 0x01,
+ ZONE2 = 0x02,
+ ZONE3 = 0x03,
+ ZONE4 = 0x04,
+ ZONE5 = 0x05,
+ ZONE6 = 0x06
+ };
+
+ enum VIDEO_STANDARD
+ {
+ VID_INVALID = 0x00000000,
+ NTSC_M = 0x00400100,
+ PAL_I = 0x00800300
+ };
+
+ enum XBE_REGION
+ {
+ XBE_INVALID = 0x00,
+ NORTH_AMERICA = 0x01,
+ JAPAN = 0x02,
+ EURO_AUSTRALIA = 0x04
+ };
+
+
+ //Structure that holds contents of 256 byte EEPROM image..
+ struct EEPROMDATA
+ {
+ BYTE HMAC_SHA1_Hash[20]; // 0x00 - 0x13 HMAC_SHA1 Hash
+ BYTE Confounder[8]; // 0x14 - 0x1B RC4 Encrypted Confounder ??
+ BYTE HDDKkey[16]; // 0x1C - 0x2B RC4 Encrypted HDD key
+ BYTE XBERegion[4]; // 0x2C - 0x2F RC4 Encrypted Region code (0x01 North America, 0x02 Japan, 0x04 Europe)
+
+ BYTE Checksum2[4]; // 0x30 - 0x33 Checksum of next 44 bytes
+ UCHAR SerialNumber[12]; // 0x34 - 0x3F Xbox serial number
+ BYTE MACAddress[6]; // 0x40 - 0x45 Ethernet MAC address
+ BYTE UNKNOWN2[2]; // 0x46 - 0x47 Unknown Padding ?
+
+ BYTE OnlineKey[16]; // 0x48 - 0x57 Online Key ?
+
+ BYTE VideoStandard[4]; // 0x58 - 0x5B ** 0x00014000 = NTSC, 0x00038000 = PAL
+
+ BYTE UNKNOWN3[4]; // 0x5C - 0x5F Unknown Padding ?
+
+
+ //Comes configured up to here from factory.. everything after this can be zero'd out...
+ //To reset XBOX to Factory settings, Make checksum3 0xFFFFFFFF and zero all data below (0x64-0xFF)
+ //Doing this will Reset XBOX and upon startup will get Language & Setup screen...
+ BYTE Checksum3[4]; // 0x60 - 0x63 other Checksum of next
+
+ BYTE TimeZoneBias[4]; // 0x64 - 0x67 Zone Bias?
+ UCHAR TimeZoneStdName[4]; // 0x68 - 0x6B Standard timezone
+ UCHAR TimeZoneDltName[4]; // 0x5C - 0x6F Daylight timezone
+ BYTE UNKNOWN4[8]; // 0x70 - 0x77 Unknown Padding ?
+ BYTE TimeZoneStdDate[4]; // 0x78 - 0x7B 10-05-00-02 (Month-Day-DayOfWeek-Hour)
+ BYTE TimeZoneDltDate[4]; // 0x7C - 0x7F 04-01-00-02 (Month-Day-DayOfWeek-Hour)
+ BYTE UNKNOWN5[8]; // 0x80 - 0x87 Unknown Padding ?
+ BYTE TimeZoneStdBias[4]; // 0x88 - 0x8B Standard Bias?
+ BYTE TimeZoneDltBias[4]; // 0x8C - 0x8F Daylight Bias?
+
+ BYTE LanguageID[4]; // 0x90 - 0x93 Language ID
+
+ BYTE VideoFlags[4]; // 0x94 - 0x97 Video Settings
+ BYTE AudioFlags[4]; // 0x98 - 0x9B Audio Settings
+
+ BYTE ParentalControlGames[4]; // 0x9C - 0x9F 0=MAX rating
+ BYTE ParentalControlPwd[4]; // 0xA0 - 0xA3 7=X, 8=Y, B=LTrigger, C=RTrigger
+ BYTE ParentalControlMovies[4]; // 0xA4 - 0xA7 0=Max rating
+
+ BYTE XBOXLiveIPAddress[4]; // 0xA8 - 0xAB XBOX Live IP Address..
+ BYTE XBOXLiveDNS[4]; // 0xAC - 0xAF XBOX Live DNS Server..
+ BYTE XBOXLiveGateWay[4]; // 0xB0 - 0xB3 XBOX Live Gateway Address..
+ BYTE XBOXLiveSubNetMask[4]; // 0xB4 - 0xB7 XBOX Live Subnet Mask..
+ BYTE OtherSettings[4]; // 0xA8 - 0xBB Other XBLive settings ?
+
+ BYTE DVDPlaybackKitZone[4]; // 0xBC - 0xBF DVD Playback Kit Zone
+
+ BYTE UNKNOWN6[64]; // 0xC0 - 0xFF Unknown Codes / History ?
+ };
+ typedef EEPROMDATA* LPEEPROMDATA;
+
+ XKEEPROM(void);
+ XKEEPROM(LPEEPROMDATA pEEPROMData, BOOL Encrypted);
+ ~XKEEPROM(void);
+
+ bool ReadFromBINFile(const char* fileName, bool isEncrypted);
+ bool WriteToBINFile(const char* fileName);
+
+//very XBOX specific funtions to read/write EEPROM from hardware
+#if defined (_XBOX)
+ void ReadFromXBOX();
+ void WriteToXBOX();
+#endif
+
+ void GetEEPROMData(LPEEPROMDATA pEEPROMData);
+ void SetDecryptedEEPROMData(XBOX_VERSION Version, LPEEPROMDATA pEEPROMData);
+ void SetEncryptedEEPROMData(LPEEPROMDATA pEEPROMData);
+
+ XBOX_VERSION GetXBOXVersion();
+
+ void GetConfounderString(LPSTR Confounder, LPDWORD Length);
+ void SetConfounderString(LPCSTR Confounder);
+
+ void GetHDDKeyString(LPSTR HDDKey, LPDWORD Length);
+ void SetHDDKeyString(LPCSTR HDDKey);
+
+ void GetXBERegionString(LPSTR XBERegion, LPDWORD Length);
+ void SetXBERegionString(LPCSTR XBERegion);
+ void SetXBERegionVal(XBE_REGION RegionVal);
+ XBE_REGION GetXBERegionVal();
+
+ char* GetSerialNumberString();
+ void SetSerialNumberString(const char* SerialNumber);
+
+ char* GetMACAddressString();
+ void SetMACAddressString(const char* MACAddress);
+
+ void GetOnlineKeyString(LPSTR OnlineKey, LPDWORD Length);
+ void SetOnlineKeyString(LPCSTR OnlineKey);
+
+ void SetDVDRegionVal(unsigned int ZoneVal);
+ unsigned int GetDVDRegionVal();
+
+ void SetAudioFlagsVal(unsigned int AudioFlagsVal);
+ unsigned int GetAudioFlagsVal();
+
+ void SetVideoFlagsVal(unsigned int VideoFlagsVal);
+ unsigned int GetVideoFlagsVal();
+
+ void SetVideoStandardVal(unsigned int StandardVal);
+ unsigned int GetVideoStandardVal();
+
+ BOOL EncryptAndCalculateCRC();
+ BOOL EncryptAndCalculateCRC(XBOX_VERSION XBOXVersion);
+
+ BOOL Decrypt();
+ BOOL Decrypt(LPBYTE EEPROM_Key);
+
+ BOOL IsEncrypted();
+
+ void CalculateChecksum2();
+ void CalculateChecksum3();
+
+protected:
+ EEPROMDATA m_EEPROMData;
+ XBOX_VERSION m_XBOX_Version;
+ BOOL m_EncryptedState;
+
+};
+
+typedef XKEEPROM::XBOX_VERSION XBOX_VERSION;
+typedef XKEEPROM::DVD_ZONE DVD_ZONE;
+typedef XKEEPROM::VIDEO_STANDARD VIDEO_STANDARD;
+typedef XKEEPROM::XBE_REGION XBE_REGION;
+typedef XKEEPROM::EEPROMDATA EEPROMDATA;
+typedef XKEEPROM::LPEEPROMDATA LPEEPROMDATA;
+
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKExports.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKExports.h
new file mode 100644
index 0000000..7bd936f
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKExports.h
@@ -0,0 +1,234 @@
+/*
+**********************************
+**********************************
+** BROUGHT TO YOU BY: **
+**********************************
+**********************************
+** **
+** [TEAM ASSEMBLY] **
+** **
+** www.team-assembly.com **
+** **
+******************************************************************************************************
+* This is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+******************************************************************************************************
+
+
+********************************************************************************************************
+** XKEXPORTS.H - XBOX Kernel Exports Header
+********************************************************************************************************
+**
+** This Header containts various helpful XBOX Kernel exports and other #defines..
+** This is pretty much a work in progress and will contrinue to grow in future..
+**
+********************************************************************************************************
+
+UPDATE LOG:
+--------------------------------------------------------------------------------------------------------
+Date: 02/18/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared 0.2 for Public Release
+--------------------------------------------------------------------------------------------------------
+
+*/
+
+#pragma once
+
+
+#include
+#include "..\xboxInternals.h"
+
+#ifdef _DEBUG
+ #define OUTPUT_DEBUG_STRING(s) OutputDebugStringA(s)
+#else
+ #define OUTPUT_DEBUG_STRING(s) (VOID)(s)
+#endif
+
+#define XB_SUCCESS(Status) ((LONG)(Status) >= 0)
+
+//Defines for Symbolic Links...
+#define DriveA "\\??\\A:"
+#define DriveC "\\??\\C:"
+#define DeviceC "\\Device\\Harddisk0\\Partition2"
+#define DriveD "\\??\\D:"
+#define CdRom "\\Device\\CdRom0"
+#define DriveE "\\??\\E:"
+#define DeviceE "\\Device\\Harddisk0\\Partition1"
+#define DriveF "\\??\\F:"
+#define DeviceF "\\Device\\Harddisk0\\Partition6"
+#define DriveG "\\??\\G:"
+#define DeviceG "\\Device\\Harddisk0\\Partition7"
+#define DriveH "\\??\\H:"
+#define DeviceH "\\Device\\Harddisk0\\Partition8"
+#define DriveX "\\??\\X:"
+#define DeviceX "\\Device\\Harddisk0\\Partition3"
+#define DriveY "\\??\\Y:"
+#define DeviceY "\\Device\\Harddisk0\\Partition4"
+#define DriveZ "\\??\\Z:"
+#define DeviceZ "\\Device\\Harddisk0\\Partition5"
+
+typedef CONST SHORT CSHORT;
+
+struct XBOX_KRNL_VERSION
+{
+ WORD Major;
+ WORD Minor;
+ WORD Build;
+};
+
+//Unicode STRING
+typedef struct _STRINGX
+{
+ USHORT Length;
+ USHORT MaximumLength;
+ PSTR Buffer;
+} UNICODE_STRING, *PUNICODE_STRING, ANSI_STRING, *PANSI_STRING;
+
+//for use with IOCTL
+//typedef struct _IO_STATUS_BLOCK {
+// union
+// {
+// LONG Status;
+// LPVOID Pointer;
+// };
+//
+// LPLONG Information;
+//} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
+
+//for use with IOCTL
+
+
+
+// Flags for OBJECT_ATTRIBUTES::Attributes
+#define OBJ_INHERIT 0x00000002L
+#define OBJ_PERMANENT 0x00000010L
+#define OBJ_EXCLUSIVE 0x00000020L
+#define OBJ_OPENIF 0x00000080L
+#define OBJ_OPENLINK 0x00000100L
+#define OBJ_KERNEL_HANDLE 0x00000200L
+#define OBJ_VALID_ATTRIBUTES 0x000003F2L
+
+// Differences from NT: SECURITY_DESCRIPTOR support is gone.
+#define InitializeObjectAttributes( p, n, a, r ) { \
+ (p)->RootDirectory = r; \
+ (p)->Attributes = a; \
+ (p)->ObjectName = n; \
+ }
+
+
+// CreateDisposition values for NtCreateFile()
+#define FILE_SUPERSEDE 0x00000000
+#define FILE_OPEN 0x00000001
+#define FILE_CREATE 0x00000002
+#define FILE_OPEN_IF 0x00000003
+#define FILE_OVERWRITE 0x00000004
+#define FILE_OVERWRITE_IF 0x00000005
+#define FILE_MAXIMUM_DISPOSITION 0x00000005
+
+
+// CreateOption values for NtCreateFile()
+// FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT is what CreateFile
+// uses for most things when translating to NtCreateFile.
+#define FILE_DIRECTORY_FILE 0x00000001
+#define FILE_WRITE_THROUGH 0x00000002
+#define FILE_SEQUENTIAL_ONLY 0x00000004
+#define FILE_NO_INTERMEDIATE_BUFFERING 0x00000008
+#define FILE_SYNCHRONOUS_IO_ALERT 0x00000010
+#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020
+#define FILE_NON_DIRECTORY_FILE 0x00000040
+#define FILE_CREATE_TREE_CONNECTION 0x00000080
+#define FILE_COMPLETE_IF_OPLOCKED 0x00000100
+#define FILE_NO_EA_KNOWLEDGE 0x00000200
+#define FILE_OPEN_FOR_RECOVERY 0x00000400
+#define FILE_RANDOM_ACCESS 0x00000800
+#define FILE_DELETE_ON_CLOSE 0x00001000
+#define FILE_OPEN_BY_FILE_ID 0x00002000
+#define FILE_OPEN_FOR_BACKUP_INTENT 0x00004000
+#define FILE_NO_COMPRESSION 0x00008000
+#define FILE_RESERVE_OPFILTER 0x00100000
+#define FILE_OPEN_REPARSE_POINT 0x00200000
+#define FILE_OPEN_NO_RECALL 0x00400000
+#define FILE_OPEN_FOR_FREE_SPACE_QUERY 0x00800000
+#define FILE_COPY_STRUCTURED_STORAGE 0x00000041
+#define FILE_STRUCTURED_STORAGE 0x00000441
+#define FILE_VALID_OPTION_FLAGS 0x00ffffff
+#define FILE_VALID_PIPE_OPTION_FLAGS 0x00000032
+#define FILE_VALID_MAILSLOT_OPTION_FLAGS 0x00000032
+#define FILE_VALID_SET_FLAGS 0x00000036
+
+
+#define FILE_DEVICE_CONTROLLER 0x00000004
+#define IOCTL_SCSI_BASE FILE_DEVICE_CONTROLLER
+
+
+// Access types
+#define FILE_ANY_ACCESS 0
+#define FILE_READ_ACCESS ( 0x0001 ) // file & pipe
+#define FILE_WRITE_ACCESS ( 0x0002 ) // file & pipe
+
+// Method types
+#define METHOD_BUFFERED 0
+#define METHOD_IN_DIRECT 1
+#define METHOD_OUT_DIRECT 2
+#define METHOD_NEITHER 3
+
+// The all-important CTL_CODE
+#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
+ ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
+)
+
+//Kernel Exports for doing all the cool stuff !!
+extern "C" {
+ //XBOXAPI LONG WINAPI RtlInitAnsiString(OUT PANSI_STRING DestinationString, IN LPCSTR SourceString);
+
+
+
+// XBOXAPI LONG WINAPI NtCreateFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT IO_STATUS_BLOCK* IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions);
+
+// XBOXAPI LONG WINAPI NtDeviceIoControlFile(IN HANDLE FileHandle, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG IoControlCode, IN PVOID InputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID OutputBuffer OPTIONAL, IN ULONG OutputBufferLength);
+
+ XBOXAPI VOID WINAPI HalEnableSecureTrayEject(VOID);
+
+
+}
+
+//Some important Kernel exported Variables
+//extern "C" XBOXAPI LPVOID XepDefaultImagePath;
+//extern "C" XBOXAPI LPVOID XepLoaderLock;
+extern "C" XBOXAPI LPVOID XboxHardwareInfo;
+//extern "C" XBOXAPI LPVOID KeHasQuickBooted;
+//extern "C" XBOXAPI LPVOID ObpDosDevicesDriveLetterMap;
+//extern "C" XBOXAPI LPVOID XepDataTableEntry;
+//extern "C" XBOXAPI LPVOID FactorySettingsInfo;
+//extern "C" XBOXAPI LPVOID UserSettingsInfo;
+extern "C" XBOXAPI LPVOID ExpCdRomBootROMString;
+extern "C" XBOXAPI LPVOID ExpHardDiskBootROMString;
+extern "C" XBOXAPI LPVOID ExpHDXbdmDLL;
+
+extern "C" XBOXAPI LPVOID ExpStartDebugMonitor;
+
+extern "C" XBOXAPI LPVOID ExpTryToBootMediaROM;
+
+extern "C" XBOXAPI LPVOID ExpDVDXbdmDLL;
+extern "C" XBOXAPI LPVOID XepDashboardRedirectionPath;
+extern "C" XBOXAPI LPVOID XepDashboardImagePath;
+extern "C" XBOXAPI LPVOID ObpIoDevicesDirectoryObject;
+extern "C" XBOXAPI LPVOID ExpCdRomBootROMStringBuffer; // IdexCdRomDeviceNameBuffer;
+//extern "C" XBOXAPI LPVOID LaunchDataPage;
+// extern "C" XBOXAPI LPVOID XboxBootFlags;
+extern "C" XBOXAPI LPVOID XboxKrnlVersion;
+extern "C" XBOXAPI LPVOID XboxEEPROMKey;
+//extern "C" XBOXAPI LPVOID XboxHDKey;
+
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKGeneral.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKGeneral.cpp
new file mode 100644
index 0000000..77b3d3c
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKGeneral.cpp
@@ -0,0 +1,536 @@
+/*
+**********************************
+**********************************
+** BROUGHT TO YOU BY: **
+**********************************
+**********************************
+** **
+** [TEAM ASSEMBLY] **
+** **
+** www.team-assembly.com **
+** **
+******************************************************************************************************
+* This is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+******************************************************************************************************
+
+
+********************************************************************************************************
+** XKGENERAL.CPP - General Utility and Helper function Implementation
+********************************************************************************************************
+**
+** This Class contains mostly static helper functions to do all kinds of data/type conversions
+** and read from INI files etc.. This is a work in progress and will continue to grow..
+**
+********************************************************************************************************
+
+UPDATE LOG:
+--------------------------------------------------------------------------------------------------------
+Date: 02/18/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared 0.2 for Public Release
+--------------------------------------------------------------------------------------------------------
+Date: 01/08/2003
+By: UNDEAD [team-assembly]
+Reason: Fixed two Memory leaks - Thanks to tommyhl for spotting it!!!
+--------------------------------------------------------------------------------------------------------
+Date: 01/06/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared for Public Release
+--------------------------------------------------------------------------------------------------------
+
+*/
+
+#include
+#include "xkgeneral.h"
+
+XKGeneral::XKGeneral(void)
+{
+}
+
+XKGeneral::~XKGeneral(void)
+{
+}
+
+//This Funciton converts BYTES to a String representation of the HEX value of the Bytes
+void XKGeneral::BytesToHexStr(LPBYTE SrcBytes, DWORD byteCount, LPSTR DstString)
+{
+ BytesToHexStr(SrcBytes, byteCount, DstString, 0x00);
+}
+
+//This Funciton converts BYTES to a String representation of the HEX value of the Bytes
+//Includes a paramter to specify a seperator or Field delimiter between Hex BYTE values
+void XKGeneral::BytesToHexStr(LPBYTE SrcBytes, DWORD byteCount, LPSTR DstString, UCHAR Seperator)
+{
+ USHORT Inc = (Seperator == 0x00)?2:3;
+
+ for (ULONG i=0; i < byteCount; i++)
+ {
+ if ((UCHAR)*(SrcBytes+i) > 0x0F)
+ {
+ itoa((UCHAR)*(SrcBytes+i), DstString+(i*Inc), 16);
+ }
+ else
+ {
+ *(DstString+i*Inc) = '0';
+ itoa((UCHAR)*(SrcBytes+i), DstString+(i*Inc+1), 16);
+
+ }
+ }
+
+ if (Seperator != 0x00)
+ {
+ for (ULONG i=1; i < byteCount; i++)
+ *(DstString+i*Inc-1) = Seperator;
+ }
+
+}
+
+//This Function converts a String that Contains anyting to into
+//a String that containts ONLY valid numerical values..
+//Specify the base, eg. Hex = 16, Decimal=10 etc.
+//RemoveInvalid indacates if invalid values should be Zero or removed..
+void XKGeneral::MixedStrToDecStr(LPSTR StringData, LPDWORD StrLen, CHAR Base, BOOL RemoveInvalid)
+{
+ UCHAR DecChars[16] = HEX_VALUES;
+
+ DWORD dwSize = *StrLen;
+ DWORD currentOffset = 0;
+ LPSTR sData = new CHAR[dwSize+1];
+ ZeroMemory(sData, dwSize+1);
+ strncpy(sData, StringData, dwSize);
+
+ if (!RemoveInvalid)
+ memset(StringData, '0', dwSize);
+ else
+ ZeroMemory(StringData, dwSize);
+
+ strupr(sData);
+
+ for (DWORD i = 0; i < dwSize; i++)
+ {
+ LPSTR ChrOffset = strchr((LPCSTR)&DecChars, *(sData+i));
+ if ((ChrOffset != NULL) && ((ChrOffset - (LPSTR)&DecChars) <= Base-1))
+ {
+ memcpy(StringData+currentOffset, ChrOffset, 1);
+ currentOffset++;
+ }
+ else if (!RemoveInvalid)
+ {
+ currentOffset++;
+ }
+ }
+
+ delete[] sData;
+ *StrLen = (DWORD)strlen(StringData);
+
+}
+
+DWORD XKGeneral::HexStrToDWORD(LPBYTE StringData, LPDWORD pBufferLen, BOOL RemoveInvalid, BOOL FlipByteOrder)
+{
+ DWORD retVal = 0;
+ BYTE temp[4];
+
+
+ HexStrToBytes(StringData, pBufferLen, RemoveInvalid);
+
+ if (FlipByteOrder)
+ {
+ memcpy(temp, StringData, 4);
+ StringData[3] = temp[0];
+ StringData[2] = temp[1];
+ StringData[1] = temp[2];
+ StringData[0] = temp[3];
+ }
+
+ retVal = *((LPDWORD) StringData);
+ return retVal;
+}
+
+//This Funciton converts String representation of the HEX value into BYTES
+//RemoveInvalid indacates if invalid values should be Zero or removed..
+void XKGeneral::HexStrToBytes(LPBYTE StringData, LPDWORD pBufferLen, BOOL RemoveInvalid)
+{
+ UCHAR retVal = 0x00;
+
+ DWORD dwSize = *pBufferLen;
+ LPSTR sData = new CHAR[dwSize+1];
+
+ ZeroMemory(sData, dwSize+1);
+ strncpy(sData, (LPCSTR)StringData, dwSize);
+ ZeroMemory(StringData, dwSize);
+
+ MixedStrToDecStr(sData, &dwSize, 16, RemoveInvalid);
+
+ for (DWORD i = 0; i < dwSize/2; i++)
+ {
+ UCHAR tmpstr[3];
+ ZeroMemory(tmpstr,3);
+ memcpy(tmpstr, (LPCSTR)(sData+(i*2)), 2);
+ memset(StringData+i, (UCHAR)strtol((LPCSTR)&tmpstr, NULL, 16), 1);
+ }
+
+ delete[] sData;
+ *pBufferLen = dwSize/2;
+}
+
+//This Funciton can read from an INI file and parse out certain values from the file
+//
+// Example .INI file can contain:
+//
+// [SECTION_MAIN]
+// Value1 = "My Value"
+//
+BOOL XKGeneral::ReadINIFileItem(LPCSTR INIFileName, LPCSTR INISection, LPCSTR INIItem, LPSTR ItemValue, LPDWORD ValueLen)
+{
+ BOOL retVal = FALSE;
+ LONG retSize = 0;
+
+ HANDLE iniFile = CreateFile(INIFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (iniFile != INVALID_HANDLE_VALUE)
+ {
+ LPSTR sTempSection = NULL;
+ LPSTR sNextSection = NULL ;
+ LPSTR sTempItem = NULL;
+ ULONG sectionOffset = 0;
+ DWORD filesize = GetFileSize(iniFile, NULL);
+ BOOL foundSection = FALSE, foundItem=FALSE;
+
+ LPBYTE iniData = new BYTE[filesize+2];
+ ZeroMemory(iniData, filesize+2);
+ memset(iniData, '\n', filesize+2); //This is a cheezy trick to help not to search past end of the file..
+
+ ReadFile(iniFile, iniData, filesize, &filesize, NULL);
+
+ do
+ {
+ sTempSection = strchr((LPCSTR)iniData+sectionOffset, '[');
+ if ((sTempSection != NULL) && (strncmp(sTempSection+1, INISection, strlen(INISection)) == 0))
+ {
+ sNextSection = strchr((LPCSTR)sTempSection + strlen(INISection), '[');
+ sNextSection = (sNextSection != NULL)?sNextSection:(LPSTR)iniData + filesize;
+
+ foundSection = TRUE;
+ break;
+ }
+ sectionOffset = (ULONG)((LPBYTE)sTempSection - iniData) + 1;
+ }
+ while (sTempSection != NULL);
+
+ if (foundSection)
+ for (LPSTR finditem = sTempSection+strlen(INISection)+2; finditem < sNextSection-1; finditem = min(strchr(finditem, '\n')+1, sNextSection))
+ {
+ LPSTR snextitem = min(strchr(finditem, '\n')+1, sNextSection);
+ LPSTR spossible = strchr(finditem, *INIItem);
+ LPSTR scomment = strchr(finditem, '#');
+
+ if ((spossible!= NULL) && (scomment != NULL) && (scomment < spossible))
+ continue; //found a Commented Line..
+
+ if ((spossible!= NULL) && (spossible < snextitem))
+ finditem = spossible; //found possible match
+
+ //Check if its a sure match...
+ if (strncmp(finditem, INIItem, strlen(INIItem)) == 0)
+ {
+ foundItem = TRUE;
+
+ sTempItem = strchr(finditem+strlen(INIItem), '=') + 1;
+ LPSTR sEnd = min(strchr(sTempItem, '\n')-1, sNextSection);
+ LONG sLen = (LONG)(sEnd - sTempItem);
+ LONG sLen2 = (LONG)min((LONG)strlen(sTempItem), sLen);
+
+ if (*ValueLen >= (DWORD)sLen2)
+ {
+ ULONG startpos = 0;
+ ULONG endpos = (ULONG)sLen2;
+
+ //Do LEFT and RIGHT trim....
+ while ((*sTempItem+startpos == ' ') && (startpos < endpos))
+ startpos++;
+
+ while ((*sTempItem+endpos == ' ') && (endpos > startpos))
+ endpos--;
+
+
+ ZeroMemory(ItemValue, sLen2+1);
+ strncpy(ItemValue, sTempItem+startpos,sLen2-startpos-(sLen2-endpos));
+
+ }
+ else
+ {
+ foundSection = FALSE;
+ foundItem = FALSE;
+ }
+ retSize = (LONG)min((LONG)strlen(sTempItem), sLen);
+
+ break;
+ }
+ }
+
+ retVal = foundSection & foundItem;
+ delete[] iniData;
+ CloseHandle(iniFile);
+ }
+
+ *ValueLen = retSize;
+ return retVal;
+}
+
+//This Funciton can write value in an INI file
+//
+// Example .INI file can contain:
+//
+// [SECTION_MAIN]
+// Value1 = "My Value"
+//
+BOOL XKGeneral::WriteINIFileItem(LPCSTR INIFileName,LPCSTR INISection,LPCSTR INIItem,LPSTR ItemValue)
+{
+ char ctINIFileName[MAX_PATH+1];
+ char ctINISection[MAX_PATH+1];
+ char ctINIItem[MAX_PATH+1];
+ char ctItemValue[MAX_PATH+1];
+ char ctSearchINISection[MAX_PATH+1];
+ char ctSearchINIItem[MAX_PATH+1];
+ char ctINILine[MAX_PATH];
+ FILE *INIFile=NULL;
+ FILE *TMPFile=NULL;
+ bool bInINISection=false;
+ bool bINISectionExist=false;
+ bool bModified=false;
+
+ strcpy(ctINIFileName,INIFileName);
+ StripSpaces(ctINIFileName);
+ strcpy(ctINISection,INISection);
+ StripSpaces(ctINISection);
+ strcpy(ctINIItem,INIItem);
+ StripSpaces(ctINIItem);
+ strcpy(ctItemValue,ItemValue);
+ StripSpaces(ctItemValue);
+ sprintf(ctSearchINISection,"[%s]",ctINISection);
+ sprintf(ctSearchINIItem,"%s=",ctINIItem);
+
+ INIFile=fopen(ctINIFileName,"r+");
+ if (!INIFile) INIFile=fopen(ctINIFileName,"w+");
+ if (INIFile)
+ {
+ TMPFile=fopen("Z:\\WriteiniBackup.tmp","w+");
+ if (TMPFile)
+ {
+ while (!feof(INIFile))
+ {
+ if (!fgets(ctINILine,MAX_PATH,INIFile)) break;
+// if (fscanf(INIFile,"%s",ctINILine)==EOF) break;
+
+ StripCarriageReturn(ctINILine);
+ StripSpaces(ctINILine);
+
+ if (strlen(ctINILine))
+ {
+ if (ctINILine[0]=='['&&ctINILine[strlen(ctINILine)-1]==']')
+ {
+ if (strcmp(ctINILine,ctSearchINISection)==NULL)
+ {
+ bInINISection=true;
+ if (!bINISectionExist) bINISectionExist=true;
+ }
+ else if (bInINISection) bInINISection=false;
+ }
+ else if (bInINISection)
+ {
+ if (strncmp(ctINILine,ctSearchINIItem,strlen(ctSearchINIItem))==NULL)
+ {
+ sprintf(ctINILine,"%s%s",ctSearchINIItem,ctItemValue);
+ bModified=true;
+ }
+ }
+
+ }
+
+ if (fprintf(TMPFile,"%s\n",ctINILine)<0) break;
+
+ }
+
+ if (!bModified)
+ {
+ if (!bINISectionExist)
+ {
+ fprintf(TMPFile,"%s\n",ctSearchINISection);
+ fprintf(TMPFile,"%s%s\n",ctSearchINIItem,ctItemValue);
+ bModified=true;
+ }
+ else
+ {
+
+ bInINISection=false;
+
+ rewind(INIFile);
+ rewind(TMPFile);
+
+ while (!feof(INIFile))
+ {
+ if (!fgets(ctINILine,MAX_PATH,INIFile)) break;
+// if (fscanf(INIFile,"%s",ctINILine)==EOF) break;
+
+ StripCarriageReturn(ctINILine);
+ StripSpaces(ctINILine);
+
+ if (strlen(ctINILine)&&!bModified)
+ {
+ if (ctINILine[0]=='['&&ctINILine[strlen(ctINILine)-1]==']')
+ {
+ if (strcmp(ctINILine,ctSearchINISection)==NULL) bInINISection=true;
+ }
+ }
+
+ if (fprintf(TMPFile,"%s\n",ctINILine)<0) break;
+
+ if (bInINISection)
+ {
+ fprintf(TMPFile,"%s%s\n",ctSearchINIItem,ctItemValue);
+ bInINISection=false;
+ bModified=true;
+ }
+ }
+
+ }
+ }
+
+ rewind(INIFile);
+ rewind(TMPFile);
+
+ while (!feof(TMPFile))
+ {
+ if (!fgets(ctINILine,MAX_PATH,TMPFile)) break;
+// if (fscanf(TMPFile,"%s",ctINILine)==EOF) break;
+ StripCarriageReturn(ctINILine);
+ StripSpaces(ctINILine);
+ if (fprintf(INIFile,"%s\n",ctINILine)<0) break;
+ }
+
+ fclose(TMPFile);
+ }
+ fclose(INIFile);
+ }
+ return bModified;
+}
+
+//Strip Carriage Return Characters (10,13) From String
+void XKGeneral::StripCarriageReturn(LPSTR sString)
+{
+ for (int iInd=0;iInd<(int)strlen(sString);iInd++)
+ {
+ if (sString[iInd]==10||sString[iInd]==13)
+ {
+ sString[iInd]=0;
+ break;
+ }
+ }
+}
+
+//Strip Space Characters On Left And Right From String
+void XKGeneral::StripSpaces(LPSTR sString)
+{
+ StripLeftSpaces(sString);
+ StripRightSpaces(sString);
+}
+
+//Strip Space Characters On Left From String
+void XKGeneral::StripLeftSpaces(LPSTR sString)
+{
+ char *pcTmp=NULL;
+ int iInd;
+
+ for (iInd=0;iInd<(int)strlen(sString);iInd++)
+ {
+ if (sString[iInd]!=' ')
+ {
+ pcTmp=&sString[iInd];
+ break;
+ }
+ }
+ if (pcTmp) strcpy(sString,pcTmp);
+}
+
+//Strip Space Characters On Right From String
+void XKGeneral::StripRightSpaces(LPSTR sString)
+{
+ int iInd;
+
+ for (iInd=strlen(sString)-1;iInd>=0;iInd--)
+ {
+ if (sString[iInd]!=' ')
+ {
+ sString[++iInd]=0;
+ break;
+ }
+ }
+}
+
+//Strip quotes from mostly File Paths.. hence FILENAME_MAX
+void XKGeneral::StripQuotes(LPSTR sString, LPDWORD strLen)
+{
+ StripEnclosedChars(sString, strLen, '\"');
+}
+
+//This Function simply strips out Characters from a enclosed string..
+//Especially if reading from INI file and value is enlcosed with quotes..
+void XKGeneral::StripEnclosedChars(LPSTR sString, LPDWORD strLen, CHAR EncloseChar)
+{
+ UCHAR tmpString[FILENAME_MAX]; //Work off Max Filename.. should be big enough..
+ ZeroMemory(tmpString, FILENAME_MAX);
+
+ //get string to work with..
+ strcpy((LPSTR)tmpString, sString);
+ ZeroMemory(sString, *strLen);
+
+ LPSTR tmpFirst = strchr((LPCSTR)tmpString, EncloseChar);
+ LPSTR tmpLast = strrchr((LPCSTR)tmpString, EncloseChar);
+
+ //check if Null, if null then just beginning of string..
+ tmpFirst = (tmpFirst != NULL)?tmpFirst+1:(LPSTR)tmpString;
+
+ //check if Null, if null then just use end of string..
+ tmpLast = (tmpLast != NULL)?tmpLast:(LPSTR)tmpString+*strLen;
+
+ *strLen = (LONG)(tmpLast - tmpFirst);
+
+ if (tmpFirst != NULL)
+ strncpy(sString, tmpFirst, *strLen);
+}
+
+// Modify Lower Characters Into Upper Characters Into String
+void XKGeneral::ToUpperString(LPSTR sString)
+{
+ int iInd;
+
+ for (iInd=0;iInd<(int)strlen(sString);iInd++)
+ {
+ if (sString[iInd]>='a'&&sString[iInd]<='z') sString[iInd]=toupper(sString[iInd]);
+ else sString[iInd]=sString[iInd];
+ }
+}
+
+// Modify Upper Characters Into Lower Characters Into String
+void XKGeneral::ToLowerString(LPSTR sString)
+{
+ int iInd;
+
+ for (iInd=0;iInd<(int)strlen(sString);iInd++)
+ {
+ if (sString[iInd]>='A'&&sString[iInd]<='Z') sString[iInd]=tolower(sString[iInd]);
+ else sString[iInd]=sString[iInd];
+ }
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKGeneral.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKGeneral.h
new file mode 100644
index 0000000..cedb032
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKGeneral.h
@@ -0,0 +1,94 @@
+/*
+**********************************
+**********************************
+** BROUGHT TO YOU BY: **
+**********************************
+**********************************
+** **
+** [TEAM ASSEMBLY] **
+** **
+** www.team-assembly.com **
+** **
+******************************************************************************************************
+* This is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+******************************************************************************************************
+
+
+********************************************************************************************************
+** XKGENERAL.H - General Utility and Helper function Class' Header
+********************************************************************************************************
+**
+** This is the Class Header, see the .CPP file for more comments and implementation details.
+**
+********************************************************************************************************
+
+UPDATE LOG:
+--------------------------------------------------------------------------------------------------------
+Date: 02/18/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared 0.2 for Public Release
+--------------------------------------------------------------------------------------------------------
+Date: 01/06/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared for Public Release
+--------------------------------------------------------------------------------------------------------
+
+*/
+
+#pragma once
+#if defined (_WINDOWS)
+ #pragma message ("Compiling for WINDOWS: " __FILE__)
+ #include // MFC core and standard components
+#elif defined (_XBOX)
+ #pragma message ("Compiling for XBOX: " __FILE__)
+ #include
+#else
+ #error ERR: Have to Define _WINDOWS or _XBOX !!
+#endif
+
+#ifndef FILENAME_MAX
+ #define FILENAME_MAX 260
+#endif
+
+class XKGeneral
+{
+protected:
+ #define HEX_VALUES {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}
+
+public:
+ XKGeneral(void);
+ ~XKGeneral(void);
+
+ //Generic conversion functions..
+ static void BytesToHexStr(LPBYTE SrcBytes, DWORD byteCount, LPSTR DstString);
+ static void BytesToHexStr(LPBYTE SrcBytes, DWORD byteCount, LPSTR DstString, UCHAR Seperator);
+ static void MixedStrToDecStr(LPSTR StringData, LPDWORD StrLen, CHAR Base, BOOL RemoveInvalid);
+ static void HexStrToBytes(LPBYTE StringData, LPDWORD pBufferLen, BOOL RemoveInvalid);
+ static DWORD HexStrToDWORD(LPBYTE StringData, LPDWORD pBufferLen, BOOL RemoveInvalid, BOOL FlipByteOrder);
+
+ //Read items and values from a .INI file..
+ static BOOL ReadINIFileItem(LPCSTR INIFileName, LPCSTR INISection, LPCSTR INIItem, LPSTR ItemValue, LPDWORD ValueLen);
+ static BOOL WriteINIFileItem(LPCSTR INIFileName, LPCSTR INISection, LPCSTR INIItem, LPSTR ItemValue);
+
+ //Strip Quotes from a string..
+ static void StripLeftSpaces(LPSTR sString);
+ static void StripRightSpaces(LPSTR sString);
+ static void StripSpaces(LPSTR sString);
+ static void StripCarriageReturn(LPSTR sString);
+ static void StripEnclosedChars(LPSTR sString, LPDWORD strLen, CHAR EncloseChar);
+ static void StripQuotes(LPSTR sString, LPDWORD strLen);
+ static void ToUpperString(LPSTR sString);
+ static void ToLowerString(LPSTR sString);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKHDD.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKHDD.cpp
new file mode 100644
index 0000000..373c255
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKHDD.cpp
@@ -0,0 +1,268 @@
+/*
+**********************************
+**********************************
+** BROUGHT TO YOU BY: **
+**********************************
+**********************************
+** **
+** [TEAM ASSEMBLY] **
+** **
+** www.team-assembly.com **
+** **
+******************************************************************************************************
+* This is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+******************************************************************************************************
+
+********************************************************************************************************
+** XKHDD.CPP - Hard Disk Class Implementation
+********************************************************************************************************
+**
+** This Class contains functionality to access a IDE HDD and query it by sending ATA Commands.
+** Member helper function included to parse ATA IDENTIFY data and get HDD Serial, Model etc.
+**
+**
+********************************************************************************************************
+
+********************************************************************************************************
+** CREDITS:
+********************************************************************************************************
+** SPEEDBUMP:
+** ----------
+** My utmost greatfullness and admiration goes towards SpeedBump for all his hard work..
+** I used most of his code and converted to C++ objects etc..
+**
+** MRUEL:
+** ------
+** Thanks for the pointing us to the Pascall Code that was used for Locking/Unlocking the disk..
+** Great work on UnlockX.. keep it up !
+**
+** MARTIN GERDES:
+** --------------
+** An editor of the german "c't" magazine. The article we referenced was published in
+** c't Magazine 11/91 "Platten-Auslese - Konfiguration von AT-Bus-Platten lesen"
+** Thanks!, We ported this Pascall and ASM stuff to CPP to access the IDE Ports directly
+**
+********************************************************************************************************
+
+
+********************************************************************************************************
+** References:
+********************************************************************************************************
+**
+** ATA Specification:
+** ------------------
+** This stuff helped us a quite a bit.. so go check it out !
+** REFERENCE URL: ftp://fission.dt.wdc.com/pub/standards/ata/ata-3/ata3-r6.doc
+**
+********************************************************************************************************
+
+
+UPDATE LOG:
+--------------------------------------------------------------------------------------------------------
+Date: 02/18/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared 0.2 for Public Release
+--------------------------------------------------------------------------------------------------------
+Date: 01/06/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared for Public Release
+--------------------------------------------------------------------------------------------------------
+*/
+
+#include "XKHDD.h"
+#include "XKRC4.h"
+#include "XKSHA1.h"
+#include "..\xboxInternals.h"
+#include
+
+XKHDD::XKHDD()
+{
+}
+
+XKHDD::~XKHDD(void)
+{
+}
+
+//Byte swap the Data that comes back from ATA command.. and clean out blanks etc.
+int XKHDD::CleanATAData(unsigned char *dst, unsigned char *src, int len)
+{
+ unsigned char tmp;
+ int i;
+
+ for(i=0; i < len; i+=2)
+ {
+ tmp = src[i];
+ dst[i] = src[i+1];
+ dst[i+1] = tmp;
+ }
+
+ --dst;
+ for(i=len; i>0; --i)
+ {
+ if (dst[i] != ' ') break;
+ }
+
+ return i;
+}
+
+void XKHDD::GenerateHDDPwd(UCHAR* HDDKey, UCHAR* IDEData, UCHAR* HDDPass)
+{
+ XKSHA1 SHA1Obj;
+
+ UCHAR serial[0x14];
+ ZeroMemory(serial, 0x14);
+
+ UCHAR model[0x28];
+ ZeroMemory(model, 0x28);
+
+ UCHAR s_length = 0x14;
+ UCHAR m_length = 0x28;
+
+ s_length = CleanATAData(serial, IDEData+HDD_SERIAL_OFFSET, s_length);
+ m_length = CleanATAData(model, IDEData+HDD_MODEL_OFFSET, m_length);
+
+
+ SHA1Obj.HMAC_SHA1 (HDDPass, HDDKey, 0x10, model, m_length, serial, s_length);
+}
+
+char* XKHDD::GetIDEModel(UCHAR* IDEData)
+{
+ int length = 0x28;
+ unsigned char* model = (unsigned char*)malloc(length + 1);
+ length = CleanATAData(model, IDEData + HDD_MODEL_OFFSET, length);
+ model[length] = 0;
+ return (char*)model;
+
+}
+
+WORD XKHDD::GetIDESecurityStatus(UCHAR* IDEData)
+{
+ WORD retVal = (WORD) *(IDEData+HDD_SECURITY_STATUS_OFFSET);
+ return retVal;
+}
+
+char* XKHDD::GetIDESerial(UCHAR* IDEData)
+{
+ int length = 0x14;
+ unsigned char* serial = (unsigned char*)malloc(length + 1);
+ length = CleanATAData(serial, IDEData + HDD_SERIAL_OFFSET, length);
+ serial[length] = 0;
+ return (char*)serial;
+}
+
+//XBOX Version of Sending ATA Commands..
+//Since XBOX runs everything in Kernel Mode, we use direct port access :)
+BOOL XKHDD::SendATACommand(WORD IDEPort, LPATA_COMMAND_OBJ ATACommandObj, UCHAR ReadWrite)
+{
+ BOOL retVal = FALSE;
+ DWORD defwaitcount = 30000;
+ DWORD waitcount = defwaitcount;
+ WORD inVal=0;
+ WORD SuccessRet = 0x58;
+ WORD flgBsy = 0x80;
+
+ LPDWORD PIDEDATA = (LPDWORD) &ATACommandObj->DATA_BUFFER ;
+
+ //Write IDE Registers to IDE Port.. and in essence Execute the ATA Command..
+ _outp(IDEPort + 1, ATACommandObj->IPReg.bFeaturesReg);
+ _outp(IDEPort + 2, ATACommandObj->IPReg.bSectorCountReg);
+ _outp(IDEPort + 3, ATACommandObj->IPReg.bSectorNumberReg);
+ _outp(IDEPort + 4, ATACommandObj->IPReg.bCylLowReg);
+ _outp(IDEPort + 5, ATACommandObj->IPReg.bCylHighReg);
+ _outp(IDEPort + 6, ATACommandObj->IPReg.bDriveHeadReg);
+ _outp(IDEPort + 7, ATACommandObj->IPReg.bCommandReg);
+ Sleep(50);
+
+ //Command Executed, Check Status.. If not success, wait a while..
+ inVal = _inp(IDEPort+7);
+ while (((inVal & SuccessRet) != SuccessRet) && (waitcount > 0))
+ {
+ inVal = _inp(IDEPort+7); //Check Status..
+ KeStallExecutionProcessor(100);
+ waitcount--;
+ }
+
+
+ //IF Waitcount reaches 0 it means a TimeOut occured while waiting for command to complete
+ //This will return FALSE...
+
+
+ //Is this a IDE command that Requests Data, if so, Read the from IDE port ...
+ if ((waitcount > 0) && (ReadWrite == IDE_COMMAND_READ))
+ {
+ //Read the command return output Registers
+ ATACommandObj->OPReg.bErrorReg = _inp(IDEPort + 1);
+ ATACommandObj->OPReg.bSectorCountReg = _inp(IDEPort + 2);
+ ATACommandObj->OPReg.bSectorNumberReg = _inp(IDEPort + 3);
+ ATACommandObj->OPReg.bCylLowReg = _inp(IDEPort + 4);
+ ATACommandObj->OPReg.bCylHighReg = _inp(IDEPort + 5);
+ ATACommandObj->OPReg.bDriveHeadReg = _inp(IDEPort + 6);
+ ATACommandObj->OPReg.bStatusReg = _inp(IDEPort + 7);
+
+ ATACommandObj->DATA_BUFFSIZE = 512;
+
+ //Now read a sector (512 Bytes) from the IDE Port
+ ZeroMemory(ATACommandObj->DATA_BUFFER, 512);
+ for (int i = 0; i < 128; i++)
+ {
+ PIDEDATA[i] = _inpd(IDEPort);
+ }
+
+ waitcount = defwaitcount;
+ inVal = _inp(0x200+IDEPort+6);
+ while (((inVal & flgBsy) == flgBsy) && (waitcount > 0))
+ {
+ inVal = _inp(0x200+IDEPort+6); //Check Status..
+ KeStallExecutionProcessor(100);
+ waitcount--;
+ }
+
+ retVal = waitcount > 0;
+ }
+
+ //Is this a IDE command that Sends Data, if so, write the Data to IDE Port..
+ if ((waitcount > 0) && (ATACommandObj->DATA_BUFFSIZE > 0) && (ReadWrite == IDE_COMMAND_WRITE))
+ {
+ //Read the command return output Registers
+ ATACommandObj->OPReg.bErrorReg = _inp(IDEPort + 1);
+ ATACommandObj->OPReg.bSectorCountReg = _inp(IDEPort + 2);
+ ATACommandObj->OPReg.bSectorNumberReg = _inp(IDEPort + 3);
+ ATACommandObj->OPReg.bCylLowReg = _inp(IDEPort + 4);
+ ATACommandObj->OPReg.bCylHighReg = _inp(IDEPort + 5);
+ ATACommandObj->OPReg.bDriveHeadReg = _inp(IDEPort + 6);
+ ATACommandObj->OPReg.bStatusReg = _inp(IDEPort + 7);
+
+ //Now Write a sector (512 Bytes) To the IDE Port
+ for (int i = 0; i < 128; i++)
+ {
+ _outpd(IDEPort, PIDEDATA[i]);
+ }
+
+ waitcount = defwaitcount;
+ inVal = _inp(0x200+IDEPort+6);
+ while (((inVal & flgBsy) == flgBsy) && (waitcount > 0))
+ {
+ inVal = _inp(0x200+IDEPort+6); //Check Status..
+ KeStallExecutionProcessor(100);
+ waitcount--;
+ }
+
+ retVal = waitcount > 0;
+ }
+
+ return retVal;
+}
+
+
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKHDD.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKHDD.h
new file mode 100644
index 0000000..05b44b8
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKHDD.h
@@ -0,0 +1,183 @@
+/*
+**********************************
+**********************************
+** BROUGHT TO YOU BY: **
+**********************************
+**********************************
+** **
+** [TEAM ASSEMBLY] **
+** **
+** www.team-assembly.com **
+** **
+******************************************************************************************************
+* This is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+******************************************************************************************************
+
+
+********************************************************************************************************
+** XKHDD.H - Hard Disk Class Header
+********************************************************************************************************
+**
+** This is the Class Header, see the .CPP file for more comments and implementation details.
+** Member helper function included to parse ATA IDENTIFY data and get HDD Serial, Model etc.
+**
+**
+********************************************************************************************************
+
+********************************************************************************************************
+** CREDITS:
+********************************************************************************************************
+** SPEEDBUMP:
+** ----------
+** My utmost greatfullness and admiration goes towards SpeedBump for all his hard work..
+** I used most of his code and converted to C++ objects etc..
+**
+** MRUEL:
+** -------
+** Thanks for the pointing us to the Pascall Code that was used for Locking/Unlocking the disk..
+** Great work on UnlockX.. keep it up !
+**
+** MARTIN GERDES:
+** -------------
+** An editor of the german "c't" magazine. The article we referenced was published in
+** c't Magazine 11/91 "Platten-Auslese - Konfiguration von AT-Bus-Platten lesen"
+** Thanks!, We ported this Pascall and ASM stuff to CPP to access the IDE Ports directly
+**
+********************************************************************************************************
+
+
+********************************************************************************************************
+** References:
+********************************************************************************************************
+**
+** ATA Specification:
+** ------------------
+** This stuff helped us a quite a bit.. so go check it out !
+** REFERENCE URL: ftp://fission.dt.wdc.com/pub/standards/ata/ata-3/ata3-r6.doc
+**
+********************************************************************************************************
+
+UPDATE LOG:
+--------------------------------------------------------------------------------------------------------
+Date: 02/18/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared 0.2 for Public Release
+--------------------------------------------------------------------------------------------------------
+Date: 01/06/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared for Public Release
+--------------------------------------------------------------------------------------------------------
+
+*/
+#pragma once
+
+#include
+
+
+//Important ATA IDENTIFY Structure offsets..
+//As per ATA Spec
+#define HDD_SERIAL_OFFSET 0x014
+#define HDD_MODEL_OFFSET 0x036
+#define HDD_SECURITY_STATUS_OFFSET 0x100
+
+//IDE Port Addresses
+#define IDE_PRIMARY_PORT 0x01F0
+#define IDE_SECONDARY_PORT 0x0170
+
+//Important ATA Register Values
+//As per ATA Spec
+#define IDE_DEVICE_MASTER 0x00A0
+#define IDE_DEVICE_SLAVE 0x00B0
+
+//Important ATA/ATAPI Commands
+//As per ATA Spec
+#define IDE_ATAPI_IDENTIFY 0xA1
+#define IDE_ATA_IDENTIFY 0xEC
+
+#define IDE_ATA_SECURITY_SETPASSWORD 0xF1
+#define IDE_ATA_SECURITY_UNLOCK 0xF2
+#define IDE_ATA_SECURITY_FREEZE 0xF5
+#define IDE_ATA_SECURITY_DISABLE 0xF6
+
+//Important ATA IDENTIFY Data Structure values
+//As per ATA Spec
+#define IDE_SECURITY_SUPPORTED 0x0001
+#define IDE_SECURITY_ENABLED 0x0002
+#define IDE_SECURITY_PASSWORD_SET 0x0004
+#define IDE_SECURITY_FROZEN 0x0008
+#define IDE_SECURITY_COUNT_EXPIRED 0x0010
+#define IDE_SECURITY_LEVEL_MAX 0x0100
+
+//Important ATA Command return register values
+//As per ATA Spec
+#define IDE_ERROR_SUCCESS 0x0000
+#define IDE_ERROR_ABORT 0x0004
+
+//Our SendATACommand needs this to figure our if we should
+//read or write data to IDE registers..
+#define IDE_COMMAND_READ 0x00
+#define IDE_COMMAND_WRITE 0x01
+
+class XKHDD
+{
+public:
+
+
+ //IDE ATA Input Registers Structure
+ typedef struct IP_IDE_REG
+ {
+ BYTE bFeaturesReg;
+ BYTE bSectorCountReg;
+ BYTE bSectorNumberReg;
+ BYTE bCylLowReg;
+ BYTE bCylHighReg;
+ BYTE bDriveHeadReg;
+ BYTE bCommandReg;
+ };
+ typedef IP_IDE_REG* LPIP_IDE_REG;
+
+ //IDE ATA Output Registers Structure
+ typedef struct OP_IDE_REG
+ {
+ BYTE bErrorReg;
+ BYTE bSectorCountReg;
+ BYTE bSectorNumberReg;
+ BYTE bCylLowReg;
+ BYTE bCylHighReg;
+ BYTE bDriveHeadReg;
+ BYTE bStatusReg;
+ };
+ typedef OP_IDE_REG* LPOP_IDE_REG;
+
+ //Our own object for issuing commands..
+ //Includes in/ou register objects and 1 Sector of HDD Data
+ typedef struct ATA_COMMAND_OBJ
+ {
+ IP_IDE_REG IPReg;
+ OP_IDE_REG OPReg;
+ BYTE DATA_BUFFER[512];
+ ULONG DATA_BUFFSIZE;
+ };
+ typedef ATA_COMMAND_OBJ* LPATA_COMMAND_OBJ;
+
+ XKHDD();
+ virtual ~XKHDD(void);
+ static BOOL SendATACommand(WORD IDEPort, LPATA_COMMAND_OBJ ATACommandObj, UCHAR ReadWrite);
+ static char* GetIDEModel(UCHAR* IDEData);
+ static char* GetIDESerial(UCHAR* IDEData);
+ static WORD GetIDESecurityStatus(UCHAR* IDEData);
+ static int CleanATAData(unsigned char *dst, unsigned char *src, int len);
+ static void GenerateHDDPwd(UCHAR* HDDKey, UCHAR* IDEData, UCHAR* HDDPass);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKRC4.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKRC4.cpp
new file mode 100644
index 0000000..a2b8b9c
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKRC4.cpp
@@ -0,0 +1,130 @@
+/*
+**********************************
+**********************************
+** BROUGHT TO YOU BY: **
+**********************************
+**********************************
+** **
+** [TEAM ASSEMBLY] **
+** **
+** www.team-assembly.com **
+** **
+******************************************************************************************************
+* This is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+******************************************************************************************************
+
+********************************************************************************************************
+** XKRC4.CPP - General RC4 Encryption Class' Implementation
+********************************************************************************************************
+**
+** This is the Class Contains basic RC4 encryption functionality...
+**
+********************************************************************************************************
+
+
+********************************************************************************************************
+** CREDITS:
+********************************************************************************************************
+** SPEEDBUMP:
+** ---------
+** My utmost greatfullness and admiration goes towards SpeedBump for all his hard work..
+** I used most of his code and converted to C++ objects etc..
+**
+** XBOX-LINUX TEAM:
+** ---------------
+** Wow, you guys are awsome !! I bow down to your greatness !!
+** REFERENCE URL: http://xbox-linux.sourceforge.net
+**
+********************************************************************************************************
+
+UPDATE LOG:
+--------------------------------------------------------------------------------------------------------
+Date: 02/18/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared 0.2 for Public Release
+--------------------------------------------------------------------------------------------------------
+Date: 01/06/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared for Public Release
+--------------------------------------------------------------------------------------------------------
+
+*/
+#include "XKRC4.h"
+
+XKRC4::XKRC4(void)
+{
+}
+
+XKRC4::~XKRC4(void)
+{
+}
+
+void XKRC4::InitRC4Key(UCHAR* pRC4KeyData, int KeyLen, RC4KEY *pRC4Key)
+{
+ UCHAR index1;
+ UCHAR index2;
+ UCHAR* state;
+ short counter;
+
+ state = &pRC4Key->state[0];
+
+ for(counter = 0; counter < 256; counter++)
+ state[counter] = (UCHAR)counter;
+
+ pRC4Key->x = 0;
+ pRC4Key->y = 0;
+ index1 = 0;
+ index2 = 0;
+
+ for(counter = 0; counter < 256; counter++)
+ {
+ index2 = (pRC4KeyData[index1] + state[counter] + index2) % 256;
+ swap_byte(&state[counter], &state[index2]);
+ index1 = (index1 + 1) % KeyLen;
+ }
+}
+
+void XKRC4::RC4EnDecrypt(UCHAR* pData, int DataLen, RC4KEY *pRC4key)
+{
+ unsigned char x;
+ unsigned char y;
+ unsigned char* state;
+ unsigned char xorIndex;
+ long counter;
+
+ x = pRC4key->x;
+ y = pRC4key->y;
+ state = &pRC4key->state[0];
+
+ for(counter = 0; counter < DataLen; counter ++)
+ {
+ x = (x + 1) % 256;
+ y = (state[x] + y) % 256;
+ swap_byte(&state[x], &state[y]);
+ xorIndex = (state[x] + state[y]) % 256;
+ pData[counter] ^= state[xorIndex];
+ }
+
+ pRC4key->x = x;
+ pRC4key->y = y;
+}
+
+void XKRC4::swap_byte(unsigned char *a, unsigned char *b)
+{
+ unsigned char swapByte;
+ swapByte = *a;
+ *a = *b;
+ *b = swapByte;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKRC4.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKRC4.h
new file mode 100644
index 0000000..523a384
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKRC4.h
@@ -0,0 +1,97 @@
+/*
+**********************************
+**********************************
+** BROUGHT TO YOU BY: **
+**********************************
+**********************************
+** **
+** [TEAM ASSEMBLY] **
+** **
+** www.team-assembly.com **
+** **
+******************************************************************************************************
+* This is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+******************************************************************************************************
+
+
+********************************************************************************************************
+** XKRC4.H - General RC4 Encryption Class' Header
+********************************************************************************************************
+**
+** This is the Class Header, see the .CPP file for more comments and implementation details.
+**
+********************************************************************************************************
+
+
+********************************************************************************************************
+** CREDITS:
+********************************************************************************************************
+** SPEEDBUMP:
+** ---------
+** My utmost greatfullness and admiration goes towards SpeedBump for all his hard work..
+** I used most of his code and converted to C++ objects etc..
+**
+** XBOX-LINUX TEAM:
+** ---------------
+** Wow, you guys are awsome !! I bow down to your greatness !!
+** REFERENCE URL: http://xbox-linux.sourceforge.net
+**
+********************************************************************************************************
+
+UPDATE LOG:
+--------------------------------------------------------------------------------------------------------
+Date: 02/18/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared 0.2 for Public Release
+--------------------------------------------------------------------------------------------------------
+Date: 01/06/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared for Public Release
+--------------------------------------------------------------------------------------------------------
+
+*/
+#pragma once
+#if defined (_WINDOWS)
+ #pragma message ("Compiling for WINDOWS: " __FILE__)
+ #include // MFC core and standard components
+#elif defined (_XBOX)
+ #pragma message ("Compiling for XBOX: " __FILE__)
+ #include
+#else
+ #error ERR: Have to Define _WINDOWS or _XBOX !!
+#endif
+
+class XKRC4
+{
+protected:
+ void swap_byte(UCHAR* a, UCHAR* b);
+
+public:
+ struct RC4KEY
+ {
+ UCHAR state[256];
+ UCHAR x;
+ UCHAR y;
+ };
+
+ XKRC4(void);
+ virtual ~XKRC4(void);
+
+ void InitRC4Key(UCHAR* pRC4KeyData, int KeyLen, RC4KEY* pRC4Key);
+ void RC4EnDecrypt(UCHAR* pData, int DataLen, RC4KEY* pRC4key);
+
+
+};
+
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKSHA1.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKSHA1.cpp
new file mode 100644
index 0000000..01b4665
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKSHA1.cpp
@@ -0,0 +1,499 @@
+/*
+**********************************
+**********************************
+** BROUGHT TO YOU BY: **
+**********************************
+**********************************
+** **
+** [TEAM ASSEMBLY] **
+** **
+** www.team-assembly.com **
+** **
+******************************************************************************************************
+* This is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+******************************************************************************************************
+
+********************************************************************************************************
+** XKSHA1.CPP - SHA1 and HMAC_SHA1 Class' Implementation
+********************************************************************************************************
+**
+** This file implements the Secure Hashing Algorithm 1 as
+** defined in FIPS PUB 180-1 published April 17, 1995.
+**
+**
+** Added Funcionality to NOT require the KEY when doing HMAC_SHA1 hashes
+** as per xbox-Linux groups "Fridaym 13th Middle Message Hack"
+**
+********************************************************************************************************
+
+
+********************************************************************************************************
+** CREDITS:
+********************************************************************************************************
+** SPEEDBUMP:
+** My utmost greatfullness and admiration goes towards SpeedBump for all his hard work..
+** I used most of his code and converted to C++ objects etc..
+**
+** XBOX-LINUX TEAM:
+** ---------------
+** In particular "Franz", Wow, you guys are awsome !! I bow down to your greatness !!
+** The "Friday 13th" Middle Message Hack really saved our butts !!
+** REFERENCE URL: http://xbox-linux.sourceforge.net
+**
+********************************************************************************************************
+
+UPDATE LOG:
+--------------------------------------------------------------------------------------------------------
+Date: 02/18/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared 0.2 for Public Release
+--------------------------------------------------------------------------------------------------------
+Date: 01/06/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared for Public Release
+--------------------------------------------------------------------------------------------------------
+Date: 11/27/2004
+By: Yoshihiro
+Reason: Update for XBOX 1.6 Eeprom
+--------------------------------------------------------------------------------------------------------
+
+*/
+
+
+#include "xksha1.h"
+
+XKSHA1::XKSHA1(void)
+{
+}
+
+XKSHA1::~XKSHA1(void)
+{
+}
+
+
+int XKSHA1::SHA1Reset(SHA1Context* context)
+{
+ if (!context)
+ {
+ return shaNull;
+ }
+
+ context->Length_Low = 0;
+ context->Length_High = 0;
+ context->Message_Block_Index = 0;
+
+ context->Intermediate_Hash[0] = 0x67452301;
+ context->Intermediate_Hash[1] = 0xEFCDAB89;
+ context->Intermediate_Hash[2] = 0x98BADCFE;
+ context->Intermediate_Hash[3] = 0x10325476;
+ context->Intermediate_Hash[4] = 0xC3D2E1F0;
+
+ context->Computed = 0;
+ context->Corrupted = 0;
+
+ return shaSuccess;
+}
+
+
+int XKSHA1::SHA1Result( SHA1Context* context, UCHAR Message_Digest[SHA1HashSize])
+{
+ int i;
+
+ if (!context || !Message_Digest)
+ {
+ return shaNull;
+ }
+
+ if (context->Corrupted)
+ {
+ return context->Corrupted;
+ }
+
+ if (!context->Computed)
+ {
+ SHA1PadMessage(context);
+ for(i=0; i<64; ++i)
+ {
+ /* message may be sensitive, clear it out*/
+ context->Message_Block[i] = 0;
+ }
+
+ context->Length_Low = 0; /* and clear length */
+ context->Length_High = 0;
+ context->Computed = 1;
+
+ }
+
+ for(i = 0; i < SHA1HashSize; ++i)
+ {
+ Message_Digest[i] = context->Intermediate_Hash[i>>2] >> 8 * ( 3 - ( i & 0x03 ) );
+ }
+
+ return shaSuccess;
+}
+
+int XKSHA1::SHA1Input(SHA1Context* context, const UCHAR* message_array, unsigned int length)
+{
+ if (!length)
+ {
+ return shaSuccess;
+ }
+
+ if (!context || !message_array)
+ {
+ return shaNull;
+ }
+
+ if (context->Computed)
+ {
+ context->Corrupted = shaStateError;
+
+ return shaStateError;
+ }
+
+ if (context->Corrupted)
+ {
+ return context->Corrupted;
+ }
+
+ while(length-- && !context->Corrupted)
+ {
+ context->Message_Block[context->Message_Block_Index++] = (*message_array & 0xFF);
+
+ context->Length_Low += 8;
+
+ if (context->Length_Low == 0)
+ {
+ context->Length_High++;
+ if (context->Length_High == 0)
+ {
+ /* Message is too long */
+ context->Corrupted = 1;
+ }
+ }
+
+ if (context->Message_Block_Index == 64)
+ {
+ SHA1ProcessMessageBlock(context);
+ }
+
+ message_array++;
+ }
+
+ return shaSuccess;
+}
+
+
+
+void XKSHA1::SHA1ProcessMessageBlock(SHA1Context* context)
+{
+ const UINT32 K[] = { /* Constants defined in SHA-1 */
+ 0x5A827999,
+ 0x6ED9EBA1,
+ 0x8F1BBCDC,
+ 0xCA62C1D6
+ };
+ int t; /* Loop counter */
+ UINT32 temp; /* Temporary word value */
+ UINT32 W[80]; /* Word sequence */
+ UINT32 A, B, C, D, E; /* Word buffers */
+
+ /*
+ * Initialize the first 16 words in the array W
+ */
+ for(t = 0; t < 16; t++)
+ {
+ W[t] = context->Message_Block[t * 4] << 24;
+ W[t] |= context->Message_Block[t * 4 + 1] << 16;
+ W[t] |= context->Message_Block[t * 4 + 2] << 8;
+ W[t] |= context->Message_Block[t * 4 + 3];
+ }
+
+ for(t = 16; t < 80; t++)
+ {
+ W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
+ }
+
+ A = context->Intermediate_Hash[0];
+ B = context->Intermediate_Hash[1];
+ C = context->Intermediate_Hash[2];
+ D = context->Intermediate_Hash[3];
+ E = context->Intermediate_Hash[4];
+
+ for(t = 0; t < 20; t++)
+ {
+ temp = SHA1CircularShift(5,A) +
+ ((B & C) | ((~B) & D)) + E + W[t] + K[0];
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+
+ B = A;
+ A = temp;
+ }
+
+ for(t = 20; t < 40; t++)
+ {
+ temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ for(t = 40; t < 60; t++)
+ {
+ temp = SHA1CircularShift(5,A) +
+ ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ for(t = 60; t < 80; t++)
+ {
+ temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ context->Intermediate_Hash[0] += A;
+ context->Intermediate_Hash[1] += B;
+ context->Intermediate_Hash[2] += C;
+ context->Intermediate_Hash[3] += D;
+ context->Intermediate_Hash[4] += E;
+
+ context->Message_Block_Index = 0;
+}
+
+
+void XKSHA1::SHA1PadMessage(SHA1Context* context)
+{
+ /*
+ * Check to see if the current message block is too small to hold
+ * the initial padding bits and length. If so, we will pad the
+ * block, process it, and then continue padding into a second
+ * block.
+ */
+ if (context->Message_Block_Index > 55)
+ {
+ context->Message_Block[context->Message_Block_Index++] = 0x80;
+ while(context->Message_Block_Index < 64)
+ {
+ context->Message_Block[context->Message_Block_Index++] = 0;
+ }
+
+ SHA1ProcessMessageBlock(context);
+
+ while(context->Message_Block_Index < 56)
+ {
+ context->Message_Block[context->Message_Block_Index++] = 0;
+ }
+ }
+ else
+ {
+ context->Message_Block[context->Message_Block_Index++] = 0x80;
+ while(context->Message_Block_Index < 56)
+ {
+
+ context->Message_Block[context->Message_Block_Index++] = 0;
+ }
+ }
+
+ /*
+ * Store the message length as the last 8 octets
+ */
+ context->Message_Block[56] = context->Length_High >> 24;
+ context->Message_Block[57] = context->Length_High >> 16;
+ context->Message_Block[58] = context->Length_High >> 8;
+ context->Message_Block[59] = context->Length_High;
+ context->Message_Block[60] = context->Length_Low >> 24;
+ context->Message_Block[61] = context->Length_Low >> 16;
+ context->Message_Block[62] = context->Length_Low >> 8;
+ context->Message_Block[63] = context->Length_Low;
+
+ SHA1ProcessMessageBlock(context);
+}
+
+
+void XKSHA1::quick_SHA1( UCHAR* SHA1_result, ... )
+{
+ va_list args;
+ struct SHA1Context context;
+
+ va_start(args,SHA1_result);
+
+ SHA1Reset(&context);
+
+ while(1)
+ {
+ UCHAR* buffer = va_arg(args,UCHAR* );
+ int length;
+
+ if (buffer == NULL) break;
+
+ length = va_arg(args,int);
+
+ SHA1Input(&context,buffer,length);
+ }
+
+ SHA1Result(&context,SHA1_result);
+
+ va_end(args);
+}
+
+
+void XKSHA1::HMAC_SHA1(UCHAR* result, UCHAR* key, int key_length, UCHAR* text1, int text1_length, UCHAR* text2, int text2_length)
+{
+ UCHAR state1[0x40];
+ UCHAR state2[0x40+0x14];
+ int i;
+ struct SHA1Context context;
+
+ for(i=0x40-1; i>=key_length;--i) state1[i] = 0x36;
+ for(;i>=0;--i) state1[i] = key[i] ^ 0x36;
+
+// quick_SHA1 ( &state2[0x40],
+// state1, 0x40,
+// text1, text1_length,
+// text2, text2_length,
+// NULL );
+
+ SHA1Reset(&context);
+ SHA1Input(&context,state1,0x40);
+ SHA1Input(&context,text1,text1_length);
+ SHA1Input(&context,text2,text2_length);
+ SHA1Result(&context,&state2[0x40]);
+
+ for(i=0x40-1; i>=key_length;--i) state2[i] = 0x5C;
+ for(;i>=0;--i) state2[i] = key[i] ^ 0x5C;
+
+ //quick_SHA1 ( result,state2,0x40+0x14,NULL );
+ SHA1Reset(&context);
+ SHA1Input(&context,state2,0x40+0x14);
+ SHA1Result(&context,result);
+}
+
+
+int XKSHA1::HMAC1Reset(int version,SHA1Context *context)
+{
+ SHA1Reset(context);
+ switch (version) {
+ case 9:
+ context->Intermediate_Hash[0] = 0x85F9E51A;
+ context->Intermediate_Hash[1] = 0xE04613D2;
+ context->Intermediate_Hash[2] = 0x6D86A50C;
+ context->Intermediate_Hash[3] = 0x77C32E3C;
+ context->Intermediate_Hash[4] = 0x4BD717A4;
+ break;
+ case 10:
+ context->Intermediate_Hash[0] = 0x72127625;
+ context->Intermediate_Hash[1] = 0x336472B9;
+ context->Intermediate_Hash[2] = 0xBE609BEA;
+ context->Intermediate_Hash[3] = 0xF55E226B;
+ context->Intermediate_Hash[4] = 0x99958DAC;
+ break;
+ case 11:
+ context->Intermediate_Hash[0] = 0x39B06E79;
+ context->Intermediate_Hash[1] = 0xC9BD25E8;
+ context->Intermediate_Hash[2] = 0xDBC6B498;
+ context->Intermediate_Hash[3] = 0x40B4389D;
+ context->Intermediate_Hash[4] = 0x86BBD7ED;
+ break;
+ case 12:
+ context->Intermediate_Hash[0] = 0x8058763a;
+ context->Intermediate_Hash[1] = 0xf97d4e0e;
+ context->Intermediate_Hash[2] = 0x865a9762;
+ context->Intermediate_Hash[3] = 0x8a3d920d;
+ context->Intermediate_Hash[4] = 0x08995b2c;
+ break;
+ }
+
+ context->Length_Low = 512;
+
+ return shaSuccess;
+}
+
+int XKSHA1::HMAC2Reset(int version,SHA1Context *context)
+{
+ SHA1Reset(context);
+ switch (version) {
+ case 9:
+ context->Intermediate_Hash[0] = 0x5D7A9C6B;
+ context->Intermediate_Hash[1] = 0xE1922BEB;
+ context->Intermediate_Hash[2] = 0xB82CCDBC;
+ context->Intermediate_Hash[3] = 0x3137AB34;
+ context->Intermediate_Hash[4] = 0x486B52B3;
+ break;
+ case 10:
+ context->Intermediate_Hash[0] = 0x76441D41;
+ context->Intermediate_Hash[1] = 0x4DE82659;
+ context->Intermediate_Hash[2] = 0x2E8EF85E;
+ context->Intermediate_Hash[3] = 0xB256FACA;
+ context->Intermediate_Hash[4] = 0xC4FE2DE8;
+ break;
+ case 11:
+ context->Intermediate_Hash[0] = 0x9B49BED3;
+ context->Intermediate_Hash[1] = 0x84B430FC;
+ context->Intermediate_Hash[2] = 0x6B8749CD;
+ context->Intermediate_Hash[3] = 0xEBFE5FE5;
+ context->Intermediate_Hash[4] = 0xD96E7393;
+ break;
+ case 12:
+ context->Intermediate_Hash[0] = 0x01075307;
+ context->Intermediate_Hash[1] = 0xa2f1e037;
+ context->Intermediate_Hash[2] = 0x1186eeea;
+ context->Intermediate_Hash[3] = 0x88da9992;
+ context->Intermediate_Hash[4] = 0x168a5609;
+ break;
+ }
+ context->Length_Low = 512;
+ return shaSuccess;
+
+}
+
+
+void XKSHA1::XBOX_HMAC_SHA1(int version, UCHAR* result, ... )
+{
+ va_list args;
+ struct SHA1Context context;
+ va_start(args, result);
+
+ HMAC1Reset(version, &context);
+ while(1) {
+ unsigned char *buffer = va_arg(args,unsigned char *);
+ int length;
+
+ if (buffer == NULL) break;
+ length = va_arg(args,int);
+ SHA1Input(&context,buffer,length);
+
+ }
+ va_end(args);
+
+ SHA1Result(&context,&context.Message_Block[0]);
+
+ HMAC2Reset(version, &context);
+
+ SHA1Input(&context,&context.Message_Block[0],0x14);
+
+ SHA1Result(&context,result);
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKSHA1.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKSHA1.h
new file mode 100644
index 0000000..36abb34
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKSHA1.h
@@ -0,0 +1,134 @@
+/*
+**********************************
+**********************************
+** BROUGHT TO YOU BY: **
+**********************************
+**********************************
+** **
+** [TEAM ASSEMBLY] **
+** **
+** www.team-assembly.com **
+** **
+******************************************************************************************************
+* This is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+******************************************************************************************************
+
+
+********************************************************************************************************
+** XKSHA1.H - General SHA1 and HMAC_SHA1 Class' Header
+********************************************************************************************************
+**
+** This is the Class Header, see the .CPP file for more comments and implementation details.
+**
+** This file implements the Secure Hashing Algorithm 1 as
+** defined in FIPS PUB 180-1 published April 17, 1995.
+**
+**
+** Added Funcionality to NOT require the KEY when doing HMAC_SHA1 hashes
+** as per xbox-Linux groups "Fridaym 13th Middle Message Hack"
+**
+********************************************************************************************************
+
+
+********************************************************************************************************
+** CREDITS:
+********************************************************************************************************
+** SPEEDBUMP:
+** My utmost greatfullness and admiration goes towards SpeedBump for all his hard work..
+** I used most of his code and converted to C++ objects etc..
+**
+** XBOX-LINUX TEAM:
+** ---------------
+** In particular "Franz", Wow, you guys are awsome !! I bow down to your greatness !!
+** The "Friday 13th" Middle Message Hack really saved our butts !!
+** REFERENCE URL: http://xbox-linux.sourceforge.net
+**
+********************************************************************************************************
+
+UPDATE LOG:
+--------------------------------------------------------------------------------------------------------
+Date: 02/18/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared 0.2 for Public Release
+--------------------------------------------------------------------------------------------------------
+Date: 01/06/2003
+By: UNDEAD [team-assembly]
+Reason: Prepared for Public Release
+--------------------------------------------------------------------------------------------------------
+
+*/
+#pragma once
+#if defined (_WINDOWS)
+ #pragma message ("Compiling for WINDOWS: " __FILE__)
+ #include // MFC core and standard components
+#elif defined (_XBOX)
+ #pragma message ("Compiling for XBOX: " __FILE__)
+ #include
+ #include
+#else
+ #error ERR: Have to Define _WINDOWS or _XBOX !!
+#endif
+
+#define SHA1HashSize 20
+#define SHA1CircularShift(bits,word) \
+ (((word) << (bits)) | ((word) >> (32-(bits))))
+
+class XKSHA1
+{
+ struct SHA1Context
+ {
+ UINT32 Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */
+
+ UINT32 Length_Low; /* Message length in bits */
+ UINT32 Length_High; /* Message length in bits */
+
+ DWORD Message_Block_Index; /* Index into message block array */
+ UCHAR Message_Block[64]; /* 512-bit message blocks */
+
+ int Computed; /* Is the digest computed? */
+ int Corrupted; /* Is the message digest corrupted? */
+ };
+
+ enum
+ {
+ shaSuccess = 0,
+ shaNull, /* Null pointer parameter */
+ shaInputTooLong, /* input data too long */
+ shaStateError /* called Input after Result */
+ };
+
+public:
+ XKSHA1(void);
+ ~XKSHA1(void);
+
+ void HMAC_SHA1(UCHAR* result, UCHAR* key, int key_length, UCHAR* text1, int text1_length, UCHAR* text2, int text2_length);
+ void quick_SHA1( UCHAR* SHA1_result, ... );
+
+ //Skip the Key used from eeprom.. Kudos franz@caos.at
+ void XBOX_HMAC_SHA1(int version, UCHAR* result, ... );
+
+private:
+ int SHA1Reset(SHA1Context*);
+ int SHA1Input(SHA1Context*, const UCHAR* , unsigned int);
+ int SHA1Result(SHA1Context*, UCHAR Message_Digest[SHA1HashSize]);
+ void SHA1ProcessMessageBlock(SHA1Context* context);
+ void SHA1PadMessage(SHA1Context* context);
+
+ //Skip the Key used from eeprom.. Kudos franz@caos.at
+ int HMAC1Reset(int version,SHA1Context *context);
+ int HMAC2Reset(int version,SHA1Context *context);
+
+};
+
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKflash.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKflash.h
new file mode 100644
index 0000000..208ec90
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/XKUtils/XKflash.h
@@ -0,0 +1,378 @@
+
+#ifndef XBOXFLASH_H
+#define XBOXFLASH_H
+
+#include
+#include
+
+#define FLASH_STATUS_DQ7 0x80
+#define FLASH_STATUS_TOGGLE 0x40
+#define FLASH_STATUS_ERROR 0x20
+#define FLASH_STATUS_ERASE_TIMER 0x08
+#define FLASH_STATUS_TOGGLE_ALT 0x04
+
+#define FLASH_BASE_ADDRESS 0xff000000
+#define FLASH_UNLOCK_ADDR_1 (FLASH_BASE_ADDRESS+0x5555)
+#define FLASH_UNLOCK_ADDR_2 (FLASH_BASE_ADDRESS+0x2aaa)
+#define FLASH_UNLOCK_ADDR_3 (FLASH_BASE_ADDRESS+0x5555)
+#define FLASH_UNLOCK_ADDR_4 (FLASH_BASE_ADDRESS+0x5555)
+
+#define FLASH_UNLOCK2_ADDR_1 (FLASH_BASE_ADDRESS+0x5555)
+#define FLASH_UNLOCK2_ADDR_2 (FLASH_BASE_ADDRESS+0x5555)
+#define FLASH_UNLOCK2_ADDR_3 (FLASH_BASE_ADDRESS+0x2aaa)
+#define FLASH_UNLOCK2_ADDR_4 (FLASH_BASE_ADDRESS+0x5555)
+
+
+#define FLASH_UNLOCK_DATA_1 0xaa
+#define FLASH_UNLOCK_DATA_2 0x55
+#define FLASH_UNLOCK_DATA_3 0x90
+#define FLASH_UNLOCK_DATA_4 0xff
+
+#define FLASH_UNLOCK2_DATA_1 0xf0
+#define FLASH_UNLOCK2_DATA_2 0xaa
+#define FLASH_UNLOCK2_DATA_3 0x55
+#define FLASH_UNLOCK2_DATA_4 0xf0
+
+
+#define FLASH_COMMAND_RESET 0xf0
+#define FLASH_COMMAND_AUTOSELECT 0x90
+#define FLASH_COMMAND_PROGRAM 0xa0
+#define FLASH_COMMAND_UNLOCK_BYPASS 0x20
+#define FLASH_COMMAND_ERASE 0x80
+
+#define FLASH_COMMAND_ERASE_BLOCK 0x30
+#define FLASH_COMMAND_ERASE_ALL 0x10
+
+#define FLASH_BLOCK_COUNT 0x10
+#define FLASH_BLOCK_MASK (FLASH_BLOCK_COUNT-1)
+
+typedef struct fci_s {
+ unsigned char mfct;
+ unsigned char devc;
+ char text[30];
+ unsigned long size;
+ struct fci_s *next;
+} fci_t;
+
+class CXBoxFlash
+{
+ fci_t *flashinfo;
+ void (*UpdateStatus)(WCHAR *line1, WCHAR *line2, unsigned long addr);
+
+public:
+ CXBoxFlash()
+ {
+ flashinfo=NULL;
+ }
+
+ ~CXBoxFlash(void)
+ {
+ }
+
+ fci_t* AddFCI(BYTE manuf, BYTE code, char *text, unsigned long size)
+ {
+ fci_t *cur = flashinfo;
+
+ if(cur==NULL) {
+ flashinfo = (fci_t*)malloc(sizeof(fci_t));
+ cur=flashinfo;
+ } else {
+ while(cur->next!=NULL) cur=cur->next;
+ cur->next = (fci_t*)malloc(sizeof(fci_t));
+ cur=cur->next;
+ }
+ memset(cur, 0, sizeof(fci_t));
+
+ cur->mfct = manuf;
+ cur->devc = code;
+ strcpy(cur->text,text);
+ cur->size = size;
+
+ return cur;
+ }
+
+ fci_t* FindFCI(BYTE manuf, BYTE code)
+ {
+ fci_t *cur = flashinfo;
+
+ while(cur!=NULL) {
+ if((cur->mfct==manuf) && (cur->devc==code)) return cur;
+ cur=cur->next;
+ }
+ return NULL;
+ }
+
+ inline void Write(DWORD address,BYTE data)
+ {
+ volatile BYTE *ptr=(BYTE*)address;
+ *ptr=data;
+ }
+
+ inline BYTE Read(DWORD address)
+ {
+ volatile BYTE *ptr=(BYTE*)address;
+ return *ptr;
+ }
+
+void SetReadMode2(void)
+ {
+ // Unlock stage 1
+ Write(FLASH_UNLOCK_ADDR_1,FLASH_UNLOCK_DATA_1);
+ Write(FLASH_UNLOCK_ADDR_2,FLASH_UNLOCK_DATA_2);
+ Write(FLASH_UNLOCK_ADDR_3,FLASH_UNLOCK_DATA_3);
+ // Issue the reset
+ Write(FLASH_UNLOCK_ADDR_1,FLASH_COMMAND_RESET);
+
+ BYTE dummy=Read(FLASH_BASE_ADDRESS);
+ }
+
+fci_t* CheckID2(void)
+ {
+ BYTE manuf,code;
+
+ // Unlock stage 1
+ // detect 29xxxxxx Winbond :)
+ Write(FLASH_UNLOCK_ADDR_1,FLASH_UNLOCK_DATA_1);
+ Write(FLASH_UNLOCK_ADDR_2,FLASH_UNLOCK_DATA_2);
+ Write(FLASH_UNLOCK_ADDR_3,FLASH_UNLOCK_DATA_3);
+ // Issue the autroselect
+ Write(FLASH_UNLOCK_ADDR_3,FLASH_UNLOCK_DATA_3);
+ Write(FLASH_UNLOCK_ADDR_4,FLASH_UNLOCK_DATA_4);
+ // Detect 28xxxxxx
+ Write(FLASH_UNLOCK_ADDR_1,FLASH_COMMAND_AUTOSELECT);
+
+ manuf=Read(FLASH_BASE_ADDRESS);
+ code=Read(FLASH_BASE_ADDRESS+1);
+ SetReadMode();
+
+ return FindFCI(manuf,code);
+}
+
+void SetReadMode(void)
+ {
+ // Unlock stage 1
+ Write(FLASH_UNLOCK_ADDR_1,FLASH_UNLOCK_DATA_1);
+ Write(FLASH_UNLOCK_ADDR_2,FLASH_UNLOCK_DATA_2);
+ // Issue the reset
+ Write(FLASH_UNLOCK_ADDR_1,FLASH_COMMAND_RESET);
+
+ // Leave it in a read mode to avoid any buss contention issues
+ BYTE dummy=Read(FLASH_BASE_ADDRESS);
+ }
+
+ fci_t* CheckID(void)
+ {
+ BYTE manuf,code;
+
+ // Unlock stage 1
+ Write(FLASH_UNLOCK_ADDR_1,FLASH_UNLOCK_DATA_1);
+ Write(FLASH_UNLOCK_ADDR_2,FLASH_UNLOCK_DATA_2);
+ // Issue the autroselect
+ Write(FLASH_UNLOCK_ADDR_1,FLASH_COMMAND_AUTOSELECT);
+
+ manuf=Read(FLASH_BASE_ADDRESS);
+ code=Read(FLASH_BASE_ADDRESS+1);
+
+ // All done
+ SetReadMode();
+
+ return FindFCI(manuf,code);
+ }
+
+bool EraseBlock(int block)//int block)
+ {
+ bool retval;
+
+ // Unlock stage 1
+ Write(FLASH_UNLOCK_ADDR_1,FLASH_UNLOCK_DATA_1);
+ Write(FLASH_UNLOCK_ADDR_2,FLASH_UNLOCK_DATA_2);
+ // Issue the erase
+ Write(FLASH_UNLOCK_ADDR_1,FLASH_COMMAND_ERASE);
+ // Unlock stage 2
+ Write(FLASH_UNLOCK_ADDR_1,FLASH_UNLOCK_DATA_1);
+ Write(FLASH_UNLOCK_ADDR_2,FLASH_UNLOCK_DATA_2);
+ // Now set the block
+ Write((FLASH_UNLOCK_ADDR_1+(block&FLASH_BLOCK_MASK)),FLASH_COMMAND_ERASE_BLOCK);
+
+ // Now poll for a result
+ retval=WaitOnToggle();
+
+ // All done
+ SetReadMode();
+
+ return retval;
+ }
+bool EraseDevice(fci_t* fci)
+ {
+
+ bool retval;
+
+ // Unlock stage 1
+ Write(FLASH_UNLOCK_ADDR_1,FLASH_UNLOCK_DATA_1);
+ Write(FLASH_UNLOCK_ADDR_2,FLASH_UNLOCK_DATA_2);
+ // Issue the erase
+ Write(FLASH_UNLOCK_ADDR_1,FLASH_COMMAND_ERASE);
+ // Unlock stage 2
+ Write(FLASH_UNLOCK_ADDR_1,FLASH_UNLOCK_DATA_1);
+ Write(FLASH_UNLOCK_ADDR_2,FLASH_UNLOCK_DATA_2);
+ // Now set the block
+ Write(FLASH_UNLOCK_ADDR_1,FLASH_COMMAND_ERASE_ALL);
+
+ // Now poll for a result
+ retval=WaitOnToggle();
+
+ // All done
+ SetReadMode();
+
+ // Check it all 0xFF
+ for(DWORD address=FLASH_BASE_ADDRESS;address<(FLASH_BASE_ADDRESS+fci->size);address++)
+ {
+ if(Read(address)!=0xff)
+ {
+// WCHAR tmpW[128];
+// wsprintfW(tmpW, L"Unable to erase 0x%08x", address);
+// UpdateStatus(L"Erase Failure:", tmpW, address);
+ return false;
+ }
+ }
+
+// return retval;
+ }
+
+ bool ProgramDevice(char *filename,fci_t* fci)
+ {
+ FILE *fp;
+ BYTE data;
+ volatile BYTE dummy;
+ DWORD twiddle=0;
+ DWORD address=FLASH_BASE_ADDRESS;
+ bool retval;
+ long BinFileSize;
+
+ fp=fopen(filename,"rb");
+ if (fp==NULL) return false;
+ fseek(fp,0L,SEEK_END);
+ BinFileSize=ftell(fp);
+ fseek(fp,0L,SEEK_SET);
+
+// if (BinFileSize!=fci->size) return false;
+
+ while (fread(&data,1,sizeof(BYTE),fp)==1)
+ {
+// // Check address bound
+// if(address>=FLASH_BASE_ADDRESS+0x100000)
+// {
+// UpdateStatus(L"Programming Failure:", L"Incorrect Filesize", address);
+// fclose(fp);
+// SetReadMode();
+// return 0;
+// }
+
+ // Unlock stage 1
+ Write(FLASH_UNLOCK_ADDR_1,FLASH_UNLOCK_DATA_1);
+ Write(FLASH_UNLOCK_ADDR_2,FLASH_UNLOCK_DATA_2);
+ // Issue the program command
+ Write(FLASH_UNLOCK_ADDR_1,FLASH_COMMAND_PROGRAM);
+ // Program Byte
+ Write(address,data);
+ retval=WaitOnToggle();
+ // Do the Data polling test
+ while(1)
+ {
+ dummy=Read(address);
+
+ if((data&FLASH_STATUS_DQ7)==(dummy&FLASH_STATUS_DQ7)) break;
+
+ dummy=Read(address);
+ if((data&FLASH_STATUS_DQ7)==(dummy&FLASH_STATUS_DQ7))
+ {
+ break;
+ }
+ else
+ {
+// wsprintfW(tmpW, L"Write failure at 0x%08x", address);
+// UpdateStatus(L"Programming Failure:", tmpW, address);
+ fclose(fp);
+ SetReadMode();
+ return false;
+ }
+ }
+ Write(FLASH_UNLOCK_ADDR_1,FLASH_COMMAND_RESET);
+
+ dummy=Read(address);
+ // Verify the written byte
+ if(dummy!=data)
+ {
+// wsprintfW(tmpW, L"Verify failure at 0x%08x, Wrote 0x%02x, Read 0x%02x", address, data, dummy);
+// UpdateStatus(L"Programming Failure:", tmpW, address);
+ fclose(fp);
+ SetReadMode();
+ return false;
+ }
+
+ // Next byte
+ address++;
+
+ // User information
+// if((address&0xffff)==0x0000)
+// {
+// wsprintfW(tmpW, L"Wrote block %02d",(address>>16)&0xff);
+// UpdateStatus(L"Writing...", tmpW, address);
+// }
+ }
+
+// wsprintfW(tmpW, L"Wrote %i bytes", address && 0xffffff);
+// UpdateStatus(L"Verifying...", tmpW, address);
+
+ // Verify written code
+ int count=0;
+ fseek(fp,0,SEEK_SET);
+ address=FLASH_BASE_ADDRESS;
+ while (fread(&data,1,sizeof(BYTE),fp)==1)
+ {
+ if (data!=Read(address))
+ {
+// wsprintfW(tmpW, L"Verify failure at 0x%08x, Wrote 0x%02x, Read 0x%02x", address, data, Read(address));
+// UpdateStatus(L"Programming Failure:", tmpW, address);
+ if(count++>8) return 0;
+ }
+ address++;
+ }
+
+ fclose(fp);
+
+ if(count) {
+// UpdateStatus(L"Programming Failure:", L"One or more bytes did not write propperly.", FLASH_BASE_ADDRESS);
+ return false;
+ } else {
+// UpdateStatus(L"Programming Complete:", L"Flash Programming Successful.", address-1);
+ return true;
+ }
+ }
+
+ bool WaitOnToggle(void)
+ {
+ BYTE last,current;
+ last=Read(FLASH_BASE_ADDRESS);
+ while(1)
+ {
+ // We wait for the toggle bit to stop toggling
+ current=Read(FLASH_BASE_ADDRESS);
+ // Check for an end to toggling
+ if((last&FLASH_STATUS_TOGGLE)==(current&FLASH_STATUS_TOGGLE)) break;
+ last=current;
+
+ // We're still in command mode so its OK to check for Error condition
+ if(current&FLASH_STATUS_ERROR)
+ {
+ last=Read(FLASH_BASE_ADDRESS);
+ current=Read(FLASH_BASE_ADDRESS);
+ if((last&FLASH_STATUS_TOGGLE)==(current&FLASH_STATUS_TOGGLE)) break; else return false;
+ }
+ }
+ return true;
+ }
+
+};
+
+#endif
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/alignment.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/alignment.h
new file mode 100644
index 0000000..4ac482d
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/alignment.h
@@ -0,0 +1,8 @@
+#pragma once
+
+enum horizAlignment
+{
+ horizAlignmentLeft,
+ horizAlignmentCenter,
+ horizAlignmentRight,
+};
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/audioPlayer.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/audioPlayer.cpp
new file mode 100644
index 0000000..6fd3a7a
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/audioPlayer.cpp
@@ -0,0 +1,256 @@
+#include "audioPlayer.h"
+#include "stringUtility.h"
+#include "settingsManager.h"
+#include "fileSystem.h"
+#include "pointerMap.h"
+#include "context.h"
+#include "utils.h"
+
+#include
+#include
+
+#define STB_VORBIS_HEADER_ONLY
+#include "stb_vorbis.cpp"
+#include "stb.h"
+
+#define AUDIO_PACKETS 64
+#define AUDIO_OUTPUT_BUF_SIZE 8192
+
+extern "C"
+{
+ extern BOOL g_fDirectSoundDisableBusyWaitWarning;
+}
+
+namespace {
+
+ pointerMap* mAudioContainerMap;
+ LPDIRECTSOUND8 mDirectSoundDevice;
+ uint32_t mUniqueSoundId;
+ bool mPause;
+ CRITICAL_SECTION mPlayerMutex;
+}
+
+bool audioPlayer::init()
+{
+ InitializeCriticalSection(&mPlayerMutex);
+
+ g_fDirectSoundDisableBusyWaitWarning = TRUE;
+
+ mAudioContainerMap = new pointerMap(true);
+ mUniqueSoundId = 0;
+
+ HRESULT hr = DirectSoundCreate( NULL, &mDirectSoundDevice, NULL );
+ return SUCCEEDED(hr);
+}
+
+bool audioPlayer::close()
+{
+ for (uint32_t i = 0; i < mAudioContainerMap->count(); i++)
+ {
+ audioContainer* sound = mAudioContainerMap->get(i);
+ EnterCriticalSection(&mPlayerMutex);
+ sound->requestStop = true;
+ LeaveCriticalSection(&mPlayerMutex);
+ }
+ delete(mAudioContainerMap);
+ if (mDirectSoundDevice)
+ {
+ mDirectSoundDevice->Release();
+ mDirectSoundDevice = NULL;
+ }
+ DeleteCriticalSection(&mPlayerMutex);
+ return true;
+}
+
+uint32_t audioPlayer::play(const char* soundName, bool repeat)
+{
+ if (mPause == true || mAudioContainerMap->count() >= 20)
+ {
+ return 0;
+ }
+
+ char* soundPackPath = context::getSoundPackPath();
+ if (strlen(soundPackPath) == 0)
+ {
+ free(soundPackPath);
+ return 0;
+ }
+
+ mUniqueSoundId++;
+
+ audioContainer* sound = new audioContainer();
+ sound->id = mUniqueSoundId;
+ sound->filePath = fileSystem::combinePath(soundPackPath, soundName);
+ sound->repeat = repeat;
+ sound->requestStop = false;
+ sound->thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)process, (void*)sound, 0, NULL);
+ mAudioContainerMap->add(mUniqueSoundId, sound);
+
+ utils::debugPrint("Sound %i play start with thread handle %i\n", mUniqueSoundId, sound->thread);
+
+ free(soundPackPath);
+
+ return mUniqueSoundId;
+}
+
+bool audioPlayer::stop(uint32_t key)
+{
+ audioContainer* sound = mAudioContainerMap->get(key);
+ if (sound == NULL)
+ {
+ return false;
+ }
+
+ EnterCriticalSection(&mPlayerMutex);
+ sound->requestStop = true;
+ LeaveCriticalSection(&mPlayerMutex);
+ return true;
+}
+
+void audioPlayer::pause(bool value)
+{
+ mPause = value;
+}
+
+uint64_t WINAPI audioPlayer::process(void* param)
+{
+ audioContainer* container = (audioContainer*)param;
+ bool repeat = container->repeat;
+
+ int error;
+ stb_vorbis *vorbis = stb_vorbis_open_filename(container->filePath, &error, NULL);
+ if (vorbis == NULL)
+ {
+ return 0;
+ }
+
+ stb_vorbis_info vorbisInfo = stb_vorbis_get_info(vorbis);
+
+ WAVEFORMATEX waveFormat;
+ memset(&waveFormat, 0, sizeof(waveFormat));
+ waveFormat.wFormatTag = WAVE_FORMAT_PCM;
+ waveFormat.nChannels = vorbisInfo.channels;
+ waveFormat.nSamplesPerSec = vorbisInfo.sample_rate;
+ waveFormat.wBitsPerSample = sizeof(short) * 8;
+ waveFormat.nBlockAlign = (waveFormat.wBitsPerSample >> 3) * waveFormat.nChannels;
+ waveFormat.nAvgBytesPerSec = waveFormat.nBlockAlign * waveFormat.nSamplesPerSec;
+
+ DSSTREAMDESC streamDesc;
+ memset(&streamDesc, 0, sizeof(streamDesc));
+ streamDesc.dwMaxAttachedPackets = AUDIO_PACKETS;
+ streamDesc.lpwfxFormat = &waveFormat;
+
+ LPDIRECTSOUNDSTREAM directSoundStream;
+ mDirectSoundDevice->CreateSoundStream(&streamDesc, &directSoundStream, NULL);
+
+ float percent = repeat ? (settingsManager::getMusicVolume() / 100.0f) : (settingsManager::getSoundVolume() / 100.0f);
+ int volume = (int)(DSBVOLUME_HW_MIN * (1.0f - min(max(percent, 0.0f), 1.0f)));
+ directSoundStream->SetVolume(volume);
+ directSoundStream->SetHeadroom(0);
+
+ DSMIXBINVOLUMEPAIR mixBinVolumePair[6];
+ mixBinVolumePair[0].dwMixBin = DSMIXBIN_FRONT_LEFT;
+ mixBinVolumePair[0].lVolume = DSBVOLUME_MAX;
+ mixBinVolumePair[1].dwMixBin = DSMIXBIN_FRONT_RIGHT;
+ mixBinVolumePair[1].lVolume = DSBVOLUME_MAX;
+ mixBinVolumePair[2].dwMixBin = DSMIXBIN_FRONT_CENTER;
+ mixBinVolumePair[2].lVolume = DSBVOLUME_MIN;
+ mixBinVolumePair[3].dwMixBin = DSMIXBIN_LOW_FREQUENCY;
+ mixBinVolumePair[3].lVolume = DSBVOLUME_MIN;
+ mixBinVolumePair[4].dwMixBin = DSMIXBIN_BACK_LEFT;
+ mixBinVolumePair[4].lVolume = DSBVOLUME_MIN;
+ mixBinVolumePair[5].dwMixBin = DSMIXBIN_BACK_RIGHT;
+ mixBinVolumePair[5].lVolume = DSBVOLUME_MIN;
+
+ DSMIXBINS mixBins;
+ mixBins.dwMixBinCount = 6;
+ mixBins.lpMixBinVolumePairs = mixBinVolumePair;
+ directSoundStream->SetMixBins(&mixBins);
+
+ uint32_t* packetStatus = (uint32_t*)malloc(AUDIO_PACKETS * sizeof(uint32_t));
+ memset(packetStatus, 0, AUDIO_PACKETS * sizeof(uint32_t));
+ uint32_t* completedSize = (uint32_t*)malloc(AUDIO_PACKETS * sizeof(uint32_t));
+ memset(completedSize, 0, AUDIO_PACKETS * sizeof(uint32_t));
+
+ char* decodeBuffer = (char *)malloc(AUDIO_PACKETS * AUDIO_OUTPUT_BUF_SIZE);
+
+ utils::debugPrint("Sound %i play loop begin\n", container->id);
+
+ bool eof = false;
+ while (true)
+ {
+ EnterCriticalSection(&mPlayerMutex);
+ bool requestStop = container->requestStop;
+ LeaveCriticalSection(&mPlayerMutex);
+
+ if (mPause == true)
+ {
+ DirectSoundDoWork();
+ Sleep(10);
+ continue;
+ }
+
+ if (eof == true || requestStop == true)
+ {
+ DirectSoundDoWork();
+ Sleep(10);
+ break;
+ }
+
+ float percent = repeat ? (settingsManager::getMusicVolume() / 100.0f) : (settingsManager::getSoundVolume() / 100.0f);
+ int volume = (int)(DSBVOLUME_HW_MIN * (1.0f - min(max(percent, 0.0f), 1.0f)));
+ directSoundStream->SetVolume(volume);
+
+ for (int i = 0; i < AUDIO_PACKETS; i++)
+ {
+ if (packetStatus[i] != XMEDIAPACKET_STATUS_PENDING)
+ {
+ char *decodeBufferOffset = decodeBuffer + (i * AUDIO_OUTPUT_BUF_SIZE);
+ const int bytesRead = (int)stb_vorbis_get_samples_short_interleaved(vorbis, vorbisInfo.channels, (short*)decodeBufferOffset, AUDIO_OUTPUT_BUF_SIZE / sizeof(short)) * vorbisInfo.channels * sizeof(short);
+ if (bytesRead != AUDIO_OUTPUT_BUF_SIZE)
+ {
+ memset(decodeBufferOffset + bytesRead, 0, AUDIO_OUTPUT_BUF_SIZE - bytesRead);
+ }
+ if (bytesRead != 0)
+ {
+ XMEDIAPACKET mediaPacket;
+ memset(&mediaPacket, 0, sizeof(mediaPacket));
+ mediaPacket.pvBuffer = decodeBufferOffset;
+ mediaPacket.dwMaxSize = bytesRead;
+ mediaPacket.pdwCompletedSize = &completedSize[i];
+ mediaPacket.pdwStatus = &packetStatus[i];
+ directSoundStream->Process(&mediaPacket, NULL);
+ }
+ else if (repeat == true)
+ {
+ stb_vorbis_seek(vorbis, 0);
+ }
+ else
+ {
+ eof = true;
+ break;
+ }
+ }
+ }
+ DirectSoundDoWork();
+ Sleep(100);
+ }
+
+ int maxSamples = ((AUDIO_PACKETS * AUDIO_OUTPUT_BUF_SIZE) / sizeof(short)) / vorbisInfo.channels;
+ int waitTime = (int)(maxSamples / (vorbisInfo.sample_rate / 1000.0f));
+ Sleep(waitTime);
+
+ directSoundStream->FlushEx(0, DSSTREAMFLUSHEX_ASYNC);
+ directSoundStream->Release();
+
+ free(packetStatus);
+ free(completedSize);
+ free(decodeBuffer);
+ stb_vorbis_close(vorbis);
+
+ utils::debugPrint("Sound %i ending\n", container->id);
+
+ mAudioContainerMap->removeKey(container->id);
+
+ return 1;
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/audioPlayer.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/audioPlayer.h
new file mode 100644
index 0000000..b720090
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/audioPlayer.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#include "xboxInternals.h"
+#include "utils.h"
+
+typedef struct audioContainer
+{
+ uint32_t id;
+ char* filePath;
+ bool repeat;
+ bool requestStop;
+ HANDLE thread;
+
+ ~audioContainer()
+ {
+ utils::debugPrint("Sound %i disposing\n", id);
+ CloseHandle(thread);
+ free(filePath);
+ }
+} audioContainer;
+
+class audioPlayer
+{
+public:
+ static bool init();
+ static bool close();
+ static uint32_t play(const char* soundName, bool repeat);
+ static bool stop(uint32_t key);
+ static void pause(bool value);
+private:
+ static uint64_t WINAPI process(void* param);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/cerbiosIniHelper.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/cerbiosIniHelper.cpp
new file mode 100644
index 0000000..69a90d9
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/cerbiosIniHelper.cpp
@@ -0,0 +1,416 @@
+#include "cerbiosIniHelper.h"
+
+#include "xboxInternals.h"
+#include "stringUtility.h"
+#include "utils.h"
+#include "fileSystem.h"
+
+void cerbiosIniHelper::upperCase(char* value)
+{
+ for (uint32_t i = 0; i < (int)strlen(value); i++)
+ {
+ value[i] = (char)(value[i] >= 97 && value[i] <= 122 ? value[i] - 32 : value[i]);
+ }
+}
+
+void cerbiosIniHelper::trimSpace(char* value)
+{
+ char* pos = value;
+ int length = strlen(pos);
+
+ while (length > 0 && isspace(pos[length - 1])) {
+ pos[length - 1] = 0;
+ length--;
+ }
+
+ while (length > 0 && *pos && isspace(*pos)) {
+ ++pos;
+ --length;
+ }
+
+ memmove(value, pos, length + 1);
+}
+
+uint8_t cerbiosIniHelper::parseByte(char* value, uint8_t defaultValue)
+{
+ char* endPtr;
+ uint8_t result;
+
+ upperCase(value);
+
+ if (strncmp(value, "0X", 2) == 0)
+ {
+ result = (uint8_t)strtol(value + 2, &endPtr, 16);
+ }
+ else
+ {
+ result = (uint8_t)strtol(value, &endPtr, 10);
+ }
+
+ if (*endPtr == 0)
+ {
+ return result;
+ }
+
+ return defaultValue;
+}
+
+uint8_t cerbiosIniHelper::parseBoolean(char* value, uint8_t defaultValue)
+{
+ upperCase(value);
+ if (strcmp(value, "TRUE") == 0) {
+ return 1;
+ }
+ else if (strcmp(value, "FALSE") == 0) {
+ return 0;
+ }
+ return defaultValue;
+}
+
+void cerbiosIniHelper::parseConfigLine(cerbiosConfig* config, char* param1, char* param2, char* buffer, unsigned long bufferSize)
+{
+ char* params[2];
+ params[0] = param1;
+ params[1] = param2;
+
+ uint32_t paramLengths[2];
+ paramLengths[0] = 0;
+ paramLengths[1] = 0;
+
+ uint32_t paramIndex = 0;
+ for (uint32_t i = 0; i < bufferSize; i++) {
+ char currentChar = buffer[i];
+ if (paramIndex > 1) {
+ return;
+ }
+ else if (currentChar == '=') {
+ params[paramIndex][paramLengths[paramIndex]] = 0;
+ paramIndex++;
+ continue;
+ }
+ else if (currentChar == ';') {
+ break;
+ }
+ if (paramLengths[paramIndex] > 255) {
+ continue;
+ }
+ params[paramIndex][paramLengths[paramIndex]] = currentChar;
+ paramLengths[paramIndex] = paramLengths[paramIndex] + 1;
+ }
+ params[paramIndex][paramLengths[paramIndex]] = 0;
+
+ if (paramIndex != 1) {
+ return;
+ }
+
+ trimSpace(params[0]);
+ upperCase(params[0]);
+
+ trimSpace(params[1]);
+
+ if (strcmp(params[0], "DRIVESETUP") == 0) {
+ config->DriveSetup = parseByte(params[1], config->DriveSetup);
+ config->DriveSetup = min(max(config->DriveSetup , 0), 3);
+ }
+ else if (strcmp(params[0], "AVCHECK") == 0) {
+ config->AVCheck = parseBoolean(params[1], config->AVCheck);
+ }
+ else if (strcmp(params[0], "DEBUG") == 0) {
+ config->Debug = parseBoolean(params[1], config->Debug);
+ }
+ else if (strcmp(params[0], "CDPATH1") == 0) {
+ strncpy(config->CdPath1, params[1], 99);
+ }
+ else if (strcmp(params[0], "CDPATH2") == 0) {
+ strncpy(config->CdPath2, params[1], 99);
+ }
+ else if (strcmp(params[0], "CDPATH3") == 0) {
+ strncpy(config->CdPath3, params[1], 99);
+ }
+ else if (strcmp(params[0], "DASHPATH1") == 0) {
+ strncpy(config->DashPath1, params[1], 99);
+ }
+ else if (strcmp(params[0], "DASHPATH2") == 0) {
+ strncpy(config->DashPath2, params[1], 99);
+ }
+ else if (strcmp(params[0], "DASHPATH3") == 0) {
+ strncpy(config->DashPath3, params[1], 99);
+ }
+ else if (strcmp(params[0], "BOOTANIMPATH") == 0) {
+ strncpy(config->BootAnimPath, params[1], 99);
+ }
+ else if (strcmp(params[0], "FRONTLED") == 0 && strlen(params[1]) == 4) {
+ strncpy(config->FrontLed, params[1], 4);
+ upperCase(config->FrontLed);
+ }
+ else if (strcmp(params[0], "FANSPEED") == 0) {
+ config->FanSpeed = parseByte(params[1], config->FanSpeed);
+ }
+ else if (strcmp(params[0], "UDMAMOE") == 0) {
+ config->UdmaModeMaster = parseByte(params[1], config->UdmaModeMaster);
+ }
+ else if (strcmp(params[0], "UDMAMODEMASTER") == 0) {
+ config->UdmaModeMaster = parseByte(params[1], config->UdmaModeMaster);
+ }
+ else if (strcmp(params[0], "UDMAMODESLAVE") == 0) {
+ config->UdmaModeSlave = parseByte(params[1], config->UdmaModeSlave);
+ }
+ else if (strcmp(params[0], "FORCE480P") == 0) {
+ config->Force480p = parseBoolean(params[1], config->Force480p);
+ }
+ else if (strcmp(params[0], "FORCEVGA") == 0) {
+ config->ForceVGA = parseBoolean(params[1], config->ForceVGA);
+ }
+ else if (strcmp(params[0], "RTCENABLE") == 0) {
+ config->RtcEnable = parseBoolean(params[1], config->RtcEnable);
+ }
+ else if (strcmp(params[0], "BLOCKDASHUPDATE") == 0) {
+ config->BlockDashUpdate = parseBoolean(params[1], config->BlockDashUpdate);
+ }
+ else if (strcmp(params[0], "RESETONEJECT") == 0) {
+ config->ResetOnEject = parseBoolean(params[1], config->ResetOnEject);
+ }
+}
+
+void cerbiosIniHelper::parseConfig(cerbiosConfig* config, utils::dataContainer* configData)
+{
+ char* lineBuffer = (char*)malloc(1024);
+ char* param1 = (char*)lineBuffer + 512;
+ char* param2 = (char*)param1 + 256;
+ bool skip = FALSE;
+
+ uint32_t lineLength = 0;
+ for (uint32_t i = 0; i < configData->size; i++)
+ {
+ char currentChar = configData->data[i];
+ if (currentChar == '\t')
+ {
+ continue;
+ }
+ else if (currentChar == ';')
+ {
+ skip = true;
+ }
+ else if (currentChar == '\r' || currentChar == '\n')
+ {
+ if (lineLength > 0)
+ {
+ parseConfigLine(config, param1, param2, lineBuffer, lineLength);
+ lineLength = 0;
+ }
+ skip = false;
+ continue;
+ }
+ else if (lineLength < 512 && skip == FALSE)
+ {
+ lineBuffer[lineLength] = currentChar;
+ lineLength++;
+ }
+ }
+
+ if (lineLength > 0)
+ {
+ parseConfigLine(config, param1, param2, lineBuffer, lineLength);
+ }
+
+ free(lineBuffer);
+}
+
+cerbiosConfig cerbiosIniHelper::loadConfig()
+{
+ // Init default config
+
+ cerbiosConfig config;
+ memset(&config, 0, sizeof(config));
+ setConfigDefault(&config);
+
+ uint32_t fileHandle;
+ if (fileSystem::fileOpen("HDD0-C:\\cerbios.ini", fileSystem::FileModeRead, fileHandle))
+ {
+ uint32_t fileSize;
+ if (fileSystem::fileSize(fileHandle, fileSize))
+ {
+ char* buffer = (char*)malloc(fileSize);
+ uint32_t bytesRead;
+ if (fileSystem::fileRead(fileHandle, buffer, fileSize, bytesRead) && bytesRead == fileSize)
+ {
+ utils::dataContainer* configData;
+ configData = new utils::dataContainer(buffer, fileSize, fileSize);
+ parseConfig(&config, configData);
+ delete(configData);
+ }
+ free(buffer);
+ }
+ fileSystem::fileClose(fileHandle);
+ }
+
+ config.FanSpeed = min(((config.FanSpeed / 10) * 10), 100);
+ config.DriveSetup = min(config.DriveSetup, 3);
+ for (uint32_t i = 0; i < 4; i++)
+ {
+ char value = config.FrontLed[i];
+ if (value != 'G' && value != 'R' && value != 'A' && value != 'O')
+ {
+ config.FrontLed[i] = 'G';
+ }
+ }
+ config.UdmaModeMaster = min(config.UdmaModeMaster, 6);
+ config.UdmaModeSlave = min(config.UdmaModeSlave, 6);
+
+ return config;
+}
+
+void cerbiosIniHelper::buildConfig(cerbiosConfig* config, char* buffer)
+{
+ buffer[0] = 0;
+
+ strcat(buffer, "; Cerbios Config\r\n");
+ strcat(buffer, "\r\n");
+
+ strcat(buffer, "; Check For AV Pack\r\n");
+ strcat(buffer, "AVCheck = ");
+ strcat(buffer, config->AVCheck == 1 ? "True" : "False");
+ strcat(buffer, "\r\n");
+ strcat(buffer, "\r\n");
+
+ strcat(buffer, "; LED Ring Color, G = Green, R = Red, A = Amber, O = Off\r\n");
+ strcat(buffer, "FrontLed = ");
+ strcat(buffer, config->FrontLed);
+ strcat(buffer, "\r\n");
+ strcat(buffer, "\r\n");
+
+ strcat(buffer, "; Fan Speed 0 = Default, 10-100 = Manual Control, Supports increments of 2's\r\n");
+ strcat(buffer, "FanSpeed = ");
+ char* fanSpeed = stringUtility::formatString("%i", config->FanSpeed);
+ strcat(buffer, fanSpeed);
+ free(fanSpeed);
+ strcat(buffer, "\r\n");
+ strcat(buffer, "\r\n");
+
+ strcat(buffer, "; Drive Setup\r\n");
+ strcat(buffer, "; 0 = HDD & DVD, 1 = HDD & No DVD (Legacy Mode), 2 = HDD & No DVD (Modern Mode), 3 = Dual HDD\r\n");
+ strcat(buffer, "DriveSetup = ");
+ char* driveSetup = stringUtility::formatString("%i", config->DriveSetup);
+ strcat(buffer, driveSetup);
+ free(driveSetup);
+ strcat(buffer, "\r\n");
+ strcat(buffer, "\r\n");
+
+ strcat(buffer, "; Set Master Drive UDMA mode 0-6 on cold-boot\r\n");
+ strcat(buffer, "UdmaMode = ");
+ char* udmaMode = stringUtility::formatString("%i", config->UdmaModeMaster);
+ strcat(buffer, udmaMode);
+ strcat(buffer, "\r\n");
+ strcat(buffer, "UdmaModeMaster = ");
+ strcat(buffer, udmaMode);
+ strcat(buffer, "\r\n");
+ free(udmaMode);
+ strcat(buffer, "\r\n");
+
+ strcat(buffer, "; Set Slave Drive UDMA mode 0-6 on cold-boot (if enabled by DriveSetup = 3)\r\n");
+ strcat(buffer, "UdmaModeSlave = ");
+ char* udmaModeSlave = stringUtility::formatString("%i", config->UdmaModeSlave);
+ strcat(buffer, udmaModeSlave);
+ free(udmaModeSlave);
+ strcat(buffer, "\r\n");
+ strcat(buffer, "\r\n");
+
+ strcat(buffer, "; Enables Automatic Time Sync With Optional RTC Hardware Connected to SMBus\r\n");
+ strcat(buffer, "RtcEnable = ");
+ strcat(buffer, config->RtcEnable == 1 ? "True" : "False");
+ strcat(buffer, "\r\n");
+ strcat(buffer, "\r\n");
+
+ strcat(buffer, "; Forces AV Modes That Would Normally Be Rendered At 480i to 480p. Requires 480p Set In MS Dash And Component Cables\r\n");
+ strcat(buffer, "Force480p = ");
+ strcat(buffer, config->Force480p == 1 ? "True" : "False");
+ strcat(buffer, "\r\n");
+ strcat(buffer, "\r\n");
+
+ strcat(buffer, "; Forces VGA Modes For Component Cables Or Custom VGA Cables Using Mode(2+3) for VGA Displays Only, This Enables Force480p By Default & Sets Console To NTSC.\r\n");
+ strcat(buffer, "ForceVGA = ");
+ strcat(buffer, config->ForceVGA == 1 ? "True" : "False");
+ strcat(buffer, "\r\n");
+ strcat(buffer, "\r\n");
+
+ strcat(buffer, "; Load XDK Launcher/XBDM if it exists (Debug Bios Only)\r\n");
+ strcat(buffer, "Debug = ");
+ strcat(buffer, config->Debug == 1 ? "True" : "False");
+ strcat(buffer, "\r\n");
+ strcat(buffer, "\r\n");
+
+ strcat(buffer, "; Blocks Games From Updating The Original Xbox Dashboard, Useful for softmods.\r\n");
+ strcat(buffer, "BlockDashUpdate = ");
+ strcat(buffer, config->BlockDashUpdate == 1 ? "True" : "False");
+ strcat(buffer, "\r\n");
+ strcat(buffer, "\r\n");
+
+ strcat(buffer, "; Restore original stock xbox reset functionality when the DVD tray is ejected.\r\n");
+ strcat(buffer, "ResetOnEject = ");
+ strcat(buffer, config->ResetOnEject == 1 ? "True" : "False");
+ strcat(buffer, "\r\n");
+ strcat(buffer, "\r\n");
+
+ strcat(buffer, "; CD Paths (always falls back to D:\\default.xbe)\r\n");
+ strcat(buffer, "CdPath1 = ");
+ strcat(buffer, config->CdPath1);
+ strcat(buffer, "\r\n");
+ strcat(buffer, "CdPath2 = ");
+ strcat(buffer, config->CdPath2);
+ strcat(buffer, "\r\n");
+ strcat(buffer, "CdPath3 = ");
+ strcat(buffer, config->CdPath3);
+ strcat(buffer, "\r\n");
+ strcat(buffer, "\r\n");
+
+ strcat(buffer, "; Dash Paths (always falls back to C:\\xboxdash.xbe)\r\n");
+ strcat(buffer, "DashPath1 = ");
+ strcat(buffer, config->DashPath1);
+ strcat(buffer, "\r\n");
+ strcat(buffer, "DashPath2 = ");
+ strcat(buffer, config->DashPath2);
+ strcat(buffer, "\r\n");
+ strcat(buffer, "DashPath3 = ");
+ strcat(buffer, config->DashPath3);
+ strcat(buffer, "\r\n");
+ strcat(buffer, "\r\n");
+
+ strcat(buffer, "; Boot Animation Path (always falls back to C:\\BootAnims\\Xbox\\bootanim.xbe)\r\n");
+ strcat(buffer, "BootAnimPath = ");
+ strcat(buffer, config->BootAnimPath);
+ strcat(buffer, "\r\n");
+}
+
+void cerbiosIniHelper::saveConfig(char* buffer)
+{
+ uint32_t fileHandle;
+ if (fileSystem::fileOpen("HDD0-C:\\cerbios.ini", fileSystem::FileModeWrite, fileHandle))
+ {
+ uint32_t bytesWritten = 0;
+ fileSystem::fileWrite(fileHandle, buffer, strlen(buffer), bytesWritten);
+ fileSystem::fileClose(fileHandle);
+ }
+}
+
+void cerbiosIniHelper::setConfigDefault(cerbiosConfig* config)
+{
+ config->DriveSetup = 1;
+ config->AVCheck = 1;
+ config->Debug = 0;
+ strcpy(config->CdPath1, "");
+ strcpy(config->CdPath2, "");
+ strcpy(config->CdPath3, "");
+ strcpy(config->DashPath1, "\\Device\\Harddisk0\\Partition2\\evoxdash.xbe");
+ strcpy(config->DashPath2, "\\Device\\Harddisk0\\Partition2\\avalaunch.xbe");
+ strcpy(config->DashPath3, "\\Device\\Harddisk0\\Partition2\\nexgen.xbe");
+ strcpy(config->BootAnimPath, "\\Device\\Harddisk0\\Partition2\\BootAnims\\Xbox\\bootanim.xbe");
+ strcpy(config->FrontLed, "GGGG");
+ config->FanSpeed = 0;
+ config->UdmaModeMaster = 2;
+ config->UdmaModeSlave = 2;
+ config->Force480p = 0;
+ config->ForceVGA = 0;
+ config->RtcEnable = 0;
+ config->BlockDashUpdate = 0;
+ config->ResetOnEject = 0;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/cerbiosIniHelper.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/cerbiosIniHelper.h
new file mode 100644
index 0000000..44467c1
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/cerbiosIniHelper.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include "utils.h"
+#include "xboxInternals.h"
+
+typedef struct cerbiosConfig
+{
+ unsigned char AVCheck;
+ unsigned char Debug;
+ unsigned char DriveSetup;
+ char CdPath1[100];
+ char CdPath2[100];
+ char CdPath3[100];
+ char DashPath1[100];
+ char DashPath2[100];
+ char DashPath3[100];
+ char BootAnimPath[100];
+ char FrontLed[5];
+ unsigned char FanSpeed;
+ unsigned char UdmaModeMaster;
+ unsigned char UdmaModeSlave;
+ unsigned char Force480p;
+ unsigned char ForceVGA;
+ unsigned char RtcEnable;
+ unsigned char BlockDashUpdate;
+ unsigned char ResetOnEject;
+} cerbiosConfig;
+
+class cerbiosIniHelper
+{
+public:
+ static cerbiosConfig loadConfig();
+ static void buildConfig(cerbiosConfig* config, char* buffer);
+ static void saveConfig(char* buffer);
+ static void setConfigDefault(cerbiosConfig* config);
+private:
+ static void upperCase(char* value);
+ static void trimSpace(char* value);
+ static uint8_t parseByte(char* value, uint8_t defaultValue);
+ static uint8_t parseBoolean(char* value, uint8_t defaultValue);
+ static void parseConfigLine(cerbiosConfig* config, char* param1, char* param2, char* buffer, unsigned long bufferSize);
+ static void parseConfig(cerbiosConfig* config, utils::dataContainer* configData);
+};
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/component.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/component.cpp
new file mode 100644
index 0000000..139b5e8
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/component.cpp
@@ -0,0 +1,270 @@
+#include "component.h"
+#include "drawing.h"
+#include "ssfn.h"
+#include "theme.h"
+
+#include
+
+void component::panel(uint32_t fill, uint32_t stroke, int x, int y, int width, int height)
+{
+ drawing::drawNinePatch("panel-fill", fill, x, y, width, height);
+ drawing::drawNinePatch("panel-stroke", stroke, x, y, width, height);
+}
+
+void component::button(bool selected, bool active, const char* label, int x, int y, int width, int height)
+{
+ int textWidth;
+ int textHeight;
+ drawing::measureBitmapString(context::getBitmapFontSmall(), label, &textWidth, &textHeight);
+
+ if (active)
+ {
+ if (selected)
+ {
+ panel(theme::getButtonActiveHoverFillColor(), theme::getButtonActiveHoverStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonActiveHoverTextColor(), x + ((width - textWidth) / 2), y + ((height - textHeight) / 2) - 3);
+ }
+ else
+ {
+ panel(theme::getButtonActiveFillColor(), theme::getButtonActiveStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonActiveTextColor(), x + ((width - textWidth) / 2), y + ((height - textHeight) / 2) - 3);
+ }
+ }
+ else
+ {
+ if (selected)
+ {
+ panel(theme::getButtonInactiveHoverFillColor(), theme::getButtonInactiveHoverStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonInactiveHoverTextColor(), x + ((width - textWidth) / 2), y + ((height - textHeight) / 2) - 3);
+ }
+ else
+ {
+ panel(theme::getButtonInactiveFillColor(), theme::getButtonInactiveStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonInactiveTextColor(), x + ((width - textWidth) / 2), y + ((height - textHeight) / 2) - 3);
+ }
+ }
+}
+
+void component::splitButton(bool selected, bool active, const char* label1, int label1Width, const char* label2, int x, int y, int width, int height)
+{
+ int textWidth;
+ int textHeight;
+ drawing::measureBitmapString(context::getBitmapFontSmall(), label2, &textWidth, &textHeight);
+
+ if (active)
+ {
+ if (selected)
+ {
+ panel(theme::getButtonActiveHoverFillColor(), theme::getButtonActiveHoverStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label1, theme::getButtonActiveHoverTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label2, theme::getButtonActiveHoverTextColor(), x + 10 + label1Width, y + ((height - textHeight) / 2) - 3);
+ }
+ else
+ {
+ panel(theme::getButtonActiveFillColor(), theme::getButtonActiveStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label1, theme::getButtonActiveTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label2, theme::getButtonActiveTextColor(), x + 10 + label1Width, y + ((height - textHeight) / 2) - 3);
+ }
+ }
+ else
+ {
+ if (selected)
+ {
+ panel(theme::getButtonInactiveHoverFillColor(), theme::getButtonInactiveHoverStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label1, theme::getButtonInactiveHoverTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label2, theme::getButtonInactiveHoverTextColor(), x + 10 + label1Width, y + ((height - textHeight) / 2) - 3);
+ }
+ else
+ {
+ panel(theme::getButtonInactiveFillColor(), theme::getButtonInactiveStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label1, theme::getButtonInactiveTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label2, theme::getButtonInactiveTextColor(), x + 10 + label1Width, y + ((height - textHeight) / 2) - 3);
+ }
+ }
+}
+
+
+void component::fileButton(bool selected, bool active, bool isFile, const char* label, int x, int y, int width, int height)
+{
+ int textWidth;
+ int textHeight;
+ drawing::measureBitmapString(context::getBitmapFontSmall(), label, &textWidth, &textHeight);
+
+ if (active)
+ {
+ if (selected)
+ {
+ panel(theme::getButtonActiveHoverFillColor(), theme::getButtonActiveHoverStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonActiveHoverTextColor(), x + 30, y + ((height - textHeight) / 2) - 3);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), isFile ? "\xC2\xA6" : "\xC2\xA5", theme::getButtonActiveHoverTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ }
+ else
+ {
+ panel(theme::getButtonActiveFillColor(), theme::getButtonActiveStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonActiveTextColor(), x + 30, y + ((height - textHeight) / 2) - 3);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), isFile ? "\xC2\xA6" : "\xC2\xA5", theme::getButtonActiveTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ }
+ }
+ else
+ {
+ if (selected)
+ {
+ panel(theme::getButtonInactiveHoverFillColor(), theme::getButtonInactiveHoverStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonInactiveHoverTextColor(), x + 30, y + ((height - textHeight) / 2) - 3);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), isFile ? "\xC2\xA6" : "\xC2\xA5", theme::getButtonInactiveHoverTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ }
+ else
+ {
+ panel(theme::getButtonInactiveFillColor(), theme::getButtonInactiveStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonInactiveTextColor(), x + 30, y + ((height - textHeight) / 2) - 3);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), isFile ? "\xC2\xA6" : "\xC2\xA5", theme::getButtonInactiveTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ }
+ }
+}
+
+void component::ledButton(bool selected, uint8_t ledColor, const char* label, int x, int y, int width, int height)
+{
+ int textWidth;
+ int textHeight;
+ drawing::measureBitmapString(context::getBitmapFontSmall(), label, &textWidth, &textHeight);
+
+ if (selected)
+ {
+ if (ledColor == 0)
+ {
+ panel(theme::getButtonLedOffHoverFillColor(), theme::getButtonLedOffHoverStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonLedOffHoverTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ }
+ else if (ledColor == 1)
+ {
+ panel(theme::getButtonLedRedHoverFillColor(), theme::getButtonLedRedHoverStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonLedRedHoverTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ }
+ else if (ledColor == 2)
+ {
+ panel(theme::getButtonLedGreenHoverFillColor(), theme::getButtonLedGreenHoverStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonLedGreenHoverTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ }
+ else if (ledColor == 3)
+ {
+ panel(theme::getButtonLedYellowHoverFillColor(), theme::getButtonLedYellowHoverStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonLedYellowHoverTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ }
+ else if (ledColor == 4)
+ {
+ panel(theme::getButtonLedBlueHoverFillColor(),theme::getButtonLedBlueHoverStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonLedBlueHoverTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ }
+ else if (ledColor == 5)
+ {
+ panel(theme::getButtonLedPurpleHoverFillColor(),theme::getButtonLedPurpleHoverStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonLedPurpleHoverTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ }
+ else if (ledColor == 6)
+ {
+ panel(theme::getButtonLedTurquoiseHoverFillColor(), theme::getButtonLedTurquoiseHoverStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonLedTurquoiseHoverTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ }
+ else if (ledColor == 7)
+ {
+ panel(theme::getButtonLedWhiteHoverFillColor(), theme::getButtonLedWhiteHoverStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonLedWhiteHoverTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ }
+ }
+ else
+ {
+ if (ledColor == 0)
+ {
+ panel(theme::getButtonLedOffFillColor(), theme::getButtonLedOffStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonLedOffTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ }
+ else if (ledColor == 1)
+ {
+ panel(theme::getButtonLedRedFillColor(), theme::getButtonLedRedStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonLedRedTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ }
+ else if (ledColor == 2)
+ {
+ panel(theme::getButtonLedGreenFillColor(), theme::getButtonLedGreenStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonLedGreenTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ }
+ else if (ledColor == 3)
+ {
+ panel(theme::getButtonLedYellowFillColor(), theme::getButtonLedYellowStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonLedYellowTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ }
+ else if (ledColor == 4)
+ {
+ panel(theme::getButtonLedBlueFillColor(), theme::getButtonLedBlueStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonLedBlueTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ }
+ else if (ledColor == 5)
+ {
+ panel(theme::getButtonLedPurpleFillColor(), theme::getButtonLedPurpleStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonLedPurpleTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ }
+ else if (ledColor == 6)
+ {
+ panel(theme::getButtonLedTurquoiseFillColor(), theme::getButtonLedTurquoiseStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonLedTurquoiseTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ }
+ else if (ledColor == 7)
+ {
+ panel(theme::getButtonLedWhiteFillColor(), theme::getButtonLedWhiteStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, theme::getButtonLedWhiteTextColor(), x + 10, y + ((height - textHeight) / 2) - 3);
+ }
+ }
+}
+
+void component::text(const char* label, bool disabled, horizAlignment hAlign, int x, int y, int width, int height)
+{
+ int textWidth;
+ int textHeight;
+ drawing::measureBitmapString(context::getBitmapFontSmall(), label, &textWidth, &textHeight);
+
+ int xPos = x;
+ if (hAlign == horizAlignmentCenter)
+ {
+ xPos = x + ((width - textWidth) / 2);
+ }
+ else if (hAlign == horizAlignmentRight)
+ {
+ xPos = x + (width - textWidth);
+ }
+
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, disabled ? theme::getTextDisabledColor() : theme::getTextColor(), xPos, y + ((height - textHeight) / 2) - 3);
+}
+
+void component::textBox(const char* label, bool selected, bool disabled, horizAlignment hAlign, int x, int y, int width, int height, bool vAlignTop, bool solidBg)
+{
+ int textWidth;
+ int textHeight;
+ drawing::measureBitmapString(context::getBitmapFontSmall(), label, &textWidth, &textHeight);
+
+ int xPos = x + 16;
+ if (hAlign == horizAlignmentCenter)
+ {
+ xPos = x + ((width - textWidth) / 2);
+ }
+ else if (hAlign == horizAlignmentRight)
+ {
+ xPos = (x + 16) + ((width - 32) - textWidth);
+ }
+
+ int yPos = vAlignTop ? (y + 16 - 3) : (y + ((height - textHeight) / 2) - 3);
+ if (selected == true)
+ {
+ uint32_t fillColor = theme::getTextPanelHoverFillColor();
+ if(solidBg) fillColor |= 0xff000000;
+ panel(fillColor, theme::getTextPanelHoverStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, disabled ? theme::getTextDisabledColor() : theme::getTextPanelHoverTextColor(), xPos, yPos);
+ }
+ else
+ {
+ uint32_t fillColor = theme::getTextPanelHoverFillColor();
+ if(solidBg) fillColor |= 0xff000000;
+ panel(fillColor, theme::getTextPanelStrokeColor(), x, y, width, height);
+ drawing::drawBitmapString(context::getBitmapFontSmall(), label, disabled ? theme::getTextDisabledColor() : theme::getTextPanelTextColor(), xPos, yPos);
+ }
+
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/component.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/component.h
new file mode 100644
index 0000000..2a91cd7
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/component.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "xboxInternals.h"
+#include "alignment.h"
+
+#include
+
+class component
+{
+public:
+ static void panel(uint32_t fill, uint32_t stroke, int x, int y, int width, int height);
+ static void button(bool selected, bool active, const char* label, int x, int y, int width, int height);
+ static void splitButton(bool selected, bool active, const char* label1, int label1Width, const char* label2, int x, int y, int width, int height);
+ static void fileButton(bool selected, bool active, bool isFile, const char* label, int x, int y, int width, int height);
+ static void ledButton(bool selected, uint8_t ledColor, const char* label, int x, int y, int width, int height);
+ static void text(const char* label, bool disabled, horizAlignment hAlign, int x, int y, int width, int height);
+ static void textBox(const char* label, bool selected, bool disabled, horizAlignment hAlign, int x, int y, int width, int height, bool vAlignTop = false, bool solidBg = false);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/context.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/context.cpp
new file mode 100644
index 0000000..687cf45
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/context.cpp
@@ -0,0 +1,352 @@
+#include "context.h"
+#include "inputManager.h"
+#include "pointerMap.h"
+#include "modchip.h"
+#include "globalTypes.h"
+#include "modchipDummy.h"
+#include "modchipXenium.h"
+#include "modchipXecuter.h"
+#include "modchipSmartxx.h"
+#include "modchipModxo.h"
+#include "modchipAladdin1mb.h"
+#include "modchipAladdin2mb.h"
+#include "modchipXchanger.h"
+
+namespace
+{
+ modchip* mModchip;
+ modchipType mModchipType;
+ char* mCurrentIp = NULL;
+ uint32_t mCurrentFreeMem = NULL;
+ char* mCurrentTitle = NULL;
+ uint32_t mCurrentFanSpeed = 0;
+ uint32_t mCurrentCpuTemp = 0;
+ uint32_t mCurrentMbTemp = 0;
+ bool mNetworkInitialized;
+ LPDIRECT3DDEVICE8 mD3dDevice;
+ int32_t mBufferWidth;
+ int32_t mBufferHeight;
+ int32_t mBufferPitch;
+ int32_t* mBuffer;
+ pointerMap* mImageMap = NULL;
+ bitmapFont* mBitmapFontSmall = NULL;
+ bitmapFont* mBitmapFontMedium = NULL;
+ bitmapFont* mBitmapFontLarge = NULL;
+ char* mSoundPackPath = NULL;
+ uint32_t mMusicId;
+ utils::dataContainer* mMasterPassword = NULL;
+ utils::dataContainer* mUserPassword = NULL;
+ char* mDriveModel = NULL;
+ char* mDriveSerial = NULL;
+ bool mTakeScreenshot = false;
+ utils::dataContainer* mScreenshot = NULL;
+ CRITICAL_SECTION mMutex;
+}
+
+modchip* context::getModchip()
+{
+ return mModchip;
+}
+
+
+void context::setModchipType(modchipType modchipType)
+{
+ if (mModchip != NULL)
+ {
+ delete(mModchip);
+ }
+ if (modchipType == modchipTypeXenium)
+ {
+ mModchip = new modchipXenium();
+ }
+ else if (modchipType == modchipTypeXecuter)
+ {
+ mModchip = new modchipXecuter();
+ }
+ else if (modchipType == modchipTypeSmartxx)
+ {
+ mModchip = new modchipSmartxx();
+ }
+ else if (modchipType == modchipTypeModxo)
+ {
+ mModchip = new modchipModxo();
+ }
+ else if (modchipType == modchipTypeAladdin1mb)
+ {
+ mModchip = new modchipAladdin1mb();
+ }
+ else if (modchipType == modchipTypeAladdin2mb)
+ {
+ mModchip = new modchipAladdin2mb();
+ }
+ else if (modchipType == modchipTypeXchanger)
+ {
+ mModchip = new modchipXchanger();
+ }
+ else if (modchipType == modchipTypeDummy)
+ {
+ mModchip = new modchipDummy();
+ }
+ mModchipType = modchipType;
+}
+
+modchipType context::getModchipType()
+{
+ return mModchipType;
+}
+
+void context::setCurrentIp(const char* ip)
+{
+ free(mCurrentIp);
+ mCurrentIp = strdup(ip);
+}
+
+char* context::getCurrentIp()
+{
+ return mCurrentIp == NULL ? strdup("0.0.0.0") : strdup(mCurrentIp);
+}
+
+void context::setCurrentFreeMem(uint32_t freeMem)
+{
+ mCurrentFreeMem = freeMem;
+}
+
+uint32_t context::getCurrentFreeMem()
+{
+ return mCurrentFreeMem;
+}
+
+void context::setCurrentTitle(const char* title)
+{
+ free(mCurrentTitle);
+ mCurrentTitle = strdup(title);
+}
+
+char* context::getCurrentTitle()
+{
+ return mCurrentTitle == NULL ? strdup("") : strdup(mCurrentTitle);
+}
+
+void context::setCurrentFanSpeed(int32_t fanSpeed)
+{
+ mCurrentFanSpeed = fanSpeed;
+}
+
+int32_t context::getCurrentFanSpeed()
+{
+ return mCurrentFanSpeed;
+}
+
+void context::setCurrentCpuTemp(int32_t cpuTemp)
+{
+ mCurrentCpuTemp = cpuTemp;
+}
+
+int32_t context::getCurrentCpuTemp()
+{
+ return mCurrentCpuTemp;
+}
+
+void context::setCurrentMbTemp(int32_t mbTemp)
+{
+ mCurrentMbTemp = mbTemp;
+}
+
+int32_t context::getCurrentMbTemp()
+{
+ return mCurrentMbTemp;
+}
+
+void context::setNetworkInitialized(bool value)
+{
+ mNetworkInitialized = value;
+}
+
+bool context::getNetworkInitialized()
+{
+ return mNetworkInitialized;
+}
+
+void context::setD3dDevice(LPDIRECT3DDEVICE8 d3dDevice)
+{
+ mD3dDevice = d3dDevice;
+}
+
+LPDIRECT3DDEVICE8 context::getD3dDevice()
+{
+ return mD3dDevice;
+}
+
+void context::setBufferWidth(int32_t bufferWidth)
+{
+ mBufferWidth = bufferWidth;
+}
+
+int32_t context::getBufferWidth()
+{
+ return mBufferWidth;
+}
+
+void context::setBufferHeight(int32_t bufferHeight)
+{
+ mBufferHeight = bufferHeight;
+}
+
+int32_t context::getBufferHeight()
+{
+ return mBufferHeight;
+}
+
+void context::setBufferPitch(int32_t bufferPitch)
+{
+ mBufferPitch = bufferPitch;
+}
+
+int32_t context::getBufferPitch()
+{
+ return mBufferPitch;
+}
+
+void context::setBuffer(int32_t* buffer)
+{
+ mBuffer = buffer;
+}
+
+int32_t* context::getBuffer()
+{
+ return mBuffer;
+}
+
+void context::setImageMap(pointerMap* imageMap)
+{
+ mImageMap = imageMap;
+}
+
+pointerMap* context::getImageMap()
+{
+ return mImageMap;
+}
+
+void context::setBitmapFontSmall(bitmapFont* font)
+{
+ mBitmapFontSmall = font;
+}
+
+bitmapFont* context::getBitmapFontSmall()
+{
+ return mBitmapFontSmall;
+}
+
+void context::setBitmapFontMedium(bitmapFont* font)
+{
+ mBitmapFontMedium = font;
+}
+
+bitmapFont* context::getBitmapFontMedium()
+{
+ return mBitmapFontMedium;
+}
+
+void context::setBitmapFontLarge(bitmapFont* font)
+{
+ mBitmapFontLarge = font;
+}
+
+bitmapFont* context::getBitmapFontLarge()
+{
+ return mBitmapFontLarge;
+}
+
+void context::setSoundPackPath(const char* soundPackPath)
+{
+ free(mSoundPackPath);
+ mSoundPackPath = strdup(soundPackPath);
+}
+
+char* context::getSoundPackPath()
+{
+ return strdup(mSoundPackPath);
+}
+
+void context::setMusicId(uint32_t musicId)
+{
+ mMusicId = musicId;
+}
+
+uint32_t context::getMusicId()
+{
+ return mMusicId;
+}
+
+void context::setMasterPassword(utils::dataContainer* masterPassword)
+{
+ delete(mMasterPassword);
+ mMasterPassword = masterPassword;
+}
+
+utils::dataContainer* context::getMasterPassword()
+{
+ return mMasterPassword;
+}
+
+void context::setUserPassword(utils::dataContainer* userPassword)
+{
+ delete(mUserPassword);
+ mUserPassword = userPassword;
+}
+
+utils::dataContainer* context::getUserPassword()
+{
+ return mUserPassword;
+}
+
+void context::setDriveModel(const char* model)
+{
+ free(mDriveModel);
+ mDriveModel = strdup(model);
+}
+
+char* context::getDriveModel()
+{
+ return mDriveModel == NULL ? strdup("") : strdup(mDriveModel);
+}
+
+void context::setDriveSerial(const char* serial)
+{
+ free(mDriveSerial);
+ mDriveSerial = strdup(serial);
+}
+
+char* context::getDriveSerial()
+{
+ return mDriveSerial == NULL ? strdup("") : strdup(mDriveSerial);
+}
+
+void context::setTakeScreenshot(bool takeScreenshot)
+{
+ mTakeScreenshot = takeScreenshot;
+}
+
+bool context::getTakeScreenshot()
+{
+ return mTakeScreenshot;
+}
+
+void context::setScreenshot(utils::dataContainer* screenshot)
+{
+ if (mScreenshot != NULL)
+ {
+ delete(mScreenshot);
+ }
+ mScreenshot = screenshot;
+}
+
+utils::dataContainer* context::getScreenshot()
+{
+ if (mScreenshot == NULL)
+ {
+ return NULL;
+ }
+ utils::dataContainer* screenshotCopy = new utils::dataContainer(mScreenshot->data, mScreenshot->size, mScreenshot->size);
+ return screenshotCopy;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/context.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/context.h
new file mode 100644
index 0000000..8c8dc4e
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/context.h
@@ -0,0 +1,95 @@
+#pragma once
+
+#include "inputManager.h"
+#include "math.h"
+#include "pointerMap.h"
+#include "modchip.h"
+#include "xboxInternals.h"
+
+#include
+
+typedef struct image
+{
+ int width;
+ int height;
+ D3DTexture *texture;
+ math::rectF uvRect;
+
+ ~image()
+ {
+ texture->Release();
+ }
+
+} image;
+
+typedef struct bitmapFont
+{
+ pointerMap* charMap;
+ image* image;
+ int lineHeight;
+ int spacing;
+
+ ~bitmapFont()
+ {
+ delete(charMap);
+ delete(image);
+ }
+
+} bitmapFont;
+
+class context
+{
+public:
+ static modchip* getModchip();
+ static void setModchipType(modchipType modchipType);
+ static modchipType getModchipType();
+ static void setCurrentIp(const char* ip);
+ static char* getCurrentIp();
+ static void setCurrentFreeMem(uint32_t freeMem);
+ static uint32_t getCurrentFreeMem();
+ static void setCurrentTitle(const char* title);
+ static char* getCurrentTitle();
+ static void setCurrentFanSpeed(int32_t fanSpeed);
+ static int32_t getCurrentFanSpeed();
+ static void setCurrentCpuTemp(int32_t cpuTemp);
+ static int32_t getCurrentCpuTemp();
+ static void setCurrentMbTemp(int32_t mbTemp);
+ static int32_t getCurrentMbTemp();
+ static void setNetworkInitialized(bool value);
+ static bool getNetworkInitialized();
+ static void setD3dDevice(LPDIRECT3DDEVICE8 d3dDevice);
+ static LPDIRECT3DDEVICE8 getD3dDevice();
+ static void setBufferWidth(int32_t bufferWidth);
+ static int32_t getBufferWidth();
+ static void setBufferHeight(int32_t bufferHeight);
+ static int32_t getBufferHeight();
+ static void setBufferPitch(int32_t bufferPitch);
+ static int32_t getBufferPitch();
+ static void setBuffer(int32_t* buffer);
+ static int32_t* getBuffer();
+ static void setImageMap(pointerMap* imageMap);
+ static pointerMap* getImageMap();
+ static inputManager* getInputManager();
+ static void setBitmapFontSmall(bitmapFont* font);
+ static bitmapFont* getBitmapFontSmall();
+ static void setBitmapFontMedium(bitmapFont* font);
+ static bitmapFont* getBitmapFontMedium();
+ static void setBitmapFontLarge(bitmapFont* font);
+ static bitmapFont* getBitmapFontLarge();
+ static void setSoundPackPath(const char* soundPackPath);
+ static char* getSoundPackPath();
+ static void setMusicId(uint32_t musicId);
+ static uint32_t getMusicId();
+ static void setMasterPassword(utils::dataContainer* masterPassword);
+ static utils::dataContainer* getMasterPassword();
+ static void setUserPassword(utils::dataContainer* userPassword);
+ static utils::dataContainer* getUserPassword();
+ static void setDriveModel(const char* model);
+ static char* getDriveModel();
+ static void setDriveSerial(const char* serial);
+ static char* getDriveSerial();
+ static void setTakeScreenshot(bool takeScreenshot);
+ static bool getTakeScreenshot();
+ static void setScreenshot(utils::dataContainer* screenshot);
+ static utils::dataContainer* getScreenshot();
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/crc32.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/crc32.cpp
new file mode 100644
index 0000000..9097f35
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/crc32.cpp
@@ -0,0 +1,76 @@
+#include "crc32.h"
+
+#include "xboxinternals.h"
+#include "fileSystem.h"
+
+namespace
+{
+ const uint32_t crctable[256] = {
+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+ 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+ };
+}
+
+uint32_t crc32::calculate(const uint8_t *buffer, uint32_t size)
+{
+ unsigned long crc = 0xffffffff;
+ calculate(buffer, size, crc);
+ return crc ^ 0xffffffff;
+}
+
+uint32_t crc32::calculate(uint32_t fileHandle)
+{
+ unsigned long crc = 0xffffffff;
+ uint8_t *buffer = (uint8_t*)malloc(65535);
+ uint32_t bytesRead = 0;
+ while (true)
+ {
+ if (fileSystem::fileRead(fileHandle, (char*)buffer, 65535, bytesRead)) {
+ return 0;
+ }
+ if (bytesRead == 0) {
+ break;
+ }
+ calculate(buffer, bytesRead, crc);
+ }
+ free(buffer);
+ return crc ^ 0xffffffff;
+}
+
+void crc32::calculate(const uint8_t *buffer, uint32_t size, uint32_t& crc)
+{
+ while (size--)
+ {
+ crc = (crc >> 8) ^ crctable[(crc & 0xff) ^ *buffer++];
+ }
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/crc32.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/crc32.h
new file mode 100644
index 0000000..8a1f604
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/crc32.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "xboxinternals.h"
+
+class crc32
+{
+public:
+ static uint32_t calculate(const uint8_t *buffer, uint32_t size);
+ static uint32_t calculate(uint32_t fileHandle);
+private:
+ static void calculate(const uint8_t *buffer, uint32_t size, uint32_t& crc);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/drawing.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/drawing.cpp
new file mode 100644
index 0000000..dadc630
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/drawing.cpp
@@ -0,0 +1,730 @@
+#include "drawing.h"
+#include "context.h"
+#include "math.h"
+#include "utils.h"
+#include "meshUtility.h"
+#include "stringUtility.h"
+#include "theme.h"
+#include "pointerMap.h"
+
+#include
+
+#define SSFN_IMPLEMENTATION
+#define SFFN_MAXLINES 8192
+#define SSFN_memcmp memcmp
+#define SSFN_memset memset
+#define SSFN_realloc realloc
+#define SSFN_free free
+#include "ssfn.h"
+
+#define STB_IMAGE_IMPLEMENTATION
+#define STBI_ASSERT(x)
+#include "stb_image.h"
+
+#define STB_IMAGE_WRITE_IMPLEMENTATION
+#include "stb_image_write.h"
+
+namespace
+{
+ ssfn_t* mFontContext = NULL;
+ //ssfn_buf_t* mFontBuffer = NULL;
+
+ //SSFN::Font* mFont = NULL;
+}
+
+inline unsigned char lerp(unsigned char a, unsigned char b, float t)
+{
+ return (unsigned char)(a + t * (b - a));
+}
+
+inline int length(int a, int b)
+{
+ return (a * a) + (b * b);
+}
+
+void drawing::swizzle(const void *src, const uint32_t& depth, const uint32_t& width, const uint32_t& height, void *dest)
+{
+ for (UINT y = 0; y < height; y++)
+ {
+ UINT sy = 0;
+ if (y < width)
+ {
+ for (int bit = 0; bit < 16; bit++)
+ sy |= ((y >> bit) & 1) << (2*bit);
+ sy <<= 1; // y counts twice
+ }
+ else
+ {
+ UINT y_mask = y % width;
+ for (int bit = 0; bit < 16; bit++)
+ sy |= ((y_mask >> bit) & 1) << (2*bit);
+ sy <<= 1; // y counts twice
+ sy += (y / width) * width * width;
+ }
+ BYTE *s = (BYTE *)src + y * width * depth;
+ for (UINT x = 0; x < width; x++)
+ {
+ UINT sx = 0;
+ if (x < height * 2)
+ {
+ for (int bit = 0; bit < 16; bit++)
+ sx |= ((x >> bit) & 1) << (2*bit);
+ }
+ else
+ {
+ int x_mask = x % (2*height);
+ for (int bit = 0; bit < 16; bit++)
+ sx |= ((x_mask >> bit) & 1) << (2*bit);
+ sx += (x / (2 * height)) * 2 * height * height;
+ }
+ BYTE *d = (BYTE *)dest + (sx + sy)*depth;
+ for (unsigned int i = 0; i < depth; ++i)
+ *d++ = *s++;
+ }
+ }
+}
+
+ //uint8_t* pixels = imageData;
+ //for (int i = 0; i < width * height * 4; i+=4)
+ //{
+ // // swap bgra to rgba
+ // unsigned char temp = pixels[i + 0];
+ // pixels[i + 0] = pixels[i + 2];
+ // pixels[i + 2] = temp;
+ //}
+
+image* drawing::createImage(uint8_t* imageData, D3DFORMAT format, int width, int height)
+{
+ image* imageToAdd = new image();
+ imageToAdd->width = width;
+ imageToAdd->height = height;
+
+ if (FAILED(D3DXCreateTexture(context::getD3dDevice(), imageToAdd->width, imageToAdd->height, 1, 0, format, D3DPOOL_DEFAULT, &imageToAdd->texture)))
+ {
+ return false;
+ }
+
+ D3DSURFACE_DESC surfaceDesc;
+ imageToAdd->texture->GetLevelDesc(0, &surfaceDesc);
+
+ imageToAdd->uvRect = math::rectF(0, 0, imageToAdd->width / (float)surfaceDesc.Width, imageToAdd->height / (float)surfaceDesc.Height);
+
+ D3DLOCKED_RECT lockedRect;
+ if (SUCCEEDED(imageToAdd->texture->LockRect(0, &lockedRect, NULL, 0)))
+ {
+ uint8_t* tempBuffer = (uint8_t*)malloc(surfaceDesc.Size);
+ memset(tempBuffer, 0, surfaceDesc.Size);
+ uint8_t* src = imageData;
+ uint8_t* dst = tempBuffer;
+ for (int32_t y = 0; y < imageToAdd->height; y++)
+ {
+ memcpy(dst, src, imageToAdd->width * 4);
+ src += imageToAdd->width * 4;
+ dst += surfaceDesc.Width * 4;
+ }
+ swizzle(tempBuffer, 4, surfaceDesc.Width, surfaceDesc.Height, lockedRect.pBits);
+ free(tempBuffer);
+ imageToAdd->texture->UnlockRect(0);
+ }
+
+ return imageToAdd;
+}
+
+void drawing::addImage(const char* key, uint8_t* imageData, D3DFORMAT format, int width, int height)
+{
+ image* imageToAdd = createImage(imageData, format, width, height);
+ context::getImageMap()->add(key, imageToAdd);
+}
+
+uint64_t drawing::getImageMemUse(const char* key)
+{
+ image* imageInfo = context::getImageMap()->get(key);
+ if (imageInfo == NULL)
+ {
+ return 0;
+ }
+ return utils::roundUpToNextPowerOf2(imageInfo->width) * utils::roundUpToNextPowerOf2(imageInfo->height) * 4;
+}
+
+void drawing::removeImage(const char* key)
+{
+ image* imageToRemove = context::getImageMap()->get(key);
+ if (imageToRemove != NULL)
+ {
+ context::getImageMap()->removeKey(key);
+ }
+}
+
+bool drawing::loadImage(const char* buffer, uint32_t length, const char* key)
+{
+ int width;
+ int height;
+ uint8_t* imageData = (uint8_t*)stbi_load_from_memory((const stbi_uc*)buffer, length, &width, &height, NULL, STBI_rgb_alpha);
+ if (imageData == NULL)
+ {
+ return false;
+ }
+ addImage(key, imageData, D3DFMT_A8B8G8R8, width, height);
+ free(imageData);
+ return true;
+}
+
+bool drawing::loadFont(const uint8_t* data)
+{
+ if (mFontContext == NULL)
+ {
+ mFontContext = (ssfn_t*)malloc(sizeof(ssfn_t));
+ memset(mFontContext, 0, sizeof(ssfn_t));
+ }
+
+ int result = ssfn_load(mFontContext, data);
+ return result == 0;
+}
+
+void drawing::clearBackground(uint32_t index)
+{
+ char* backgroundName = stringUtility::formatString("background:%i", index);
+
+ uint32_t backgroundColor = theme::getBackgroundColor();
+ context::getD3dDevice()->Clear(0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, (0xff << 24) | backgroundColor, 1.0f, 0L);
+
+ for (int i = 0; i < 2; i++)
+ {
+ int index = theme::getBackgroundOverlayAsUnderlay() == true ? (1 - i) : i;
+ if (index == 0 && imageExists(backgroundName) == true)
+ {
+ drawImage(backgroundName, theme::getBackgroundImageTint(), 0, 0, context::getBufferWidth(), context::getBufferHeight());
+ }
+ if (index == 1 && imageExists("background-overlay") == true)
+ {
+ drawImage("background-overlay", theme::getBackgroundOverlayImageTint(), 0, 0, context::getBufferWidth(), context::getBufferHeight());
+ }
+ }
+
+ free(backgroundName);
+}
+
+bool drawing::imageExists(const char* key)
+{
+ image* result = context::getImageMap()->get(key);
+ return result != NULL;
+}
+
+image* drawing::getImage(const char* key)
+{
+ image* result = context::getImageMap()->get(key);
+ return result;
+}
+
+void drawing::setTint(unsigned int color)
+{
+ context::getD3dDevice()->SetRenderState(D3DRS_TEXTUREFACTOR, color);
+}
+
+void drawing::drawImage(image* image, uint32_t tint, int x, int y, int width, int height)
+{
+ if (image == NULL)
+ {
+ return;
+
+ }
+ context::getD3dDevice()->SetRenderState(D3DRS_TEXTUREFACTOR, tint);
+ float newY = (float)context::getBufferHeight() - (y + height);
+ context::getD3dDevice()->SetTexture(0, image->texture);
+ utils::dataContainer* vertices = meshUtility::createQuadXY(math::vec3F((float)x - 0.5f, newY - 0.5f, 0), math::sizeF((float)width, (float)height), image->uvRect);
+ context::getD3dDevice()->DrawPrimitiveUP(D3DPT_TRIANGLELIST, (vertices->size / sizeof(meshUtility::vertex)) / 3, vertices->data, sizeof(meshUtility::vertex));
+ delete(vertices);
+}
+
+void drawing::drawImage(image* image, uint32_t tint, int x, int y)
+{
+ if (image == NULL)
+ {
+ return;
+
+ }
+ drawImage(image, tint, x, y, image->width, image->height);
+}
+
+void drawing::drawImage(const char* imageKey, uint32_t tint, int x, int y, int width, int height)
+{
+ image* imageToDraw = getImage(imageKey);
+ if (imageToDraw == NULL)
+ {
+ return;
+ }
+ drawImage(imageToDraw, tint, x, y, width, height);
+}
+
+void drawing::drawImage(const char* imageKey, uint32_t tint, int x, int y)
+{
+ image* imageToDraw = getImage(imageKey);
+ if (imageToDraw == NULL)
+ {
+ return;
+ }
+ drawImage(imageToDraw, tint, x, y);
+}
+
+void drawing::drawNinePatch(const char* imageKey, uint32_t tint, int x, int y, int width, int height)
+{
+ image* imageToDraw = getImage(imageKey);
+ if (imageToDraw == NULL)
+ {
+ return;
+ }
+ context::getD3dDevice()->SetRenderState(D3DRS_TEXTUREFACTOR, tint);
+ float newY = (float)context::getBufferHeight() - (y + height);
+ context::getD3dDevice()->SetTexture(0, imageToDraw->texture);
+ utils::dataContainer* vertices = meshUtility::createNinePatchXY(math::vec3F((float)x - 0.5f, newY - 0.5f, 0), math::sizeF((float)width, (float)height), imageToDraw->uvRect);
+ context::getD3dDevice()->DrawPrimitiveUP(D3DPT_TRIANGLELIST, (vertices->size / sizeof(meshUtility::vertex)) / 3, vertices->data, sizeof(meshUtility::vertex));
+ delete(vertices);
+}
+
+image* drawing::renderHorizontalLine(const char* cacheKey, unsigned int color, int width, int height)
+{
+ if (imageExists(cacheKey) == false)
+ {
+ uint32_t* imageData = (uint32_t*)malloc(width * height * 4);
+ for (int i = 0; i < width * height; i++)
+ {
+ imageData[i] = color;
+ }
+ addImage(cacheKey, (uint8_t*)imageData, D3DFMT_A8R8G8B8, width, height);
+ free(imageData);
+ }
+ return getImage(cacheKey);
+}
+
+image* drawing::renderRoundedRect(const char* cacheKey, uint32_t width, uint32_t height, uint32_t cornerRadius, uint32_t fillColor, uint32_t strokeColor, uint32_t strokeWidth)
+{
+ if (imageExists(cacheKey) == false)
+ {
+ uint32_t* imageData = (uint32_t*)malloc(width * height * 4);
+
+ int widthMinus1 = width - 1;
+ int heightMinus1 = height - 1;
+ for (unsigned int y = 0; y < height; y++)
+ {
+ float gradient = (float)y / height;
+ for (unsigned int x = 0; x < width; x++)
+ {
+ unsigned int color = 0x00000000;
+
+ bool isInsideRect = (y >= cornerRadius && y < height - cornerRadius) || (x >= cornerRadius && x < width - cornerRadius);
+ int topLeftCornerLength = length(y - cornerRadius, x - cornerRadius);
+ int topRightCornerLength = length(y - cornerRadius, x - (widthMinus1 - cornerRadius));
+ int bottomLeftCornerLength = length(y - (heightMinus1 - cornerRadius), x - cornerRadius);
+ int bottomRightCornerLength = length(y - (heightMinus1 - cornerRadius), x - (widthMinus1 - cornerRadius));
+ int cornerRadiusSquared = cornerRadius * cornerRadius;
+
+ bool isInsideTopLeftCorner = topLeftCornerLength < cornerRadiusSquared;
+ bool isInsideTopRightCorner = topRightCornerLength < cornerRadiusSquared;
+ bool isInsideBottomLeftCorner = bottomLeftCornerLength < cornerRadiusSquared;
+ bool isInsideBottomRightCorner = bottomRightCornerLength < cornerRadiusSquared;
+ if (isInsideRect || isInsideTopLeftCorner || isInsideTopRightCorner || isInsideBottomLeftCorner || isInsideBottomRightCorner)
+ {
+ color = fillColor;
+ }
+ imageData[(y * width) + x] = color;
+ }
+ }
+
+ if (strokeWidth > 0)
+ {
+ for (uint32_t y = 0; y < height; y++)
+ {
+ int count = 0;
+ for (uint32_t x = 0; x < width; x++)
+ {
+ uint32_t color = imageData[(y * width) + x];
+ if (count == strokeWidth)
+ {
+ break;
+ }
+ if (color > 0)
+ {
+ imageData[(y * width) + x] = strokeColor;
+ imageData[(y * width) + (width - 1) - x] = strokeColor;
+ count++;
+ }
+ }
+ }
+
+ for (uint32_t x = 0; x < width; x++)
+ {
+ int count = 0;
+ for (uint32_t y = 0; y < height; y++)
+ {
+ uint32_t color = imageData[(y * width) + x];
+ if (count == strokeWidth)
+ {
+ break;
+ }
+ if (color > 0)
+ {
+ imageData[(y * width) + x] = strokeColor;
+ imageData[(((height - 1) - y) * width) + x] = strokeColor;
+ count++;
+ }
+ }
+ }
+ }
+
+ //stbi_write_jpg("App:\\test.jpg", width, height, 4, imageData, 100);
+ addImage(cacheKey, (uint8_t*)imageData, D3DFMT_A8R8G8B8, width, height);
+ free(imageData);
+ }
+ return getImage(cacheKey);
+}
+
+void drawing::drawHorizontalLine(uint32_t color, int x, int y, int width, int height)
+{
+ char* cacheKey = stringUtility::formatString("drawHorizontalLine-%02x-%02x", width, height);
+ image* image = renderHorizontalLine(cacheKey, color, width, height);
+ drawImage(image, color, x, y);
+ free(cacheKey);
+}
+//
+//void drawing::measureString(const char* fontName, int fontStyle, int fontSize, const char* message, int* width, int* height)
+//{
+// ssfn_select(mFontContext, SSFN_FAMILY_ANY, fontName, fontStyle, fontSize);
+// ssfn_bbox(mFontContext, message, width, height, NULL, NULL);
+//}
+//
+//image* drawing::renderString(const char* cacheKey, Bounds bounds, const char* message, uint32_t color)
+//{
+// if (imageExists(cacheKey) == false)
+// {
+// int ret;
+//
+// uint32_t* imageData = (uint32_t*)malloc(bounds.width * bounds.height * 4);
+// memset(imageData, 0, bounds.width * bounds.height * 4);
+//
+// ssfn_buf_t buffer;
+// memset(&buffer, 0, sizeof(buffer));
+// buffer.ptr = (uint8_t*)imageData;
+// buffer.x = bounds.left;
+// buffer.y = bounds.top;
+// buffer.w = bounds.width;
+// buffer.h = bounds.height;
+// buffer.p = bounds.width * 4;
+// buffer.bg = color;
+// buffer.fg = color;
+//
+// const char *text = message;
+//
+// while((ret = ssfn_render(mFontContext, &buffer, text)) > 0)
+// {
+// text += ret;
+// }
+//
+// addImage(cacheKey, (uint8_t*)imageData, D3DFMT_A8R8G8B8, bounds.width, bounds.height);
+// free(imageData);
+// }
+// return getImage(cacheKey);
+//}
+//
+//void drawing::drawString(const char* fontName, int fontStyle, int fontSize, const char* message, uint32_t color, int x, int y)
+//{
+// ssfn_select(mFontContext, SSFN_FAMILY_ANY, fontName, fontStyle, fontSize);
+//
+// Bounds bounds;
+// ssfn_bbox(mFontContext, message, &bounds.width, &bounds.height, &bounds.left, &bounds.top);
+//
+// char* cacheKey = stringUtility::formatString("drawString-%s-%02x-%02x-%s-%08x-%08x", fontName, fontStyle, fontSize, message, color);
+// image* image = renderString(cacheKey, bounds, message, color);
+// drawImage(image, 0xffffffff, x, y);
+// free(cacheKey);
+//}
+//
+//void drawing::drawStringAligned(const char* fontName, int fontStyle, int fontSize, const char* message, uint32_t color, horizAlignment hAlign, int x, int y, int width)
+//{
+// ssfn_select(mFontContext, SSFN_FAMILY_ANY, fontName, fontStyle, fontSize);
+//
+// int textWidth = 0;
+// measureString(fontName, fontStyle, fontSize, message, &textWidth, NULL);
+//
+// int xPos = x;
+// if (hAlign == horizAlignmentCenter)
+// {
+// xPos = x + ((width - textWidth) / 2);
+// }
+// else if (hAlign == horizAlignmentRight)
+// {
+// xPos = x + (width - textWidth);
+// }
+//
+// drawString(fontName, fontStyle, fontSize, message, color, xPos, y);
+//}
+
+bitmapFont* drawing::generateBitmapFont(const char* fontName, int fontStyle, int fontSize, int lineHeight, int spacing, int textureDimension)
+{
+ bitmapFont* font = new bitmapFont();
+ font->charMap = new pointerMap(true);
+
+ ssfn_select(mFontContext, SSFN_FAMILY_ANY, fontName, fontStyle, fontSize);
+
+ int textureWidth = textureDimension;
+ int textureHeight = textureDimension;
+
+ uint32_t* imageData = (uint32_t*)malloc(textureWidth * textureHeight * 4);
+ memset(imageData, 0, textureWidth * textureHeight * 4);
+
+ int x = 2;
+ int y = 2;
+
+ char* charsToEncode = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\xC2\xA1\xC2\xA2\xC2\xA3\xC2\xA4\xC2\xA5\xC2\xA6\xC2\xA7\xC2\xA8\xC2\xA9\xC2\xAA\xC2\xAB\xC2\xAC\xC2\xAD\xC2\xAE\xC2\xAF\xC2\xB0\xC2\xB1\xC2\xB2\xC2\xB3\xC2\xB4\xC2\xB5\xC2\xB6";
+ char* currentCharPos = charsToEncode;
+ while(*currentCharPos)
+ {
+ char* nextCharPos = currentCharPos;
+ uint32_t unicode = ssfn_utf8(&nextCharPos);
+
+ int32_t length = nextCharPos - currentCharPos;
+ char* currentChar = (char*)malloc(length + 1);
+ memcpy(currentChar, currentCharPos, length);
+ currentChar[length] = 0;
+
+ currentCharPos = nextCharPos;
+
+ Bounds bounds;
+ int ret = ssfn_bbox(mFontContext, currentChar, &bounds.width, &bounds.height, &bounds.left, &bounds.top);
+ if (ret != 0)
+ {
+ continue;
+ }
+
+ if ((x + bounds.width + 2) > textureWidth)
+ {
+ x = 2;
+ y = y + bounds.height + 2;
+ }
+
+ math::rectI* rect = new math::rectI();
+ rect->x = x;
+ rect->y = y;
+ rect->width = bounds.width;
+ rect->height = bounds.height;
+
+ char* unicodeString = stringUtility::formatString("%i", unicode);
+ font->charMap->add(unicodeString, rect);
+ free(unicodeString);
+
+ ssfn_buf_t buffer;
+ memset(&buffer, 0, sizeof(buffer));
+ buffer.ptr = (uint8_t*)imageData;
+ buffer.x = x + bounds.left;
+ buffer.y = y + bounds.top;
+ buffer.w = textureWidth;
+ buffer.h = textureHeight;
+ buffer.p = textureWidth * 4;
+ buffer.bg = 0xffffffff;
+ buffer.fg = 0xffffffff;
+
+ ssfn_render(mFontContext, &buffer, currentChar);
+
+ x = x + bounds.width + 2;
+ free(currentChar);
+ }
+
+ font->image = createImage((uint8_t*)imageData, D3DFMT_A8R8G8B8, textureWidth, textureHeight);
+ font->lineHeight = lineHeight;
+ font->spacing = spacing;
+ free(imageData);
+
+ return font;
+}
+
+void drawing::measureBitmapString(bitmapFont* font, const char* message, int* width, int* height)
+{
+ image* image = font->image;
+
+ int xPosMax = 0;
+
+ int xPos = 0;
+ int yPos = 0;
+
+ char* currentCharPos = (char*)message;
+ while(*currentCharPos)
+ {
+ char* nextCharPos = currentCharPos;
+ uint32_t unicode = ssfn_utf8(&nextCharPos);
+
+ int32_t length = nextCharPos - currentCharPos;
+ char* currentChar = (char*)malloc(length + 1);
+ memcpy(currentChar, currentCharPos, length);
+ currentChar[length] = 0;
+
+ currentCharPos = nextCharPos;
+
+ if (stringUtility::equals(currentChar, "\n", false) == true)
+ {
+ xPos = 0;
+ yPos += font->lineHeight;
+ continue;
+ }
+
+ char* unicodeString = stringUtility::formatString("%i", unicode);
+ math::rectI* rect = font->charMap->get(unicodeString);
+ free(unicodeString);
+ if (rect == NULL)
+ {
+ continue;
+ }
+
+ xPos = xPos + rect->width + font->spacing;
+ xPosMax = max(xPosMax, xPos);
+ free(currentChar);
+ }
+
+ if (width != NULL)
+ {
+ *width = xPosMax - 2;
+ }
+
+ if (height != NULL)
+ {
+ *height = yPos + font->lineHeight;
+ }
+}
+
+void drawing::drawBitmapString(bitmapFont* font, const char* message, uint32_t color, int x, int y)
+{
+ image* image = font->image;
+
+ int xPos = x;
+ int yPos = y;
+
+ char* currentCharPos = (char*)message;
+ while(*currentCharPos)
+ {
+ char* nextCharPos = currentCharPos;
+ uint32_t unicode = ssfn_utf8(&nextCharPos);
+
+ int32_t length = nextCharPos - currentCharPos;
+ char* currentChar = (char*)malloc(length + 1);
+ memcpy(currentChar, currentCharPos, length);
+ currentChar[length] = 0;
+
+ currentCharPos = nextCharPos;
+
+ if (stringUtility::equals(currentChar, "\n", false) == true)
+ {
+ xPos = x;
+ yPos += font->lineHeight;
+ continue;
+ }
+
+ char* unicodeString = stringUtility::formatString("%i", unicode);
+ math::rectI* rect = font->charMap->get(unicodeString);
+ free(unicodeString);
+ if (rect == NULL)
+ {
+ continue;
+ }
+
+ math::rectF uvRect;
+ uvRect.x = rect->x / (float)image->width;
+ uvRect.y = rect->y / (float)image->height;
+ uvRect.width = rect->width / (float)image->width;
+ uvRect.height = rect->height / (float)image->height;
+
+ uint32_t charColor = color;
+ if (unicode == 161)
+ {
+ charColor = theme::getJoyButtonAColor();
+ }
+ else if (unicode == 162)
+ {
+ charColor = theme::getJoyButtonBColor();
+ }
+ else if (unicode == 163)
+ {
+ charColor = theme::getJoyButtonXColor();
+ }
+ else if (unicode == 164)
+ {
+ charColor = theme::getJoyButtonYColor();
+ }
+ else if (unicode == 182)
+ {
+ charColor = theme::getJoyButtonBlackColor();
+ }
+ else if (unicode == 181)
+ {
+ charColor = theme::getJoyButtonWhiteColor();
+ }
+
+ context::getD3dDevice()->SetRenderState(D3DRS_TEXTUREFACTOR, charColor);
+ float newY = (float)context::getBufferHeight() - (yPos + rect->height);
+ context::getD3dDevice()->SetTexture(0, image->texture);
+ utils::dataContainer* vertices = meshUtility::createQuadXY(math::vec3F((float)xPos - 0.5f, newY - 0.5f, 0), math::sizeF((float)rect->width, (float)rect->height), uvRect);
+ context::getD3dDevice()->DrawPrimitiveUP(D3DPT_TRIANGLELIST, (vertices->size / sizeof(meshUtility::vertex)) / 3, vertices->data, sizeof(meshUtility::vertex));
+ delete(vertices);
+
+ xPos = xPos + rect->width + font->spacing;
+ free(currentChar);
+ }
+}
+
+void drawing::drawBitmapStringAligned(bitmapFont* font, const char* message, uint32_t color, horizAlignment hAlign, int x, int y, int width)
+{
+ int textWidth = 0;
+ measureBitmapString(font, message, &textWidth, NULL);
+
+ int xPos = x;
+ if (hAlign == horizAlignmentCenter)
+ {
+ xPos = x + ((width - textWidth) / 2);
+ }
+ else if (hAlign == horizAlignmentRight)
+ {
+ xPos = x + (width - textWidth);
+ }
+
+ drawBitmapString(font, message, color, xPos, y);
+}
+
+utils::dataContainer* drawing::takeScreenshot()
+{
+ utils::dataContainer* result = NULL;
+
+ IDirect3DSurface8* surface;
+ context::getD3dDevice()->GetBackBuffer(-1, D3DBACKBUFFER_TYPE_MONO, &surface);
+
+ D3DLOCKED_RECT lockedRect;
+ if (surface->LockRect(&lockedRect, NULL, D3DLOCK_READONLY) >= 0)
+ {
+ uint8_t* pBits = (uint8_t*)lockedRect.pBits;
+
+ D3DSURFACE_DESC desc;
+ surface->GetDesc(&desc);
+
+ uint8_t* buffer = (uint8_t*)malloc(desc.Width * desc.Height * 4);
+ uint8_t* bufferOffset = buffer;
+
+ for (uint32_t y = 0; y < desc.Height; ++y) {
+ uint8_t* row = pBits + y * lockedRect.Pitch;
+ for (uint32_t x = 0; x < desc.Width; ++x) {
+ uint8_t* pixel = row + x * 4;
+ bufferOffset[0] = pixel[2];
+ bufferOffset[1] = pixel[1];
+ bufferOffset[2] = pixel[0];
+ bufferOffset[3] = 0xff;
+ bufferOffset += 4;
+ }
+ }
+
+ int fileSize = 0;
+ char *pngData = (char*)stbi_write_png_to_mem(buffer, lockedRect.Pitch, desc.Width, desc.Height, 4, &fileSize);
+ result = new utils::dataContainer(pngData, fileSize, fileSize);
+ free(buffer);
+ free(pngData);
+
+ surface->UnlockRect();
+ }
+ surface->Release();
+
+ return result;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/drawing.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/drawing.h
new file mode 100644
index 0000000..858bf0f
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/drawing.h
@@ -0,0 +1,45 @@
+#pragma once
+
+#include "context.h"
+#include "xboxinternals.h"
+#include
+#include "math.h"
+#include "pointerMap.h"
+#include "alignment.h"
+
+typedef struct Bounds
+{
+ int width;
+ int height;
+ int left;
+ int top;
+} Bounds;
+
+class drawing
+{
+public:
+ static void swizzle(const void *src, const uint32_t& depth, const uint32_t& width, const uint32_t& height, void *dest);
+ static image* createImage(uint8_t* imageData, D3DFORMAT format, int width, int height);
+ static void addImage(const char* key, uint8_t* imageData, D3DFORMAT format, int width, int height);
+ static uint64_t getImageMemUse(const char* key);
+ static void removeImage(const char* key);
+ static bool loadImage(const char* buffer, uint32_t length, const char* key);
+ static bool loadFont(const uint8_t* data);
+ static void clearBackground(uint32_t index);
+ static bool imageExists(const char* key);
+ static image* getImage(const char* key);
+ static void setTint(unsigned int color);
+ static void drawImage(image* image, uint32_t tint, int x, int y, int width, int height);
+ static void drawImage(image* image, uint32_t tint, int x, int y);
+ static void drawImage(const char* imageKey, uint32_t tint, int x, int y, int width, int height);
+ static void drawImage(const char* imageKey, uint32_t tint, int x, int y);
+ static image* renderRoundedRect(const char* cacheKey, uint32_t width, uint32_t height, uint32_t cornerRadius, uint32_t fillColor, uint32_t strokeColor, uint32_t strokeWidth);
+ static image* renderHorizontalLine(const char* cacheKey, unsigned int color, int width, int height);
+ static void drawHorizontalLine(uint32_t color, int x, int y, int width, int height);
+ static void drawNinePatch(const char* imageKey, uint32_t tint, int x, int y, int width, int height);
+ static bitmapFont* generateBitmapFont(const char* fontName, int fontStyle, int fontSize, int lineHeight, int spacing, int textureDimension);
+ static void measureBitmapString(bitmapFont* font, const char* message, int* width, int* height);
+ static void drawBitmapString(bitmapFont* font, const char* message, uint32_t color, int x, int y);
+ static void drawBitmapStringAligned(bitmapFont* font, const char* message, uint32_t color, horizAlignment hAlign, int x, int y, int width);
+ static utils::dataContainer* takeScreenshot();
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/drive.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/drive.cpp
new file mode 100644
index 0000000..310e562
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/drive.cpp
@@ -0,0 +1,129 @@
+#include "drive.h"
+#include
+#include "stringUtility.h"
+#include "XboxInternals.h"
+#include "fileSystem.h"
+#include "inputManager.h"
+
+drive::drive(const char* mountPoint, const char* mountPointAlias, const char* systemPath, driveType drive)
+{
+ mMountPoint = strdup(mountPoint);
+ mMountPointAlias = strdup(mountPointAlias);
+ mSystemPath = strdup(systemPath);
+ mMounted = false;
+ mDriveType = drive;
+}
+
+bool drive::mount()
+{
+ if (mDriveType == driveTypeMemoryUnit) {
+ mMounted = inputManager::isMemoryUnitMounted(mMountPoint[0]);
+ return mMounted;
+ }
+
+ if (mDriveType == driveTypeCdRom && mMounted == true) {
+ mMounted = false;
+ unmount();
+ }
+
+ if (mMounted == true)
+ {
+ return true;
+ }
+
+ char* mountPoint = stringUtility::formatString("\\??\\%s:", mMountPoint);
+ char* systemPath = stringUtility::formatString("%s", mSystemPath);
+ STRING sMountPoint = {(USHORT)strlen(mountPoint), (USHORT)strlen(mountPoint) + 1, mountPoint};
+ STRING sSystemPath = {(USHORT)strlen(systemPath), (USHORT)strlen(systemPath) + 1, systemPath};
+ int result = IoCreateSymbolicLink(&sMountPoint, &sSystemPath);
+ free(mountPoint);
+ free(systemPath);
+
+ if (mDriveType == driveTypeCdRom)
+ {
+ uint32_t trayState;
+ if (HalReadSMCTrayState(&trayState, NULL) >= 0 && trayState == SMC_TRAY_STATE_MEDIA_DETECT)
+ {
+ mMounted = true;
+ }
+ }
+ else
+ {
+ mMounted = getTotalNumberOfBytes() != 0;
+ }
+
+ return mMounted;
+}
+
+bool drive::unmount()
+{
+ if (mDriveType == driveTypeMemoryUnit) {
+ mMounted = false;
+ return mMounted;
+ }
+
+ char* mountPoint = stringUtility::formatString("\\??\\%s:", mMountPoint);
+ STRING sMountPoint = {(USHORT)strlen(mountPoint), (USHORT)strlen(mountPoint) + 1, mountPoint};
+ int result = IoDeleteSymbolicLink(&sMountPoint);
+ free(mountPoint);
+
+ char* systemPath = stringUtility::formatString("%s", mSystemPath);
+ char* systemPath2 = stringUtility::rightTrim(systemPath, '\\');
+ if (mDriveType == driveTypeCdRom)
+ {
+ STRING sSystemPath = {(USHORT)strlen(systemPath2), (USHORT)strlen(systemPath2) + 1, systemPath2};
+ result |= IoDismountVolumeByName(&sSystemPath);
+ }
+ free(systemPath2);
+ free(systemPath);
+
+ mMounted = false;
+ return result == 0;
+}
+
+bool drive::isMounted()
+{
+ return mMounted;
+}
+
+char* drive::getMountPoint()
+{
+ return strdup(mMountPoint);
+}
+
+char* drive::getMountPointAlias()
+{
+ return strdup(mMountPointAlias);
+}
+
+char* drive::getSystemPath()
+{
+ return strdup(mSystemPath);
+}
+
+uint64_t drive::getTotalNumberOfBytes()
+{
+ char* rootPath = stringUtility::formatString("%s:\\", mMountPoint);
+ ULARGE_INTEGER totalNumberOfBytes;
+ BOOL status = GetDiskFreeSpaceExA(rootPath, NULL, &totalNumberOfBytes, NULL);
+ free(rootPath);
+ if (status == 0)
+ {
+ return 0;
+ }
+ return (uint64_t)totalNumberOfBytes.QuadPart;
+}
+
+uint64_t drive::getTotalFreeNumberOfBytes()
+{
+ char* rootPath = stringUtility::formatString("%s:\\", mMountPoint);
+ ULARGE_INTEGER totalNumberOfFreeBytes = { 0 };
+ BOOL status = GetDiskFreeSpaceExA(rootPath, &totalNumberOfFreeBytes, NULL, NULL);
+ free(rootPath);
+ if (status == 0)
+ {
+ return 0;
+ }
+ return (uint64_t)totalNumberOfFreeBytes.QuadPart;
+}
+
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/drive.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/drive.h
new file mode 100644
index 0000000..e749a09
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/drive.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "xboxinternals.h"
+#include
+#include
+#include
+
+enum driveType
+{
+ driveTypeHardDrive,
+ driveTypeCdRom,
+ driveTypeMemoryUnit,
+};
+
+class drive
+{
+public:
+ drive(const char* mountPoint, const char* mountPointAlias, const char* systemPath, driveType drive);
+ bool mount();
+ bool unmount();
+ bool isMounted();
+ char* getMountPoint();
+ char* getMountPointAlias();
+ char* getSystemPath();
+ uint64_t getTotalNumberOfBytes();
+ uint64_t getTotalFreeNumberOfBytes();
+protected:
+ char* mMountPoint;
+ char* mMountPointAlias;
+ char* mSystemPath;
+ bool mMounted;
+ driveType mDriveType;
+};
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/driveManager.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/driveManager.cpp
new file mode 100644
index 0000000..27ad788
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/driveManager.cpp
@@ -0,0 +1,286 @@
+#include "driveManager.h"
+#include "pointerVector.h"
+#include "fileSystem.h"
+#include "stringUtility.h"
+#include "Drive.h"
+
+namespace
+{
+ bool mInitialized;
+ bool mAllMounted;
+ pointerVector* m_drives = NULL;
+}
+
+bool driveManager::getTotalNumberOfBytes(const char* mountPoint, uint64_t& totalSize)
+{
+ driveManager::mountDrive(mountPoint);
+
+ for (size_t i = 0; i < m_drives->count(); i++)
+ {
+ drive* currentDrive = m_drives->get(i);
+ if (strcmp(currentDrive->getMountPoint(), mountPoint) == 0)
+ {
+ totalSize = (uint64_t)currentDrive->getTotalNumberOfBytes();
+ return true;
+ }
+ }
+ return false;
+}
+
+bool driveManager::getTotalFreeNumberOfBytes(const char* mountPoint, uint64_t& totalFree)
+{
+ driveManager::mountDrive(mountPoint);
+
+ for (size_t i = 0; i < m_drives->count(); i++)
+ {
+ drive* currentDrive = m_drives->get(i);
+ char* currentMountPoint = currentDrive->getMountPoint();
+ if (strcmp(currentMountPoint, mountPoint) == 0)
+ {
+ totalFree = (uint64_t)currentDrive->getTotalFreeNumberOfBytes();
+ free(currentMountPoint);
+ return true;
+ }
+ free(currentMountPoint);
+ }
+ return false;
+}
+
+pointerVector* driveManager::getMountedDrives()
+{
+ driveManager::mountAllDrives();
+
+ pointerVector* drives = new pointerVector(false);
+ for (uint32_t i = 0; i < m_drives->count(); i++)
+ {
+ drive* currentDrive = m_drives->get(i);
+ if (currentDrive->isMounted())
+ {
+ drives->add(currentDrive->getMountPoint());
+ }
+ }
+ return drives;
+}
+
+char* driveManager::mapFtpPath(const char* path)
+{
+ char* tempPath = stringUtility::leftTrim(path, '/');
+ for (size_t i = 0; i < m_drives->count(); i++)
+ {
+ drive* currentDrive = m_drives->get(i);
+ char* mountPointAlias = currentDrive->getMountPointAlias();
+ if (stringUtility::startsWith(tempPath, mountPointAlias, true))
+ {
+ currentDrive->mount();
+ char* localFolder = stringUtility::substr(tempPath, strlen(mountPointAlias), -1);
+ char* mountPoint = currentDrive->getMountPoint();
+ char* localPath = stringUtility::formatString("%s:%s", mountPoint, localFolder);
+ char* result = stringUtility::replace(localPath, "/", "\\");
+ free(localFolder);
+ free(mountPoint);
+ free(localPath);
+ free(tempPath);
+ free(mountPointAlias);
+ return result;
+ }
+ free(mountPointAlias);
+ }
+ free(tempPath);
+ return strdup(path);
+}
+
+bool driveManager::ftpPathMounted(const char* path)
+{
+ char* tempPath = stringUtility::leftTrim(path, '/');
+ for (size_t i = 0; i < m_drives->count(); i++)
+ {
+ drive* currentDrive = m_drives->get(i);
+ char* mountPointAlias = currentDrive->getMountPointAlias();
+ if (stringUtility::startsWith(tempPath, mountPointAlias, true))
+ {
+ currentDrive->mount();
+ free(tempPath);
+ free(mountPointAlias);
+ return currentDrive->isMounted() == true;
+ }
+ free(mountPointAlias);
+ }
+ free(tempPath);
+ return false;
+}
+
+char* driveManager::convertMountPointToSystemPath(const char* path)
+{
+ for (size_t i = 0; i < m_drives->count(); i++)
+ {
+ drive* currentDrive = m_drives->get(i);
+ char* temp = currentDrive->getMountPoint();
+ if (stringUtility::startsWith(path, temp, true))
+ {
+ char* tempSystemPath = currentDrive->getSystemPath();
+ char* localFolder = stringUtility::substr(path, strlen(temp) + 1, -1);
+ char* localPath = stringUtility::formatString("%s%s", tempSystemPath, localFolder);
+ free(localFolder);
+ free(tempSystemPath);
+ free(temp);
+ return localPath;
+ }
+ free(temp);
+ }
+ return strdup(path);
+}
+
+char* driveManager::convertMountPointToMountPointAlias(const char* path)
+{
+ for (size_t i = 0; i < m_drives->count(); i++)
+ {
+ drive* currentDrive = m_drives->get(i);
+ char* temp = currentDrive->getMountPoint();
+ if (stringUtility::startsWith(path, temp, true))
+ {
+ char* tempMountPointAlias = currentDrive->getMountPointAlias();
+ char* localFolder = stringUtility::substr(path, strlen(temp), -1);
+ char* localPath = stringUtility::formatString("%s%s", tempMountPointAlias, localFolder);
+ free(localFolder);
+ free(tempMountPointAlias);
+ free(temp);
+ return localPath;
+ }
+ free(temp);
+ }
+ return strdup(path);
+}
+
+char* driveManager::convertMountPointAliasToMountPoint(const char* path)
+{
+ for (size_t i = 0; i < m_drives->count(); i++)
+ {
+ drive* currentDrive = m_drives->get(i);
+ char* temp = currentDrive->getMountPointAlias();
+ if (stringUtility::startsWith(path, temp, true))
+ {
+ char* tempMountPoint = currentDrive->getMountPoint();
+ char* localFolder = stringUtility::substr(path, strlen(temp), -1);
+ char* localPath = stringUtility::formatString("%s%s", tempMountPoint, localFolder);
+ free(localFolder);
+ free(tempMountPoint);
+ free(temp);
+ return localPath;
+ }
+ free(temp);
+ }
+ return strdup(path);
+}
+
+char* driveManager::getDrivePartition(const char* drvLtr) {
+ for (size_t i = 0; i < m_drives->count(); i++)
+ {
+ drive* currentDrive = m_drives->get(i);
+ char* mnt = currentDrive->getMountPoint();
+ if(stricmp(drvLtr, mnt) == 0) {
+ free(mnt);
+ return currentDrive->getSystemPath();
+ }
+ free(mnt);
+ }
+ return strdup("");
+}
+
+void driveManager::init()
+{
+ if (mInitialized == false)
+ {
+ m_drives = new pointerVector(true);
+
+ m_drives->add(new drive("DVD-ROM", "DVD-ROM", "\\Device\\Cdrom0", driveTypeCdRom));
+
+ m_drives->add(new drive("HDD0-C", "HDD0-C", "\\Device\\Harddisk0\\Partition2", driveTypeHardDrive));
+ m_drives->add(new drive("HDD0-E", "HDD0-E", "\\Device\\Harddisk0\\Partition1", driveTypeHardDrive));
+ m_drives->add(new drive("HDD0-F", "HDD0-F", "\\Device\\Harddisk0\\Partition6", driveTypeHardDrive));
+ m_drives->add(new drive("HDD0-G", "HDD0-G", "\\Device\\Harddisk0\\Partition7", driveTypeHardDrive));
+ m_drives->add(new drive("HDD0-H", "HDD0-H", "\\Device\\Harddisk0\\Partition8", driveTypeHardDrive));
+ m_drives->add(new drive("HDD0-I", "HDD0-I", "\\Device\\Harddisk0\\Partition9", driveTypeHardDrive));
+ m_drives->add(new drive("HDD0-J", "HDD0-J", "\\Device\\Harddisk0\\Partition10", driveTypeHardDrive));
+ m_drives->add(new drive("HDD0-K", "HDD0-K", "\\Device\\Harddisk0\\Partition11", driveTypeHardDrive));
+ m_drives->add(new drive("HDD0-L", "HDD0-L", "\\Device\\Harddisk0\\Partition12", driveTypeHardDrive));
+ m_drives->add(new drive("HDD0-M", "HDD0-M", "\\Device\\Harddisk0\\Partition13", driveTypeHardDrive));
+ m_drives->add(new drive("HDD0-N", "HDD0-N", "\\Device\\Harddisk0\\Partition14", driveTypeHardDrive));
+ m_drives->add(new drive("HDD0-X", "HDD0-X", "\\Device\\Harddisk0\\Partition3", driveTypeHardDrive));
+ m_drives->add(new drive("HDD0-Y", "HDD0-Y", "\\Device\\Harddisk0\\Partition4", driveTypeHardDrive));
+ m_drives->add(new drive("HDD0-Z", "HDD0-Z", "\\Device\\Harddisk0\\Partition5", driveTypeHardDrive));
+
+ m_drives->add(new drive("HDD1-C", "HDD1-C", "\\Device\\Harddisk1\\Partition2", driveTypeHardDrive));
+ m_drives->add(new drive("HDD1-E", "HDD1-E", "\\Device\\Harddisk1\\Partition1", driveTypeHardDrive));
+ m_drives->add(new drive("HDD1-F", "HDD1-F", "\\Device\\Harddisk1\\Partition6", driveTypeHardDrive));
+ m_drives->add(new drive("HDD1-G", "HDD1-G", "\\Device\\Harddisk1\\Partition7", driveTypeHardDrive));
+ m_drives->add(new drive("HDD1-H", "HDD1-H", "\\Device\\Harddisk1\\Partition8", driveTypeHardDrive));
+ m_drives->add(new drive("HDD1-I", "HDD1-I", "\\Device\\Harddisk1\\Partition9", driveTypeHardDrive));
+ m_drives->add(new drive("HDD1-J", "HDD1-J", "\\Device\\Harddisk1\\Partition10", driveTypeHardDrive));
+ m_drives->add(new drive("HDD1-K", "HDD1-K", "\\Device\\Harddisk1\\Partition11", driveTypeHardDrive));
+ m_drives->add(new drive("HDD1-L", "HDD1-L", "\\Device\\Harddisk1\\Partition12", driveTypeHardDrive));
+ m_drives->add(new drive("HDD1-M", "HDD1-M", "\\Device\\Harddisk1\\Partition13", driveTypeHardDrive));
+ m_drives->add(new drive("HDD1-N", "HDD1-N", "\\Device\\Harddisk1\\Partition14", driveTypeHardDrive));
+ m_drives->add(new drive("HDD1-X", "HDD1-X", "\\Device\\Harddisk1\\Partition3", driveTypeHardDrive));
+ m_drives->add(new drive("HDD1-Y", "HDD1-Y", "\\Device\\Harddisk1\\Partition4", driveTypeHardDrive));
+ m_drives->add(new drive("HDD1-Z", "HDD1-Z", "\\Device\\Harddisk1\\Partition5", driveTypeHardDrive));
+
+ m_drives->add(new drive("H", "MMU0", "", driveTypeMemoryUnit));
+ m_drives->add(new drive("I", "MMU1", "", driveTypeMemoryUnit));
+ m_drives->add(new drive("J", "MMU2", "", driveTypeMemoryUnit));
+ m_drives->add(new drive("K", "MMU3", "", driveTypeMemoryUnit));
+ m_drives->add(new drive("L", "MMU4", "", driveTypeMemoryUnit));
+ m_drives->add(new drive("M", "MMU5", "", driveTypeMemoryUnit));
+ m_drives->add(new drive("N", "MMU6", "", driveTypeMemoryUnit));
+ m_drives->add(new drive("O", "MMU7", "", driveTypeMemoryUnit));
+
+ //https://github.com/brentdc-nz/xbmc4xbox/blob/13cf4fbab8d70b154941a6b91e101bd05cc5b111/xbmc/utils/MemoryUnitManager.cpp#L77
+
+ mInitialized = true;
+ }
+}
+
+bool driveManager::mountDrive(const char* driveLetter)
+{
+ init();
+
+ for (size_t i = 0; i < m_drives->count(); i++)
+ {
+ drive* currentDrive = m_drives->get(i);
+ char* mountPoint = currentDrive->getMountPoint();
+
+ if (stringUtility::equals(mountPoint, driveLetter, true) == true)
+ {
+ free(mountPoint);
+ return currentDrive->mount();
+ }
+ free(mountPoint);
+ }
+ return false;
+}
+
+void driveManager::mountAllDrives()
+{
+ init();
+
+ for (size_t i = 0; i < m_drives->count(); i++)
+ {
+ drive* currentDrive = m_drives->get(i);
+ currentDrive->mount();
+ }
+ mAllMounted = true;
+}
+
+void driveManager::unmountAllDrives()
+{
+ for (size_t i = 0; i < m_drives->count(); i++)
+ {
+ drive* currentDrive = m_drives->get(i);
+ currentDrive->unmount();
+ }
+ mAllMounted = false;
+}
+
+bool driveManager::isAllMounted()
+{
+ return mAllMounted;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/driveManager.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/driveManager.h
new file mode 100644
index 0000000..eed7518
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/driveManager.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "Drive.h"
+#include "pointerVector.h"
+#include "xboxinternals.h"
+
+#include
+
+class driveManager
+{
+public:
+ static bool getTotalNumberOfBytes(const char* mountPoint, uint64_t& totalSize);
+ static bool getTotalFreeNumberOfBytes(const char* mountPoint, uint64_t& totalFree);
+ static pointerVector* getMountedDrives();
+ static char* getDrivePartition(const char* drvLtr);
+ static bool ftpPathMounted(const char* path);
+ static char* mapFtpPath(const char* path);
+ static char* convertMountPointToSystemPath(const char* path);
+ static char* convertMountPointToMountPointAlias(const char* path);
+ static char* convertMountPointAliasToMountPoint(const char* path);
+ static void init();
+ static bool mountDrive(const char* driveLetter);
+ static void mountAllDrives();
+ static void unmountAllDrives();
+ static bool isAllMounted();
+};
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/extensions.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/extensions.h
new file mode 100644
index 0000000..8610f06
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/extensions.h
@@ -0,0 +1,55 @@
+#pragma once
+
+char* strtok_r(char* str, const char* delimiters, char** saveptr)
+{
+ char* token;
+
+ if (str == NULL)
+ {
+ str = *saveptr;
+ }
+
+ if (*str == '\0')
+ {
+ *saveptr = str;
+ return NULL;
+ }
+
+ str += strspn(str, delimiters);
+
+ if (*str == '\0')
+ {
+ *saveptr = str;
+ return NULL;
+ }
+
+ token = str + strcspn(str, delimiters);
+ if (*token == '\0')
+ {
+ *saveptr = token;
+ return str;
+ }
+
+ *token = '\0';
+ *saveptr = token + 1;
+ return str;
+}
+
+int strnicmp(const char *str1, const char *str2, size_t n)
+{
+ for (size_t i = 0; i < n; i++)
+ {
+ if (str1[i] == '\0' || str2[i] == '\0')
+ {
+ return 0;
+ }
+ if (tolower((unsigned char)str1[i]) < tolower((unsigned char)str2[i]))
+ {
+ return -1;
+ } else if (tolower((unsigned char)str1[i]) > tolower((unsigned char)str2[i]))
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/fileSystem.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/fileSystem.cpp
new file mode 100644
index 0000000..69e99dc
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/fileSystem.cpp
@@ -0,0 +1,641 @@
+#include "fileSystem.h"
+#include "xboxInternals.h"
+#include "stringUtility.h"
+#include "driveManager.h"
+#include "pointerMap.h"
+
+#include
+#include
+#include
+
+namespace
+{
+ typedef struct FileContainer
+ {
+ void* file;
+ } FileContainer;
+
+ uint32_t mMaxFileContainerID = 0;
+
+ pointerMap* mFileContainerMap = new pointerMap(true);
+
+ uint32_t addFileContainer(FileContainer* fileContainer)
+ {
+ uint32_t result = mMaxFileContainerID;
+ mFileContainerMap->add(result, fileContainer);
+ mMaxFileContainerID++;
+ return result;
+ }
+
+ FileContainer* getFileContainer(uint32_t fileHandle)
+ {
+ FileContainer* fileContainer = mFileContainerMap->get(fileHandle);
+ return fileContainer;
+ }
+
+ void deleteFileContainer(uint32_t fileHandle)
+ {
+ mFileContainerMap->removeKey(fileHandle);
+ }
+}
+
+fileSystem::FileInfoDetail* fileSystem::fileGetFileInfoDetail(const char* path)
+{
+ const DWORD invalidFileAttributes = (DWORD)0xFFFFFFFF;
+
+ DWORD attributes = GetFileAttributesA(path);
+ if (attributes == invalidFileAttributes)
+ {
+ return NULL;
+ }
+
+ FileInfoDetail* fileInfoDetail = new FileInfoDetail();
+ fileInfoDetail->path = strdup(path);
+ fileInfoDetail->isDirectory = (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
+ fileInfoDetail->isFile = (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
+ fileInfoDetail->accessTime.month = 1;
+ fileInfoDetail->accessTime.day = 1;
+ fileInfoDetail->accessTime.year = 2000;
+ fileInfoDetail->accessTime.hour = 0;
+ fileInfoDetail->accessTime.minute = 0;
+ fileInfoDetail->accessTime.second = 0;
+ fileInfoDetail->writeTime.month = 1;
+ fileInfoDetail->writeTime.day = 1;
+ fileInfoDetail->writeTime.year = 2000;
+ fileInfoDetail->writeTime.hour = 0;
+ fileInfoDetail->writeTime.minute = 0;
+ fileInfoDetail->writeTime.second = 0;
+
+ HANDLE fileHandle = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, fileInfoDetail->isDirectory ? FILE_FLAG_BACKUP_SEMANTICS : 0, NULL);
+ if (fileHandle != INVALID_HANDLE_VALUE)
+ {
+ FILETIME fileTimeAccess;
+ FILETIME fileTimeWrite;
+ if (GetFileTime(fileHandle, NULL, &fileTimeAccess, &fileTimeWrite) == FALSE)
+ {
+ delete(fileInfoDetail);
+ return NULL;
+ }
+
+ SYSTEMTIME systemTimeAccessLocal;
+ if (FileTimeToSystemTime(&fileTimeAccess, &systemTimeAccessLocal) == FALSE)
+ {
+ delete(fileInfoDetail);
+ return NULL;
+ }
+
+ fileInfoDetail->accessTime.month = systemTimeAccessLocal.wMonth;
+ fileInfoDetail->accessTime.day = systemTimeAccessLocal.wDay;
+ fileInfoDetail->accessTime.year = systemTimeAccessLocal.wYear;
+ fileInfoDetail->accessTime.hour = systemTimeAccessLocal.wHour;
+ fileInfoDetail->accessTime.minute = systemTimeAccessLocal.wMinute;
+ fileInfoDetail->accessTime.second = systemTimeAccessLocal.wSecond;
+
+ if (fileTimeWrite.dwHighDateTime != 0 || fileTimeWrite.dwLowDateTime)
+ {
+ FILETIME fileTimeWriteLocal;
+ if (FileTimeToLocalFileTime(&fileTimeWrite, &fileTimeWriteLocal) == FALSE)
+ {
+ delete(fileInfoDetail);
+ return NULL;
+ }
+
+ SYSTEMTIME systemTimeWriteLocal;
+ if (FileTimeToSystemTime(&fileTimeWriteLocal, &systemTimeWriteLocal) == FALSE)
+ {
+ delete(fileInfoDetail);
+ return NULL;
+ }
+
+ fileInfoDetail->writeTime.month = systemTimeWriteLocal.wMonth;
+ fileInfoDetail->writeTime.day = systemTimeWriteLocal.wDay;
+ fileInfoDetail->writeTime.year = systemTimeWriteLocal.wYear;
+ fileInfoDetail->writeTime.hour = systemTimeWriteLocal.wHour;
+ fileInfoDetail->writeTime.minute = systemTimeWriteLocal.wMinute;
+ fileInfoDetail->writeTime.second = systemTimeAccessLocal.wSecond;
+ }
+ }
+
+ DWORD fileSize = GetFileSize(fileHandle, NULL);
+ fileInfoDetail->size = fileSize;
+
+ CloseHandle(fileHandle);
+ return fileInfoDetail;
+}
+
+pointerVector* fileSystem::fileGetFileInfoDetails(const char* path)
+{
+ pointerVector* fileInfoDetails = new pointerVector(true);
+
+ WIN32_FIND_DATAA findData;
+
+ char* searchPath = combinePath(path, "*");
+ HANDLE findHandle = FindFirstFileA(searchPath, &findData);
+ free(searchPath);
+ if (findHandle == INVALID_HANDLE_VALUE)
+ {
+ return fileInfoDetails;
+ }
+
+ do
+ {
+ if (findData.cFileName == "." || findData.cFileName == "..")
+ {
+ continue;
+ }
+ char* currentPath = combinePath(path, findData.cFileName);
+
+ FileInfoDetail* fileInfoDetail = fileGetFileInfoDetail(currentPath);
+ free(currentPath);
+
+ if (fileInfoDetail == NULL)
+ {
+ FindClose(findHandle);
+ delete(fileInfoDetails);
+ return NULL;
+ }
+ fileInfoDetails->add(fileInfoDetail);
+ }
+ while (FindNextFile(findHandle, &findData));
+ FindClose(findHandle);
+
+ for (uint32_t i = 0; i < fileInfoDetails->count() - 1; i++)
+ {
+ for (uint32_t j = i + 1; j < fileInfoDetails->count(); j++)
+ {
+ FileInfoDetail* fileInfoDetail1 = fileInfoDetails->get(i);
+ FileInfoDetail* fileInfoDetail2 = fileInfoDetails->get(j);
+ if (stricmp(fileInfoDetail1->path, fileInfoDetail2->path) > 0)
+ {
+ fileInfoDetails->swap(i, j);
+ }
+ }
+ }
+
+ return fileInfoDetails;
+}
+
+bool fileSystem::fileOpen(const char* path, FileMode const fileMode, uint32_t& fileHandle)
+{
+ char* access = "";
+ if (fileMode == FileModeRead) {
+ access = "rb";
+ }
+ else if (fileMode == FileModeWrite) {
+ access = "wb";
+ }
+ else if (fileMode == FileModeAppend) {
+ access = "ab";
+ }
+ else if (fileMode == FileModeReadUpdate) {
+ access = "r+b";
+ }
+ else if (fileMode == FileModeWriteUpdate) {
+ access = "w+b";
+ }
+ else if (fileMode == FileModeAppendUpdate) {
+ access = "a+b";
+ }
+ FileContainer* fileContainer = new FileContainer();
+ fileContainer->file = fopen(path, access);
+ if (fileContainer->file == NULL)
+ {
+ delete(fileContainer);
+ return false;
+ }
+ fileHandle = addFileContainer(fileContainer);
+ return true;
+}
+
+bool fileSystem::fileRead(uint32_t fileHandle, char* readBuffer, uint32_t const bytesToRead, uint32_t& bytesRead)
+{
+ FileContainer* fileContainer = getFileContainer(fileHandle);
+ if (fileContainer == NULL) {
+ return false;
+ }
+ bytesRead = (uint32_t)fread(readBuffer, 1, bytesToRead, (FILE*)fileContainer->file);
+ return true;
+}
+
+bool fileSystem::fileWrite(uint32_t fileHandle, char* writeBuffer, uint32_t bytesToWrite, uint32_t& bytesWritten)
+{
+ FileContainer* fileContainer = getFileContainer(fileHandle);
+ if (fileContainer == NULL) {
+ bytesWritten = 0;
+ return false;
+ }
+ bytesWritten = (uint32_t)fwrite(writeBuffer, 1, bytesToWrite, (FILE*)fileContainer->file);
+ return bytesWritten == bytesToWrite;
+}
+
+bool fileSystem::fileWrite(const char* path, char* writeBuffer, uint32_t bytesToWrite, uint32_t& bytesWritten)
+{
+ uint32_t fileHandle;
+ if (fileOpen(path, FileModeWrite, fileHandle) == false)
+ {
+ return false;
+ }
+ bool result = true;
+ if (fileWrite(fileHandle, writeBuffer, bytesToWrite, bytesWritten) == false)
+ {
+ result = false;
+ }
+ return fileClose(fileHandle) && result;
+}
+
+bool fileSystem::fileClose(uint32_t fileHandle)
+{
+ FileContainer* fileContainer = getFileContainer(fileHandle);
+ if (fileContainer == NULL) {
+ return false;
+ }
+ bool result = fclose((FILE*)fileContainer->file) == 0;
+ deleteFileContainer(fileHandle);
+ return result;
+}
+
+bool fileSystem::fileSeek(uint32_t fileHandle, FileSeekMode const fileSeekMode, uint32_t const offset)
+{
+ int seek = SEEK_CUR;
+ if (fileSeekMode == FileSeekModeStart)
+ {
+ seek = SEEK_SET;
+ }
+ else if (fileSeekMode == FileSeekModeEnd)
+ {
+ seek = SEEK_END;
+ }
+ FileContainer* fileContainer = getFileContainer(fileHandle);
+ if (fileContainer == NULL) {
+ return false;
+ }
+ FILE *file = (FILE*)fileContainer->file;
+ fseek(file, offset, seek);
+ return true;
+}
+
+bool fileSystem::filePosition(uint32_t fileHandle, uint32_t& position)
+{
+ FileContainer* fileContainer = getFileContainer(fileHandle);
+ if (fileContainer == NULL) {
+ return false;
+ }
+ FILE *file = (FILE*)fileContainer->file;
+ position = ftell(file);
+ return true;
+}
+
+bool fileSystem::fileTruncate(uint32_t fileHandle, uint32_t& position)
+{
+ FileContainer* fileContainer = getFileContainer(fileHandle);
+ if (fileContainer == NULL) {
+ return false;
+ }
+ FILE *file = (FILE*)fileContainer->file;
+ return _chsize(fileno(file), position) == 0;
+}
+
+bool fileSystem::setFileTime(const char* path, const FileTime fileTime)
+{
+ SYSTEMTIME systemTime;
+ systemTime.wYear = fileTime.year;
+ systemTime.wMonth = fileTime.month;
+ systemTime.wDay = fileTime.day;
+ systemTime.wDayOfWeek = 0;
+ systemTime.wHour = fileTime.hour;
+ systemTime.wMinute = fileTime.minute;
+ systemTime.wSecond = fileTime.second;
+ systemTime.wMilliseconds = 0;
+
+ FILETIME tempFileTime;
+ SystemTimeToFileTime(&systemTime, &tempFileTime);
+
+ HANDLE fileHandle = CreateFile(path, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (fileHandle == INVALID_HANDLE_VALUE) {
+ return false;
+ }
+
+ ::SetFileTime(fileHandle, NULL, NULL, &tempFileTime);
+ CloseHandle(fileHandle);
+ return true;
+}
+
+bool fileSystem::directoryCreate(const char* path)
+{
+ bool exists;
+ if (directoryExists(path, exists) == false)
+ {
+ return false;
+ }
+ if (exists)
+ {
+ return true;
+ }
+ return CreateDirectoryA(path, NULL) == TRUE;
+}
+
+bool fileSystem::directoryDelete(const char* path, bool const recursive)
+{
+ pointerVector* fileInfoDetails = fileGetFileInfoDetails(path);
+ if (fileInfoDetails == NULL)
+ {
+ return false;
+ }
+
+ for (uint32_t i = 0; i < fileInfoDetails->count(); i++)
+ {
+ FileInfoDetail* fileInfoDetail = fileInfoDetails->get(i);
+ if (fileInfoDetail->isDirectory)
+ {
+ const char* directoryToDelete = fileInfoDetail->path;
+ if (recursive && directoryDelete(directoryToDelete, true) == false)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ const char* fileToDelete = fileInfoDetail->path;
+ if (fileDelete(fileToDelete) == false)
+ {
+ return false;
+ }
+ }
+ }
+
+ delete(fileInfoDetails);
+ return RemoveDirectoryA(path) == TRUE;
+}
+
+bool fileSystem::fileDelete(const char* path)
+{
+ return remove(path) == 0;
+}
+
+bool fileSystem::fileCopy(const char* sourcePath, const char* destPath)
+{
+ uint32_t sourceFileHandle;
+ fileOpen(sourcePath, FileModeRead, sourceFileHandle);
+
+ uint32_t destFileHandle;
+ fileOpen(destPath, FileModeWrite, destFileHandle);
+
+ char *buffer = (char*)malloc(32758);
+
+ uint32_t bytesRead;
+ if (fileRead(sourceFileHandle, buffer, 32768, bytesRead) == false)
+ {
+ fileClose(sourceFileHandle);
+ fileClose(destFileHandle);
+ return false;
+ }
+
+ while (bytesRead > 0)
+ {
+ uint32_t bytesWritten;
+ if (fileWrite(destFileHandle, buffer, bytesRead, bytesWritten) == false || bytesWritten != bytesRead)
+ {
+ fileClose(sourceFileHandle);
+ fileClose(destFileHandle);
+ return false;
+ }
+ if (fileRead(sourceFileHandle, buffer, 32768, bytesRead) == false)
+ {
+ fileClose(sourceFileHandle);
+ fileClose(destFileHandle);
+ return false;
+ }
+ }
+
+ free(buffer);
+
+ fileClose(sourceFileHandle);
+ fileClose(destFileHandle);
+ return true;
+}
+
+bool fileSystem::fileMove(const char* sourcePath, const char* destPath)
+{
+ BOOL result = MoveFileA(sourcePath, destPath);
+ return result == TRUE;
+}
+
+bool fileSystem::fileSize(uint32_t fileHandle, uint32_t& size)
+{
+ FileContainer* fileContainer = getFileContainer(fileHandle);
+ if (fileContainer == NULL) {
+ return false;
+ }
+ FILE* file = (FILE*)fileContainer->file;
+ uint32_t filePosition = ftell(file);
+ fseek(file, 0, SEEK_END);
+ size = ftell(file);
+ fseek(file, filePosition, SEEK_SET);
+ return true;
+}
+
+bool fileSystem::fileExists(const char* path, bool& exists)
+{
+ FileInfoDetail* fileInfoDetail = fileGetFileInfoDetail(path);
+ if (fileInfoDetail == NULL)
+ {
+ exists = false;
+ return true;
+ }
+ exists = fileInfoDetail->isFile;
+ delete(fileInfoDetail);
+ return true;
+}
+
+bool fileSystem::directoryExists(const char* path, bool& exists)
+{
+ FileInfoDetail* fileInfoDetail = fileGetFileInfoDetail(path);
+ if (fileInfoDetail == NULL)
+ {
+ exists = false;
+ return true;
+ }
+ exists = fileInfoDetail->isDirectory;
+ delete(fileInfoDetail);
+ return true;
+}
+
+// Tested
+char* fileSystem::getFileName(const char* path)
+{
+ uint32_t length = 0;
+ for (int i = (uint32_t)strlen(path); i > 0; i--)
+ {
+ if (path[i - 1] == '\\')
+ {
+ break;
+ }
+ length++;
+ }
+
+ char* result = (char*)malloc(length + 1);
+ if (result == NULL)
+ {
+ return NULL;
+ }
+
+ strncpy(result, path + strlen(path) - length, length);
+ result[length] = 0;
+ return result;
+}
+
+char* fileSystem::getRootPath(const char* path)
+{
+ if(!path) {
+ return strdup("");
+ }
+
+ if(path[0] == '\\') {
+ return strdup(path);
+ }
+
+ uint32_t length = 0;
+ size_t pathLen = strlen(path);
+
+ for (int i = 0; i < pathLen; i++) {
+ if (path[i] == ':') {
+ break;
+ }
+ length++;
+ }
+
+ char* result = (char*)malloc(pathLen + 1);
+ if (result == NULL)
+ {
+ return NULL;
+ }
+
+ strncpy(result, path + length + 1, pathLen - length - 1);
+ result[pathLen - length - 1] = 0;
+ return result;
+}
+
+char* fileSystem::getDriveLetter(const char* path)
+{
+ uint32_t length = 0;
+
+ if(!path || path[0] == '\\') {
+ return strdup("");
+ }
+
+ for (int i = 0; i < strlen(path); i++) {
+ if (path[i] == ':') {
+ break;
+ }
+ length++;
+ }
+
+ char* result = (char*)malloc(length + 1);
+ if (result == NULL)
+ {
+ return NULL;
+ }
+
+ strncpy(result, path, length);
+ result[length] = 0;
+ return result;
+}
+
+char* fileSystem::getFileNameWithoutExtension(const char* path)
+{
+ char* fileName = getFileName(path);
+ char* extension = getExtension(fileName);
+ char* result = stringUtility::substr(fileName, 0, strlen(fileName) - strlen(extension));
+ free(extension);
+ free(fileName);
+ return result;
+}
+
+// Tested
+char* fileSystem::getExtension(const char* path)
+{
+ uint32_t length = 0;
+ for (int i = (uint32_t)strlen(path); i > 0; i--)
+ {
+ if (path[i - 1] == '.')
+ {
+ length++;
+ break;
+ }
+ if (path[i - 1] == '\\' || path[i - 1] == '.')
+ {
+ break;
+ }
+ length++;
+ }
+
+ char* result = (char*)malloc(length + 1);
+ if (result == NULL)
+ {
+ return NULL;
+ }
+
+ strncpy(result, path + strlen(path) - length, length);
+ result[length] = 0;
+ return result;
+}
+
+// Tested
+char* fileSystem::getDirectory(const char* path)
+{
+ int32_t length = 0;
+ for (int i = (uint32_t)strlen(path); i > 0; i--)
+ {
+ if (path[i - 1] == '\\')
+ {
+ break;
+ }
+ length++;
+ }
+
+ length = length == 0 ? 0 : strlen(path) - length - 1;
+ if (length < 0)
+ {
+ return strdup("");
+ }
+
+ char* result = (char*)malloc(length + 1);
+ if (result == NULL)
+ {
+ return NULL;
+ }
+
+ strncpy(result, path, length);
+ result[length] = 0;
+ return result;
+}
+
+// Tested
+char* fileSystem::combinePath(const char* first, const char* second)
+{
+ if (strlen(first) == 0)
+ {
+ return strdup(second);
+ }
+
+ if (strlen(second) == 0)
+ {
+ return strdup(first);
+ }
+
+ char* trimmedFirst = stringUtility::rightTrim(first, '\\');
+ char* trimmedSecond = stringUtility::leftTrim(second, '\\');
+
+ uint32_t length = strlen(trimmedFirst) + 1 + strlen(trimmedSecond) + 1;
+ char* result = (char*)malloc(length);
+ if (result == NULL)
+ {
+ return NULL;
+ }
+
+ strcpy(result, trimmedFirst);
+ strcpy(result + strlen(trimmedFirst), "\\");
+ strcpy(result + strlen(trimmedFirst) + 1, trimmedSecond);
+ result[length - 1] = 0;
+ return result;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/fileSystem.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/fileSystem.h
new file mode 100644
index 0000000..59deeab
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/fileSystem.h
@@ -0,0 +1,97 @@
+#pragma once
+
+#include "xboxinternals.h"
+#include "pointerVector.h"
+
+#include
+
+class fileSystem
+{
+public:
+
+ typedef enum FileMode
+ {
+ FileModeRead = 0,
+ FileModeWrite = 1,
+ FileModeAppend = 2,
+ FileModeReadUpdate = 3,
+ FileModeWriteUpdate = 4,
+ FileModeAppendUpdate = 5
+ } FileMode;
+
+ typedef enum FileSeekMode
+ {
+ FileSeekModeStart = 0,
+ FileSeekModeEnd = 1,
+ FileSeekModeCurrent = 2
+ } FileSeekMode;
+
+ typedef struct FileTime
+ {
+ uint16_t month;
+ uint16_t day;
+ uint16_t year;
+ uint16_t hour;
+ uint16_t minute;
+ uint16_t second;
+ } FileTime;
+
+ typedef struct FileInfoDetail
+ {
+ bool isDirectory;
+ bool isFile;
+ bool isVirtual;
+ char* path;
+ uint32_t size;
+ FileTime accessTime;
+ FileTime writeTime;
+
+ FileInfoDetail()
+ {
+ isDirectory = false;
+ isFile = false;
+ isVirtual = false;
+ path = NULL;
+ size = 0;
+ memset(&accessTime, 0, sizeof(FileTime));
+ memset(&writeTime, 0, sizeof(FileTime));
+ }
+
+ ~FileInfoDetail()
+ {
+ delete(path);
+ }
+
+ } FileInfoDetail;
+
+ static fileSystem::FileInfoDetail* fileGetFileInfoDetail(const char* path);
+ static pointerVector* fileGetFileInfoDetails(const char* path);
+
+ static bool fileOpen(const char* path, FileMode const fileMode, uint32_t& fileHandle);
+ static bool fileRead(uint32_t fileHandle, char* readBuffer, uint32_t const bytesToRead, uint32_t& bytesRead);
+ static bool fileWrite(uint32_t fileHandle, char* writeBuffer, uint32_t bytesToWrite, uint32_t& bytesWritten);
+ static bool fileWrite(const char* path, char* writeBuffer, uint32_t bytesToWrite, uint32_t& bytesWritten);
+ static bool fileClose(uint32_t fileHandle);
+ static bool fileSeek(uint32_t fileHandle, FileSeekMode const fileSeekMode, uint32_t const offset);
+ static bool filePosition(uint32_t fileHandle, uint32_t& position);
+ static bool fileTruncate(uint32_t fileHandle, uint32_t& position);
+ static bool setFileTime(const char* path, const FileTime fileTime);
+
+ static bool directoryCreate(const char* path);
+ static bool directoryDelete(const char* path, bool const recursive);
+ static bool fileDelete(const char* path);
+ static bool fileCopy(const char* sourcePath, const char* destPath);
+ static bool fileMove(const char* sourcePath, const char* destPath);
+ static bool fileSize(uint32_t fileHandle, uint32_t& size);
+ static bool fileExists(const char* path, bool& exists);
+ static bool directoryExists(const char* path, bool& exists);
+
+ static char* getDriveLetter(const char* path);
+ static char* getRootPath(const char* path);
+ static char* getFileName(const char* path);
+ static char* getFileNameWithoutExtension(const char* path);
+ static char* getExtension(const char* path);
+ static char* getDirectory(const char* path);
+ static char* combinePath(const char* first, const char* second);
+};
+
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/ftpServer.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/ftpServer.cpp
new file mode 100644
index 0000000..1dfc30b
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/ftpServer.cpp
@@ -0,0 +1,1332 @@
+#include "ftpServer.h"
+#include "socketUtility.h"
+#include "fileSystem.h"
+#include "driveManager.h"
+#include "crc32.h"
+#include
+#include
+#include "stringUtility.h"
+#include "utils.h"
+
+#include
+
+#define SERVERID "PrometheOS FTP, welcome..."
+
+namespace {
+
+ LONG activeConnections = 0;
+
+ int mMaxConnections;
+ int mCommandTimeout;
+ int mConnectTimeout;
+
+ bool mStopRequested;
+
+ uint64_t sListen;
+ sockaddr_in saiListen;
+
+ HANDLE mListenThreadHandle;
+
+ int incrementConnections()
+ {
+ return (int)_InterlockedIncrement(&activeConnections);
+ }
+
+ void decrementConnections()
+ {
+ _InterlockedDecrement(&activeConnections);
+ }
+
+ char* cleanVirtualPath(const char* virtualPath)
+ {
+ const char* in = virtualPath;
+ char* buf = new char[strlen(in) + 4];
+ buf[0] = '\0';
+ buf[1] = '\0';
+ buf[2] = '\0';
+ char* out = buf + 3;
+ do {
+ *out = *in;
+ if (*out == '\\') *out = '/'; // convert backslashes to forward slashes
+ if ((*out == '\0') || (*out == '/')) {
+ if (out[-1] == '.') { // output ends with "."
+ if (out[-2] == '\0') --out; // entire output is "."
+ else if (out[-2] == '/') { // output ends with "/."
+ if (out[-3] == '\0') --out; // entire output is "/."
+ else out -= 2;
+ }
+ else if (out[-2] == '.') { // output ends with ".."
+ if (out[-3] == '\0') out -= 2; // entire output is ".."
+ else if (out[-3] == '/') { // output ends with "/.."
+ if (out[-4] == '\0') out -= 2; // entire output is "/.."
+ else {
+ out -= 3;
+ while ((out[-1] != '\0') && (out[-1] != '/')) --out;
+ }
+ }
+ }
+ else ++in;
+ }
+ else {
+ ++in;
+ if (out[-1] != '/') ++out;
+ }
+ }
+ else ++in, ++out;
+ } while (in[-1] != '\0');
+
+ char* result = strdup(buf + 3);
+ delete[] buf;
+ return result;
+ }
+
+ char* resolveRelative(const char* currentVirtual, const char* relativeVirtual)
+ {
+ if (relativeVirtual[0] != '/') {
+ char* newVirtual = stringUtility::formatString("%s\\%s", currentVirtual, relativeVirtual);
+ char *result = cleanVirtualPath(newVirtual);
+ free(newVirtual);
+ return result;
+ }
+ else {
+ char *result = cleanVirtualPath(relativeVirtual);
+ return result;
+ }
+ }
+
+ pointerVector* getDirectoryListing(const char* virtualPath)
+ {
+ if (stringUtility::equals(virtualPath, "/", false) == true)
+ {
+ pointerVector* fileInfoDetails = new pointerVector(true);
+ pointerVector* drives = driveManager::getMountedDrives();
+
+ for (size_t i = 0; i < drives->count(); i++)
+ {
+ fileSystem::FileInfoDetail* fileInfoDetail = new fileSystem::FileInfoDetail();
+ char* mountPoint = stringUtility::formatString("%s:", drives->get(i));
+ char* mountAlias = driveManager::convertMountPointToMountPointAlias(mountPoint);
+ mountAlias[strlen(mountAlias)-1] = '\0';
+
+ fileInfoDetail->isDirectory = true;
+ fileInfoDetail->isFile = false;
+ fileInfoDetail->isVirtual = true;
+ fileInfoDetail->path = mountAlias;
+ fileInfoDetail->accessTime.day = 1;
+ fileInfoDetail->accessTime.month = 1;
+ fileInfoDetail->accessTime.year = 2000;
+ fileInfoDetail->accessTime.minute = 0;
+ fileInfoDetail->accessTime.hour = 0;
+ fileInfoDetail->accessTime.second = 0;
+ fileInfoDetail->writeTime.day = 1;
+ fileInfoDetail->writeTime.month = 1;
+ fileInfoDetail->writeTime.year = 2000;
+ fileInfoDetail->writeTime.minute = 0;
+ fileInfoDetail->writeTime.hour = 0;
+ fileInfoDetail->writeTime.second = 0;
+ fileInfoDetails->add(fileInfoDetail);
+
+ free(mountPoint);
+ }
+
+ delete(drives);
+ return fileInfoDetails;
+ }
+
+ if (driveManager::ftpPathMounted(virtualPath) == false)
+ {
+ return NULL;
+ }
+
+ char* ftpPath = driveManager::mapFtpPath(virtualPath);
+
+ pointerVector* fileInfoDetails = fileSystem::fileGetFileInfoDetails(ftpPath);;
+ free(ftpPath);
+
+ if (fileInfoDetails == NULL)
+ {
+ return NULL;
+ }
+ for (size_t i = 0; i < fileInfoDetails->count(); i++)
+ {
+ fileSystem::FileInfoDetail* fileInfoDetail = fileInfoDetails->get(i);
+ fileInfoDetail->path = fileSystem::getFileName(fileInfoDetail->path);
+ }
+
+ return fileInfoDetails;
+ }
+}
+
+bool WINAPI ftpServer::connectionThread(uint64_t sCmd)
+{
+ uint64_t sData = 0;
+ uint64_t sPasv = 0;
+ char szPeerName[64];
+ char szOutput[1024];
+ char szCmd[512];
+ char* pszParam;
+ char* user = NULL;
+ char* currentVirtual = NULL;
+ char* rnfr = NULL;
+ uint32_t dw = 0;
+ uint32_t dwRestOffset = 0;
+ ReceiveStatus status = ReceiveStatus_OK;
+ bool isLoggedIn = false;
+ fileSystem::FileTime fileTime;
+ UINT_PTR i;
+
+ SOCKADDR_IN saiCmd;
+ memset(&saiCmd, 0, sizeof(SOCKADDR_IN));
+ SOCKADDR_IN saiCmdPeer;
+ memset(&saiCmdPeer, 0, sizeof(SOCKADDR_IN));
+ SOCKADDR_IN saiPasv;
+ memset(&saiPasv, 0, sizeof(SOCKADDR_IN));
+ SOCKADDR_IN saiData;
+ memset(&saiData, 0, sizeof(SOCKADDR_IN));
+
+ // Get peer address
+ dw=sizeof(SOCKADDR_IN);
+ getpeername((SOCKET)sCmd, (SOCKADDR *)&saiCmdPeer, (int *)&dw);
+ sprintf(szPeerName, "%u.%u.%u.%u",
+ saiCmdPeer.sin_addr.S_un.S_un_b.s_b1,
+ saiCmdPeer.sin_addr.S_un.S_un_b.s_b2,
+ saiCmdPeer.sin_addr.S_un.S_un_b.s_b3,
+ saiCmdPeer.sin_addr.S_un.S_un_b.s_b4);
+
+ // Send greeting
+ sprintf(szOutput, "220-%s\r\n220-You are connecting from %s:%u.\r\n220 Proceed with login.\r\n", SERVERID, szPeerName, ntohs(saiCmdPeer.sin_port));
+ socketSendString(sCmd, szOutput);
+
+ socketUtility::getSocketName(sCmd, &saiCmd);
+
+ // Command processing loop
+ while (mStopRequested == false) {
+
+ const int result = socketUtility::getReadStatus(sCmd);
+ if (result != 1)
+ {
+ Sleep(50);
+ continue;
+ }
+
+ status = socketReceiveString(sCmd, szCmd, 512, &dw);
+
+ if (status == ReceiveStatus_Network_Error) {
+ socketSendString(sCmd, "421 Network error.\r\n");
+ break;
+ } else if (status == ReceiveStatus_Timeout) {
+ socketSendString(sCmd, "421 Connection timed out.\r\n");
+ break;
+ } else if (status == ReceiveStatus_Invalid_Data) {
+ socketSendString(sCmd, "500 Malformed request.\r\n");
+ continue;
+ } else if (status == ReceiveStatus_Insufficient_Buffer) {
+ socketSendString(sCmd, "500 Command line too long.\r\n");
+ continue;
+ }
+
+ if (pszParam = strchr(szCmd, ' ')) {
+ *(pszParam++) = 0;
+ } else {
+ pszParam = szCmd + strlen(szCmd);
+ }
+
+ if (!stricmp(szCmd, "USER")) {
+ if (!*pszParam) {
+ socketSendString(sCmd, "501 Syntax error in parameters or arguments.\r\n");
+ continue;
+ } else if (isLoggedIn) {
+ socketSendString(sCmd, "503 Already logged in. Use REIN to change users.\r\n");
+ continue;
+ } else {
+ free(user);
+ user = strdup(pszParam);
+ if (stringUtility::equals(user, "xbox", false) == true)
+ {
+ sprintf(szOutput, "331 Need password for user \"%s\".\r\n", user);
+ socketSendString(sCmd, szOutput);
+ continue;
+ }
+ }
+ }
+
+ if (!stricmp(szCmd, "PASS")) {
+ if (user == NULL) {
+ socketSendString(sCmd, "503 Bad sequence of commands. Send USER first.\r\n");
+ } else if (isLoggedIn) {
+ socketSendString(sCmd, "503 Already logged in. Use REIN to change users.\r\n");
+ } else {
+ if (stringUtility::equals(user, "xbox", false) && stringUtility::equals(pszParam, "xbox", false)) {
+ if (incrementConnections() <= mMaxConnections) {
+ isLoggedIn = true;
+ free(currentVirtual);
+ currentVirtual = strdup("/");
+ sprintf(szOutput, "230 User \"%s\" logged in.\r\n", user);
+ socketSendString(sCmd, szOutput);
+ } else {
+ decrementConnections();
+ socketSendString(sCmd, "421 Your login was refused due to a server connection limit.\r\n");
+ break;
+ }
+ } else {
+ socketSendString(sCmd, "530 Incorrect password.\r\n");
+ }
+ }
+ }
+
+ else if (!stricmp(szCmd, "REIN")) {
+ if (isLoggedIn) {
+ isLoggedIn = false;
+ decrementConnections();
+ sprintf(szOutput, "220-User \"%s\" logged out.\r\n", user);
+ socketSendString(sCmd, szOutput);
+ free(user);
+ user = NULL;
+ }
+ socketSendString(sCmd, "220 REIN command successful.\r\n");
+ }
+
+ else if (!stricmp(szCmd, "HELP")) {
+ socketSendString(sCmd, "214 For help, please cry to mom.\r\n");
+ }
+
+ else if (!stricmp(szCmd, "FEAT")) {
+ socketSendString(sCmd, "211-Extensions supported:\r\n SIZE\r\n REST STREAM\r\n MDTM\r\n TVFS\r\n XCRC\r\n211 END\r\n");
+ }
+
+ //else if (!stricmp(szCmd, "SYST")) {
+ // sprintf(szOutput, "215 Windows_NT\r\n");
+ // socketSendString(sCmd, szOutput);
+ //}
+
+ else if (!stricmp(szCmd, "QUIT")) {
+ if (isLoggedIn) {
+ isLoggedIn = false;
+ decrementConnections();
+ sprintf(szOutput, "221-User \"%s\" logged out.\r\n", user);
+ socketSendString(sCmd, szOutput);
+ }
+ socketSendString(sCmd, "221 Goodbye!\r\n");
+ break;
+ }
+
+ else if (!stricmp(szCmd, "NOOP")) {
+ socketSendString(sCmd, "200 NOOP command successful.\r\n");
+ }
+
+ else if (!stricmp(szCmd, "PWD") || !stricmp(szCmd, "XPWD")) {
+ if (!isLoggedIn) {
+ socketSendString(sCmd, "530 Not logged in.\r\n");
+ } else {
+ sprintf(szOutput, "257 \"%s\" is current directory.\r\n", currentVirtual);
+ socketSendString(sCmd, szOutput);
+ }
+ }
+
+ else if (!stricmp(szCmd, "CWD") || !stricmp(szCmd, "XCWD")) {
+ if (!*pszParam) {
+ socketSendString(sCmd, "501 Syntax error in parameters or arguments.\r\n");
+ } else if (!isLoggedIn) {
+ socketSendString(sCmd, "530 Not logged in.\r\n");
+ } else {
+ char* newVirtual = resolveRelative(currentVirtual, pszParam);
+ bool isFolder = false;
+ if (stringUtility::equals(newVirtual, "/", false))
+ {
+ isFolder = true;
+ }
+ else
+ {
+ char* ftpPath = driveManager::mapFtpPath(newVirtual);
+ if (stringUtility::endsWith(ftpPath, ":", false))
+ {
+ isFolder = true;
+ }
+ else
+ {
+ fileSystem::directoryExists(ftpPath, isFolder);
+ }
+ free(ftpPath);
+ }
+
+ if (isFolder == true)
+ {
+ free(currentVirtual);
+ currentVirtual = strdup(newVirtual);
+ sprintf(szOutput, "250 \"%s\" is now current directory.\r\n", currentVirtual);
+ socketSendString(sCmd, szOutput);
+ }
+ else
+ {
+ sprintf(szOutput, "550 %s failed. \"%s\": directory not found.\r\n", szCmd, newVirtual);
+ socketSendString(sCmd, szOutput);
+ }
+
+ free(newVirtual);
+ }
+ }
+
+ else if (!stricmp(szCmd, "CDUP") || !stricmp(szCmd, "XCUP")) {
+ if (!isLoggedIn) {
+ socketSendString(sCmd, "530 Not logged in.\r\n");
+ } else {
+
+ char* tempCurrentVirtual = resolveRelative(currentVirtual, "..");
+ free(currentVirtual);
+ currentVirtual = tempCurrentVirtual;
+
+ sprintf(szOutput, "250 \"%s\" is now current directory.\r\n", currentVirtual);
+ socketSendString(sCmd, szOutput);
+ }
+ }
+
+ else if (!stricmp(szCmd, "TYPE")) {
+ if (!*pszParam) {
+ socketSendString(sCmd, "501 Syntax error in parameters or arguments.\r\n");
+ } else if (!isLoggedIn) {
+ socketSendString(sCmd, "530 Not logged in.\r\n");
+ } else {
+ socketSendString(sCmd, "200 TYPE command successful.\r\n");
+ }
+ }
+
+ else if (!stricmp(szCmd, "REST")) {
+ if (!*pszParam || (!(dw = stringUtility::toInt(pszParam)) && (*pszParam != '0'))) {
+ socketSendString(sCmd, "501 Syntax error in parameters or arguments.\r\n");
+ } else if (!isLoggedIn) {
+ socketSendString(sCmd, "530 Not logged in.\r\n");
+ } else {
+ dwRestOffset = dw;
+ sprintf(szOutput, "350 Ready to resume transfer at %u bytes.\r\n", dwRestOffset);
+ socketSendString(sCmd, szOutput);
+ }
+ }
+
+ else if (!stricmp(szCmd, "PORT")) {
+ if (!*pszParam) {
+ socketSendString(sCmd, "501 Syntax error in parameters or arguments.\r\n");
+ } else if (!isLoggedIn) {
+ socketSendString(sCmd, "530 Not logged in.\r\n");
+ } else {
+ memset(&saiData, 0, sizeof(SOCKADDR_IN));
+ saiData.sin_family = AF_INET;
+
+ unsigned char h1 = 0;
+ unsigned char h2 = 0;
+ unsigned char h3 = 0;
+ unsigned char h4 = 0;
+ unsigned char p1 = 0;
+ unsigned char p2 = 0;
+
+ dw = scanf(pszParam, "%hu,%hu,%hu,%hu,%hu,%hu", &h1, &h2, &h3, &h4, &p1, &p2);
+
+ saiData.sin_addr.S_un.S_un_b.s_b1 = h1;
+ saiData.sin_addr.S_un.S_un_b.s_b2 = h2;
+ saiData.sin_addr.S_un.S_un_b.s_b3 = h3;
+ saiData.sin_addr.S_un.S_un_b.s_b4 = h4;
+ saiData.sin_port = (p2 << 8) + p1;
+
+ if (dw == 6) {
+ socketUtility::closeSocket(sPasv);
+ socketSendString(sCmd, "200 PORT command successful.\r\n");
+ } else {
+ socketSendString(sCmd, "501 Syntax error in parameters or arguments.\r\n");
+ memset(&saiData, 0, sizeof(SOCKADDR_IN));
+ }
+ }
+ }
+
+ else if (!stricmp(szCmd, "PASV")) {
+ if (!isLoggedIn) {
+ socketSendString(sCmd, "530 Not logged in.\r\n");
+ } else {
+
+ if (sPasv) {
+ socketUtility::closeSocket(sPasv);
+ }
+
+ static u_short portTest = 6000;
+
+ XNADDR addr;
+ XNetGetTitleXnAddr(&addr);
+
+ bool found = false;
+ while (!found) {
+ memset(&saiPasv, 0, sizeof(SOCKADDR_IN));
+ saiPasv.sin_family = AF_INET;
+ saiPasv.sin_addr.s_addr = INADDR_ANY;
+ saiPasv.sin_port = portTest;
+ if (socketUtility::createSocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, sPasv))
+ {
+ found = true;
+ }
+ else
+ {
+ utils::debugPrint("Error: Could not create socket on port %u, trying to find next available.\n", portTest);
+ }
+ portTest++;
+ if (portTest > 6999)
+ {
+ portTest = 6000;
+ }
+ }
+
+ socketUtility::bindSocket(sPasv, &saiPasv);
+ socketUtility::listenSocket(sPasv, 1);
+ socketUtility::getSocketName(sPasv, &saiPasv);
+
+ sprintf(szOutput, "227 Entering Passive Mode (%u,%u,%u,%u,%u,%u)\r\n",
+ addr.ina.S_un.S_un_b.s_b1,
+ addr.ina.S_un.S_un_b.s_b2,
+ addr.ina.S_un.S_un_b.s_b3,
+ addr.ina.S_un.S_un_b.s_b4,
+ ((unsigned char *)&saiPasv.sin_port)[0],
+ ((unsigned char *)&saiPasv.sin_port)[1]);
+ socketSendString(sCmd, szOutput);
+ }
+ }
+
+ else if (!stricmp(szCmd, "LIST") || !stricmp(szCmd, "NLST"))
+ {
+ if (!isLoggedIn)
+ {
+ socketSendString(sCmd, "530 Not logged in.\r\n");
+ }
+ else
+ {
+ if (*pszParam == '-')
+ {
+ if (pszParam = strchr(pszParam, ' '))
+ {
+ pszParam++;
+ }
+ }
+ char* newVirtual = pszParam && *pszParam ? resolveRelative(currentVirtual, pszParam) : strdup(currentVirtual);
+
+ pointerVector* fileInfoDetails = getDirectoryListing(newVirtual);
+ if (fileInfoDetails != NULL)
+ {
+ sprintf(szOutput, "150 Opening %s mode data connection for listing of \"%s\".\r\n", sPasv ? "passive" : "active", newVirtual);
+ socketSendString(sCmd, szOutput);
+ sData = establishDataConnection(&saiData, &sPasv);
+ if (sData)
+ {
+ const char * months[12] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
+ for (size_t i = 0; i < fileInfoDetails->count(); i++)
+ {
+ char szLine[512];
+ fileSystem::FileInfoDetail* fileInfoDetail = fileInfoDetails->get(i);
+ if (stricmp(szCmd, "NLST") == 0)
+ {
+ strcpy(szLine, fileInfoDetail->path);
+ }
+ else
+ {
+ sprintf(szLine, "%c--------- 1 ftp ftp %llu ", fileInfoDetail->isDirectory ? 'd' : '-', fileInfoDetail->size);
+ strcat(szLine, months[fileInfoDetail->writeTime.month - 1]);
+ sprintf(szLine + strlen(szLine), " %2i %.2i:%.2i ", fileInfoDetail->writeTime.day, fileInfoDetail->writeTime.hour, fileInfoDetail->writeTime.minute);
+ strcat(szLine, fileInfoDetail->path);
+ }
+ //if (fileInfoDetail->fileInfoDetail->isDirectory == true)
+ //{
+ // strcat(szLine, "/");
+ //}
+ strcat(szLine, "\r\n");
+ socketSendString(sData, szLine);
+ }
+ socketUtility::closeSocket(sData);
+ sprintf(szOutput, "226 %s command successful.\r\n", stricmp(szCmd, "NLST") ? "LIST" : "NLST");
+ socketSendString(sCmd, szOutput);
+ }
+ else
+ {
+ socketSendString(sCmd, "425 Can't open data connection.\r\n");
+ }
+ }
+ else
+ {
+ sprintf(szOutput, "550 \"%s\": Path not found.\r\n", newVirtual);
+ socketSendString(sCmd, szOutput);
+ }
+ free(newVirtual);
+ delete(fileInfoDetails);
+ }
+ }
+
+ else if (!stricmp(szCmd, "STAT")) {
+ if (!isLoggedIn) {
+ socketSendString(sCmd, "530 Not logged in.\r\n");
+ } else {
+ if (*pszParam == '-')
+ {
+ if (pszParam = strchr(pszParam, ' '))
+ {
+ pszParam++;
+ }
+ }
+
+ char* newVirtual = pszParam && *pszParam ? resolveRelative(currentVirtual, pszParam) : strdup(currentVirtual);
+
+ pointerVector* fileInfoDetails = getDirectoryListing(newVirtual);
+ if (fileInfoDetails != NULL)
+ {
+ sprintf(szOutput, "212-Sending directory listing of \"%s\".\r\n", newVirtual);
+ socketSendString(sCmd,szOutput);
+ const char * months[12] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
+ for (size_t i = 0; i < fileInfoDetails->count(); i++)
+ {
+ char szLine[512];
+ fileSystem::FileInfoDetail* fileInfoDetail = fileInfoDetails->get(i);
+ sprintf(szLine, "%c--------- 1 ftp ftp %llu ", fileInfoDetail->isDirectory ? 'd' : '-', fileInfoDetail->size);
+ strcat(szLine, months[fileInfoDetail->writeTime.month - 1]);
+ sprintf(szLine + strlen(szLine), " %2i %.2i:%.2i ", fileInfoDetail->writeTime.day, fileInfoDetail->writeTime.hour, fileInfoDetail->writeTime.minute);
+ strcat(szLine, fileInfoDetail->path);
+ if (fileInfoDetail->isDirectory == true)
+ {
+ strcat(szLine, "/");
+ }
+ strcat(szLine, "\r\n");
+ socketSendString(sCmd, szLine);
+ }
+ }
+ else
+ {
+ sprintf(szOutput, "550 \"%s\": Path not found.\r\n", newVirtual);
+ socketSendString(sCmd, szOutput);
+ }
+
+ free(newVirtual);
+ delete(fileInfoDetails);
+ }
+ }
+
+ else if (!stricmp(szCmd, "RETR")) {
+ if (!*pszParam) {
+ socketSendString(sCmd, "501 Syntax error in parameters or arguments.\r\n");
+ } else if (!isLoggedIn) {
+ socketSendString(sCmd, "530 Not logged in.\r\n");
+ } else {
+
+ char* newVirtual = resolveRelative(currentVirtual, pszParam);
+ char* ftpPath = driveManager::mapFtpPath(newVirtual);
+
+ uint32_t fileHandle;
+ if (fileSystem::fileOpen(ftpPath, fileSystem::FileModeRead, fileHandle) == true)
+ {
+ if (dwRestOffset)
+ {
+ fileSystem::fileSeek(fileHandle, fileSystem::FileSeekModeStart, dwRestOffset);
+ dwRestOffset = 0;
+ }
+ sprintf(szOutput, "150 Opening %s mode data connection for \"%s\".\r\n", sPasv ? "passive" : "active", newVirtual);
+ socketSendString(sCmd, szOutput);
+ sData = establishDataConnection(&saiData, &sPasv);
+ if (sData)
+ {
+ if (sendSocketFile(sCmd, sData, fileHandle, &dw))
+ {
+ sprintf(szOutput, "226 \"%s\" transferred successfully.\r\n", newVirtual);
+ socketSendString(sCmd, szOutput);
+ }
+ else
+ {
+ socketSendString(sCmd, "426 Connection closed; transfer aborted.\r\n");
+ if (dw)
+ {
+ socketSendString(sCmd, "226 ABOR command successful.\r\n");
+ }
+ }
+ socketUtility::closeSocket(sData);
+ }
+ else
+ {
+ socketSendString(sCmd, "425 Can't open data connection.\r\n");
+ }
+ fileSystem::fileClose(fileHandle);
+ }
+ else
+ {
+ sprintf(szOutput, "550 \"%s\": Unable to open file.\r\n", newVirtual);
+ socketSendString(sCmd, szOutput);
+ }
+
+ free(ftpPath);
+ free(newVirtual);
+ }
+ }
+
+ else if (!stricmp(szCmd, "STOR") || !stricmp(szCmd, "APPE")) {
+ if (!*pszParam) {
+ socketSendString(sCmd, "501 Syntax error in parameters or arguments.\r\n");
+ } else if (!isLoggedIn) {
+ socketSendString(sCmd, "530 Not logged in.\r\n");
+ } else {
+ char *newVirtual = resolveRelative(currentVirtual, pszParam);
+ char* ftpPath = driveManager::mapFtpPath(newVirtual);
+
+ uint32_t fileHandle;
+ if (fileSystem::fileOpen(ftpPath, fileSystem::FileModeWriteUpdate, fileHandle) == true)
+ {
+ if (stricmp(szCmd, "APPE") == 0)
+ {
+ fileSystem::fileSeek(fileHandle, fileSystem::FileSeekModeEnd, 0);
+ }
+ else
+ {
+ fileSystem::fileSeek(fileHandle, fileSystem::FileSeekModeStart, dwRestOffset);
+ fileSystem::fileTruncate(fileHandle, dwRestOffset);
+ }
+ dwRestOffset = 0;
+ sprintf(szOutput, "150 Opening %s mode data connection for \"%s\".\r\n", sPasv ? "passive" : "active", newVirtual);
+ socketSendString(sCmd, szOutput);
+ sData = establishDataConnection(&saiData, &sPasv);
+ if (sData)
+ {
+ if (receiveSocketFile(sCmd, sData, fileHandle))
+ {
+ sprintf(szOutput, "226 \"%s\" transferred successfully.\r\n", newVirtual);
+ socketSendString(sCmd, szOutput);
+ }
+ else
+ {
+ socketSendString(sCmd, "426 Connection closed; transfer aborted.\r\n");
+ }
+ socketUtility::closeSocket(sData);
+ } else {
+ socketSendString(sCmd, "425 Can't open data connection.\r\n");
+ }
+ fileSystem::fileClose(fileHandle);
+ }
+ else
+ {
+ sprintf(szOutput, "550 \"%s\": Unable to open file.\r\n", newVirtual);
+ socketSendString(sCmd, szOutput);
+ }
+
+ free(newVirtual);
+ free(ftpPath);
+ }
+ }
+
+ else if (!stricmp(szCmd, "ABOR")) {
+ socketUtility::closeSocket(sPasv);
+ dwRestOffset = 0;
+ socketSendString(sCmd, "200 ABOR command successful.\r\n");
+ }
+
+ else if (!stricmp(szCmd, "SIZE")) {
+ if (!*pszParam) {
+ socketSendString(sCmd, "501 Syntax error in parameters or arguments.\r\n");
+ } else if (!isLoggedIn) {
+ socketSendString(sCmd, "530 Not logged in.\r\n");
+ } else {
+ char* newVirtual = resolveRelative(currentVirtual, pszParam);
+ char* ftpPath = driveManager::mapFtpPath(newVirtual);
+
+ uint32_t fileHandle;
+ if (fileSystem::fileOpen(ftpPath, fileSystem::FileModeRead, fileHandle) == true)
+ {
+ uint32_t fileSize = 0;
+ fileSystem::fileSize(fileHandle, fileSize);
+ sprintf(szOutput, "213 %llu\r\n", fileSize);
+ socketSendString(sCmd, szOutput);
+ fileSystem::fileClose(fileHandle);
+ }
+ else
+ {
+ sprintf(szOutput, "550 \"%s\": File not found.\r\n", newVirtual);
+ socketSendString(sCmd, szOutput);
+ }
+
+ free(newVirtual);
+ free(ftpPath);
+ }
+ }
+
+ else if (!stricmp(szCmd, "MDTM")) {
+ if (!*pszParam) {
+ socketSendString(sCmd, "501 Syntax error in parameters or arguments.\r\n");
+ } else if (!isLoggedIn) {
+ socketSendString(sCmd, "530 Not logged in.\r\n");
+ } else {
+ for (i = 0; i < 14; i++) {
+ if ((pszParam[i] < '0') || (pszParam[i] > '9')) {
+ break;
+ }
+ }
+ if ((i == 14) && (pszParam[14] == ' ')) {
+ strncpy(szOutput, pszParam, 4);
+ szOutput[4] = 0;
+ fileTime.year = (WORD)stringUtility::toInt(szOutput);
+ strncpy(szOutput, pszParam + 4, 2);
+ szOutput[2] = 0;
+ fileTime.month = (WORD)stringUtility::toInt(szOutput);
+ strncpy(szOutput, pszParam + 6, 2);
+ fileTime.day = (WORD)stringUtility::toInt(szOutput);
+ strncpy(szOutput, pszParam + 8, 2);
+ fileTime.hour = (WORD)stringUtility::toInt(szOutput);
+ strncpy(szOutput, pszParam + 10, 2);
+ fileTime.minute = (WORD)stringUtility::toInt(szOutput);
+ strncpy(szOutput, pszParam + 12, 2);
+ fileTime.second = (WORD)stringUtility::toInt(szOutput);
+ pszParam += 15;
+ dw = 1;
+ } else {
+ dw = 0;
+ }
+
+ char* newVirtual = resolveRelative(currentVirtual, pszParam);
+ if (dw == 1) {
+
+ char* ftpPath = driveManager::mapFtpPath(newVirtual);
+ if (fileSystem::setFileTime(ftpPath, fileTime) == true)
+ {
+ socketSendString(sCmd, "250 MDTM command successful.\r\n");
+ }
+ else
+ {
+ sprintf(szOutput, "550 \"%s\": File not found.\r\n", newVirtual);
+ socketSendString(sCmd, szOutput);
+ }
+ free(ftpPath);
+
+ } else {
+
+ char* ftpPath = driveManager::mapFtpPath(newVirtual);
+ fileSystem::FileInfoDetail* fileInfoDetail = fileSystem::fileGetFileInfoDetail(ftpPath);
+ if (fileInfoDetail != NULL)
+ {
+ sprintf(szOutput, "213 %04u%02u%02u%02u%02u%02u\r\n", fileInfoDetail->writeTime.year, fileInfoDetail->writeTime.month, fileInfoDetail->writeTime.day, fileInfoDetail->writeTime.hour, fileInfoDetail->writeTime.minute, fileInfoDetail->writeTime.second);
+ socketSendString(sCmd, szOutput);
+ }
+ else
+ {
+ sprintf(szOutput, "550 \"%s\": File not found.\r\n", newVirtual);
+ socketSendString(sCmd, szOutput);
+ }
+ delete(fileInfoDetail);
+ free(ftpPath);
+ }
+ free(newVirtual);
+ }
+ }
+
+ else if (!stricmp(szCmd, "DELE")) {
+ if (!*pszParam) {
+ socketSendString(sCmd, "501 Syntax error in parameters or arguments.\r\n");
+ } else if (!isLoggedIn) {
+ socketSendString(sCmd, "530 Not logged in.\r\n");
+ } else {
+ char* newVirtual = resolveRelative(currentVirtual, pszParam);
+ char* ftpPath = driveManager::mapFtpPath(newVirtual);
+ if (fileSystem::fileDelete(ftpPath) == true)
+ {
+ sprintf(szOutput, "250 \"%s\" deleted successfully.\r\n", newVirtual);
+ socketSendString(sCmd, szOutput);
+ }
+ else
+ {
+ sprintf(szOutput, "550 \"%s\": File not found.\r\n", newVirtual);
+ socketSendString(sCmd, szOutput);
+ }
+ free(ftpPath);
+ free(newVirtual);
+ }
+ }
+
+ else if (!stricmp(szCmd, "RNFR")) {
+ if (!*pszParam) {
+ socketSendString(sCmd, "501 Syntax error in parameters or arguments.\r\n");
+ } else if (!isLoggedIn) {
+ socketSendString(sCmd, "530 Not logged in.\r\n");
+ } else {
+ char* newVirtual = resolveRelative(currentVirtual, pszParam);
+ char* ftpPath = driveManager::mapFtpPath(newVirtual);
+ bool exists;
+ if ((fileSystem::fileExists(ftpPath, exists) == true && exists == true) || (fileSystem::directoryExists(ftpPath, exists) == true && exists == true))
+ {
+ free(rnfr);
+ rnfr = strdup(ftpPath);
+ sprintf(szOutput, "350 \"%s\": File/Directory exists; proceed with RNTO.\r\n", newVirtual);
+ socketSendString(sCmd, szOutput);
+ } else {
+ sprintf(szOutput, "550 \"%s\": File/Directory not found.\r\n", newVirtual);
+ socketSendString(sCmd, szOutput);
+ }
+ free(ftpPath);
+ free(newVirtual);
+ }
+ }
+
+ else if (!stricmp(szCmd, "RNTO")) {
+ if (!*pszParam) {
+ socketSendString(sCmd, "501 Syntax error in parameters or arguments.\r\n");
+ } else if (!isLoggedIn) {
+ socketSendString(sCmd, "530 Not logged in.\r\n");
+ } else if (rnfr == NULL) {
+ socketSendString(sCmd, "503 Bad sequence of commands. Send RNFR first.\r\n");
+ } else {
+ char* newVirtual = resolveRelative(currentVirtual, pszParam);
+ char* ftpPath = driveManager::mapFtpPath(newVirtual);
+
+ if (fileSystem::fileMove(rnfr, ftpPath) == true)
+ {
+ socketSendString(sCmd, "250 RNTO command successful.\r\n");
+ free(rnfr);
+ rnfr = NULL;
+ }
+ else
+ {
+ sprintf(szOutput, "553 \"%s\": Unable to rename file.\r\n", newVirtual);
+ socketSendString(sCmd, szOutput);
+ }
+ free(newVirtual);
+ free(ftpPath);
+ }
+ }
+
+ else if (!stricmp(szCmd, "MKD") || !stricmp(szCmd, "XMKD")) {
+ if (!*pszParam) {
+ socketSendString(sCmd, "501 Syntax error in parameters or arguments.\r\n");
+ } else if (!isLoggedIn) {
+ socketSendString(sCmd, "530 Not logged in.\r\n");
+ } else {
+ char* newVirtual = resolveRelative(currentVirtual, pszParam);
+ char* ftpPath = driveManager::mapFtpPath(newVirtual);
+ if (fileSystem::directoryCreate(ftpPath) == true)
+ {
+ sprintf(szOutput, "250 \"%s\" created successfully.\r\n", newVirtual);
+ socketSendString(sCmd, szOutput);
+ }
+ else
+ {
+ sprintf(szOutput, "550 \"%s\": Unable to create directory.\r\n", newVirtual);
+ socketSendString(sCmd, szOutput);
+ }
+ free(ftpPath);
+ free(newVirtual);
+ }
+ }
+
+ else if (!stricmp(szCmd, "RMD") || !stricmp(szCmd, "XRMD")) {
+ if (!*pszParam) {
+ socketSendString(sCmd, "501 Syntax error in parameters or arguments.\r\n");
+ } else if (!isLoggedIn) {
+ socketSendString(sCmd, "530 Not logged in.\r\n");
+ } else {
+ char* newVirtual = resolveRelative(currentVirtual, pszParam);
+ char* ftpPath = driveManager::mapFtpPath(newVirtual);
+ if (fileSystem::directoryDelete(ftpPath, true) == true)
+ {
+ sprintf(szOutput, "250 \"%s\" removed successfully.\r\n", newVirtual);
+ socketSendString(sCmd, szOutput);
+ }
+ else
+ {
+ sprintf(szOutput, "550 \"%s\": Unable to remove directory.\r\n", newVirtual);
+ socketSendString(sCmd, szOutput);
+ }
+ free(ftpPath);
+ free(newVirtual);
+ }
+ }
+
+ else if (!stricmp(szCmd, "XCRC")) {
+ if (!*pszParam) {
+ socketSendString(sCmd, "501 Syntax error in parameters or arguments.\r\n");
+ } else if (!isLoggedIn) {
+ socketSendString(sCmd, "530 Not logged in.\r\n");
+ } else {
+ char* newVirtual = resolveRelative(currentVirtual, pszParam);
+ char* ftpPath = driveManager::mapFtpPath(newVirtual);
+
+ uint32_t fileHandle;
+ if (fileSystem::fileOpen(ftpPath, fileSystem::FileModeRead, fileHandle) == true)
+ {
+ unsigned long checksum = crc32::calculate(fileHandle);
+ sprintf(szOutput, "250 %08X\r\n", checksum);
+ socketSendString(sCmd, szOutput);
+ fileSystem::fileClose(fileHandle);
+ }
+ else
+ {
+ sprintf(szOutput, "550 \"%s\": File not found.\r\n", newVirtual);
+ socketSendString(sCmd, szOutput);
+ }
+ free(ftpPath);
+ free(newVirtual);
+ }
+ }
+
+ else if (!stricmp(szCmd, "OPTS")) {
+ if (!*pszParam) {
+ socketSendString(sCmd, "501 Syntax error in parameters or arguments.\r\n");
+ } else if (!stricmp(pszParam, "UTF8 On")) {
+ socketSendString(sCmd, "200 Always in UTF8 mode.\r\n");
+ } else {
+ socketSendString(sCmd, "501 Option not understood.\r\n");
+ }
+ }
+
+ else if (!stricmp(szCmd, "AVBL")) {
+ if (!*pszParam) {
+ socketSendString(sCmd, "550 Syntax error in parameters or arguments.\r\n");
+ } else {
+
+ char* newVirtual = resolveRelative(currentVirtual, pszParam);
+ char* ftpPath = driveManager::mapFtpPath(newVirtual);
+
+ uint64_t totalFree;
+ if (driveManager::getTotalFreeNumberOfBytes(ftpPath, totalFree) == true)
+ {
+ sprintf(szOutput, "213 %llu\r\n", totalFree);
+ socketSendString(sCmd, szOutput);
+ }
+ else
+ {
+ sprintf(szOutput, "550 \"%s\": not found.\r\n", pszParam);
+ socketSendString(sCmd, szOutput);
+ }
+
+ free(ftpPath);
+ free(newVirtual);
+ }
+ }
+
+ else {
+ sprintf(szOutput, "500 Syntax error, command \"%s\" unrecognized.\r\n",szCmd);
+ socketSendString(sCmd,szOutput);
+ }
+
+ }
+
+ socketUtility::closeSocket(sPasv);
+ socketUtility::closeSocket(sCmd);
+
+ if (isLoggedIn) {
+ decrementConnections();
+ }
+
+ return false;
+}
+
+bool WINAPI ftpServer::listenThread(LPVOID lParam)
+{
+ uint64_t sIncoming = 0;
+
+ while (mStopRequested == false)
+ {
+ const int result = socketUtility::getReadStatus(sListen);
+ if (result == SOCKET_ERROR)
+ {
+ utils::debugPrint("Error: Socket status failed: %i\n", WSAGetLastError());
+ break;
+ }
+
+ if (result == 1 && socketUtility::acceptSocket(sListen, sIncoming))
+ {
+ HANDLE connectionThreadHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)connectionThread, (void*)sIncoming, 0, NULL);
+ if (connectionThreadHandle != NULL) {
+ SetThreadPriority(connectionThreadHandle, 2);
+ CloseHandle(connectionThreadHandle);
+ }
+ }
+ else
+ {
+ Sleep(50);
+ }
+ }
+
+ socketUtility::closeSocket(sListen);
+ socketUtility::closeSocket(sIncoming);
+ return false;
+}
+
+bool ftpServer::init()
+{
+ mStopRequested = false;
+
+ mListenThreadHandle = NULL;
+
+ XSetFileCacheSize(4*1024*1024);
+
+ memset(&saiListen, 0, sizeof(SOCKADDR_IN));
+ saiListen.sin_family = AF_INET;
+ saiListen.sin_addr.S_un.S_addr = INADDR_ANY;
+ saiListen.sin_port = htons(21);
+
+ mMaxConnections = 20;
+ mCommandTimeout = 300;
+ mConnectTimeout = 15;
+
+ socketUtility::createSocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, sListen);
+
+ if (!socketUtility::bindSocket(sListen, &saiListen)) {
+ socketUtility::closeSocket(sListen);
+ return false;
+ }
+
+ socketUtility::listenSocket(sListen, SOMAXCONN);
+
+ mListenThreadHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)listenThread, 0, 0, NULL);
+ if (mListenThreadHandle != NULL) {
+ SetThreadPriority(mListenThreadHandle, 2);
+ }
+
+ return true;
+}
+
+void ftpServer::close()
+{
+ mStopRequested = true;
+ WaitForSingleObject(mListenThreadHandle, INFINITE);
+ CloseHandle(mListenThreadHandle);
+}
+
+bool ftpServer::socketSendString(uint64_t s, const char *psz)
+{
+ bool bSuccess = send((SOCKET)s, psz, strlen(psz), 0) != SOCKET_ERROR;
+ return bSuccess;
+}
+
+ftpServer::ReceiveStatus ftpServer::socketReceiveString(uint64_t s, char *psz, uint32_t dwMaxChars, uint32_t* pdwCharsReceived)
+{
+ uint32_t dwChars = 0;
+ ReceiveStatus status, statusError;
+ char buf[2];
+ uint32_t dw;
+
+ for (;;) {
+ if (dwChars == dwMaxChars) {
+ statusError = ReceiveStatus_Insufficient_Buffer;
+ break;
+ }
+
+ status = socketReceiveLetter(s, psz, dwMaxChars - dwChars, &dw);
+ if (status == ReceiveStatus_OK) {
+ dwChars += dw;
+ if (*psz == '\r') *psz = 0;
+ else if (*psz == '\n') {
+ *psz = 0;
+ *pdwCharsReceived = dwChars;
+ return ReceiveStatus_OK;
+ }
+ psz += dw;
+ }
+ else if (status == ReceiveStatus_Invalid_Data || status == ReceiveStatus_Insufficient_Buffer) {
+ statusError = status;
+ break;
+ }
+ else {
+ return status;
+ }
+ }
+
+ // A non-critical error occurred, read until end of line
+ for (;;) {
+ status = socketReceiveLetter(s, buf, sizeof(buf) / sizeof(char), &dw);
+ if (status == ReceiveStatus_OK) {
+ if (*buf == '\n') {
+ return statusError;
+ }
+ }
+ else if (status == ReceiveStatus_Invalid_Data || status == ReceiveStatus_Insufficient_Buffer) {
+ // Go on...
+ }
+ else {
+ return status;
+ }
+ }
+}
+
+ftpServer::ReceiveStatus ftpServer::socketReceiveLetter(uint64_t s, char* pch, uint32_t dwMaxChars, uint32_t* pdwCharsReceived)
+{
+ char buf[4];
+ uint32_t dw;
+ TIMEVAL tv;
+ fd_set fds;
+
+ tv.tv_sec = mCommandTimeout;
+ tv.tv_usec = 0;
+ FD_ZERO(&fds);
+ FD_SET((SOCKET)s, &fds);
+ dw = select(0, &fds, 0, 0, &tv);
+ if (dw == SOCKET_ERROR || dw == 0) return ReceiveStatus_Timeout;
+ dw = recv((SOCKET)s, &buf[0], 1, 0);
+ if (dw == SOCKET_ERROR || dw == 0) return ReceiveStatus_Network_Error;
+
+ if (dwMaxChars == 0) {
+ return ReceiveStatus_Insufficient_Buffer;
+ }
+
+ pch[0] = buf[0];
+
+ *pdwCharsReceived = 1;
+ return ReceiveStatus_OK;
+}
+
+ftpServer::ReceiveStatus ftpServer::socketReceiveData(uint64_t s, char *psz, uint32_t dwBytesToRead, uint32_t* pdwBytesRead)
+{
+ uint32_t dw;
+ TIMEVAL tv;
+ fd_set fds;
+
+ tv.tv_sec = mConnectTimeout;
+ tv.tv_usec = 0;
+ memset(&fds, 0, sizeof(fd_set));
+ FD_SET((SOCKET)s, &fds);
+ dw = select(0, &fds, 0, 0, &tv);
+ if (dw == SOCKET_ERROR || dw == 0) {
+ utils::debugPrint("Error: SocketReceiveData failed with Timeout.\n");
+ return ReceiveStatus_Timeout;
+ }
+ dw = recv((SOCKET)s, psz, dwBytesToRead, 0);
+ if (dw == SOCKET_ERROR) {
+ utils::debugPrint("Error: SocketReceiveData failed with Network Error.\n");
+ return ReceiveStatus_Network_Error;
+ }
+ *pdwBytesRead = dw;
+ return ReceiveStatus_OK;
+}
+
+uint64_t ftpServer::establishDataConnection(sockaddr_in *psaiData, uint64_t*psPasv)
+{
+ uint64_t sData;
+ uint32_t dw;
+ TIMEVAL tv;
+ fd_set fds;
+
+ if (psPasv && *psPasv) {
+ tv.tv_sec = mConnectTimeout;
+ tv.tv_usec = 0;
+ memset(&fds, 0, sizeof(fd_set));
+ FD_SET((SOCKET)*psPasv,&fds);
+ dw = select(0,&fds,0,0,&tv);
+ if (dw && dw != SOCKET_ERROR) {
+ socketUtility::acceptSocket(*psPasv, psaiData, sData);
+ } else {
+ sData=0;
+ }
+ socketUtility::closeSocket(*psPasv);
+ return sData;
+ } else {
+
+ socketUtility::createSocket(AF_INET,SOCK_STREAM, IPPROTO_TCP, sData);
+ if (!socketUtility::connectSocket(sData, psaiData)) {
+ socketUtility::closeSocket(sData);
+ return INVALID_SOCKET;
+ } else {
+ return sData;
+ }
+ }
+}
+
+bool ftpServer::receiveSocketFile(uint64_t sCmd, uint64_t sData, uint32_t fileHandle)
+{
+ uint32_t socketBufferSize = RECV_SOCKET_BUFFER_SIZE;
+ socketUtility::setSocketRecvSize(sData, socketBufferSize);
+
+ int driveSectorBufferSize = 128 * 1024;
+ int combinedBufferSize = socketBufferSize + driveSectorBufferSize;
+ char *combinedBuffer = (char*)malloc(combinedBufferSize);
+
+ bool fileComplete = false;
+
+ uint32_t totalBytesToWrite = 0;
+ uint32_t totalWritten = 0;
+
+ while (true)
+ {
+
+ while (!fileComplete && totalBytesToWrite < (uint32_t)driveSectorBufferSize)
+ {
+ uint32_t bytesRead = 0;
+ if (socketReceiveData(sData, combinedBuffer + totalBytesToWrite, socketBufferSize, &bytesRead) != ReceiveStatus_OK)
+ {
+ free(combinedBuffer);
+ return false;
+ }
+ totalBytesToWrite += bytesRead;
+ if (bytesRead == 0) {
+ fileComplete = true;
+ break;
+ }
+ }
+
+ if (fileComplete && totalBytesToWrite == 0)
+ {
+ free(combinedBuffer);
+ return true;
+ }
+
+ uint32_t bytesWritten = 0;
+ uint32_t bytesToWrite = min((uint32_t)driveSectorBufferSize, totalBytesToWrite);
+ if (!fileSystem::fileWrite(fileHandle, combinedBuffer, bytesToWrite, bytesWritten))
+ {
+ utils::debugPrint("Error: WriteFile failed: %i", GetLastError());
+ free(combinedBuffer);
+ return false;
+ }
+
+ totalBytesToWrite -= bytesWritten;
+ totalWritten += bytesWritten;
+ memmove(combinedBuffer, combinedBuffer + bytesWritten, totalBytesToWrite);
+
+ }
+}
+
+bool ftpServer::sendSocketFile(uint64_t sCmd, uint64_t sData, uint32_t fileHandle, uint32_t* pdwAbortFlag)
+{
+ uint32_t bufferSize = SEND_SOCKET_BUFFER_SIZE;
+ socketUtility::setSocketSendSize(sData, bufferSize);
+ char *szBuffer = (char*)malloc(bufferSize);
+
+ while (true)
+ {
+ uint32_t bytesRead;
+ if (fileSystem::fileRead(fileHandle, szBuffer, bufferSize, bytesRead) == false)
+ {
+ utils::debugPrint("Error: ReadFile failed: %i", GetLastError());
+ free(szBuffer);
+ return false;
+ }
+
+ if (bytesRead == 0)
+ {
+ free(szBuffer);
+ return true;
+ }
+
+ int bytesToSend = bytesRead;
+ int bufferOffset = 0;
+
+ while (bytesToSend > 0)
+ {
+ int sent = send((SOCKET)sData, szBuffer + bufferOffset, bytesToSend, 0);
+ int queueLength = 0;
+ socketUtility::getReadQueueLength(sCmd, queueLength);
+ if (queueLength > 0) {
+ char szCmd[512];
+ uint32_t bytes_received = 0;
+ if (socketReceiveString(sCmd, szCmd, 512, &bytes_received) == ReceiveStatus_OK) {
+ if (!stricmp(szCmd, "ABOR")) {
+ *pdwAbortFlag = 1;
+ free(szBuffer);
+ return false;
+ }
+ else {
+ socketSendString(sCmd, "500 Only command allowed at this time is ABOR.\r\n");
+ }
+ }
+ }
+ bytesToSend -= sent;
+ bufferOffset += (int)sent;
+ if (sent < 1)
+ {
+ free(szBuffer);
+ return false;
+ }
+ }
+ }
+ return true;
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/ftpServer.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/ftpServer.h
new file mode 100644
index 0000000..f1eca5b
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/ftpServer.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include "socketUtility.h"
+#include "fileSystem.h"
+#include
+#include
+#include
+
+class ftpServer
+{
+public:
+
+ typedef enum _ReceiveStatus {
+ ReceiveStatus_OK = 1,
+ ReceiveStatus_Network_Error,
+ ReceiveStatus_Timeout,
+ ReceiveStatus_Invalid_Data,
+ ReceiveStatus_Insufficient_Buffer
+ } ReceiveStatus;
+
+ static bool WINAPI connectionThread(uint64_t pParam);
+
+ static bool WINAPI listenThread(LPVOID lParam);
+
+ static bool init();
+ static void close();
+ static bool socketSendString(uint64_t s, const char *psz);
+ static ReceiveStatus socketReceiveString(uint64_t s, char *psz, uint32_t dwMaxChars, uint32_t* pdwCharsReceived);
+ static ReceiveStatus socketReceiveLetter(uint64_t s, char* pch, uint32_t dwMaxChars, uint32_t* pdwCharsReceived);
+ static ReceiveStatus socketReceiveData(uint64_t s, char *psz, uint32_t dwBytesToRead, uint32_t* pdwBytesRead);
+ static uint64_t establishDataConnection(sockaddr_in* psaiData, uint64_t* psPasv);
+ static bool receiveSocketFile(uint64_t sCmd, uint64_t sData, uint32_t fileHandle);
+ static bool sendSocketFile(uint64_t sCmd, uint64_t sData, uint32_t fileHandle, uint32_t* pdwAbortFlag);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/globalDefines.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/globalDefines.h
new file mode 100644
index 0000000..44c713f
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/globalDefines.h
@@ -0,0 +1,305 @@
+#pragma once
+
+// SPI2PAR
+
+#define SPI2PAR_CURSORHOME 1
+#define SPI2PAR_HIDEDISPLAY 2
+#define SPI2PAR_SHOWDISPLAY 3
+#define SPI2PAR_HIDECURSOR 4
+#define SPI2PAR_SHOWUNDERLINECURSOR 5
+#define SPI2PAR_SHOWBLOCKCURSOR 6
+#define SPI2PAR_SHOWINVERTEDCURSOR 7
+#define SPI2PAR_BACKSPACE 8
+#define SPI2PAR_MODULECONFIG 9
+#define SPI2PAR_LINEFEED 10
+#define SPI2PAR_DELETEINPLACE 11
+#define SPI2PAR_FORMFEED 12
+#define SPI2PAR_CARRIAGERETURN 13
+#define SPI2PAR_SETBACKLIGHT 14
+#define SPI2PAR_SETCONTRAST 15
+#define SPI2PAR_SETCURSORPOSITION 17
+#define SPI2PAR_DRAWBARGRAPH 18
+#define SPI2PAR_SCROLLON 19
+#define SPI2PAR_SCROLLOFF 20
+#define SPI2PAR_WRAPON 23
+#define SPI2PAR_WRAPOFF 24
+#define SPI2PAR_CUSTOMCHARACTER 25
+#define SPI2PAR_REBOOT 26
+#define SPI2PAR_CURSORMOVE 27
+#define SPI2PAR_LARGENUMBER 28
+
+// Modxo
+
+#define MODXO_LCD_DELAY 2
+#define MODXO_LCD_COMMAND_MODE 0x80
+#define MODXO_LCD_DATA_MODE 0x40
+
+#define MODXO_PIXEL_FORMAT_GRB 0
+#define MODXO_PIXEL_FORMAT_RGB 1
+#define MODXO_PIXEL_FORMAT_BRG 2
+#define MODXO_PIXEL_FORMAT_RBG 3
+#define MODXO_PIXEL_FORMAT_BGR 4
+#define MODXO_PIXEL_FORMAT_GBR 5
+
+#define MODXO_NVM_REGISTER_RGB_STATUS_PF 1
+#define MODXO_NVM_REGISTER_RGB_STRIP1_PF 2
+#define MODXO_NVM_REGISTER_RGB_STRIP2_PF 3
+#define MODXO_NVM_REGISTER_RGB_STRIP3_PF 4
+#define MODXO_NVM_REGISTER_RGB_STRIP4_PF 5
+
+#define MODXO_REGISTER_NVM_CONFIG_SEL 0xDEA4
+#define MODXO_REGISTER_NVM_CONFIG_VAL 0xDEA5
+#define MODXO_REGISTER_VOLATILE_CONFIG_SEL 0xDEA6
+#define MODXO_REGISTER_VOLATILE_CONFIG_VAL 0xDEA7
+#define MODXO_REGISTER_LCD_COMMAND 0xDEA8
+#define MODXO_REGISTER_LCD_DATA 0xDEA9
+#define MODXO_REGISTER_BANKING 0xDEAA
+#define MODXO_REGISTER_SIZE 0xDEAB
+#define MODXO_REGISTER_MEM_ERASE 0xDEAC
+#define MODXO_REGISTER_CHIP_ID 0xDEAD
+#define MODXO_REGISTER_MEM_FLUSH 0xDEAE
+#define MODXO_REGISTER_LED_COMMAND 0xA2
+#define MODXO_REGISTER_LED_DATA 0xA3
+
+#define MODXO_BANK_TSOP 0xc0
+#define MODXO_BANK_MODXO 0x00
+#define MODXO_BANK_BOOTLOADER 0x01
+#define MODXO_BANK_PROMETHEOS1 0x02
+#define MODXO_BANK_PROMETHEOS2 0x03
+
+#define MODXO_LCD_SPI 0x00
+#define MODXO_LCD_I2C 0x01
+#define MODXO_LCD_REMOVE_I2C_PREFIX 2
+#define MODXO_LCD_SET_I2C_PREFIX 3
+#define MODXO_LCD_SET_CLK 4
+#define MODXO_LCD_SET_SPI_MODE 5
+
+#define MODXO_LED_CMD_SET_LED_COUNT_STRIP 0x00
+#define MODXO_LED_CMD_FILL_STRIP_COL 0x01
+#define MODXO_LED_CMD_UPDATE_STRIPS 0x02
+#define MODXO_LED_CMD_SET_PIX_IDX 0x03
+#define MODXO_LED_CMD_WRITE_PIX_COL 0x04
+#define MODXO_LED_CMD_SET_PIX_COUNT 0x05
+#define MODXO_LED_CMD_WRITE_EFFECT 0x06
+#define MODXO_LED_CMD_SELECT_COLOR 0xF0
+#define MODXO_LED_CMD_SELECT_STRIP 0xFC
+
+#define MODXO_EFFECT_PIXELS_SHIFT_UP 0x01
+#define MODXO_EFFECT_PIXELS_SHIFT_DOWN 0x02
+#define MODXO_EFFECT_PIXELS_FADE 0x03
+#define MODXO_EFFECT_PIXELS_RANDOM 0x04
+#define MODXO_EFFECT_PIXELS_RAINBOW 0x05
+#define MODXO_EFFECT_PIXELS_BRIGHTNESS 0x06
+
+// Aladdin
+
+#define ALADDIN_LCD_DELAY 2
+
+#define ALADDIN_REGISTER_IO 0xF70Du
+#define ALADDIN_REGISTER_DISP_O 0xF700u
+#define ALADDIN_REGISTER_LCD_BL 0xF701u
+#define ALADDIN_REGISTER_LCD_CT 0xF703u
+#define ALADDIN_REGISTER_GPIO 0xF70D
+#define ALADDIN_REGISTER_BANKING 0xF70F
+
+#define ALADDIN_SPI_CS_BIT 0x08
+#define ALADDIN_SPI_MOSI_BIT 0x40
+#define ALADDIN_SPI_CLK_BIT 0x20
+
+#define ALADDIN_DISP_EXT_CONTROL 0x08
+#define ALADDIN_DISP_NW_FLAG 0x01
+#define ALADDIN_DISP_CON_RS 0x01
+#define ALADDIN_DISP_CON_RW 0x02
+#define ALADDIN_DISP_CON_E 0x04
+#define ALADDIN_DISP_INI 0x01
+#define ALADDIN_DISP_CMD 0x00
+#define ALADDIN_DISP_DAT 0x02
+#define ALADDIN_DISP_CLEAR 0x01
+#define ALADDIN_DISP_HOME 0x02
+#define ALADDIN_DISP_ENTRY_MODE_SET 0x04
+#define ALADDIN_DISP_S_FLAG 0x01
+#define ALADDIN_DISP_ID_FLAG 0x02
+#define ALADDIN_DISP_CONTROL 0x08
+#define ALADDIN_DISP_D_FLAG 0x04
+#define ALADDIN_DISP_C_FLAG 0x02
+#define ALADDIN_DISP_B_FLAG 0x01
+#define ALADDIN_DISP_SHIFT 0x10
+#define ALADDIN_DISP_SC_FLAG 0x08
+#define ALADDIN_DISP_RL_FLAG 0x04
+#define ALADDIN_DISP_FUNCTION_SET 0x20
+#define ALADDIN_DISP_DL_FLAG 0x10
+#define ALADDIN_DISP_N_FLAG 0x08
+#define ALADDIN_DISP_F_FLAG 0x04
+#define ALADDIN_DISP_RE_FLAG 0x04
+#define ALADDIN_DISP_CGRAM_SET 0x40
+#define ALADDIN_DISP_SEGRAM_SET 0x40
+#define ALADDIN_DISP_DDRAM_SET 0x80
+#define ALADDIN_DISP_EN5V 0x01
+
+#define ALADDIN1MB_BANK_TSOP 0
+#define ALADDIN1MB_BANK_BOOTLOADER 0x87
+#define ALADDIN1MB_BANK_PROMETHEOS 0x84
+#define ALADDIN1MB_BANK_SLOT1_256K 0x86
+#define ALADDIN1MB_SETTINGS_BANK ALADDIN1MB_BANK_PROMETHEOS
+#define ALADDIN1MB_SETTINGS_OFFSET (0x07f000)
+
+#define ALADDIN2MB_BANK_TSOP 0
+#define ALADDIN2MB_BANK_MEM_REGISTER 0x1F
+#define ALADDIN2MB_BANK_SLOT1_256K 0x10
+#define ALADDIN2MB_BANK_SLOT2_256K 0x11
+#define ALADDIN2MB_BANK_SLOT3_256K 0x12
+#define ALADDIN2MB_BANK_SLOT4_256K 0x13
+#define ALADDIN2MB_BANK_SLOT1_512K 0x18
+#define ALADDIN2MB_BANK_SLOT2_512K 0x19
+#define ALADDIN2MB_BANK_SLOT1_1024K 0x1a
+#define ALADDIN2MB_BANK_BOOTLOADER 0x14
+#define ALADDIN2MB_BANK_PROMETHEOS1 0x15
+#define ALADDIN2MB_BANK_PROMETHEOS2 0x16
+#define ALADDIN2MB_BANK_PROMETHEOS3 0x17
+#define ALADDIN2MB_SETTINGS_BANK ALADDIN2MB_BANK_PROMETHEOS3
+#define ALADDIN2MB_SETTINGS_OFFSET (0x1ff000 - 0x1c0000)
+#define ALADDIN2MB_INSTALLER_LOGO_BANK ALADDIN2MB_BANK_PROMETHEOS3
+#define ALADDIN2MB_INSTALLER_LOGO_OFFSET (0x1f7000 - 0x1c0000)
+
+//Smartxx
+
+#define SMARTXX_LCD_DELAY 2
+
+#define SMARTXX_REGISTER_BANKING 0x00EF
+#define SMARTXX_REGISTER_LED 0x00EE
+#define SMARTXX_SPI_MOSI_BIT 0x10
+#define SMARTXX_SPI_CS_BIT 0x20
+#define SMARTXX_SPI_CLK_BIT 0x40
+
+#define SMARTXX_BANK_TSOP 0
+#define SMARTXX_BANK_BOOTLOADER 1
+#define SMARTXX_BANK_PROMETHEOS1 2
+#define SMARTXX_BANK_PROMETHEOS2 10
+#define SMARTXX_BANK_SLOT1_256K 3
+#define SMARTXX_BANK_SLOT2_256K 4
+#define SMARTXX_BANK_SLOT3_256K 5
+#define SMARTXX_BANK_SLOT4_256K 6
+#define SMARTXX_BANK_SLOT1_512K 7
+#define SMARTXX_BANK_SLOT2_512K 8
+#define SMARTXX_BANK_SLOT1_1024K 9
+#define SMARTXX_SETTINGS_BANK SMARTXX_BANK_PROMETHEOS2
+#define SMARTXX_SETTINGS_OFFSET (0x1f8000 - 0x1c0000)
+#define SMARTXX_INSTALLER_LOGO_BANK SMARTXX_BANK_PROMETHEOS2
+#define SMARTXX_INSTALLER_LOGO_OFFSET (0x1fa000 - 0x1c0000)
+
+//Xecuter
+
+#define XECUTER_LCD_DELAY 2
+
+#define XECUTER_REGISTER_HARDWARE_BANKING 0xF501
+#define XECUTER_REGISTER_SOFTWARE_BANKING 0xF502
+#define XECUTER_REGISTER_LED 0x00EE
+#define XECUTER_SPI_MOSI_BIT 0x10
+#define XECUTER_SPI_CS_BIT 0x20
+#define XECUTER_SPI_CLK_BIT 0x40
+
+#define XECUTER_BANK_TSOP 0x6f
+#define XECUTER_BANK_BACKUP_256K 0x8f
+#define XECUTER_DISABLE_BACKUP 0xf
+
+#define XECUTER_BANK_BOOTLOADER 0x00
+#define XECUTER_BANK_PROMETHEOS1 0x01
+#define XECUTER_BANK_PROMETHEOS2 0x02
+#define XECUTER_BANK_PROMETHEOS3 0x03
+#define XECUTER_BANK_SLOT1_256K 0x04
+#define XECUTER_BANK_SLOT2_256K 0x05
+#define XECUTER_BANK_SLOT3_256K 0x06
+#define XECUTER_BANK_SLOT4_256K 0x07
+#define XECUTER_BANK_SLOT1_512K 0x0a
+#define XECUTER_BANK_SLOT2_512K 0x0b
+#define XECUTER_BANK_SLOT1_1024K 0x0d
+
+#define XECUTER_SETTINGS_BANK XECUTER_BANK_PROMETHEOS3
+#define XECUTER_SETTINGS_OFFSET (0x0f0000 - 0x0c0000)
+#define XECUTER_INSTALLER_LOGO_BANK XECUTER_BANK_PROMETHEOS3
+#define XECUTER_INSTALLER_LOGO_OFFSET (0x0e0000 - 0x0c0000)
+
+#define XECUTER_REGISTER_DISP_O_LIGHT 0xf503
+#define XECUTER_REGISTER_DISP_O_DAT 0xf504
+#define XECUTER_REGISTER_DISP_O_CMD 0xf505
+#define XECUTER_REGISTER_DISP_O_DIR_DAT 0xf506
+#define XECUTER_REGISTER_DISP_O_DIR_CMD 0xf507
+
+#define XECUTER_DISP_CON_RS 0x01
+#define XECUTER_DISP_CON_RW 0x02
+#define XECUTER_DISP_CON_E 0x04
+#define XECUTER_DISP_INI 0x01
+#define XECUTER_DISP_CMD 0x00
+#define XECUTER_DISP_DAT 0x02
+#define XECUTER_DISP_CLEAR 0x01
+#define XECUTER_DISP_HOME 0x02
+#define XECUTER_DISP_ENTRY_MODE_SET 0x04
+#define XECUTER_DISP_S_FLAG 0x01
+#define XECUTER_DISP_ID_FLAG 0x02
+#define XECUTER_DISP_CONTROL 0x08
+#define XECUTER_DISP_D_FLAG 0x04
+#define XECUTER_DISP_C_FLAG 0x02
+#define XECUTER_DISP_B_FLAG 0x01
+#define XECUTER_DISP_SHIFT 0x10
+#define XECUTER_DISP_SC_FLAG 0x08
+#define XECUTER_DISP_RL_FLAG 0x04
+#define XECUTER_DISP_FUNCTION_SET 0x20
+#define XECUTER_DISP_DL_FLAG 0x10
+#define XECUTER_DISP_N_FLAG 0x08
+#define XECUTER_DISP_F_FLAG 0x04
+#define XECUTER_DISP_RE_FLAG 0x04
+#define XECUTER_DISP_CGRAM_SET 0x40
+#define XECUTER_DISP_SEGRAM_SET 0x40
+#define XECUTER_DISP_DDRAM_SET 0x80
+
+//Xenium
+
+#define XENIUM_LCD_DELAY 2
+
+#define XENIUM_REGISTER_BANKING 0x00EF
+#define XENIUM_REGISTER_LED 0x00EE
+#define XENIUM_SPI_MOSI_BIT 0x10
+#define XENIUM_SPI_CS_BIT 0x20
+#define XENIUM_SPI_CLK_BIT 0x40
+
+#define XENIUM_BANK_TSOP 0
+#define XENIUM_BANK_BOOTLOADER 1
+#define XENIUM_BANK_PROMETHEOS1 2
+#define XENIUM_BANK_PROMETHEOS2 10
+#define XENIUM_BANK_SLOT1_256K 3
+#define XENIUM_BANK_SLOT2_256K 4
+#define XENIUM_BANK_SLOT3_256K 5
+#define XENIUM_BANK_SLOT4_256K 6
+#define XENIUM_BANK_SLOT1_512K 7
+#define XENIUM_BANK_SLOT2_512K 8
+#define XENIUM_BANK_SLOT1_1024K 9
+#define XENIUM_SETTINGS_BANK XENIUM_BANK_PROMETHEOS2
+#define XENIUM_SETTINGS_OFFSET (0x1f8000 - 0x1c0000)
+#define XENIUM_INSTALLER_LOGO_BANK XENIUM_BANK_PROMETHEOS2
+#define XENIUM_INSTALLER_LOGO_OFFSET (0x1fa000 - 0x1c0000)
+
+//XTREMIUM
+
+#define XTREMIUM_LCD_DELAY 2
+
+#define XTREMIUM_REGISTER_BANKING 0x00c
+#define XTREMIUM_REGISTER_LED 0x00EE
+#define XTREMIUM_SPI_MOSI_BIT 0x10
+#define XTREMIUM_SPI_CS_BIT 0x20
+#define XTREMIUM_SPI_CLK_BIT 0x40
+
+#define XTREMIUM_BANK_TSOP 0
+#define XTREMIUM_BANK_BOOTLOADER 1
+#define XTREMIUM_BANK_PROMETHEOS1 2
+#define XTREMIUM_BANK_PROMETHEOS2 10
+#define XTREMIUM_BANK_SLOT1_256K 3
+#define XTREMIUM_BANK_SLOT2_256K 4
+#define XTREMIUM_BANK_SLOT3_256K 5
+#define XTREMIUM_BANK_SLOT4_256K 6
+#define XTREMIUM_BANK_SLOT1_512K 7
+#define XTREMIUM_BANK_SLOT2_512K 8
+#define XTREMIUM_BANK_SLOT1_1024K 9
+#define XTREMIUM_SETTINGS_BANK XTREMIUM_BANK_PROMETHEOS2
+#define XTREMIUM_SETTINGS_OFFSET (0x1f8000 - 0x1c0000)
+#define XTREMIUM_INSTALLER_LOGO_BANK XTREMIUM_BANK_PROMETHEOS2
+#define XTREMIUM_INSTALLER_LOGO_OFFSET (0x1fa000 - 0x1c0000)
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/globalTypes.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/globalTypes.h
new file mode 100644
index 0000000..7096b1b
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/globalTypes.h
@@ -0,0 +1,20 @@
+#pragma once
+
+enum modchipType
+{
+ modchipTypeXenium,
+ modchipTypeXtremium,
+ modchipTypeXecuter,
+ modchipTypeSmartxx,
+ modchipTypeModxo,
+ modchipTypeAladdin1mb,
+ modchipTypeAladdin2mb,
+ modchipTypeXchanger,
+ modchipTypeDummy,
+};
+
+enum bankType
+{
+ bankTypeSystem,
+ bankTypeUser,
+};
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/harddrive.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/harddrive.cpp
new file mode 100644
index 0000000..f25fe4c
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/harddrive.cpp
@@ -0,0 +1,321 @@
+#include "harddrive.h"
+
+#include "stringUtility.h"
+#include "utils.h"
+#include "driveManager.h"
+#include "xboxInternals.h"
+
+bool harddrive::formatDrive(int harddrive)
+{
+ XboxPartitionTable table;
+ ULONGLONG totalSectors = 0;
+ DWORD version = 0;
+
+ NTSTATUS status = harddrive::readLbaInfo(harddrive, &table, &totalSectors, &version);
+ if (status != STATUS_SUCCESS)
+ {
+ utils::debugPrint("Read LBA info failed. Status: %08X\n", status);
+ return false;
+ }
+
+ driveManager::unmountAllDrives();
+
+ harddrive::initXboxPartitionTable(harddrive, totalSectors, &table);
+ status = harddrive::writePartitionTable(harddrive, &table);
+ if (status != STATUS_SUCCESS)
+ {
+ utils::debugPrint("Partition write failed.\n");
+ driveManager::mountAllDrives();
+ return false;
+ }
+
+ for (int i = 0; i < 14; i++)
+ {
+ if (table.TableEntries[i].Flags == harddrive::partitionTableEntryFlagNotInUse)
+ {
+ continue;
+ }
+
+ ULONGLONG lbaSize = harddrive::getPartitionLBASize(&table.TableEntries[i]);
+ ULONG clusterSize = harddrive::calculateClusterSize(lbaSize);
+ ULONG clusterSizeBytes = clusterSize << 10;
+
+ char* partition = stringUtility::formatString("\\Device\\Harddisk%i\\Partition%i", harddrive, i + 1);
+ STRING partitionString;
+ RtlInitAnsiString(&partitionString, partition);
+ BOOL success = XapiFormatFATVolumeEx(&partitionString, clusterSizeBytes);
+
+ // XapiFormatFATVolumeEx will format the partition with
+ // an incorrect SectorsPerCluster for large partitions, let's fix it
+ if(success && i >= 5) {
+ success = largePartitionFixup(harddrive, &table.TableEntries[i], clusterSizeBytes);
+ }
+
+ if (success == FALSE)
+ {
+ utils::debugPrint("Partition '%s' format failed.\n", partition);
+ free(partition);
+ driveManager::mountAllDrives();
+ return false;
+ }
+ free(partition);
+ }
+
+ driveManager::mountAllDrives();
+ return true;
+}
+
+ULONG harddrive::calculateClusterSize(ULONGLONG lbaSize)
+{
+ ULONG clusterSize = 16;
+ ULONGLONG compare = 0x20000000;
+ while (lbaSize > compare)
+ {
+ compare = compare * 2;
+ clusterSize = clusterSize * 2;
+ }
+ return clusterSize;
+}
+
+void harddrive::setPartitionName(const char* name, XboxPartitionTableEntry* entry)
+{
+ memset(entry->Name, 0x20, 16);
+ strncpy((char*)entry->Name, name, strlen(name));
+ entry->Flags = partitionTableEntryFlagInUse;
+}
+
+void harddrive::setPartitionLBAStart(ULONGLONG start, XboxPartitionTableEntry* entry)
+{
+ entry->LBAStartLo = (ULONG)(start & 0x00000000ffffffff);
+ entry->LBAStartHi = (USHORT)((start & 0x0000ffff00000000) >> 32);
+}
+
+void harddrive::setPartitionLBASize(ULONGLONG size, XboxPartitionTableEntry* entry)
+{
+ entry->LBASizeLo = (ULONG)(size & 0x00000000ffffffff);
+ entry->LBASizeHi = (USHORT)((size & 0x0000ffff00000000) >> 32);
+}
+
+ULONGLONG harddrive::getPartitionLBASize(XboxPartitionTableEntry* entry)
+{
+ return (((ULONGLONG)entry->LBASizeHi) << 32) | ((ULONGLONG)entry->LBASizeLo);
+}
+
+void harddrive::initXboxPartitionTable(int harddrive, ULONGLONG totalSectors, XboxPartitionTable* partitionTable)
+{
+ LONGLONG fPartLbaSize = totalSectors - PARTITION_XBOX_DATA_F_LBA_START;
+ memset(partitionTable, 0, sizeof(XboxPartitionTable));
+ strncpy((char*)partitionTable->Magic, "****PARTINFO****", 16);
+ partitionTable->FatxMode = harddrive == 0 ? 1 : 2;
+
+ setPartitionName(PARTITION_XBOX_NAME_DATA_E, &partitionTable->TableEntries[0]);
+ setPartitionLBAStart(PARTITION_XBOX_DATA_E_LBA_START, &partitionTable->TableEntries[0]);
+ setPartitionLBASize(PARTITION_XBOX_DATA_E_LBA_SIZE, &partitionTable->TableEntries[0]);
+
+ setPartitionName(PARTITION_XBOX_NAME_SHELL_C, &partitionTable->TableEntries[1]);
+ setPartitionLBAStart(PARTITION_XBOX_SHELL_C_LBA_START, &partitionTable->TableEntries[1]);
+ setPartitionLBASize(PARTITION_XBOX_SHELL_C_LBA_SIZE, &partitionTable->TableEntries[1]);
+
+ setPartitionName(PARTITION_XBOX_NAME_CACHE_X, &partitionTable->TableEntries[2]);
+ setPartitionLBAStart(PARTITION_XBOX_CACHE_X_LBA_START, &partitionTable->TableEntries[2]);
+ setPartitionLBASize(PARTITION_XBOX_CACHE_X_LBA_SIZE, &partitionTable->TableEntries[2]);
+
+ setPartitionName(PARTITION_XBOX_NAME_CACHE_Y, &partitionTable->TableEntries[3]);
+ setPartitionLBAStart(PARTITION_XBOX_CACHE_Y_LBA_START, &partitionTable->TableEntries[3]);
+ setPartitionLBASize(PARTITION_XBOX_CACHE_Y_LBA_SIZE, &partitionTable->TableEntries[3]);
+
+ setPartitionName(PARTITION_XBOX_NAME_CACHE_Z, &partitionTable->TableEntries[4]);
+ setPartitionLBAStart(PARTITION_XBOX_CACHE_Z_LBA_START, &partitionTable->TableEntries[4]);
+ setPartitionLBASize(PARTITION_XBOX_CACHE_Z_LBA_SIZE, &partitionTable->TableEntries[4]);
+
+ if(fPartLbaSize > 0) {
+ setPartitionName(PARTITION_XBOX_NAME_DRIVE_F, &partitionTable->TableEntries[5]);
+ setPartitionLBAStart(PARTITION_XBOX_DATA_F_LBA_START, &partitionTable->TableEntries[5]);
+ setPartitionLBASize(fPartLbaSize - 1, &partitionTable->TableEntries[5]);
+ }
+}
+
+NTSTATUS harddrive::readLbaInfo(int harddrive, XboxPartitionTable *p_table, ULONGLONG *total_sectors, DWORD *version)
+{
+ STRING a_file;
+ OBJECT_ATTRIBUTES obj_attr;
+ IO_STATUS_BLOCK io_stat_block;
+ HANDLE handle;
+ NTSTATUS stat;
+ unsigned int lba48_ioctl_cmd_in_buf[100];
+ unsigned int lba48_ioctl_cmd_out_buf[100];
+ unsigned int geom_ioctl_cmd_in_buf[100];
+ unsigned int partition_table_addr;
+ DISK_GEOMETRY DiskGeometry;
+
+ memset(p_table, 0, sizeof(XboxPartitionTable));
+
+ RtlInitAnsiString(&a_file, harddrive == 0 ? "\\Device\\Harddisk0\\partition0" : "\\Device\\Harddisk1\\partition0");
+ obj_attr.RootDirectory = 0;
+ obj_attr.ObjectName = &a_file;
+ obj_attr.Attributes = OBJ_CASE_INSENSITIVE;
+
+ stat = NtOpenFile(&handle, (GENERIC_READ|0x00100000), &obj_attr, &io_stat_block, (FILE_SHARE_READ|FILE_SHARE_WRITE), 0x10);
+ if (stat != STATUS_SUCCESS)
+ {
+ return stat;
+ }
+
+ memset(geom_ioctl_cmd_in_buf, 0, sizeof(geom_ioctl_cmd_in_buf));
+ geom_ioctl_cmd_in_buf[0] = IOCTL_SUBCMD_GET_INFO;
+
+ stat = NtDeviceIoControlFile(handle, 0, 0, 0, &io_stat_block, IOCTL_DISK_GET_DRIVE_GEOMETRY, geom_ioctl_cmd_in_buf, sizeof(geom_ioctl_cmd_in_buf), &DiskGeometry, sizeof(DiskGeometry));
+ if (stat == STATUS_SUCCESS)
+ {
+ *total_sectors = DiskGeometry.Cylinders.QuadPart;
+ }
+ else
+ {
+ *total_sectors = 0;
+ }
+
+ if (stat == STATUS_SUCCESS)
+ {
+ memset(lba48_ioctl_cmd_in_buf, 0, sizeof(lba48_ioctl_cmd_in_buf));
+ lba48_ioctl_cmd_in_buf[0] = IOCTL_SUBCMD_GET_INFO;
+
+ memset(lba48_ioctl_cmd_out_buf, 0, sizeof(lba48_ioctl_cmd_out_buf));
+
+ stat = NtDeviceIoControlFile(handle, 0, 0, 0, &io_stat_block, IOCTL_CMD_LBA48_ACCESS, lba48_ioctl_cmd_in_buf, sizeof(lba48_ioctl_cmd_in_buf), lba48_ioctl_cmd_out_buf, sizeof(lba48_ioctl_cmd_out_buf));
+ }
+
+ NtClose(handle);
+ if (stat != STATUS_SUCCESS)
+ {
+ return stat;
+ }
+
+ if ((lba48_ioctl_cmd_out_buf[LBA48_GET_INFO_MAGIC1_IDX] != LBA48_GET_INFO_MAGIC1_VAL) || (lba48_ioctl_cmd_out_buf[LBA48_GET_INFO_MAGIC2_IDX] != LBA48_GET_INFO_MAGIC2_VAL))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ partition_table_addr = lba48_ioctl_cmd_out_buf[LBA48_GET_INFO_LOWCODE_BASE_IDX];
+ partition_table_addr += lba48_ioctl_cmd_out_buf[LBA48_GET_INFO_PART_TABLE_OFS_IDX];
+
+ *version = lba48_ioctl_cmd_out_buf[LBA48_GET_INFO_PATCHCODE_VERSION_IDX];
+
+ if (*version == 2)
+ {
+ partition_table_addr += 0x200;
+ }
+
+ memcpy(p_table, (void *)partition_table_addr, sizeof(XboxPartitionTable));
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS harddrive::writePartitionTable(int harddrive, XboxPartitionTable *p_table)
+{
+ HANDLE hDisk = NULL;
+ NTSTATUS status = 0;
+ STRING a_path;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ LARGE_INTEGER RWOffset;
+ FILE_FS_SIZE_INFORMATION fsi;
+ ULONG PartTableSize = sizeof(XboxPartitionTable);
+
+ memset(&fsi, 0, sizeof(fsi));
+ RtlInitAnsiString(&a_path, harddrive == 0 ? "\\Device\\Harddisk0\\partition0" : "\\Device\\Harddisk1\\partition0");
+ InitializeObjectAttributes(&ObjectAttributes, &a_path, OBJ_CASE_INSENSITIVE, NULL);
+
+ status = NtOpenFile(&hDisk, SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE, &ObjectAttributes, &IoStatusBlock, (FILE_SHARE_READ|FILE_SHARE_WRITE), FILE_SYNCHRONOUS_IO_ALERT);
+ if(status < 0) {
+ goto CleanupAndReturn;
+ }
+
+ RWOffset.QuadPart = 0;
+ status = NtWriteFile(hDisk, NULL, NULL, NULL, &IoStatusBlock, (PVOID)p_table, PartTableSize, &RWOffset);
+ if(status < 0) {
+ goto CleanupAndReturn;
+ }
+
+ status = NtQueryVolumeInformationFile(hDisk, &IoStatusBlock, &fsi, sizeof(fsi), FileFsSizeInformation);
+ if(status < 0) {
+ goto CleanupAndReturn;
+ }
+
+ // Write a backup of the partition table at the end of the drive.
+ // We removed a sector from the last partition in initXboxPartitionTable()
+ // in order to accommodate the backup.
+ RWOffset.QuadPart = (fsi.TotalAllocationUnits.QuadPart * (LONGLONG)(fsi.BytesPerSector * fsi.SectorsPerAllocationUnit)) - PartTableSize;
+ status = NtWriteFile(hDisk, NULL, NULL, NULL, &IoStatusBlock, (PVOID)p_table, PartTableSize, &RWOffset);
+ if(status < 0) {
+ goto CleanupAndReturn;
+ }
+
+CleanupAndReturn:
+ NtClose(hDisk);
+ return status;
+}
+
+bool harddrive::largePartitionFixup(ULONG harddrive, XboxPartitionTableEntry* entry, ULONG clusterSize) {
+ NTSTATUS status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ DISK_GEOMETRY DiskGeometry;
+ ULONG SectorShift;
+ LARGE_INTEGER ByteOffset;
+ LARGE_INTEGER Offset;
+ ULONG ReadLength = ROUND_TO_PAGES(sizeof(FAT_VOLUME_METADATA));
+ HANDLE VolumeHandle = NULL;
+ PFAT_VOLUME_METADATA VolumeMetadata = NULL;
+ bool ret = false;
+
+ Offset.QuadPart = 0;
+
+ char* partition = stringUtility::formatString("\\Device\\Harddisk%i\\Partition0", harddrive);
+ STRING partitionString;
+ RtlInitAnsiString(&partitionString, partition);
+
+ InitializeObjectAttributes(&ObjectAttributes, &partitionString, OBJ_CASE_INSENSITIVE, NULL);
+
+ if(status = NtOpenFile(&VolumeHandle, SYNCHRONIZE | GENERIC_READ |
+ GENERIC_WRITE, &ObjectAttributes, &IoStatusBlock, (FILE_SHARE_READ|FILE_SHARE_WRITE),
+ FILE_SYNCHRONOUS_IO_ALERT | FILE_NO_INTERMEDIATE_BUFFERING)) {
+ goto CleanupAndReturn;
+ }
+
+ if(status = NtDeviceIoControlFile(VolumeHandle, NULL, NULL, NULL, &IoStatusBlock,
+ IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &DiskGeometry,
+ sizeof(DiskGeometry))) {
+ goto CleanupAndReturn;
+ }
+
+ SectorShift = utils::FindFirstSetRightMember(DiskGeometry.BytesPerSector);
+ Offset.HighPart = entry->LBAStartHi;
+ Offset.LowPart = entry->LBAStartLo;
+ Offset.QuadPart <<= SectorShift;
+
+ VolumeMetadata = (PFAT_VOLUME_METADATA)malloc(ReadLength);
+
+ ByteOffset = Offset;
+ if(status = NtReadFile(VolumeHandle, NULL, NULL, NULL, &IoStatusBlock,
+ VolumeMetadata, ReadLength, &ByteOffset)) {
+ goto CleanupAndReturn;
+ }
+
+ if(memcmp(&VolumeMetadata->Signature, "FATX", 4) == 0 && VolumeMetadata->SectorsPerCluster == 0) {
+ VolumeMetadata->SectorsPerCluster = (ULONG)(clusterSize >> SectorShift);
+
+ ByteOffset = Offset;
+ if(status = NtWriteFile(VolumeHandle, NULL, NULL, NULL, &IoStatusBlock,
+ VolumeMetadata, ReadLength, &ByteOffset)) {
+ goto CleanupAndReturn;
+ }
+ }
+
+ ret = true;
+
+CleanupAndReturn:
+ NtClose(VolumeHandle);
+ free(VolumeMetadata);
+ free(partition);
+ return ret;
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/harddrive.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/harddrive.h
new file mode 100644
index 0000000..9d200af
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/harddrive.h
@@ -0,0 +1,154 @@
+#pragma once
+
+#include
+
+#include "xboxInternals.h"
+
+typedef struct XboxPartitionTableEntry
+{
+ UCHAR Name[16];
+ ULONG Flags;
+ ULONG LBAStartLo;
+ ULONG LBASizeLo;
+ USHORT LBAStartHi;
+ USHORT LBASizeHi;
+} XboxPartitionTableEntry;
+
+typedef struct XboxPartitionTable
+{
+ UCHAR Magic[16];
+ UCHAR FatxMode;
+ char Res0[31];
+ XboxPartitionTableEntry TableEntries[14];
+ char Res1[16];
+} XboxPartitionTable;
+
+typedef enum MEDIA_TYPE {
+ Unknown, // Format is unknown
+ F5_1Pt2_512, // 5.25", 1.2MB, 512 bytes/sector
+ F3_1Pt44_512, // 3.5", 1.44MB, 512 bytes/sector
+ F3_2Pt88_512, // 3.5", 2.88MB, 512 bytes/sector
+ F3_20Pt8_512, // 3.5", 20.8MB, 512 bytes/sector
+ F3_720_512, // 3.5", 720KB, 512 bytes/sector
+ F5_360_512, // 5.25", 360KB, 512 bytes/sector
+ F5_320_512, // 5.25", 320KB, 512 bytes/sector
+ F5_320_1024, // 5.25", 320KB, 1024 bytes/sector
+ F5_180_512, // 5.25", 180KB, 512 bytes/sector
+ F5_160_512, // 5.25", 160KB, 512 bytes/sector
+ RemovableMedia, // Removable media other than floppy
+ FixedMedia, // Fixed hard disk media
+ F3_120M_512, // 3.5", 120M Floppy
+ F3_640_512, // 3.5" , 640KB, 512 bytes/sector
+ F5_640_512, // 5.25", 640KB, 512 bytes/sector
+ F5_720_512, // 5.25", 720KB, 512 bytes/sector
+ F3_1Pt2_512, // 3.5" , 1.2Mb, 512 bytes/sector
+ F3_1Pt23_1024, // 3.5" , 1.23Mb, 1024 bytes/sector
+ F5_1Pt23_1024, // 5.25", 1.23MB, 1024 bytes/sector
+ F3_128Mb_512, // 3.5" MO 128Mb 512 bytes/sector
+ F3_230Mb_512, // 3.5" MO 230Mb 512 bytes/sector
+ F8_256_128 // 8", 256KB, 128 bytes/sector
+} MEDIA_TYPE;
+
+typedef struct DISK_GEOMETRY {
+ LARGE_INTEGER Cylinders;
+ MEDIA_TYPE MediaType;
+ DWORD TracksPerCylinder;
+ DWORD SectorsPerTrack;
+ DWORD BytesPerSector;
+} DISK_GEOMETRY;
+
+#define OBJ_CASE_INSENSITIVE 0x00000040
+
+#define IOCTL_CMD_LBA48_ACCESS 0xcafebabe
+#define IOCTL_SUBCMD_GET_INFO 0
+
+#define LBA48_GET_INFO_MAGIC1_IDX 0
+#define LBA48_GET_INFO_MAGIC1_VAL 0xcafebabe
+#define LBA48_GET_INFO_MAGIC2_IDX 1
+#define LBA48_GET_INFO_MAGIC2_VAL 0xbabeface
+#define LBA48_GET_INFO_PATCHCODE_VERSION_IDX 2
+#define LBA48_GET_INFO_LOWCODE_BASE_IDX 3
+#define LBA48_GET_INFO_HIGHCODE_BASE_IDX 4
+#define LBA48_GET_INFO_PATCHSEG_SIZE_IDX 5
+#define LBA48_GET_INFO_PART_TABLE_OFS_IDX 6
+
+#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
+ ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
+)
+
+#define FILE_DEVICE_DISK 0x00000007
+#define FILE_SYNCHRONOUS_IO_ALERT 0x00000010
+#define FILE_NO_INTERMEDIATE_BUFFERING 0x00000008
+
+#define FILE_ANY_ACCESS 0
+//#define FILE_READ_ACCESS ( 0x0001 ) // file & pipe
+//#define FILE_WRITE_ACCESS ( 0x0002 ) // file & pipe
+
+#define METHOD_BUFFERED 0
+
+#define IOCTL_DISK_BASE FILE_DEVICE_DISK
+#define IOCTL_DISK_GET_DRIVE_GEOMETRY CTL_CODE(IOCTL_DISK_BASE, 0x0000, METHOD_BUFFERED, FILE_ANY_ACCESS)
+//#define IOCTL_DISK_GET_PARTITION_INFO CTL_CODE(IOCTL_DISK_BASE, 0x0001, METHOD_BUFFERED, FILE_READ_ACCESS)
+//#define IOCTL_DISK_SET_PARTITION_INFO CTL_CODE(IOCTL_DISK_BASE, 0x0002, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+//#define IOCTL_DISK_GET_DRIVE_LAYOUT CTL_CODE(IOCTL_DISK_BASE, 0x0003, METHOD_BUFFERED, FILE_READ_ACCESS)
+//#define IOCTL_DISK_SET_DRIVE_LAYOUT CTL_CODE(IOCTL_DISK_BASE, 0x0004, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+//#define IOCTL_DISK_VERIFY CTL_CODE(IOCTL_DISK_BASE, 0x0005, METHOD_BUFFERED, FILE_ANY_ACCESS)
+//#define IOCTL_DISK_FORMAT_TRACKS CTL_CODE(IOCTL_DISK_BASE, 0x0006, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+//#define IOCTL_DISK_REASSIGN_BLOCKS CTL_CODE(IOCTL_DISK_BASE, 0x0007, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+//#define IOCTL_DISK_PERFORMANCE CTL_CODE(IOCTL_DISK_BASE, 0x0008, METHOD_BUFFERED, FILE_ANY_ACCESS)
+//#define IOCTL_DISK_IS_WRITABLE CTL_CODE(IOCTL_DISK_BASE, 0x0009, METHOD_BUFFERED, FILE_ANY_ACCESS)
+//#define IOCTL_DISK_LOGGING CTL_CODE(IOCTL_DISK_BASE, 0x000a, METHOD_BUFFERED, FILE_ANY_ACCESS)
+//#define IOCTL_DISK_FORMAT_TRACKS_EX CTL_CODE(IOCTL_DISK_BASE, 0x000b, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+//#define IOCTL_DISK_HISTOGRAM_STRUCTURE CTL_CODE(IOCTL_DISK_BASE, 0x000c, METHOD_BUFFERED, FILE_ANY_ACCESS)
+//#define IOCTL_DISK_HISTOGRAM_DATA CTL_CODE(IOCTL_DISK_BASE, 0x000d, METHOD_BUFFERED, FILE_ANY_ACCESS)
+//#define IOCTL_DISK_HISTOGRAM_RESET CTL_CODE(IOCTL_DISK_BASE, 0x000e, METHOD_BUFFERED, FILE_ANY_ACCESS)
+//#define IOCTL_DISK_REQUEST_STRUCTURE CTL_CODE(IOCTL_DISK_BASE, 0x000f, METHOD_BUFFERED, FILE_ANY_ACCESS)
+//#define IOCTL_DISK_REQUEST_DATA CTL_CODE(IOCTL_DISK_BASE, 0x0010, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define PARTITION_XBOX_CACHE_X_LBA_SIZE 0x177000
+#define PARTITION_XBOX_CACHE_X_LBA_START 0x400
+#define PARTITION_XBOX_CACHE_Y_LBA_SIZE 0x177000
+#define PARTITION_XBOX_CACHE_Y_LBA_START (PARTITION_XBOX_CACHE_X_LBA_START + PARTITION_XBOX_CACHE_X_LBA_SIZE)
+#define PARTITION_XBOX_CACHE_Z_LBA_SIZE 0x177000
+#define PARTITION_XBOX_CACHE_Z_LBA_START (PARTITION_XBOX_CACHE_Y_LBA_START + PARTITION_XBOX_CACHE_Y_LBA_SIZE)
+#define PARTITION_XBOX_SHELL_C_LBA_SIZE 0xfa000
+#define PARTITION_XBOX_SHELL_C_LBA_START (PARTITION_XBOX_CACHE_Z_LBA_START + PARTITION_XBOX_CACHE_Z_LBA_SIZE)
+#define PARTITION_XBOX_DATA_E_LBA_SIZE 0x9896b0
+#define PARTITION_XBOX_DATA_E_LBA_START (PARTITION_XBOX_SHELL_C_LBA_START + PARTITION_XBOX_SHELL_C_LBA_SIZE)
+#define PARTITION_XBOX_DATA_F_LBA_START (PARTITION_XBOX_DATA_E_LBA_START + PARTITION_XBOX_DATA_E_LBA_SIZE)
+
+#define PARTITION_XBOX_NAME_DATA_E "XBOX DATA E"
+#define PARTITION_XBOX_NAME_SHELL_C "XBOX SHELL C"
+#define PARTITION_XBOX_NAME_CACHE_X "XBOX CACHE X"
+#define PARTITION_XBOX_NAME_CACHE_Y "XBOX CACHE Y"
+#define PARTITION_XBOX_NAME_CACHE_Z "XBOX CACHE Z"
+#define PARTITION_XBOX_NAME_DRIVE_F "DRIVE F"
+
+class harddrive
+{
+public:
+
+ enum partitionTableEntryFlag
+ {
+ partitionTableEntryFlagNotInUse = 0x00000000,
+ partitionTableEntryFlagInUse = 0x80000000,
+ };
+
+ enum fatxMode
+ {
+ fatxModeCerbiosPrimary = 1,
+ fatxModeCerbiosSecondary = 2,
+ fatxModeStellar = 3,
+ };
+
+ static bool largePartitionFixup(ULONG harddrive, XboxPartitionTableEntry* entry, ULONG clusterSize);
+ static bool formatDrive(int harddrive);
+ static ULONG calculateClusterSize(ULONGLONG lbaSize);
+ static void setPartitionName(const char* name, XboxPartitionTableEntry* entry);
+ static void setPartitionLBAStart(ULONGLONG start, XboxPartitionTableEntry* entry);
+ static void setPartitionLBASize(ULONGLONG size, XboxPartitionTableEntry* entry);
+ static ULONGLONG getPartitionLBASize(XboxPartitionTableEntry* entry);
+ static void initXboxPartitionTable(int harddrive, ULONGLONG totalSectors, XboxPartitionTable* partitionTable);
+ static NTSTATUS readLbaInfo(int harddrive, XboxPartitionTable *p_table, ULONGLONG *total_sectors, DWORD *version);
+ static NTSTATUS writePartitionTable(int harddrive, XboxPartitionTable *p_table);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/hddVscUnlocker.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/hddVscUnlocker.cpp
new file mode 100644
index 0000000..59b401d
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/hddVscUnlocker.cpp
@@ -0,0 +1,955 @@
+#include "hddVscUnlocker.h"
+#include "xboxinternals.h"
+#include "stringUtility.h"
+#include "utils.h"
+#include
+#include
+
+#ifdef _DEBUG
+ #define DBG_STR_SIZE (1 * 1024 * 1024)
+#else
+ #define DBG_STR_SIZE (4096)
+#endif
+
+hddVscUnlocker::hddVscUnlocker() {
+ mIdePort = IDE_PORT_PRIMARY;
+ mIdeDrv = IDE_DRIVE_MASTER;
+ mLastError = STATUS_SUCCESS;
+ mHasMasterPwd = false;
+ mHasUserPwd = false;
+
+ debugStrOffset = 0;
+ debugStr = (char*)malloc(DBG_STR_SIZE);
+ memset(debugStr, 0, DBG_STR_SIZE);
+ debugArrOff = 0;
+ debugArrSize = 4096;
+ memset(mDebugArr, 0, debugArrSize);
+
+ memset(&mDrvInfo, 0, sizeof(DRIVE_INFO));
+ memset(&mIdentSect, 0, sizeof(IDENT_SECTOR));
+}
+
+hddVscUnlocker::~hddVscUnlocker() {
+ free(debugStr);
+ freeIdentifyData();
+}
+
+void hddVscUnlocker::setIdePort(IDE_PORT port) {
+ mIdePort = port;
+}
+
+void hddVscUnlocker::setIdeDrive(IDE_DRIVE drv) {
+ mIdeDrv = drv;
+}
+
+void hddVscUnlocker::debug(char* str) {
+ if(debugStrOffset >= DBG_STR_SIZE) {
+ debugStrOffset = 0;
+ memset(debugStr, 0, DBG_STR_SIZE);
+ }
+
+ uint32_t len = strlen(str);
+ memcpy(debugStr + debugStrOffset, str, len);
+ debugStrOffset += len;
+}
+
+void hddVscUnlocker::debugArr(uint32_t val) {
+ mDebugArr[debugArrOff++] = val;
+ if(debugArrOff>debugArrSize) {
+ debugArrOff = 0;
+ memset(mDebugArr, 0, debugArrSize);
+ }
+}
+
+// This will set/clear bit 4 of the drive select register
+uint8_t hddVscUnlocker::getDrvRegBits(uint8_t drvReg) {
+ if(mIdeDrv == IDE_DRIVE_MASTER) {
+ return drvReg & ~0x10;
+ } else {
+ return drvReg | 0x10;
+ }
+}
+
+void hddVscUnlocker::freeIdentifyData() {
+ free(mDrvInfo.model);
+ free(mDrvInfo.serial);
+ free(mDrvInfo.firmware);
+ memset(&mDrvInfo, 0, sizeof(DRIVE_INFO));
+}
+
+bool hddVscUnlocker::waitForDrive(bool altPort, uint32_t timeout) {
+ uint8_t flags = 0x80; // 1000 0000 = Drive busy flag
+ uint8_t status = 0;
+ uint16_t reg = mIdePort + 7;
+ uint8_t scale = 10;
+ timeout = timeout * scale;
+ uint32_t start = timeout;
+
+ // Read from alt status port, doesn't distrub any flags
+ if(altPort) {
+ reg = 0x200 + mIdePort + 6;
+ }
+
+ status = _inp(reg);
+ while (((status & flags) == flags) && (timeout > 0)) {
+ status = _inp(reg);
+ KeStallExecutionProcessor(100);
+ timeout--;
+ }
+
+ uint32_t time = (start - timeout) / scale;
+ utils::debugPrint("[waitForDrive] status: %02X, reg: %02X, time: %lums\n", status, reg, time);
+
+ if((status & flags) == flags) {
+ mLastError = STATUS_IO_TIMEOUT;
+ return false;
+ }
+
+ mLastError = STATUS_SUCCESS;
+ return true;
+}
+
+bool hddVscUnlocker::spinWait(bool altPort, uint32_t timeout) {
+ uint16_t reg = altPort ? (0x200 + mIdePort + 6) : (mIdePort + 7);
+ uint8_t status = 0;
+ mLastError = STATUS_SUCCESS;
+
+ do {
+ status = _inp(reg);
+ if((status & 0x80) == 0) return true;
+ KeStallExecutionProcessor(100);
+ } while(--timeout);
+
+ mLastError = STATUS_IO_TIMEOUT;
+ return false;
+}
+
+bool hddVscUnlocker::wdUnlockMod42() {
+ if(!wdVscEnSvcMode()) {
+ utils::debugPrint("wdVscEnSvcMode err: 0x%08X\n", getLastError());
+ return false;
+ }
+
+ if(!wdVscReadSecSect()) {
+ utils::debugPrint("wdVscReadSecSect err: 0x%08X\n", getLastError());
+ return false;
+ }
+
+ uint8_t buf[8192];
+ uint32_t firstSectSize = 512;
+ uint32_t sectIdx = 11;
+ memset(buf, 0, sizeof(buf));
+
+ readDriveData(buf, firstSectSize);
+ utils::hexDumpDebug(buf, firstSectSize);
+
+ uint8_t numSects = ((uint16_t*)buf)[sectIdx];
+ uint32_t numBytes = numSects * 512;
+
+ utils::debugPrint("wdMod42 numSects: 0x%04X - %d\n", numSects, numBytes);
+
+ if(numBytes > sizeof(buf)) {
+ utils::debugPrint("Unable to allocate Mod42 buffer\n");
+ return false;
+ }
+
+ if(!wdVscReadSecSect(numSects)) {
+ utils::debugPrint("wdVscReadSecSect_2 err: 0x%08X\n", getLastError());
+ return false;
+ }
+
+ readDriveData(buf, numBytes);
+ utils::hexDumpDebug(buf, numBytes);
+
+ if(!resetIdeBus()) {
+ return false;
+ }
+
+ wdExtractAndSetPwds(buf);
+
+ if(!doAtaSecUnlock()) {
+ return false;
+ }
+
+ mLastError = STATUS_SUCCESS;
+ return true;
+}
+
+bool hddVscUnlocker::wdOemUnlock_WDC_WD80EB() {
+ return wdUnlockMod42();
+}
+
+bool hddVscUnlocker::wdRoylUnlock() {
+ uint8_t statusReg = mIdePort + 7;
+
+ if(!wdRoylVscEnDis()) {
+ utils::debugPrint("wdRoylVscEnDis err: 0x%08X\n", getLastError());
+ return false;
+ }
+
+ if(!wdRoylSeekMod02()) {
+ utils::debugPrint("wdRoylSeekMod02 err: 0x%08X\n", getLastError());
+ return false;
+ }
+
+ if(!wdRoylReadMod02()) {
+ utils::debugPrint("wdRoylReadMod02_1 err: 0x%08X\n", getLastError());
+ return false;
+ }
+
+ uint8_t buf[8192];
+ uint32_t firstSectSize = 512;
+ uint32_t sectIdx = 5;
+ uint32_t passIdx = 0x3d;
+ memset(buf, 0, sizeof(buf));
+
+ readDriveData(buf, firstSectSize);
+ utils::hexDumpDebug(buf, firstSectSize);
+
+ if(memcmp(buf, "ROYL", 4) != 0) {
+ // Check for in-between drives (2005-ish)
+ if(memcmp(buf + 0x8c, "WD-", 3) == 0) {
+ sectIdx = 11;
+ passIdx = 0x31;
+ } else {
+ utils::debugPrint("Not a WD ROYL drive\n");
+ return wdUnlockMod42();
+ }
+ }
+
+ uint8_t numSects = ((uint16_t*)buf)[sectIdx] - 1;
+ uint32_t numBytes = numSects * 512;
+
+ utils::debugPrint("wdRoyl numSects: 0x%04X - %d\n", numSects, numBytes);
+
+ if((numBytes + firstSectSize) > sizeof(buf)) {
+ utils::debugPrint("Unable to allocate ROYL buffer\n");
+ return false;
+ }
+
+ if(!wdRoylReadMod02(numSects)) {
+ utils::debugPrint("wdRoylReadMod02_2 err: 0x%08X\n", getLastError());
+ return false;
+ }
+
+ readDriveData(buf + firstSectSize, numBytes);
+ utils::hexDumpDebug(buf + firstSectSize, numBytes);
+
+ if(!wdRoylVscEnDis(true)) {
+ utils::debugPrint("wdRoylVscEnDis err: 0x%08X\n", getLastError());
+ return false;
+ }
+
+ if(!waitForDrive(false)) {
+ return false;
+ }
+
+ wdRoylExtractAndSetPwds(buf, passIdx);
+
+ if(!doAtaSecUnlock()) {
+ return false;
+ }
+
+ mLastError = STATUS_SUCCESS;
+ return true;
+}
+
+bool hddVscUnlocker::wdRoylVscEnDis(bool disable) {
+ IDE_CMD cmd = { disable ? 0x44 : 0x45, 0x0b, 0x00, 0x44, 0x57, 0xa0, 0x80 };
+ if(!sendDriveCmd(cmd)) {
+ utils::debugPrint("sendDriveCmd err: %08X\n", getLastError());
+ return false;
+ }
+
+ mLastError = STATUS_SUCCESS;
+ return true;
+}
+
+bool hddVscUnlocker::wdRoylReadMod02(uint8_t numSects) {
+ IDE_CMD cmd = { 0xd5, numSects, 0xbf, 0x4f, 0xc2, 0xa0, 0xb0 };
+ if(!sendDriveCmd(cmd)) {
+ utils::debugPrint("sendDriveCmd err: %08X\n", getLastError());
+ return false;
+ }
+
+ mLastError = STATUS_SUCCESS;
+ return true;
+}
+
+bool hddVscUnlocker::wdRoylSeekMod02() {
+ IDE_CMD cmd = { 0xd6, 0x01, 0xbe, 0x4f, 0xc2, 0xa0, 0xb0 };
+ if(!sendDriveCmd(cmd)) {
+ utils::debugPrint("sendDriveCmd err: %08X\n", getLastError());
+ return false;
+ }
+
+ uint8_t buf[512];
+ memset(buf, 0, sizeof(buf));
+ buf[0] = 0x0b;
+ buf[1] = 0x00;
+ buf[2] = 0x04;
+ buf[3] = 0x00;
+ buf[4] = 0x02;
+
+ if(!writeDriveData(buf, sizeof(buf))) {
+ utils::debugPrint("writeDriveData err: %08X\n", getLastError());
+ return false;
+ }
+
+ mLastError = STATUS_SUCCESS;
+ return true;
+}
+
+bool hddVscUnlocker::wdRoylRstDrv() {
+ IDE_CMD cmd = { 0xd6, 0x01, 0xbe, 0x4f, 0xc2, 0xa0, 0xb0 };
+ if(!sendDriveCmd(cmd)) {
+ utils::debugPrint("sendDriveCmd err: %08X\n", getLastError());
+ return false;
+ }
+
+ uint8_t buf[512];
+ memset(buf, 0, sizeof(buf));
+ buf[0] = 0x1c;
+ buf[1] = 0x00;
+ buf[2] = 0x01;
+
+ if(!writeDriveData(buf, sizeof(buf))) {
+ utils::debugPrint("writeDriveData err: %08X\n", getLastError());
+ return false;
+ }
+
+ mLastError = STATUS_SUCCESS;
+ return true;
+}
+
+void hddVscUnlocker::sgConvertHexPwdStr(uint32_t offset, uint32_t size, char* buf, uint8_t* out) {
+ for(uint32_t i = offset, n = 0; i < (offset + size); ) {
+ uint8_t upper = buf[i];
+ uint8_t lower = buf[i+1];
+
+ if(upper == 0x20 || upper == 0x0d) {
+ i++; continue;
+ }
+
+ if(upper == 0x0a) {
+ i+=8; continue;
+ }
+
+ char hexStr[3] = { upper, lower, '\0' };
+ out[n] = (uint8_t)strtol(hexStr, NULL, 16);
+ n++;
+ i+=2;
+ }
+}
+
+void hddVscUnlocker::sgExtractAndSetPwds(char* buf, uint32_t mstrOffset, uint32_t userOffset) {
+ mHasMasterPwd = true;
+ mHasUserPwd = true;
+
+ sgConvertHexPwdStr(mstrOffset, 0x50, buf, mMasterPwd);
+ sgConvertHexPwdStr(userOffset, 0x50, buf, mUserPwd);
+
+ utils::debugPrint("Seagate Master Pwd:\n");
+ utils::hexDumpDebug(mMasterPwd, ATA_SEC_PWD_SIZE);
+
+ utils::debugPrint("Seagate User Pwd:\n");
+ utils::hexDumpDebug(mUserPwd, ATA_SEC_PWD_SIZE);
+}
+
+bool hddVscUnlocker::sgVscEnableDiagMode() {
+ IDE_CMD cmd = { 0, 0x44, 0x69, 0x61, 0x47, 0xe0, 0xfe }; // ".DiaG.."
+ sendDriveRawCmd(cmd);
+ KeStallExecutionProcessor(10000);
+ return spinWait();
+}
+
+bool hddVscUnlocker::sgVscDiagSendByte(uint8_t cmdByte) {
+ IDE_CMD cmd = { 0, 1, 0, 0, cmdByte, 0xe0, 0xfe };
+ sendDriveRawCmd(cmd);
+ KeStallExecutionProcessor(10000);
+ return spinWait(true);
+}
+
+bool hddVscUnlocker::sgVscDiagSendCmd(char* cmd) {
+ bool res = true;
+ uint32_t status = 0;
+
+ while(*cmd != 0) {
+ if(!sgVscDiagSendByte(*cmd)) {
+ res = false;
+ break;
+ }
+
+ status = _inp(mIdePort + 7);
+ if((status & 1) != 0) {
+ mLastError = STATUS_INVALID_DEVICE_REQUEST;
+ res = false;
+ break;
+ }
+
+ KeStallExecutionProcessor(10000);
+ cmd++;
+ }
+
+ KeStallExecutionProcessor(10000);
+ return res;
+}
+
+uint8_t hddVscUnlocker::sgVscDiagReadWait(uint8_t* status, uint32_t timeout) {
+ do {
+ *status = _inp(0x200 + mIdePort + 6);
+
+ if(((*status & 0x80) == 0) && ((*status & 0x40) != 0)) {
+ return 1;
+ }
+
+ KeStallExecutionProcessor(100);
+ } while(--timeout);
+
+ return 0;
+}
+
+bool hddVscUnlocker::sgVscDiagRead(char* buf, uint32_t expLen, uint32_t timeout) {
+ IDE_CMD cmd = { 0, 1, 0, 0, 0, 0xe0, 0xff };
+ uint8_t status;
+ uint32_t i = 0;
+ uint32_t bufsize = 0;
+ char* start = buf;
+ bool res = true;
+ bool hasExpLen = !!expLen;
+
+ do {
+ if(i >= 10) {
+ res = false;
+ break;
+ }
+
+ --expLen;
+
+ if(hasExpLen && expLen == 0) {
+ timeout = 1000;
+ }
+
+ sendDriveRawCmd(cmd);
+ KeStallExecutionProcessor(1000);
+ uint8_t waitRes = sgVscDiagReadWait(&status, timeout);
+
+ if(!waitRes) {
+ *buf = _inp(mIdePort + 4);
+ buf++;
+ res = false;
+ break;
+ }
+
+ if((status & 1) == 0) {
+ *buf = _inp(mIdePort + 4);
+ buf++;
+ } else {
+ uint8_t flags = _inp(mIdePort + 2);
+ if((flags & 1) == 0) {
+ res = false;
+ break;
+ }
+ i++;
+ }
+ } while(true);
+
+ *buf = 0;
+ KeStallExecutionProcessor(10000);
+ return res;
+}
+
+bool hddVscUnlocker::sgVscDiagExecCmd(char* cmd, char* buffer, uint32_t expLen, uint32_t timeout) {
+ sgVscDiagSendCmd(cmd);
+ sgVscDiagRead(buffer, strlen(cmd), timeout);
+ sgVscDiagSendCmd("\r");
+ sgVscDiagRead(buffer, expLen, timeout);
+ return true;
+}
+
+bool hddVscUnlocker::sgOemUnlock_ST310014A() {
+ bool res = true;
+ mLastError = STATUS_SUCCESS;
+
+ char discard[512];
+ char buffer[2048];
+ memset(discard, 0xcc, sizeof(discard));
+ memset(buffer, 0xcc, sizeof(buffer));
+
+ uint8_t irql;
+ HalGetInterruptVector(0xe, &irql); // 0xe = PNPISABus
+ uint8_t oldIrql = KfRaiseIrql(irql);
+
+ if(!sgVscEnableDiagMode()) {
+ res = false;
+ goto out;
+ }
+
+
+ sgVscDiagSendCmd("\x1a"); // Ctrl-Z (enable terminal)
+ sgVscDiagRead(discard, 20);
+
+ sgVscDiagExecCmd("/2", discard, 4); // change to diagnostic command level 2
+ sgVscDiagExecCmd("S006b", discard, 4); // seek to logical cylinder/head, i.e. track 6Bh
+ sgVscDiagExecCmd("R20,01", discard, 4); // read sector 20h into buffer
+ sgVscDiagExecCmd("C0,570", discard, 4); // copy one sector from buffer 0 to buffer 570h
+ sgVscDiagExecCmd("B570", buffer, 0x5ea); // print buffer 570h to terminal
+
+ sgVscDiagSendCmd("\x03"); // Ctrl-C (soft reset device)
+ sgVscDiagRead(discard, 0x29, 30000);
+
+ KeStallExecutionProcessor(100000);
+ resetIdeBusRaw();
+
+out:
+ KfLowerIrql(oldIrql);
+
+ sgExtractAndSetPwds(buffer, 0xa8, 0xf8);
+
+ if(!waitForDrive()) {
+ res = false;
+ }
+
+ if(!doAtaSecUnlock()) {
+ res = false;
+ }
+
+ return res;
+}
+
+bool hddVscUnlocker::sgOemUnlock_ST310211A() {
+ uint8_t irql;
+ HalGetInterruptVector(0xe, &irql); // 0xe = PNPISABus
+ uint8_t irqlVect = KfRaiseIrql(irql);
+
+ bool res = true;
+ mLastError = STATUS_SUCCESS;
+
+ char discard[512];
+ char buffer[2048];
+ memset(discard, 0, sizeof(discard));
+ memset(buffer, 0, sizeof(buffer));
+
+ if(!sgVscEnableDiagMode()) {
+ res = false;
+ goto out;
+ }
+
+ sgVscDiagSendCmd("\x1a");
+ sgVscDiagRead(discard, 12);
+
+ sgVscDiagExecCmd("GFFFFFFF3", discard, 4);
+ sgVscDiagExecCmd("/2", discard, 4);
+ sgVscDiagExecCmd("B0,0", buffer, 0x5e2);
+
+ sgVscDiagSendCmd("\x03");
+ sgVscDiagRead(discard, 0x91, 30000);
+
+ KeStallExecutionProcessor(100000);
+ resetIdeBusRaw();
+
+out:
+ KfLowerIrql(irqlVect);
+
+ sgExtractAndSetPwds(buffer, 0xa0, 0xf0);
+
+ if(!waitForDrive()) {
+ res = false;
+ }
+
+ if(!doAtaSecUnlock()) {
+ res = false;
+ }
+
+ return res;
+}
+
+void hddVscUnlocker::wdExtractAndSetPwds(uint8_t* buf) {
+ memcpy(mMasterPwd, buf + WD_INFO_MASTER_PWD_OFFSET, ATA_SEC_PWD_SIZE);
+ utils::debugPrint("WD Master Pwd:\n");
+ utils::hexDumpDebug(mMasterPwd, ATA_SEC_PWD_SIZE);
+
+ memcpy(mUserPwd, buf + WD_INFO_USER_PWD_OFFSET, ATA_SEC_PWD_SIZE);
+ utils::debugPrint("WD User Pwd:\n");
+ utils::hexDumpDebug(mUserPwd, ATA_SEC_PWD_SIZE);
+
+ mHasMasterPwd = true;
+ mHasUserPwd = true;
+}
+
+void hddVscUnlocker::wdRoylExtractAndSetPwds(uint8_t* buf, uint32_t idx) {
+ uint16_t passRecOff = ((uint16_t*)buf)[idx];
+ utils::debugPrint("WD ROYL Password Offset: 0x%04x\n", passRecOff);
+
+ memcpy(mMasterPwd, buf + passRecOff + 4 + ATA_SEC_PWD_SIZE, ATA_SEC_PWD_SIZE);
+ utils::debugPrint("WD ROYL Master Pwd:\n");
+ utils::hexDumpDebug(mMasterPwd, ATA_SEC_PWD_SIZE);
+
+ memcpy(mUserPwd, buf + passRecOff + 4, ATA_SEC_PWD_SIZE);
+ utils::debugPrint("WD ROYL User Pwd:\n");
+ utils::hexDumpDebug(mUserPwd, ATA_SEC_PWD_SIZE);
+
+ mHasMasterPwd = true;
+ mHasUserPwd = true;
+}
+
+void hddVscUnlocker::parseIdentifySector() {
+ freeIdentifyData();
+
+ utils::byteSwap16((uint8_t*)mIdentSect.model, sizeof(mIdentSect.model));
+ utils::byteSwap16((uint8_t*)mIdentSect.serial, sizeof(mIdentSect.serial));
+ utils::byteSwap16((uint8_t*)mIdentSect.firmware, sizeof(mIdentSect.firmware));
+
+ char model[sizeof(mIdentSect.model) + 1] = { 0 };
+ char serial[sizeof(mIdentSect.serial) + 1] = { 0 };
+ char firmware[sizeof(mIdentSect.firmware) + 1] = { 0 };
+
+ memcpy(model, mIdentSect.model, sizeof(mIdentSect.model));
+ memcpy(serial, mIdentSect.serial, sizeof(mIdentSect.serial));
+ memcpy(firmware, mIdentSect.firmware, sizeof(mIdentSect.firmware));
+
+ stringUtility::fTrim(model);
+ stringUtility::fTrim(serial);
+ stringUtility::fTrim(firmware);
+
+ mDrvInfo.model = strdup(model);
+ mDrvInfo.serial = strdup(serial);
+ mDrvInfo.firmware = strdup(firmware);
+}
+
+bool hddVscUnlocker::doAtaSecUnlock() {
+ if(!sendSecUnlockDisableCmd(false)) {
+ utils::debugPrint("sendSecUnlockDisableCmd err: 0x%08X\n", getLastError());
+ return false;
+ }
+
+ if(!identifyDrive()) {
+ utils::debugPrint("identifyDrive err: 0x%08X\n", getLastError());
+ return false;
+ }
+
+ if(mIdentSect.secLocked) {
+ utils::debugPrint("Drive still locked, giving up.\n");
+ return false;
+ }
+
+ if(!sendSecUnlockDisableCmd()) {
+ utils::debugPrint("sendSecUnlockDisableCmd err: 0x%08X\n", getLastError());
+ return false;
+ }
+
+ if(!identifyDrive()) {
+ utils::debugPrint("identifyDrive err: 0x%08X\n", getLastError());
+ return false;
+ }
+
+ if(mIdentSect.secEnabled) {
+ utils::debugPrint("Drive lock still enabled, giving up.\n");
+ return false;
+ }
+
+ mLastError = STATUS_SUCCESS;
+ return true;
+}
+
+bool hddVscUnlocker::identifyDrive() {
+ if(!sendIdentifyCmd()) {
+ utils::debugPrint("sendIdentifyCmd err: 0x%08X\n", getLastError());
+ return false;
+ }
+
+ readDriveData((uint8_t*)&mIdentSect, sizeof(IDENT_SECTOR));
+ parseIdentifySector();
+
+ //utils::hexDumpDebug(&mIdentSect, sizeof(mIdentSect));
+ utils::debugPrint("[identifyDrive] model: \"%s\", serial: \"%s\", fw: \"%s\"\n", mDrvInfo.model, mDrvInfo.serial, mDrvInfo.firmware);
+
+ mLastError = STATUS_SUCCESS;
+ return true;
+}
+
+void hddVscUnlocker::sendDriveRawCmd(IDE_CMD cmd) {
+ // Set the selected drive bit (master/slave)
+ cmd.drv = getDrvRegBits(cmd.drv);
+
+ _outp(mIdePort + 1, cmd.feat);
+ _outp(mIdePort + 2, cmd.nSect);
+ _outp(mIdePort + 3, cmd.sLow);
+ _outp(mIdePort + 4, cmd.sMed);
+ _outp(mIdePort + 5, cmd.sHigh);
+ _outp(mIdePort + 6, cmd.drv);
+ _outp(mIdePort + 7, cmd.cmd); // Sending cmd initiates drive action and raises BSY flag
+}
+
+bool hddVscUnlocker::sendDriveCmd(IDE_CMD cmd, bool altPort, uint32_t timeout) {
+ if(!waitForDrive(altPort, timeout)) {
+ return false;
+ }
+
+ utils::debugPrint("[sendDriveCmd] cmd:\n");
+ utils::hexDumpDebug(&cmd, sizeof(cmd));
+
+ sendDriveRawCmd(cmd);
+
+ if(!waitForDrive(altPort, timeout)) {
+ return false;
+ }
+
+ mLastError = STATUS_SUCCESS;
+ return true;
+}
+
+hddVscUnlocker::IDE_REG hddVscUnlocker::readDriveReg(bool altPort) {
+ IDE_REG reg = { 0, 0, 0, 0, 0, 0, 0 };
+ uint8_t statusReg = altPort ? (0x200 + mIdePort + 6) : (mIdePort + 7);
+
+ reg.err = _inp(mIdePort + 1);
+ reg.nSect = _inp(mIdePort + 2);
+ reg.sLow = _inp(mIdePort + 3);
+ reg.sMed = _inp(mIdePort + 4);
+ reg.sHigh = _inp(mIdePort + 5);
+ reg.drv = _inp(mIdePort + 6);
+ reg.status = _inp(statusReg);
+
+ utils::debugPrint("[readDriveReg] reg:\n");
+ utils::hexDumpDebug(®, sizeof(reg));
+
+ return reg;
+}
+
+bool hddVscUnlocker::readDriveData(uint8_t* buf, uint32_t size) {
+ uint32_t cnt = size / sizeof(uint32_t);
+ uint32_t* data = (uint32_t*)buf;
+
+ if(!waitForDrive()) {
+ return false;
+ }
+
+ uint8_t tmp = 4;
+
+ for (uint32_t i = 0; (i < cnt); i++) {
+ data[i] = _inpd(mIdePort);
+ KeStallExecutionProcessor(500);
+ }
+
+ if(!waitForDrive(false)) {
+ return false;
+ }
+
+ mLastError = STATUS_SUCCESS;
+ return true;
+}
+
+bool hddVscUnlocker::writeDriveData(uint8_t* buf, uint32_t size) {
+ uint32_t cnt = size / sizeof(uint32_t);
+ uint32_t* data = (uint32_t*)buf;
+
+ utils::debugPrint("[writeDriveData] buf:\n");
+ utils::hexDumpDebug(buf, size);
+
+ if(!waitForDrive()) {
+ return false;
+ }
+
+ for (uint32_t i = 0; (i < cnt); i++) {
+ _outpd(mIdePort, data[i]);
+ KeStallExecutionProcessor(500);
+ }
+
+ if(!waitForDrive(false)) {
+ return false;
+ }
+
+ mLastError = STATUS_SUCCESS;
+ return true;
+}
+
+void hddVscUnlocker::resetIdeBusRaw() {
+ uint16_t reg = 0x200 + mIdePort + 6;
+
+ _outp(reg, 0);
+ KeStallExecutionProcessor(50);
+ _outp(reg, 4);
+ KeStallExecutionProcessor(100);
+ _outp(reg, 0);
+ KeStallExecutionProcessor(50);
+}
+
+bool hddVscUnlocker::resetIdeBus() {
+ utils::debugPrint("Resetting IDE bus on port 0x%X...\n", mIdePort);
+
+ if(!waitForDrive()) {
+ return false;
+ }
+
+ resetIdeBusRaw();
+
+ if(!waitForDrive(false)) {
+ return false;
+ }
+
+ mLastError = STATUS_SUCCESS;
+ return true;
+}
+
+bool hddVscUnlocker::isDriveLocked(bool doId) {
+ if(doId && !identifyDrive()) {
+ utils::debugPrint("identifyDrive err: 0x%08X\n", getLastError());
+ return true;
+ }
+
+ utils::debugPrint("[isDriveLocked] secEn: %u, secLock: %u\n", mIdentSect.secEnabled, mIdentSect.secLocked);
+
+ return mIdentSect.secEnabled && mIdentSect.secLocked;
+}
+
+// checkOnly = Check if drive model is supported
+bool hddVscUnlocker::attemptVscUnlock(bool checkOnly) {
+ bool result = false;
+
+ if(!checkOnly && !identifyDrive()) {
+ utils::debugPrint("identifyDrive err: 0x%08X\n", getLastError());
+ return false;
+ }
+
+ if(!checkOnly && !isDriveLocked(false)) {
+ utils::debugPrint("Drive \"%s\" is already unlocked, quitting...\n", mDrvInfo.model);
+ return false;
+ }
+
+ mHasMasterPwd = false;
+ mHasUserPwd = false;
+
+ if(memcmp(mDrvInfo.model, "WDC WD80EB", 10) == 0) {
+ if(checkOnly) return true;
+ result = wdOemUnlock_WDC_WD80EB();
+ } else if(memcmp(mDrvInfo.model, "ST310014A", 9) == 0) {
+ if(checkOnly) return true;
+ result = sgOemUnlock_ST310014A();
+ } else if(memcmp(mDrvInfo.model, "ST310211A", 9) == 0) {
+ if(checkOnly) return true;
+ result = sgOemUnlock_ST310211A();
+ } else if(memcmp(mDrvInfo.model, "WDC ", 4) == 0) {
+ if(checkOnly) return true;
+ result = wdRoylUnlock();
+ } else {
+ mLastError = STATUS_DEVICE_DOES_NOT_EXIST;
+ result = false;
+ }
+
+ return result;
+}
+
+bool hddVscUnlocker::checkVscUnlock() {
+ return attemptVscUnlock(true);
+}
+
+bool hddVscUnlocker::getMasterPwd(uint8_t* buf) {
+ if(mHasMasterPwd) {
+ memcpy(buf, mMasterPwd, ATA_SEC_PWD_SIZE);
+
+ mLastError = STATUS_SUCCESS;
+ return true;
+ }
+
+ mLastError = STATUS_NOT_FOUND;
+ return false;
+}
+
+bool hddVscUnlocker::getUserPwd(uint8_t* buf) {
+ if(mHasUserPwd) {
+ memcpy(buf, mUserPwd, ATA_SEC_PWD_SIZE);
+
+ mLastError = STATUS_SUCCESS;
+ return true;
+ }
+
+ mLastError = STATUS_NOT_FOUND;
+ return false;
+}
+
+hddVscUnlocker::DRIVE_INFO hddVscUnlocker::getDriveInfo() {
+ DRIVE_INFO ret;
+ if(!mDrvInfo.model) identifyDrive();
+ if(mDrvInfo.model) ret.model = strdup(mDrvInfo.model);
+ if(mDrvInfo.serial) ret.serial = strdup(mDrvInfo.serial);
+ if(mDrvInfo.firmware) ret.firmware = strdup(mDrvInfo.firmware);
+ return ret;
+}
+
+bool hddVscUnlocker::sendSecUnlockDisableCmd(bool disable, bool userPwd) {
+ uint8_t* pwd = userPwd ? mUserPwd : mMasterPwd;
+
+ if(!pwd) {
+ return false;
+ }
+
+ uint8_t op = disable ? 0xf6 : 0xf2;
+
+ IDE_CMD cmd = { 0, 0, 0, 0, 0, 0xa0, op };
+ if(!sendDriveCmd(cmd)) {
+ utils::debugPrint("sendDriveCmd err: %08X\n", getLastError());
+ return false;
+ }
+
+ uint8_t buf[512];
+ memset(buf, 0, sizeof(buf));
+ buf[0] = userPwd ? 0 : 1;
+ memcpy(buf+2, pwd, ATA_SEC_PWD_SIZE);
+
+ if(!writeDriveData(buf, sizeof(buf))) {
+ utils::debugPrint("writeDriveData err: %08X\n", getLastError());
+ return false;
+ }
+
+ mLastError = STATUS_SUCCESS;
+ return true;
+}
+
+bool hddVscUnlocker::sendIdentifyCmd() {
+ IDE_CMD cmd = { 0, 0, 0, 0, 0, 0xa0, 0xec };
+ if(!sendDriveCmd(cmd)) {
+ utils::debugPrint("sendDriveCmd err: %08X\n", getLastError());
+ return false;
+ }
+
+ mLastError = STATUS_SUCCESS;
+ return true;
+}
+
+bool hddVscUnlocker::wdVscEnSvcMode() {
+ IDE_CMD cmd = { 0x57, 0x44, 0x43, 0, 0, 0xa0, 0x8a };
+ if(!sendDriveCmd(cmd)) {
+ utils::debugPrint("sendDriveCmd err: %08X\n", getLastError());
+ return false;
+ }
+
+ mLastError = STATUS_SUCCESS;
+ return true;
+}
+
+bool hddVscUnlocker::wdVscReadSecSect(uint8_t numSects) {
+ IDE_CMD cmd = { 0, numSects, 0, 0, 0x0f, 0xe0, 0x21 };
+ if(!sendDriveCmd(cmd)) {
+ utils::debugPrint("sendDriveCmd err: %08X\n", getLastError());
+ return false;
+ }
+
+ mLastError = STATUS_SUCCESS;
+ return true;
+}
+
+bool hddVscUnlocker::sgVscDiagReadByte() {
+ IDE_CMD cmd = { 0, 1, 0, 0, 0, 0xe0, 0xff };
+ if(!sendDriveCmd(cmd, true)) {
+ utils::debugPrint("sendDriveCmd err: %08X\n", getLastError());
+ return false;
+ }
+
+ mLastError = STATUS_SUCCESS;
+ return true;
+}
+
+NTSTATUS hddVscUnlocker::getLastError() {
+ return mLastError;
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/hddVscUnlocker.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/hddVscUnlocker.h
new file mode 100644
index 0000000..c3b0079
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/hddVscUnlocker.h
@@ -0,0 +1,154 @@
+#pragma once
+
+#include "xboxinternals.h"
+
+class hddVscUnlocker {
+public:
+
+ enum IDE_PORT {
+ IDE_PORT_PRIMARY = 0x1f0,
+ IDE_PORT_SECONDARY = 0x170
+ };
+
+ enum IDE_DRIVE {
+ IDE_DRIVE_MASTER = 0,
+ IDE_DRIVE_SLAVE = 1
+ };
+
+ enum ATA_SEC {
+ ATA_SEC_PWD_SIZE = 32
+ };
+
+ enum WD_INFO {
+ WD_INFO_MASTER_PWD_OFFSET = 0x398,
+ WD_INFO_USER_PWD_OFFSET = 0x3b8
+ };
+
+ struct IDE_CMD {
+ uint8_t feat;
+ uint8_t nSect;
+ uint8_t sLow;
+ uint8_t sMed;
+ uint8_t sHigh;
+ uint8_t drv;
+ uint8_t cmd;
+ };
+
+ struct IDE_REG {
+ uint8_t err;
+ uint8_t nSect;
+ uint8_t sLow;
+ uint8_t sMed;
+ uint8_t sHigh;
+ uint8_t drv;
+ uint8_t status;
+ };
+
+ struct DRIVE_INFO {
+ char* model;
+ char* serial;
+ char* firmware;
+ };
+
+ struct IDENT_SECTOR { // Words
+ uint16_t res0[10]; // 0-9
+ char serial[20]; // 10-19
+ uint16_t res10[3]; // 20-22
+ char firmware[8]; // 23-26
+ char model[40]; // 27-46
+ uint16_t res20[13]; // 47-59
+ uint32_t nSect28; // 60-61
+ uint16_t res30[21]; // 62-82
+ uint16_t pad1:10; // 83:0-9
+ uint16_t isLba48:1; // 83:10
+ uint16_t pad10:5; // 83:11-15
+ uint16_t res40[16]; // 84-99
+ uint64_t nSect48; // 100-103
+ uint16_t res50[24]; // 104-127
+ uint16_t secSupported:1; // 128:0
+ uint16_t secEnabled:1; // 128:1
+ uint16_t secLocked:1; // 128:2
+ uint16_t secFrozen:1; // 128:3
+ uint16_t pad20:12; // 83:4-15
+ uint16_t res60[127]; // 129-255
+ };
+
+ hddVscUnlocker();
+ ~hddVscUnlocker();
+
+ NTSTATUS getLastError(); // Returns the last NTSTATUS if an error occured from call to attemptVscUnlock()
+ void setIdePort(IDE_PORT port); // Primary/Secondary port select
+ void setIdeDrive(IDE_DRIVE drv); // Master/Slave drive select
+ bool attemptVscUnlock(bool checkOnly = false); // Primary unlock func
+ bool checkVscUnlock(); // Same as attemptVscUnlock() but just returns if model is supported
+ bool getMasterPwd(uint8_t* buf); // OUT buf, sets master password, returns true if available
+ bool getUserPwd(uint8_t* buf); // OUT buf, sets user password, returns true if available
+ DRIVE_INFO getDriveInfo(); // Returns model/serial/fw info
+
+protected:
+ IDE_REG readDriveReg(bool altPort = false);
+ bool sendDriveCmd(IDE_CMD cmd, bool altPort = false, uint32_t timeout = 2000);
+ void sendDriveRawCmd(IDE_CMD cmd);
+ bool readDriveData(uint8_t* buf, uint32_t size);
+ bool writeDriveData(uint8_t* buf, uint32_t size);
+ bool waitForDrive(bool altPort = true, uint32_t timeout = 2000);
+ uint8_t getDrvRegBits(uint8_t drvReg);
+ bool identifyDrive();
+ void freeIdentifyData();
+ void parseIdentifySector();
+ bool isDriveLocked(bool doId = true);
+ bool sendIdentifyCmd();
+ bool resetIdeBus();
+ void resetIdeBusRaw();
+ bool doAtaSecUnlock();
+ bool spinWait(bool altPort = false, uint32_t timeout = 10000);
+ void debug(char* str);
+ void debugArr(uint32_t val);
+ bool sendSecUnlockDisableCmd(bool disable = true, bool userPwd = true);
+
+ // WD specific functions
+ bool wdUnlockMod42();
+ bool wdOemUnlock_WDC_WD80EB();
+ bool wdVscEnSvcMode();
+ bool wdVscReadSecSect(uint8_t numSects = 1);
+ void wdExtractAndSetPwds(uint8_t* buf);
+
+ // Seagate specific functions
+ bool sgOemUnlock_ST310014A();
+ bool sgOemUnlock_ST310211A();
+ bool sgVscEnableDiagMode();
+ bool sgVscDiagSendCmd(char* cmd);
+ bool sgVscDiagRead(char* buf, uint32_t expLen = 0, uint32_t timeout = 10000);
+ uint8_t sgVscDiagReadWait(uint8_t* status, uint32_t timeout = 10000);
+ bool sgVscDiagSendByte(uint8_t cmdByte);
+ bool sgVscDiagReadByte();
+ bool sgVscDiagExecCmd(char* cmd, char* buffer, uint32_t expLen = 0, uint32_t timeout = 10000);
+ void sgConvertHexPwdStr(uint32_t offset, uint32_t size, char* buf, uint8_t* out);
+ void sgExtractAndSetPwds(char* buf, uint32_t mstrOffset, uint32_t userOffset);
+
+ // WD ROYL specific functions
+ bool wdRoylUnlock();
+ bool wdRoylVscEnDis(bool disable = false);
+ bool wdRoylSeekMod02();
+ bool wdRoylRstDrv();
+ bool wdRoylReadMod02(uint8_t numSects = 1);
+ void wdRoylExtractAndSetPwds(uint8_t* buf, uint32_t idx);
+
+ IDE_PORT mIdePort;
+ IDE_DRIVE mIdeDrv;
+ NTSTATUS mLastError;
+ uint8_t mMasterPwd[ATA_SEC_PWD_SIZE];
+ uint8_t mUserPwd[ATA_SEC_PWD_SIZE];
+ bool mHasMasterPwd;
+ bool mHasUserPwd;
+ DRIVE_INFO mDrvInfo;
+ IDENT_SECTOR mIdentSect;
+ char* debugStr;
+ uint32_t debugStrOffset;
+ uint32_t mDebugArr[4096];
+ uint32_t debugArrSize;
+ uint32_t debugArrOff;
+
+private:
+
+};
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/hdmiDevice.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/hdmiDevice.cpp
new file mode 100644
index 0000000..fc497dd
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/hdmiDevice.cpp
@@ -0,0 +1,44 @@
+#include "hdmiDevice.h"
+#include "xboxinternals.h"
+#include "versioning.h"
+
+NTSTATUS hdmiDevice::address1WriteByte(UCHAR cmd, UCHAR data)
+{
+ NTSTATUS status;
+ status = HalWriteSMBusByte(I2C_HDMI_ADDRESS1, cmd, data);
+ return status;
+}
+
+NTSTATUS hdmiDevice::address1ReadByte(UCHAR cmd, UCHAR* data)
+{
+ NTSTATUS status;
+ ULONG temp;
+ status = HalReadSMBusByte(I2C_HDMI_ADDRESS1, cmd, &temp);
+ if (data != NULL)
+ {
+ *data = (UCHAR)temp;
+ }
+ return status;
+}
+
+bool hdmiDevice::detectDevice()
+{
+ NTSTATUS status;
+ status = address1WriteByte(0, 0);
+ status |= address1ReadByte(0, NULL);
+ return status == STATUS_SUCCESS;
+}
+
+semver hdmiDevice::getVersion()
+{
+ semver version;
+ memset(&version, 0, sizeof(version));
+ address1ReadByte(I2C_HDMI_VERSION1, &version.major);
+ address1ReadByte(I2C_HDMI_VERSION2, &version.minor);
+ address1ReadByte(I2C_HDMI_VERSION3, &version.patch);
+ if (version.major == 0 && version.minor == 0 && version.patch == 0)
+ {
+ version.major = 1;
+ }
+ return version;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/hdmiDevice.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/hdmiDevice.h
new file mode 100644
index 0000000..3c5469c
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/hdmiDevice.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "xboxinternals.h"
+#include "versioning.h"
+
+#define I2C_HDMI_ADDRESS1 0x88
+#define I2C_HDMI_ADDRESS2 0x86
+
+#define I2C_HDMI_VERSION1 0x57
+#define I2C_HDMI_VERSION2 0x58
+#define I2C_HDMI_VERSION3 0x59
+
+class hdmiDevice
+{
+public:
+ static NTSTATUS address1WriteByte(UCHAR cmd, UCHAR data);
+ static NTSTATUS address1ReadByte(UCHAR cmd, UCHAR* data);
+ static bool detectDevice();
+ static semver getVersion();
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/hdmiSettingsManager.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/hdmiSettingsManager.cpp
new file mode 100644
index 0000000..2dcd6a2
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/hdmiSettingsManager.cpp
@@ -0,0 +1,95 @@
+#include "hdmiSettingsManager.h"
+#include "versioning.h"
+#include "fileSystem.h"
+#include "stringUtility.h"
+
+namespace
+{
+ hdmiSettingsState mSettings;
+}
+
+semver hdmiSettingsManager::getSoftwareVersion()
+{
+ semver appVersion;
+ memset(&appVersion, 0, sizeof(appVersion));
+ appVersion.major = 2;
+ appVersion.minor = 2;
+ appVersion.patch = 2;
+ return appVersion;
+}
+
+semver hdmiSettingsManager::getFirmwareVersion()
+{
+ semver appVersion;
+ memset(&appVersion, 0, sizeof(appVersion));
+ appVersion.major = 2;
+ appVersion.minor = 2;
+ appVersion.patch = 2;
+ return appVersion;
+}
+
+char* hdmiSettingsManager::getVersionSting(semver version)
+{
+ return stringUtility::formatString("%i.%i.%i", version.major, version.minor, version.patch);
+}
+
+void hdmiSettingsManager::initSettings()
+{
+ memset(&mSettings, 0, sizeof(mSettings));
+ mSettings.firmwareVersion = getSoftwareVersion();
+ mSettings.softwareVersion = getFirmwareVersion();
+ mSettings.autoVideoBlank = 1;
+ mSettings.autoRegionSwitch = 1;
+}
+
+void hdmiSettingsManager::loadSettings()
+{
+ initSettings();
+
+ uint32_t fileHandle;
+ if (fileSystem::fileOpen("HDD0-C:\\ElpisHD\\settings.bin", fileSystem::FileModeRead, fileHandle))
+ {
+ uint32_t fileSize;
+ if (fileSystem::fileSize(fileHandle, fileSize))
+ {
+ if (fileSize != sizeof(mSettings))
+ {
+ initSettings();
+ }
+ else
+ {
+ uint32_t bytesRead;
+ if (fileSystem::fileRead(fileHandle, (char*)&mSettings, fileSize, bytesRead) && bytesRead == fileSize)
+ {
+ if (versioning::compareVersion(mSettings.softwareVersion, getSoftwareVersion()) != 0)
+ {
+ initSettings();
+ }
+ if (versioning::compareVersion(mSettings.firmwareVersion, getFirmwareVersion()) != 0)
+ {
+ initSettings();
+ }
+ }
+ else
+ {
+ initSettings();
+ }
+ }
+ }
+ fileSystem::fileClose(fileHandle);
+ }
+}
+
+void hdmiSettingsManager::saveSettings()
+{
+ if (fileSystem::directoryCreate("HDD0-C:\\ElpisHD") == true)
+ {
+ uint32_t bytesWritten;
+ fileSystem::fileWrite("HDD0-C:\\ElpisHD\\settings.bin", (char*)&mSettings, sizeof(mSettings), bytesWritten);
+ }
+}
+
+hdmiSettingsState* hdmiSettingsManager::getSettings()
+{
+ return &mSettings;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/hdmiSettingsManager.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/hdmiSettingsManager.h
new file mode 100644
index 0000000..db685ae
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/hdmiSettingsManager.h
@@ -0,0 +1,50 @@
+#pragma once
+
+#include "xboxinternals.h"
+#include "versioning.h"
+
+#pragma pack(push,1)
+typedef struct hdmiSettingsState
+{
+ semver firmwareVersion;
+ semver softwareVersion;
+ uint32_t checksum;
+ uint8_t outputResolution;
+ uint8_t widescreen;
+ uint8_t colorspace;
+ uint8_t interpolation;
+ uint8_t interpolationScaleX;
+ uint8_t interpolationScaleY;
+ uint8_t interpolationWeightX;
+ uint8_t interpolationWeightY;
+ uint8_t autoVideoBlank;
+ uint8_t autoRegionSwitch;
+ uint8_t prescaleFixDisable;
+ uint8_t disable480p169;
+ uint8_t aviInfoOverride;
+ uint8_t pictureAspectRatio;
+ uint8_t activeFormatAspectRatio;
+ uint8_t activeFormatStatus;
+ uint8_t barInfoPresent;
+ uint16_t barInfoEtb;
+ uint16_t barInfoEbb;
+ uint16_t barInfoElb;
+ uint16_t barInfoSrb;
+ uint8_t pixelClockDelayOverride;
+ uint8_t pixelClockDelay;
+ uint8_t pixelClockDelayNeg;
+ uint8_t padding[212];
+} hdmiSettingsState;
+#pragma pack(pop)
+
+class hdmiSettingsManager
+{
+public:
+ static semver getSoftwareVersion();
+ static semver getFirmwareVersion();
+ static char* getVersionSting(semver version);
+ static void initSettings();
+ static void loadSettings();
+ static void saveSettings();
+ static hdmiSettingsState* getSettings();
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/httpServer.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/httpServer.cpp
new file mode 100644
index 0000000..6b27b78
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/httpServer.cpp
@@ -0,0 +1,617 @@
+#include "httpServer.h"
+#include "fileSystem.h"
+#include "stringUtility.h"
+#include "socketUtility.h"
+#include "utils.h"
+
+#include
+#include
+#include
+
+namespace {
+
+ SOCKADDR_IN mConnectionAddress;
+ uint64_t mListenSocket;
+ pointerVector* mClientSockets = NULL;
+ int mPortIn;
+ int m_iXferPort;
+ uint64_t passive_socket;
+ bool mStopRequested;
+ HANDLE mListenThreadHandle;
+
+ HttpOnGetCallback mOnGetCallback;
+ HttpOnPostCallback mOnPostCallback;
+ HttpOnResponseSentCallback mOnResponseSentCallback;
+}
+
+bool WINAPI httpServer::listenThread(LPVOID lParam)
+{
+ while (mStopRequested == false)
+ {
+ refresh();
+ Sleep(50);
+ }
+
+ if (mListenSocket != INVALID_SOCKET)
+ {
+ int result = closesocket((SOCKET)mListenSocket);
+ if (result != 0)
+ {
+ utils::debugPrint("Error: Close socket failed: %i\n", WSAGetLastError());
+ }
+ mListenSocket = INVALID_SOCKET;
+ }
+
+ for (unsigned int i = 0; i < mClientSockets->count(); ++i)
+ {
+ HttpClientSocket* clientSocket = mClientSockets->get(i);
+
+ int result = socketUtility::endBrokerSocket(clientSocket->socket);
+ if (result == EXIT_FAILURE)
+ {
+ utils::debugPrint("Error: Close socket failed: %i\n", WSAGetLastError());
+ }
+ clientSocket->socket = INVALID_SOCKET;
+ }
+
+ return false;
+}
+
+void httpServer::registerOnGetCallback(HttpOnGetCallback callback)
+{
+ mOnGetCallback = callback;
+}
+
+void httpServer::removeOnGetCallback()
+{
+ mOnGetCallback = NULL;
+}
+
+void httpServer::registerOnPostCallback(HttpOnPostCallback callback)
+{
+ mOnPostCallback = callback;
+}
+
+void httpServer::removeOnPostCallback()
+{
+ mOnPostCallback = NULL;
+}
+
+void httpServer::registerOnResponseSentCallback(HttpOnResponseSentCallback callback)
+{
+ mOnResponseSentCallback = callback;
+}
+
+void httpServer::removeOnResponseSentCallback()
+{
+ mOnResponseSentCallback = NULL;
+}
+
+utils::dataContainer* httpServer::generateResponse(const int errorCode, const char* message)
+{
+ utils::debugPrint("Response: %s\n", message);
+ utils::dataContainer* dataContainer = new utils::dataContainer();
+ dataContainer->data = stringUtility::formatString("HTTP/1.1 %i %s\r\nContent-Length: 0\r\n\r\n", errorCode, message);
+ dataContainer->size = strlen(dataContainer->data);
+ return dataContainer;
+}
+
+utils::dataContainer* httpServer::redirect()
+{
+ utils::debugPrint("Redirect: index.html\n");
+ utils::dataContainer* dataContainer = new utils::dataContainer();
+ dataContainer->data = strdup("HTTP/1.1 301 Moved Permanently\r\nLocation: /index.html\r\n\r\n");
+ dataContainer->size = strlen(dataContainer->data);
+ return dataContainer;
+}
+
+void httpServer::init()
+{
+ mStopRequested = false;
+
+ mListenThreadHandle = NULL;
+
+ mPortIn = 80;
+ mClientSockets = new pointerVector(true);
+
+ utils::debugPrint("Socket server init on port %i\n", mPortIn);
+
+ memset(&mConnectionAddress, 0, sizeof(SOCKADDR_IN));
+ mConnectionAddress.sin_family = AF_INET;
+ mConnectionAddress.sin_addr.s_addr = htonl( INADDR_ANY );
+ mConnectionAddress.sin_port = htons(mPortIn);
+
+ mListenSocket = socketUtility::createSocket(mConnectionAddress, true);
+ if (mListenSocket == NULL)
+ {
+ return;
+ }
+
+ mListenThreadHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)listenThread, 0, 0, NULL);
+ if (mListenThreadHandle) {
+ SetThreadPriority(mListenThreadHandle, 2);
+ }
+}
+
+void httpServer::close()
+{
+ mStopRequested = true;
+ WaitForSingleObject(mListenThreadHandle, INFINITE);
+ CloseHandle(mListenThreadHandle);
+}
+
+RequestBody* httpServer::getRequestBody(utils::dataContainer* input, uint32_t& index)
+{
+ char* request = NULL;
+ char* requestVerb = NULL;
+ char* requestPath = NULL;
+ char* requestQuery = NULL;
+ pointerVector* requestHeaders = NULL;
+ pointerVector* requestParts = NULL;
+ pointerVector* queryParts = NULL;
+ RequestBody* result = NULL;
+
+ request = getLine(input, index);
+ utils::debugPrint("Request: %s\n", request);
+
+ requestParts = stringUtility::split(request, " ", false);
+ if (requestParts->count() != 3)
+ {
+ utils::debugPrint("Error: Unexpected request format");
+ goto cleanup;
+ }
+
+ requestVerb = strdup(requestParts->get(0));
+ requestPath = stringUtility::replace(requestParts->get(1), "/", "\\");
+ requestQuery = strdup("");
+
+ queryParts = stringUtility::split(requestPath, "?", false);
+ if (queryParts->count() == 2)
+ {
+ free(requestPath);
+ requestPath = strdup(queryParts->get(0));
+ free(requestQuery);
+ requestQuery = strdup(queryParts->get(1));
+ }
+
+ utils::debugPrint("Verb: %s\n", requestVerb);
+ utils::debugPrint("Path: %s\n", requestPath);
+ utils::debugPrint("Query: %s\n", requestQuery);
+
+ result = new RequestBody();
+ result->verb = strdup(requestVerb);
+ result->path = strdup(requestPath);
+ result->query = strdup(requestQuery);
+ result->headers = getHeaders(input, index);
+
+cleanup:
+
+ free(request);
+ free(requestVerb);
+ free(requestPath);
+ free(requestQuery);
+ delete(requestHeaders);
+ delete(requestParts);
+ delete(queryParts);
+ return result;
+}
+
+void httpServer::refresh()
+{
+ const int result = socketUtility::getReadStatus(mListenSocket);
+ if (result == SOCKET_ERROR)
+ {
+ utils::debugPrint("Error: Socket status failed: %i\n", WSAGetLastError());
+ return;
+ }
+
+ //utils::debugPrint("read status = %i\n", result);
+
+ if (result == 1)
+ {
+ int client_size = sizeof(sockaddr_in);
+
+ HttpClientSocket* clientSocket = new HttpClientSocket();
+
+ clientSocket->totalSent = 0;
+ clientSocket->totalReceived = 0;
+ clientSocket->socket = accept((SOCKET)mListenSocket, (struct sockaddr*)&clientSocket->address, &client_size);
+
+ if (clientSocket->socket == INVALID_SOCKET)
+ {
+ utils::debugPrint("Error: Socket accept failed: %i\n", WSAGetLastError());
+ return;
+ }
+ mClientSockets->add(clientSocket);
+ utils::debugPrint("Connected client: %i\n", (int)mClientSockets->count());
+ }
+
+ // Read incoming socket data
+
+ for (unsigned int i = 0; i < mClientSockets->count(); ++i)
+ {
+ HttpClientSocket* current_client = mClientSockets->get(i);
+
+ const int status = socketUtility::getReadStatus(current_client->socket);
+ if (status == SOCKET_ERROR)
+ {
+ const int result = socketUtility::endBrokerSocket(current_client->socket);
+ if (result == EXIT_FAILURE)
+ {
+ utils::debugPrint("Error: Socket end failed: %i\n", WSAGetLastError());
+ }
+ current_client->socket = INVALID_SOCKET;
+ continue;
+ }
+
+ if (status == 1)
+ {
+ const int available_data_size = socketUtility::getAvailableDataSize(current_client->socket);
+ if (available_data_size > 0)
+ {
+ if (current_client->requestBody == NULL)
+ {
+ utils::debugPrint("Body size = %lu\n", available_data_size);
+
+ utils::dataContainer* dataContainer = new utils::dataContainer(available_data_size);
+
+ const int bytes_received = socketUtility::receiveSocketData(current_client->socket, dataContainer->data, available_data_size);
+ if (bytes_received == -1)
+ {
+ continue;
+ }
+
+ uint32_t index = 0;
+ current_client->requestBody = getRequestBody(dataContainer, index);
+
+ utils::debugPrint("Body size vs index) = %lu, index = %lu, diff = %lu\n", available_data_size, index, available_data_size - index);
+
+ pointerVector* contentLengthParts = getHeaderValueParts(current_client->requestBody->headers, "Content-Length:");
+ if (contentLengthParts->count() == 1)
+ {
+ current_client->contentLength = stringUtility::toInt(contentLengthParts->get(0));
+ }
+
+ if (current_client->contentLength > 0)
+ {
+ uint32_t bytesToCopy = available_data_size - index;
+ current_client->dataIn = new utils::dataContainer(dataContainer->data + index, current_client->contentLength, bytesToCopy);
+ current_client->totalReceived = bytesToCopy;
+ }
+
+ delete(contentLengthParts);
+ }
+ else
+ {
+ uint32_t used = current_client->totalReceived;
+ const int bytes_received = socketUtility::receiveSocketData(current_client->socket, (char*)(¤t_client->dataIn->data[used]), available_data_size);
+ if (bytes_received == -1)
+ {
+ continue;
+ }
+ current_client->totalReceived+=bytes_received;
+ utils::debugPrint("Total Recieved %lu\n", current_client->totalReceived);
+ }
+ }
+ }
+ }
+
+ // Process outgoing socket data
+
+ for (unsigned int i = 0; i < mClientSockets->count(); ++i)
+ {
+ HttpClientSocket* current_client = mClientSockets->get(i);
+
+ if (current_client->socket == INVALID_SOCKET)
+ {
+ continue;
+ }
+
+ if (current_client->requestBody != NULL && current_client->totalReceived == current_client->contentLength)
+ {
+ if (stringUtility::equals(current_client->requestBody->verb, "GET", false))
+ {
+ current_client->dataOut = processGet(current_client->requestBody);
+ }
+ else if (stringUtility::equals(current_client->requestBody->verb, "POST", false))
+ {
+ current_client->dataOut = processPost(current_client->requestBody, current_client->dataIn);
+ }
+ else
+ {
+ char* errorMessage = stringUtility::formatString("Unsupported Verb %s", current_client->requestBody->verb);
+ current_client->dataOut = generateResponse(405, errorMessage);
+ free(errorMessage);
+ }
+
+ const uint32_t total = current_client->dataOut->size;
+ uint32_t remaining = current_client->dataOut->size - current_client->totalSent;
+ while (remaining > 0)
+ {
+ const int bytes_sent = socketUtility::sendSocketData(current_client->socket, (const char*)¤t_client->dataOut->data[current_client->totalSent], remaining);
+ if (bytes_sent == -1)
+ {
+ int socketError = WSAGetLastError();
+ if (socketError == WSAWOULDBLOCK)
+ {
+ utils::debugPrint("Socket busy, retrying...");
+ Sleep(50);
+ continue;
+ }
+
+ utils::debugPrint("Error: Client %i send failed: %i\n", (int)i, WSAGetLastError());
+ const int result = socketUtility::endBrokerSocket(current_client->socket);
+ if (result == EXIT_FAILURE)
+ {
+ utils::debugPrint("Error: Socket end failed: %i\n", WSAGetLastError());
+ }
+ current_client->socket = INVALID_SOCKET;
+ break;
+ }
+ current_client->totalSent += bytes_sent;
+ remaining = current_client->dataOut->size - current_client->totalSent;
+ utils::debugPrint("Send progress %i of %i\n", current_client->totalSent, total);
+ }
+
+ const int result = socketUtility::endBrokerSocket(current_client->socket);
+ if (result == EXIT_FAILURE)
+ {
+ utils::debugPrint("Error: Socket end failed: %i\n", WSAGetLastError());
+ }
+ current_client->socket = INVALID_SOCKET;
+
+ if (mOnResponseSentCallback != NULL)
+ {
+ mOnResponseSentCallback();
+ }
+ }
+ }
+
+ // Remove finished sockets
+
+ if (mClientSockets->count() > 0)
+ {
+ for (size_t i = mClientSockets->count(); i-- > 0;)
+ {
+ HttpClientSocket* current_client = mClientSockets->get(i);
+ if (current_client->socket == INVALID_SOCKET)
+ {
+ mClientSockets->remove(i);
+ }
+ }
+ }
+}
+
+char* httpServer::getLine(utils::dataContainer* input, uint32_t& index)
+{
+ uint32_t length = 0;
+ for (uint32_t i = index; i < input->size; i++)
+ {
+ if (input->data[i] == '\r')
+ {
+ continue;
+ }
+ if (input->data[i] == '\n')
+ {
+ break;
+ }
+ length++;
+ }
+
+ char* result = (char*)malloc(length + 1);
+
+ uint32_t offset = 0;
+ for (uint32_t i = index; i < input->size; i++)
+ {
+ index = i + 1;
+ if (input->data[i] == '\r')
+ {
+ continue;
+ }
+ if (input->data[i] == '\n')
+ {
+ break;
+ }
+ result[offset] = input->data[i];
+ offset++;
+ }
+
+ result[length] = 0;
+ return result;
+}
+
+pointerVector* httpServer::getHeaders(utils::dataContainer* input, uint32_t& index)
+{
+ pointerVector* headers = new pointerVector(false);
+ while (index < input->size)
+ {
+ char* line = getLine(input, index);
+ if (strlen(line) == 0)
+ {
+ break;
+ }
+ utils::debugPrint("Header: %s\n", line);
+ headers->add(line);
+ }
+ return headers;
+}
+
+pointerVector* httpServer::getHeaderValueParts(pointerVector* headers, const char* header)
+{
+ pointerVector* result = new pointerVector(false);
+
+ for (uint32_t i = 0; i < headers->count(); i++)
+ {
+ if (stringUtility::startsWith(headers->get(i), header, true) == false)
+ {
+ continue;
+ }
+
+ char* temp = stringUtility::substr(headers->get(i), strlen(header), -1);
+ char* headerValue = stringUtility::trim(temp, ' ');
+
+ pointerVector* headerValueParts = stringUtility::split(headerValue, ";", true);
+
+ for (uint32_t j = 0; j < headerValueParts->count(); j++)
+ {
+ utils::debugPrint("HeaderValuePart for %s %s\n", header, headerValueParts->get(j));
+ result->add(strdup(headerValueParts->get(j)));
+ }
+
+ free(temp);
+ free(headerValue);
+ delete(headerValueParts);
+
+ return result;
+ }
+
+ return result;
+}
+
+utils::dataContainer* httpServer::processGet(RequestBody* requestBody)
+{
+ utils::dataContainer* getResponse = NULL;
+ char* extension = NULL;
+ char* mimeType = NULL;
+ char* contentLength = NULL;
+ char* header = NULL;
+
+ if (mOnGetCallback != NULL)
+ {
+ getResponse = mOnGetCallback(requestBody->path, requestBody->query);
+ }
+ else
+ {
+ getResponse = generateResponse(404, "Not found");
+ }
+
+ free(extension);
+ free(mimeType);
+ free(contentLength);
+ free(header);
+ return getResponse;
+}
+
+utils::dataContainer* httpServer::processPost(RequestBody* requestBody, utils::dataContainer* input)
+{
+ utils::dataContainer* postResponse = NULL;
+ pointerVector* contentTypeParts = NULL;
+ pointerVector* contentLengthParts = NULL;
+ pointerVector* formParts = NULL;
+ char* boundary = NULL;
+ char* boundaryDelimiter = NULL;
+
+ contentTypeParts = getHeaderValueParts(requestBody->headers, "Content-Type:");
+ if (contentTypeParts->count() != 2)
+ {
+ postResponse = generateResponse(500, "Unexpected Content-Type format");
+ goto cleanup;
+ }
+
+ contentLengthParts = getHeaderValueParts(requestBody->headers, "Content-Length:");
+ if (contentLengthParts->count() != 1)
+ {
+ postResponse = generateResponse(500, "Unexpected Content-Length format");
+ goto cleanup;
+ }
+
+ uint32_t contentLength = stringUtility::toInt(contentLengthParts->get(0));
+
+ if (stringUtility::equals(contentTypeParts->get(0), "multipart/form-data", false) == false)
+ {
+ postResponse = generateResponse(500, "Invalid Content-Type, expected 'multipart/form-data'");
+ goto cleanup;
+ }
+
+ boundary = stringUtility::splitAfter(contentTypeParts->get(1), "boundary=");
+ if (strlen(boundary) == 0)
+ {
+ postResponse = generateResponse(500, "Unexpected boundary format");
+ goto cleanup;
+ }
+
+ boundaryDelimiter = stringUtility::formatString("--%s", boundary);
+
+ formParts = new pointerVector(true);
+
+ uint32_t index = stringUtility::find(input->data, input->size, 0, boundaryDelimiter, false);
+ while (index != StringNotFouund)
+ {
+ index += strlen(boundaryDelimiter) + 2;
+ pointerVector* formHeaders = getHeaders(input, index);
+
+ uint32_t startPos = index;
+ index = stringUtility::find(input->data, input->size, index, boundaryDelimiter, false);
+ if (index == StringNotFouund)
+ {
+ delete(formHeaders);
+ break;
+ }
+
+ uint32_t bodyLength = (index - startPos) - 2;
+ utils::dataContainer* formData = new utils::dataContainer(input->data + startPos, bodyLength, bodyLength);
+
+ FormPart* formPart = new FormPart(formHeaders, formData);
+ formParts->add(formPart);
+ }
+
+ for (int i = 0; i < (int)formParts->count(); i++)
+ {
+ FormPart* part = formParts->get(i);
+ utils::debugPrint("Form part length = %lu\n", part->body->size);
+ utils::debugPrint("Form part text = %s\n", part->body->data);
+ }
+
+ if (mOnPostCallback != NULL)
+ {
+ postResponse = mOnPostCallback(requestBody->path, requestBody->query, formParts);
+ goto cleanup;
+ }
+ else
+ {
+ postResponse = generateResponse(404, "Not found");
+ goto cleanup;
+ }
+
+cleanup:
+ delete(contentTypeParts);
+ delete(contentLengthParts);
+ delete(formParts);
+ free(boundary);
+ free(boundaryDelimiter);
+ return postResponse;
+}
+
+char* httpServer::getMimeType(const char* extension)
+{
+ char* result = NULL;
+
+ char* lowerExtension = stringUtility::lowerCase(extension);
+
+ if (strcmp(lowerExtension, ".html") == 0) {
+ result = strdup("text/html; charset=utf-8");
+ } else if (strcmp(lowerExtension, ".gif") == 0) {
+ result = strdup("image/gif");
+ } else if (strcmp(lowerExtension, ".jpg") == 0) {
+ result = strdup("image/jpeg");
+ } else if (strcmp(lowerExtension, ".png") == 0) {
+ result = strdup("image/png");
+ } else if (strcmp(lowerExtension, ".svg") == 0) {
+ result = strdup("image/svg+xml");
+ } else if (strcmp(lowerExtension, ".ico") == 0) {
+ result = strdup("image/vnd.microsoft.icon");
+ } else if (strcmp(lowerExtension, ".css") == 0) {
+ result = strdup("text/css; charset=utf-8");
+ } else if (strcmp(lowerExtension, ".txt") == 0) {
+ result = strdup("text/plain; charset=utf-8");
+ } else if (strcmp(lowerExtension, ".js") == 0) {
+ result = strdup("text/javascript; charset=utf-8");
+ } else if (strcmp(lowerExtension, ".json") == 0) {
+ result = strdup("application/json; charset=utf-8");
+ } else {
+ result = strdup("application/octet-stream");
+ }
+
+ free(lowerExtension);
+ return result;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/httpServer.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/httpServer.h
new file mode 100644
index 0000000..32ad0b4
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/httpServer.h
@@ -0,0 +1,93 @@
+#pragma once
+
+#include "xboxinternals.h"
+#include "pointerVector.h"
+#include "utils.h"
+#include
+#include
+#include
+
+typedef struct RequestBody {
+ char* verb;
+ char* path;
+ char* query;
+ pointerVector* headers;
+} RequestBody;
+
+typedef struct FormPart {
+
+ pointerVector* headers;
+ utils::dataContainer* body;
+
+ FormPart() : headers(NULL), body(NULL) {}
+
+ FormPart(pointerVector* headers, utils::dataContainer* body) : headers(headers), body(body) {}
+
+ ~FormPart()
+ {
+ delete(this->headers);
+ delete(this->body);
+ }
+
+} FormPart;
+
+typedef struct HttpClientSocket {
+
+ uint64_t socket;
+ SOCKADDR address;
+ RequestBody* requestBody;
+ uint32_t contentLength;
+ utils::dataContainer* dataIn;
+ int totalReceived;
+ utils::dataContainer* dataOut;
+ int totalSent;
+
+ HttpClientSocket()
+ {
+ socket = 0;
+ memset(&address, 0, sizeof(address));
+ requestBody = NULL;
+ contentLength = 0;
+ dataIn = NULL;
+ totalReceived = 0;
+ dataOut = NULL;
+ totalSent = 0;
+ }
+
+ ~HttpClientSocket()
+ {
+ delete(this->requestBody);
+ delete(this->dataIn);
+ delete(this->dataOut);
+ }
+
+} HttpClientSocket;
+
+typedef utils::dataContainer* (*HttpOnGetCallback)(const char* path, const char* query);
+typedef utils::dataContainer* (*HttpOnPostCallback)(const char* path, const char* query, pointerVector* formParts);
+typedef void (*HttpOnResponseSentCallback)();
+
+class httpServer
+{
+public:
+ static utils::dataContainer* generateResponse(const int errorCode, const char* message);
+ static utils::dataContainer* redirect();
+ static void init();
+ static void close();
+ static void registerOnGetCallback(HttpOnGetCallback callback);
+ static void removeOnGetCallback();
+ static void registerOnPostCallback(HttpOnPostCallback callback);
+ static void removeOnPostCallback();
+ static void registerOnResponseSentCallback(HttpOnResponseSentCallback callback);
+ static void removeOnResponseSentCallback();
+ static char* getMimeType(const char* extension);
+private:
+ static bool WINAPI listenThread(LPVOID lParam);
+ static RequestBody* getRequestBody(utils::dataContainer* input, uint32_t& index);
+ static void refresh();
+ static char* getLine(utils::dataContainer* input, uint32_t& index);
+ static pointerVector* getHeaders(utils::dataContainer* input, uint32_t& index);
+ static pointerVector* getHeaderValueParts(pointerVector* headers, const char* header);
+ static utils::dataContainer* processGet(RequestBody* requestBody);
+ static utils::dataContainer* processPost(RequestBody* requestBody, utils::dataContainer* input);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/inputManager.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/inputManager.cpp
new file mode 100644
index 0000000..ad4f6fb
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/inputManager.cpp
@@ -0,0 +1,373 @@
+#include "inputManager.h"
+#include "audioPlayer.h"
+#include "stringUtility.h"
+
+namespace
+{
+ bool mInitialized = false;
+ HANDLE mControllerHandles[XGetPortCount()];
+ CHAR mMemoryUnityHandles[XGetPortCount() * 2];
+ JoystickButtonStates mControllerStatesPrevious[XGetPortCount()];
+ JoystickButtonStates mControllerStatesCurrent[XGetPortCount()];
+}
+
+void inputManager::processController()
+{
+ if (mInitialized == false)
+ {
+ mInitialized = true;
+ XInitDevices(0, 0);
+ for (int i = 0; i < XGetPortCount(); i++)
+ {
+ mControllerHandles[i] = 0;
+ memset(&mControllerStatesPrevious[i], 0, sizeof(JoystickButtonStates));
+ memset(&mControllerStatesCurrent[i], 0, sizeof(JoystickButtonStates));
+ }
+ for (int i = 0; i < XGetPortCount() * 2; i++)
+ {
+ mMemoryUnityHandles[i] = 0;
+ }
+ }
+
+ DWORD insertions = 0;
+ DWORD removals = 0;
+ if (XGetDeviceChanges(XDEVICE_TYPE_GAMEPAD, &insertions, &removals) == TRUE)
+ {
+ for (int i = 0; i < XGetPortCount(); i++)
+ {
+ if ((insertions & 1) == 1)
+ {
+ mControllerHandles[i] = XInputOpen(XDEVICE_TYPE_GAMEPAD, i, XDEVICE_NO_SLOT, NULL);
+ }
+ if ((removals & 1) == 1)
+ {
+ XInputClose(mControllerHandles[i]);
+ mControllerHandles[i] = NULL;
+ }
+ insertions = insertions >> 1;
+ removals = removals >> 1;
+ }
+ }
+
+ if(XGetDeviceChanges(XDEVICE_TYPE_MEMORY_UNIT, &insertions, &removals) == TRUE)
+ {
+ for (uint32_t iPort = 0; iPort < XGetPortCount(); iPort++)
+ {
+ for (uint32_t iSlot = 0; iSlot < 2; iSlot++ )
+ {
+ uint32_t mask = iPort + (iSlot ? 16 : 0);
+ mask = 1 << mask;
+
+ uint32_t index = (iPort * 2) + iSlot;
+ if ((mask & removals) != 0 && mMemoryUnityHandles[index] != 0)
+ {
+ char* mountPoint = stringUtility::formatString("\\??\\%c:", 'H' + index);
+ STRING sMountPoint = {(USHORT)strlen(mountPoint), (USHORT)strlen(mountPoint) + 1, mountPoint};
+
+ DEVICE_OBJECT* device = MU_GetExistingDeviceObject(iPort, iSlot);
+ IoDismountVolume(device);
+
+ IoDeleteSymbolicLink(&sMountPoint);
+ free(mountPoint);
+ MU_CloseDeviceObject(iPort, iSlot);
+ mMemoryUnityHandles[index] = 0;
+ }
+
+ if ((mask & insertions) != 0 && mMemoryUnityHandles[index] == 0)
+ {
+ char szDeviceName[64];
+ STRING DeviceName;
+ DeviceName.Length = 0;
+ DeviceName.MaximumLength = sizeof(szDeviceName) / sizeof(CHAR) - 2;
+ DeviceName.Buffer = szDeviceName;
+ if (MU_CreateDeviceObject(iPort, iSlot, &DeviceName) >= 0)
+ {
+ char* mountPoint = stringUtility::formatString("\\??\\%c:", 'H' + index);
+ STRING sMountPoint = {(USHORT)strlen(mountPoint), (USHORT)strlen(mountPoint) + 1, mountPoint};
+ IoCreateSymbolicLink(&sMountPoint, &DeviceName);
+ free(mountPoint);
+ mMemoryUnityHandles[index] = (char)('H' + index);
+ }
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < XGetPortCount(); i++)
+ {
+
+ memcpy(&mControllerStatesPrevious[i], &mControllerStatesCurrent[i], sizeof(JoystickButtonStates));
+ memset(&mControllerStatesCurrent[i], 0, sizeof(JoystickButtonStates));
+
+ if (mControllerHandles[i] == NULL)
+ {
+ continue;
+ }
+
+ XINPUT_STATE inputStates;
+ if (XInputGetState(mControllerHandles[i], &inputStates) != 0)
+ {
+ continue;
+ }
+
+ XINPUT_GAMEPAD gamePad;
+ memcpy(&gamePad, &inputStates.Gamepad, sizeof(XINPUT_GAMEPAD));
+
+ if (gamePad.bAnalogButtons[XINPUT_GAMEPAD_A] > 32)
+ {
+ mControllerStatesCurrent[i].buttonA = JoystickButtonStatePressed;
+ }
+ if (gamePad.bAnalogButtons[XINPUT_GAMEPAD_B] > 32)
+ {
+ mControllerStatesCurrent[i].buttonB = JoystickButtonStatePressed;
+ }
+ if (gamePad.bAnalogButtons[XINPUT_GAMEPAD_X] > 32)
+ {
+ mControllerStatesCurrent[i].buttonX = JoystickButtonStatePressed;
+ }
+ if (gamePad.bAnalogButtons[XINPUT_GAMEPAD_Y] > 32)
+ {
+ mControllerStatesCurrent[i].buttonY = JoystickButtonStatePressed;
+ }
+ if (gamePad.bAnalogButtons[XINPUT_GAMEPAD_WHITE] > 32)
+ {
+ mControllerStatesCurrent[i].buttonWhite = JoystickButtonStatePressed;
+ }
+ if (gamePad.bAnalogButtons[XINPUT_GAMEPAD_BLACK] > 32)
+ {
+ mControllerStatesCurrent[i].buttonBlack = JoystickButtonStatePressed;
+ }
+ if ((gamePad.wButtons & XINPUT_GAMEPAD_BACK) != 0)
+ {
+ mControllerStatesCurrent[i].buttonBack = JoystickButtonStatePressed;
+ }
+ if ((gamePad.wButtons & XINPUT_GAMEPAD_START) != 0)
+ {
+ mControllerStatesCurrent[i].buttonStart = JoystickButtonStatePressed;
+ }
+ if ((gamePad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) != 0)
+ {
+ mControllerStatesCurrent[i].buttonLeftThumb = JoystickButtonStatePressed;
+ }
+ if ((gamePad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) != 0)
+ {
+ mControllerStatesCurrent[i].buttonRightThumb = JoystickButtonStatePressed;
+ }
+ if ((gamePad.wButtons & XINPUT_GAMEPAD_DPAD_UP) != 0)
+ {
+ mControllerStatesCurrent[i].buttonDpadUp = JoystickButtonStatePressed;
+ }
+ if ((gamePad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) != 0)
+ {
+ mControllerStatesCurrent[i].buttonDpadRight = JoystickButtonStatePressed;
+ }
+ if ((gamePad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) != 0)
+ {
+ mControllerStatesCurrent[i].buttonDpadDown = JoystickButtonStatePressed;
+ }
+ if ((gamePad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) != 0)
+ {
+ mControllerStatesCurrent[i].buttonDpadLeft = JoystickButtonStatePressed;
+ }
+ if (gamePad.bAnalogButtons[XINPUT_GAMEPAD_LEFT_TRIGGER] > 128)
+ {
+ mControllerStatesCurrent[i].buttonTriggerLeft = JoystickButtonStatePressed;
+ }
+ if (gamePad.bAnalogButtons[XINPUT_GAMEPAD_RIGHT_TRIGGER] > 128)
+ {
+ mControllerStatesCurrent[i].buttonTriggerRight = JoystickButtonStatePressed;
+ }
+ }
+}
+
+bool inputManager::buttonDown(JoystickButton button, int port)
+{
+ for (int i = 0; i < XGetPortCount(); i++)
+ {
+ if (port >= 0 && port != i)
+ {
+ continue;
+ }
+
+ if (mControllerHandles[i] == NULL)
+ {
+ continue;
+ }
+
+ if (button == ButtonA && mControllerStatesCurrent[i].buttonA == JoystickButtonStatePressed)
+ {
+ return true;
+ }
+ else if (button == ButtonB && mControllerStatesCurrent[i].buttonB == JoystickButtonStatePressed)
+ {
+ return true;
+ }
+ else if (button == ButtonX && mControllerStatesCurrent[i].buttonX == JoystickButtonStatePressed)
+ {
+ return true;
+ }
+ else if (button == ButtonY && mControllerStatesCurrent[i].buttonY == JoystickButtonStatePressed)
+ {
+ return true;
+ }
+ else if (button == ButtonWhite && mControllerStatesCurrent[i].buttonWhite == JoystickButtonStatePressed)
+ {
+ return true;
+ }
+ else if (button == ButtonBlack && mControllerStatesCurrent[i].buttonBlack == JoystickButtonStatePressed)
+ {
+ return true;
+ }
+ else if (button == ButtonBack && mControllerStatesCurrent[i].buttonBack == JoystickButtonStatePressed)
+ {
+ return true;
+ }
+ else if (button == ButtonStart && mControllerStatesCurrent[i].buttonStart == JoystickButtonStatePressed)
+ {
+ return true;
+ }
+ else if (button == ButtonLeftThumb && mControllerStatesCurrent[i].buttonLeftThumb == JoystickButtonStatePressed)
+ {
+ return true;
+ }
+ else if (button == ButtonRightThumb && mControllerStatesCurrent[i].buttonRightThumb == JoystickButtonStatePressed)
+ {
+ return true;
+ }
+ else if (button == ButtonDpadUp && mControllerStatesCurrent[i].buttonDpadUp == JoystickButtonStatePressed)
+ {
+ return true;
+ }
+ else if (button == ButtonDpadRight && mControllerStatesCurrent[i].buttonDpadRight == JoystickButtonStatePressed)
+ {
+ return true;
+ }
+ else if (button == ButtonDpadDown && mControllerStatesCurrent[i].buttonDpadDown == JoystickButtonStatePressed)
+ {
+ return true;
+ }
+ else if (button == ButtonDpadLeft && mControllerStatesCurrent[i].buttonDpadLeft == JoystickButtonStatePressed)
+ {
+ return true;
+ }
+ else if (button == ButtonTriggerLeft && mControllerStatesCurrent[i].buttonTriggerLeft == JoystickButtonStatePressed)
+ {
+ return true;
+ }
+ else if (button == ButtonTriggerRight && mControllerStatesCurrent[i].buttonTriggerRight == JoystickButtonStatePressed)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool inputManager::buttonPressed(JoystickButton button, int port)
+{
+ for (int i = 0; i < XGetPortCount(); i++)
+ {
+ if (port >= 0 && port != i)
+ {
+ continue;
+ }
+
+ if (mControllerHandles[i] == NULL)
+ {
+ continue;
+ }
+
+ if (button == ButtonA && mControllerStatesCurrent[i].buttonA == JoystickButtonStatePressed && mControllerStatesPrevious[i].buttonA == JoystickButtonStateNone)
+ {
+ audioPlayer::play("button-a.ogg", false);
+ return true;
+ }
+ else if (button == ButtonB && mControllerStatesCurrent[i].buttonB == JoystickButtonStatePressed && mControllerStatesPrevious[i].buttonB == JoystickButtonStateNone)
+ {
+ audioPlayer::play("button-other.ogg", false);
+ return true;
+ }
+ else if (button == ButtonX && mControllerStatesCurrent[i].buttonX == JoystickButtonStatePressed && mControllerStatesPrevious[i].buttonX == JoystickButtonStateNone)
+ {
+ audioPlayer::play("button-x.ogg", false);
+ return true;
+ }
+ else if (button == ButtonY && mControllerStatesCurrent[i].buttonY == JoystickButtonStatePressed && mControllerStatesPrevious[i].buttonY == JoystickButtonStateNone)
+ {
+ audioPlayer::play("button-other.ogg", false);
+ return true;
+ }
+ else if (button == ButtonWhite && mControllerStatesCurrent[i].buttonWhite == JoystickButtonStatePressed && mControllerStatesPrevious[i].buttonWhite == JoystickButtonStateNone)
+ {
+ audioPlayer::play("button-other.ogg", false);
+ return true;
+ }
+ else if (button == ButtonBlack && mControllerStatesCurrent[i].buttonBlack == JoystickButtonStatePressed && mControllerStatesPrevious[i].buttonBlack == JoystickButtonStateNone)
+ {
+ audioPlayer::play("button-other.ogg", false);
+ return true;
+ }
+ else if (button == ButtonBack && mControllerStatesCurrent[i].buttonBack == JoystickButtonStatePressed && mControllerStatesPrevious[i].buttonBack == JoystickButtonStateNone)
+ {
+ audioPlayer::play("button-back.ogg", false);
+ return true;
+ }
+ else if (button == ButtonStart && mControllerStatesCurrent[i].buttonStart == JoystickButtonStatePressed && mControllerStatesPrevious[i].buttonStart == JoystickButtonStateNone)
+ {
+ audioPlayer::play("button-other.ogg", false);
+ return true;
+ }
+ else if (button == ButtonLeftThumb && mControllerStatesCurrent[i].buttonLeftThumb == JoystickButtonStatePressed && mControllerStatesPrevious[i].buttonLeftThumb == JoystickButtonStateNone)
+ {
+ audioPlayer::play("button-other.ogg", false);
+ return true;
+ }
+ else if (button == ButtonRightThumb && mControllerStatesCurrent[i].buttonRightThumb == JoystickButtonStatePressed && mControllerStatesPrevious[i].buttonRightThumb == JoystickButtonStateNone)
+ {
+ audioPlayer::play("button-other.ogg", false);
+ return true;
+ }
+ else if (button == ButtonDpadUp && mControllerStatesCurrent[i].buttonDpadUp == JoystickButtonStatePressed && mControllerStatesPrevious[i].buttonDpadUp == JoystickButtonStateNone)
+ {
+ audioPlayer::play("button-up.ogg", false);
+ return true;
+ }
+ else if (button == ButtonDpadRight && mControllerStatesCurrent[i].buttonDpadRight == JoystickButtonStatePressed && mControllerStatesPrevious[i].buttonDpadRight == JoystickButtonStateNone)
+ {
+ audioPlayer::play("button-other.ogg", false);
+ return true;
+ }
+ else if (button == ButtonDpadDown && mControllerStatesCurrent[i].buttonDpadDown == JoystickButtonStatePressed && mControllerStatesPrevious[i].buttonDpadDown == JoystickButtonStateNone)
+ {
+ audioPlayer::play("button-down.ogg", false);
+ return true;
+ }
+ else if (button == ButtonDpadLeft && mControllerStatesCurrent[i].buttonDpadLeft == JoystickButtonStatePressed && mControllerStatesPrevious[i].buttonDpadLeft == JoystickButtonStateNone)
+ {
+ audioPlayer::play("button-other.ogg", false);
+ return true;
+ }
+ else if (button == ButtonTriggerLeft && mControllerStatesCurrent[i].buttonTriggerLeft == JoystickButtonStatePressed && mControllerStatesPrevious[i].buttonTriggerLeft == JoystickButtonStateNone)
+ {
+ audioPlayer::play("button-other.ogg", false);
+ return true;
+ }
+ else if (button == ButtonTriggerRight && mControllerStatesCurrent[i].buttonTriggerRight == JoystickButtonStatePressed && mControllerStatesPrevious[i].buttonTriggerRight == JoystickButtonStateNone)
+ {
+ audioPlayer::play("button-other.ogg", false);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool inputManager::isMemoryUnitMounted(char letter)
+{
+ for (int i = 0; i < XGetPortCount() * 2; i++)
+ {
+ if (mMemoryUnityHandles[i] == letter)
+ {
+ return true;
+ }
+ }
+ return false;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/inputManager.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/inputManager.h
new file mode 100644
index 0000000..8b05255
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/inputManager.h
@@ -0,0 +1,56 @@
+#pragma once
+
+#include
+
+typedef enum JoystickButtonState {
+ JoystickButtonStateNone,
+ JoystickButtonStatePressed
+} JoystickButtonState;
+
+typedef enum JoystickButton {
+ ButtonA,
+ ButtonB,
+ ButtonX,
+ ButtonY,
+ ButtonWhite,
+ ButtonBlack,
+ ButtonBack,
+ ButtonStart,
+ ButtonLeftThumb,
+ ButtonRightThumb,
+ ButtonDpadUp,
+ ButtonDpadRight,
+ ButtonDpadDown,
+ ButtonDpadLeft,
+ ButtonTriggerLeft,
+ ButtonTriggerRight
+} JoystickButton;
+
+typedef struct JoystickButtonStates
+{
+ JoystickButtonState buttonA;
+ JoystickButtonState buttonB;
+ JoystickButtonState buttonX;
+ JoystickButtonState buttonY;
+ JoystickButtonState buttonWhite;
+ JoystickButtonState buttonBlack;
+ JoystickButtonState buttonBack;
+ JoystickButtonState buttonStart;
+ JoystickButtonState buttonLeftThumb;
+ JoystickButtonState buttonRightThumb;
+ JoystickButtonState buttonDpadUp;
+ JoystickButtonState buttonDpadRight;
+ JoystickButtonState buttonDpadDown;
+ JoystickButtonState buttonDpadLeft;
+ JoystickButtonState buttonTriggerLeft;
+ JoystickButtonState buttonTriggerRight;
+} JoystickButtonStates;
+
+class inputManager
+{
+public:
+ static void processController();
+ static bool buttonDown(JoystickButton button, int port = -1);
+ static bool buttonPressed(JoystickButton button, int port = -1);
+ static bool isMemoryUnitMounted(char letter);
+};
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/json.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/json.h
new file mode 100644
index 0000000..f7be066
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/json.h
@@ -0,0 +1,3446 @@
+/*
+ The latest version of this library is available on GitHub;
+ https://github.com/sheredom/json.h.
+*/
+
+/*
+ This is free and unencumbered software released into the public domain.
+
+ Anyone is free to copy, modify, publish, use, compile, sell, or
+ distribute this software, either in source code form or as a compiled
+ binary, for any purpose, commercial or non-commercial, and by any
+ means.
+
+ In jurisdictions that recognize copyright laws, the author or authors
+ of this software dedicate any and all copyright interest in the
+ software to the public domain. We make this dedication for the benefit
+ of the public at large and to the detriment of our heirs and
+ successors. We intend this dedication to be an overt act of
+ relinquishment in perpetuity of all present and future rights to this
+ software under copyright law.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ OTHER DEALINGS IN THE SOFTWARE.
+
+ For more information, please refer to .
+*/
+
+#ifndef SHEREDOM_JSON_H_INCLUDED
+#define SHEREDOM_JSON_H_INCLUDED
+
+#if defined(_MSC_VER)
+#pragma warning(push)
+
+/* disable warning: no function prototype given: converting '()' to '(void)' */
+#pragma warning(disable : 4255)
+
+/* disable warning: '__cplusplus' is not defined as a preprocessor macro,
+ * replacing with '0' for '#if/#elif' */
+#pragma warning(disable : 4668)
+
+/* disable warning: 'bytes padding added after construct' */
+#pragma warning(disable : 4820)
+#endif
+
+#include
+#include
+
+#if defined(_MSC_VER) || defined(__WATCOMC__)
+#define json_weak __inline
+#elif defined(__clang__) || defined(__GNUC__)
+#define json_weak __attribute__((weak))
+#else
+#error Non clang, non gcc, non MSVC, non WATCOM compiler found!
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct json_value_s;
+struct json_parse_result_s;
+
+enum json_parse_flags_e {
+ json_parse_flags_default = 0,
+
+ /* allow trailing commas in objects and arrays. For example, both [true,] and
+ {"a" : null,} would be allowed with this option on. */
+ json_parse_flags_allow_trailing_comma = 0x1,
+
+ /* allow unquoted keys for objects. For example, {a : null} would be allowed
+ with this option on. */
+ json_parse_flags_allow_unquoted_keys = 0x2,
+
+ /* allow a global unbracketed object. For example, a : null, b : true, c : {}
+ would be allowed with this option on. */
+ json_parse_flags_allow_global_object = 0x4,
+
+ /* allow objects to use '=' instead of ':' between key/value pairs. For
+ example, a = null, b : true would be allowed with this option on. */
+ json_parse_flags_allow_equals_in_object = 0x8,
+
+ /* allow that objects don't have to have comma separators between key/value
+ pairs. */
+ json_parse_flags_allow_no_commas = 0x10,
+
+ /* allow c-style comments (either variants) to be ignored in the input JSON
+ file. */
+ json_parse_flags_allow_c_style_comments = 0x20,
+
+ /* deprecated flag, unused. */
+ json_parse_flags_deprecated = 0x40,
+
+ /* record location information for each value. */
+ json_parse_flags_allow_location_information = 0x80,
+
+ /* allow strings to be 'single quoted'. */
+ json_parse_flags_allow_single_quoted_strings = 0x100,
+
+ /* allow numbers to be hexadecimal. */
+ json_parse_flags_allow_hexadecimal_numbers = 0x200,
+
+ /* allow numbers like +123 to be parsed. */
+ json_parse_flags_allow_leading_plus_sign = 0x400,
+
+ /* allow numbers like .0123 or 123. to be parsed. */
+ json_parse_flags_allow_leading_or_trailing_decimal_point = 0x800,
+
+ /* allow Infinity, -Infinity, NaN, -NaN. */
+ json_parse_flags_allow_inf_and_nan = 0x1000,
+
+ /* allow multi line string values. */
+ json_parse_flags_allow_multi_line_strings = 0x2000,
+
+ /* allow simplified JSON to be parsed. Simplified JSON is an enabling of a set
+ of other parsing options. */
+ json_parse_flags_allow_simplified_json =
+ (json_parse_flags_allow_trailing_comma |
+ json_parse_flags_allow_unquoted_keys |
+ json_parse_flags_allow_global_object |
+ json_parse_flags_allow_equals_in_object |
+ json_parse_flags_allow_no_commas),
+
+ /* allow JSON5 to be parsed. JSON5 is an enabling of a set of other parsing
+ options. */
+ json_parse_flags_allow_json5 =
+ (json_parse_flags_allow_trailing_comma |
+ json_parse_flags_allow_unquoted_keys |
+ json_parse_flags_allow_c_style_comments |
+ json_parse_flags_allow_single_quoted_strings |
+ json_parse_flags_allow_hexadecimal_numbers |
+ json_parse_flags_allow_leading_plus_sign |
+ json_parse_flags_allow_leading_or_trailing_decimal_point |
+ json_parse_flags_allow_inf_and_nan |
+ json_parse_flags_allow_multi_line_strings)
+};
+
+/* Parse a JSON text file, returning a pointer to the root of the JSON
+ * structure. json_parse performs 1 call to malloc for the entire encoding.
+ * Returns 0 if an error occurred (malformed JSON input, or malloc failed). */
+json_weak struct json_value_s *json_parse(const void *src, size_t src_size);
+
+/* Parse a JSON text file, returning a pointer to the root of the JSON
+ * structure. json_parse performs 1 call to alloc_func_ptr for the entire
+ * encoding. Returns 0 if an error occurred (malformed JSON input, or malloc
+ * failed). If an error occurred, the result struct (if not NULL) will explain
+ * the type of error, and the location in the input it occurred. If
+ * alloc_func_ptr is null then malloc is used. */
+json_weak struct json_value_s *
+json_parse_ex(const void *src, size_t src_size, size_t flags_bitset,
+ void *(*alloc_func_ptr)(void *, size_t), void *user_data,
+ struct json_parse_result_s *result);
+
+/* Extracts a value and all the data that makes it up into a newly created
+ * value. json_extract_value performs 1 call to malloc for the entire encoding.
+ */
+json_weak struct json_value_s *
+json_extract_value(const struct json_value_s *value);
+
+/* Extracts a value and all the data that makes it up into a newly created
+ * value. json_extract_value performs 1 call to alloc_func_ptr for the entire
+ * encoding. If alloc_func_ptr is null then malloc is used. */
+json_weak struct json_value_s *
+json_extract_value_ex(const struct json_value_s *value,
+ void *(*alloc_func_ptr)(void *, size_t), void *user_data);
+
+/* Write out a minified JSON utf-8 string. This string is an encoding of the
+ * minimal string characters required to still encode the same data.
+ * json_write_minified performs 1 call to malloc for the entire encoding. Return
+ * 0 if an error occurred (malformed JSON input, or malloc failed). The out_size
+ * parameter is optional as the utf-8 string is null terminated. */
+json_weak void *json_write_minified(const struct json_value_s *value,
+ size_t *out_size);
+
+/* Write out a pretty JSON utf-8 string. This string is encoded such that the
+ * resultant JSON is pretty in that it is easily human readable. The indent and
+ * newline parameters allow a user to specify what kind of indentation and
+ * newline they want (two spaces / three spaces / tabs? \r, \n, \r\n ?). Both
+ * indent and newline can be NULL, indent defaults to two spaces (" "), and
+ * newline defaults to linux newlines ('\n' as the newline character).
+ * json_write_pretty performs 1 call to malloc for the entire encoding. Return 0
+ * if an error occurred (malformed JSON input, or malloc failed). The out_size
+ * parameter is optional as the utf-8 string is null terminated. */
+json_weak void *json_write_pretty(const struct json_value_s *value,
+ const char *indent, const char *newline,
+ size_t *out_size);
+
+/* Reinterpret a JSON value as a string. Returns null is the value was not a
+ * string. */
+json_weak struct json_string_s *
+json_value_as_string(struct json_value_s *const value);
+
+/* Reinterpret a JSON value as a number. Returns null is the value was not a
+ * number. */
+json_weak struct json_number_s *
+json_value_as_number(struct json_value_s *const value);
+
+/* Reinterpret a JSON value as an object. Returns null is the value was not an
+ * object. */
+json_weak struct json_object_s *
+json_value_as_object(struct json_value_s *const value);
+
+/* Reinterpret a JSON value as an array. Returns null is the value was not an
+ * array. */
+json_weak struct json_array_s *
+json_value_as_array(struct json_value_s *const value);
+
+/* Whether the value is true. */
+json_weak int json_value_is_true(const struct json_value_s *const value);
+
+/* Whether the value is false. */
+json_weak int json_value_is_false(const struct json_value_s *const value);
+
+/* Whether the value is null. */
+json_weak int json_value_is_null(const struct json_value_s *const value);
+
+/* The various types JSON values can be. Used to identify what a value is. */
+typedef enum json_type_e {
+ json_type_string,
+ json_type_number,
+ json_type_object,
+ json_type_array,
+ json_type_true,
+ json_type_false,
+ json_type_null
+
+} json_type_t;
+
+/* A JSON string value. */
+typedef struct json_string_s {
+ /* utf-8 string */
+ const char *string;
+ /* The size (in bytes) of the string */
+ size_t string_size;
+
+} json_string_t;
+
+/* A JSON string value (extended). */
+typedef struct json_string_ex_s {
+ /* The JSON string this extends. */
+ struct json_string_s string;
+
+ /* The character offset for the value in the JSON input. */
+ size_t offset;
+
+ /* The line number for the value in the JSON input. */
+ size_t line_no;
+
+ /* The row number for the value in the JSON input, in bytes. */
+ size_t row_no;
+
+} json_string_ex_t;
+
+/* A JSON number value. */
+typedef struct json_number_s {
+ /* ASCII string containing representation of the number. */
+ const char *number;
+ /* the size (in bytes) of the number. */
+ size_t number_size;
+
+} json_number_t;
+
+/* an element of a JSON object. */
+typedef struct json_object_element_s {
+ /* the name of this element. */
+ struct json_string_s *name;
+ /* the value of this element. */
+ struct json_value_s *value;
+ /* the next object element (can be NULL if the last element in the object). */
+ struct json_object_element_s *next;
+
+} json_object_element_t;
+
+/* a JSON object value. */
+typedef struct json_object_s {
+ /* a linked list of the elements in the object. */
+ struct json_object_element_s *start;
+ /* the number of elements in the object. */
+ size_t length;
+
+} json_object_t;
+
+/* an element of a JSON array. */
+typedef struct json_array_element_s {
+ /* the value of this element. */
+ struct json_value_s *value;
+ /* the next array element (can be NULL if the last element in the array). */
+ struct json_array_element_s *next;
+
+} json_array_element_t;
+
+/* a JSON array value. */
+typedef struct json_array_s {
+ /* a linked list of the elements in the array. */
+ struct json_array_element_s *start;
+ /* the number of elements in the array. */
+ size_t length;
+
+} json_array_t;
+
+/* a JSON value. */
+typedef struct json_value_s {
+ /* a pointer to either a json_string_s, json_number_s, json_object_s, or. */
+ /* json_array_s. Should be cast to the appropriate struct type based on what.
+ */
+ /* the type of this value is. */
+ void *payload;
+ /* must be one of json_type_e. If type is json_type_true, json_type_false, or.
+ */
+ /* json_type_null, payload will be NULL. */
+ size_t type;
+
+} json_value_t;
+
+/* a JSON value (extended). */
+typedef struct json_value_ex_s {
+ /* the JSON value this extends. */
+ struct json_value_s value;
+
+ /* the character offset for the value in the JSON input. */
+ size_t offset;
+
+ /* the line number for the value in the JSON input. */
+ size_t line_no;
+
+ /* the row number for the value in the JSON input, in bytes. */
+ size_t row_no;
+
+} json_value_ex_t;
+
+/* a parsing error code. */
+enum json_parse_error_e {
+ /* no error occurred (huzzah!). */
+ json_parse_error_none = 0,
+
+ /* expected either a comma or a closing '}' or ']' to close an object or. */
+ /* array! */
+ json_parse_error_expected_comma_or_closing_bracket,
+
+ /* colon separating name/value pair was missing! */
+ json_parse_error_expected_colon,
+
+ /* expected string to begin with '"'! */
+ json_parse_error_expected_opening_quote,
+
+ /* invalid escaped sequence in string! */
+ json_parse_error_invalid_string_escape_sequence,
+
+ /* invalid number format! */
+ json_parse_error_invalid_number_format,
+
+ /* invalid value! */
+ json_parse_error_invalid_value,
+
+ /* reached end of buffer before object/array was complete! */
+ json_parse_error_premature_end_of_buffer,
+
+ /* string was malformed! */
+ json_parse_error_invalid_string,
+
+ /* a call to malloc, or a user provider allocator, failed. */
+ json_parse_error_allocator_failed,
+
+ /* the JSON input had unexpected trailing characters that weren't part of the.
+ JSON value. */
+ json_parse_error_unexpected_trailing_characters,
+
+ /* catch-all error for everything else that exploded (real bad chi!). */
+ json_parse_error_unknown
+};
+
+/* error report from json_parse_ex(). */
+typedef struct json_parse_result_s {
+ /* the error code (one of json_parse_error_e). */
+ size_t error;
+
+ /* the character offset for the error in the JSON input. */
+ size_t error_offset;
+
+ /* the line number for the error in the JSON input. */
+ size_t error_line_no;
+
+ /* the row number for the error, in bytes. */
+ size_t error_row_no;
+
+} json_parse_result_t;
+
+#ifdef __cplusplus
+} /* extern "C". */
+#endif
+
+#include
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+#define json_uintmax_t unsigned __int64
+
+#if defined(_MSC_VER)
+#define json_strtoumax _strtoui64
+#else
+#define json_strtoumax strtoumax
+#endif
+
+#if defined(__cplusplus) && (__cplusplus >= 201103L)
+#define json_null nullptr
+#else
+#define json_null 0
+#endif
+
+#if defined(__clang__)
+#pragma clang diagnostic push
+
+/* we do one big allocation via malloc, then cast aligned slices of this for. */
+/* our structures - we don't have a way to tell the compiler we know what we. */
+/* are doing, so disable the warning instead! */
+#pragma clang diagnostic ignored "-Wcast-align"
+
+/* We use C style casts everywhere. */
+#pragma clang diagnostic ignored "-Wold-style-cast"
+
+/* We need long long for strtoull. */
+#pragma clang diagnostic ignored "-Wc++11-long-long"
+
+/* Who cares if nullptr doesn't work with C++98, we don't use it there! */
+#pragma clang diagnostic ignored "-Wc++98-compat"
+#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
+#elif defined(_MSC_VER)
+#pragma warning(push)
+
+/* disable 'function selected for inline expansion' warning. */
+#pragma warning(disable : 4711)
+
+/* disable '#pragma warning: there is no warning number' warning. */
+#pragma warning(disable : 4619)
+
+/* disable 'warning number not a valid compiler warning' warning. */
+#pragma warning(disable : 4616)
+
+/* disable 'Compiler will insert Spectre mitigation for memory load if
+ * /Qspectre. */
+/* switch specified' warning. */
+#pragma warning(disable : 5045)
+#endif
+
+struct json_parse_state_s {
+ const char *src;
+ size_t size;
+ size_t offset;
+ size_t flags_bitset;
+ char *data;
+ char *dom;
+ size_t dom_size;
+ size_t data_size;
+ size_t line_no; /* line counter for error reporting. */
+ size_t line_offset; /* (offset-line_offset) is the character number (in
+ bytes). */
+ size_t error;
+};
+
+json_weak int json_hexadecimal_digit(const char c);
+int json_hexadecimal_digit(const char c) {
+ if ('0' <= c && c <= '9') {
+ return c - '0';
+ }
+ if ('a' <= c && c <= 'f') {
+ return c - 'a' + 10;
+ }
+ if ('A' <= c && c <= 'F') {
+ return c - 'A' + 10;
+ }
+ return -1;
+}
+
+json_weak int json_hexadecimal_value(const char *c, const unsigned long size,
+ unsigned long *result);
+int json_hexadecimal_value(const char *c, const unsigned long size,
+ unsigned long *result) {
+ const char *p;
+ int digit;
+
+ if (size > sizeof(unsigned long) * 2) {
+ return 0;
+ }
+
+ *result = 0;
+ for (p = c; (unsigned long)(p - c) < size; ++p) {
+ *result <<= 4;
+ digit = json_hexadecimal_digit(*p);
+ if (digit < 0 || digit > 15) {
+ return 0;
+ }
+ *result |= (unsigned char)digit;
+ }
+ return 1;
+}
+
+json_weak int json_skip_whitespace(struct json_parse_state_s *state);
+int json_skip_whitespace(struct json_parse_state_s *state) {
+ size_t offset = state->offset;
+ const size_t size = state->size;
+ const char *const src = state->src;
+
+ if (offset >= state->size) {
+ return 0;
+ }
+
+ /* the only valid whitespace according to ECMA-404 is ' ', '\n', '\r' and
+ * '\t'. */
+ switch (src[offset]) {
+ default:
+ return 0;
+ case ' ':
+ case '\r':
+ case '\t':
+ case '\n':
+ break;
+ }
+
+ do {
+ switch (src[offset]) {
+ default:
+ /* Update offset. */
+ state->offset = offset;
+ return 1;
+ case ' ':
+ case '\r':
+ case '\t':
+ break;
+ case '\n':
+ state->line_no++;
+ state->line_offset = offset;
+ break;
+ }
+
+ offset++;
+ } while (offset < size);
+
+ /* Update offset. */
+ state->offset = offset;
+ return 1;
+}
+
+json_weak int json_skip_c_style_comments(struct json_parse_state_s *state);
+int json_skip_c_style_comments(struct json_parse_state_s *state) {
+ /* to have a C-style comment we need at least 2 characters of space */
+ if ((state->offset + 2) > state->size) {
+ return 0;
+ }
+
+ /* do we have a comment? */
+ if ('/' == state->src[state->offset]) {
+ if ('/' == state->src[state->offset + 1]) {
+ /* we had a comment of the form // */
+
+ /* skip first '/' */
+ state->offset++;
+
+ /* skip second '/' */
+ state->offset++;
+
+ while (state->offset < state->size) {
+ switch (state->src[state->offset]) {
+ default:
+ /* skip the character in the comment */
+ state->offset++;
+ break;
+ case '\n':
+ /* if we have a newline, our comment has ended! Skip the newline */
+ state->offset++;
+
+ /* we entered a newline, so move our line info forward */
+ state->line_no++;
+ state->line_offset = state->offset;
+ return 1;
+ }
+ }
+
+ /* we reached the end of the JSON file! */
+ return 1;
+ } else if ('*' == state->src[state->offset + 1]) {
+ /* we had a comment in the C-style long form */
+
+ /* skip '/' */
+ state->offset++;
+
+ /* skip '*' */
+ state->offset++;
+
+ while (state->offset + 1 < state->size) {
+ if (('*' == state->src[state->offset]) &&
+ ('/' == state->src[state->offset + 1])) {
+ /* we reached the end of our comment! */
+ state->offset += 2;
+ return 1;
+ } else if ('\n' == state->src[state->offset]) {
+ /* we entered a newline, so move our line info forward */
+ state->line_no++;
+ state->line_offset = state->offset;
+ }
+
+ /* skip character within comment */
+ state->offset++;
+ }
+
+ /* comment wasn't ended correctly which is a failure */
+ return 1;
+ }
+ }
+
+ /* we didn't have any comment, which is ok too! */
+ return 0;
+}
+
+json_weak int json_skip_all_skippables(struct json_parse_state_s *state);
+int json_skip_all_skippables(struct json_parse_state_s *state) {
+ /* skip all whitespace and other skippables until there are none left. note
+ * that the previous version suffered from read past errors should. the
+ * stream end on json_skip_c_style_comments eg. '{"a" ' with comments flag.
+ */
+
+ int did_consume = 0;
+ const size_t size = state->size;
+
+ if (json_parse_flags_allow_c_style_comments & state->flags_bitset) {
+ do {
+ if (state->offset == size) {
+ state->error = json_parse_error_premature_end_of_buffer;
+ return 1;
+ }
+
+ did_consume = json_skip_whitespace(state);
+
+ /* This should really be checked on access, not in front of every call.
+ */
+ if (state->offset >= size) {
+ state->error = json_parse_error_premature_end_of_buffer;
+ return 1;
+ }
+
+ did_consume |= json_skip_c_style_comments(state);
+ } while (0 != did_consume);
+ } else {
+ do {
+ if (state->offset == size) {
+ state->error = json_parse_error_premature_end_of_buffer;
+ return 1;
+ }
+
+ did_consume = json_skip_whitespace(state);
+ } while (0 != did_consume);
+ }
+
+ if (state->offset == size) {
+ state->error = json_parse_error_premature_end_of_buffer;
+ return 1;
+ }
+
+ return 0;
+}
+
+json_weak int json_get_value_size(struct json_parse_state_s *state,
+ int is_global_object);
+
+json_weak int json_get_string_size(struct json_parse_state_s *state,
+ size_t is_key);
+int json_get_string_size(struct json_parse_state_s *state, size_t is_key) {
+ size_t offset = state->offset;
+ const size_t size = state->size;
+ size_t data_size = 0;
+ const char *const src = state->src;
+ const int is_single_quote = '\'' == src[offset];
+ const char quote_to_use = is_single_quote ? '\'' : '"';
+ const size_t flags_bitset = state->flags_bitset;
+ unsigned long codepoint;
+ unsigned long high_surrogate = 0;
+
+ if ((json_parse_flags_allow_location_information & flags_bitset) != 0 &&
+ is_key != 0) {
+ state->dom_size += sizeof(struct json_string_ex_s);
+ } else {
+ state->dom_size += sizeof(struct json_string_s);
+ }
+
+ if ('"' != src[offset]) {
+ /* if we are allowed single quoted strings check for that too. */
+ if (!((json_parse_flags_allow_single_quoted_strings & flags_bitset) &&
+ is_single_quote)) {
+ state->error = json_parse_error_expected_opening_quote;
+ state->offset = offset;
+ return 1;
+ }
+ }
+
+ /* skip leading '"' or '\''. */
+ offset++;
+
+ while ((offset < size) && (quote_to_use != src[offset])) {
+ /* add space for the character. */
+ data_size++;
+
+ switch (src[offset]) {
+ default:
+ break;
+ case '\0':
+ case '\t':
+ state->error = json_parse_error_invalid_string;
+ state->offset = offset;
+ return 1;
+ }
+
+ if ('\\' == src[offset]) {
+ /* skip reverse solidus character. */
+ offset++;
+
+ if (offset == size) {
+ state->error = json_parse_error_premature_end_of_buffer;
+ state->offset = offset;
+ return 1;
+ }
+
+ switch (src[offset]) {
+ default:
+ state->error = json_parse_error_invalid_string_escape_sequence;
+ state->offset = offset;
+ return 1;
+ case '"':
+ case '\\':
+ case '/':
+ case 'b':
+ case 'f':
+ case 'n':
+ case 'r':
+ case 't':
+ /* all valid characters! */
+ offset++;
+ break;
+ case 'u':
+ if (!(offset + 5 < size)) {
+ /* invalid escaped unicode sequence! */
+ state->error = json_parse_error_invalid_string_escape_sequence;
+ state->offset = offset;
+ return 1;
+ }
+
+ codepoint = 0;
+ if (!json_hexadecimal_value(&src[offset + 1], 4, &codepoint)) {
+ /* escaped unicode sequences must contain 4 hexadecimal digits! */
+ state->error = json_parse_error_invalid_string_escape_sequence;
+ state->offset = offset;
+ return 1;
+ }
+
+ /* Valid sequence!
+ * see: https://en.wikipedia.org/wiki/UTF-8#Invalid_code_points.
+ * 1 7 U + 0000 U + 007F 0xxxxxxx.
+ * 2 11 U + 0080 U + 07FF 110xxxxx
+ * 10xxxxxx.
+ * 3 16 U + 0800 U + FFFF 1110xxxx
+ * 10xxxxxx 10xxxxxx.
+ * 4 21 U + 10000 U + 10FFFF 11110xxx
+ * 10xxxxxx 10xxxxxx 10xxxxxx.
+ * Note: the high and low surrogate halves used by UTF-16 (U+D800
+ * through U+DFFF) and code points not encodable by UTF-16 (those after
+ * U+10FFFF) are not legal Unicode values, and their UTF-8 encoding must
+ * be treated as an invalid byte sequence. */
+
+ if (high_surrogate != 0) {
+ /* we previously read the high half of the \uxxxx\uxxxx pair, so now
+ * we expect the low half. */
+ if (codepoint >= 0xdc00 &&
+ codepoint <= 0xdfff) { /* low surrogate range. */
+ data_size += 3;
+ high_surrogate = 0;
+ } else {
+ state->error = json_parse_error_invalid_string_escape_sequence;
+ state->offset = offset;
+ return 1;
+ }
+ } else if (codepoint <= 0x7f) {
+ data_size += 0;
+ } else if (codepoint <= 0x7ff) {
+ data_size += 1;
+ } else if (codepoint >= 0xd800 &&
+ codepoint <= 0xdbff) { /* high surrogate range. */
+ /* The codepoint is the first half of a "utf-16 surrogate pair". so we
+ * need the other half for it to be valid: \uHHHH\uLLLL. */
+ if (offset + 11 > size || '\\' != src[offset + 5] ||
+ 'u' != src[offset + 6]) {
+ state->error = json_parse_error_invalid_string_escape_sequence;
+ state->offset = offset;
+ return 1;
+ }
+ high_surrogate = codepoint;
+ } else if (codepoint >= 0xd800 &&
+ codepoint <= 0xdfff) { /* low surrogate range. */
+ /* we did not read the other half before. */
+ state->error = json_parse_error_invalid_string_escape_sequence;
+ state->offset = offset;
+ return 1;
+ } else {
+ data_size += 2;
+ }
+ /* escaped codepoints after 0xffff are supported in json through utf-16
+ * surrogate pairs: \uD83D\uDD25 for U+1F525. */
+
+ offset += 5;
+ break;
+ }
+ } else if (('\r' == src[offset]) || ('\n' == src[offset])) {
+ if (!(json_parse_flags_allow_multi_line_strings & flags_bitset)) {
+ /* invalid escaped unicode sequence! */
+ state->error = json_parse_error_invalid_string_escape_sequence;
+ state->offset = offset;
+ return 1;
+ }
+
+ offset++;
+ } else {
+ /* skip character (valid part of sequence). */
+ offset++;
+ }
+ }
+
+ /* If the offset is equal to the size, we had a non-terminated string! */
+ if (offset == size) {
+ state->error = json_parse_error_premature_end_of_buffer;
+ state->offset = offset - 1;
+ return 1;
+ }
+
+ /* skip trailing '"' or '\''. */
+ offset++;
+
+ /* add enough space to store the string. */
+ state->data_size += data_size;
+
+ /* one more byte for null terminator ending the string! */
+ state->data_size++;
+
+ /* update offset. */
+ state->offset = offset;
+
+ return 0;
+}
+
+json_weak int is_valid_unquoted_key_char(const char c);
+int is_valid_unquoted_key_char(const char c) {
+ return (('0' <= c && c <= '9') || ('a' <= c && c <= 'z') ||
+ ('A' <= c && c <= 'Z') || ('_' == c));
+}
+
+json_weak int json_get_key_size(struct json_parse_state_s *state);
+int json_get_key_size(struct json_parse_state_s *state) {
+ const size_t flags_bitset = state->flags_bitset;
+
+ if (json_parse_flags_allow_unquoted_keys & flags_bitset) {
+ size_t offset = state->offset;
+ const size_t size = state->size;
+ const char *const src = state->src;
+ size_t data_size = state->data_size;
+
+ /* if we are allowing unquoted keys, first grok for a quote... */
+ if ('"' == src[offset]) {
+ /* ... if we got a comma, just parse the key as a string as normal. */
+ return json_get_string_size(state, 1);
+ } else if ((json_parse_flags_allow_single_quoted_strings & flags_bitset) &&
+ ('\'' == src[offset])) {
+ /* ... if we got a comma, just parse the key as a string as normal. */
+ return json_get_string_size(state, 1);
+ } else {
+ while ((offset < size) && is_valid_unquoted_key_char(src[offset])) {
+ offset++;
+ data_size++;
+ }
+
+ /* one more byte for null terminator ending the string! */
+ data_size++;
+
+ if (json_parse_flags_allow_location_information & flags_bitset) {
+ state->dom_size += sizeof(struct json_string_ex_s);
+ } else {
+ state->dom_size += sizeof(struct json_string_s);
+ }
+
+ /* update offset. */
+ state->offset = offset;
+
+ /* update data_size. */
+ state->data_size = data_size;
+
+ return 0;
+ }
+ } else {
+ /* we are only allowed to have quoted keys, so just parse a string! */
+ return json_get_string_size(state, 1);
+ }
+}
+
+json_weak int json_get_object_size(struct json_parse_state_s *state,
+ int is_global_object);
+int json_get_object_size(struct json_parse_state_s *state,
+ int is_global_object) {
+ const size_t flags_bitset = state->flags_bitset;
+ const char *const src = state->src;
+ const size_t size = state->size;
+ size_t elements = 0;
+ int allow_comma = 0;
+ int found_closing_brace = 0;
+
+ if (is_global_object) {
+ /* if we found an opening '{' of an object, we actually have a normal JSON
+ * object at the root of the DOM... */
+ if (!json_skip_all_skippables(state) && '{' == state->src[state->offset]) {
+ /* . and we don't actually have a global object after all! */
+ is_global_object = 0;
+ }
+ }
+
+ if (!is_global_object) {
+ if ('{' != src[state->offset]) {
+ state->error = json_parse_error_unknown;
+ return 1;
+ }
+
+ /* skip leading '{'. */
+ state->offset++;
+ }
+
+ state->dom_size += sizeof(struct json_object_s);
+
+ if ((state->offset == size) && !is_global_object) {
+ state->error = json_parse_error_premature_end_of_buffer;
+ return 1;
+ }
+
+ do {
+ if (!is_global_object) {
+ if (json_skip_all_skippables(state)) {
+ state->error = json_parse_error_premature_end_of_buffer;
+ return 1;
+ }
+
+ if ('}' == src[state->offset]) {
+ /* skip trailing '}'. */
+ state->offset++;
+
+ found_closing_brace = 1;
+
+ /* finished the object! */
+ break;
+ }
+ } else {
+ /* we don't require brackets, so that means the object ends when the input
+ * stream ends! */
+ if (json_skip_all_skippables(state)) {
+ break;
+ }
+ }
+
+ /* if we parsed at least one element previously, grok for a comma. */
+ if (allow_comma) {
+ if (',' == src[state->offset]) {
+ /* skip comma. */
+ state->offset++;
+ allow_comma = 0;
+ } else if (json_parse_flags_allow_no_commas & flags_bitset) {
+ /* we don't require a comma, and we didn't find one, which is ok! */
+ allow_comma = 0;
+ } else {
+ /* otherwise we are required to have a comma, and we found none. */
+ state->error = json_parse_error_expected_comma_or_closing_bracket;
+ return 1;
+ }
+
+ if (json_parse_flags_allow_trailing_comma & flags_bitset) {
+ continue;
+ } else {
+ if (json_skip_all_skippables(state)) {
+ state->error = json_parse_error_premature_end_of_buffer;
+ return 1;
+ }
+ }
+ }
+
+ if (json_get_key_size(state)) {
+ /* key parsing failed! */
+ state->error = json_parse_error_invalid_string;
+ return 1;
+ }
+
+ if (json_skip_all_skippables(state)) {
+ state->error = json_parse_error_premature_end_of_buffer;
+ return 1;
+ }
+
+ if (json_parse_flags_allow_equals_in_object & flags_bitset) {
+ const char current = src[state->offset];
+ if ((':' != current) && ('=' != current)) {
+ state->error = json_parse_error_expected_colon;
+ return 1;
+ }
+ } else {
+ if (':' != src[state->offset]) {
+ state->error = json_parse_error_expected_colon;
+ return 1;
+ }
+ }
+
+ /* skip colon. */
+ state->offset++;
+
+ if (json_skip_all_skippables(state)) {
+ state->error = json_parse_error_premature_end_of_buffer;
+ return 1;
+ }
+
+ if (json_get_value_size(state, /* is_global_object = */ 0)) {
+ /* value parsing failed! */
+ return 1;
+ }
+
+ /* successfully parsed a name/value pair! */
+ elements++;
+ allow_comma = 1;
+ } while (state->offset < size);
+
+ if ((state->offset == size) && !is_global_object && !found_closing_brace) {
+ state->error = json_parse_error_premature_end_of_buffer;
+ return 1;
+ }
+
+ state->dom_size += sizeof(struct json_object_element_s) * elements;
+
+ return 0;
+}
+
+json_weak int json_get_array_size(struct json_parse_state_s *state);
+int json_get_array_size(struct json_parse_state_s *state) {
+ const size_t flags_bitset = state->flags_bitset;
+ size_t elements = 0;
+ int allow_comma = 0;
+ const char *const src = state->src;
+ const size_t size = state->size;
+
+ if ('[' != src[state->offset]) {
+ /* expected array to begin with leading '['. */
+ state->error = json_parse_error_unknown;
+ return 1;
+ }
+
+ /* skip leading '['. */
+ state->offset++;
+
+ state->dom_size += sizeof(struct json_array_s);
+
+ while (state->offset < size) {
+ if (json_skip_all_skippables(state)) {
+ state->error = json_parse_error_premature_end_of_buffer;
+ return 1;
+ }
+
+ if (']' == src[state->offset]) {
+ /* skip trailing ']'. */
+ state->offset++;
+
+ state->dom_size += sizeof(struct json_array_element_s) * elements;
+
+ /* finished the object! */
+ return 0;
+ }
+
+ /* if we parsed at least once element previously, grok for a comma. */
+ if (allow_comma) {
+ if (',' == src[state->offset]) {
+ /* skip comma. */
+ state->offset++;
+ allow_comma = 0;
+ } else if (!(json_parse_flags_allow_no_commas & flags_bitset)) {
+ state->error = json_parse_error_expected_comma_or_closing_bracket;
+ return 1;
+ }
+
+ if (json_parse_flags_allow_trailing_comma & flags_bitset) {
+ allow_comma = 0;
+ continue;
+ } else {
+ if (json_skip_all_skippables(state)) {
+ state->error = json_parse_error_premature_end_of_buffer;
+ return 1;
+ }
+ }
+ }
+
+ if (json_get_value_size(state, /* is_global_object = */ 0)) {
+ /* value parsing failed! */
+ return 1;
+ }
+
+ /* successfully parsed an array element! */
+ elements++;
+ allow_comma = 1;
+ }
+
+ /* we consumed the entire input before finding the closing ']' of the array!
+ */
+ state->error = json_parse_error_premature_end_of_buffer;
+ return 1;
+}
+
+json_weak int json_get_number_size(struct json_parse_state_s *state);
+int json_get_number_size(struct json_parse_state_s *state) {
+ const size_t flags_bitset = state->flags_bitset;
+ size_t offset = state->offset;
+ const size_t size = state->size;
+ int had_leading_digits = 0;
+ const char *const src = state->src;
+
+ state->dom_size += sizeof(struct json_number_s);
+
+ if ((json_parse_flags_allow_hexadecimal_numbers & flags_bitset) &&
+ (offset + 1 < size) && ('0' == src[offset]) &&
+ (('x' == src[offset + 1]) || ('X' == src[offset + 1]))) {
+ /* skip the leading 0x that identifies a hexadecimal number. */
+ offset += 2;
+
+ /* consume hexadecimal digits. */
+ while ((offset < size) && (('0' <= src[offset] && src[offset] <= '9') ||
+ ('a' <= src[offset] && src[offset] <= 'f') ||
+ ('A' <= src[offset] && src[offset] <= 'F'))) {
+ offset++;
+ }
+ } else {
+ int found_sign = 0;
+ int inf_or_nan = 0;
+
+ if ((offset < size) &&
+ (('-' == src[offset]) ||
+ ((json_parse_flags_allow_leading_plus_sign & flags_bitset) &&
+ ('+' == src[offset])))) {
+ /* skip valid leading '-' or '+'. */
+ offset++;
+
+ found_sign = 1;
+ }
+
+ if (json_parse_flags_allow_inf_and_nan & flags_bitset) {
+ const char inf[9] = "Infinity";
+ const size_t inf_strlen = sizeof(inf) - 1;
+ const char nan[4] = "NaN";
+ const size_t nan_strlen = sizeof(nan) - 1;
+
+ if (offset + inf_strlen < size) {
+ int found = 1;
+ size_t i;
+ for (i = 0; i < inf_strlen; i++) {
+ if (inf[i] != src[offset + i]) {
+ found = 0;
+ break;
+ }
+ }
+
+ if (found) {
+ /* We found our special 'Infinity' keyword! */
+ offset += inf_strlen;
+
+ inf_or_nan = 1;
+ }
+ }
+
+ if (offset + nan_strlen < size) {
+ int found = 1;
+ size_t i;
+ for (i = 0; i < nan_strlen; i++) {
+ if (nan[i] != src[offset + i]) {
+ found = 0;
+ break;
+ }
+ }
+
+ if (found) {
+ /* We found our special 'NaN' keyword! */
+ offset += nan_strlen;
+
+ inf_or_nan = 1;
+ }
+ }
+
+ if (inf_or_nan) {
+ if (offset < size) {
+ switch (src[offset]) {
+ default:
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 'e':
+ case 'E':
+ /* cannot follow an inf or nan with digits! */
+ state->error = json_parse_error_invalid_number_format;
+ state->offset = offset;
+ return 1;
+ }
+ }
+ }
+ }
+
+ if (found_sign && !inf_or_nan && (offset < size) &&
+ !('0' <= src[offset] && src[offset] <= '9')) {
+ /* check if we are allowing leading '.'. */
+ if (!(json_parse_flags_allow_leading_or_trailing_decimal_point &
+ flags_bitset) ||
+ ('.' != src[offset])) {
+ /* a leading '-' must be immediately followed by any digit! */
+ state->error = json_parse_error_invalid_number_format;
+ state->offset = offset;
+ return 1;
+ }
+ }
+
+ if ((offset < size) && ('0' == src[offset])) {
+ /* skip valid '0'. */
+ offset++;
+
+ /* we need to record whether we had any leading digits for checks later.
+ */
+ had_leading_digits = 1;
+
+ if ((offset < size) && ('0' <= src[offset] && src[offset] <= '9')) {
+ /* a leading '0' must not be immediately followed by any digit! */
+ state->error = json_parse_error_invalid_number_format;
+ state->offset = offset;
+ return 1;
+ }
+ }
+
+ /* the main digits of our number next. */
+ while ((offset < size) && ('0' <= src[offset] && src[offset] <= '9')) {
+ offset++;
+
+ /* we need to record whether we had any leading digits for checks later.
+ */
+ had_leading_digits = 1;
+ }
+
+ if ((offset < size) && ('.' == src[offset])) {
+ offset++;
+
+ if ((offset >= size) || !('0' <= src[offset] && src[offset] <= '9')) {
+ if (!(json_parse_flags_allow_leading_or_trailing_decimal_point &
+ flags_bitset) ||
+ !had_leading_digits) {
+ /* a decimal point must be followed by at least one digit. */
+ state->error = json_parse_error_invalid_number_format;
+ state->offset = offset;
+ return 1;
+ }
+ }
+
+ /* a decimal point can be followed by more digits of course! */
+ while ((offset < size) && ('0' <= src[offset] && src[offset] <= '9')) {
+ offset++;
+ }
+ }
+
+ if ((offset < size) && ('e' == src[offset] || 'E' == src[offset])) {
+ /* our number has an exponent! Skip 'e' or 'E'. */
+ offset++;
+
+ if ((offset < size) && ('-' == src[offset] || '+' == src[offset])) {
+ /* skip optional '-' or '+'. */
+ offset++;
+ }
+
+ if ((offset < size) && !('0' <= src[offset] && src[offset] <= '9')) {
+ /* an exponent must have at least one digit! */
+ state->error = json_parse_error_invalid_number_format;
+ state->offset = offset;
+ return 1;
+ }
+
+ /* consume exponent digits. */
+ do {
+ offset++;
+ } while ((offset < size) && ('0' <= src[offset] && src[offset] <= '9'));
+ }
+ }
+
+ if (offset < size) {
+ switch (src[offset]) {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ case '}':
+ case ',':
+ case ']':
+ /* all of the above are ok. */
+ break;
+ case '=':
+ if (json_parse_flags_allow_equals_in_object & flags_bitset) {
+ break;
+ }
+
+ state->error = json_parse_error_invalid_number_format;
+ state->offset = offset;
+ return 1;
+ default:
+ state->error = json_parse_error_invalid_number_format;
+ state->offset = offset;
+ return 1;
+ }
+ }
+
+ state->data_size += offset - state->offset;
+
+ /* one more byte for null terminator ending the number string! */
+ state->data_size++;
+
+ /* update offset. */
+ state->offset = offset;
+
+ return 0;
+}
+
+json_weak int json_get_value_size(struct json_parse_state_s *state,
+ int is_global_object);
+int json_get_value_size(struct json_parse_state_s *state,
+ int is_global_object) {
+ const size_t flags_bitset = state->flags_bitset;
+ const char *const src = state->src;
+ size_t offset;
+ const size_t size = state->size;
+
+ if (json_parse_flags_allow_location_information & flags_bitset) {
+ state->dom_size += sizeof(struct json_value_ex_s);
+ } else {
+ state->dom_size += sizeof(struct json_value_s);
+ }
+
+ if (is_global_object) {
+ return json_get_object_size(state, /* is_global_object = */ 1);
+ } else {
+ if (json_skip_all_skippables(state)) {
+ state->error = json_parse_error_premature_end_of_buffer;
+ return 1;
+ }
+
+ /* can cache offset now. */
+ offset = state->offset;
+
+ switch (src[offset]) {
+ case '"':
+ return json_get_string_size(state, 0);
+ case '\'':
+ if (json_parse_flags_allow_single_quoted_strings & flags_bitset) {
+ return json_get_string_size(state, 0);
+ } else {
+ /* invalid value! */
+ state->error = json_parse_error_invalid_value;
+ return 1;
+ }
+ case '{':
+ return json_get_object_size(state, /* is_global_object = */ 0);
+ case '[':
+ return json_get_array_size(state);
+ case '-':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return json_get_number_size(state);
+ case '+':
+ if (json_parse_flags_allow_leading_plus_sign & flags_bitset) {
+ return json_get_number_size(state);
+ } else {
+ /* invalid value! */
+ state->error = json_parse_error_invalid_number_format;
+ return 1;
+ }
+ case '.':
+ if (json_parse_flags_allow_leading_or_trailing_decimal_point &
+ flags_bitset) {
+ return json_get_number_size(state);
+ } else {
+ /* invalid value! */
+ state->error = json_parse_error_invalid_number_format;
+ return 1;
+ }
+ default:
+ if ((offset + 4) <= size && 't' == src[offset + 0] &&
+ 'r' == src[offset + 1] && 'u' == src[offset + 2] &&
+ 'e' == src[offset + 3]) {
+ state->offset += 4;
+ return 0;
+ } else if ((offset + 5) <= size && 'f' == src[offset + 0] &&
+ 'a' == src[offset + 1] && 'l' == src[offset + 2] &&
+ 's' == src[offset + 3] && 'e' == src[offset + 4]) {
+ state->offset += 5;
+ return 0;
+ } else if ((offset + 4) <= size && 'n' == state->src[offset + 0] &&
+ 'u' == state->src[offset + 1] &&
+ 'l' == state->src[offset + 2] &&
+ 'l' == state->src[offset + 3]) {
+ state->offset += 4;
+ return 0;
+ } else if ((json_parse_flags_allow_inf_and_nan & flags_bitset) &&
+ (offset + 3) <= size && 'N' == src[offset + 0] &&
+ 'a' == src[offset + 1] && 'N' == src[offset + 2]) {
+ return json_get_number_size(state);
+ } else if ((json_parse_flags_allow_inf_and_nan & flags_bitset) &&
+ (offset + 8) <= size && 'I' == src[offset + 0] &&
+ 'n' == src[offset + 1] && 'f' == src[offset + 2] &&
+ 'i' == src[offset + 3] && 'n' == src[offset + 4] &&
+ 'i' == src[offset + 5] && 't' == src[offset + 6] &&
+ 'y' == src[offset + 7]) {
+ return json_get_number_size(state);
+ }
+
+ /* invalid value! */
+ state->error = json_parse_error_invalid_value;
+ return 1;
+ }
+ }
+}
+
+json_weak void json_parse_value(struct json_parse_state_s *state,
+ int is_global_object,
+ struct json_value_s *value);
+
+json_weak void json_parse_string(struct json_parse_state_s *state,
+ struct json_string_s *string);
+void json_parse_string(struct json_parse_state_s *state,
+ struct json_string_s *string) {
+ size_t offset = state->offset;
+ size_t bytes_written = 0;
+ const char *const src = state->src;
+ const char quote_to_use = '\'' == src[offset] ? '\'' : '"';
+ char *data = state->data;
+ unsigned long high_surrogate = 0;
+ unsigned long codepoint;
+
+ string->string = data;
+
+ /* skip leading '"' or '\''. */
+ offset++;
+
+ while (quote_to_use != src[offset]) {
+ if ('\\' == src[offset]) {
+ /* skip the reverse solidus. */
+ offset++;
+
+ switch (src[offset++]) {
+ default:
+ return; /* we cannot ever reach here. */
+ case 'u': {
+ codepoint = 0;
+ if (!json_hexadecimal_value(&src[offset], 4, &codepoint)) {
+ return; /* this shouldn't happen as the value was already validated.
+ */
+ }
+
+ offset += 4;
+
+ if (codepoint <= 0x7fu) {
+ data[bytes_written++] = (char)codepoint; /* 0xxxxxxx. */
+ } else if (codepoint <= 0x7ffu) {
+ data[bytes_written++] =
+ (char)(0xc0u | (codepoint >> 6)); /* 110xxxxx. */
+ data[bytes_written++] =
+ (char)(0x80u | (codepoint & 0x3fu)); /* 10xxxxxx. */
+ } else if (codepoint >= 0xd800 &&
+ codepoint <= 0xdbff) { /* high surrogate. */
+ high_surrogate = codepoint;
+ continue; /* we need the low half to form a complete codepoint. */
+ } else if (codepoint >= 0xdc00 &&
+ codepoint <= 0xdfff) { /* low surrogate. */
+ /* combine with the previously read half to obtain the complete
+ * codepoint. */
+ const unsigned long surrogate_offset =
+ 0x10000u - (0xD800u << 10) - 0xDC00u;
+ codepoint = (high_surrogate << 10) + codepoint + surrogate_offset;
+ high_surrogate = 0;
+ data[bytes_written++] =
+ (char)(0xF0u | (codepoint >> 18)); /* 11110xxx. */
+ data[bytes_written++] =
+ (char)(0x80u | ((codepoint >> 12) & 0x3fu)); /* 10xxxxxx. */
+ data[bytes_written++] =
+ (char)(0x80u | ((codepoint >> 6) & 0x3fu)); /* 10xxxxxx. */
+ data[bytes_written++] =
+ (char)(0x80u | (codepoint & 0x3fu)); /* 10xxxxxx. */
+ } else {
+ /* we assume the value was validated and thus is within the valid
+ * range. */
+ data[bytes_written++] =
+ (char)(0xe0u | (codepoint >> 12)); /* 1110xxxx. */
+ data[bytes_written++] =
+ (char)(0x80u | ((codepoint >> 6) & 0x3fu)); /* 10xxxxxx. */
+ data[bytes_written++] =
+ (char)(0x80u | (codepoint & 0x3fu)); /* 10xxxxxx. */
+ }
+ } break;
+ case '"':
+ data[bytes_written++] = '"';
+ break;
+ case '\\':
+ data[bytes_written++] = '\\';
+ break;
+ case '/':
+ data[bytes_written++] = '/';
+ break;
+ case 'b':
+ data[bytes_written++] = '\b';
+ break;
+ case 'f':
+ data[bytes_written++] = '\f';
+ break;
+ case 'n':
+ data[bytes_written++] = '\n';
+ break;
+ case 'r':
+ data[bytes_written++] = '\r';
+ break;
+ case 't':
+ data[bytes_written++] = '\t';
+ break;
+ case '\r':
+ data[bytes_written++] = '\r';
+
+ /* check if we have a "\r\n" sequence. */
+ if ('\n' == src[offset]) {
+ data[bytes_written++] = '\n';
+ offset++;
+ }
+
+ break;
+ case '\n':
+ data[bytes_written++] = '\n';
+ break;
+ }
+ } else {
+ /* copy the character. */
+ data[bytes_written++] = src[offset++];
+ }
+ }
+
+ /* skip trailing '"' or '\''. */
+ offset++;
+
+ /* record the size of the string. */
+ string->string_size = bytes_written;
+
+ /* add null terminator to string. */
+ data[bytes_written++] = '\0';
+
+ /* move data along. */
+ state->data += bytes_written;
+
+ /* update offset. */
+ state->offset = offset;
+}
+
+json_weak void json_parse_key(struct json_parse_state_s *state,
+ struct json_string_s *string);
+void json_parse_key(struct json_parse_state_s *state,
+ struct json_string_s *string) {
+ if (json_parse_flags_allow_unquoted_keys & state->flags_bitset) {
+ const char *const src = state->src;
+ char *const data = state->data;
+ size_t offset = state->offset;
+
+ /* if we are allowing unquoted keys, check for quoted anyway... */
+ if (('"' == src[offset]) || ('\'' == src[offset])) {
+ /* ... if we got a quote, just parse the key as a string as normal. */
+ json_parse_string(state, string);
+ } else {
+ size_t size = 0;
+
+ string->string = state->data;
+
+ while (is_valid_unquoted_key_char(src[offset])) {
+ data[size++] = src[offset++];
+ }
+
+ /* add null terminator to string. */
+ data[size] = '\0';
+
+ /* record the size of the string. */
+ string->string_size = size++;
+
+ /* move data along. */
+ state->data += size;
+
+ /* update offset. */
+ state->offset = offset;
+ }
+ } else {
+ /* we are only allowed to have quoted keys, so just parse a string! */
+ json_parse_string(state, string);
+ }
+}
+
+json_weak void json_parse_object(struct json_parse_state_s *state,
+ int is_global_object,
+ struct json_object_s *object);
+void json_parse_object(struct json_parse_state_s *state, int is_global_object,
+ struct json_object_s *object) {
+ const size_t flags_bitset = state->flags_bitset;
+ const size_t size = state->size;
+ const char *const src = state->src;
+ size_t elements = 0;
+ int allow_comma = 0;
+ struct json_object_element_s *previous = json_null;
+
+ if (is_global_object) {
+ /* if we skipped some whitespace, and then found an opening '{' of an. */
+ /* object, we actually have a normal JSON object at the root of the DOM...
+ */
+ if ('{' == src[state->offset]) {
+ /* . and we don't actually have a global object after all! */
+ is_global_object = 0;
+ }
+ }
+
+ if (!is_global_object) {
+ /* skip leading '{'. */
+ state->offset++;
+ }
+
+ (void)json_skip_all_skippables(state);
+
+ /* reset elements. */
+ elements = 0;
+
+ while (state->offset < size) {
+ struct json_object_element_s *element = json_null;
+ struct json_string_s *string = json_null;
+ struct json_value_s *value = json_null;
+
+ if (!is_global_object) {
+ (void)json_skip_all_skippables(state);
+
+ if ('}' == src[state->offset]) {
+ /* skip trailing '}'. */
+ state->offset++;
+
+ /* finished the object! */
+ break;
+ }
+ } else {
+ if (json_skip_all_skippables(state)) {
+ /* global object ends when the file ends! */
+ break;
+ }
+ }
+
+ /* if we parsed at least one element previously, grok for a comma. */
+ if (allow_comma) {
+ if (',' == src[state->offset]) {
+ /* skip comma. */
+ state->offset++;
+ allow_comma = 0;
+ continue;
+ }
+ }
+
+ element = (struct json_object_element_s *)state->dom;
+
+ state->dom += sizeof(struct json_object_element_s);
+
+ if (json_null == previous) {
+ /* this is our first element, so record it in our object. */
+ object->start = element;
+ } else {
+ previous->next = element;
+ }
+
+ previous = element;
+
+ if (json_parse_flags_allow_location_information & flags_bitset) {
+ struct json_string_ex_s *string_ex =
+ (struct json_string_ex_s *)state->dom;
+ state->dom += sizeof(struct json_string_ex_s);
+
+ string_ex->offset = state->offset;
+ string_ex->line_no = state->line_no;
+ string_ex->row_no = state->offset - state->line_offset;
+
+ string = &(string_ex->string);
+ } else {
+ string = (struct json_string_s *)state->dom;
+ state->dom += sizeof(struct json_string_s);
+ }
+
+ element->name = string;
+
+ (void)json_parse_key(state, string);
+
+ (void)json_skip_all_skippables(state);
+
+ /* skip colon or equals. */
+ state->offset++;
+
+ (void)json_skip_all_skippables(state);
+
+ if (json_parse_flags_allow_location_information & flags_bitset) {
+ struct json_value_ex_s *value_ex = (struct json_value_ex_s *)state->dom;
+ state->dom += sizeof(struct json_value_ex_s);
+
+ value_ex->offset = state->offset;
+ value_ex->line_no = state->line_no;
+ value_ex->row_no = state->offset - state->line_offset;
+
+ value = &(value_ex->value);
+ } else {
+ value = (struct json_value_s *)state->dom;
+ state->dom += sizeof(struct json_value_s);
+ }
+
+ element->value = value;
+
+ json_parse_value(state, /* is_global_object = */ 0, value);
+
+ /* successfully parsed a name/value pair! */
+ elements++;
+ allow_comma = 1;
+ }
+
+ /* if we had at least one element, end the linked list. */
+ if (previous) {
+ previous->next = json_null;
+ }
+
+ if (0 == elements) {
+ object->start = json_null;
+ }
+
+ object->length = elements;
+}
+
+json_weak void json_parse_array(struct json_parse_state_s *state,
+ struct json_array_s *array);
+void json_parse_array(struct json_parse_state_s *state,
+ struct json_array_s *array) {
+ const char *const src = state->src;
+ const size_t size = state->size;
+ size_t elements = 0;
+ int allow_comma = 0;
+ struct json_array_element_s *previous = json_null;
+
+ /* skip leading '['. */
+ state->offset++;
+
+ (void)json_skip_all_skippables(state);
+
+ /* reset elements. */
+ elements = 0;
+
+ do {
+ struct json_array_element_s *element = json_null;
+ struct json_value_s *value = json_null;
+
+ (void)json_skip_all_skippables(state);
+
+ if (']' == src[state->offset]) {
+ /* skip trailing ']'. */
+ state->offset++;
+
+ /* finished the array! */
+ break;
+ }
+
+ /* if we parsed at least one element previously, grok for a comma. */
+ if (allow_comma) {
+ if (',' == src[state->offset]) {
+ /* skip comma. */
+ state->offset++;
+ allow_comma = 0;
+ continue;
+ }
+ }
+
+ element = (struct json_array_element_s *)state->dom;
+
+ state->dom += sizeof(struct json_array_element_s);
+
+ if (json_null == previous) {
+ /* this is our first element, so record it in our array. */
+ array->start = element;
+ } else {
+ previous->next = element;
+ }
+
+ previous = element;
+
+ if (json_parse_flags_allow_location_information & state->flags_bitset) {
+ struct json_value_ex_s *value_ex = (struct json_value_ex_s *)state->dom;
+ state->dom += sizeof(struct json_value_ex_s);
+
+ value_ex->offset = state->offset;
+ value_ex->line_no = state->line_no;
+ value_ex->row_no = state->offset - state->line_offset;
+
+ value = &(value_ex->value);
+ } else {
+ value = (struct json_value_s *)state->dom;
+ state->dom += sizeof(struct json_value_s);
+ }
+
+ element->value = value;
+
+ json_parse_value(state, /* is_global_object = */ 0, value);
+
+ /* successfully parsed an array element! */
+ elements++;
+ allow_comma = 1;
+ } while (state->offset < size);
+
+ /* end the linked list. */
+ if (previous) {
+ previous->next = json_null;
+ }
+
+ if (0 == elements) {
+ array->start = json_null;
+ }
+
+ array->length = elements;
+}
+
+json_weak void json_parse_number(struct json_parse_state_s *state,
+ struct json_number_s *number);
+void json_parse_number(struct json_parse_state_s *state,
+ struct json_number_s *number) {
+ const size_t flags_bitset = state->flags_bitset;
+ size_t offset = state->offset;
+ const size_t size = state->size;
+ size_t bytes_written = 0;
+ const char *const src = state->src;
+ char *data = state->data;
+
+ number->number = data;
+
+ if (json_parse_flags_allow_hexadecimal_numbers & flags_bitset) {
+ if (('0' == src[offset]) &&
+ (('x' == src[offset + 1]) || ('X' == src[offset + 1]))) {
+ /* consume hexadecimal digits. */
+ while ((offset < size) &&
+ (('0' <= src[offset] && src[offset] <= '9') ||
+ ('a' <= src[offset] && src[offset] <= 'f') ||
+ ('A' <= src[offset] && src[offset] <= 'F') ||
+ ('x' == src[offset]) || ('X' == src[offset]))) {
+ data[bytes_written++] = src[offset++];
+ }
+ }
+ }
+
+ while (offset < size) {
+ int end = 0;
+
+ switch (src[offset]) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '.':
+ case 'e':
+ case 'E':
+ case '+':
+ case '-':
+ data[bytes_written++] = src[offset++];
+ break;
+ default:
+ end = 1;
+ break;
+ }
+
+ if (0 != end) {
+ break;
+ }
+ }
+
+ if (json_parse_flags_allow_inf_and_nan & flags_bitset) {
+ const size_t inf_strlen = 8; /* = strlen("Infinity");. */
+ const size_t nan_strlen = 3; /* = strlen("NaN");. */
+
+ if (offset + inf_strlen < size) {
+ if ('I' == src[offset]) {
+ size_t i;
+ /* We found our special 'Infinity' keyword! */
+ for (i = 0; i < inf_strlen; i++) {
+ data[bytes_written++] = src[offset++];
+ }
+ }
+ }
+
+ if (offset + nan_strlen < size) {
+ if ('N' == src[offset]) {
+ size_t i;
+ /* We found our special 'NaN' keyword! */
+ for (i = 0; i < nan_strlen; i++) {
+ data[bytes_written++] = src[offset++];
+ }
+ }
+ }
+ }
+
+ /* record the size of the number. */
+ number->number_size = bytes_written;
+ /* add null terminator to number string. */
+ data[bytes_written++] = '\0';
+ /* move data along. */
+ state->data += bytes_written;
+ /* update offset. */
+ state->offset = offset;
+}
+
+json_weak void json_parse_value(struct json_parse_state_s *state,
+ int is_global_object,
+ struct json_value_s *value);
+void json_parse_value(struct json_parse_state_s *state, int is_global_object,
+ struct json_value_s *value) {
+ const size_t flags_bitset = state->flags_bitset;
+ const char *const src = state->src;
+ const size_t size = state->size;
+ size_t offset;
+
+ (void)json_skip_all_skippables(state);
+
+ /* cache offset now. */
+ offset = state->offset;
+
+ if (is_global_object) {
+ value->type = json_type_object;
+ value->payload = state->dom;
+ state->dom += sizeof(struct json_object_s);
+ json_parse_object(state, /* is_global_object = */ 1,
+ (struct json_object_s *)value->payload);
+ } else {
+ switch (src[offset]) {
+ case '"':
+ case '\'':
+ value->type = json_type_string;
+ value->payload = state->dom;
+ state->dom += sizeof(struct json_string_s);
+ json_parse_string(state, (struct json_string_s *)value->payload);
+ break;
+ case '{':
+ value->type = json_type_object;
+ value->payload = state->dom;
+ state->dom += sizeof(struct json_object_s);
+ json_parse_object(state, /* is_global_object = */ 0,
+ (struct json_object_s *)value->payload);
+ break;
+ case '[':
+ value->type = json_type_array;
+ value->payload = state->dom;
+ state->dom += sizeof(struct json_array_s);
+ json_parse_array(state, (struct json_array_s *)value->payload);
+ break;
+ case '-':
+ case '+':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '.':
+ value->type = json_type_number;
+ value->payload = state->dom;
+ state->dom += sizeof(struct json_number_s);
+ json_parse_number(state, (struct json_number_s *)value->payload);
+ break;
+ default:
+ if ((offset + 4) <= size && 't' == src[offset + 0] &&
+ 'r' == src[offset + 1] && 'u' == src[offset + 2] &&
+ 'e' == src[offset + 3]) {
+ value->type = json_type_true;
+ value->payload = json_null;
+ state->offset += 4;
+ } else if ((offset + 5) <= size && 'f' == src[offset + 0] &&
+ 'a' == src[offset + 1] && 'l' == src[offset + 2] &&
+ 's' == src[offset + 3] && 'e' == src[offset + 4]) {
+ value->type = json_type_false;
+ value->payload = json_null;
+ state->offset += 5;
+ } else if ((offset + 4) <= size && 'n' == src[offset + 0] &&
+ 'u' == src[offset + 1] && 'l' == src[offset + 2] &&
+ 'l' == src[offset + 3]) {
+ value->type = json_type_null;
+ value->payload = json_null;
+ state->offset += 4;
+ } else if ((json_parse_flags_allow_inf_and_nan & flags_bitset) &&
+ (offset + 3) <= size && 'N' == src[offset + 0] &&
+ 'a' == src[offset + 1] && 'N' == src[offset + 2]) {
+ value->type = json_type_number;
+ value->payload = state->dom;
+ state->dom += sizeof(struct json_number_s);
+ json_parse_number(state, (struct json_number_s *)value->payload);
+ } else if ((json_parse_flags_allow_inf_and_nan & flags_bitset) &&
+ (offset + 8) <= size && 'I' == src[offset + 0] &&
+ 'n' == src[offset + 1] && 'f' == src[offset + 2] &&
+ 'i' == src[offset + 3] && 'n' == src[offset + 4] &&
+ 'i' == src[offset + 5] && 't' == src[offset + 6] &&
+ 'y' == src[offset + 7]) {
+ value->type = json_type_number;
+ value->payload = state->dom;
+ state->dom += sizeof(struct json_number_s);
+ json_parse_number(state, (struct json_number_s *)value->payload);
+ }
+ break;
+ }
+ }
+}
+
+struct json_value_s *
+json_parse_ex(const void *src, size_t src_size, size_t flags_bitset,
+ void *(*alloc_func_ptr)(void *user_data, size_t size),
+ void *user_data, struct json_parse_result_s *result) {
+ struct json_parse_state_s state;
+ void *allocation;
+ struct json_value_s *value;
+ size_t total_size;
+ int input_error;
+
+ if (result) {
+ result->error = json_parse_error_none;
+ result->error_offset = 0;
+ result->error_line_no = 0;
+ result->error_row_no = 0;
+ }
+
+ if (json_null == src) {
+ /* invalid src pointer was null! */
+ return json_null;
+ }
+
+ state.src = (const char *)src;
+ state.size = src_size;
+ state.offset = 0;
+ state.line_no = 1;
+ state.line_offset = 0;
+ state.error = json_parse_error_none;
+ state.dom_size = 0;
+ state.data_size = 0;
+ state.flags_bitset = flags_bitset;
+
+ input_error = json_get_value_size(
+ &state, (int)(json_parse_flags_allow_global_object & state.flags_bitset));
+
+ if (0 == input_error) {
+ json_skip_all_skippables(&state);
+
+ if (state.offset != state.size) {
+ /* our parsing didn't have an error, but there are characters remaining in
+ * the input that weren't part of the JSON! */
+
+ state.error = json_parse_error_unexpected_trailing_characters;
+ input_error = 1;
+ }
+ }
+
+ if (input_error) {
+ /* parsing value's size failed (most likely an invalid JSON DOM!). */
+ if (result) {
+ result->error = state.error;
+ result->error_offset = state.offset;
+ result->error_line_no = state.line_no;
+ result->error_row_no = state.offset - state.line_offset;
+ }
+ return json_null;
+ }
+
+ /* our total allocation is the combination of the dom and data sizes (we. */
+ /* first encode the structure of the JSON, and then the data referenced by. */
+ /* the JSON values). */
+ total_size = state.dom_size + state.data_size;
+
+ if (json_null == alloc_func_ptr) {
+ allocation = malloc(total_size);
+ } else {
+ allocation = alloc_func_ptr(user_data, total_size);
+ }
+
+ if (json_null == allocation) {
+ /* malloc failed! */
+ if (result) {
+ result->error = json_parse_error_allocator_failed;
+ result->error_offset = 0;
+ result->error_line_no = 0;
+ result->error_row_no = 0;
+ }
+
+ return json_null;
+ }
+
+ /* reset offset so we can reuse it. */
+ state.offset = 0;
+
+ /* reset the line information so we can reuse it. */
+ state.line_no = 1;
+ state.line_offset = 0;
+
+ state.dom = (char *)allocation;
+ state.data = state.dom + state.dom_size;
+
+ if (json_parse_flags_allow_location_information & state.flags_bitset) {
+ struct json_value_ex_s *value_ex = (struct json_value_ex_s *)state.dom;
+ state.dom += sizeof(struct json_value_ex_s);
+
+ value_ex->offset = state.offset;
+ value_ex->line_no = state.line_no;
+ value_ex->row_no = state.offset - state.line_offset;
+
+ value = &(value_ex->value);
+ } else {
+ value = (struct json_value_s *)state.dom;
+ state.dom += sizeof(struct json_value_s);
+ }
+
+ json_parse_value(
+ &state, (int)(json_parse_flags_allow_global_object & state.flags_bitset),
+ value);
+
+ return (struct json_value_s *)allocation;
+}
+
+struct json_value_s *json_parse(const void *src, size_t src_size) {
+ return json_parse_ex(src, src_size, json_parse_flags_default, json_null,
+ json_null, json_null);
+}
+
+struct json_extract_result_s {
+ size_t dom_size;
+ size_t data_size;
+};
+
+struct json_value_s *json_extract_value(const struct json_value_s *value) {
+ return json_extract_value_ex(value, json_null, json_null);
+}
+
+json_weak struct json_extract_result_s
+json_extract_get_number_size(const struct json_number_s *const number);
+json_weak struct json_extract_result_s
+json_extract_get_string_size(const struct json_string_s *const string);
+json_weak struct json_extract_result_s
+json_extract_get_object_size(const struct json_object_s *const object);
+json_weak struct json_extract_result_s
+json_extract_get_array_size(const struct json_array_s *const array);
+json_weak struct json_extract_result_s
+json_extract_get_value_size(const struct json_value_s *const value);
+
+struct json_extract_result_s
+json_extract_get_number_size(const struct json_number_s *const number) {
+ struct json_extract_result_s result;
+ result.dom_size = sizeof(struct json_number_s);
+ result.data_size = number->number_size;
+ return result;
+}
+
+struct json_extract_result_s
+json_extract_get_string_size(const struct json_string_s *const string) {
+ struct json_extract_result_s result;
+ result.dom_size = sizeof(struct json_string_s);
+ result.data_size = string->string_size + 1;
+ return result;
+}
+
+struct json_extract_result_s
+json_extract_get_object_size(const struct json_object_s *const object) {
+ struct json_extract_result_s result;
+ size_t i;
+ const struct json_object_element_s *element = object->start;
+
+ result.dom_size = sizeof(struct json_object_s) +
+ (sizeof(struct json_object_element_s) * object->length);
+ result.data_size = 0;
+
+ for (i = 0; i < object->length; i++) {
+ const struct json_extract_result_s string_result =
+ json_extract_get_string_size(element->name);
+ const struct json_extract_result_s value_result =
+ json_extract_get_value_size(element->value);
+
+ result.dom_size += string_result.dom_size;
+ result.data_size += string_result.data_size;
+
+ result.dom_size += value_result.dom_size;
+ result.data_size += value_result.data_size;
+
+ element = element->next;
+ }
+
+ return result;
+}
+
+struct json_extract_result_s
+json_extract_get_array_size(const struct json_array_s *const array) {
+ struct json_extract_result_s result;
+ size_t i;
+ const struct json_array_element_s *element = array->start;
+
+ result.dom_size = sizeof(struct json_array_s) +
+ (sizeof(struct json_array_element_s) * array->length);
+ result.data_size = 0;
+
+ for (i = 0; i < array->length; i++) {
+ const struct json_extract_result_s value_result =
+ json_extract_get_value_size(element->value);
+
+ result.dom_size += value_result.dom_size;
+ result.data_size += value_result.data_size;
+
+ element = element->next;
+ }
+
+ return result;
+}
+
+struct json_extract_result_s
+json_extract_get_value_size(const struct json_value_s *const value) {
+ struct json_extract_result_s result = {0, 0};
+
+ switch (value->type) {
+ default:
+ break;
+ case json_type_object:
+ result = json_extract_get_object_size(
+ (const struct json_object_s *)value->payload);
+ break;
+ case json_type_array:
+ result = json_extract_get_array_size(
+ (const struct json_array_s *)value->payload);
+ break;
+ case json_type_number:
+ result = json_extract_get_number_size(
+ (const struct json_number_s *)value->payload);
+ break;
+ case json_type_string:
+ result = json_extract_get_string_size(
+ (const struct json_string_s *)value->payload);
+ break;
+ }
+
+ result.dom_size += sizeof(struct json_value_s);
+
+ return result;
+}
+
+struct json_extract_state_s {
+ char *dom;
+ char *data;
+};
+
+json_weak void json_extract_copy_value(struct json_extract_state_s *const state,
+ const struct json_value_s *const value);
+void json_extract_copy_value(struct json_extract_state_s *const state,
+ const struct json_value_s *const value) {
+ struct json_string_s *string;
+ struct json_number_s *number;
+ struct json_object_s *object;
+ struct json_array_s *array;
+ struct json_value_s *new_value;
+
+ memcpy(state->dom, value, sizeof(struct json_value_s));
+ new_value = (struct json_value_s *)state->dom;
+ state->dom += sizeof(struct json_value_s);
+ new_value->payload = state->dom;
+
+ if (json_type_string == value->type) {
+ memcpy(state->dom, value->payload, sizeof(struct json_string_s));
+ string = (struct json_string_s *)state->dom;
+ state->dom += sizeof(struct json_string_s);
+
+ memcpy(state->data, string->string, string->string_size + 1);
+ string->string = state->data;
+ state->data += string->string_size + 1;
+ } else if (json_type_number == value->type) {
+ memcpy(state->dom, value->payload, sizeof(struct json_number_s));
+ number = (struct json_number_s *)state->dom;
+ state->dom += sizeof(struct json_number_s);
+
+ memcpy(state->data, number->number, number->number_size);
+ number->number = state->data;
+ state->data += number->number_size;
+ } else if (json_type_object == value->type) {
+ struct json_object_element_s *element;
+ size_t i;
+
+ memcpy(state->dom, value->payload, sizeof(struct json_object_s));
+ object = (struct json_object_s *)state->dom;
+ state->dom += sizeof(struct json_object_s);
+
+ element = object->start;
+ object->start = (struct json_object_element_s *)state->dom;
+
+ for (i = 0; i < object->length; i++) {
+ struct json_value_s *previous_value;
+ struct json_object_element_s *previous_element;
+
+ memcpy(state->dom, element, sizeof(struct json_object_element_s));
+ element = (struct json_object_element_s *)state->dom;
+ state->dom += sizeof(struct json_object_element_s);
+
+ string = element->name;
+ memcpy(state->dom, string, sizeof(struct json_string_s));
+ string = (struct json_string_s *)state->dom;
+ state->dom += sizeof(struct json_string_s);
+ element->name = string;
+
+ memcpy(state->data, string->string, string->string_size + 1);
+ string->string = state->data;
+ state->data += string->string_size + 1;
+
+ previous_value = element->value;
+ element->value = (struct json_value_s *)state->dom;
+ json_extract_copy_value(state, previous_value);
+
+ previous_element = element;
+ element = element->next;
+
+ if (element) {
+ previous_element->next = (struct json_object_element_s *)state->dom;
+ }
+ }
+ } else if (json_type_array == value->type) {
+ struct json_array_element_s *element;
+ size_t i;
+
+ memcpy(state->dom, value->payload, sizeof(struct json_array_s));
+ array = (struct json_array_s *)state->dom;
+ state->dom += sizeof(struct json_array_s);
+
+ element = array->start;
+ array->start = (struct json_array_element_s *)state->dom;
+
+ for (i = 0; i < array->length; i++) {
+ struct json_value_s *previous_value;
+ struct json_array_element_s *previous_element;
+
+ memcpy(state->dom, element, sizeof(struct json_array_element_s));
+ element = (struct json_array_element_s *)state->dom;
+ state->dom += sizeof(struct json_array_element_s);
+
+ previous_value = element->value;
+ element->value = (struct json_value_s *)state->dom;
+ json_extract_copy_value(state, previous_value);
+
+ previous_element = element;
+ element = element->next;
+
+ if (element) {
+ previous_element->next = (struct json_array_element_s *)state->dom;
+ }
+ }
+ }
+}
+
+struct json_value_s *json_extract_value_ex(const struct json_value_s *value,
+ void *(*alloc_func_ptr)(void *,
+ size_t),
+ void *user_data) {
+ void *allocation;
+ struct json_extract_result_s result;
+ struct json_extract_state_s state;
+ size_t total_size;
+
+ if (json_null == value) {
+ /* invalid value was null! */
+ return json_null;
+ }
+
+ result = json_extract_get_value_size(value);
+ total_size = result.dom_size + result.data_size;
+
+ if (json_null == alloc_func_ptr) {
+ allocation = malloc(total_size);
+ } else {
+ allocation = alloc_func_ptr(user_data, total_size);
+ }
+
+ state.dom = (char *)allocation;
+ state.data = state.dom + result.dom_size;
+
+ json_extract_copy_value(&state, value);
+
+ return (struct json_value_s *)allocation;
+}
+
+struct json_string_s *json_value_as_string(struct json_value_s *const value) {
+ if (value->type != json_type_string) {
+ return json_null;
+ }
+
+ return (struct json_string_s *)value->payload;
+}
+
+struct json_number_s *json_value_as_number(struct json_value_s *const value) {
+ if (value->type != json_type_number) {
+ return json_null;
+ }
+
+ return (struct json_number_s *)value->payload;
+}
+
+struct json_object_s *json_value_as_object(struct json_value_s *const value) {
+ if (value->type != json_type_object) {
+ return json_null;
+ }
+
+ return (struct json_object_s *)value->payload;
+}
+
+struct json_array_s *json_value_as_array(struct json_value_s *const value) {
+ if (value->type != json_type_array) {
+ return json_null;
+ }
+
+ return (struct json_array_s *)value->payload;
+}
+
+int json_value_is_true(const struct json_value_s *const value) {
+ return value->type == json_type_true;
+}
+
+int json_value_is_false(const struct json_value_s *const value) {
+ return value->type == json_type_false;
+}
+
+int json_value_is_null(const struct json_value_s *const value) {
+ return value->type == json_type_null;
+}
+
+json_weak int
+json_write_minified_get_value_size(const struct json_value_s *value,
+ size_t *size);
+
+json_weak int json_write_get_number_size(const struct json_number_s *number,
+ size_t *size);
+int json_write_get_number_size(const struct json_number_s *number,
+ size_t *size) {
+ json_uintmax_t parsed_number;
+ size_t i;
+
+ if (number->number_size >= 2) {
+ switch (number->number[1]) {
+ default:
+ break;
+ case 'x':
+ case 'X':
+ /* the number is a json_parse_flags_allow_hexadecimal_numbers hexadecimal
+ * so we have to do extra work to convert it to a non-hexadecimal for JSON
+ * output. */
+ parsed_number = json_strtoumax(number->number, json_null, 0);
+
+ i = 0;
+
+ while (0 != parsed_number) {
+ parsed_number /= 10;
+ i++;
+ }
+
+ *size += i;
+ return 0;
+ }
+ }
+
+ /* check to see if the number has leading/trailing decimal point. */
+ i = 0;
+
+ /* skip any leading '+' or '-'. */
+ if ((i < number->number_size) &&
+ (('+' == number->number[i]) || ('-' == number->number[i]))) {
+ i++;
+ }
+
+ /* check if we have infinity. */
+ if ((i < number->number_size) && ('I' == number->number[i])) {
+ const char *inf = "Infinity";
+ size_t k;
+
+ for (k = i; k < number->number_size; k++) {
+ const char c = *inf++;
+
+ /* Check if we found the Infinity string! */
+ if ('\0' == c) {
+ break;
+ } else if (c != number->number[k]) {
+ break;
+ }
+ }
+
+ if ('\0' == *inf) {
+ /* Inf becomes 1.7976931348623158e308 because JSON can't support it. */
+ *size += 22;
+
+ /* if we had a leading '-' we need to record it in the JSON output. */
+ if ('-' == number->number[0]) {
+ *size += 1;
+ }
+ }
+
+ return 0;
+ }
+
+ /* check if we have nan. */
+ if ((i < number->number_size) && ('N' == number->number[i])) {
+ const char *nan = "NaN";
+ size_t k;
+
+ for (k = i; k < number->number_size; k++) {
+ const char c = *nan++;
+
+ /* Check if we found the NaN string! */
+ if ('\0' == c) {
+ break;
+ } else if (c != number->number[k]) {
+ break;
+ }
+ }
+
+ if ('\0' == *nan) {
+ /* NaN becomes 1 because JSON can't support it. */
+ *size += 1;
+
+ return 0;
+ }
+ }
+
+ /* if we had a leading decimal point. */
+ if ((i < number->number_size) && ('.' == number->number[i])) {
+ /* 1 + because we had a leading decimal point. */
+ *size += 1;
+ goto cleanup;
+ }
+
+ for (; i < number->number_size; i++) {
+ const char c = number->number[i];
+ if (!('0' <= c && c <= '9')) {
+ break;
+ }
+ }
+
+ /* if we had a trailing decimal point. */
+ if ((i + 1 == number->number_size) && ('.' == number->number[i])) {
+ /* 1 + because we had a trailing decimal point. */
+ *size += 1;
+ goto cleanup;
+ }
+
+cleanup:
+ *size += number->number_size; /* the actual string of the number. */
+
+ /* if we had a leading '+' we don't record it in the JSON output. */
+ if ('+' == number->number[0]) {
+ *size -= 1;
+ }
+
+ return 0;
+}
+
+json_weak int json_write_get_string_size(const struct json_string_s *string,
+ size_t *size);
+int json_write_get_string_size(const struct json_string_s *string,
+ size_t *size) {
+ size_t i;
+ for (i = 0; i < string->string_size; i++) {
+ switch (string->string[i]) {
+ case '"':
+ case '\\':
+ case '\b':
+ case '\f':
+ case '\n':
+ case '\r':
+ case '\t':
+ *size += 2;
+ break;
+ default:
+ *size += 1;
+ break;
+ }
+ }
+
+ *size += 2; /* need to encode the surrounding '"' characters. */
+
+ return 0;
+}
+
+json_weak int
+json_write_minified_get_array_size(const struct json_array_s *array,
+ size_t *size);
+int json_write_minified_get_array_size(const struct json_array_s *array,
+ size_t *size) {
+ struct json_array_element_s *element;
+
+ *size += 2; /* '[' and ']'. */
+
+ if (1 < array->length) {
+ *size += array->length - 1; /* ','s seperate each element. */
+ }
+
+ for (element = array->start; json_null != element; element = element->next) {
+ if (json_write_minified_get_value_size(element->value, size)) {
+ /* value was malformed! */
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+json_weak int
+json_write_minified_get_object_size(const struct json_object_s *object,
+ size_t *size);
+int json_write_minified_get_object_size(const struct json_object_s *object,
+ size_t *size) {
+ struct json_object_element_s *element;
+
+ *size += 2; /* '{' and '}'. */
+
+ *size += object->length; /* ':'s seperate each name/value pair. */
+
+ if (1 < object->length) {
+ *size += object->length - 1; /* ','s seperate each element. */
+ }
+
+ for (element = object->start; json_null != element; element = element->next) {
+ if (json_write_get_string_size(element->name, size)) {
+ /* string was malformed! */
+ return 1;
+ }
+
+ if (json_write_minified_get_value_size(element->value, size)) {
+ /* value was malformed! */
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+json_weak int
+json_write_minified_get_value_size(const struct json_value_s *value,
+ size_t *size);
+int json_write_minified_get_value_size(const struct json_value_s *value,
+ size_t *size) {
+ switch (value->type) {
+ default:
+ /* unknown value type found! */
+ return 1;
+ case json_type_number:
+ return json_write_get_number_size((struct json_number_s *)value->payload,
+ size);
+ case json_type_string:
+ return json_write_get_string_size((struct json_string_s *)value->payload,
+ size);
+ case json_type_array:
+ return json_write_minified_get_array_size(
+ (struct json_array_s *)value->payload, size);
+ case json_type_object:
+ return json_write_minified_get_object_size(
+ (struct json_object_s *)value->payload, size);
+ case json_type_true:
+ *size += 4; /* the string "true". */
+ return 0;
+ case json_type_false:
+ *size += 5; /* the string "false". */
+ return 0;
+ case json_type_null:
+ *size += 4; /* the string "null". */
+ return 0;
+ }
+}
+
+json_weak char *json_write_minified_value(const struct json_value_s *value,
+ char *data);
+
+json_weak char *json_write_number(const struct json_number_s *number,
+ char *data);
+char *json_write_number(const struct json_number_s *number, char *data) {
+ json_uintmax_t parsed_number, backup;
+ size_t i;
+
+ if (number->number_size >= 2) {
+ switch (number->number[1]) {
+ default:
+ break;
+ case 'x':
+ case 'X':
+ /* The number is a json_parse_flags_allow_hexadecimal_numbers hexadecimal
+ * so we have to do extra work to convert it to a non-hexadecimal for JSON
+ * output. */
+ parsed_number = json_strtoumax(number->number, json_null, 0);
+
+ /* We need a copy of parsed number twice, so take a backup of it. */
+ backup = parsed_number;
+
+ i = 0;
+
+ while (0 != parsed_number) {
+ parsed_number /= 10;
+ i++;
+ }
+
+ /* Restore parsed_number to its original value stored in the backup. */
+ parsed_number = backup;
+
+ /* Now use backup to take a copy of i, or the length of the string. */
+ backup = i;
+
+ do {
+ *(data + i - 1) = '0' + (char)(parsed_number % 10);
+ parsed_number /= 10;
+ i--;
+ } while (0 != parsed_number);
+
+ data += backup;
+
+ return data;
+ }
+ }
+
+ /* check to see if the number has leading/trailing decimal point. */
+ i = 0;
+
+ /* skip any leading '-'. */
+ if ((i < number->number_size) &&
+ (('+' == number->number[i]) || ('-' == number->number[i]))) {
+ i++;
+ }
+
+ /* check if we have infinity. */
+ if ((i < number->number_size) && ('I' == number->number[i])) {
+ const char *inf = "Infinity";
+ size_t k;
+
+ for (k = i; k < number->number_size; k++) {
+ const char c = *inf++;
+
+ /* Check if we found the Infinity string! */
+ if ('\0' == c) {
+ break;
+ } else if (c != number->number[k]) {
+ break;
+ }
+ }
+
+ if ('\0' == *inf++) {
+ const char *dbl_max;
+
+ /* if we had a leading '-' we need to record it in the JSON output. */
+ if ('-' == number->number[0]) {
+ *data++ = '-';
+ }
+
+ /* Inf becomes 1.7976931348623158e308 because JSON can't support it. */
+ for (dbl_max = "1.7976931348623158e308"; '\0' != *dbl_max; dbl_max++) {
+ *data++ = *dbl_max;
+ }
+
+ return data;
+ }
+ }
+
+ /* check if we have nan. */
+ if ((i < number->number_size) && ('N' == number->number[i])) {
+ const char *nan = "NaN";
+ size_t k;
+
+ for (k = i; k < number->number_size; k++) {
+ const char c = *nan++;
+
+ /* Check if we found the NaN string! */
+ if ('\0' == c) {
+ break;
+ } else if (c != number->number[k]) {
+ break;
+ }
+ }
+
+ if ('\0' == *nan++) {
+ /* NaN becomes 0 because JSON can't support it. */
+ *data++ = '0';
+ return data;
+ }
+ }
+
+ /* if we had a leading decimal point. */
+ if ((i < number->number_size) && ('.' == number->number[i])) {
+ i = 0;
+
+ /* skip any leading '+'. */
+ if ('+' == number->number[i]) {
+ i++;
+ }
+
+ /* output the leading '-' if we had one. */
+ if ('-' == number->number[i]) {
+ *data++ = '-';
+ i++;
+ }
+
+ /* insert a '0' to fix the leading decimal point for JSON output. */
+ *data++ = '0';
+
+ /* and output the rest of the number as normal. */
+ for (; i < number->number_size; i++) {
+ *data++ = number->number[i];
+ }
+
+ return data;
+ }
+
+ for (; i < number->number_size; i++) {
+ const char c = number->number[i];
+ if (!('0' <= c && c <= '9')) {
+ break;
+ }
+ }
+
+ /* if we had a trailing decimal point. */
+ if ((i + 1 == number->number_size) && ('.' == number->number[i])) {
+ i = 0;
+
+ /* skip any leading '+'. */
+ if ('+' == number->number[i]) {
+ i++;
+ }
+
+ /* output the leading '-' if we had one. */
+ if ('-' == number->number[i]) {
+ *data++ = '-';
+ i++;
+ }
+
+ /* and output the rest of the number as normal. */
+ for (; i < number->number_size; i++) {
+ *data++ = number->number[i];
+ }
+
+ /* insert a '0' to fix the trailing decimal point for JSON output. */
+ *data++ = '0';
+
+ return data;
+ }
+
+ i = 0;
+
+ /* skip any leading '+'. */
+ if ('+' == number->number[i]) {
+ i++;
+ }
+
+ for (; i < number->number_size; i++) {
+ *data++ = number->number[i];
+ }
+
+ return data;
+}
+
+json_weak char *json_write_string(const struct json_string_s *string,
+ char *data);
+char *json_write_string(const struct json_string_s *string, char *data) {
+ size_t i;
+
+ *data++ = '"'; /* open the string. */
+
+ for (i = 0; i < string->string_size; i++) {
+ switch (string->string[i]) {
+ case '"':
+ *data++ = '\\'; /* escape the control character. */
+ *data++ = '"';
+ break;
+ case '\\':
+ *data++ = '\\'; /* escape the control character. */
+ *data++ = '\\';
+ break;
+ case '\b':
+ *data++ = '\\'; /* escape the control character. */
+ *data++ = 'b';
+ break;
+ case '\f':
+ *data++ = '\\'; /* escape the control character. */
+ *data++ = 'f';
+ break;
+ case '\n':
+ *data++ = '\\'; /* escape the control character. */
+ *data++ = 'n';
+ break;
+ case '\r':
+ *data++ = '\\'; /* escape the control character. */
+ *data++ = 'r';
+ break;
+ case '\t':
+ *data++ = '\\'; /* escape the control character. */
+ *data++ = 't';
+ break;
+ default:
+ *data++ = string->string[i];
+ break;
+ }
+ }
+
+ *data++ = '"'; /* close the string. */
+
+ return data;
+}
+
+json_weak char *json_write_minified_array(const struct json_array_s *array,
+ char *data);
+char *json_write_minified_array(const struct json_array_s *array, char *data) {
+ struct json_array_element_s *element = json_null;
+
+ *data++ = '['; /* open the array. */
+
+ for (element = array->start; json_null != element; element = element->next) {
+ if (element != array->start) {
+ *data++ = ','; /* ','s seperate each element. */
+ }
+
+ data = json_write_minified_value(element->value, data);
+
+ if (json_null == data) {
+ /* value was malformed! */
+ return json_null;
+ }
+ }
+
+ *data++ = ']'; /* close the array. */
+
+ return data;
+}
+
+json_weak char *json_write_minified_object(const struct json_object_s *object,
+ char *data);
+char *json_write_minified_object(const struct json_object_s *object,
+ char *data) {
+ struct json_object_element_s *element = json_null;
+
+ *data++ = '{'; /* open the object. */
+
+ for (element = object->start; json_null != element; element = element->next) {
+ if (element != object->start) {
+ *data++ = ','; /* ','s seperate each element. */
+ }
+
+ data = json_write_string(element->name, data);
+
+ if (json_null == data) {
+ /* string was malformed! */
+ return json_null;
+ }
+
+ *data++ = ':'; /* ':'s seperate each name/value pair. */
+
+ data = json_write_minified_value(element->value, data);
+
+ if (json_null == data) {
+ /* value was malformed! */
+ return json_null;
+ }
+ }
+
+ *data++ = '}'; /* close the object. */
+
+ return data;
+}
+
+json_weak char *json_write_minified_value(const struct json_value_s *value,
+ char *data);
+char *json_write_minified_value(const struct json_value_s *value, char *data) {
+ switch (value->type) {
+ default:
+ /* unknown value type found! */
+ return json_null;
+ case json_type_number:
+ return json_write_number((struct json_number_s *)value->payload, data);
+ case json_type_string:
+ return json_write_string((struct json_string_s *)value->payload, data);
+ case json_type_array:
+ return json_write_minified_array((struct json_array_s *)value->payload,
+ data);
+ case json_type_object:
+ return json_write_minified_object((struct json_object_s *)value->payload,
+ data);
+ case json_type_true:
+ data[0] = 't';
+ data[1] = 'r';
+ data[2] = 'u';
+ data[3] = 'e';
+ return data + 4;
+ case json_type_false:
+ data[0] = 'f';
+ data[1] = 'a';
+ data[2] = 'l';
+ data[3] = 's';
+ data[4] = 'e';
+ return data + 5;
+ case json_type_null:
+ data[0] = 'n';
+ data[1] = 'u';
+ data[2] = 'l';
+ data[3] = 'l';
+ return data + 4;
+ }
+}
+
+void *json_write_minified(const struct json_value_s *value, size_t *out_size) {
+ size_t size = 0;
+ char *data = json_null;
+ char *data_end = json_null;
+
+ if (json_null == value) {
+ return json_null;
+ }
+
+ if (json_write_minified_get_value_size(value, &size)) {
+ /* value was malformed! */
+ return json_null;
+ }
+
+ size += 1; /* for the '\0' null terminating character. */
+
+ data = (char *)malloc(size);
+
+ if (json_null == data) {
+ /* malloc failed! */
+ return json_null;
+ }
+
+ data_end = json_write_minified_value(value, data);
+
+ if (json_null == data_end) {
+ /* bad chi occurred! */
+ free(data);
+ return json_null;
+ }
+
+ /* null terminated the string. */
+ *data_end = '\0';
+
+ if (json_null != out_size) {
+ *out_size = size;
+ }
+
+ return data;
+}
+
+json_weak int json_write_pretty_get_value_size(const struct json_value_s *value,
+ size_t depth, size_t indent_size,
+ size_t newline_size,
+ size_t *size);
+
+json_weak int json_write_pretty_get_array_size(const struct json_array_s *array,
+ size_t depth, size_t indent_size,
+ size_t newline_size,
+ size_t *size);
+int json_write_pretty_get_array_size(const struct json_array_s *array,
+ size_t depth, size_t indent_size,
+ size_t newline_size, size_t *size) {
+ struct json_array_element_s *element;
+
+ *size += 1; /* '['. */
+
+ if (0 < array->length) {
+ /* if we have any elements we need to add a newline after our '['. */
+ *size += newline_size;
+
+ *size += array->length - 1; /* ','s seperate each element. */
+
+ for (element = array->start; json_null != element;
+ element = element->next) {
+ /* each element gets an indent. */
+ *size += (depth + 1) * indent_size;
+
+ if (json_write_pretty_get_value_size(element->value, depth + 1,
+ indent_size, newline_size, size)) {
+ /* value was malformed! */
+ return 1;
+ }
+
+ /* each element gets a newline too. */
+ *size += newline_size;
+ }
+
+ /* since we wrote out some elements, need to add a newline and indentation.
+ */
+ /* to the trailing ']'. */
+ *size += depth * indent_size;
+ }
+
+ *size += 1; /* ']'. */
+
+ return 0;
+}
+
+json_weak int
+json_write_pretty_get_object_size(const struct json_object_s *object,
+ size_t depth, size_t indent_size,
+ size_t newline_size, size_t *size);
+int json_write_pretty_get_object_size(const struct json_object_s *object,
+ size_t depth, size_t indent_size,
+ size_t newline_size, size_t *size) {
+ struct json_object_element_s *element;
+
+ *size += 1; /* '{'. */
+
+ if (0 < object->length) {
+ *size += newline_size; /* need a newline next. */
+
+ *size += object->length - 1; /* ','s seperate each element. */
+
+ for (element = object->start; json_null != element;
+ element = element->next) {
+ /* each element gets an indent and newline. */
+ *size += (depth + 1) * indent_size;
+ *size += newline_size;
+
+ if (json_write_get_string_size(element->name, size)) {
+ /* string was malformed! */
+ return 1;
+ }
+
+ *size += 3; /* seperate each name/value pair with " : ". */
+
+ if (json_write_pretty_get_value_size(element->value, depth + 1,
+ indent_size, newline_size, size)) {
+ /* value was malformed! */
+ return 1;
+ }
+ }
+
+ *size += depth * indent_size;
+ }
+
+ *size += 1; /* '}'. */
+
+ return 0;
+}
+
+json_weak int json_write_pretty_get_value_size(const struct json_value_s *value,
+ size_t depth, size_t indent_size,
+ size_t newline_size,
+ size_t *size);
+int json_write_pretty_get_value_size(const struct json_value_s *value,
+ size_t depth, size_t indent_size,
+ size_t newline_size, size_t *size) {
+ switch (value->type) {
+ default:
+ /* unknown value type found! */
+ return 1;
+ case json_type_number:
+ return json_write_get_number_size((struct json_number_s *)value->payload,
+ size);
+ case json_type_string:
+ return json_write_get_string_size((struct json_string_s *)value->payload,
+ size);
+ case json_type_array:
+ return json_write_pretty_get_array_size(
+ (struct json_array_s *)value->payload, depth, indent_size, newline_size,
+ size);
+ case json_type_object:
+ return json_write_pretty_get_object_size(
+ (struct json_object_s *)value->payload, depth, indent_size,
+ newline_size, size);
+ case json_type_true:
+ *size += 4; /* the string "true". */
+ return 0;
+ case json_type_false:
+ *size += 5; /* the string "false". */
+ return 0;
+ case json_type_null:
+ *size += 4; /* the string "null". */
+ return 0;
+ }
+}
+
+json_weak char *json_write_pretty_value(const struct json_value_s *value,
+ size_t depth, const char *indent,
+ const char *newline, char *data);
+
+json_weak char *json_write_pretty_array(const struct json_array_s *array,
+ size_t depth, const char *indent,
+ const char *newline, char *data);
+char *json_write_pretty_array(const struct json_array_s *array, size_t depth,
+ const char *indent, const char *newline,
+ char *data) {
+ size_t k, m;
+ struct json_array_element_s *element;
+
+ *data++ = '['; /* open the array. */
+
+ if (0 < array->length) {
+ for (k = 0; '\0' != newline[k]; k++) {
+ *data++ = newline[k];
+ }
+
+ for (element = array->start; json_null != element;
+ element = element->next) {
+ if (element != array->start) {
+ *data++ = ','; /* ','s seperate each element. */
+
+ for (k = 0; '\0' != newline[k]; k++) {
+ *data++ = newline[k];
+ }
+ }
+
+ for (k = 0; k < depth + 1; k++) {
+ for (m = 0; '\0' != indent[m]; m++) {
+ *data++ = indent[m];
+ }
+ }
+
+ data = json_write_pretty_value(element->value, depth + 1, indent, newline,
+ data);
+
+ if (json_null == data) {
+ /* value was malformed! */
+ return json_null;
+ }
+ }
+
+ for (k = 0; '\0' != newline[k]; k++) {
+ *data++ = newline[k];
+ }
+
+ for (k = 0; k < depth; k++) {
+ for (m = 0; '\0' != indent[m]; m++) {
+ *data++ = indent[m];
+ }
+ }
+ }
+
+ *data++ = ']'; /* close the array. */
+
+ return data;
+}
+
+json_weak char *json_write_pretty_object(const struct json_object_s *object,
+ size_t depth, const char *indent,
+ const char *newline, char *data);
+char *json_write_pretty_object(const struct json_object_s *object, size_t depth,
+ const char *indent, const char *newline,
+ char *data) {
+ size_t k, m;
+ struct json_object_element_s *element;
+
+ *data++ = '{'; /* open the object. */
+
+ if (0 < object->length) {
+ for (k = 0; '\0' != newline[k]; k++) {
+ *data++ = newline[k];
+ }
+
+ for (element = object->start; json_null != element;
+ element = element->next) {
+ if (element != object->start) {
+ *data++ = ','; /* ','s seperate each element. */
+
+ for (k = 0; '\0' != newline[k]; k++) {
+ *data++ = newline[k];
+ }
+ }
+
+ for (k = 0; k < depth + 1; k++) {
+ for (m = 0; '\0' != indent[m]; m++) {
+ *data++ = indent[m];
+ }
+ }
+
+ data = json_write_string(element->name, data);
+
+ if (json_null == data) {
+ /* string was malformed! */
+ return json_null;
+ }
+
+ /* " : "s seperate each name/value pair. */
+ *data++ = ' ';
+ *data++ = ':';
+ *data++ = ' ';
+
+ data = json_write_pretty_value(element->value, depth + 1, indent, newline,
+ data);
+
+ if (json_null == data) {
+ /* value was malformed! */
+ return json_null;
+ }
+ }
+
+ for (k = 0; '\0' != newline[k]; k++) {
+ *data++ = newline[k];
+ }
+
+ for (k = 0; k < depth; k++) {
+ for (m = 0; '\0' != indent[m]; m++) {
+ *data++ = indent[m];
+ }
+ }
+ }
+
+ *data++ = '}'; /* close the object. */
+
+ return data;
+}
+
+json_weak char *json_write_pretty_value(const struct json_value_s *value,
+ size_t depth, const char *indent,
+ const char *newline, char *data);
+char *json_write_pretty_value(const struct json_value_s *value, size_t depth,
+ const char *indent, const char *newline,
+ char *data) {
+ switch (value->type) {
+ default:
+ /* unknown value type found! */
+ return json_null;
+ case json_type_number:
+ return json_write_number((struct json_number_s *)value->payload, data);
+ case json_type_string:
+ return json_write_string((struct json_string_s *)value->payload, data);
+ case json_type_array:
+ return json_write_pretty_array((struct json_array_s *)value->payload, depth,
+ indent, newline, data);
+ case json_type_object:
+ return json_write_pretty_object((struct json_object_s *)value->payload,
+ depth, indent, newline, data);
+ case json_type_true:
+ data[0] = 't';
+ data[1] = 'r';
+ data[2] = 'u';
+ data[3] = 'e';
+ return data + 4;
+ case json_type_false:
+ data[0] = 'f';
+ data[1] = 'a';
+ data[2] = 'l';
+ data[3] = 's';
+ data[4] = 'e';
+ return data + 5;
+ case json_type_null:
+ data[0] = 'n';
+ data[1] = 'u';
+ data[2] = 'l';
+ data[3] = 'l';
+ return data + 4;
+ }
+}
+
+void *json_write_pretty(const struct json_value_s *value, const char *indent,
+ const char *newline, size_t *out_size) {
+ size_t size = 0;
+ size_t indent_size = 0;
+ size_t newline_size = 0;
+ char *data = json_null;
+ char *data_end = json_null;
+
+ if (json_null == value) {
+ return json_null;
+ }
+
+ if (json_null == indent) {
+ indent = " "; /* default to two spaces. */
+ }
+
+ if (json_null == newline) {
+ newline = "\n"; /* default to linux newlines. */
+ }
+
+ while ('\0' != indent[indent_size]) {
+ ++indent_size; /* skip non-null terminating characters. */
+ }
+
+ while ('\0' != newline[newline_size]) {
+ ++newline_size; /* skip non-null terminating characters. */
+ }
+
+ if (json_write_pretty_get_value_size(value, 0, indent_size, newline_size,
+ &size)) {
+ /* value was malformed! */
+ return json_null;
+ }
+
+ size += 1; /* for the '\0' null terminating character. */
+
+ data = (char *)malloc(size);
+
+ if (json_null == data) {
+ /* malloc failed! */
+ return json_null;
+ }
+
+ data_end = json_write_pretty_value(value, 0, indent, newline, data);
+
+ if (json_null == data_end) {
+ /* bad chi occurred! */
+ free(data);
+ return json_null;
+ }
+
+ /* null terminated the string. */
+ *data_end = '\0';
+
+ if (json_null != out_size) {
+ *out_size = size;
+ }
+
+ return data;
+}
+
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#elif defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+#endif /* SHEREDOM_JSON_H_INCLUDED. */
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/main.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/main.cpp
new file mode 100644
index 0000000..2af879e
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/main.cpp
@@ -0,0 +1,912 @@
+#include "stdafx.h"
+#include
+#include
+
+#include "harddrive.h"
+#include "rtcManager.h"
+#include "temperatureManager.h"
+#include "context.h"
+#include "drawing.h"
+#include "Scenes\scene.h"
+#include "Scenes\mainScene.h"
+#include "Scenes\autoBootScene.h"
+#include "Scenes\flashFlowScene.h"
+#include "Scenes\sceneManager.h"
+#include "inputManager.h"
+#include "settingsManager.h"
+#include "xboxConfig.h"
+#include "xboxinternals.h"
+#include "meshUtility.h"
+#include "utils.h"
+#include "resources.h"
+#include "stringUtility.h"
+#include "settingsManager.h"
+#include "hdmiSettingsManager.h"
+#include "hdmiDevice.h"
+#include "json.h"
+#include "theme.h"
+#include "ssfn.h"
+#include "ftpServer.h"
+#include "httpServer.h"
+#include "driveManager.h"
+#include "XKUtils\XKEEPROM.h"
+#include "timeUtility.h"
+#include "network.h"
+#include "audioPlayer.h"
+#include "modchipXenium.h"
+#include "modchipXtremium.h"
+#include "modchipXecuter.h"
+#include "modchipXchanger.h"
+#include "modchipSmartxx.h"
+#include "modchipModxo.h"
+#include "modchipAladdin1mb.h"
+#include "modchipAladdin2mb.h"
+#include "modchipDummy.h"
+#include "Threads\lcdRender.h"
+#include "Threads\flashBackup.h"
+#include "Plugins\PEProcess.h"
+#include "cerbiosIniHelper.h"
+
+#include "stb_image_write.h"
+
+#include
+
+#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_TEX1)
+
+enum apiActionEnum
+{
+ apiActionNone = 0,
+ apiActionLaunchBank = 1,
+ apiActionLaunchTsop = 2,
+ apiActionReboot = 3,
+ apiActionShutdown = 41
+};
+
+namespace
+{
+ apiActionEnum mApiAction = apiActionNone;
+ int mBankId = 0;
+ int mCounter = 0;
+}
+
+utils::dataContainer* onGetCallback(const char* path, const char* query)
+{
+ utils::dataContainer* body = NULL;
+
+ if (stringUtility::equals(path, "\\", true))
+ {
+ return httpServer::redirect();
+ }
+ else if (stringUtility::equals(path, "\\pico.css", true))
+ {
+ body = new utils::dataContainer((char*)&pico_css, sizeof(pico_css), sizeof(pico_css));
+ }
+ else if (stringUtility::equals(path, "\\favicon.ico", true))
+ {
+ body = new utils::dataContainer((char*)&favicon_ico, sizeof(favicon_ico), sizeof(favicon_ico));
+ }
+ else if (stringUtility::equals(path, "\\flash.html", true))
+ {
+ body = new utils::dataContainer((char*)&flash_html, sizeof(flash_html), sizeof(flash_html));
+ }
+ else if (stringUtility::equals(path, "\\flash.js", true))
+ {
+ body = new utils::dataContainer((char*)&flash_js, sizeof(flash_js), sizeof(flash_js));
+ }
+ else if (stringUtility::equals(path, "\\remove.html", true))
+ {
+ body = new utils::dataContainer((char*)&remove_html, sizeof(remove_html), sizeof(remove_html));
+ }
+ else if (stringUtility::equals(path, "\\remove.js", true))
+ {
+ body = new utils::dataContainer((char*)&remove_js, sizeof(remove_js), sizeof(remove_js));
+ }
+ else if (stringUtility::equals(path, "\\remoteview.html", true))
+ {
+ body = new utils::dataContainer((char*)&remoteview_html, sizeof(remoteview_html), sizeof(remoteview_html));
+ }
+ else if (stringUtility::equals(path, "\\remoteview.js", true))
+ {
+ body = new utils::dataContainer((char*)&remoteview_js, sizeof(remoteview_js), sizeof(remoteview_js));
+ }
+ else if (stringUtility::equals(path, "\\launch.html", true))
+ {
+ body = new utils::dataContainer((char*)&launch_html, sizeof(launch_html), sizeof(launch_html));
+ }
+ else if (stringUtility::equals(path, "\\launch.js", true))
+ {
+ body = new utils::dataContainer((char*)&launch_js, sizeof(launch_js), sizeof(launch_js));
+ }
+ else if (stringUtility::equals(path, "\\cerbiosini.html", true))
+ {
+ body = new utils::dataContainer((char*)&cerbiosini_html, sizeof(cerbiosini_html), sizeof(cerbiosini_html));
+ }
+ else if (stringUtility::equals(path, "\\cerbiosini.js", true))
+ {
+ body = new utils::dataContainer((char*)&cerbiosini_js, sizeof(cerbiosini_js), sizeof(cerbiosini_js));
+ }
+ else if (stringUtility::equals(path, "\\download.html", true))
+ {
+ body = new utils::dataContainer((char*)&download_html, sizeof(download_html), sizeof(download_html));
+ }
+ else if (stringUtility::equals(path, "\\download.js", true))
+ {
+ body = new utils::dataContainer((char*)&download_js, sizeof(download_js), sizeof(download_js));
+ }
+ else if (stringUtility::equals(path, "\\downloads.html", true))
+ {
+ body = new utils::dataContainer((char*)&downloads_html, sizeof(downloads_html), sizeof(downloads_html));
+ }
+ else if (stringUtility::equals(path, "\\downloads.js", true))
+ {
+ body = new utils::dataContainer((char*)&downloads_js, sizeof(downloads_js), sizeof(downloads_js));
+ }
+ else if (stringUtility::equals(path, "\\index.html", true))
+ {
+ body = new utils::dataContainer((char*)&index_html, sizeof(index_html), sizeof(index_html));
+ }
+ else if (stringUtility::equals(path, "\\index.js", true))
+ {
+ body = new utils::dataContainer((char*)&index_js, sizeof(index_js), sizeof(index_js));
+ }
+ else if (stringUtility::equals(path, "\\main.css", true))
+ {
+ body = new utils::dataContainer((char*)&main_css, sizeof(main_css), sizeof(main_css));
+ }
+ else if (stringUtility::equals(path, "\\api\\freeslots.json", true))
+ {
+ char* freeSlotsJson = settingsManager::getFreeSlotsJson();
+ body = new utils::dataContainer(freeSlotsJson, strlen(freeSlotsJson), strlen(freeSlotsJson));
+ free(freeSlotsJson);
+ }
+ else if (stringUtility::equals(path, "\\api\\bankinfo.json", true))
+ {
+ char* bankInfosJson = settingsManager::getBankInfosJson();
+ body = new utils::dataContainer(bankInfosJson, strlen(bankInfosJson), strlen(bankInfosJson));
+ free(bankInfosJson);
+ }
+ else if (stringUtility::equals(path, "\\api\\shutdown", true))
+ {
+ mApiAction = apiActionShutdown;
+ return httpServer::generateResponse(200, "OK");
+ }
+ else if (stringUtility::equals(path, "\\api\\reboot", true))
+ {
+ mApiAction = apiActionReboot;
+ return httpServer::generateResponse(200, "OK");
+ }
+ else if (stringUtility::equals(path, "\\api\\launchbank", true))
+ {
+ int id = stringUtility::toInt(query);
+ utils::debugPrint("Launching bank %i", id);
+ if (id >= 0 && id <= 3)
+ {
+ mApiAction = apiActionLaunchBank;
+ mBankId = id;
+ }
+ return httpServer::generateResponse(200, "OK");
+ }
+ else if (stringUtility::equals(path, "\\api\\launchtsop", true))
+ {
+ utils::debugPrint("Launching TSOP");
+ mApiAction = apiActionLaunchTsop;
+ return httpServer::generateResponse(200, "OK");
+ }
+ else if (stringUtility::equals(path, "\\api\\removebank", true))
+ {
+ int id = stringUtility::toInt(query);
+ utils::debugPrint("Removing bank %i", id);
+ if (id >= 0 && id <= 3)
+ {
+ settingsManager::deleteBank(id);
+ }
+ return httpServer::generateResponse(200, "OK");
+ }
+ else if (stringUtility::equals(path, "\\api\\downloadbank", true))
+ {
+ int id = stringUtility::toInt(query);
+ utils::debugPrint("Downloading bank %i", id);
+ if (id >= 0 && id <= 3)
+ {
+ body = settingsManager::readBank(id);
+ }
+ }
+ else if (stringUtility::equals(path, "\\api\\downloadeeprom", true))
+ {
+ XKEEPROM* eeprom = new XKEEPROM();
+ eeprom->ReadFromXBOX();
+ body = new utils::dataContainer(EEPROM_SIZE);
+ eeprom->GetEEPROMData((LPEEPROMDATA)body->data);
+ delete(eeprom);
+ }
+ else if (stringUtility::equals(path, "\\api\\downloadprom", true))
+ {
+ body = context::getModchip()->readFlash(false);
+ }
+ else if (stringUtility::equals(path, "\\api\\cerbiosini", true))
+ {
+ char* temp = (char*)malloc(65536);
+ cerbiosConfig config = cerbiosIniHelper::loadConfig();
+ cerbiosIniHelper::buildConfig(&config, temp);
+ body = new utils::dataContainer(temp, strlen(temp), strlen(temp));
+ }
+ else if (stringUtility::equals(path, "\\api\\screenshot", true))
+ {
+ context::setScreenshot(NULL);
+ context::setTakeScreenshot(true);
+ while (context::getScreenshot() == NULL)
+ {
+ Sleep(100);
+ }
+ body = context::getScreenshot();
+ }
+
+ if (body == NULL)
+ {
+ return httpServer::generateResponse(404, "Mot found");
+ }
+
+ char* extension = fileSystem::getExtension(path);
+ char* mimeType = httpServer::getMimeType(extension);
+ char* contentLength = stringUtility::formatString("%lu", body->size);
+ char* header = stringUtility::formatString("HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nCache-Control: no-cache\r\nContent-Type: %s\r\nX-Content-Type-Options: nosniff\r\nContent-Length: %s\r\n\r\n", mimeType, contentLength);
+
+ utils::debugPrint("Header len = %i\n", strlen(header));
+ utils::debugPrint("Response = %s\n", header);
+
+ utils::dataContainer* result = new utils::dataContainer(strlen(header) + body->size);
+ memcpy(result->data, header, strlen(header));
+ memcpy(result->data + strlen(header), body->data, body->size);
+
+ delete(body);
+ free(extension);
+ free(mimeType);
+ free(contentLength);
+ free(header);
+
+ return result;
+}
+
+utils::dataContainer* onPostCallback(const char* path, const char* query, pointerVector* formParts)
+{
+ utils::debugPrint("Post reciecved\n");
+
+ if (stringUtility::equals(path, "\\api\\upload", true))
+ {
+ if (formParts->count() != 2)
+ {
+ return httpServer::generateResponse(400, "Unexpected form parts.");
+ }
+
+ FormPart* formPart = formParts->get(0);
+
+ if (context::getModchip()->isValidBankSize(formPart->body->size) == false)
+ {
+ return httpServer::generateResponse(406, "Invalid size detected.");
+ }
+
+ FormPart* jsonPart = formParts->get(1);
+
+ char* bankName = NULL;
+ uint8_t ledColor = 0;
+
+ char *json = (char*)jsonPart->body->data;
+ struct json_value_s* root = json_parse(json, strlen(json));
+ struct json_object_s* object = (struct json_object_s*)root->payload;
+
+ struct json_object_element_s* element = object->start;
+ while (element != NULL)
+ {
+ if (stringUtility::equals(element->name->string, "ledColor", true))
+ {
+ struct json_number_s* numberValue = json_value_as_number(element->value);
+ ledColor = (uint8_t)stringUtility::toInt(numberValue->number);
+ }
+ else if (stringUtility::equals(element->name->string, "bankName", true))
+ {
+ struct json_string_s* stringValue = json_value_as_string(element->value);
+ bankName = strdup(stringValue->string);
+ }
+ element = element->next;
+ }
+
+ uint8_t slotsNeeded = (uint8_t)(formPart->body->size >> 18);
+ settingsManager::optimizeBanks(slotsNeeded);
+
+ bool flashSuccess = false;
+
+ uint8_t bankId = 0;
+ if (settingsManager::tryGetFreeBank(slotsNeeded, bankId))
+ {
+ settingsManager::eraseBank(bankId, formPart->body->size);
+ settingsManager::writeBank(bankId, formPart->body, bankName == NULL ? "Unknown" : bankName, ledColor);
+ flashSuccess = settingsManager::verifyBank(bankId, formPart->body);
+ }
+
+ free(bankName);
+ free(root);
+
+ if (flashSuccess == true)
+ {
+ return httpServer::generateResponse(200, "OK");
+ }
+
+ return httpServer::generateResponse(406, "No wnough free slots.");
+ }
+ else if (stringUtility::equals(path, "\\api\\cerbiosini", true))
+ {
+ if (formParts->count() != 1)
+ {
+ return httpServer::generateResponse(400, "Unexpected form parts.");
+ }
+
+ FormPart* formPart = formParts->get(0);
+
+ if (formPart->body->size > 65535)
+ {
+ return httpServer::generateResponse(406, "Invalid size detected.");
+ }
+
+ FormPart* bodyPart = formParts->get(0);
+ char* body = (char*)bodyPart->body->data;
+ cerbiosIniHelper::saveConfig(body);
+ }
+
+ return httpServer::generateResponse(404, "Mot found");
+}
+
+void onResponseSentCallback()
+{
+ if (mApiAction == apiActionShutdown)
+ {
+ utils::shutdown();
+ Sleep(5000);
+ }
+ else if (mApiAction == apiActionReboot)
+ {
+ utils::reboot();
+ Sleep(5000);
+ }
+ else if (mApiAction == apiActionLaunchBank)
+ {
+ settingsManager::launchBank(mBankId);
+ Sleep(5000);
+ }
+ else if (mApiAction == apiActionLaunchTsop)
+ {
+ settingsManager::launchTsop();
+ Sleep(5000);
+ }
+}
+
+typedef struct {
+ DWORD dwWidth;
+ DWORD dwHeight;
+ BOOL fProgressive;
+ BOOL fWideScreen;
+ DWORD dwFreq;
+} DISPLAY_MODE;
+
+DISPLAY_MODE displayModes[] =
+{
+ //{ 720, 480, TRUE, TRUE, 60 }, // 720x480 progressive 16x9
+ //{ 720, 480, TRUE, FALSE, 60 }, // 720x480 progressive 4x3
+ //{ 720, 480, FALSE, TRUE, 50 }, // 720x480 interlaced 16x9 50Hz
+ //{ 720, 480, FALSE, FALSE, 50 }, // 720x480 interlaced 4x3 50Hz
+ //{ 720, 480, FALSE, TRUE, 60 }, // 720x480 interlaced 16x9
+ //{ 720, 480, FALSE, FALSE, 60 }, // 720x480 interlaced 4x3
+
+
+ // Width Height Progressive Widescreen
+
+ // HDTV Progressive Modes
+ { 1280, 720, TRUE, TRUE, 60 }, // 1280x720 progressive 16x9
+
+ // EDTV Progressive Modes
+ { 720, 480, TRUE, TRUE, 60 }, // 720x480 progressive 16x9
+ { 640, 480, TRUE, TRUE, 60 }, // 640x480 progressive 16x9
+ { 720, 480, TRUE, FALSE, 60 }, // 720x480 progressive 4x3
+ { 640, 480, TRUE, FALSE, 60 }, // 640x480 progressive 4x3
+
+ // HDTV Interlaced Modes
+ // { 1920, 1080, FALSE, TRUE, 60 }, // 1920x1080 interlaced 16x9
+
+ // SDTV PAL-50 Interlaced Modes
+ { 720, 480, FALSE, TRUE, 50 }, // 720x480 interlaced 16x9 50Hz
+ { 640, 480, FALSE, TRUE, 50 }, // 640x480 interlaced 16x9 50Hz
+ { 720, 480, FALSE, FALSE, 50 }, // 720x480 interlaced 4x3 50Hz
+ { 640, 480, FALSE, FALSE, 50 }, // 640x480 interlaced 4x3 50Hz
+
+ // SDTV NTSC / PAL-60 Interlaced Modes
+ { 720, 480, FALSE, TRUE, 60 }, // 720x480 interlaced 16x9
+ { 640, 480, FALSE, TRUE, 60 }, // 640x480 interlaced 16x9
+ { 720, 480, FALSE, FALSE, 60 }, // 720x480 interlaced 4x3
+ { 640, 480, FALSE, FALSE, 60 }, // 640x480 interlaced 4x3
+};
+
+#define NUM_MODES (sizeof(displayModes) / sizeof(displayModes[0]))
+
+bool supportsMode(DISPLAY_MODE mode, DWORD dwVideoStandard, DWORD dwVideoFlags)
+{
+ if (mode.dwFreq == 60 && !(dwVideoFlags & XC_VIDEO_FLAGS_PAL_60Hz) && (dwVideoStandard == XC_VIDEO_STANDARD_PAL_I))
+ {
+ return false;
+ }
+ if (mode.dwFreq == 50 && (dwVideoStandard != XC_VIDEO_STANDARD_PAL_I))
+ {
+ return false;
+ }
+ if (mode.dwHeight == 480 && mode.fWideScreen && !(dwVideoFlags & XC_VIDEO_FLAGS_WIDESCREEN ))
+ {
+ return false;
+ }
+ if (mode.dwHeight == 480 && mode.fProgressive && !(dwVideoFlags & XC_VIDEO_FLAGS_HDTV_480p))
+ {
+ return false;
+ }
+ if (mode.dwHeight == 720 && !(dwVideoFlags & XC_VIDEO_FLAGS_HDTV_720p))
+ {
+ return false;
+ }
+ if (mode.dwHeight == 1080 && !(dwVideoFlags & XC_VIDEO_FLAGS_HDTV_1080i))
+ {
+ return false;
+ }
+ return true;
+}
+
+bool createDevice()
+{
+ uint32_t videoFlags = XGetVideoFlags();
+ uint32_t videoStandard = XGetVideoStandard();
+ uint32_t currentMode;
+ for (currentMode = 0; currentMode < NUM_MODES-1; currentMode++)
+ {
+ if (supportsMode(displayModes[currentMode], videoStandard, videoFlags))
+ {
+ break;
+ }
+ }
+
+ LPDIRECT3D8 d3d = Direct3DCreate8(D3D_SDK_VERSION);
+ if(d3d == NULL)
+ {
+ utils::debugPrint("Failed to create d3d\n");
+ return false;
+ }
+
+ context::setBufferWidth(720);
+ context::setBufferHeight(480);
+ //context::setBufferWidth(displayModes[currentMode].dwWidth);
+ //context::setBufferHeight(displayModes[currentMode].dwHeight);
+
+ D3DPRESENT_PARAMETERS params;
+ ZeroMemory(¶ms, sizeof(params));
+ params.BackBufferWidth = displayModes[currentMode].dwWidth;
+ params.BackBufferHeight = displayModes[currentMode].dwHeight;
+ params.Flags = displayModes[currentMode].fProgressive ? D3DPRESENTFLAG_PROGRESSIVE : D3DPRESENTFLAG_INTERLACED;
+ params.Flags |= displayModes[currentMode].fWideScreen ? D3DPRESENTFLAG_WIDESCREEN : 0;
+ params.FullScreen_RefreshRateInHz = displayModes[currentMode].dwFreq;
+ params.BackBufferFormat = D3DFMT_X8R8G8B8;
+ params.BackBufferCount = 1;
+ params.EnableAutoDepthStencil = FALSE;
+ params.SwapEffect = D3DSWAPEFFECT_COPY;
+ params.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+
+ LPDIRECT3DDEVICE8 d3dDevice;
+ if (FAILED(d3d->CreateDevice(0, D3DDEVTYPE_HAL, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING, ¶ms, &d3dDevice)))
+ {
+ utils::debugPrint("Failed to create device\n");
+ return false;
+ }
+ context::setD3dDevice(d3dDevice);
+
+ D3DXMATRIX matProjection;
+ D3DXMatrixOrthoOffCenterLH(&matProjection, 0, (float)context::getBufferWidth(), 0, (float)context::getBufferHeight(), 1.0f, 100.0f);
+ context::getD3dDevice()->SetTransform(D3DTS_PROJECTION, &matProjection);
+
+ D3DXMATRIX matView;
+ D3DXMatrixIdentity(&matView);
+ context::getD3dDevice()->SetTransform( D3DTS_VIEW, &matView);
+
+ D3DXMATRIX matWorld;
+ D3DXMatrixIdentity(&matWorld);
+ context::getD3dDevice()->SetTransform( D3DTS_WORLD, &matWorld);
+
+ context::getD3dDevice()->SetRenderState(D3DRS_LIGHTING, FALSE);
+ context::getD3dDevice()->SetVertexShader(D3DFVF_CUSTOMVERTEX);
+ context::getD3dDevice()->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
+ context::getD3dDevice()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
+ context::getD3dDevice()->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
+
+ context::getD3dDevice()->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ context::getD3dDevice()->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
+ context::getD3dDevice()->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
+ context::getD3dDevice()->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);
+ context::getD3dDevice()->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
+ context::getD3dDevice()->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
+
+ context::getD3dDevice()->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
+ context::getD3dDevice()->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
+ context::getD3dDevice()->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
+
+ context::getD3dDevice()->BeginScene();
+ context::getD3dDevice()->Clear(0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0xff000000, 1.0f, 0L);
+ context::getD3dDevice()->EndScene();
+ context::getD3dDevice()->Present(NULL, NULL, NULL, NULL);
+
+ return true;
+}
+
+void refreshInfo()
+{
+ if (network::isReady() == true)
+ {
+ XNADDR addr;
+ memset(&addr, 0, sizeof(addr));
+ DWORD dwState = XNetGetTitleXnAddr(&addr);
+ if (dwState != XNET_GET_XNADDR_PENDING)
+ {
+ char* ipAddress = (XNetGetEthernetLinkStatus() & XNET_ETHERNET_LINK_ACTIVE) ? stringUtility::formatString("%i.%i.%i.%i",
+ addr.ina.S_un.S_un_b.s_b1,
+ addr.ina.S_un.S_un_b.s_b2,
+ addr.ina.S_un.S_un_b.s_b3,
+ addr.ina.S_un.S_un_b.s_b4) : strdup("0.0.0.0");
+ char* currentIp = context::getCurrentIp();
+ if (stringUtility::equals(ipAddress, currentIp, false) == false)
+ {
+ context::setCurrentIp(ipAddress);
+ mCounter = 0;
+ }
+ free(ipAddress);
+ free(currentIp);
+ }
+ }
+
+ if (mCounter == 0)
+ {
+ context::setCurrentFreeMem(utils::getFreePhysicalMemory());
+ context::setCurrentFanSpeed(temperatureManager::getFanSpeed() * 2);
+ context::setCurrentCpuTemp(temperatureManager::getCpuTemp());
+ context::setCurrentMbTemp(temperatureManager::getMbTemp());
+ mCounter = 60;
+ }
+ else
+ {
+ mCounter--;
+ }
+}
+#define WIFI_SSID_LENGTH 32
+#define WIFI_PASSWORD_LENGTH 63
+
+#define I2C_SLAVE_ADDRESS 0x60
+#define I2C_DATA_LENGTH 256
+
+#define I2C_READ_FLAG 0x00
+#define I2C_WRITE_FLAG 0x80
+
+#define I2C_COMMAND_EFFECT 0x00
+#define I2C_COMMAND_EFFECT_PARAM (I2C_COMMAND_EFFECT + 1)
+#define I2C_COMMAND_EFFECT_COLOR1_R (I2C_COMMAND_EFFECT_PARAM + 1)
+#define I2C_COMMAND_EFFECT_COLOR1_G (I2C_COMMAND_EFFECT_COLOR1_R + 1)
+#define I2C_COMMAND_EFFECT_COLOR1_B (I2C_COMMAND_EFFECT_COLOR1_G + 1)
+#define I2C_COMMAND_EFFECT_COLOR2_R (I2C_COMMAND_EFFECT_COLOR1_B + 1)
+#define I2C_COMMAND_EFFECT_COLOR2_G (I2C_COMMAND_EFFECT_COLOR2_R + 1)
+#define I2C_COMMAND_EFFECT_COLOR2_B (I2C_COMMAND_EFFECT_COLOR2_G + 1)
+#define I2C_COMMAND_COLOR1_R (I2C_COMMAND_EFFECT_COLOR2_B + 1)
+#define I2C_COMMAND_COLOR1_G (I2C_COMMAND_COLOR1_R + 1)
+#define I2C_COMMAND_COLOR1_B (I2C_COMMAND_COLOR1_G + 1)
+#define I2C_COMMAND_COLOR2_R (I2C_COMMAND_COLOR1_B + 1)
+#define I2C_COMMAND_COLOR2_G (I2C_COMMAND_COLOR2_R + 1)
+#define I2C_COMMAND_COLOR2_B (I2C_COMMAND_COLOR2_G + 1)
+#define I2C_COMMAND_COLOR3_R (I2C_COMMAND_COLOR2_B + 1)
+#define I2C_COMMAND_COLOR3_G (I2C_COMMAND_COLOR3_R + 1)
+#define I2C_COMMAND_COLOR3_B (I2C_COMMAND_COLOR3_G + 1)
+#define I2C_COMMAND_COLOR4_R (I2C_COMMAND_COLOR3_B + 1)
+#define I2C_COMMAND_COLOR4_G (I2C_COMMAND_COLOR4_R + 1)
+#define I2C_COMMAND_COLOR4_B (I2C_COMMAND_COLOR4_G + 1)
+#define I2C_COMMAND_WIFI_SSID_START (I2C_COMMAND_COLOR4_B + 1)
+#define I2C_COMMAND_WIFI_SSID_END (I2C_COMMAND_WIFI_SSID_START + WIFI_SSID_LENGTH - 1)
+#define I2C_COMMAND_WIFI_PASSWORD_START (I2C_COMMAND_WIFI_SSID_END + 1)
+#define I2C_COMMAND_WIFI_PASSWORD_END (I2C_COMMAND_WIFI_PASSWORD_START + WIFI_PASSWORD_LENGTH - 1)
+
+#define I2C_COMMAND_APPLY 0x7E
+#define I2C_COMMAND_SET_COMMAND 0x7F
+
+#define WIFI_SSID "EqUiNoX"
+#define WIFI_PASSWORD "R1chm0nd"
+
+void writeScratchSetting(uint8_t command, uint8_t value)
+{
+ HalWriteSMBusByte(I2C_SLAVE_ADDRESS << 1, command | I2C_WRITE_FLAG, value);
+ Sleep(1);
+}
+
+void applySettings()
+{
+ HalWriteSMBusByte(I2C_SLAVE_ADDRESS << 1, I2C_COMMAND_APPLY | I2C_WRITE_FLAG, 0x00);
+ Sleep(1);
+}
+
+void writeColor(uint8_t command, uint8_t r, uint8_t g, uint8_t b)
+{
+ writeScratchSetting(command, r);
+ writeScratchSetting(command + 1, g);
+ writeScratchSetting(command + 2, b);
+
+ applySettings();
+ Sleep(100);
+}
+
+void writeWifiDetails()
+{
+ uint8_t ssid_len = strlen(WIFI_SSID);
+ for (uint8_t i = 0; i < ssid_len; i++)
+ {
+ writeScratchSetting(I2C_COMMAND_WIFI_SSID_START + i, WIFI_SSID[i]);
+ }
+
+ uint8_t password_len = strlen(WIFI_PASSWORD);
+ for (uint8_t i = 0; i < password_len; i++)
+ {
+ writeScratchSetting(I2C_COMMAND_WIFI_PASSWORD_START + i, WIFI_PASSWORD[i]);
+ }
+
+ applySettings();
+}
+
+void readSetting(uint8_t command, uint8_t* value)
+{
+ HalWriteSMBusByte(I2C_SLAVE_ADDRESS << 1, I2C_COMMAND_SET_COMMAND | I2C_WRITE_FLAG, command);
+ Sleep(1);
+
+ uint32_t temp = 0;
+ HalReadSMBusByte(I2C_SLAVE_ADDRESS << 1, I2C_READ_FLAG, &temp);
+ Sleep(1);
+
+ *value = (uint8_t)temp;
+}
+
+void checkForSpecialButtons() {
+ // Toggle PrometheOS VGA setting on/off
+ if(
+ inputManager::buttonDown(ButtonTriggerLeft) &&
+ inputManager::buttonDown(ButtonTriggerRight) &&
+ inputManager::buttonDown(ButtonWhite)
+ ) {
+ settingsManager::setVgaEnable(!settingsManager::getVgaEnable());
+ Sleep(200);
+ HalReturnToFirmware(1); // BIOS reboot
+ }
+
+ // Toggle between NTSC-M and PAL-50
+ if(
+ inputManager::buttonDown(ButtonTriggerLeft) &&
+ inputManager::buttonDown(ButtonTriggerRight) &&
+ inputManager::buttonDown(ButtonBlack)
+ ) {
+ if(xboxConfig::getVideoStandardNTSCM()) {
+ xboxConfig::setVideoStandardPALI50();
+ } else {
+ xboxConfig::setVideoStandardNTSCM();
+ }
+ Sleep(200);
+ HalReturnToFirmware(1); // BIOS reboot
+ }
+}
+
+void __cdecl main()
+{
+#ifndef TOOLS
+ utils::debugPrint("Welcome to PrometheOS\n");
+#else
+ utils::debugPrint("Welcome to PrometheOS Tools\n");
+#endif
+
+ /*writeWifiDetails();
+
+ while (true)
+ {
+ writeColor(I2C_COMMAND_COLOR2_R, 0xff, 0x00, 0x00);
+ writeColor(I2C_COMMAND_COLOR2_R, 0xff, 0xff, 0x00);
+ writeColor(I2C_COMMAND_COLOR2_R, 0x00, 0xff, 0x00);
+ writeColor(I2C_COMMAND_COLOR2_R, 0x00, 0xff, 0xff);
+ writeColor(I2C_COMMAND_COLOR2_R, 0x00, 0x00, 0xff);
+ writeColor(I2C_COMMAND_COLOR2_R, 0xff, 0x00, 0xff);
+ }*/
+
+#ifdef XENIUM
+ context::setModchipType(modchipTypeXenium);
+#elif XTREMIUM
+ context::setModchipType(modchipTypeXtremium);
+#elif XECUTER
+ context::setModchipType(modchipTypeXecuter);
+#elif XCHANGER
+ context::setModchipType(modchipTypeXchanger);
+#elif SMARTXX
+ context::setModchipType(modchipTypeSmartxx);
+#elif MODXO
+ context::setModchipType(modchipTypeModxo);
+#elif ALADDIN1MB
+ context::setModchipType(modchipTypeAladdin1mb);
+#elif ALADDIN2MB
+ context::setModchipType(modchipTypeAladdin2mb);
+#elif DUMMY
+ context::setModchipType(modchipTypeDummy);
+#elif TOOLS
+ context::setModchipType(modchip::detectModchip());
+#endif
+
+ //XboxPartitionTable PartTbl;
+ //XboxPartitionTable* KernelPartTblAdd;
+ //DWORD g_dwUserSectors;
+ //DWORD lba48PatchVersion;
+
+ //if (harddrive::readLbaInfo(&PartTbl, &KernelPartTblAdd, &g_dwUserSectors, &lba48PatchVersion))
+ //{
+ //}
+
+ //format example
+ //status = XapiFormatFATVolumeEx(&partition_str[i], ClusterSize << 10);
+
+ utils::setLedStates(SMC_LED_STATES_GREEN_STATE0 | SMC_LED_STATES_GREEN_STATE1 | SMC_LED_STATES_GREEN_STATE2 | SMC_LED_STATES_GREEN_STATE3);
+
+ bool deviceCreated = createDevice();
+
+ temperatureManager::init();
+
+ context::setNetworkInitialized(false);
+
+ driveManager::mountDrive("HDD0-C");
+ driveManager::mountDrive("HDD0-E");
+
+ xboxConfig::init();
+ xboxConfig::autoFix();
+ settingsManager::loadSettings();
+
+ if (hdmiDevice::detectDevice() == true)
+ {
+ hdmiSettingsManager::loadSettings();
+ }
+
+ if (settingsManager::getRtcEnable() == true && xboxConfig::getHasRtcExpansion() == true)
+ {
+ rtcDateTime dateTime = rtcManager::getDateTime();
+ rtcManager::setXboxDateTime(dateTime);
+ }
+
+ httpServer::registerOnGetCallback(onGetCallback);
+ httpServer::registerOnPostCallback(onPostCallback);
+ httpServer::registerOnResponseSentCallback(onResponseSentCallback);
+
+ if (deviceCreated == false)
+ {
+ network::init();
+ while (true)
+ {
+ temperatureManager::refresh();
+ Sleep(100);
+ }
+ }
+
+ context::setImageMap(new pointerMap(true));
+
+ drawing::loadFont(&font_sfn[0]);
+
+ //\xC2\xA1 = A
+ //\xC2\xA2 = B
+ //\xC2\xA3 = X
+ //\xC2\xA4 = Y
+ //\xC2\xA5 = Folder
+ //\xC2\xA6 = File
+ //\xC2\xA7 = P
+ //\xC2\xA8 = R
+ //\xC2\xA9 = O
+ //\xC2\xAA = M
+ //\xC2\xAB = E
+ //\xC2\xAC = T
+ //\xC2\xAD = H
+ //\xC2\xAE = S
+ //\xC2\xAF = Cursor On
+ //\xC2\xB0 = Cursor Off
+ //\xC2\xB1 = Deg
+ //\xC2\xB2 = LT
+ //\xC2\xB3 = RT
+ //\xC2\xB4 = L
+ //\xC2\xB5 = White
+ //\xC2\xB6 = Black
+
+ bitmapFont* fontSmall = drawing::generateBitmapFont("FreeSans", SSFN_STYLE_REGULAR, 18, 18, 0, 256);
+ context::setBitmapFontSmall(fontSmall);
+ bitmapFont* fontMedium = drawing::generateBitmapFont("FreeSans", SSFN_STYLE_REGULAR, 25, 25, 0, 256);
+ context::setBitmapFontMedium(fontMedium);
+ bitmapFont* fontLarge = drawing::generateBitmapFont("FreeSans", SSFN_STYLE_REGULAR, 32, 32, 0, 512);
+ context::setBitmapFontLarge(fontLarge);
+
+ drawing::renderRoundedRect("panel-fill", 24, 24, 6, 0xffffffff, 0x00000000, 0);
+ drawing::renderRoundedRect("panel-stroke", 24, 24, 6, 0x01010100, 0xffffffff, 2);
+
+ lcdRender::startThread();
+
+ sceneManager::pushScene(sceneItemMainScene);
+ if (settingsManager::hasAutoBootBank() == true)
+ {
+ sceneManager::pushScene(sceneItemAutoBootScene);
+ }
+
+ char* skinName = settingsManager::getSkinName();
+ theme::loadSkin(skinName);
+ free(skinName);
+
+ audioPlayer::init();
+ char* soundPackName = settingsManager::getSoundPackName();
+ theme::loadSoundPack(soundPackName);
+ free(soundPackName);
+
+ uint64_t start = timeUtility::getMillisecondsNow();
+
+ uint32_t frameIndex = 0;
+ int32_t frameDirection = -1;
+
+ //PEParam_t* params;
+ //params = (PEParam_t*)malloc(sizeof(PEParam_t));
+ //memset(params, 0, sizeof(PEParam_t));
+
+ //char* name = PEProcess::getPluginName("E:\\Root\\plugin.nxe");
+ //uint32_t result = PEProcess::PE_Run("E:\\Root\\plugin.nxe", params);
+ //free(name);
+
+
+ while (TRUE)
+ {
+ context::getD3dDevice()->BeginScene();
+
+ temperatureManager::refresh();
+ inputManager::processController();
+ checkForSpecialButtons();
+ drawing::clearBackground((uint32_t)frameIndex);
+
+ if (context::getTakeScreenshot() == true)
+ {
+ context::setScreenshot(drawing::takeScreenshot());
+ context::setTakeScreenshot(false);
+ }
+
+ refreshInfo();
+
+ sceneManager::getScene()->update();
+ sceneManager::getScene()->render();
+
+ context::getD3dDevice()->EndScene();
+ context::getD3dDevice()->Present(NULL, NULL, NULL, NULL);
+
+ uint32_t backgroundCount = theme::getBackgroundFrameCount();
+ if (backgroundCount > 0)
+ {
+ uint64_t end = timeUtility::getMillisecondsNow();
+ if (end - start > theme::getBackgroundFrameDelay())
+ {
+ uint32_t backgroundCount = theme::getBackgroundFrameCount();
+ if ( theme::getBackgroundFramePingPong() == true)
+ {
+ frameIndex = min(frameIndex, backgroundCount - 1);
+ if (frameIndex == 0 || frameIndex == (backgroundCount - 1))
+ {
+ frameDirection = -1 * frameDirection;
+ }
+ frameIndex = frameIndex + frameDirection;
+ }
+ else
+ {
+ frameIndex = (frameIndex + 1) % backgroundCount;
+ }
+
+ start = end;
+ }
+ }
+ else
+ {
+ frameIndex = 0;
+ }
+ }
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/math.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/math.cpp
new file mode 100644
index 0000000..930d56f
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/math.cpp
@@ -0,0 +1,36 @@
+#include "math.h"
+
+float math::calcNinePatchPosition(int index, float length)
+{
+ if (index == 0)
+ {
+ return 0.0f;
+ }
+ if (index == 1)
+ {
+ return 8.0f;
+ }
+ if (index == 2)
+ {
+ return length - 8.0f;
+ }
+ return length;
+}
+
+float math::calcNinePatchUV(int index, float length)
+{
+ float uvPerPixel = length / 24.0f;
+ if (index == 0)
+ {
+ return 0.0f;
+ }
+ if (index == 1)
+ {
+ return 8.0f * uvPerPixel;
+ }
+ if (index == 2)
+ {
+ return length - (8.0f * uvPerPixel);
+ }
+ return length;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/math.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/math.h
new file mode 100644
index 0000000..27dc824
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/math.h
@@ -0,0 +1,79 @@
+#pragma once
+
+class math
+{
+public:
+
+ typedef struct vec2F
+ {
+ union {
+ struct {
+ float x;
+ float y;
+ };
+ float values[2];
+ };
+ vec2F() : x(0), y(0) {}
+ vec2F(const float x, const float y) : x(x), y(y) {}
+ } vec2F;
+
+ typedef struct vec3F
+ {
+ union {
+ struct {
+ float x;
+ float y;
+ float z;
+ };
+ float values[3];
+ };
+ vec3F() : x(0), y(0), z(0) {}
+ vec3F(const float x, const float y, const float z) : x(x), y(y), z(z) {}
+ } vec3F;
+
+ typedef struct sizeF
+ {
+ union {
+ struct {
+ float width;
+ float height;
+ };
+ float values[2];
+ };
+ sizeF() : width(0), height(0) {}
+ sizeF(const float width, const float height) : width(width), height(height) {}
+ } sizeF;
+
+ typedef struct rectF
+ {
+ union {
+ struct {
+ float x;
+ float y;
+ float width;
+ float height;
+ };
+ float values[4];
+ };
+ rectF() : x(0), y(0), width(0), height(0) {}
+ rectF(const float x, const float y, const float width, const float height) : x(x), y(y), width(width), height(height) {}
+ } rectF;
+
+ typedef struct rectI
+ {
+ union {
+ struct {
+ int x;
+ int y;
+ int width;
+ int height;
+ };
+ int values[4];
+ };
+ rectI() : x(0), y(0), width(0), height(0) {}
+ rectI(const int x, const int y, const int width, const int height) : x(x), y(y), width(width), height(height) {}
+ } rectI;
+
+ static float calcNinePatchPosition(int index, float length);
+ static float calcNinePatchUV(int index, float length);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/meshUtility.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/meshUtility.cpp
new file mode 100644
index 0000000..76bb9bc
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/meshUtility.cpp
@@ -0,0 +1,70 @@
+#include "meshUtility.h"
+
+utils::dataContainer* meshUtility::createQuadXY(const math::vec3F& position, const math::sizeF& size, const math::rectF& uvRect)
+{
+ vertex v1 = vertex(position.x, position.y, position.z, uvRect.x, uvRect.y + uvRect.height);
+ vertex v2 = vertex(position.x + size.width, position.y, position.z, uvRect.x + uvRect.width, uvRect.y + uvRect.height);
+ vertex v3 = vertex(position.x + size.width, position.y + size.height, position.z, uvRect.x + uvRect.width, uvRect.y);
+ vertex v4 = vertex(position.x, position.y + size.height, position.z, uvRect.x, uvRect.y);
+
+ utils::dataContainer* vertices = new utils::dataContainer();
+ vertices->size = 6 * sizeof(vertex);
+ vertices->data = (char*)malloc(vertices->size);
+
+ memcpy(vertices->data + (0 * sizeof(vertex)), &v3, sizeof(vertex));
+ memcpy(vertices->data + (1 * sizeof(vertex)), &v2, sizeof(vertex));
+ memcpy(vertices->data + (2 * sizeof(vertex)), &v1, sizeof(vertex));
+ memcpy(vertices->data + (3 * sizeof(vertex)), &v3, sizeof(vertex));
+ memcpy(vertices->data + (4 * sizeof(vertex)), &v1, sizeof(vertex));
+ memcpy(vertices->data + (5 * sizeof(vertex)), &v4, sizeof(vertex));
+
+ return vertices;
+}
+
+
+utils::dataContainer* meshUtility::createNinePatchXY(const math::vec3F& position, const math::sizeF& size, const math::rectF& uvRect)
+{
+ utils::dataContainer* tempVertices = new utils::dataContainer();
+ tempVertices->size = (4 * 4) * sizeof(vertex);
+ tempVertices->data = (char*)malloc(tempVertices->size);
+
+ uint32_t tempVertexIndex = 0;
+ for (int y = 0; y < 4; y++)
+ {
+ float piecePosY = math::calcNinePatchPosition(y, size.height) + position.y;
+ float pieceUVY = math::calcNinePatchUV(y, uvRect.height) + uvRect.y;
+ for (int x = 0; x < 4; x++)
+ {
+ float piecePosX = math::calcNinePatchPosition(x, size.width) + position.x;
+ float pieceUVX = math::calcNinePatchUV(x, uvRect.width) + uvRect.x;
+ vertex v = vertex(piecePosX, piecePosY, 0, pieceUVX, pieceUVY);
+ memcpy(tempVertices->data + (tempVertexIndex * sizeof(vertex)), &v, sizeof(vertex));
+ tempVertexIndex++;
+ }
+ }
+
+ utils::dataContainer* vertices = new utils::dataContainer();
+ vertices->size = (9 * 6) * sizeof(vertex);
+ vertices->data = (char*)malloc(vertices->size);
+
+ uint32_t vertexIndex = 0;
+ for (int yy = 0; yy < 3; yy++)
+ {
+ for (int xx = 0; xx < 3; xx++)
+ {
+ int offset = xx + (yy * 4);
+
+ memcpy(vertices->data + ((vertexIndex + 0) * sizeof(vertex)), tempVertices->data + ((5 + offset) * sizeof(vertex)), sizeof(vertex));
+ memcpy(vertices->data + ((vertexIndex + 1) * sizeof(vertex)), tempVertices->data + ((1 + offset) * sizeof(vertex)), sizeof(vertex));
+ memcpy(vertices->data + ((vertexIndex + 2) * sizeof(vertex)), tempVertices->data + ((0 + offset) * sizeof(vertex)), sizeof(vertex));
+ memcpy(vertices->data + ((vertexIndex + 3) * sizeof(vertex)), tempVertices->data + ((4 + offset) * sizeof(vertex)), sizeof(vertex));
+ memcpy(vertices->data + ((vertexIndex + 4) * sizeof(vertex)), tempVertices->data + ((5 + offset) * sizeof(vertex)), sizeof(vertex));
+ memcpy(vertices->data + ((vertexIndex + 5) * sizeof(vertex)), tempVertices->data + ((0 + offset) * sizeof(vertex)), sizeof(vertex));
+
+ vertexIndex += 6;
+ }
+ }
+
+ delete(tempVertices);
+ return vertices;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/meshUtility.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/meshUtility.h
new file mode 100644
index 0000000..043b1e1
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/meshUtility.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include "math.h"
+#include "utils.h"
+
+class meshUtility
+{
+public:
+
+ typedef struct vertex
+ {
+ math::vec3F position;
+ math::vec2F texcoord;
+
+ vertex()
+ {
+ position = math::vec3F();
+ texcoord = math::vec2F();
+ }
+
+ vertex(const float& positionX, const float& positionY, const float& positionZ,
+ const float& texcoordX, const float& texcoordY)
+ {
+ position = math::vec3F(positionX, positionY, positionZ);
+ texcoord = math::vec2F(texcoordX, texcoordY);
+ }
+
+ vertex(const math::vec3F& position, const math::vec2F& texcoord) : position(position), texcoord(texcoord) {}
+
+ } vertex;
+
+ static utils::dataContainer* createQuadXY(const math::vec3F& position, const math::sizeF& size, const math::rectF& uvRect);
+ static utils::dataContainer* createNinePatchXY(const math::vec3F& position, const math::sizeF& size, const math::rectF& uvRect);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchip.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchip.cpp
new file mode 100644
index 0000000..32f4bdb
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchip.cpp
@@ -0,0 +1,66 @@
+#include "modchip.h"
+#include "xboxInternals.h"
+#include "globalTypes.h"
+
+uint8_t modchip::inputByte(uint16_t port)
+{
+ unsigned char value;
+ __asm {
+ mov dx, port
+ in al, dx
+ mov value, al
+ }
+ return value;
+}
+
+void modchip::outputByte(uint16_t port, uint8_t value)
+{
+ __asm {
+ mov dx, port
+ mov al, value
+ out dx, al
+ }
+}
+
+modchipType modchip::detectModchip()
+{
+ //int x = inputByte(0xf701);
+ //if (inputByte(0xEE) == 0x55)
+ //{
+ // uint8_t currentBank = inputByte(0xef);
+ // outputByte(0xef, 0x0B);
+ // bool isXtremium = (inputByte(0xef) & 0x0c) == 0x0c;
+ // outputByte(0xef, currentBank);
+ // return isXtremium ? modchipTypeXtremium : modchipTypeXenium;
+ //}
+ if (inputByte(0xf500) == 0xE1)
+ {
+ return modchipTypeXecuter;
+ }
+ //if (inputByte(0xf701) == 0xf1 || inputByte(0xf701) == 0xf2 || inputByte(0xf701) == 0xf8)
+ //{
+ // return modchipTypeSmartxx;
+ //}
+ if (inputByte(0xdead) == 0xaf)
+ {
+ return modchipTypeModxo;
+ }
+ if (inputByte(0xf701) == 0x11) // Lattice Based
+ {
+ return modchipTypeAladdin1mb;
+ }
+ if (inputByte(0xf701) == 0x15) // Xilinx Based
+ {
+ return modchipTypeAladdin1mb;
+ }
+ if (inputByte(0xf701) == 0x69) // Latice Based
+ {
+ return modchipTypeAladdin2mb;
+ }
+ if (inputByte(0x1912) != 0xff)
+ {
+ return modchipTypeXchanger;
+ }
+ // Just default to xenium if unknown
+ return modchipTypeXenium;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchip.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchip.h
new file mode 100644
index 0000000..aa221e1
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchip.h
@@ -0,0 +1,96 @@
+#pragma once
+
+#include "utils.h"
+#include "xboxInternals.h"
+#include "globalTypes.h"
+#include "DisplayDrivers\displayDriver.h"
+#include "DisplayDrivers\displayFactory.h"
+
+#ifndef TOOLS
+#include "settingsManager.h"
+#endif
+
+#define LPC_MEMORY_BASE 0xFF000000u
+
+#define LED_COLOR_OFF 0
+#define LED_COLOR_RED 1
+#define LED_COLOR_GREEN 2
+#define LED_COLOR_AMBER 3
+#define LED_COLOR_BLUE 4
+#define LED_COLOR_PURPLE 5
+#define LED_COLOR_TEAL 6
+#define LED_COLOR_WHITE 7
+
+typedef struct supportInfo
+{
+ bool supportsLed;
+ bool supportsLcd;
+ bool supportsLcdInfo;
+ bool supportsLcdBacklight;
+ bool supportsLcdContrast;
+ bool supportsRecovery;
+} supportInfo;
+
+class modchip
+{
+public:
+
+ static uint8_t inputByte(uint16_t port);
+ static void outputByte(uint16_t port, uint8_t value);
+ static modchipType detectModchip();
+
+ virtual void setLedColor(uint8_t ledColor) = 0;
+
+ virtual uint32_t getSlotCount() = 0;
+ virtual uint32_t getFlashSize(bool recovery) = 0;
+ virtual void disableRecovery() = 0;
+ virtual bool isValidBankSize(uint32_t size) = 0;
+ virtual bool isValidFlashSize(bool recovery, uint32_t size) = 0;
+ virtual uint32_t getBankSize(uint8_t bank) = 0;
+ virtual uint32_t getBankMemOffset(uint8_t bank) = 0;
+ virtual uint32_t getBankStartOffset(uint8_t bank) = 0;
+ virtual uint8_t getBankFromIdAndSlots(uint8_t id, uint8_t slots) = 0;
+ virtual utils::dataContainer* readBank(uint8_t bank) = 0;
+ virtual void eraseBank(uint8_t bank) = 0;
+ virtual void writeBank(uint8_t bank, utils::dataContainer* dataContainer) = 0;
+ virtual bool verifyBank(uint8_t bank, utils::dataContainer* dataContainer) = 0;
+
+ virtual uint8_t getFlashBankCount(bool recovery) = 0;
+ virtual uint8_t getFlashBank(bool recovery, uint8_t bank) = 0;
+ virtual bankType getFlashBankType(bool recovery, uint8_t bank) = 0;
+ virtual utils::dataContainer* readFlash(bool recovery) = 0;
+
+ virtual void launchBank(uint8_t bank, uint8_t ledColor) = 0;
+ virtual void launchTsop() = 0;
+ virtual void launchRecovery() = 0;
+
+#ifndef TOOLS
+ virtual void loadSettings(settingsState& settings) = 0;
+ virtual void saveSettings(settingsState& settings) = 0;
+#endif
+
+ virtual utils::dataContainer* getInstallerLogo() = 0;
+
+ virtual displayDriver* getDisplayDriver(bool current) = 0;
+ virtual supportInfo getSupportInfo(bool current) = 0;
+ virtual uint8_t getLcdModeCount() = 0;
+ virtual char* getLcdModeString(uint8_t lcdMode) = 0;
+ virtual uint8_t getLcdModelCount(bool current) = 0;
+ virtual char* getLcdModelString(bool current, uint8_t lcdModel) = 0;
+ virtual uint8_t getLcdAddressCount(bool current) = 0;
+ virtual char* getLcdAddressString(bool current, uint8_t lcdAddress) = 0;
+
+ virtual void lcdSetCursorPosition(uint8_t row, uint8_t col) = 0;
+ virtual void lcdInit() = 0;
+ virtual void lcdPrintMessage(const char* message) = 0;
+ virtual void lcdSetBacklight(uint8_t value) = 0;
+ virtual void lcdSetContrast(uint8_t value) = 0;
+
+private:
+
+ virtual void setBank(uint8_t bank) = 0;
+ virtual uint8_t getBank() = 0;
+ virtual bool isEraseMemOffset(uint32_t memOffset) = 0;
+ virtual bool isProtectedMemOffset(uint32_t memOffset) = 0;
+ virtual void sectorErase(uint32_t offset) = 0;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipAladdin1mb.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipAladdin1mb.cpp
new file mode 100644
index 0000000..969c2ed
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipAladdin1mb.cpp
@@ -0,0 +1,551 @@
+#include "modchipAladdin1mb.h"
+#include "crc32.h"
+#include "settingsManager.h"
+#include "globalDefines.h"
+#include "stringUtility.h"
+
+//#define ALADDIN1MB_INSTALLER_LOGO_BANK ALADDIN1MB_BANK_PROMETHEOS2
+//#define ALADDIN1MB_INSTALLER_LOGO_OFFSET (0x1f0000 - 0x1c0000)
+
+//Bank_PrometheOS = 0x84 0x000000 - 0x07ffff Sector Size 4096 Total 524288 (See below)
+//Bank1_256k = 0x86 0x080000 - 0x0bffff Sector Size 4096 Total 262144
+//Bank_Bootloader = 0x87 0x0C0000 - 0x0fffff Sector Size 4096 Total 262144
+
+//0x000000 - 0x07efff Sector Size 4096 Total 520192 (PrometheOS)
+//0x07f000 - 0x07ffff Sector Size 4096 Total 4096 (Settings)
+
+modchipAladdin1mb::modchipAladdin1mb()
+{
+ mBank = ALADDIN1MB_BANK_BOOTLOADER;
+}
+
+void modchipAladdin1mb::setLedColor(uint8_t ledColor)
+{
+ //outputByte(ALADDIN1MB_REGISTER_LED, ledColor);
+}
+
+uint32_t modchipAladdin1mb::getSlotCount()
+{
+ return 1;
+}
+
+uint32_t modchipAladdin1mb::getFlashSize(bool recovery)
+{
+ return recovery ? 0 : (1 * 1024 * 1024);
+}
+
+void modchipAladdin1mb::disableRecovery()
+{
+}
+
+bool modchipAladdin1mb::isValidBankSize(uint32_t size)
+{
+ return size == (256 * 1024);
+}
+
+bool modchipAladdin1mb::isValidFlashSize(bool recovery, uint32_t size)
+{
+ return size == getFlashSize(recovery);
+}
+
+uint32_t modchipAladdin1mb::getBankSize(uint8_t bank)
+{
+ if (bank == ALADDIN1MB_BANK_BOOTLOADER)
+ {
+ return 256 * 1024;
+ }
+ if (bank == ALADDIN1MB_BANK_PROMETHEOS)
+ {
+ return 512 * 1024;
+ }
+ if (bank == ALADDIN1MB_BANK_SLOT1_256K)
+ {
+ return 256 * 1024;
+ }
+ return 0;
+}
+
+uint32_t modchipAladdin1mb::getBankMemOffset(uint8_t bank)
+{
+ if (bank == ALADDIN1MB_BANK_SLOT1_256K)
+ {
+ return 0x080000;
+ }
+ if (bank == ALADDIN1MB_BANK_BOOTLOADER)
+ {
+ return 0x0c0000;
+ }
+ if (bank == ALADDIN1MB_BANK_PROMETHEOS)
+ {
+ return 0x000000;
+ }
+ return 0;
+}
+
+uint32_t modchipAladdin1mb::getBankStartOffset(uint8_t bank)
+{
+ return 0;
+}
+
+uint8_t modchipAladdin1mb::getBankFromIdAndSlots(uint8_t id, uint8_t slots)
+{
+ if (id == 0 && slots == 1)
+ {
+ return ALADDIN1MB_BANK_SLOT1_256K;
+ }
+ return 0;
+}
+
+utils::dataContainer* modchipAladdin1mb::readBank(uint8_t bank)
+{
+ setBank(bank);
+ uint32_t bankSize = getBankSize(bank);
+ utils::dataContainer* dataContainer = new utils::dataContainer(bankSize);
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)(LPC_MEMORY_BASE + getBankStartOffset(bank));
+ memcpy(dataContainer->data, (void*)&lpcMemMap[0], bankSize);
+ setBank(ALADDIN1MB_BANK_BOOTLOADER);
+ return dataContainer;
+}
+
+void modchipAladdin1mb::eraseBank(uint8_t bank)
+{
+ setBank(bank);
+
+ setLedColor(LED_COLOR_AMBER);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ uint32_t memOffset = getBankMemOffset(bank);
+ uint32_t startOffset = getBankStartOffset(bank);
+ uint32_t bankSize = getBankSize(bank);
+
+ uint32_t offset = 0;
+ while (offset < bankSize)
+ {
+ if (isEraseMemOffset(memOffset + startOffset + offset))
+ {
+ sectorErase(offset);
+ }
+ offset += 4096;
+ }
+
+ setBank(ALADDIN1MB_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+}
+
+void modchipAladdin1mb::writeBank(uint8_t bank, utils::dataContainer* dataContainer)
+{
+ setBank(bank);
+
+ setLedColor(LED_COLOR_BLUE);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)(LPC_MEMORY_BASE + getBankStartOffset(bank));
+
+ for (uint32_t i = 0; i < dataContainer->size; i++)
+ {
+ uint8_t value = (uint8_t)dataContainer->data[i];
+ lpcMemMap[0x5555] = 0xAA;
+ lpcMemMap[0x2AAA] = 0x55;
+ lpcMemMap[0x5555] = 0xA0;
+ lpcMemMap[i] = value;
+ while (lpcMemMap[i] != value);
+ }
+ lpcMemMap[0] = 0xF0;
+
+ setBank(ALADDIN1MB_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+}
+
+bool modchipAladdin1mb::verifyBank(uint8_t bank, utils::dataContainer* dataContainer)
+{
+ setBank(bank);
+
+ utils::dataContainer* writtenData = readBank(bank);
+
+ setLedColor(LED_COLOR_PURPLE);
+
+ bool ok = true;
+ for (uint32_t i = 0; i < dataContainer->size; i++)
+ {
+ if (writtenData->data[i] == dataContainer->data[i])
+ {
+ continue;
+ }
+ ok = false;
+ break;
+ }
+
+ delete(writtenData);
+
+ setBank(ALADDIN1MB_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+ return ok;
+}
+
+uint8_t modchipAladdin1mb::getFlashBankCount(bool recovery)
+{
+ return 3;
+}
+
+uint8_t modchipAladdin1mb::getFlashBank(bool recovery, uint8_t bank)
+{
+ const uint8_t banks[] = {
+ ALADDIN1MB_BANK_SLOT1_256K,
+ ALADDIN1MB_BANK_BOOTLOADER,
+ ALADDIN1MB_BANK_PROMETHEOS
+ };
+ return recovery ? 0 : banks[bank];
+}
+
+bankType modchipAladdin1mb::getFlashBankType(bool recovery, uint8_t bank)
+{
+ const bankType banks[] = {
+ bankTypeUser,
+ bankTypeSystem,
+ bankTypeSystem,
+ };
+ return recovery ? bankTypeUser : banks[bank];
+}
+
+utils::dataContainer* modchipAladdin1mb::readFlash(bool recovery)
+{
+ utils::dataContainer* result = new utils::dataContainer(getFlashSize(recovery));
+ for (uint8_t i = 0; i < getFlashBankCount(recovery); i++)
+ {
+ uint8_t bank = getFlashBank(recovery, i);
+ uint32_t memOffset = getBankMemOffset(bank);
+ utils::dataContainer* bankData = readBank(bank);
+ memcpy(result->data + memOffset, bankData->data, bankData->size);
+ delete(bankData);
+ }
+ return result;
+}
+
+void modchipAladdin1mb::launchBank(uint8_t bank, uint8_t ledColor)
+{
+ DWORD scratch;
+ HalReadSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, &scratch);
+ HalWriteSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, scratch & ~SCRATCH_REGISTER_BITVALUE_NO_ANIMATION);
+ setBank(bank);
+ setLedColor(ledColor);
+ HalReturnToFirmware(RETURN_FIRMWARE_REBOOT);
+}
+
+void modchipAladdin1mb::launchTsop()
+{
+ DWORD scratch;
+ HalReadSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, &scratch);
+ HalWriteSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, scratch & ~SCRATCH_REGISTER_BITVALUE_NO_ANIMATION);
+ setBank(ALADDIN1MB_BANK_TSOP);
+ setLedColor(LED_COLOR_OFF);
+ HalReturnToFirmware(RETURN_FIRMWARE_REBOOT);
+}
+
+void modchipAladdin1mb::launchRecovery()
+{
+}
+
+#ifndef TOOLS
+
+void modchipAladdin1mb::loadSettings(settingsState& settings)
+{
+ setBank(ALADDIN1MB_SETTINGS_BANK);
+
+ setLedColor(LED_COLOR_WHITE);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ memcpy(&settings, (void*)&lpcMemMap[ALADDIN1MB_SETTINGS_OFFSET], sizeof(settings));
+ uint32_t checksum = crc32::calculate(((uint8_t*)&settings) + sizeof(uint32_t), sizeof(settings) - sizeof(uint32_t));
+
+ setBank(ALADDIN1MB_BANK_BOOTLOADER);
+
+ if (checksum != settings.checksum || versioning::compareVersion(settings.version, settingsManager::getVersion()) != 0)
+ {
+ settingsManager::initSettings();
+ settingsManager::saveSettings();
+ }
+
+ setLedColor(settingsManager::getLedColor());
+}
+
+void modchipAladdin1mb::saveSettings(settingsState& settings)
+{
+ setBank(ALADDIN1MB_SETTINGS_BANK);
+
+ settings.checksum = crc32::calculate(((uint8_t*)&settings) + sizeof(uint32_t), sizeof(settings) - sizeof(uint32_t));
+ utils::dataContainer* settingsData = new utils::dataContainer((char*)&settings, sizeof(settings), sizeof(settings));
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ setLedColor(LED_COLOR_AMBER);
+ sectorErase(ALADDIN1MB_SETTINGS_OFFSET);
+
+ setLedColor(LED_COLOR_BLUE);
+ for (uint32_t i = 0; i < settingsData->size; i++)
+ {
+ uint8_t value = (uint8_t)settingsData->data[i];
+ lpcMemMap[0x5555] = 0xAA;
+ lpcMemMap[0x2AAA] = 0x55;
+ lpcMemMap[0x5555] = 0xA0;
+ lpcMemMap[ALADDIN1MB_SETTINGS_OFFSET + i] = value;
+ while (lpcMemMap[ALADDIN1MB_SETTINGS_OFFSET + i] != value);
+ }
+ lpcMemMap[0] = 0xF0;
+
+ setBank(ALADDIN1MB_BANK_BOOTLOADER);
+
+ setLedColor(settingsManager::getLedColor());
+}
+
+#endif
+
+utils::dataContainer* modchipAladdin1mb::getInstallerLogo()
+{
+ utils::dataContainer* installerLogo = new utils::dataContainer(32768);
+ return installerLogo;
+}
+
+displayDriver* modchipAladdin1mb::getDisplayDriver(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ uint8_t lcdModel = settingsManager::getLcdModel(current);
+ if (lcdMode == 1)
+ {
+ if (lcdModel == 0)
+ {
+ return displayFactory::getDisplay(displayVariantHD44780Aladdin);
+ }
+ if (lcdModel == 1)
+ {
+ return displayFactory::getDisplay(displayVariantSPI2PARAladdin);
+ }
+ }
+ if (lcdMode == 2)
+ {
+ if (lcdModel == 0)
+ {
+ return displayFactory::getDisplay(displayVariantHD44780LPC);
+ }
+ if (lcdModel == 1)
+ {
+ return displayFactory::getDisplay(displayVariantLCDXXXXLPC);
+ }
+ }
+ return NULL;
+}
+
+supportInfo modchipAladdin1mb::getSupportInfo(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ uint8_t lcdModel = settingsManager::getLcdModel(current);
+
+ supportInfo info;
+ info.supportsLed = false;
+ info.supportsLcd = true;
+
+ bool lcdInfo = false;
+ bool backlight = false;
+ bool contrast = false;
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver != NULL)
+ {
+ driver->getSupport(lcdInfo, backlight, contrast);
+ }
+ info.supportsLcdInfo = lcdInfo;
+ info.supportsLcdBacklight = backlight;
+ info.supportsLcdContrast = contrast;
+
+ info.supportsRecovery = false;
+ return info;
+}
+
+uint8_t modchipAladdin1mb::getLcdModeCount()
+{
+ return 3;
+}
+
+char* modchipAladdin1mb::getLcdModeString(uint8_t lcdMode)
+{
+ if (lcdMode == 1)
+ {
+ return strdup("Aladdin");
+ }
+ if (lcdMode == 2)
+ {
+ return strdup("SMBUS");
+ }
+ return strdup("Disabled");
+}
+
+uint8_t modchipAladdin1mb::getLcdModelCount(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ if (lcdMode == 1)
+ {
+ return 2;
+ }
+ if (lcdMode == 2)
+ {
+ return 2;
+ }
+ return 0;
+}
+
+char* modchipAladdin1mb::getLcdModelString(bool current, uint8_t lcdModel)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return strdup("");
+ }
+ return driver->getModel();
+}
+
+uint8_t modchipAladdin1mb::getLcdAddressCount(bool current)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return 0;
+ }
+ return driver->getI2cAddressCount();
+}
+
+char* modchipAladdin1mb::getLcdAddressString(bool current, uint8_t lcdAddress)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return strdup("");
+ }
+ uint8_t address = driver->getI2cAddress(lcdAddress);
+ char* result = stringUtility::formatString("0x%2X", address);
+ return result;
+}
+
+void modchipAladdin1mb::lcdSetCursorPosition(uint8_t row, uint8_t col)
+{
+ if (row > 3)
+ {
+ row = 3;
+ }
+ if (col > 19)
+ {
+ col = 19;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setCursorPosition(row, col);
+}
+
+void modchipAladdin1mb::lcdInit()
+{
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->init();
+}
+
+void modchipAladdin1mb::lcdPrintMessage(const char* message)
+{
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->printMessage(message);
+}
+
+void modchipAladdin1mb::lcdSetBacklight(uint8_t value)
+{
+ if (value > 100)
+ {
+ value = 100;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setBacklight(value);
+}
+
+void modchipAladdin1mb::lcdSetContrast(uint8_t value)
+{
+ if (value > 100)
+ {
+ value = 100;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setContrast(value);
+}
+
+// Private
+
+void modchipAladdin1mb::setBank(uint8_t bank)
+{
+ mBank = bank;
+ outputByte(ALADDIN_REGISTER_BANKING, mBank);
+}
+
+uint8_t modchipAladdin1mb::getBank()
+{
+ return mBank;
+}
+
+bool modchipAladdin1mb::isEraseMemOffset(uint32_t memOffset)
+{
+ return (memOffset % 4096) == 0;
+}
+
+bool modchipAladdin1mb::isProtectedMemOffset(uint32_t memOffset)
+{
+ if (isProtectedMemOffset(memOffset))
+ {
+ return true;
+ }
+ return false;
+}
+
+void modchipAladdin1mb::sectorErase(uint32_t offset)
+{
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+ lpcMemMap[0x5555] = 0xAA;
+ lpcMemMap[0x2AAA] = 0x55;
+ lpcMemMap[0x5555] = 0x80;
+ lpcMemMap[0x5555] = 0xAA;
+ lpcMemMap[0x2AAA] = 0x55;
+ lpcMemMap[offset] = 0x30;
+ while(lpcMemMap[0] != lpcMemMap[0]);
+ lpcMemMap[0x5555] = 0xF0;
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipAladdin1mb.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipAladdin1mb.h
new file mode 100644
index 0000000..66cfb77
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipAladdin1mb.h
@@ -0,0 +1,70 @@
+#pragma once
+
+#include "modchip.h"
+#include "xboxInternals.h"
+#include "settingsManager.h"
+
+class modchipAladdin1mb : public modchip
+{
+public:
+
+ modchipAladdin1mb();
+ void setLedColor(uint8_t ledColor);
+
+ uint32_t getSlotCount();
+ uint32_t getFlashSize(bool recovery);
+ void disableRecovery();
+ bool isValidBankSize(uint32_t size);
+ bool isValidFlashSize(bool recovery, uint32_t size);
+ uint32_t getBankSize(uint8_t bank);
+ uint32_t getBankMemOffset(uint8_t bank);
+ uint32_t getBankStartOffset(uint8_t bank);
+ uint8_t getBankFromIdAndSlots(uint8_t id, uint8_t slots);
+ utils::dataContainer* readBank(uint8_t bank);
+ void eraseBank(uint8_t bank);
+ void writeBank(uint8_t bank, utils::dataContainer* dataContainer);
+ bool verifyBank(uint8_t bank, utils::dataContainer* dataContainer);
+
+ uint8_t getFlashBankCount(bool recovery);
+ uint8_t getFlashBank(bool recovery, uint8_t bank);
+ bankType getFlashBankType(bool recovery, uint8_t bank);
+ utils::dataContainer* readFlash(bool recovery);
+
+ void launchBank(uint8_t bank, uint8_t ledColor);
+ void launchTsop();
+ void launchRecovery();
+
+#ifndef TOOLS
+ void loadSettings(settingsState& settings);
+ void saveSettings(settingsState& settings);
+#endif
+
+ utils::dataContainer* getInstallerLogo();
+
+ displayDriver* getDisplayDriver(bool current);
+ supportInfo getSupportInfo(bool current);
+ uint8_t getLcdModeCount();
+ char* getLcdModeString(uint8_t lcdMode);
+ uint8_t getLcdModelCount(bool current);
+ char* getLcdModelString(bool current, uint8_t lcdModel);
+ uint8_t getLcdAddressCount(bool current);
+ char* getLcdAddressString(bool current, uint8_t lcdAddress);
+
+ void lcdSetCursorPosition(uint8_t row, uint8_t col);
+ void lcdInit();
+ void lcdPrintMessage(const char* message);
+ void lcdSetBacklight(uint8_t value);
+ void lcdSetContrast(uint8_t value);
+
+private:
+
+ void setBank(uint8_t bank);
+ uint8_t getBank();
+ bool isEraseMemOffset(uint32_t memOffset);
+ bool isProtectedMemOffset(uint32_t memOffset);
+ void sectorErase(uint32_t offset);
+
+private:
+
+ uint8_t mBank;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipAladdin2mb.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipAladdin2mb.cpp
new file mode 100644
index 0000000..6652979
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipAladdin2mb.cpp
@@ -0,0 +1,708 @@
+#include "modchipAladdin2mb.h"
+#include "crc32.h"
+#include "settingsManager.h"
+#include "globalDefines.h"
+#include "stringUtility.h"
+
+
+
+//#define READ_ARRAY_CMD 0xff
+//#define RD_STATUS_CMD 0x70
+//#define CLR_STATUS_CMD 0x50
+//#define ERASE_SET_CMD 0x20
+//#define ERASE_CNF_CMD 0xd0
+//#define PRG_SETUP_CMD 0x40
+//#define SECTOR_ERASE_SET_CMD 0x30
+//#define WSM_BUSY 0x80
+
+//#define ALADDIN2MB_INSTALLER_LOGO_BANK ALADDIN2MB_BANK_PROMETHEOS2
+//#define ALADDIN2MB_INSTALLER_LOGO_OFFSET (0x1f0000 - 0x1c0000)
+
+//Bank_PrometheOS = 0x84 0x000000 - 0x07ffff Sector Size 4096 Total 524288 (See below)
+//Bank1_256k = 0x86 0x080000 - 0x0bffff Sector Size 4096 Total 262144
+//Bank_Bootloader = 0x87 0x0C0000 - 0x0fffff Sector Size 4096 Total 262144
+
+//0x000000 - 0x07efff Sector Size 4096 Total 520192 (PrometheOS)
+//0x07f000 - 0x07ffff Sector Size 4096 Total 4096 (Settings)
+
+modchipAladdin2mb::modchipAladdin2mb()
+{
+ mBank = ALADDIN2MB_BANK_BOOTLOADER;
+}
+
+void modchipAladdin2mb::setLedColor(uint8_t ledColor)
+{
+ //outputByte(ALADDIN2MB_REGISTER_LED, ledColor);
+}
+
+uint32_t modchipAladdin2mb::getSlotCount()
+{
+ return 4;
+}
+
+uint32_t modchipAladdin2mb::getFlashSize(bool recovery)
+{
+ return recovery ? 0 : (2 * 1024 * 1024);
+}
+
+void modchipAladdin2mb::disableRecovery()
+{
+}
+
+bool modchipAladdin2mb::isValidBankSize(uint32_t size)
+{
+ return size == (256 * 1024) || size == (512 * 1024) || size == (1024 * 1024);
+}
+
+bool modchipAladdin2mb::isValidFlashSize(bool recovery, uint32_t size)
+{
+ return size == getFlashSize(recovery);
+}
+
+uint32_t modchipAladdin2mb::getBankSize(uint8_t bank)
+{
+ if (bank == ALADDIN2MB_BANK_SLOT1_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == ALADDIN2MB_BANK_SLOT2_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == ALADDIN2MB_BANK_SLOT3_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == ALADDIN2MB_BANK_SLOT4_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == ALADDIN2MB_BANK_SLOT1_512K)
+ {
+ return 512 * 1024;
+ }
+ if (bank == ALADDIN2MB_BANK_SLOT2_512K)
+ {
+ return 512 * 1024;
+ }
+ if (bank == ALADDIN2MB_BANK_SLOT1_1024K)
+ {
+ return 1024 * 1024;
+ }
+ if (bank == ALADDIN2MB_BANK_BOOTLOADER)
+ {
+ return 256 * 1024;
+ }
+ if (bank == ALADDIN2MB_BANK_PROMETHEOS1)
+ {
+ return 256 * 1024;
+ }
+ if (bank == ALADDIN2MB_BANK_PROMETHEOS2)
+ {
+ return 256 * 1024;
+ }
+ if (bank == ALADDIN2MB_BANK_PROMETHEOS3)
+ {
+ return 256 * 1024;
+ }
+ return 0;
+}
+
+uint32_t modchipAladdin2mb::getBankMemOffset(uint8_t bank)
+{
+ if (bank == ALADDIN2MB_BANK_SLOT1_256K)
+ {
+ return 0x000000;
+ }
+ if (bank == ALADDIN2MB_BANK_SLOT2_256K)
+ {
+ return 0x040000;
+ }
+ if (bank == ALADDIN2MB_BANK_SLOT3_256K)
+ {
+ return 0x080000;
+ }
+ if (bank == ALADDIN2MB_BANK_SLOT4_256K)
+ {
+ return 0x0c0000;
+ }
+ if (bank == ALADDIN2MB_BANK_SLOT1_512K)
+ {
+ return 0x000000;
+ }
+ if (bank == ALADDIN2MB_BANK_SLOT2_512K)
+ {
+ return 0x080000;
+ }
+ if (bank == ALADDIN2MB_BANK_SLOT1_1024K)
+ {
+ return 0x000000;
+ }
+ if (bank == ALADDIN2MB_BANK_BOOTLOADER)
+ {
+ return 0x100000;
+ }
+ if (bank == ALADDIN2MB_BANK_PROMETHEOS1)
+ {
+ return 0x140000;
+ }
+ if (bank == ALADDIN2MB_BANK_PROMETHEOS2)
+ {
+ return 0x180000;
+ }
+ if (bank == ALADDIN2MB_BANK_PROMETHEOS3)
+ {
+ return 0x1c0000;
+ }
+ return 0;
+}
+
+uint32_t modchipAladdin2mb::getBankStartOffset(uint8_t bank)
+{
+ return 0;
+}
+
+uint8_t modchipAladdin2mb::getBankFromIdAndSlots(uint8_t id, uint8_t slots)
+{
+ if (id == 0 && slots == 1)
+ {
+ return ALADDIN2MB_BANK_SLOT1_256K;
+ }
+ if (id == 1 && slots == 1)
+ {
+ return ALADDIN2MB_BANK_SLOT2_256K;
+ }
+ if (id == 2 && slots == 1)
+ {
+ return ALADDIN2MB_BANK_SLOT3_256K;
+ }
+ if (id == 3 && slots == 1)
+ {
+ return ALADDIN2MB_BANK_SLOT4_256K;
+ }
+ if (id == 0 && slots == 2)
+ {
+ return ALADDIN2MB_BANK_SLOT1_512K;
+ }
+ if (id == 2 && slots == 2)
+ {
+ return ALADDIN2MB_BANK_SLOT2_512K;
+ }
+ if (id == 0 && slots == 4)
+ {
+ return ALADDIN2MB_BANK_SLOT1_1024K;
+ }
+ return 0;
+}
+
+utils::dataContainer* modchipAladdin2mb::readBank(uint8_t bank)
+{
+ setBank(bank);
+ uint32_t bankSize = getBankSize(bank);
+ utils::dataContainer* dataContainer = new utils::dataContainer(bankSize);
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)(LPC_MEMORY_BASE + getBankStartOffset(bank));
+ memcpy(dataContainer->data, (void*)&lpcMemMap[0], bankSize);
+ setBank(ALADDIN2MB_BANK_BOOTLOADER);
+ return dataContainer;
+}
+
+void modchipAladdin2mb::eraseBank(uint8_t bank)
+{
+ setBank(bank);
+
+ setLedColor(LED_COLOR_AMBER);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ uint32_t memOffset = getBankMemOffset(bank);
+ uint32_t startOffset = getBankStartOffset(bank);
+ uint32_t bankSize = getBankSize(bank);
+
+ uint32_t offset = 0;
+ while (offset < bankSize)
+ {
+ if (isEraseMemOffset(memOffset + startOffset + offset))
+ {
+ sectorErase(offset);
+ }
+ offset += 4096;
+ }
+
+ setBank(ALADDIN2MB_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+}
+
+void modchipAladdin2mb::writeBank(uint8_t bank, utils::dataContainer* dataContainer)
+{
+ setBank(bank);
+
+ setLedColor(LED_COLOR_BLUE);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)(LPC_MEMORY_BASE + getBankStartOffset(bank));
+
+ for (uint32_t i = 0; i < dataContainer->size; i++)
+ {
+ uint8_t value = (uint8_t)dataContainer->data[i];
+ lpcMemMap[0] = 0x50;
+ lpcMemMap[0] = 0x40;
+ lpcMemMap[i] = value;
+ lpcMemMap[0] = 0x70;
+ uint8_t status = lpcMemMap[0];
+ while((lpcMemMap[0] & 0x80) != 0x80);
+ }
+ lpcMemMap[0] = 0xff;
+
+ setBank(ALADDIN2MB_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+}
+
+bool modchipAladdin2mb::verifyBank(uint8_t bank, utils::dataContainer* dataContainer)
+{
+ setBank(bank);
+
+ utils::dataContainer* writtenData = readBank(bank);
+
+ setLedColor(LED_COLOR_PURPLE);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ bool ok = true;
+ for (uint32_t i = 0; i < dataContainer->size; i++)
+ {
+ if (writtenData->data[i] == dataContainer->data[i])
+ {
+ continue;
+ }
+ ok = false;
+ break;
+ }
+
+ delete(writtenData);
+
+ setBank(ALADDIN2MB_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+ return ok;
+}
+
+uint8_t modchipAladdin2mb::getFlashBankCount(bool recovery)
+{
+ return 8;
+}
+
+uint8_t modchipAladdin2mb::getFlashBank(bool recovery, uint8_t bank)
+{
+ const uint8_t banks[] = {
+ ALADDIN2MB_BANK_SLOT1_256K,
+ ALADDIN2MB_BANK_SLOT2_256K,
+ ALADDIN2MB_BANK_SLOT3_256K,
+ ALADDIN2MB_BANK_SLOT4_256K,
+ ALADDIN2MB_BANK_BOOTLOADER,
+ ALADDIN2MB_BANK_PROMETHEOS1,
+ ALADDIN2MB_BANK_PROMETHEOS2,
+ ALADDIN2MB_BANK_PROMETHEOS3,
+ };
+ return recovery ? 0 : banks[bank];
+}
+
+bankType modchipAladdin2mb::getFlashBankType(bool recovery, uint8_t bank)
+{
+ const bankType banks[] = {
+ bankTypeUser,
+ bankTypeUser,
+ bankTypeUser,
+ bankTypeUser,
+ bankTypeSystem,
+ bankTypeSystem,
+ bankTypeSystem,
+ bankTypeSystem,
+ };
+ return recovery ? bankTypeUser : banks[bank];
+}
+
+utils::dataContainer* modchipAladdin2mb::readFlash(bool recovery)
+{
+ utils::dataContainer* result = new utils::dataContainer(getFlashSize(recovery));
+ for (uint8_t i = 0; i < getFlashBankCount(recovery); i++)
+ {
+ uint8_t bank = getFlashBank(recovery, i);
+ uint32_t memOffset = getBankMemOffset(bank);
+ utils::dataContainer* bankData = readBank(bank);
+ memcpy(result->data + memOffset, bankData->data, bankData->size);
+ delete(bankData);
+ }
+ return result;
+}
+
+void modchipAladdin2mb::launchBank(uint8_t bank, uint8_t ledColor)
+{
+ DWORD scratch;
+ HalReadSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, &scratch);
+ HalWriteSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, scratch & ~SCRATCH_REGISTER_BITVALUE_NO_ANIMATION);
+ setBank(bank);
+ setLedColor(ledColor);
+ HalReturnToFirmware(RETURN_FIRMWARE_REBOOT);
+}
+
+void modchipAladdin2mb::launchTsop()
+{
+ DWORD scratch;
+ HalReadSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, &scratch);
+ HalWriteSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, scratch & ~SCRATCH_REGISTER_BITVALUE_NO_ANIMATION);
+ setBank(ALADDIN2MB_BANK_TSOP);
+ setLedColor(LED_COLOR_OFF);
+ HalReturnToFirmware(RETURN_FIRMWARE_REBOOT);
+}
+
+void modchipAladdin2mb::launchRecovery()
+{
+}
+
+#ifndef TOOLS
+
+void modchipAladdin2mb::loadSettings(settingsState& settings)
+{
+ setBank(ALADDIN2MB_SETTINGS_BANK);
+
+ setLedColor(LED_COLOR_WHITE);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ memcpy(&settings, (void*)&lpcMemMap[ALADDIN2MB_SETTINGS_OFFSET], sizeof(settings));
+ uint32_t checksum = crc32::calculate(((uint8_t*)&settings) + sizeof(uint32_t), sizeof(settings) - sizeof(uint32_t));
+
+ setBank(ALADDIN2MB_BANK_BOOTLOADER);
+
+ if (checksum != settings.checksum || versioning::compareVersion(settings.version, settingsManager::getVersion()) != 0)
+ {
+ settingsManager::initSettings();
+ settingsManager::saveSettings();
+ }
+
+ setLedColor(settingsManager::getLedColor());
+}
+
+void modchipAladdin2mb::saveSettings(settingsState& settings)
+{
+ setBank(ALADDIN2MB_SETTINGS_BANK);
+
+ settings.checksum = crc32::calculate(((uint8_t*)&settings) + sizeof(uint32_t), sizeof(settings) - sizeof(uint32_t));
+ utils::dataContainer* settingsData = new utils::dataContainer((char*)&settings, sizeof(settings), sizeof(settings));
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ setLedColor(LED_COLOR_AMBER);
+ sectorErase(ALADDIN2MB_SETTINGS_OFFSET);
+
+ setLedColor(LED_COLOR_BLUE);
+ for (uint32_t i = 0; i < settingsData->size; i++)
+ {
+ uint8_t value = (uint8_t)settingsData->data[i];
+ lpcMemMap[0] = 0x50;
+ lpcMemMap[0] = 0x40;
+ lpcMemMap[ALADDIN2MB_SETTINGS_OFFSET + i] = value;
+ lpcMemMap[0] = 0x70;
+ uint8_t status = lpcMemMap[0];
+ while((lpcMemMap[0] & 0x80) != 0x80);
+ }
+ lpcMemMap[0] = 0xff;
+
+ setBank(ALADDIN2MB_BANK_BOOTLOADER);
+
+ setLedColor(settingsManager::getLedColor());
+}
+
+#endif
+
+utils::dataContainer* modchipAladdin2mb::getInstallerLogo()
+{
+ setBank(ALADDIN2MB_INSTALLER_LOGO_BANK);
+
+ setLedColor(LED_COLOR_WHITE);
+
+ utils::dataContainer* installerLogo = new utils::dataContainer(32768);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+ memcpy(installerLogo->data, (void*)&lpcMemMap[ALADDIN2MB_INSTALLER_LOGO_OFFSET], installerLogo->size);
+
+ setBank(ALADDIN2MB_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+ return installerLogo;
+}
+
+displayDriver* modchipAladdin2mb::getDisplayDriver(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ uint8_t lcdModel = settingsManager::getLcdModel(current);
+ if (lcdMode == 1)
+ {
+ if (lcdModel == 0)
+ {
+ return displayFactory::getDisplay(displayVariantHD44780Aladdin);
+ }
+ if (lcdModel == 1)
+ {
+ return displayFactory::getDisplay(displayVariantSPI2PARAladdin);
+ }
+ }
+ if (lcdMode == 2)
+ {
+ if (lcdModel == 0)
+ {
+ return displayFactory::getDisplay(displayVariantHD44780LPC);
+ }
+ if (lcdModel == 1)
+ {
+ return displayFactory::getDisplay(displayVariantLCDXXXXLPC);
+ }
+ }
+ return NULL;
+}
+
+supportInfo modchipAladdin2mb::getSupportInfo(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ uint8_t lcdModel = settingsManager::getLcdModel(current);
+
+ supportInfo info;
+ info.supportsLed = false;
+ info.supportsLcd = true;
+
+ bool lcdInfo = false;
+ bool backlight = false;
+ bool contrast = false;
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver != NULL)
+ {
+ driver->getSupport(lcdInfo, backlight, contrast);
+ }
+ info.supportsLcdInfo = lcdInfo;
+ info.supportsLcdBacklight = backlight;
+ info.supportsLcdContrast = contrast;
+
+ info.supportsRecovery = false;
+ return info;
+}
+
+uint8_t modchipAladdin2mb::getLcdModeCount()
+{
+ return 3;
+}
+
+char* modchipAladdin2mb::getLcdModeString(uint8_t lcdMode)
+{
+ if (lcdMode == 1)
+ {
+ return strdup("Aladdin");
+ }
+ if (lcdMode == 2)
+ {
+ return strdup("SMBUS");
+ }
+ return strdup("Disabled");
+}
+
+uint8_t modchipAladdin2mb::getLcdModelCount(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ if (lcdMode == 1)
+ {
+ return 2;
+ }
+ if (lcdMode == 2)
+ {
+ return 2;
+ }
+ return 0;
+}
+
+char* modchipAladdin2mb::getLcdModelString(bool current, uint8_t lcdModel)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return strdup("");
+ }
+ return driver->getModel();
+}
+
+uint8_t modchipAladdin2mb::getLcdAddressCount(bool current)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return 0;
+ }
+ return driver->getI2cAddressCount();
+}
+
+char* modchipAladdin2mb::getLcdAddressString(bool current, uint8_t lcdAddress)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return strdup("");
+ }
+ uint8_t address = driver->getI2cAddress(lcdAddress);
+ char* result = stringUtility::formatString("0x%2X", address);
+ return result;
+}
+
+void modchipAladdin2mb::lcdSetCursorPosition(uint8_t row, uint8_t col)
+{
+ if (row > 3)
+ {
+ row = 3;
+ }
+ if (col > 19)
+ {
+ col = 19;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setCursorPosition(row, col);
+}
+
+void modchipAladdin2mb::lcdInit()
+{
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->init();
+}
+
+void modchipAladdin2mb::lcdPrintMessage(const char* message)
+{
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->printMessage(message);
+}
+
+void modchipAladdin2mb::lcdSetBacklight(uint8_t value)
+{
+ if (value > 100)
+ {
+ value = 100;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setBacklight(value);
+}
+
+void modchipAladdin2mb::lcdSetContrast(uint8_t value)
+{
+ if (value > 100)
+ {
+ value = 100;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setContrast(value);
+}
+
+// Private
+
+void modchipAladdin2mb::setBank(uint8_t bank)
+{
+ mBank = bank;
+ outputByte(ALADDIN_REGISTER_BANKING, mBank);
+}
+
+uint8_t modchipAladdin2mb::getBank()
+{
+ return mBank;
+}
+
+bool modchipAladdin2mb::isEraseMemOffset(uint32_t memOffset)
+{
+ return (memOffset % 4096) == 0;
+}
+
+bool modchipAladdin2mb::isProtectedMemOffset(uint32_t memOffset)
+{
+ if (isProtectedMemOffset(memOffset))
+ {
+ return true;
+ }
+ return false;
+}
+
+void modchipAladdin2mb::sectorErase(uint32_t offset)
+{
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ // Unprotect mem if needed
+ uint8_t originalBank = getBank();
+ setBank(ALADDIN2MB_BANK_MEM_REGISTER);
+ bool isProtected = lpcMemMap[0x000002] != 0;
+ if (isProtected == true)
+ {
+ for(int i = 0x00; i < 0x23; i++)
+ {
+ if (i == 0x22)
+ {
+ lpcMemMap[0x1FC002] = 0x00;
+ }
+ else if (i == 0x21)
+ {
+ lpcMemMap[0x1FA002] = 0x00;
+ }
+ else if (i == 0x20)
+ {
+ lpcMemMap[0x1F8002] = 0x00;
+ }
+ else
+ {
+ lpcMemMap[(i << 16) | 0x000002] = 0x00;
+ }
+ }
+ }
+ lpcMemMap[0x400000] = 0xff;
+ setBank(originalBank);
+
+ // Erase sector
+ lpcMemMap[0] = 0x50;
+ lpcMemMap[0] = 0x30;
+ lpcMemMap[offset] = 0xD0;
+ lpcMemMap[0] = 0x70;
+ while((lpcMemMap[0] & 0x80) != 0x80);
+ lpcMemMap[0] = 0xff;
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipAladdin2mb.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipAladdin2mb.h
new file mode 100644
index 0000000..ea2f807
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipAladdin2mb.h
@@ -0,0 +1,73 @@
+#pragma once
+
+#include "modchip.h"
+#include "xboxInternals.h"
+
+#ifndef TOOLS
+#include "settingsManager.h"
+#endif
+
+class modchipAladdin2mb : public modchip
+{
+public:
+
+ modchipAladdin2mb();
+ void setLedColor(uint8_t ledColor);
+
+ uint32_t getSlotCount();
+ uint32_t getFlashSize(bool recovery);
+ void disableRecovery();
+ bool isValidBankSize(uint32_t size);
+ bool isValidFlashSize(bool recovery, uint32_t size);
+ uint32_t getBankSize(uint8_t bank);
+ uint32_t getBankMemOffset(uint8_t bank);
+ uint32_t getBankStartOffset(uint8_t bank);
+ uint8_t getBankFromIdAndSlots(uint8_t id, uint8_t slots);
+ utils::dataContainer* readBank(uint8_t bank);
+ void eraseBank(uint8_t bank);
+ void writeBank(uint8_t bank, utils::dataContainer* dataContainer);
+ bool verifyBank(uint8_t bank, utils::dataContainer* dataContainer);
+
+ uint8_t getFlashBankCount(bool recovery);
+ uint8_t getFlashBank(bool recovery, uint8_t bank);
+ bankType getFlashBankType(bool recovery, uint8_t bank);
+ utils::dataContainer* readFlash(bool recovery);
+
+ void launchBank(uint8_t bank, uint8_t ledColor);
+ void launchTsop();
+ void launchRecovery();
+
+#ifndef TOOLS
+ void loadSettings(settingsState& settings);
+ void saveSettings(settingsState& settings);
+#endif
+
+ utils::dataContainer* getInstallerLogo();
+
+ displayDriver* getDisplayDriver(bool current);
+ supportInfo getSupportInfo(bool current);
+ uint8_t getLcdModeCount();
+ char* getLcdModeString(uint8_t lcdMode);
+ uint8_t getLcdModelCount(bool current);
+ char* getLcdModelString(bool current, uint8_t lcdModel);
+ uint8_t getLcdAddressCount(bool current);
+ char* getLcdAddressString(bool current, uint8_t lcdAddress);
+
+ void lcdSetCursorPosition(uint8_t row, uint8_t col);
+ void lcdInit();
+ void lcdPrintMessage(const char* message);
+ void lcdSetBacklight(uint8_t value);
+ void lcdSetContrast(uint8_t value);
+
+private:
+
+ void setBank(uint8_t bank);
+ uint8_t getBank();
+ bool isEraseMemOffset(uint32_t memOffset);
+ bool isProtectedMemOffset(uint32_t memOffset);
+ void sectorErase(uint32_t offset);
+
+private:
+
+ uint8_t mBank;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipDummy.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipDummy.cpp
new file mode 100644
index 0000000..bd4cac2
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipDummy.cpp
@@ -0,0 +1,630 @@
+#include "modchipDummy.h"
+#include "crc32.h"
+#include "settingsManager.h"
+#include "stringUtility.h"
+
+#define DUMMY_BANK_TSOP 0
+#define DUMMY_BANK_BOOTLOADER 1
+#define DUMMY_BANK_PROMETHEOS1 2
+#define DUMMY_BANK_PROMETHEOS2 10
+#define DUMMY_BANK_SLOT1_256K 3
+#define DUMMY_BANK_SLOT2_256K 4
+#define DUMMY_BANK_SLOT3_256K 5
+#define DUMMY_BANK_SLOT4_256K 6
+#define DUMMY_BANK_SLOT1_512K 7
+#define DUMMY_BANK_SLOT2_512K 8
+#define DUMMY_BANK_SLOT1_1024K 9
+
+#define DUMMY_SETTINGS_BANK DUMMY_BANK_PROMETHEOS2
+#define DUMMY_SETTINGS_OFFSET (0x1f8000 - 0x1c0000)
+#define DUMMY_INSTALLER_LOGO_BANK DUMMY_BANK_PROMETHEOS2
+#define DUMMY_INSTALLER_LOGO_OFFSET (0x1f0000 - 0x1c0000)
+
+#define DUMMY_LCD_DELAY 2
+#define DUMMY_LCD_COMMAND_MODE 0x80
+#define DUMMY_LCD_DATA_MODE 0x40
+
+#define DUMMY_US2066_DISPLAY_MODE 0x08
+#define DUMMY_US2066_DISPLAY_MODE_OFF_FLAG 0x00
+#define DUMMY_US2066_DISPLAY_MODE_ON_FLAG 0x04
+#define DUMMY_US2066_DISPLAY_MODE_CURSOR_OFF_FLAG 0x00
+#define DUMMY_US2066_DISPLAY_MODE_CURSOR_ON_FLAG 0x02
+#define DUMMY_US2066_DISPLAY_MODE_BLINK_OFF_FLAG 0x00
+#define DUMMY_US2066_DISPLAY_MODE_BLINK_ON_FLAG 0x01
+
+#define DUMMY_US2066_EXTENDED_MODE 0x08
+#define DUMMY_US2066_EXTENDED_MODE_5DOT_FLAG 0x00
+#define DUMMY_US2066_EXTENDED_MODE_6DOT_FLAG 0x04
+#define DUMMY_US2066_EXTENDED_MODE_INVERT_CURSOR_OFF_FLAG 0x00
+#define DUMMY_US2066_EXTENDED_MODE_INVERT_CURSOR_FLAG 0x02
+#define DUMMY_US2066_EXTENDED_MODE_1TO2ROWS_FLAG 0x00
+#define DUMMY_US2066_EXTENDED_MODE_3TO4ROWS_FLAG 0x01
+
+
+// commands
+#define DUMMY_LCD_CLEARDISPLAY 0x01
+#define DUMMY_LCD_RETURNHOME 0x02
+#define DUMMY_LCD_ENTRYMODESET 0x04
+#define DUMMY_LCD_DISPLAYCONTROL 0x08
+#define DUMMY_LCD_CURSORSHIFT 0x10
+#define DUMMY_LCD_FUNCTIONSET 0x20
+#define DUMMY_LCD_SETCGRAMADDR 0x40
+#define DUMMY_LCD_SETDDRAMADDR 0x80
+
+// flags for display entry mode
+#define DUMMY_LCD_ENTRYRIGHT 0x00
+#define DUMMY_LCD_ENTRYLEFT 0x02
+#define DUMMY_LCD_ENTRYSHIFTINCREMENT 0x01
+#define DUMMY_LCD_ENTRYSHIFTDECREMENT 0x00
+
+// flags for display on/off control
+#define DUMMY_LCD_DISPLAYON 0x04
+#define DUMMY_LCD_DISPLAYOFF 0x00
+#define DUMMY_LCD_CURSORON 0x02
+#define DUMMY_LCD_CURSOROFF 0x00
+#define DUMMY_LCD_BLINKON 0x01
+#define DUMMY_LCD_BLINKOFF 0x00
+
+// flags for display/cursor shift
+#define DUMMY_LCD_DISPLAYMOVE 0x08
+#define DUMMY_LCD_CURSORMOVE 0x00
+#define DUMMY_LCD_MOVERIGHT 0x04
+#define DUMMY_LCD_MOVELEFT 0x00
+
+// flags for function set
+#define DUMMY_LCD_8BITMODE 0x10
+#define DUMMY_LCD_4BITMODE 0x00
+#define DUMMY_LCD_2LINE 0x08
+#define DUMMY_LCD_1LINE 0x00
+#define DUMMY_LCD_5x10DOTS 0x04
+#define DUMMY_LCD_5x8DOTS 0x00
+
+// flags for backlight control
+#define DUMMY_LCD_BACKLIGHT B00001000
+#define DUMMY_LCD_NOBACKLIGHT B00000000
+
+// values for graphtype in calls to init_bargraph and character geometry
+#define DUMMY_LCDI2C_VERTICAL_BAR_GRAPH 1
+#define DUMMY_LCDI2C_HORIZONTAL_BAR_GRAPH 2
+#define DUMMY_LCDI2C_HORIZONTAL_LINE_GRAPH 3
+#define DUMMY_LCD_CHARACTER_HORIZONTAL_DOTS 5
+#define DUMMY_LCD_CHARACTER_VERTICAL_DOTS 8
+
+#define DUMMY_LCD_EN B00000100 // Enable bit
+#define DUMMY_LCD_RW B00000010 // Read/Write bit
+#define DUMMY_LCD_RS B00000001 // Register select bit
+
+//Bank1_256k = 3 0x000000 - 0x03ffff Sector Size 65536 Total 262144
+//Bank2_256k = 4 0x040000 - 0x07ffff Sector Size 65536 Total 262144
+//Bank3_256k = 5 0x080000 - 0x0bffff Sector Size 65536 Total 262144
+//Bank4_256k = 6 0x0c0000 - 0x0fffff Sector Size 65536 Total 262144
+//Bank1_512k = 7 0x000000 - 0x07ffff Sector Size 65536 Total 524288
+//Bank2_512k = 8 0x080000 - 0x0fffff Sector Size 65536 Total 524288
+//Bank1_1024k = 9 0x000000 - 0x0fffff Sector Size 65536 Total 1048576
+//Bank_PrometheOS = 2 0x100000 - 0x17ffff Sector Size 65536 Total 524288
+//Bank_Bootloader = 1 0x180000 - 0x1bffff Sector Size 65536 Total 262144
+//Bank_Recovery = 10 0x1c0000 - 0x1fffff See Below Total 262144
+
+//0x1c0000 - 0x1effff Sector Size 65536 Total 196608 (PrometheOS Continued)
+//0x1f0000 - 0x1f7fff Sector Size 32768 Total 32768 (Installer Logo)
+//0x1f8000 - 0x1f9fff Sector Size 8192 Total 8192 (Settings)
+//0x1fa000 - 0x1fbfff Sector Size 8192 Total 8192 (Spare)
+//0x1fc000 - 0x1fffff Sector Size 16384 Total 16384 (Spare)
+
+//https://github.com/mrkaleArduinoLib/LiquidCrystal_I2C/blob/master/src/LiquidCrystal_I2C.cpp
+
+modchipDummy::modchipDummy()
+{
+ mFlashData = (uint8_t*)malloc(getFlashSize(false));
+}
+
+modchipDummy::~modchipDummy()
+{
+ free(mFlashData);
+}
+
+void modchipDummy::setLedColor(uint8_t ledColor)
+{
+}
+
+uint32_t modchipDummy::getSlotCount()
+{
+ return 4;
+}
+
+uint32_t modchipDummy::getFlashSize(bool recovery)
+{
+ return recovery ? 0 : (2 * 1024 * 1024);
+}
+
+void modchipDummy::disableRecovery()
+{
+}
+
+bool modchipDummy::isValidBankSize(uint32_t size)
+{
+ return size == (256 * 1024) || size == (512 * 1024) || size == (1024 * 1024);
+}
+
+bool modchipDummy::isValidFlashSize(bool recovery, uint32_t size)
+{
+ return size == getFlashSize(recovery);
+}
+
+uint32_t modchipDummy::getBankSize(uint8_t bank)
+{
+ if (bank == DUMMY_BANK_BOOTLOADER)
+ {
+ return 256 * 1024;
+ }
+ if (bank == DUMMY_BANK_PROMETHEOS1)
+ {
+ return 512 * 1024;
+ }
+ if (bank == DUMMY_BANK_PROMETHEOS2)
+ {
+ return 256 * 1024;
+ }
+ if (bank == DUMMY_BANK_SLOT1_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == DUMMY_BANK_SLOT2_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == DUMMY_BANK_SLOT3_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == DUMMY_BANK_SLOT4_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == DUMMY_BANK_SLOT1_512K)
+ {
+ return 512 * 1024;
+ }
+ if (bank == DUMMY_BANK_SLOT2_512K)
+ {
+ return 512 * 1024;
+ }
+ if (bank == DUMMY_BANK_SLOT1_1024K)
+ {
+ return 1024 * 1024;
+ }
+ return 0;
+}
+
+uint32_t modchipDummy::getBankMemOffset(uint8_t bank)
+{
+ if (bank == DUMMY_BANK_SLOT1_256K)
+ {
+ return 0x000000;
+ }
+ if (bank == DUMMY_BANK_SLOT2_256K)
+ {
+ return 0x040000;
+ }
+ if (bank == DUMMY_BANK_SLOT2_256K)
+ {
+ return 0x080000;
+ }
+ if (bank == DUMMY_BANK_SLOT4_256K)
+ {
+ return 0x0c0000;
+ }
+ if (bank == DUMMY_BANK_SLOT1_512K)
+ {
+ return 0x000000;
+ }
+ if (bank == DUMMY_BANK_SLOT2_512K)
+ {
+ return 0x080000;
+ }
+ if (bank == DUMMY_BANK_SLOT1_1024K)
+ {
+ return 0x000000;
+ }
+ if (bank == DUMMY_BANK_BOOTLOADER)
+ {
+ return 0x180000;
+ }
+ if (bank == DUMMY_BANK_PROMETHEOS1)
+ {
+ return 0x100000;
+ }
+ if (bank == DUMMY_BANK_PROMETHEOS2)
+ {
+ return 0x1c0000;
+ }
+ return 0;
+}
+
+uint32_t modchipDummy::getBankStartOffset(uint8_t bank)
+{
+ return 0;
+}
+
+uint8_t modchipDummy::getBankFromIdAndSlots(uint8_t id, uint8_t slots)
+{
+ if (id == 0 && slots == 1)
+ {
+ return DUMMY_BANK_SLOT1_256K;
+ }
+ if (id == 1 && slots == 1)
+ {
+ return DUMMY_BANK_SLOT2_256K;
+ }
+ if (id == 2 && slots == 1)
+ {
+ return DUMMY_BANK_SLOT3_256K;
+ }
+ if (id == 3 && slots == 1)
+ {
+ return DUMMY_BANK_SLOT4_256K;
+ }
+ if (id == 0 && slots == 2)
+ {
+ return DUMMY_BANK_SLOT1_512K;
+ }
+ if (id == 2 && slots == 2)
+ {
+ return DUMMY_BANK_SLOT2_512K;
+ }
+ if (id == 0 && slots == 4)
+ {
+ return DUMMY_BANK_SLOT1_1024K;
+ }
+ return 0;
+}
+
+utils::dataContainer* modchipDummy::readBank(uint8_t bank)
+{
+ uint32_t bankSize = getBankSize(bank);
+ utils::dataContainer* dataContainer = new utils::dataContainer(bankSize);
+ memcpy(dataContainer->data, mFlashData + getBankMemOffset(bank), bankSize);
+ return dataContainer;
+}
+
+void modchipDummy::eraseBank(uint8_t bank)
+{
+ uint32_t bankSize = getBankSize(bank);
+ uint32_t memOffset = getBankMemOffset(bank);
+ uint32_t startOffset = getBankStartOffset(bank);
+
+ uint32_t offset = 0;
+ while (offset < bankSize)
+ {
+ if (isEraseMemOffset(memOffset + startOffset + offset))
+ {
+ sectorErase(memOffset + offset);
+ }
+ offset += 8192;
+ }
+}
+
+void modchipDummy::writeBank(uint8_t bank, utils::dataContainer* dataContainer)
+{
+ uint32_t memOffset = getBankMemOffset(bank);
+ for (uint32_t i = 0; i < dataContainer->size; i++)
+ {
+ uint8_t value = (uint8_t)dataContainer->data[i];
+ mFlashData[memOffset + i] = value;
+ }
+}
+
+bool modchipDummy::verifyBank(uint8_t bank, utils::dataContainer* dataContainer)
+{
+ utils::dataContainer* writtenData = readBank(bank);
+
+ bool ok = true;
+ for (uint32_t i = 0; i < dataContainer->size; i++)
+ {
+ if (writtenData->data[i] == dataContainer->data[i])
+ {
+ continue;
+ }
+ ok = false;
+ break;
+ }
+
+ delete(writtenData);
+ return ok;
+}
+
+uint8_t modchipDummy::getFlashBankCount(bool recovery)
+{
+ return recovery ? 0 : 7;
+}
+
+uint8_t modchipDummy::getFlashBank(bool recovery, uint8_t bank)
+{
+ const uint8_t banks[] = {
+ DUMMY_BANK_SLOT1_256K,
+ DUMMY_BANK_SLOT2_256K,
+ DUMMY_BANK_SLOT3_256K,
+ DUMMY_BANK_SLOT4_256K,
+ DUMMY_BANK_BOOTLOADER,
+ DUMMY_BANK_PROMETHEOS1,
+ DUMMY_BANK_PROMETHEOS2,
+ };
+ return recovery ? 0 : banks[bank];
+}
+
+bankType modchipDummy::getFlashBankType(bool recovery, uint8_t bank)
+{
+ const bankType banks[] = {
+ bankTypeUser,
+ bankTypeUser,
+ bankTypeUser,
+ bankTypeUser,
+ bankTypeSystem,
+ bankTypeSystem,
+ bankTypeSystem,
+ };
+ return recovery ? bankTypeUser : banks[bank];
+}
+
+utils::dataContainer* modchipDummy::readFlash(bool recovery)
+{
+ utils::dataContainer* result = new utils::dataContainer(getFlashSize(recovery));
+ for (uint8_t i = 0; i < getFlashBankCount(recovery); i++)
+ {
+ uint8_t bank = getFlashBank(recovery, i);
+ uint32_t memOffset = getBankMemOffset(bank);
+ utils::dataContainer* bankData = readBank(bank);
+ memcpy(result->data + memOffset, bankData->data, bankData->size);
+ delete(bankData);
+ }
+ return result;
+}
+
+void modchipDummy::launchBank(uint8_t bank, uint8_t ledColor)
+{
+}
+
+void modchipDummy::launchTsop()
+{
+}
+
+void modchipDummy::launchRecovery()
+{
+}
+
+#ifndef TOOLS
+
+void modchipDummy::loadSettings(settingsState& settings)
+{
+ uint32_t memOffset = getBankMemOffset(DUMMY_SETTINGS_BANK);
+
+ memcpy(&settings, mFlashData + memOffset + DUMMY_SETTINGS_OFFSET , sizeof(settings));
+ uint32_t checksum = crc32::calculate(((uint8_t*)&settings) + sizeof(uint32_t), sizeof(settings) - sizeof(uint32_t));
+
+ if (checksum != settings.checksum || versioning::compareVersion(settings.version, settingsManager::getVersion()) != 0)
+ {
+ settingsManager::initSettings();
+ settingsManager::saveSettings();
+ }
+}
+
+void modchipDummy::saveSettings(settingsState& settings)
+{
+ uint32_t memOffset = getBankMemOffset(DUMMY_SETTINGS_BANK);
+
+ settings.checksum = crc32::calculate(((uint8_t*)&settings) + sizeof(uint32_t), sizeof(settings) - sizeof(uint32_t));
+ utils::dataContainer* settingsData = new utils::dataContainer((char*)&settings, sizeof(settings), sizeof(settings));
+
+ sectorErase(memOffset + DUMMY_SETTINGS_OFFSET);
+
+ for (uint32_t i = 0; i < settingsData->size; i++)
+ {
+ uint8_t value = (uint8_t)settingsData->data[i];
+ (mFlashData + memOffset + DUMMY_SETTINGS_OFFSET)[i] = value;
+ }
+}
+
+#endif
+
+utils::dataContainer* modchipDummy::getInstallerLogo()
+{
+ uint32_t memOffset = getBankMemOffset(DUMMY_INSTALLER_LOGO_BANK);
+ utils::dataContainer* installerLogo = new utils::dataContainer(32768);
+ memcpy(installerLogo->data, mFlashData + memOffset + DUMMY_INSTALLER_LOGO_OFFSET, installerLogo->size);
+ return installerLogo;
+}
+
+displayDriver* modchipDummy::getDisplayDriver(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ uint8_t lcdModel = settingsManager::getLcdModel(current);
+ if (lcdMode == 1)
+ {
+ if (lcdModel == 0)
+ {
+ return displayFactory::getDisplay(displayVariantHD44780LPC);
+ }
+ if (lcdModel == 1)
+ {
+ return displayFactory::getDisplay(displayVariantLCDXXXXLPC);
+ }
+ }
+ return NULL;
+}
+
+supportInfo modchipDummy::getSupportInfo(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ uint8_t lcdModel = settingsManager::getLcdModel(current);
+ supportInfo info;
+ info.supportsLed = false;
+ info.supportsLcd = true;
+
+ bool lcdInfo = false;
+ bool backlight = false;
+ bool contrast = false;
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver != NULL)
+ {
+ driver->getSupport(lcdInfo, backlight, contrast);
+ }
+ info.supportsLcdInfo = lcdInfo;
+ info.supportsLcdBacklight = backlight;
+ info.supportsLcdContrast = contrast;
+
+ info.supportsRecovery = false;
+ return info;
+}
+
+uint8_t modchipDummy::getLcdModeCount()
+{
+ return 2;
+}
+
+char* modchipDummy::getLcdModeString(uint8_t lcdMode)
+{
+ if (lcdMode == 1)
+ {
+ return strdup("SMBUS");
+ }
+ return strdup("Disabled");
+}
+
+uint8_t modchipDummy::getLcdModelCount(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ if (lcdMode == 1)
+ {
+ return 2;
+ }
+ return 0;
+}
+
+char* modchipDummy::getLcdModelString(bool current, uint8_t lcdModel)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return strdup("");
+ }
+ return driver->getModel();
+}
+
+uint8_t modchipDummy::getLcdAddressCount(bool current)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return 0;
+ }
+ return driver->getI2cAddressCount();
+}
+
+char* modchipDummy::getLcdAddressString(bool current, uint8_t lcdAddress)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return strdup("");
+ }
+ uint8_t address = driver->getI2cAddress(lcdAddress);
+ char* result = stringUtility::formatString("0x%2X", address);
+ return result;
+}
+
+void modchipDummy::lcdSetCursorPosition(uint8_t row, uint8_t col)
+{
+ if (row > 3)
+ {
+ row = 3;
+ }
+ if (col > 19)
+ {
+ col = 19;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setCursorPosition(row, col);
+}
+
+void modchipDummy::lcdInit()
+{
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->init();
+}
+
+void modchipDummy::lcdPrintMessage(const char* message)
+{
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->printMessage(message);
+}
+
+void modchipDummy::lcdSetBacklight(uint8_t value)
+{
+ if (value > 100)
+ {
+ value = 100;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setBacklight(value);
+}
+
+void modchipDummy::lcdSetContrast(uint8_t value)
+{
+ if (value > 100)
+ {
+ value = 100;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setContrast(value);
+}
+
+// Private
+
+void modchipDummy::setBank(uint8_t bank)
+{
+}
+
+uint8_t modchipDummy::getBank()
+{
+ return 0;
+}
+
+bool modchipDummy::isEraseMemOffset(uint32_t memOffset)
+{
+ return (memOffset % 8192) == 0;
+}
+
+bool modchipDummy::isProtectedMemOffset(uint32_t memOffset)
+{
+ return false;
+}
+
+void modchipDummy::sectorErase(uint32_t offset)
+{
+ memset(mFlashData + offset, 0, 8192);
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipDummy.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipDummy.h
new file mode 100644
index 0000000..ef9a9f8
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipDummy.h
@@ -0,0 +1,74 @@
+#pragma once
+
+#include "modchip.h"
+#include "xboxInternals.h"
+
+#ifndef TOOLS
+#include "settingsManager.h"
+#endif
+
+class modchipDummy : public modchip
+{
+public:
+
+ modchipDummy();
+ ~modchipDummy();
+ void setLedColor(uint8_t ledColor);
+
+ uint32_t getSlotCount();
+ uint32_t getFlashSize(bool recovery);
+ void disableRecovery();
+ bool isValidBankSize(uint32_t size);
+ bool isValidFlashSize(bool recovery, uint32_t size);
+ uint32_t getBankSize(uint8_t bank);
+ uint32_t getBankMemOffset(uint8_t bank);
+ uint32_t getBankStartOffset(uint8_t bank);
+ uint8_t getBankFromIdAndSlots(uint8_t id, uint8_t slots);
+ utils::dataContainer* readBank(uint8_t bank);
+ void eraseBank(uint8_t bank);
+ void writeBank(uint8_t bank, utils::dataContainer* dataContainer);
+ bool verifyBank(uint8_t bank, utils::dataContainer* dataContainer);
+
+ uint8_t getFlashBankCount(bool recovery);
+ uint8_t getFlashBank(bool recovery, uint8_t bank);
+ bankType getFlashBankType(bool recovery, uint8_t bank);
+ utils::dataContainer* readFlash(bool recovery);
+
+ void launchBank(uint8_t bank, uint8_t ledColor);
+ void launchTsop();
+ void launchRecovery();
+
+#ifndef TOOLS
+ void loadSettings(settingsState& settings);
+ void saveSettings(settingsState& settings);
+#endif
+
+ utils::dataContainer* getInstallerLogo();
+
+ displayDriver* getDisplayDriver(bool current);
+ supportInfo getSupportInfo(bool current);
+ uint8_t getLcdModeCount();
+ char* getLcdModeString(uint8_t lcdMode);
+ uint8_t getLcdModelCount(bool current);
+ char* getLcdModelString(bool current, uint8_t lcdModel);
+ uint8_t getLcdAddressCount(bool current);
+ char* getLcdAddressString(bool current, uint8_t lcdAddress);
+
+ void lcdSetCursorPosition(uint8_t row, uint8_t col);
+ void lcdInit();
+ void lcdPrintMessage(const char* message);
+ void lcdSetBacklight(uint8_t value);
+ void lcdSetContrast(uint8_t value);
+
+private:
+
+ void setBank(uint8_t bank);
+ uint8_t getBank();
+ bool isEraseMemOffset(uint32_t memOffset);
+ bool isProtectedMemOffset(uint32_t memOffset);
+ void sectorErase(uint32_t offset);
+
+private:
+
+ uint8_t* mFlashData;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipModxo.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipModxo.cpp
new file mode 100644
index 0000000..084fd98
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipModxo.cpp
@@ -0,0 +1,767 @@
+#include "modchipModxo.h"
+#include "crc32.h"
+#include "settingsManager.h"
+#include "globalDefines.h"
+#include "stringUtility.h"
+
+//
+//#define MODXO_BANK_SLOT1_256K 0x04
+//#define MODXO_BANK_SLOT2_256K 0x05
+//#define MODXO_BANK_SLOT3_256K 0x06
+//#define MODXO_BANK_SLOT4_256K 0x07
+//#define MODXO_BANK_SLOT5_256K 0x08
+//#define MODXO_BANK_SLOT6_256K 0x09
+//#define MODXO_BANK_SLOT7_256K 0x0a
+//#define MODXO_BANK_SLOT8_256K 0x0b
+//#define MODXO_BANK_SLOT9_256K 0x0c
+//#define MODXO_BANK_SLOT10_256K 0x0d
+//#define MODXO_BANK_SLOT11_256K 0x0e
+//#define MODXO_BANK_SLOT12_256K 0x0f
+//
+//#define MODXO_BANK_PROM1_512K 0x40
+//#define MODXO_BANK_PROM2_512K 0x41
+//#define MODXO_BANK_SLOT1_512K 0x42
+//#define MODXO_BANK_SLOT2_512K 0x43
+//#define MODXO_BANK_SLOT3_512K 0x44
+//#define MODXO_BANK_SLOT4_512K 0x45
+//#define MODXO_BANK_SLOT5_512K 0x46
+//#define MODXO_BANK_SLOT6_512K 0x47
+//
+//#define MODXO_BANK_PROM1_1024K 0x80
+//#define MODXO_BANK_SLOT1_1024K 0x81
+//#define MODXO_BANK_SLOT2_1024K 0x82
+//#define MODXO_BANK_SLOT3_1024K 0x83
+//#define MODXO_BANK_SLOT4_1024K 0x84
+//#define MODXO_BANK_SLOT5_1024K 0x85
+//#define MODXO_BANK_SLOT6_1024K 0x86
+//#define MODXO_BANK_SLOT7_1024K 0x87
+//#define MODXO_BANK_SLOT8_1024K 0x88
+//#define MODXO_BANK_SLOT9_1024K 0x89
+//#define MODXO_BANK_SLOT10_1024K 0x8a
+//#define MODXO_BANK_SLOT11_1024K 0x8b
+//#define MODXO_BANK_SLOT12_1024K 0x8c
+//#define MODXO_BANK_SLOT13_1024K 0x8d
+//#define MODXO_BANK_SLOT14_1024K 0x8e
+//#define MODXO_BANK_SLOT15_1024K 0x8f
+
+#define MODXO_SETTINGS_BANK MODXO_BANK_PROMETHEOS2
+#define MODXO_SETTINGS_OFFSET (0x040000 - 0x1000)
+
+//Bank Name Bank Value Offset Size
+//
+//Tsop 1XXX XXXX NA NA
+//
+//Modxo_256k 0000 0000 0x000000 0x040000
+//PromBL_256k 0000 0001 0x040000 0x040000
+//PromOS1_256k 0000 0010 0x080000 0x040000
+//PromOS2_256k 0000 0011 0x0c0000 0x040000
+//
+//Bank01_256k 0000 0100 0x100000 0x040000
+//Bank02_256k 0000 0101 0x140000 0x040000
+//Bank03_256k 0000 0110 0x180000 0x040000
+//Bank04_256k 0000 0111 0x1c0000 0x040000
+//
+//Bank05_256k 0000 1000 0x200000 0x040000 (4+16mb only)
+//Bank06_256k 0000 1001 0x240000 0x040000 (4+16mb only)
+//Bank07_256k 0000 1010 0x280000 0x040000 (4+16mb only)
+//Bank08_256k 0000 1011 0x2c0000 0x040000 (4+16mb only)
+//
+//Bank09_256k 0000 1100 0x300000 0x040000 (4+16mb only)
+//Bank10_256k 0000 1101 0x340000 0x040000 (4+16mb only)
+//Bank11_256k 0000 1110 0x380000 0x040000 (4+16mb only)
+//Bank12_256k 0000 1111 0x3c0000 0x040000 (4+16mb only)
+//
+//Prom01_512k 0001 0000 0x000000 0x080000
+//Prom02_512k 0001 0001 0x080000 0x080000
+//Bank01_512k 0001 0010 0x100000 0x080000
+//Bank02_512k 0001 0011 0x180000 0x080000
+//Bank03_512k 0001 0100 0x200000 0x080000 (4+16mb only)
+//Bank04_512k 0001 0101 0x280000 0x080000 (4+16mb only)
+//Bank05_512k 0001 0110 0x300000 0x080000 (4+16mb only)
+//Bank06_512k 0001 0111 0x380000 0x080000 (4+16mb only)
+//
+//Prom01_1024k 0010 0000 0x000000 0x100000
+//Bank01_1024k 0010 0001 0x100000 0x100000
+//Bank02_1024k 0010 0010 0x200000 0x100000 (4+16mb only)
+//Bank03_1024k 0010 0011 0x300000 0x100000 (4+16mb only)
+//Bank04_1024k 0010 0100 0x400000 0x100000 (16mb only)
+//Bank05_1024k 0010 0101 0x500000 0x100000 (16mb only)
+//Bank06_1024k 0010 0110 0x600000 0x100000 (16mb only)
+//Bank07_1024k 0010 0111 0x700000 0x100000 (16mb only)
+//Bank08_1024k 0010 1000 0x800000 0x100000 (16mb only)
+//Bank09_1024k 0010 1001 0x900000 0x100000 (16mb only)
+//Bank10_1024k 0010 1010 0xa00000 0x100000 (16mb only)
+//Bank11_1024k 0010 1011 0xb00000 0x100000 (16mb only)
+//Bank12_1024k 0010 1100 0xc00000 0x100000 (16mb only)
+//Bank13_1024k 0010 1101 0xd00000 0x100000 (16mb only)
+//Bank14_1024k 0010 1110 0xe00000 0x100000 (16mb only)
+//Bank15_1024k 0010 1111 0xf00000 0x100000 (16mb only)
+
+static uint8_t getI2cAddress(bool current)
+{
+ int lcdAddressArray[] = { 0x27, 0x3C, 0x3D, 0x3F };
+ return lcdAddressArray[settingsManager::getLcdAddress(current)];
+}
+
+static char* getI2cAddressString(bool current)
+{
+ char* lcdAddressArray[] = { "0x27", "0x3C", "0x3D", "0x3F" };
+ return strdup(lcdAddressArray[settingsManager::getLcdAddress(current)]);
+}
+
+modchipModxo::modchipModxo()
+{
+ mBank = MODXO_BANK_BOOTLOADER;
+}
+
+void modchipModxo::setLedColor(uint8_t ledColor)
+{
+ do
+ {
+ Sleep(10);
+ }
+ while (inputByte(MODXO_REGISTER_LED_COMMAND) == 0);
+
+ outputByte(MODXO_REGISTER_LED_COMMAND, MODXO_LED_CMD_SELECT_STRIP);
+ outputByte(MODXO_REGISTER_LED_DATA, 0);
+
+ outputByte(MODXO_REGISTER_LED_COMMAND, MODXO_LED_CMD_SET_PIX_COUNT);
+ outputByte(MODXO_REGISTER_LED_DATA, 255); //This count is Pixel Count - 1, thus 255 is 256 pixels
+
+ outputByte(MODXO_REGISTER_LED_COMMAND, MODXO_LED_CMD_FILL_STRIP_COL);
+ outputByte(MODXO_REGISTER_LED_DATA, (ledColor & 1) == 1 ? 0xff : 0x00);
+ outputByte(MODXO_REGISTER_LED_DATA, (ledColor & 2) == 2 ? 0xff : 0x00);
+ outputByte(MODXO_REGISTER_LED_DATA, (ledColor & 4) == 4 ? 0xff : 0x00);
+
+ outputByte(MODXO_REGISTER_LED_COMMAND, MODXO_LED_CMD_UPDATE_STRIPS);
+}
+
+void modchipModxo::setFixedLedColor(uint8_t ledColor)
+{
+ do
+ {
+ Sleep(10);
+ }
+ while (inputByte(MODXO_REGISTER_LED_COMMAND) == 0);
+
+ outputByte(MODXO_REGISTER_LED_COMMAND, MODXO_LED_CMD_SELECT_COLOR);
+ outputByte(MODXO_REGISTER_LED_DATA, ledColor);
+}
+
+uint32_t modchipModxo::getSlotCount()
+{
+ uint32_t size = inputByte(MODXO_REGISTER_SIZE);
+ uint32_t totalSlots = 4;
+ if (size >= 16)
+ {
+ totalSlots = 16;
+ }
+ else if (size >= 8)
+ {
+ totalSlots = 12;
+ }
+ else if (size >= 4)
+ {
+ totalSlots = 8;
+ }
+ return totalSlots;
+}
+
+uint32_t modchipModxo::getFlashSize(bool recovery)
+{
+ uint32_t size = inputByte(MODXO_REGISTER_SIZE);
+ return recovery ? 0 : (size << 20);
+}
+
+void modchipModxo::disableRecovery()
+{
+}
+
+bool modchipModxo::isValidBankSize(uint32_t size)
+{
+ return size == (256 * 1024) || size == (512 * 1024) || size == (1024 * 1024);
+}
+
+bool modchipModxo::isValidFlashSize(bool recovery, uint32_t size)
+{
+ return size == getFlashSize(recovery) || size == (1024 * 1024);
+}
+
+uint32_t modchipModxo::getBankSize(uint8_t bank)
+{
+ // Return 0 if tsop bank
+ if ((bank & 0xc0) == 0xc0)
+ {
+ return 0;
+ }
+
+ uint32_t flashSizeMb = inputByte(MODXO_REGISTER_SIZE) << 20;
+ uint32_t bankSizeKb = 1 << (18 + ((bank & 0xc0) >> 6));
+ uint32_t flashOffset = (bank & 0x3f) * bankSizeKb;
+
+ // Return 0 if offset greater than flash size
+ if ((flashOffset + bankSizeKb) > flashSizeMb)
+ {
+ return 0;
+ }
+
+ return bankSizeKb;
+}
+
+uint32_t modchipModxo::getBankMemOffset(uint8_t bank)
+{
+ // Return 0 if tsop bank
+ if ((bank & 0xc0) == 0xc0)
+ {
+ return 0;
+ }
+
+ uint32_t flashSizeMb = inputByte(MODXO_REGISTER_SIZE) << 20;
+ uint32_t bankSizeKb = 1 << (18 + ((bank & 0xc0) >> 6));
+ uint32_t flashOffset = (bank & 0x3f) * bankSizeKb;
+
+ // Return 0 if offset greater than flash size
+ if ((flashOffset + bankSizeKb) > flashSizeMb)
+ {
+ return 0;
+ }
+
+ return flashOffset;
+}
+
+uint32_t modchipModxo::getBankStartOffset(uint8_t bank)
+{
+ return 0;
+}
+
+uint8_t modchipModxo::getBankFromIdAndSlots(uint8_t id, uint8_t slots)
+{
+ uint32_t flashSizeMb = inputByte(MODXO_REGISTER_SIZE) << 20;
+ uint32_t bankSizeKb = slots << 18;
+ uint32_t idOffset = 4 / slots;
+ uint8_t tempSlots = slots >> 1;
+ uint8_t tempId = (uint8_t)((id / slots) + idOffset);
+ uint32_t flashOffset = tempId * bankSizeKb;
+
+ // Return 0 if offset greater than flash size
+ if ((flashOffset + bankSizeKb) > flashSizeMb)
+ {
+ return 0;
+ }
+
+ return (tempSlots << 6) | tempId;
+}
+
+utils::dataContainer* modchipModxo::readBank(uint8_t bank)
+{
+ setBank(bank);
+ uint32_t bankSize = getBankSize(bank);
+ utils::dataContainer* dataContainer = new utils::dataContainer(bankSize);
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)(LPC_MEMORY_BASE + getBankStartOffset(bank));
+ memcpy(dataContainer->data, (void*)&lpcMemMap[0], bankSize);
+ setBank(MODXO_BANK_BOOTLOADER);
+ return dataContainer;
+}
+
+void modchipModxo::eraseBank(uint8_t bank)
+{
+ setBank(bank);
+
+ setLedColor(LED_COLOR_AMBER);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ uint32_t memOffset = getBankMemOffset(bank);
+ uint32_t startOffset = getBankStartOffset(bank);
+ uint32_t bankSize = getBankSize(bank);
+
+ uint32_t offset = 0;
+ while (offset < bankSize)
+ {
+ if (isEraseMemOffset(memOffset + startOffset + offset))
+ {
+ sectorErase(offset);
+ }
+ offset += 4096;
+ }
+
+ setBank(MODXO_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+}
+
+void modchipModxo::writeBank(uint8_t bank, utils::dataContainer* dataContainer)
+{
+ setBank(bank);
+
+ setLedColor(LED_COLOR_BLUE);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)(LPC_MEMORY_BASE + getBankStartOffset(bank));
+
+ uint32_t memOffset = getBankMemOffset(bank);
+
+ bool needsFlush = false;
+ uint8_t sector = 0;
+ for (uint32_t i = 0; i < dataContainer->size; i++)
+ {
+ if (isProtectedMemOffset(memOffset + i) == true)
+ {
+ continue;
+ }
+ needsFlush = true;
+ uint8_t value = (uint8_t)dataContainer->data[i];
+ lpcMemMap[i] = value;
+ if (needsFlush && (i & 0xfff) == 0xfff)
+ {
+ needsFlush = false;
+ outputByte(MODXO_REGISTER_MEM_FLUSH, sector);
+ do
+ {
+ Sleep(2);
+ }
+ while(inputByte(MODXO_REGISTER_MEM_FLUSH) != 0);
+ sector++;
+ }
+ }
+
+ if (needsFlush)
+ {
+ outputByte(MODXO_REGISTER_MEM_FLUSH, sector);
+ do
+ {
+ Sleep(2);
+ }
+ while(inputByte(MODXO_REGISTER_MEM_FLUSH) != 0);
+ }
+
+ setBank(MODXO_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+}
+
+bool modchipModxo::verifyBank(uint8_t bank, utils::dataContainer* dataContainer)
+{
+ setBank(bank);
+
+ utils::dataContainer* writtenData = readBank(bank);
+
+ setLedColor(LED_COLOR_PURPLE);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ uint32_t memOffset = getBankMemOffset(bank);
+
+ bool ok = true;
+ for (uint32_t i = 0; i < dataContainer->size; i++)
+ {
+ if (isProtectedMemOffset(memOffset + i) == true)
+ {
+ continue;
+ }
+ if (writtenData->data[i] == dataContainer->data[i])
+ {
+ continue;
+ }
+ ok = false;
+ break;
+ }
+
+ delete(writtenData);
+
+ setBank(MODXO_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+ return ok;
+}
+
+uint8_t modchipModxo::getFlashBankCount(bool recovery)
+{
+ uint8_t size = inputByte(MODXO_REGISTER_SIZE);
+ return recovery ? 0 : size;
+}
+
+uint8_t modchipModxo::getFlashBank(bool recovery, uint8_t bank)
+{
+ return recovery ? 0 : (bank | 0x80);
+}
+
+bankType modchipModxo::getFlashBankType(bool recovery, uint8_t bank)
+{
+ return recovery ? bankTypeUser : (bank == 0 ? bankTypeSystem : bankTypeUser);
+}
+
+utils::dataContainer* modchipModxo::readFlash(bool recovery)
+{
+ utils::dataContainer* result = new utils::dataContainer(getFlashSize(recovery));
+ for (uint8_t i = 0; i < getFlashBankCount(recovery); i++)
+ {
+ uint8_t bank = getFlashBank(recovery, i);
+ uint32_t memOffset = getBankMemOffset(bank);
+ utils::dataContainer* bankData = readBank(bank);
+ memcpy(result->data + memOffset, bankData->data, bankData->size);
+ delete(bankData);
+ }
+ return result;
+}
+
+void modchipModxo::launchBank(uint8_t bank, uint8_t ledColor)
+{
+ DWORD scratch;
+ HalReadSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, &scratch);
+ HalWriteSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, scratch & ~SCRATCH_REGISTER_BITVALUE_NO_ANIMATION);
+ setBank(bank);
+ setFixedLedColor(ledColor);
+ HalReturnToFirmware(RETURN_FIRMWARE_REBOOT);
+}
+
+void modchipModxo::launchTsop()
+{
+ DWORD scratch;
+ HalReadSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, &scratch);
+ HalWriteSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, scratch & ~SCRATCH_REGISTER_BITVALUE_NO_ANIMATION);
+ setBank(MODXO_BANK_TSOP);
+ setFixedLedColor(LED_COLOR_OFF);
+ HalReturnToFirmware(RETURN_FIRMWARE_REBOOT);
+}
+
+void modchipModxo::launchRecovery()
+{
+}
+
+#ifndef TOOLS
+
+void modchipModxo::loadSettings(settingsState& settings)
+{
+ setBank(MODXO_SETTINGS_BANK);
+
+ setLedColor(LED_COLOR_WHITE);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ memcpy(&settings, (void*)&lpcMemMap[MODXO_SETTINGS_OFFSET], sizeof(settings));
+ uint32_t checksum = crc32::calculate(((uint8_t*)&settings) + sizeof(uint32_t), sizeof(settings) - sizeof(uint32_t));
+
+ setBank(MODXO_BANK_BOOTLOADER);
+
+ if (checksum != settings.checksum || versioning::compareVersion(settings.version, settingsManager::getVersion()) != 0)
+ {
+ settingsManager::initSettings();
+ settingsManager::saveSettings();
+ }
+
+ setLedColor(settingsManager::getLedColor());
+}
+
+void modchipModxo::saveSettings(settingsState& settings)
+{
+ setBank(MODXO_SETTINGS_BANK);
+
+ settings.checksum = crc32::calculate(((uint8_t*)&settings) + sizeof(uint32_t), sizeof(settings) - sizeof(uint32_t));
+ utils::dataContainer* settingsData = new utils::dataContainer((char*)&settings, sizeof(settings), sizeof(settings));
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ setLedColor(LED_COLOR_AMBER);
+ sectorErase(MODXO_SETTINGS_OFFSET);
+
+ setLedColor(LED_COLOR_BLUE);
+
+ bool needsFlush = false;
+ uint8_t sector = (uint8_t)(MODXO_SETTINGS_OFFSET >> 12);
+ for (uint32_t i = 0; i < settingsData->size; i++)
+ {
+ needsFlush = true;
+ uint8_t value = (uint8_t)settingsData->data[i];
+ lpcMemMap[MODXO_SETTINGS_OFFSET + i] = value;
+ if (needsFlush && ((MODXO_SETTINGS_OFFSET + i) & 0xfff) == 0xfff)
+ {
+ needsFlush = false;
+ outputByte(MODXO_REGISTER_MEM_FLUSH, sector);
+ do
+ {
+ Sleep(2);
+ }
+ while(inputByte(MODXO_REGISTER_MEM_FLUSH) != 0);
+ sector++;
+ }
+ }
+
+ if (needsFlush)
+ {
+ outputByte(MODXO_REGISTER_MEM_FLUSH, sector);
+ do
+ {
+ Sleep(2);
+ }
+ while(inputByte(MODXO_REGISTER_MEM_FLUSH) != 0);
+ }
+
+ setBank(MODXO_BANK_BOOTLOADER);
+
+ setLedColor(settingsManager::getLedColor());
+}
+
+#endif
+
+utils::dataContainer* modchipModxo::getInstallerLogo()
+{
+ utils::dataContainer* installerLogo = new utils::dataContainer(32768);
+ return installerLogo;
+}
+
+displayDriver* modchipModxo::getDisplayDriver(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ uint8_t lcdModel = settingsManager::getLcdModel(current);
+ if (lcdMode == 1)
+ {
+ if (lcdModel == 0)
+ {
+ return displayFactory::getDisplay(displayVariantHD44780Modxo);
+ }
+ if (lcdModel == 1)
+ {
+ return displayFactory::getDisplay(displayVariantLCDXXXXModxo);
+ }
+ }
+ if (lcdMode == 2)
+ {
+ if (lcdModel == 0)
+ {
+ return displayFactory::getDisplay(displayVariantSPI2PARModxo);
+ }
+ }
+ if (lcdMode == 3)
+ {
+ if (lcdModel == 0)
+ {
+ return displayFactory::getDisplay(displayVariantHD44780LPC);
+ }
+ if (lcdModel == 1)
+ {
+ return displayFactory::getDisplay(displayVariantLCDXXXXLPC);
+ }
+ }
+ return NULL;
+}
+
+supportInfo modchipModxo::getSupportInfo(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ uint8_t lcdModel = settingsManager::getLcdModel(current);
+ supportInfo info;
+ info.supportsLed = true;
+ info.supportsLcd = true;
+
+ bool lcdInfo = false;
+ bool backlight = false;
+ bool contrast = false;
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver != NULL)
+ {
+ driver->getSupport(lcdInfo, backlight, contrast);
+ }
+ info.supportsLcdInfo = lcdInfo;
+ info.supportsLcdBacklight = backlight;
+ info.supportsLcdContrast = contrast;
+
+ info.supportsRecovery = false;
+ return info;
+}
+
+uint8_t modchipModxo::getLcdModeCount()
+{
+ return 4;
+}
+
+char* modchipModxo::getLcdModeString(uint8_t lcdMode)
+{
+ if (lcdMode == 1)
+ {
+ return strdup("Legacy I2C");
+ }
+ else if (lcdMode == 2)
+ {
+ return strdup("Legacy SPI2PAR");
+ }
+ else if (lcdMode == 3)
+ {
+ return strdup("SMBUS");
+ }
+ return strdup("Disabled");
+}
+
+uint8_t modchipModxo::getLcdModelCount(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ if (lcdMode == 1)
+ {
+ return 2;
+ }
+ else if (lcdMode == 2)
+ {
+ return 1;
+ }
+ else if (lcdMode == 3)
+ {
+ return 2;
+ }
+ return 0;
+}
+
+char* modchipModxo::getLcdModelString(bool current, uint8_t lcdModel)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return strdup("");
+ }
+ return driver->getModel();
+}
+
+uint8_t modchipModxo::getLcdAddressCount(bool current)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return 0;
+ }
+ return driver->getI2cAddressCount();
+}
+
+char* modchipModxo::getLcdAddressString(bool current, uint8_t lcdAddress)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return strdup("");
+ }
+ uint8_t address = driver->getI2cAddress(lcdAddress);
+ char* result = stringUtility::formatString("0x%2X", address);
+ return result;
+}
+
+void modchipModxo::lcdSetCursorPosition(uint8_t row, uint8_t col)
+{
+ if (row > 3)
+ {
+ row = 3;
+ }
+ if (col > 19)
+ {
+ col = 19;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setCursorPosition(row, col);
+}
+
+void modchipModxo::lcdInit()
+{
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->init();
+}
+
+void modchipModxo::lcdPrintMessage(const char* message)
+{
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->printMessage(message);
+}
+
+void modchipModxo::lcdSetBacklight(uint8_t value)
+{
+ if (value > 100)
+ {
+ value = 100;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setBacklight(value);
+}
+
+void modchipModxo::lcdSetContrast(uint8_t value)
+{
+ if (value > 100)
+ {
+ value = 100;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setContrast(value);
+}
+
+// Private
+
+void modchipModxo::setBank(uint8_t bank)
+{
+ mBank = bank;
+ outputByte(MODXO_REGISTER_BANKING, mBank);
+}
+
+uint8_t modchipModxo::getBank()
+{
+ mBank = (inputByte(MODXO_REGISTER_BANKING) & 0x0f);
+ return mBank;
+}
+
+bool modchipModxo::isEraseMemOffset(uint32_t memOffset)
+{
+ return (memOffset % 4096) == 0;
+}
+
+bool modchipModxo::isProtectedMemOffset(uint32_t memOffset)
+{
+ return false;
+}
+
+void modchipModxo::sectorErase(uint32_t offset)
+{
+ if (isProtectedMemOffset(offset))
+ {
+ return;
+ }
+
+ outputByte(MODXO_REGISTER_MEM_ERASE, 'D');
+ outputByte(MODXO_REGISTER_MEM_ERASE, 'I');
+ outputByte(MODXO_REGISTER_MEM_ERASE, 'E');
+ outputByte(MODXO_REGISTER_MEM_ERASE, (uint8_t)(offset >> 12));
+ do
+ {
+ Sleep(2);
+ }
+ while(inputByte(MODXO_REGISTER_MEM_ERASE) != 0);
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipModxo.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipModxo.h
new file mode 100644
index 0000000..8fa77f8
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipModxo.h
@@ -0,0 +1,76 @@
+#pragma once
+
+#include "modchip.h"
+#include "xboxInternals.h"
+
+#ifndef TOOLS
+#include "settingsManager.h"
+#endif
+
+class modchipModxo : public modchip
+{
+public:
+
+ void ledTest();
+
+ modchipModxo();
+ void setLedColor(uint8_t ledColor);
+ void setFixedLedColor(uint8_t ledColor);
+
+ uint32_t getSlotCount();
+ uint32_t getFlashSize(bool recovery);
+ void disableRecovery();
+ bool isValidBankSize(uint32_t size);
+ bool isValidFlashSize(bool recovery, uint32_t size);
+ uint32_t getBankSize(uint8_t bank);
+ uint32_t getBankMemOffset(uint8_t bank);
+ uint32_t getBankStartOffset(uint8_t bank);
+ uint8_t getBankFromIdAndSlots(uint8_t id, uint8_t slots);
+ utils::dataContainer* readBank(uint8_t bank);
+ void eraseBank(uint8_t bank);
+ void writeBank(uint8_t bank, utils::dataContainer* dataContainer);
+ bool verifyBank(uint8_t bank, utils::dataContainer* dataContainer);
+
+ uint8_t getFlashBankCount(bool recovery);
+ uint8_t getFlashBank(bool recovery, uint8_t bank);
+ bankType getFlashBankType(bool recovery, uint8_t bank);
+ utils::dataContainer* readFlash(bool recovery);
+
+ void launchBank(uint8_t bank, uint8_t ledColor);
+ void launchTsop();
+ void launchRecovery();
+
+#ifndef TOOLS
+ void loadSettings(settingsState& settings);
+ void saveSettings(settingsState& settings);
+#endif
+
+ utils::dataContainer* getInstallerLogo();
+
+ displayDriver* getDisplayDriver(bool current);
+ supportInfo getSupportInfo(bool current);
+ uint8_t getLcdModeCount();
+ char* getLcdModeString(uint8_t lcdMode);
+ uint8_t getLcdModelCount(bool current);
+ char* getLcdModelString(bool current, uint8_t lcdModel);
+ uint8_t getLcdAddressCount(bool current);
+ char* getLcdAddressString(bool current, uint8_t lcdAddress);
+
+ void lcdSetCursorPosition(uint8_t row, uint8_t col);
+ void lcdInit();
+ void lcdPrintMessage(const char* message);
+ void lcdSetBacklight(uint8_t value);
+ void lcdSetContrast(uint8_t value);
+
+private:
+
+ void setBank(uint8_t bank);
+ uint8_t getBank();
+ bool isEraseMemOffset(uint32_t memOffset);
+ bool isProtectedMemOffset(uint32_t memOffset);
+ void sectorErase(uint32_t offset);
+
+private:
+
+ uint8_t mBank;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipSmartxx.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipSmartxx.cpp
new file mode 100644
index 0000000..5a0b93f
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipSmartxx.cpp
@@ -0,0 +1,715 @@
+#include "modchipSmartxx.h"
+#include "crc32.h"
+#include "settingsManager.h"
+#include "globalDefines.h"
+#include "stringUtility.h"
+
+//Bank1_256k = 3 0x000000 - 0x03ffff Sector Size 65536 Total 262144
+//Bank2_256k = 4 0x040000 - 0x07ffff Sector Size 65536 Total 262144
+//Bank3_256k = 5 0x080000 - 0x0bffff Sector Size 65536 Total 262144
+//Bank4_256k = 6 0x0c0000 - 0x0fffff Sector Size 65536 Total 262144
+//Bank1_512k = 7 0x000000 - 0x07ffff Sector Size 65536 Total 524288
+//Bank2_512k = 8 0x080000 - 0x0fffff Sector Size 65536 Total 524288
+//Bank1_1024k = 9 0x000000 - 0x0fffff Sector Size 65536 Total 1048576
+//Bank_PrometheOS = 2 0x100000 - 0x17ffff Sector Size 65536 Total 524288
+//Bank_Bootloader = 1 0x180000 - 0x1bffff Sector Size 65536 Total 262144
+//Bank_Recovery = 10 0x1c0000 - 0x1fffff See Below Total 262144
+
+//0x1c0000 - 0x1effff Sector Size 65536
+//0x1f0000 - 0x1f7fff Sector Size 32768
+//0x1f8000 - 0x1fbfff Sector Size 8192
+//0x1fc000 - 0x1fffff Sector Size 16384
+
+//0x1c0000 - 0x1dffff Total 131072 (Protected - Installer Logo (IOpen Xenium))
+//0x1e0000 - 0x1f7fff Total 98304 (PrometheOS Continued)
+//0x1f8000 - 0x1f9fff Total 8192 (Protected)
+//0x1fa000 - 0x1fbfff Total 8192 (Settings)
+//0x1fc000 - 0x1fffff Total 16384 (Spare)
+
+modchipSmartxx::modchipSmartxx()
+{
+ InitializeCriticalSection(&mMutex);
+ uint8_t bank = SMARTXX_BANK_BOOTLOADER;
+ displaySPI2PARSmartxx::getInstance()->setBankValue(bank);
+ uint8_t spi = inputByte(SMARTXX_REGISTER_BANKING) & 0x70;
+ displaySPI2PARSmartxx::getInstance()->setSpiValue(spi);
+}
+
+void modchipSmartxx::setLedColor(uint8_t ledColor)
+{
+ outputByte(SMARTXX_REGISTER_LED, ledColor);
+}
+
+uint32_t modchipSmartxx::getSlotCount()
+{
+ return 4;
+}
+
+uint32_t modchipSmartxx::getFlashSize(bool recovery)
+{
+ return recovery ? 0 : (2 * 1024 * 1024);
+}
+
+void modchipSmartxx::disableRecovery()
+{
+}
+
+bool modchipSmartxx::isValidBankSize(uint32_t size)
+{
+ return size == (256 * 1024) || size == (512 * 1024) || size == (1024 * 1024);
+}
+
+bool modchipSmartxx::isValidFlashSize(bool recovery, uint32_t size)
+{
+ return size == getFlashSize(recovery);
+}
+
+uint32_t modchipSmartxx::getBankSize(uint8_t bank)
+{
+ if (bank == SMARTXX_BANK_BOOTLOADER)
+ {
+ return 256 * 1024;
+ }
+ if (bank == SMARTXX_BANK_PROMETHEOS1)
+ {
+ return 512 * 1024;
+ }
+ if (bank == SMARTXX_BANK_PROMETHEOS2)
+ {
+ return 256 * 1024;
+ }
+ if (bank == SMARTXX_BANK_SLOT1_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == SMARTXX_BANK_SLOT2_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == SMARTXX_BANK_SLOT3_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == SMARTXX_BANK_SLOT4_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == SMARTXX_BANK_SLOT1_512K)
+ {
+ return 512 * 1024;
+ }
+ if (bank == SMARTXX_BANK_SLOT2_512K)
+ {
+ return 512 * 1024;
+ }
+ if (bank == SMARTXX_BANK_SLOT1_1024K)
+ {
+ return 1024 * 1024;
+ }
+ return 0;
+}
+
+uint32_t modchipSmartxx::getBankMemOffset(uint8_t bank)
+{
+ if (bank == SMARTXX_BANK_SLOT1_256K)
+ {
+ return 0x000000;
+ }
+ if (bank == SMARTXX_BANK_SLOT2_256K)
+ {
+ return 0x040000;
+ }
+ if (bank == SMARTXX_BANK_SLOT2_256K)
+ {
+ return 0x080000;
+ }
+ if (bank == SMARTXX_BANK_SLOT4_256K)
+ {
+ return 0x0c0000;
+ }
+ if (bank == SMARTXX_BANK_SLOT1_512K)
+ {
+ return 0x000000;
+ }
+ if (bank == SMARTXX_BANK_SLOT2_512K)
+ {
+ return 0x080000;
+ }
+ if (bank == SMARTXX_BANK_SLOT1_1024K)
+ {
+ return 0x000000;
+ }
+ if (bank == SMARTXX_BANK_BOOTLOADER)
+ {
+ return 0x180000;
+ }
+ if (bank == SMARTXX_BANK_PROMETHEOS1)
+ {
+ return 0x100000;
+ }
+ if (bank == SMARTXX_BANK_PROMETHEOS2)
+ {
+ return 0x1c0000;
+ }
+ return 0;
+}
+
+uint32_t modchipSmartxx::getBankStartOffset(uint8_t bank)
+{
+ return 0;
+}
+
+uint8_t modchipSmartxx::getBankFromIdAndSlots(uint8_t id, uint8_t slots)
+{
+ if (id == 0 && slots == 1)
+ {
+ return SMARTXX_BANK_SLOT1_256K;
+ }
+ if (id == 1 && slots == 1)
+ {
+ return SMARTXX_BANK_SLOT2_256K;
+ }
+ if (id == 2 && slots == 1)
+ {
+ return SMARTXX_BANK_SLOT3_256K;
+ }
+ if (id == 3 && slots == 1)
+ {
+ return SMARTXX_BANK_SLOT4_256K;
+ }
+ if (id == 0 && slots == 2)
+ {
+ return SMARTXX_BANK_SLOT1_512K;
+ }
+ if (id == 2 && slots == 2)
+ {
+ return SMARTXX_BANK_SLOT2_512K;
+ }
+ if (id == 0 && slots == 4)
+ {
+ return SMARTXX_BANK_SLOT1_1024K;
+ }
+ return 0;
+}
+
+utils::dataContainer* modchipSmartxx::readBank(uint8_t bank)
+{
+ setBank(bank);
+ uint32_t bankSize = getBankSize(bank);
+ utils::dataContainer* dataContainer = new utils::dataContainer(bankSize);
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)(LPC_MEMORY_BASE + getBankStartOffset(bank));
+ memcpy(dataContainer->data, (void*)&lpcMemMap[0], bankSize);
+ setBank(SMARTXX_BANK_BOOTLOADER);
+ return dataContainer;
+}
+
+void modchipSmartxx::eraseBank(uint8_t bank)
+{
+ setBank(bank);
+
+ setLedColor(LED_COLOR_AMBER);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ uint32_t memOffset = getBankMemOffset(bank);
+ uint32_t startOffset = getBankStartOffset(bank);
+ uint32_t bankSize = getBankSize(bank);
+
+ uint32_t offset = 0;
+ while (offset < bankSize)
+ {
+ if (isEraseMemOffset(memOffset + startOffset + offset))
+ {
+ sectorErase(offset);
+ }
+ offset += 8192;
+ }
+
+ setBank(SMARTXX_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+}
+
+void modchipSmartxx::writeBank(uint8_t bank, utils::dataContainer* dataContainer)
+{
+ setBank(bank);
+
+ setLedColor(LED_COLOR_BLUE);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)(LPC_MEMORY_BASE + getBankStartOffset(bank));
+
+ uint32_t memOffset = getBankMemOffset(bank);
+
+ for (uint32_t i = 0; i < dataContainer->size; i++)
+ {
+ if (isProtectedMemOffset(memOffset + i) == true)
+ {
+ continue;
+ }
+ uint8_t value = (uint8_t)dataContainer->data[i];
+ lpcMemMap[0xAAAA] = 0xAA;
+ lpcMemMap[0x5555] = 0x55;
+ lpcMemMap[0xAAAA] = 0xA0;
+ lpcMemMap[i] = value;
+ while (lpcMemMap[i] != value);
+ }
+ lpcMemMap[0] = 0xf0;
+
+ setBank(SMARTXX_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+}
+
+bool modchipSmartxx::verifyBank(uint8_t bank, utils::dataContainer* dataContainer)
+{
+ setBank(bank);
+
+ utils::dataContainer* writtenData = readBank(bank);
+
+ setLedColor(LED_COLOR_PURPLE);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ uint32_t memOffset = getBankMemOffset(bank);
+
+ bool ok = true;
+ for (uint32_t i = 0; i < dataContainer->size; i++)
+ {
+ if (isProtectedMemOffset(memOffset + i) == true)
+ {
+ continue;
+ }
+ if (writtenData->data[i] == dataContainer->data[i])
+ {
+ continue;
+ }
+ ok = false;
+ break;
+ }
+
+ delete(writtenData);
+
+ setBank(SMARTXX_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+ return ok;
+}
+
+uint8_t modchipSmartxx::getFlashBankCount(bool recovery)
+{
+ return recovery ? 0 : 7;
+}
+
+uint8_t modchipSmartxx::getFlashBank(bool recovery, uint8_t bank)
+{
+ const uint8_t banks[] = {
+ SMARTXX_BANK_SLOT1_256K,
+ SMARTXX_BANK_SLOT2_256K,
+ SMARTXX_BANK_SLOT3_256K,
+ SMARTXX_BANK_SLOT4_256K,
+ SMARTXX_BANK_BOOTLOADER,
+ SMARTXX_BANK_PROMETHEOS1,
+ SMARTXX_BANK_PROMETHEOS2,
+ };
+ return recovery ? 0 : banks[bank];
+}
+
+bankType modchipSmartxx::getFlashBankType(bool recovery, uint8_t bank)
+{
+ const bankType banks[] = {
+ bankTypeUser,
+ bankTypeUser,
+ bankTypeUser,
+ bankTypeUser,
+ bankTypeSystem,
+ bankTypeSystem,
+ bankTypeSystem,
+ };
+ return recovery ? bankTypeUser : banks[bank];
+}
+
+utils::dataContainer* modchipSmartxx::readFlash(bool recovery)
+{
+ utils::dataContainer* result = new utils::dataContainer(getFlashSize(recovery));
+ for (uint8_t i = 0; i < getFlashBankCount(recovery); i++)
+ {
+ uint8_t bank = getFlashBank(recovery, i);
+ uint32_t memOffset = getBankMemOffset(bank);
+ utils::dataContainer* bankData = readBank(bank);
+ memcpy(result->data + memOffset, bankData->data, bankData->size);
+ delete(bankData);
+ }
+ return result;
+}
+
+void modchipSmartxx::launchBank(uint8_t bank, uint8_t ledColor)
+{
+ DWORD scratch;
+ HalReadSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, &scratch);
+ HalWriteSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, scratch & ~SCRATCH_REGISTER_BITVALUE_NO_ANIMATION);
+ setBank(bank);
+ setLedColor(ledColor);
+ HalReturnToFirmware(RETURN_FIRMWARE_REBOOT);
+}
+
+void modchipSmartxx::launchTsop()
+{
+ DWORD scratch;
+ HalReadSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, &scratch);
+ HalWriteSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, scratch & ~SCRATCH_REGISTER_BITVALUE_NO_ANIMATION);
+ setBank(SMARTXX_BANK_TSOP);
+ setLedColor(LED_COLOR_OFF);
+ HalReturnToFirmware(RETURN_FIRMWARE_REBOOT);
+}
+
+void modchipSmartxx::launchRecovery()
+{
+}
+
+#ifndef TOOLS
+
+void modchipSmartxx::loadSettings(settingsState& settings)
+{
+ setBank(SMARTXX_SETTINGS_BANK);
+
+ setLedColor(LED_COLOR_WHITE);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ memcpy(&settings, (void*)&lpcMemMap[SMARTXX_SETTINGS_OFFSET], sizeof(settings));
+ uint32_t checksum = crc32::calculate(((uint8_t*)&settings) + sizeof(uint32_t), sizeof(settings) - sizeof(uint32_t));
+
+ setBank(SMARTXX_BANK_BOOTLOADER);
+
+ if (checksum != settings.checksum || versioning::compareVersion(settings.version, settingsManager::getVersion()) != 0)
+ {
+ settingsManager::initSettings();
+ settingsManager::saveSettings();
+ }
+
+ setLedColor(settingsManager::getLedColor());
+}
+
+void modchipSmartxx::saveSettings(settingsState& settings)
+{
+ setBank(SMARTXX_SETTINGS_BANK);
+
+ settings.checksum = crc32::calculate(((uint8_t*)&settings) + sizeof(uint32_t), sizeof(settings) - sizeof(uint32_t));
+ utils::dataContainer* settingsData = new utils::dataContainer((char*)&settings, sizeof(settings), sizeof(settings));
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ setLedColor(LED_COLOR_AMBER);
+ sectorErase(SMARTXX_SETTINGS_OFFSET);
+
+ setLedColor(LED_COLOR_BLUE);
+ for (uint32_t i = 0; i < settingsData->size; i++)
+ {
+ uint8_t value = (uint8_t)settingsData->data[i];
+ lpcMemMap[0xAAAA] = 0xAA;
+ lpcMemMap[0x5555] = 0x55;
+ lpcMemMap[0xAAAA] = 0xA0;
+ lpcMemMap[SMARTXX_SETTINGS_OFFSET + i] = value;
+ while (lpcMemMap[SMARTXX_SETTINGS_OFFSET + i] != value);
+ }
+ lpcMemMap[0] = 0xF0;
+
+ setBank(SMARTXX_BANK_BOOTLOADER);
+
+ setLedColor(settingsManager::getLedColor());
+}
+
+#endif
+
+utils::dataContainer* modchipSmartxx::getInstallerLogo()
+{
+ setBank(SMARTXX_INSTALLER_LOGO_BANK);
+
+ setLedColor(LED_COLOR_WHITE);
+
+ utils::dataContainer* installerLogo = new utils::dataContainer(32768);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+ memcpy(installerLogo->data, (void*)&lpcMemMap[SMARTXX_INSTALLER_LOGO_OFFSET], installerLogo->size);
+
+ setBank(SMARTXX_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+ return installerLogo;
+}
+
+displayDriver* modchipSmartxx::getDisplayDriver(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ uint8_t lcdModel = settingsManager::getLcdModel(current);
+ if (lcdMode == 1)
+ {
+ if (lcdModel == 0)
+ {
+ return displayFactory::getDisplay(displayVariantSPI2PARSmartxx);
+ }
+ }
+ if (lcdMode == 2)
+ {
+ if (lcdModel == 0)
+ {
+ return displayFactory::getDisplay(displayVariantHD44780LPC);
+ }
+ if (lcdModel == 1)
+ {
+ return displayFactory::getDisplay(displayVariantLCDXXXXLPC);
+ }
+ }
+ return NULL;
+}
+
+supportInfo modchipSmartxx::getSupportInfo(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ supportInfo info;
+ info.supportsLed = true;
+ info.supportsLcd = true;
+
+ bool lcdInfo = false;
+ bool backlight = false;
+ bool contrast = false;
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver != NULL)
+ {
+ driver->getSupport(lcdInfo, backlight, contrast);
+ }
+ info.supportsLcdInfo = lcdInfo;
+ info.supportsLcdBacklight = backlight;
+ info.supportsLcdContrast = contrast;
+
+ info.supportsRecovery = false;
+ return info;
+}
+
+uint8_t modchipSmartxx::getLcdModeCount()
+{
+ return 3;
+}
+
+char* modchipSmartxx::getLcdModeString(uint8_t lcdMode)
+{
+ if (lcdMode == 1)
+ {
+ return strdup("Smartxx");
+ }
+ if (lcdMode == 2)
+ {
+ return strdup("SMBUS");
+ }
+ return strdup("Disabled");
+}
+
+uint8_t modchipSmartxx::getLcdModelCount(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ if (lcdMode == 1)
+ {
+ return 1;
+ }
+ if (lcdMode == 2)
+ {
+ return 2;
+ }
+ return 0;
+}
+
+char* modchipSmartxx::getLcdModelString(bool current, uint8_t lcdModel)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return strdup("");
+ }
+ return driver->getModel();
+}
+
+uint8_t modchipSmartxx::getLcdAddressCount(bool current)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return 0;
+ }
+ return driver->getI2cAddressCount();
+}
+
+char* modchipSmartxx::getLcdAddressString(bool current, uint8_t lcdAddress)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return strdup("");
+ }
+ uint8_t address = driver->getI2cAddress(lcdAddress);
+ char* result = stringUtility::formatString("0x%2X", address);
+ return result;
+}
+
+void modchipSmartxx::lcdSetCursorPosition(uint8_t row, uint8_t col)
+{
+ if (row > 3)
+ {
+ row = 3;
+ }
+ if (col > 19)
+ {
+ col = 19;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ EnterCriticalSection(&mMutex);
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setCursorPosition(row, col);
+ LeaveCriticalSection(&mMutex);
+}
+
+void modchipSmartxx::lcdInit()
+{
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ EnterCriticalSection(&mMutex);
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->init();
+ LeaveCriticalSection(&mMutex);
+}
+
+void modchipSmartxx::lcdPrintMessage(const char* message)
+{
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ EnterCriticalSection(&mMutex);
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->printMessage(message);
+ LeaveCriticalSection(&mMutex);
+}
+
+void modchipSmartxx::lcdSetBacklight(uint8_t value)
+{
+ if (value > 100)
+ {
+ value = 100;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ EnterCriticalSection(&mMutex);
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setBacklight(value);
+ LeaveCriticalSection(&mMutex);
+}
+
+void modchipSmartxx::lcdSetContrast(uint8_t value)
+{
+ if (value > 100)
+ {
+ value = 100;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ EnterCriticalSection(&mMutex);
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setContrast(value);
+ LeaveCriticalSection(&mMutex);
+}
+
+// Private
+
+void modchipSmartxx::setBank(uint8_t bank)
+{
+ EnterCriticalSection(&mMutex);
+ displaySPI2PARSmartxx::getInstance()->setBankValue(bank);
+ uint8_t spi = displaySPI2PARSmartxx::getInstance()->getSpiValue();
+ outputByte(SMARTXX_REGISTER_BANKING, (spi | bank));
+ LeaveCriticalSection(&mMutex);
+}
+
+uint8_t modchipSmartxx::getBank()
+{
+ EnterCriticalSection(&mMutex);
+ uint8_t bank = (inputByte(SMARTXX_REGISTER_BANKING) & 0x0f);
+ displaySPI2PARSmartxx::getInstance()->setBankValue(bank);
+ LeaveCriticalSection(&mMutex);
+ return bank;
+}
+
+bool modchipSmartxx::isEraseMemOffset(uint32_t memOffset)
+{
+ if (memOffset >= 0x000000 && memOffset <= 0x1effff)
+ {
+ return (memOffset % 65536) == 0;
+ }
+ if (memOffset >= 0x1f0000 && memOffset <= 0x1f7fff)
+ {
+ return (memOffset % 32768) == 0;
+ }
+ if (memOffset >= 0x1f8000 && memOffset <= 0x1fbfff)
+ {
+ return (memOffset % 8192) == 0;
+ }
+ if (memOffset >= 0x1fc000 && memOffset <= 0x1fffff)
+ {
+ return (memOffset % 16384) == 0;
+ }
+ return false;
+}
+
+bool modchipSmartxx::isProtectedMemOffset(uint32_t memOffset)
+{
+ if (memOffset >= 0x1c0000 && memOffset <= 0x1dffff)
+ {
+ return true;
+ }
+ return false;
+}
+
+void modchipSmartxx::sectorErase(uint32_t offset)
+{
+ if (isProtectedMemOffset(offset))
+ {
+ return;
+ }
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+ lpcMemMap[0xAAAA] = 0xAA;
+ lpcMemMap[0x5555] = 0x55;
+ lpcMemMap[0xAAAA] = 0x80;
+ lpcMemMap[0xAAAA] = 0xAA;
+ lpcMemMap[0x5555] = 0x55;
+ lpcMemMap[offset] = 0x30;
+ while(lpcMemMap[0] != lpcMemMap[0]);
+ lpcMemMap[0] = 0xF0;
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipSmartxx.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipSmartxx.h
new file mode 100644
index 0000000..1748631
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipSmartxx.h
@@ -0,0 +1,73 @@
+#pragma once
+
+#include "modchip.h"
+#include "xboxInternals.h"
+
+#ifndef TOOLS
+#include "settingsManager.h"
+#endif
+
+class modchipSmartxx : public modchip
+{
+public:
+
+ modchipSmartxx();
+ void setLedColor(uint8_t ledColor);
+
+ uint32_t getSlotCount();
+ uint32_t getFlashSize(bool recovery);
+ void disableRecovery();
+ bool isValidBankSize(uint32_t size);
+ bool isValidFlashSize(bool recovery, uint32_t size);
+ uint32_t getBankSize(uint8_t bank);
+ uint32_t getBankMemOffset(uint8_t bank);
+ uint32_t getBankStartOffset(uint8_t bank);
+ uint8_t getBankFromIdAndSlots(uint8_t id, uint8_t slots);
+ utils::dataContainer* readBank(uint8_t bank);
+ void eraseBank(uint8_t bank);
+ void writeBank(uint8_t bank, utils::dataContainer* dataContainer);
+ bool verifyBank(uint8_t bank, utils::dataContainer* dataContainer);
+
+ uint8_t getFlashBankCount(bool recovery);
+ uint8_t getFlashBank(bool recovery, uint8_t bank);
+ bankType getFlashBankType(bool recovery, uint8_t bank);
+ utils::dataContainer* readFlash(bool recovery);
+
+ void launchBank(uint8_t bank, uint8_t ledColor);
+ void launchTsop();
+ void launchRecovery();
+
+#ifndef TOOLS
+ void loadSettings(settingsState& settings);
+ void saveSettings(settingsState& settings);
+#endif
+
+ utils::dataContainer* getInstallerLogo();
+
+ displayDriver* getDisplayDriver(bool current);
+ supportInfo getSupportInfo(bool current);
+ uint8_t getLcdModeCount();
+ char* getLcdModeString(uint8_t lcdMode);
+ uint8_t getLcdModelCount(bool current);
+ char* getLcdModelString(bool current, uint8_t lcdModel);
+ uint8_t getLcdAddressCount(bool current);
+ char* getLcdAddressString(bool current, uint8_t lcdAddress);
+
+ void lcdSetCursorPosition(uint8_t row, uint8_t col);
+ void lcdInit();
+ void lcdPrintMessage(const char* message);
+ void lcdSetBacklight(uint8_t value);
+ void lcdSetContrast(uint8_t value);
+
+private:
+
+ void setBank(uint8_t bank);
+ uint8_t getBank();
+ bool isEraseMemOffset(uint32_t memOffset);
+ bool isProtectedMemOffset(uint32_t memOffset);
+ void sectorErase(uint32_t offset);
+
+private:
+
+ CRITICAL_SECTION mMutex;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXchanger.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXchanger.cpp
new file mode 100644
index 0000000..ebf3b16
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXchanger.cpp
@@ -0,0 +1,434 @@
+#include "modchipXchanger.h"
+#include "crc32.h"
+#include "globalDefines.h"
+#include "stringUtility.h"
+
+#define XCHANGER_REGISTER_BANKING 0x1912
+//#define XCHANGER_REGISTER_LED 0x00EE
+#define XCHANGER_SPI_CLK_BIT 0x40
+#define XCHANGER_SPI_MOSI_BIT 0x10
+
+#define XCHANGER_BANK_TSOP 0x3
+#define XCHANGER_BANK_BOOTLOADER 0x0
+#define XCHANGER_BANK_SLOT1_256K 0x1
+#define XCHANGER_BANK_PROMETHEOS 0x2
+
+#define XCHANGER_SETTINGS_BANK XCHANGER_BANK_PROMETHEOS
+#define XCHANGER_SETTINGS_OFFSET (0x07f000)
+//#define XCHANGER_INSTALLER_LOGO_BANK XCHANGER_BANK_PROMETHEOS2
+//#define XCHANGER_INSTALLER_LOGO_OFFSET (0x1f0000 - 0x1c0000)
+
+//Bank_PrometheOS = 0x84 0x000000 - 0x07ffff Sector Size 4096 Total 524288 (See below)
+//Bank1_256k = 0x86 0x080000 - 0x0bffff Sector Size 4096 Total 262144
+//Bank_Bootloader = 0x87 0x0C0000 - 0x0fffff Sector Size 4096 Total 262144
+
+//0x000000 - 0x07efff Sector Size 4096 Total 520192 (PrometheOS)
+//0x07f000 - 0x07ffff Sector Size 4096 Total 4096 (Settings)
+
+modchipXchanger::modchipXchanger()
+{
+ mBank = XCHANGER_BANK_BOOTLOADER;
+ mSpi = 0;
+}
+
+void modchipXchanger::setLedColor(uint8_t ledColor)
+{
+ //outputByte(XCHANGER_REGISTER_LED, ledColor);
+}
+
+uint32_t modchipXchanger::getSlotCount()
+{
+ return 1;
+}
+
+uint32_t modchipXchanger::getFlashSize(bool recovery)
+{
+ return recovery ? 0 : (1 * 1024 * 1024);
+}
+
+void modchipXchanger::disableRecovery()
+{
+}
+
+bool modchipXchanger::isValidBankSize(uint32_t size)
+{
+ return size == (256 * 1024);
+}
+
+bool modchipXchanger::isValidFlashSize(bool recovery, uint32_t size)
+{
+ return size == getFlashSize(recovery);
+}
+
+uint32_t modchipXchanger::getBankSize(uint8_t bank)
+{
+ if (bank == XCHANGER_BANK_PROMETHEOS)
+ {
+ return 512 * 1024;
+ }
+ if (bank == XCHANGER_BANK_SLOT1_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == XCHANGER_BANK_BOOTLOADER)
+ {
+ return 256 * 1024;
+ }
+ return 0;
+}
+
+uint32_t modchipXchanger::getBankMemOffset(uint8_t bank)
+{
+ if (bank == XCHANGER_BANK_PROMETHEOS)
+ {
+ return 0x000000;
+ }
+ if (bank == XCHANGER_BANK_SLOT1_256K)
+ {
+ return 0x080000;
+ }
+ if (bank == XCHANGER_BANK_BOOTLOADER)
+ {
+ return 0x0c0000;
+ }
+ return 0;
+}
+
+uint32_t modchipXchanger::getBankStartOffset(uint8_t bank)
+{
+ return 0;
+}
+
+uint8_t modchipXchanger::getBankFromIdAndSlots(uint8_t id, uint8_t slots)
+{
+ if (id == 0 && slots == 1)
+ {
+ return XCHANGER_BANK_SLOT1_256K;
+ }
+ return 0;
+}
+
+utils::dataContainer* modchipXchanger::readBank(uint8_t bank)
+{
+ setBank(bank);
+ uint32_t bankSize = getBankSize(bank);
+ utils::dataContainer* dataContainer = new utils::dataContainer(bankSize);
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)(LPC_MEMORY_BASE + getBankStartOffset(bank));
+ memcpy(dataContainer->data, (void*)&lpcMemMap[0], bankSize);
+ setBank(XCHANGER_BANK_BOOTLOADER);
+ return dataContainer;
+}
+
+void modchipXchanger::eraseBank(uint8_t bank)
+{
+ setBank(bank);
+
+ setLedColor(LED_COLOR_AMBER);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ uint32_t memOffset = getBankMemOffset(bank);
+ uint32_t startOffset = getBankStartOffset(bank);
+ uint32_t bankSize = getBankSize(bank);
+
+ uint32_t offset = 0;
+ while (offset < bankSize)
+ {
+ if (isEraseMemOffset(memOffset + startOffset + offset))
+ {
+ sectorErase(offset);
+ }
+ offset += 4096;
+ }
+
+ setBank(XCHANGER_BANK_BOOTLOADER);
+
+ setLedColor(LED_COLOR_GREEN);
+}
+
+void modchipXchanger::writeBank(uint8_t bank, utils::dataContainer* dataContainer)
+{
+ setBank(bank);
+
+ setLedColor(LED_COLOR_BLUE);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)(LPC_MEMORY_BASE + getBankStartOffset(bank));
+
+ for (uint32_t i = 0; i < dataContainer->size; i++)
+ {
+ uint8_t value = (uint8_t)dataContainer->data[i];
+ lpcMemMap[0x5555] = 0xAA;
+ lpcMemMap[0x2AAA] = 0x55;
+ lpcMemMap[0x5555] = 0xA0;
+ lpcMemMap[i] = value;
+ while (lpcMemMap[i] != value);
+ }
+ lpcMemMap[0] = 0xF0;
+
+ setBank(XCHANGER_BANK_BOOTLOADER);
+
+ setLedColor(LED_COLOR_GREEN);
+}
+
+bool modchipXchanger::verifyBank(uint8_t bank, utils::dataContainer* dataContainer)
+{
+ setBank(bank);
+
+ utils::dataContainer* writtenData = readBank(bank);
+
+ setLedColor(LED_COLOR_PURPLE);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ bool ok = true;
+ for (uint32_t i = 0; i < dataContainer->size; i++)
+ {
+ if (writtenData->data[i] == dataContainer->data[i])
+ {
+ continue;
+ }
+ ok = false;
+ break;
+ }
+
+ delete(writtenData);
+
+ setBank(XCHANGER_BANK_BOOTLOADER);
+
+ setLedColor(LED_COLOR_GREEN);
+ return ok;
+}
+
+uint8_t modchipXchanger::getFlashBankCount(bool recovery)
+{
+ return recovery ? 0 : 3;
+}
+
+uint8_t modchipXchanger::getFlashBank(bool recovery, uint8_t bank)
+{
+ const uint8_t banks[] = {
+ XCHANGER_BANK_SLOT1_256K,
+ XCHANGER_BANK_BOOTLOADER,
+ XCHANGER_BANK_PROMETHEOS
+ };
+ return recovery ? 0 : banks[bank];
+}
+
+bankType modchipXchanger::getFlashBankType(bool recovery, uint8_t bank)
+{
+ const bankType banks[] = {
+ bankTypeUser,
+ bankTypeSystem,
+ bankTypeSystem,
+ };
+ return recovery ? bankTypeUser : banks[bank];
+}
+
+utils::dataContainer* modchipXchanger::readFlash(bool recovery)
+{
+ utils::dataContainer* result = new utils::dataContainer(getFlashSize(recovery));
+ for (uint8_t i = 0; i < getFlashBankCount(recovery); i++)
+ {
+ uint8_t bank = getFlashBank(recovery, i);
+ uint32_t memOffset = getBankMemOffset(bank);
+ utils::dataContainer* bankData = readBank(bank);
+ memcpy(result->data + memOffset, bankData->data, bankData->size);
+ delete(bankData);
+ }
+ return result;
+}
+
+void modchipXchanger::launchBank(uint8_t bank, uint8_t ledColor)
+{
+ DWORD scratch;
+ HalReadSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, &scratch);
+ HalWriteSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, scratch & ~SCRATCH_REGISTER_BITVALUE_NO_ANIMATION);
+ setBank(bank);
+ setLedColor(ledColor);
+ HalReturnToFirmware(RETURN_FIRMWARE_REBOOT);
+}
+
+void modchipXchanger::launchTsop()
+{
+ DWORD scratch;
+ HalReadSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, &scratch);
+ HalWriteSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, scratch & ~SCRATCH_REGISTER_BITVALUE_NO_ANIMATION);
+ setBank(XCHANGER_BANK_TSOP);
+ setLedColor(LED_COLOR_OFF);
+ HalReturnToFirmware(RETURN_FIRMWARE_REBOOT);
+}
+
+void modchipXchanger::launchRecovery()
+{
+}
+
+#ifndef TOOLS
+
+void modchipXchanger::loadSettings(settingsState& settings)
+{
+ setBank(XCHANGER_SETTINGS_BANK);
+
+ setLedColor(LED_COLOR_WHITE);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ memcpy(&settings, (void*)&lpcMemMap[XCHANGER_SETTINGS_OFFSET], sizeof(settings));
+ uint32_t checksum = crc32::calculate(((uint8_t*)&settings) + sizeof(uint32_t), sizeof(settings) - sizeof(uint32_t));
+
+ setBank(XCHANGER_BANK_BOOTLOADER);
+
+ if (checksum != settings.checksum || versioning::compareVersion(settings.version, settingsManager::getVersion()) != 0)
+ {
+ settingsManager::initSettings();
+ settingsManager::saveSettings();
+ }
+
+ setLedColor(settingsManager::getLedColor());
+}
+
+void modchipXchanger::saveSettings(settingsState& settings)
+{
+ setBank(XCHANGER_SETTINGS_BANK);
+
+ settings.checksum = crc32::calculate(((uint8_t*)&settings) + sizeof(uint32_t), sizeof(settings) - sizeof(uint32_t));
+ utils::dataContainer* settingsData = new utils::dataContainer((char*)&settings, sizeof(settings), sizeof(settings));
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ setLedColor(LED_COLOR_AMBER);
+ sectorErase(XCHANGER_SETTINGS_OFFSET);
+
+ setLedColor(LED_COLOR_BLUE);
+ for (uint32_t i = 0; i < settingsData->size; i++)
+ {
+ uint8_t value = (uint8_t)settingsData->data[i];
+ lpcMemMap[0x5555] = 0xAA;
+ lpcMemMap[0x2AAA] = 0x55;
+ lpcMemMap[0x5555] = 0xA0;
+ lpcMemMap[XCHANGER_SETTINGS_OFFSET + i] = value;
+ while (lpcMemMap[XCHANGER_SETTINGS_OFFSET + i] != value);
+ }
+ lpcMemMap[0] = 0xF0;
+
+ setBank(XCHANGER_BANK_BOOTLOADER);
+
+ setLedColor(settingsManager::getLedColor());
+}
+
+#endif
+
+utils::dataContainer* modchipXchanger::getInstallerLogo()
+{
+ utils::dataContainer* installerLogo = new utils::dataContainer(32768);
+ return installerLogo;
+}
+
+displayDriver* modchipXchanger::getDisplayDriver(bool current)
+{
+ return NULL;
+}
+
+supportInfo modchipXchanger::getSupportInfo(bool current)
+{
+ supportInfo info;
+ info.supportsLed = false;
+ info.supportsLcd = false;
+ info.supportsLcdInfo = false;
+ info.supportsLcdBacklight = false;
+ info.supportsLcdContrast = false;
+ info.supportsRecovery = false;
+ return info;
+}
+
+uint8_t modchipXchanger::getLcdModeCount()
+{
+ return 0;
+}
+
+char* modchipXchanger::getLcdModeString(uint8_t lcdMode)
+{
+ return strdup("");
+}
+
+uint8_t modchipXchanger::getLcdModelCount(bool current)
+{
+ return 0;
+}
+
+char* modchipXchanger::getLcdModelString(bool current, uint8_t lcdModel)
+{
+ return strdup("");
+}
+
+uint8_t modchipXchanger::getLcdAddressCount(bool current)
+{
+ return 0;
+}
+
+char* modchipXchanger::getLcdAddressString(bool current, uint8_t lcdAddress)
+{
+ return strdup("");
+}
+
+void modchipXchanger::lcdSetCursorPosition(uint8_t row, uint8_t col)
+{
+}
+
+void modchipXchanger::lcdInit()
+{
+}
+
+void modchipXchanger::lcdPrintMessage(const char* message)
+{
+}
+
+void modchipXchanger::lcdSetBacklight(uint8_t value)
+{
+}
+
+void modchipXchanger::lcdSetContrast(uint8_t value)
+{
+}
+
+// Private
+
+void modchipXchanger::setBank(uint8_t bank)
+{
+ mBank = bank;
+ outputByte(XCHANGER_REGISTER_BANKING, bank);
+}
+
+uint8_t modchipXchanger::getBank()
+{
+ //mBank = inputByte(XCHANGER_REGISTER_BANKING);
+ return mBank;
+}
+
+bool modchipXchanger::isEraseMemOffset(uint32_t memOffset)
+{
+ return (memOffset % 4096) == 0;
+}
+
+bool modchipXchanger::isProtectedMemOffset(uint32_t memOffset)
+{
+ if (isProtectedMemOffset(memOffset))
+ {
+ return true;
+ }
+ return false;
+}
+
+void modchipXchanger::sectorErase(uint32_t offset)
+{
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+ lpcMemMap[0x5555] = 0xAA;
+ lpcMemMap[0x2AAA] = 0x55;
+ lpcMemMap[0x5555] = 0x80;
+ lpcMemMap[0x5555] = 0xAA;
+ lpcMemMap[0x2AAA] = 0x55;
+ lpcMemMap[offset] = 0x30;
+ while(lpcMemMap[0] != lpcMemMap[0]);
+ //lpcMemMap[0x5555]=0xaa;
+ // lpcMemMap[0x2aaa]=0x55;
+ lpcMemMap[0x5555]=0xF0;
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXchanger.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXchanger.h
new file mode 100644
index 0000000..82e4789
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXchanger.h
@@ -0,0 +1,74 @@
+#pragma once
+
+#include "modchip.h"
+#include "xboxInternals.h"
+
+#ifndef TOOLS
+#include "settingsManager.h"
+#endif
+
+class modchipXchanger : public modchip
+{
+public:
+
+ modchipXchanger();
+ void setLedColor(uint8_t ledColor);
+
+ uint32_t getSlotCount();
+ uint32_t getFlashSize(bool recovery);
+ void disableRecovery();
+ bool isValidBankSize(uint32_t size);
+ bool isValidFlashSize(bool recovery, uint32_t size);
+ uint32_t getBankSize(uint8_t bank);
+ uint32_t getBankMemOffset(uint8_t bank);
+ uint32_t getBankStartOffset(uint8_t bank);
+ uint8_t getBankFromIdAndSlots(uint8_t id, uint8_t slots);
+ utils::dataContainer* readBank(uint8_t bank);
+ void eraseBank(uint8_t bank);
+ void writeBank(uint8_t bank, utils::dataContainer* dataContainer);
+ bool verifyBank(uint8_t bank, utils::dataContainer* dataContainer);
+
+ uint8_t getFlashBankCount(bool recovery);
+ uint8_t getFlashBank(bool recovery, uint8_t bank);
+ bankType getFlashBankType(bool recovery, uint8_t bank);
+ utils::dataContainer* readFlash(bool recovery);
+
+ void launchBank(uint8_t bank, uint8_t ledColor);
+ void launchTsop();
+ void launchRecovery();
+
+#ifndef TOOLS
+ void loadSettings(settingsState& settings);
+ void saveSettings(settingsState& settings);
+#endif
+
+ utils::dataContainer* getInstallerLogo();
+
+ displayDriver* getDisplayDriver(bool current);
+ supportInfo getSupportInfo(bool current);
+ uint8_t getLcdModeCount();
+ char* getLcdModeString(uint8_t lcdMode);
+ uint8_t getLcdModelCount(bool current);
+ char* getLcdModelString(bool current, uint8_t lcdModel);
+ uint8_t getLcdAddressCount(bool current);
+ char* getLcdAddressString(bool current, uint8_t lcdAddress);
+
+ void lcdSetCursorPosition(uint8_t row, uint8_t col);
+ void lcdInit();
+ void lcdPrintMessage(const char* message);
+ void lcdSetBacklight(uint8_t value);
+ void lcdSetContrast(uint8_t value);
+
+private:
+
+ void setBank(uint8_t bank);
+ uint8_t getBank();
+ bool isEraseMemOffset(uint32_t memOffset);
+ bool isProtectedMemOffset(uint32_t memOffset);
+ void sectorErase(uint32_t offset);
+
+private:
+
+ uint8_t mBank;
+ uint8_t mSpi;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXecuter.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXecuter.cpp
new file mode 100644
index 0000000..1d6c96c
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXecuter.cpp
@@ -0,0 +1,777 @@
+#include "modchipXecuter.h"
+#include "crc32.h"
+#include "settingsManager.h"
+#include "globalDefines.h"
+#include "stringUtility.h"
+
+//#define DISPLAY_E 0x04 //Mapped for LPCMod output format.
+//#define DISPLAY_RS 0x02 //Mapped for LPCMod output format.
+//#define DISP_CLEAR 0x01 // cmd: clear display command
+//#define DISP_HOME 0x02 // cmd: return cursor to home
+//#define DISP_ENTRY_MODE_SET 0x04 // cmd: enable cursor moving direction and enable the shift of entire display
+//#define DISP_S_FLAG 0x01
+//#define DISP_ID_FLAG 0x02
+//#define DISP_CONTROL 0x08 //cmd: display ON/OFF
+//#define DISP_D_FLAG 0x04 // display on
+//#define DISP_C_FLAG 0x02 // cursor on
+//#define DISP_B_FLAG 0x01 // blinking on
+//#define DISP_EXT_CONTROL 0x08
+//
+//#define DISP_FW_FLAG 0x04
+//#define DISP_BW_FLAG 0x02
+//#define DISP_NW_FLAG 0x01
+//
+//#define DISP_SHIFT 0x10
+//#define DISP_SC_FLAG 0x08
+//#define DISP_RL_FLAG 0x04
+//#define DISP_FUNCTION_SET 0x20
+//#define DISP_DL_FLAG 0x10
+//#define DISP_N_FLAG 0x08
+//#define DISP_F_FLAG 0x04
+//#define DISP_RE_FLAG 0x04
+//#define DISP_CGRAM_SET 0x40
+//#define DISP_SEGRAM_SET 0x40
+#define DISP_DDRAM_SET 0x80
+
+
+//Bank_Bootloader = 0 0x000000 - 0x03ffff Sector Size 65536 Total 262144
+//Bank_PrometheOS1 = 1 0x040000 - 0x07ffff Sector Size 65536 Total 262144
+//Bank_PrometheOS2 = 2 0x080000 - 0x0bffff Sector Size 65536 Total 262144
+//Bank_PrometheOS3 = 3 0x0c0000 - 0x0fffff Sector Size 65536 Total 262144
+//Bank1_256k = 4 0x100000 - 0x13ffff Sector Size 65536 Total 262144
+//Bank2_256k = 5 0x140000 - 0x17ffff Sector Size 65536 Total 262144
+//Bank3_256k = 6 0x180000 - 0x1bffff Sector Size 65536 Total 262144
+//Bank4_256k = 7 0x1c0000 - 0x1fffff Sector Size 65536 Total 262144
+//Bank1_512k = 7 0x100000 - 0x17ffff Sector Size 65536 Total 524288
+//Bank2_512k = 8 0x180000 - 0x1fffff Sector Size 65536 Total 524288
+//Bank1_1024k = 9 0x100000 - 0x1fffff Sector Size 65536 Total 1048576
+
+//0x0c0000 - 0x0dffff Total 131072 PrometheOS Continued
+//0x0e0000 - 0x0effff Total 65536 Installer Logo
+//0x0f0000 - 0x0fffff Total 65536 Settings
+
+modchipXecuter::modchipXecuter()
+{
+ mBank = XECUTER_BANK_BOOTLOADER;
+}
+
+void modchipXecuter::setLedColor(uint8_t ledColor)
+{
+}
+
+uint32_t modchipXecuter::getSlotCount()
+{
+ return 4;
+}
+
+uint32_t modchipXecuter::getFlashSize(bool recovery)
+{
+ return recovery ? (256 * 1024) : (2 * 1024 * 1024);
+}
+
+void modchipXecuter::disableRecovery()
+{
+ outputByte(XECUTER_REGISTER_HARDWARE_BANKING, XECUTER_DISABLE_BACKUP);
+}
+
+bool modchipXecuter::isValidBankSize(uint32_t size)
+{
+ return size == (256 * 1024) || size == (512 * 1024) || size == (1024 * 1024);
+}
+
+bool modchipXecuter::isValidFlashSize(bool recovery, uint32_t size)
+{
+ return size == getFlashSize(recovery);
+}
+
+uint32_t modchipXecuter::getBankSize(uint8_t bank)
+{
+ if (bank == XECUTER_BANK_BOOTLOADER)
+ {
+ return 256 * 1024;
+ }
+ if (bank == XECUTER_BANK_PROMETHEOS1)
+ {
+ return 256 * 1024;
+ }
+ if (bank == XECUTER_BANK_PROMETHEOS2)
+ {
+ return 256 * 1024;
+ }
+ if (bank == XECUTER_BANK_PROMETHEOS3)
+ {
+ return 256 * 1024;
+ }
+ if (bank == XECUTER_BANK_SLOT1_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == XECUTER_BANK_SLOT2_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == XECUTER_BANK_SLOT3_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == XECUTER_BANK_SLOT4_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == XECUTER_BANK_SLOT1_512K)
+ {
+ return 512 * 1024;
+ }
+ if (bank == XECUTER_BANK_SLOT2_512K)
+ {
+ return 512 * 1024;
+ }
+ if (bank == XECUTER_BANK_SLOT1_1024K)
+ {
+ return 1024 * 1024;
+ }
+ if (bank == XECUTER_BANK_BACKUP_256K)
+ {
+ return 256 * 1024;
+ }
+ return 0;
+}
+
+uint32_t modchipXecuter::getBankMemOffset(uint8_t bank)
+{
+ if (bank == XECUTER_BANK_BOOTLOADER)
+ {
+ return 0x000000;
+ }
+ if (bank == XECUTER_BANK_PROMETHEOS1)
+ {
+ return 0x040000;
+ }
+ if (bank == XECUTER_BANK_PROMETHEOS2)
+ {
+ return 0x080000;
+ }
+ if (bank == XECUTER_BANK_PROMETHEOS3)
+ {
+ return 0x0c0000;
+ }
+ if (bank == XECUTER_BANK_SLOT1_256K)
+ {
+ return 0x100000;
+ }
+ if (bank == XECUTER_BANK_SLOT2_256K)
+ {
+ return 0x140000;
+ }
+ if (bank == XECUTER_BANK_SLOT3_256K)
+ {
+ return 0x180000;
+ }
+ if (bank == XECUTER_BANK_SLOT4_256K)
+ {
+ return 0x1c0000;
+ }
+ if (bank == XECUTER_BANK_SLOT1_512K)
+ {
+ return 0x100000;
+ }
+ if (bank == XECUTER_BANK_SLOT2_512K)
+ {
+ return 0x180000;
+ }
+ if (bank == XECUTER_BANK_SLOT1_1024K)
+ {
+ return 0x100000;
+ }
+ if (bank == XECUTER_BANK_BACKUP_256K)
+ {
+ return 0x000000;
+ }
+ return 0;
+}
+
+uint32_t modchipXecuter::getBankStartOffset(uint8_t bank)
+{
+ return 0;
+}
+
+uint8_t modchipXecuter::getBankFromIdAndSlots(uint8_t id, uint8_t slots)
+{
+ if (id == 0 && slots == 1)
+ {
+ return XECUTER_BANK_SLOT1_256K;
+ }
+ if (id == 1 && slots == 1)
+ {
+ return XECUTER_BANK_SLOT2_256K;
+ }
+ if (id == 2 && slots == 1)
+ {
+ return XECUTER_BANK_SLOT3_256K;
+ }
+ if (id == 3 && slots == 1)
+ {
+ return XECUTER_BANK_SLOT4_256K;
+ }
+ if (id == 0 && slots == 2)
+ {
+ return XECUTER_BANK_SLOT1_512K;
+ }
+ if (id == 2 && slots == 2)
+ {
+ return XECUTER_BANK_SLOT2_512K;
+ }
+ if (id == 0 && slots == 4)
+ {
+ return XECUTER_BANK_SLOT1_1024K;
+ }
+ return 0;
+}
+
+utils::dataContainer* modchipXecuter::readBank(uint8_t bank)
+{
+ setBank(bank);
+ uint32_t bankSize = getBankSize(bank);
+ utils::dataContainer* dataContainer = new utils::dataContainer(bankSize);
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)(LPC_MEMORY_BASE + getBankStartOffset(bank));
+ memcpy(dataContainer->data, (void*)&lpcMemMap[0], bankSize);
+ setBank(XECUTER_BANK_BOOTLOADER);
+ return dataContainer;
+}
+
+void modchipXecuter::eraseBank(uint8_t bank)
+{
+ setBank(bank);
+
+ setLedColor(LED_COLOR_AMBER);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ uint32_t memOffset = getBankMemOffset(bank);
+ uint32_t startOffset = getBankStartOffset(bank);
+ uint32_t bankSize = getBankSize(bank);
+
+ uint32_t offset = 0;
+ while (offset < bankSize)
+ {
+ if (isEraseMemOffset(memOffset + startOffset + offset))
+ {
+ sectorErase(offset);
+ }
+ offset += 8192;
+ }
+
+ setBank(XECUTER_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+}
+
+void modchipXecuter::writeBank(uint8_t bank, utils::dataContainer* dataContainer)
+{
+ setBank(bank);
+
+ setLedColor(LED_COLOR_BLUE);
+
+ if (checkWriteProtect() == false)
+ {
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)(LPC_MEMORY_BASE + getBankStartOffset(bank));
+
+ uint32_t memOffset = getBankMemOffset(bank);
+
+ for (uint32_t i = 0; i < dataContainer->size; i++)
+ {
+ if (isProtectedMemOffset(memOffset + i) == true)
+ {
+ continue;
+ }
+ uint8_t value = (uint8_t)dataContainer->data[i];
+ lpcMemMap[0x5555] = 0xAA;
+ lpcMemMap[0x2AAA] = 0x55;
+ lpcMemMap[0x5555] = 0xA0;
+ lpcMemMap[i] = value;
+ while (lpcMemMap[i] != value);
+ }
+ lpcMemMap[0] = 0xf0;
+ }
+
+ setBank(XECUTER_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+}
+
+bool modchipXecuter::verifyBank(uint8_t bank, utils::dataContainer* dataContainer)
+{
+ setBank(bank);
+
+ utils::dataContainer* writtenData = readBank(bank);
+
+ setLedColor(LED_COLOR_PURPLE);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ uint32_t memOffset = getBankMemOffset(bank);
+
+ bool ok = true;
+ for (uint32_t i = 0; i < dataContainer->size; i++)
+ {
+ if (isProtectedMemOffset(memOffset + i) == true)
+ {
+ continue;
+ }
+ if (writtenData->data[i] == dataContainer->data[i])
+ {
+ continue;
+ }
+ ok = false;
+ break;
+ }
+
+ delete(writtenData);
+
+ setBank(XECUTER_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+ return ok;
+}
+
+uint8_t modchipXecuter::getFlashBankCount(bool recovery)
+{
+ return recovery ? 1 : 8;
+}
+
+uint8_t modchipXecuter::getFlashBank(bool recovery, uint8_t bank)
+{
+ const uint8_t banks[] = {
+ XECUTER_BANK_SLOT1_256K,
+ XECUTER_BANK_SLOT2_256K,
+ XECUTER_BANK_SLOT3_256K,
+ XECUTER_BANK_SLOT4_256K,
+ XECUTER_BANK_BOOTLOADER,
+ XECUTER_BANK_PROMETHEOS1,
+ XECUTER_BANK_PROMETHEOS2,
+ XECUTER_BANK_PROMETHEOS3
+ };
+ return recovery ? XECUTER_BANK_BACKUP_256K : banks[bank];
+}
+
+bankType modchipXecuter::getFlashBankType(bool recovery, uint8_t bank)
+{
+ const bankType banks[] = {
+ bankTypeUser,
+ bankTypeUser,
+ bankTypeUser,
+ bankTypeUser,
+ bankTypeSystem,
+ bankTypeSystem,
+ bankTypeSystem,
+ bankTypeSystem,
+ };
+ return recovery ? bankTypeUser : banks[bank];
+}
+
+utils::dataContainer* modchipXecuter::readFlash(bool recovery)
+{
+ utils::dataContainer* result = new utils::dataContainer(getFlashSize(recovery));
+ for (uint8_t i = 0; i < getFlashBankCount(recovery); i++)
+ {
+ uint8_t bank = getFlashBank(recovery, i);
+ uint32_t memOffset = getBankMemOffset(bank);
+ utils::dataContainer* bankData = readBank(bank);
+ memcpy(result->data + memOffset, bankData->data, bankData->size);
+ delete(bankData);
+ }
+ return result;
+}
+
+void modchipXecuter::launchBank(uint8_t bank, uint8_t ledColor)
+{
+ DWORD scratch;
+ HalReadSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, &scratch);
+ HalWriteSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, scratch & ~SCRATCH_REGISTER_BITVALUE_NO_ANIMATION);
+ setBank(bank);
+ setLedColor(ledColor);
+ HalReturnToFirmware(RETURN_FIRMWARE_REBOOT);
+}
+
+void modchipXecuter::launchTsop()
+{
+ DWORD scratch;
+ HalReadSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, &scratch);
+ HalWriteSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, scratch & ~SCRATCH_REGISTER_BITVALUE_NO_ANIMATION);
+ setBank(XECUTER_BANK_TSOP);
+ setLedColor(LED_COLOR_OFF);
+ HalReturnToFirmware(RETURN_FIRMWARE_REBOOT);
+}
+
+void modchipXecuter::launchRecovery()
+{
+ DWORD scratch;
+ HalReadSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, &scratch);
+ HalWriteSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, scratch & ~SCRATCH_REGISTER_BITVALUE_NO_ANIMATION);
+ setBank(XECUTER_BANK_BACKUP_256K);
+ setLedColor(LED_COLOR_OFF);
+ HalReturnToFirmware(RETURN_FIRMWARE_REBOOT);
+}
+
+#ifndef TOOLS
+
+void modchipXecuter::loadSettings(settingsState& settings)
+{
+ setBank(XECUTER_SETTINGS_BANK);
+
+ setLedColor(LED_COLOR_WHITE);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ memcpy(&settings, (void*)&lpcMemMap[XECUTER_SETTINGS_OFFSET], sizeof(settings));
+ uint32_t checksum = crc32::calculate(((uint8_t*)&settings) + sizeof(uint32_t), sizeof(settings) - sizeof(uint32_t));
+
+ setBank(XECUTER_BANK_BOOTLOADER);
+
+ if (checksum != settings.checksum || versioning::compareVersion(settings.version, settingsManager::getVersion()) != 0)
+ {
+ settingsManager::initSettings();
+ settingsManager::saveSettings();
+ }
+
+ setLedColor(settingsManager::getLedColor());
+}
+
+void modchipXecuter::saveSettings(settingsState& settings)
+{
+ if (checkWriteProtect() == true)
+ {
+ return;
+ }
+
+ setBank(XECUTER_SETTINGS_BANK);
+
+ settings.checksum = crc32::calculate(((uint8_t*)&settings) + sizeof(uint32_t), sizeof(settings) - sizeof(uint32_t));
+ utils::dataContainer* settingsData = new utils::dataContainer((char*)&settings, sizeof(settings), sizeof(settings));
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ setLedColor(LED_COLOR_AMBER);
+ sectorErase(XECUTER_SETTINGS_OFFSET);
+
+ setLedColor(LED_COLOR_BLUE);
+ for (uint32_t i = 0; i < settingsData->size; i++)
+ {
+ uint8_t value = (uint8_t)settingsData->data[i];
+ lpcMemMap[0x5555] = 0xAA;
+ lpcMemMap[0x2AAA] = 0x55;
+ lpcMemMap[0x5555] = 0xA0;
+ lpcMemMap[XECUTER_SETTINGS_OFFSET + i] = value;
+ while (lpcMemMap[XECUTER_SETTINGS_OFFSET + i] != value);
+ }
+ lpcMemMap[0] = 0xF0;
+
+ setBank(XECUTER_BANK_BOOTLOADER);
+
+ setLedColor(settingsManager::getLedColor());
+}
+
+#endif
+
+utils::dataContainer* modchipXecuter::getInstallerLogo()
+{
+ setBank(XECUTER_INSTALLER_LOGO_BANK);
+
+ setLedColor(LED_COLOR_WHITE);
+
+ utils::dataContainer* installerLogo = new utils::dataContainer(32768);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+ memcpy(installerLogo->data, (void*)&lpcMemMap[XECUTER_INSTALLER_LOGO_OFFSET], installerLogo->size);
+
+ setBank(XECUTER_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+ return installerLogo;
+}
+
+displayDriver* modchipXecuter::getDisplayDriver(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ uint8_t lcdModel = settingsManager::getLcdModel(current);
+ if (lcdMode == 1)
+ {
+ if (lcdModel == 0)
+ {
+ return displayFactory::getDisplay(displayVariantHD44780Xecuter);
+ }
+ }
+ if (lcdMode == 2)
+ {
+ if (lcdModel == 0)
+ {
+ return displayFactory::getDisplay(displayVariantHD44780LPC);
+ }
+ if (lcdModel == 1)
+ {
+ return displayFactory::getDisplay(displayVariantLCDXXXXLPC);
+ }
+ }
+ return NULL;
+}
+
+supportInfo modchipXecuter::getSupportInfo(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ supportInfo info;
+ info.supportsLed = false;
+ info.supportsLcd = true;
+
+ bool lcdInfo = false;
+ bool backlight = false;
+ bool contrast = false;
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver != NULL)
+ {
+ driver->getSupport(lcdInfo, backlight, contrast);
+ }
+ info.supportsLcdInfo = lcdInfo;
+ info.supportsLcdBacklight = backlight;
+ info.supportsLcdContrast = contrast;
+
+ info.supportsRecovery = true;
+ return info;
+}
+
+uint8_t modchipXecuter::getLcdModeCount()
+{
+ return 3;
+}
+
+char* modchipXecuter::getLcdModeString(uint8_t lcdMode)
+{
+ if (lcdMode == 1)
+ {
+ return strdup("Xecuter");
+ }
+ if (lcdMode == 2)
+ {
+ return strdup("SMBUS");
+ }
+ return strdup("Disabled");
+}
+
+uint8_t modchipXecuter::getLcdModelCount(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ if (lcdMode == 1)
+ {
+ return 1;
+ }
+ if (lcdMode == 2)
+ {
+ return 2;
+ }
+ return 0;
+}
+
+char* modchipXecuter::getLcdModelString(bool current, uint8_t lcdModel)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return strdup("");
+ }
+ return driver->getModel();
+}
+
+uint8_t modchipXecuter::getLcdAddressCount(bool current)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return 0;
+ }
+ return driver->getI2cAddressCount();
+}
+
+char* modchipXecuter::getLcdAddressString(bool current, uint8_t lcdAddress)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return strdup("");
+ }
+ uint8_t address = driver->getI2cAddress(lcdAddress);
+ char* result = stringUtility::formatString("0x%2X", address);
+ return result;
+}
+
+void modchipXecuter::lcdSetCursorPosition(uint8_t row, uint8_t col)
+{
+ if (row > 3)
+ {
+ row = 3;
+ }
+ if (col > 19)
+ {
+ col = 19;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setCursorPosition(row, col);
+}
+
+void modchipXecuter::lcdInit()
+{
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->init();
+}
+
+void modchipXecuter::lcdPrintMessage(const char* message)
+{
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->printMessage(message);
+}
+
+void modchipXecuter::lcdSetBacklight(uint8_t value)
+{
+ if (value > 100)
+ {
+ value = 100;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setBacklight(value);
+}
+
+void modchipXecuter::lcdSetContrast(uint8_t value)
+{
+ if (value > 100)
+ {
+ value = 100;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setContrast(value);
+}
+
+// Private
+
+void modchipXecuter::setBank(uint8_t bank)
+{
+ mBank = bank;
+
+ if (mBank > 0xf)
+ {
+ outputByte(XECUTER_REGISTER_HARDWARE_BANKING, mBank);
+ }
+ else
+ {
+ outputByte(XECUTER_REGISTER_SOFTWARE_BANKING, mBank | 0x80);
+ }
+}
+
+uint8_t modchipXecuter::getBank()
+{
+ return mBank;
+}
+
+bool modchipXecuter::isEraseMemOffset(uint32_t memOffset)
+{
+ if (mBank == XECUTER_BANK_BACKUP_256K)
+ {
+ if (memOffset >= 0x000000 && memOffset <= 0x02ffff)
+ {
+ return (memOffset % 65536) == 0;
+ }
+ if (memOffset >= 0x030000 && memOffset <= 0x037fff)
+ {
+ return (memOffset % 32768) == 0;
+ }
+ if (memOffset >= 0x038000 && memOffset <= 0x03bfff)
+ {
+ return (memOffset % 8192) == 0;
+ }
+ if (memOffset >= 0x03c000 && memOffset <= 0x03ffff)
+ {
+ return (memOffset % 16384) == 0;
+ }
+ }
+ return (memOffset % 65536) == 0;
+}
+
+bool modchipXecuter::isProtectedMemOffset(uint32_t memOffset)
+{
+ return false;
+}
+
+void modchipXecuter::sectorErase(uint32_t offset)
+{
+ if (mBank != XECUTER_BANK_BACKUP_256K && (checkWriteProtect() || isProtectedMemOffset(offset)))
+ {
+ return;
+ }
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+ lpcMemMap[0x5555] = 0xAA;
+ lpcMemMap[0x2AAA] = 0x55;
+ lpcMemMap[0x5555] = 0x80;
+ lpcMemMap[0x5555] = 0xAA;
+ lpcMemMap[0x2AAA] = 0x55;
+ lpcMemMap[offset] = 0x30;
+ while(lpcMemMap[0] != lpcMemMap[0]);
+ lpcMemMap[0] = 0xF0;
+}
+
+bool modchipXecuter::checkWriteProtect()
+{
+ if (mBank == XECUTER_BANK_BACKUP_256K)
+ {
+ return false;
+ }
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ lpcMemMap[0x5555] = 0xAA;
+ lpcMemMap[0x2AAA] = 0x55;
+ lpcMemMap[0x5555] = 0x90;
+ uint8_t manuf = lpcMemMap[0];
+ uint8_t devid = lpcMemMap[1];
+ lpcMemMap[0] = 0xF0;
+
+ bool isProtectOn = (manuf != 0x01 || devid != 0xad);
+ return isProtectOn;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXecuter.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXecuter.h
new file mode 100644
index 0000000..6db2e68
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXecuter.h
@@ -0,0 +1,74 @@
+#pragma once
+
+#include "modchip.h"
+#include "xboxInternals.h"
+
+#ifndef TOOLS
+#include "settingsManager.h"
+#endif
+
+class modchipXecuter : public modchip
+{
+public:
+
+ modchipXecuter();
+ void setLedColor(uint8_t ledColor);
+
+ uint32_t getSlotCount();
+ uint32_t getFlashSize(bool recovery);
+ void disableRecovery();
+ bool isValidBankSize(uint32_t size);
+ bool isValidFlashSize(bool recovery, uint32_t size);
+ uint32_t getBankSize(uint8_t bank);
+ uint32_t getBankMemOffset(uint8_t bank);
+ uint32_t getBankStartOffset(uint8_t bank);
+ uint8_t getBankFromIdAndSlots(uint8_t id, uint8_t slots);
+ utils::dataContainer* readBank(uint8_t bank);
+ void eraseBank(uint8_t bank);
+ void writeBank(uint8_t bank, utils::dataContainer* dataContainer);
+ bool verifyBank(uint8_t bank, utils::dataContainer* dataContainer);
+
+ uint8_t getFlashBankCount(bool recovery);
+ uint8_t getFlashBank(bool recovery, uint8_t bank);
+ bankType getFlashBankType(bool recovery, uint8_t bank);
+ utils::dataContainer* readFlash(bool recovery);
+
+ void launchBank(uint8_t bank, uint8_t ledColor);
+ void launchTsop();
+ void launchRecovery();
+
+#ifndef TOOLS
+ void loadSettings(settingsState& settings);
+ void saveSettings(settingsState& settings);
+#endif
+
+ utils::dataContainer* getInstallerLogo();
+
+ displayDriver* getDisplayDriver(bool current);
+ supportInfo getSupportInfo(bool current);
+ uint8_t getLcdModeCount();
+ char* getLcdModeString(uint8_t lcdMode);
+ uint8_t getLcdModelCount(bool current);
+ char* getLcdModelString(bool current, uint8_t lcdModel);
+ uint8_t getLcdAddressCount(bool current);
+ char* getLcdAddressString(bool current, uint8_t lcdAddress);
+
+ void lcdSetCursorPosition(uint8_t row, uint8_t col);
+ void lcdInit();
+ void lcdPrintMessage(const char* message);
+ void lcdSetBacklight(uint8_t value);
+ void lcdSetContrast(uint8_t value);
+
+private:
+
+ void setBank(uint8_t bank);
+ uint8_t getBank();
+ bool isEraseMemOffset(uint32_t memOffset);
+ bool isProtectedMemOffset(uint32_t memOffset);
+ void sectorErase(uint32_t offset);
+ bool checkWriteProtect();
+
+private:
+
+ uint8_t mBank;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXenium.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXenium.cpp
new file mode 100644
index 0000000..66edfc3
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXenium.cpp
@@ -0,0 +1,712 @@
+#include "modchipXenium.h"
+#include "crc32.h"
+#include "settingsManager.h"
+#include "globalDefines.h"
+#include "stringUtility.h"
+
+//Bank1_256k = 3 0x000000 - 0x03ffff Sector Size 65536 Total 262144
+//Bank2_256k = 4 0x040000 - 0x07ffff Sector Size 65536 Total 262144
+//Bank3_256k = 5 0x080000 - 0x0bffff Sector Size 65536 Total 262144
+//Bank4_256k = 6 0x0c0000 - 0x0fffff Sector Size 65536 Total 262144
+//Bank1_512k = 7 0x000000 - 0x07ffff Sector Size 65536 Total 524288
+//Bank2_512k = 8 0x080000 - 0x0fffff Sector Size 65536 Total 524288
+//Bank1_1024k = 9 0x000000 - 0x0fffff Sector Size 65536 Total 1048576
+//Bank_PrometheOS = 2 0x100000 - 0x17ffff Sector Size 65536 Total 524288
+//Bank_Bootloader = 1 0x180000 - 0x1bffff Sector Size 65536 Total 262144
+//Bank_Recovery = 10 0x1c0000 - 0x1fffff See Below Total 262144
+
+//0x1c0000 - 0x1effff Sector Size 65536
+//0x1f0000 - 0x1f7fff Sector Size 32768
+//0x1f8000 - 0x1fbfff Sector Size 8192
+//0x1fc000 - 0x1fffff Sector Size 16384
+
+//0x1c0000 - 0x1dffff Total 131072 (Protected - Installer Logo (IOpen Xenium))
+//0x1e0000 - 0x1f7fff Total 98304 (PrometheOS Continued)
+//0x1f8000 - 0x1f9fff Total 8192 (Protected)
+//0x1fa000 - 0x1fbfff Total 8192 (Settings)
+//0x1fc000 - 0x1fffff Total 16384 (Spare)
+
+modchipXenium::modchipXenium()
+{
+ InitializeCriticalSection(&mMutex);
+ uint8_t bank = XENIUM_BANK_BOOTLOADER;
+ displaySPI2PARXenium::getInstance()->setBankValue(bank);
+ uint8_t spi = inputByte(XENIUM_REGISTER_BANKING) & 0x70;
+ displaySPI2PARXenium::getInstance()->setSpiValue(spi);
+}
+
+void modchipXenium::setLedColor(uint8_t ledColor)
+{
+ outputByte(XENIUM_REGISTER_LED, ledColor);
+}
+
+uint32_t modchipXenium::getSlotCount()
+{
+ return 4;
+}
+
+uint32_t modchipXenium::getFlashSize(bool recovery)
+{
+ return recovery ? 0 : (2 * 1024 * 1024);
+}
+
+void modchipXenium::disableRecovery()
+{
+}
+
+bool modchipXenium::isValidBankSize(uint32_t size)
+{
+ return size == (256 * 1024) || size == (512 * 1024) || size == (1024 * 1024);
+}
+
+bool modchipXenium::isValidFlashSize(bool recovery, uint32_t size)
+{
+ return size == getFlashSize(recovery);
+}
+
+
+uint32_t modchipXenium::getBankSize(uint8_t bank)
+{
+ if (bank == XENIUM_BANK_BOOTLOADER)
+ {
+ return 256 * 1024;
+ }
+ if (bank == XENIUM_BANK_PROMETHEOS1)
+ {
+ return 512 * 1024;
+ }
+ if (bank == XENIUM_BANK_PROMETHEOS2)
+ {
+ return 256 * 1024;
+ }
+ if (bank == XENIUM_BANK_SLOT1_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == XENIUM_BANK_SLOT2_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == XENIUM_BANK_SLOT3_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == XENIUM_BANK_SLOT4_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == XENIUM_BANK_SLOT1_512K)
+ {
+ return 512 * 1024;
+ }
+ if (bank == XENIUM_BANK_SLOT2_512K)
+ {
+ return 512 * 1024;
+ }
+ if (bank == XENIUM_BANK_SLOT1_1024K)
+ {
+ return 1024 * 1024;
+ }
+ return 0;
+}
+
+uint32_t modchipXenium::getBankMemOffset(uint8_t bank)
+{
+ if (bank == XENIUM_BANK_SLOT1_256K)
+ {
+ return 0x000000;
+ }
+ if (bank == XENIUM_BANK_SLOT2_256K)
+ {
+ return 0x040000;
+ }
+ if (bank == XENIUM_BANK_SLOT2_256K)
+ {
+ return 0x080000;
+ }
+ if (bank == XENIUM_BANK_SLOT4_256K)
+ {
+ return 0x0c0000;
+ }
+ if (bank == XENIUM_BANK_SLOT1_512K)
+ {
+ return 0x000000;
+ }
+ if (bank == XENIUM_BANK_SLOT2_512K)
+ {
+ return 0x080000;
+ }
+ if (bank == XENIUM_BANK_SLOT1_1024K)
+ {
+ return 0x000000;
+ }
+ if (bank == XENIUM_BANK_BOOTLOADER)
+ {
+ return 0x180000;
+ }
+ if (bank == XENIUM_BANK_PROMETHEOS1)
+ {
+ return 0x100000;
+ }
+ if (bank == XENIUM_BANK_PROMETHEOS2)
+ {
+ return 0x1c0000;
+ }
+ return 0;
+}
+
+uint32_t modchipXenium::getBankStartOffset(uint8_t bank)
+{
+ return 0;
+}
+
+uint8_t modchipXenium::getBankFromIdAndSlots(uint8_t id, uint8_t slots)
+{
+ if (id == 0 && slots == 1)
+ {
+ return XENIUM_BANK_SLOT1_256K;
+ }
+ if (id == 1 && slots == 1)
+ {
+ return XENIUM_BANK_SLOT2_256K;
+ }
+ if (id == 2 && slots == 1)
+ {
+ return XENIUM_BANK_SLOT3_256K;
+ }
+ if (id == 3 && slots == 1)
+ {
+ return XENIUM_BANK_SLOT4_256K;
+ }
+ if (id == 0 && slots == 2)
+ {
+ return XENIUM_BANK_SLOT1_512K;
+ }
+ if (id == 2 && slots == 2)
+ {
+ return XENIUM_BANK_SLOT2_512K;
+ }
+ if (id == 0 && slots == 4)
+ {
+ return XENIUM_BANK_SLOT1_1024K;
+ }
+ return 0;
+}
+
+utils::dataContainer* modchipXenium::readBank(uint8_t bank)
+{
+ setBank(bank);
+ uint32_t bankSize = getBankSize(bank);
+ utils::dataContainer* dataContainer = new utils::dataContainer(bankSize);
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)(LPC_MEMORY_BASE + getBankStartOffset(bank));
+ memcpy(dataContainer->data, (void*)&lpcMemMap[0], bankSize);
+ setBank(XENIUM_BANK_BOOTLOADER);
+ return dataContainer;
+}
+
+void modchipXenium::eraseBank(uint8_t bank)
+{
+ setBank(bank);
+
+ setLedColor(LED_COLOR_AMBER);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ uint32_t memOffset = getBankMemOffset(bank);
+ uint32_t startOffset = getBankStartOffset(bank);
+ uint32_t bankSize = getBankSize(bank);
+
+ uint32_t offset = 0;
+ while (offset < bankSize)
+ {
+ if (isEraseMemOffset(memOffset + startOffset + offset))
+ {
+ sectorErase(offset);
+ }
+ offset += 8192;
+ }
+
+ setBank(XENIUM_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+}
+
+void modchipXenium::writeBank(uint8_t bank, utils::dataContainer* dataContainer)
+{
+ setBank(bank);
+
+ setLedColor(LED_COLOR_BLUE);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)(LPC_MEMORY_BASE + getBankStartOffset(bank));
+
+ uint32_t memOffset = getBankMemOffset(bank);
+
+ for (uint32_t i = 0; i < dataContainer->size; i++)
+ {
+ if (isProtectedMemOffset(memOffset + i) == true)
+ {
+ continue;
+ }
+ uint8_t value = (uint8_t)dataContainer->data[i];
+ lpcMemMap[0xAAAA] = 0xAA;
+ lpcMemMap[0x5555] = 0x55;
+ lpcMemMap[0xAAAA] = 0xA0;
+ lpcMemMap[i] = value;
+ while (lpcMemMap[i] != value);
+ }
+ lpcMemMap[0] = 0xf0;
+
+ setBank(XENIUM_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+}
+
+bool modchipXenium::verifyBank(uint8_t bank, utils::dataContainer* dataContainer)
+{
+ setBank(bank);
+
+ utils::dataContainer* writtenData = readBank(bank);
+
+ setLedColor(LED_COLOR_PURPLE);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ uint32_t memOffset = getBankMemOffset(bank);
+
+ bool ok = true;
+ for (uint32_t i = 0; i < dataContainer->size; i++)
+ {
+ if (isProtectedMemOffset(memOffset + i) == true)
+ {
+ continue;
+ }
+ if (writtenData->data[i] == dataContainer->data[i])
+ {
+ continue;
+ }
+ ok = false;
+ break;
+ }
+
+ delete(writtenData);
+
+ setBank(XENIUM_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+ return ok;
+}
+
+uint8_t modchipXenium::getFlashBankCount(bool recovery)
+{
+ return recovery ? 0 : 7;
+}
+
+uint8_t modchipXenium::getFlashBank(bool recovery, uint8_t bank)
+{
+ const uint8_t banks[] = {
+ XENIUM_BANK_SLOT1_256K,
+ XENIUM_BANK_SLOT2_256K,
+ XENIUM_BANK_SLOT3_256K,
+ XENIUM_BANK_SLOT4_256K,
+ XENIUM_BANK_BOOTLOADER,
+ XENIUM_BANK_PROMETHEOS1,
+ XENIUM_BANK_PROMETHEOS2,
+ };
+ return recovery ? 0 : banks[bank];
+}
+
+bankType modchipXenium::getFlashBankType(bool recovery, uint8_t bank)
+{
+ const bankType banks[] = {
+ bankTypeUser,
+ bankTypeUser,
+ bankTypeUser,
+ bankTypeUser,
+ bankTypeSystem,
+ bankTypeSystem,
+ bankTypeSystem,
+ };
+ return recovery ? bankTypeUser : banks[bank];
+}
+
+utils::dataContainer* modchipXenium::readFlash(bool recovery)
+{
+ utils::dataContainer* result = new utils::dataContainer(getFlashSize(recovery));
+ for (uint8_t i = 0; i < getFlashBankCount(recovery); i++)
+ {
+ uint8_t bank = getFlashBank(recovery, i);
+ uint32_t memOffset = getBankMemOffset(bank);
+ utils::dataContainer* bankData = readBank(bank);
+ memcpy(result->data + memOffset, bankData->data, bankData->size);
+ delete(bankData);
+ }
+ return result;
+}
+
+void modchipXenium::launchBank(uint8_t bank, uint8_t ledColor)
+{
+ DWORD scratch;
+ HalReadSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, &scratch);
+ HalWriteSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, scratch & ~SCRATCH_REGISTER_BITVALUE_NO_ANIMATION);
+ setBank(bank);
+ setLedColor(ledColor);
+ HalReturnToFirmware(RETURN_FIRMWARE_REBOOT);
+}
+
+void modchipXenium::launchTsop()
+{
+ DWORD scratch;
+ HalReadSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, &scratch);
+ HalWriteSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, scratch & ~SCRATCH_REGISTER_BITVALUE_NO_ANIMATION);
+ setBank(XENIUM_BANK_TSOP);
+ setLedColor(LED_COLOR_OFF);
+ HalReturnToFirmware(RETURN_FIRMWARE_REBOOT);
+}
+
+void modchipXenium::launchRecovery()
+{
+}
+
+#ifndef TOOLS
+
+void modchipXenium::loadSettings(settingsState& settings)
+{
+ setBank(XENIUM_SETTINGS_BANK);
+
+ setLedColor(LED_COLOR_WHITE);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ memcpy(&settings, (void*)&lpcMemMap[XENIUM_SETTINGS_OFFSET], sizeof(settings));
+ uint32_t checksum = crc32::calculate(((uint8_t*)&settings) + sizeof(uint32_t), sizeof(settings) - sizeof(uint32_t));
+
+ setBank(XENIUM_BANK_BOOTLOADER);
+
+ if (checksum != settings.checksum || versioning::compareVersion(settings.version, settingsManager::getVersion()) != 0)
+ {
+ settingsManager::initSettings();
+ settingsManager::saveSettings();
+ }
+
+ setLedColor(settingsManager::getLedColor());
+}
+
+void modchipXenium::saveSettings(settingsState& settings)
+{
+ setBank(XENIUM_SETTINGS_BANK);
+
+ settings.checksum = crc32::calculate(((uint8_t*)&settings) + sizeof(uint32_t), sizeof(settings) - sizeof(uint32_t));
+ utils::dataContainer* settingsData = new utils::dataContainer((char*)&settings, sizeof(settings), sizeof(settings));
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ setLedColor(LED_COLOR_AMBER);
+ sectorErase(XENIUM_SETTINGS_OFFSET);
+
+ setLedColor(LED_COLOR_BLUE);
+ for (uint32_t i = 0; i < settingsData->size; i++)
+ {
+ uint8_t value = (uint8_t)settingsData->data[i];
+ lpcMemMap[0xAAAA] = 0xAA;
+ lpcMemMap[0x5555] = 0x55;
+ lpcMemMap[0xAAAA] = 0xA0;
+ lpcMemMap[XENIUM_SETTINGS_OFFSET + i] = value;
+ while (lpcMemMap[XENIUM_SETTINGS_OFFSET + i] != value);
+ }
+ lpcMemMap[0] = 0xF0;
+
+ setBank(XENIUM_BANK_BOOTLOADER);
+
+ setLedColor(settingsManager::getLedColor());
+}
+
+#endif
+
+utils::dataContainer* modchipXenium::getInstallerLogo()
+{
+ setBank(XENIUM_INSTALLER_LOGO_BANK);
+
+ setLedColor(LED_COLOR_WHITE);
+
+ utils::dataContainer* installerLogo = new utils::dataContainer(32768);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+ memcpy(installerLogo->data, (void*)&lpcMemMap[XENIUM_INSTALLER_LOGO_OFFSET], installerLogo->size);
+
+ setBank(XENIUM_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+ return installerLogo;
+}
+
+displayDriver* modchipXenium::getDisplayDriver(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ uint8_t lcdModel = settingsManager::getLcdModel(current);
+ if (lcdMode == 1)
+ {
+ if (lcdModel == 0)
+ {
+ return displayFactory::getDisplay(displayVariantSPI2PARXenium);
+ }
+ }
+ if (lcdMode == 2)
+ {
+ if (lcdModel == 0)
+ {
+ return displayFactory::getDisplay(displayVariantHD44780LPC);
+ }
+ if (lcdModel == 1)
+ {
+ return displayFactory::getDisplay(displayVariantLCDXXXXLPC);
+ }
+ }
+ return NULL;
+}
+
+supportInfo modchipXenium::getSupportInfo(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ supportInfo info;
+ info.supportsLed = true;
+ info.supportsLcd = true;
+
+ bool lcdInfo = false;
+ bool backlight = false;
+ bool contrast = false;
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver != NULL)
+ {
+ driver->getSupport(lcdInfo, backlight, contrast);
+ }
+ info.supportsLcdInfo = lcdInfo;
+ info.supportsLcdBacklight = backlight;
+ info.supportsLcdContrast = contrast;
+
+ info.supportsRecovery = false;
+ return info;
+}
+
+uint8_t modchipXenium::getLcdModeCount()
+{
+ return 2;
+}
+
+char* modchipXenium::getLcdModeString(uint8_t lcdMode)
+{
+ if (lcdMode == 1)
+ {
+ return strdup("SPI2PAR");
+ }
+ return strdup("Disabled");
+}
+
+uint8_t modchipXenium::getLcdModelCount(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ if (lcdMode == 1)
+ {
+ return 1;
+ }
+ if (lcdMode == 2)
+ {
+ return 2;
+ }
+ return 0;
+}
+
+char* modchipXenium::getLcdModelString(bool current, uint8_t lcdModel)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return strdup("");
+ }
+ return driver->getModel();
+}
+
+uint8_t modchipXenium::getLcdAddressCount(bool current)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return 0;
+ }
+ return driver->getI2cAddressCount();
+}
+
+char* modchipXenium::getLcdAddressString(bool current, uint8_t lcdAddress)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return strdup("");
+ }
+ uint8_t address = driver->getI2cAddress(lcdAddress);
+ char* result = stringUtility::formatString("0x%2X", address);
+ return result;
+}
+
+void modchipXenium::lcdSetCursorPosition(uint8_t row, uint8_t col)
+{
+ if (row > 3)
+ {
+ row = 3;
+ }
+ if (col > 19)
+ {
+ col = 19;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ EnterCriticalSection(&mMutex);
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setCursorPosition(row, col);
+ LeaveCriticalSection(&mMutex);
+}
+
+void modchipXenium::lcdInit()
+{
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ EnterCriticalSection(&mMutex);
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->init();
+ LeaveCriticalSection(&mMutex);
+}
+
+void modchipXenium::lcdPrintMessage(const char* message)
+{
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ EnterCriticalSection(&mMutex);
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->printMessage(message);
+ LeaveCriticalSection(&mMutex);
+}
+
+void modchipXenium::lcdSetBacklight(uint8_t value)
+{
+ if (value > 100)
+ {
+ value = 100;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ EnterCriticalSection(&mMutex);
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setBacklight(value);
+ LeaveCriticalSection(&mMutex);
+}
+
+void modchipXenium::lcdSetContrast(uint8_t value)
+{
+ if (value > 100)
+ {
+ value = 100;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ EnterCriticalSection(&mMutex);
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setContrast(value);
+ LeaveCriticalSection(&mMutex);
+}
+
+// Private
+
+void modchipXenium::setBank(uint8_t bank)
+{
+ EnterCriticalSection(&mMutex);
+ displaySPI2PARXenium::getInstance()->setBankValue(bank);
+ uint8_t spi = displaySPI2PARXenium::getInstance()->getSpiValue();
+ outputByte(XENIUM_REGISTER_BANKING, (spi | bank));
+ LeaveCriticalSection(&mMutex);
+}
+
+uint8_t modchipXenium::getBank()
+{
+ EnterCriticalSection(&mMutex);
+ uint8_t bank = (inputByte(XENIUM_REGISTER_BANKING) & 0x0f);
+ displaySPI2PARXenium::getInstance()->setBankValue(bank);
+ LeaveCriticalSection(&mMutex);
+ return bank;
+}
+
+bool modchipXenium::isEraseMemOffset(uint32_t memOffset)
+{
+ if (memOffset >= 0x000000 && memOffset <= 0x1effff)
+ {
+ return (memOffset % 65536) == 0;
+ }
+ if (memOffset >= 0x1f0000 && memOffset <= 0x1f7fff)
+ {
+ return (memOffset % 32768) == 0;
+ }
+ if (memOffset >= 0x1f8000 && memOffset <= 0x1fbfff)
+ {
+ return (memOffset % 8192) == 0;
+ }
+ if (memOffset >= 0x1fc000 && memOffset <= 0x1fffff)
+ {
+ return (memOffset % 16384) == 0;
+ }
+ return false;
+}
+
+bool modchipXenium::isProtectedMemOffset(uint32_t memOffset)
+{
+ if (memOffset >= 0x1c0000 && memOffset <= 0x1dffff)
+ {
+ return true;
+ }
+ return false;
+}
+
+void modchipXenium::sectorErase(uint32_t offset)
+{
+ if (isProtectedMemOffset(offset))
+ {
+ return;
+ }
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+ lpcMemMap[0xAAAA] = 0xAA;
+ lpcMemMap[0x5555] = 0x55;
+ lpcMemMap[0xAAAA] = 0x80;
+ lpcMemMap[0xAAAA] = 0xAA;
+ lpcMemMap[0x5555] = 0x55;
+ lpcMemMap[offset] = 0x30;
+ while(lpcMemMap[0] != lpcMemMap[0]);
+ lpcMemMap[0] = 0xF0;
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXenium.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXenium.h
new file mode 100644
index 0000000..9fcc457
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXenium.h
@@ -0,0 +1,73 @@
+#pragma once
+
+#include "modchip.h"
+#include "xboxInternals.h"
+
+#ifndef TOOLS
+#include "settingsManager.h"
+#endif
+
+class modchipXenium : public modchip
+{
+public:
+
+ modchipXenium();
+ void setLedColor(uint8_t ledColor);
+
+ uint32_t getSlotCount();
+ uint32_t getFlashSize(bool recovery);
+ void disableRecovery();
+ bool isValidBankSize(uint32_t size);
+ bool isValidFlashSize(bool recovery, uint32_t size);
+ uint32_t getBankSize(uint8_t bank);
+ uint32_t getBankMemOffset(uint8_t bank);
+ uint32_t getBankStartOffset(uint8_t bank);
+ uint8_t getBankFromIdAndSlots(uint8_t id, uint8_t slots);
+ utils::dataContainer* readBank(uint8_t bank);
+ void eraseBank(uint8_t bank);
+ void writeBank(uint8_t bank, utils::dataContainer* dataContainer);
+ bool verifyBank(uint8_t bank, utils::dataContainer* dataContainer);
+
+ uint8_t getFlashBankCount(bool recovery);
+ uint8_t getFlashBank(bool recovery, uint8_t bank);
+ bankType getFlashBankType(bool recovery, uint8_t bank);
+ utils::dataContainer* readFlash(bool recovery);
+
+ void launchBank(uint8_t bank, uint8_t ledColor);
+ void launchTsop();
+ void launchRecovery();
+
+#ifndef TOOLS
+ void loadSettings(settingsState& settings);
+ void saveSettings(settingsState& settings);
+#endif
+
+ utils::dataContainer* getInstallerLogo();
+
+ displayDriver* getDisplayDriver(bool current);
+ supportInfo getSupportInfo(bool current);
+ uint8_t getLcdModeCount();
+ char* getLcdModeString(uint8_t lcdMode);
+ uint8_t getLcdModelCount(bool current);
+ char* getLcdModelString(bool current, uint8_t lcdModel);
+ uint8_t getLcdAddressCount(bool current);
+ char* getLcdAddressString(bool current, uint8_t lcdAddress);
+
+ void lcdSetCursorPosition(uint8_t row, uint8_t col);
+ void lcdInit();
+ void lcdPrintMessage(const char* message);
+ void lcdSetBacklight(uint8_t value);
+ void lcdSetContrast(uint8_t value);
+
+private:
+
+ void setBank(uint8_t bank);
+ uint8_t getBank();
+ bool isEraseMemOffset(uint32_t memOffset);
+ bool isProtectedMemOffset(uint32_t memOffset);
+ void sectorErase(uint32_t offset);
+
+private:
+
+ CRITICAL_SECTION mMutex;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXtremium.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXtremium.cpp
new file mode 100644
index 0000000..8a2ef7b
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXtremium.cpp
@@ -0,0 +1,713 @@
+#include "modchipXtremium.h"
+#include "crc32.h"
+#include "settingsManager.h"
+#include "globalDefines.h"
+#include "stringUtility.h"
+
+//Bank1_256k = 3 0x000000 - 0x03ffff Sector Size 65536 Total 262144
+//Bank2_256k = 4 0x040000 - 0x07ffff Sector Size 65536 Total 262144
+//Bank3_256k = 5 0x080000 - 0x0bffff Sector Size 65536 Total 262144
+//Bank4_256k = 6 0x0c0000 - 0x0fffff Sector Size 65536 Total 262144
+//Bank1_512k = 7 0x000000 - 0x07ffff Sector Size 65536 Total 524288
+//Bank2_512k = 8 0x080000 - 0x0fffff Sector Size 65536 Total 524288
+//Bank1_1024k = 9 0x000000 - 0x0fffff Sector Size 65536 Total 1048576
+//Bank_PrometheOS = 2 0x100000 - 0x17ffff Sector Size 65536 Total 524288
+//Bank_Bootloader = 1 0x180000 - 0x1bffff Sector Size 65536 Total 262144
+//Bank_Recovery = 10 0x1c0000 - 0x1fffff See Below Total 262144
+
+//0x1c0000 - 0x1effff Sector Size 65536
+//0x1f0000 - 0x1f7fff Sector Size 32768
+//0x1f8000 - 0x1fbfff Sector Size 8192
+//0x1fc000 - 0x1fffff Sector Size 16384
+
+//0x1c0000 - 0x1dffff Total 131072 (Protected - Installer Logo (IOpen Xtremium))
+//0x1e0000 - 0x1f7fff Total 98304 (PrometheOS Continued)
+//0x1f8000 - 0x1f9fff Total 8192 (Protected)
+//0x1fa000 - 0x1fbfff Total 8192 (Settings)
+//0x1fc000 - 0x1fffff Total 16384 (Spare)
+
+
+
+modchipXtremium::modchipXtremium()
+{
+ InitializeCriticalSection(&mMutex);
+ uint8_t bank = XTREMIUM_BANK_BOOTLOADER;
+ displaySPI2PARXtremium::getInstance()->setBankValue(bank);
+ uint8_t spi = inputByte(XTREMIUM_REGISTER_BANKING) & 0x70;
+ displaySPI2PARXtremium::getInstance()->setSpiValue(spi);
+}
+
+void modchipXtremium::setLedColor(uint8_t ledColor)
+{
+ outputByte(XTREMIUM_REGISTER_LED, ledColor);
+}
+
+uint32_t modchipXtremium::getSlotCount()
+{
+ return 4;
+}
+
+uint32_t modchipXtremium::getFlashSize(bool recovery)
+{
+ return recovery ? 0 : (2 * 1024 * 1024);
+}
+
+void modchipXtremium::disableRecovery()
+{
+}
+
+bool modchipXtremium::isValidBankSize(uint32_t size)
+{
+ return size == (256 * 1024) || size == (512 * 1024) || size == (1024 * 1024);
+}
+
+bool modchipXtremium::isValidFlashSize(bool recovery, uint32_t size)
+{
+ return size == getFlashSize(recovery);
+}
+
+uint32_t modchipXtremium::getBankSize(uint8_t bank)
+{
+ if (bank == XTREMIUM_BANK_BOOTLOADER)
+ {
+ return 256 * 1024;
+ }
+ if (bank == XTREMIUM_BANK_PROMETHEOS1)
+ {
+ return 512 * 1024;
+ }
+ if (bank == XTREMIUM_BANK_PROMETHEOS2)
+ {
+ return 256 * 1024;
+ }
+ if (bank == XTREMIUM_BANK_SLOT1_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == XTREMIUM_BANK_SLOT2_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == XTREMIUM_BANK_SLOT3_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == XTREMIUM_BANK_SLOT4_256K)
+ {
+ return 256 * 1024;
+ }
+ if (bank == XTREMIUM_BANK_SLOT1_512K)
+ {
+ return 512 * 1024;
+ }
+ if (bank == XTREMIUM_BANK_SLOT2_512K)
+ {
+ return 512 * 1024;
+ }
+ if (bank == XTREMIUM_BANK_SLOT1_1024K)
+ {
+ return 1024 * 1024;
+ }
+ return 0;
+}
+
+uint32_t modchipXtremium::getBankMemOffset(uint8_t bank)
+{
+ if (bank == XTREMIUM_BANK_SLOT1_256K)
+ {
+ return 0x000000;
+ }
+ if (bank == XTREMIUM_BANK_SLOT2_256K)
+ {
+ return 0x040000;
+ }
+ if (bank == XTREMIUM_BANK_SLOT2_256K)
+ {
+ return 0x080000;
+ }
+ if (bank == XTREMIUM_BANK_SLOT4_256K)
+ {
+ return 0x0c0000;
+ }
+ if (bank == XTREMIUM_BANK_SLOT1_512K)
+ {
+ return 0x000000;
+ }
+ if (bank == XTREMIUM_BANK_SLOT2_512K)
+ {
+ return 0x080000;
+ }
+ if (bank == XTREMIUM_BANK_SLOT1_1024K)
+ {
+ return 0x000000;
+ }
+ if (bank == XTREMIUM_BANK_BOOTLOADER)
+ {
+ return 0x180000;
+ }
+ if (bank == XTREMIUM_BANK_PROMETHEOS1)
+ {
+ return 0x100000;
+ }
+ if (bank == XTREMIUM_BANK_PROMETHEOS2)
+ {
+ return 0x1c0000;
+ }
+ return 0;
+}
+
+uint32_t modchipXtremium::getBankStartOffset(uint8_t bank)
+{
+ return 0;
+}
+
+uint8_t modchipXtremium::getBankFromIdAndSlots(uint8_t id, uint8_t slots)
+{
+ if (id == 0 && slots == 1)
+ {
+ return XTREMIUM_BANK_SLOT1_256K;
+ }
+ if (id == 1 && slots == 1)
+ {
+ return XTREMIUM_BANK_SLOT2_256K;
+ }
+ if (id == 2 && slots == 1)
+ {
+ return XTREMIUM_BANK_SLOT3_256K;
+ }
+ if (id == 3 && slots == 1)
+ {
+ return XTREMIUM_BANK_SLOT4_256K;
+ }
+ if (id == 0 && slots == 2)
+ {
+ return XTREMIUM_BANK_SLOT1_512K;
+ }
+ if (id == 2 && slots == 2)
+ {
+ return XTREMIUM_BANK_SLOT2_512K;
+ }
+ if (id == 0 && slots == 4)
+ {
+ return XTREMIUM_BANK_SLOT1_1024K;
+ }
+ return 0;
+}
+
+utils::dataContainer* modchipXtremium::readBank(uint8_t bank)
+{
+ setBank(bank);
+ uint32_t bankSize = getBankSize(bank);
+ utils::dataContainer* dataContainer = new utils::dataContainer(bankSize);
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)(LPC_MEMORY_BASE + getBankStartOffset(bank));
+ memcpy(dataContainer->data, (void*)&lpcMemMap[0], bankSize);
+ setBank(XTREMIUM_BANK_BOOTLOADER);
+ return dataContainer;
+}
+
+void modchipXtremium::eraseBank(uint8_t bank)
+{
+ setBank(bank);
+
+ setLedColor(LED_COLOR_AMBER);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ uint32_t memOffset = getBankMemOffset(bank);
+ uint32_t startOffset = getBankStartOffset(bank);
+ uint32_t bankSize = getBankSize(bank);
+
+ uint32_t offset = 0;
+ while (offset < bankSize)
+ {
+ if (isEraseMemOffset(memOffset + startOffset + offset))
+ {
+ sectorErase(offset);
+ }
+ offset += 8192;
+ }
+
+ setBank(XTREMIUM_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+}
+
+void modchipXtremium::writeBank(uint8_t bank, utils::dataContainer* dataContainer)
+{
+ setBank(bank);
+
+ setLedColor(LED_COLOR_BLUE);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)(LPC_MEMORY_BASE + getBankStartOffset(bank));
+
+ uint32_t memOffset = getBankMemOffset(bank);
+
+ for (uint32_t i = 0; i < dataContainer->size; i++)
+ {
+ if (isProtectedMemOffset(memOffset + i) == true)
+ {
+ continue;
+ }
+ uint8_t value = (uint8_t)dataContainer->data[i];
+ lpcMemMap[0xAAAA] = 0xAA;
+ lpcMemMap[0x5555] = 0x55;
+ lpcMemMap[0xAAAA] = 0xA0;
+ lpcMemMap[i] = value;
+ while (lpcMemMap[i] != value);
+ }
+ lpcMemMap[0] = 0xf0;
+
+ setBank(XTREMIUM_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+}
+
+bool modchipXtremium::verifyBank(uint8_t bank, utils::dataContainer* dataContainer)
+{
+ setBank(bank);
+
+ utils::dataContainer* writtenData = readBank(bank);
+
+ setLedColor(LED_COLOR_PURPLE);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ uint32_t memOffset = getBankMemOffset(bank);
+
+ bool ok = true;
+ for (uint32_t i = 0; i < dataContainer->size; i++)
+ {
+ if (isProtectedMemOffset(memOffset + i) == true)
+ {
+ continue;
+ }
+ if (writtenData->data[i] == dataContainer->data[i])
+ {
+ continue;
+ }
+ ok = false;
+ break;
+ }
+
+ delete(writtenData);
+
+ setBank(XTREMIUM_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+ return ok;
+}
+
+uint8_t modchipXtremium::getFlashBankCount(bool recovery)
+{
+ return recovery ? 0 : 7;
+}
+
+uint8_t modchipXtremium::getFlashBank(bool recovery, uint8_t bank)
+{
+ const uint8_t banks[] = {
+ XTREMIUM_BANK_SLOT1_256K,
+ XTREMIUM_BANK_SLOT2_256K,
+ XTREMIUM_BANK_SLOT3_256K,
+ XTREMIUM_BANK_SLOT4_256K,
+ XTREMIUM_BANK_BOOTLOADER,
+ XTREMIUM_BANK_PROMETHEOS1,
+ XTREMIUM_BANK_PROMETHEOS2,
+ };
+ return recovery ? 0 : banks[bank];
+}
+
+bankType modchipXtremium::getFlashBankType(bool recovery, uint8_t bank)
+{
+ const bankType banks[] = {
+ bankTypeUser,
+ bankTypeUser,
+ bankTypeUser,
+ bankTypeUser,
+ bankTypeSystem,
+ bankTypeSystem,
+ bankTypeSystem,
+ };
+ return recovery ? bankTypeUser : banks[bank];
+}
+
+utils::dataContainer* modchipXtremium::readFlash(bool recovery)
+{
+ utils::dataContainer* result = new utils::dataContainer(getFlashSize(recovery));
+ for (uint8_t i = 0; i < getFlashBankCount(recovery); i++)
+ {
+ uint8_t bank = getFlashBank(recovery, i);
+ uint32_t memOffset = getBankMemOffset(bank);
+ utils::dataContainer* bankData = readBank(bank);
+ memcpy(result->data + memOffset, bankData->data, bankData->size);
+ delete(bankData);
+ }
+ return result;
+}
+
+void modchipXtremium::launchBank(uint8_t bank, uint8_t ledColor)
+{
+ DWORD scratch;
+ HalReadSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, &scratch);
+ HalWriteSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, scratch & ~SCRATCH_REGISTER_BITVALUE_NO_ANIMATION);
+ setBank(bank);
+ setLedColor(ledColor);
+ HalReturnToFirmware(RETURN_FIRMWARE_REBOOT);
+}
+
+void modchipXtremium::launchTsop()
+{
+ DWORD scratch;
+ HalReadSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, &scratch);
+ HalWriteSMBusByte(SMBDEV_PIC16L, PIC16L_CMD_SCRATCH_REGISTER, scratch & ~SCRATCH_REGISTER_BITVALUE_NO_ANIMATION);
+ setBank(XTREMIUM_BANK_TSOP);
+ setLedColor(LED_COLOR_OFF);
+ HalReturnToFirmware(RETURN_FIRMWARE_REBOOT);
+}
+
+void modchipXtremium::launchRecovery()
+{
+}
+
+#ifndef TOOLS
+
+void modchipXtremium::loadSettings(settingsState& settings)
+{
+ setBank(XTREMIUM_SETTINGS_BANK);
+
+ setLedColor(LED_COLOR_WHITE);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ memcpy(&settings, (void*)&lpcMemMap[XTREMIUM_SETTINGS_OFFSET], sizeof(settings));
+ uint32_t checksum = crc32::calculate(((uint8_t*)&settings) + sizeof(uint32_t), sizeof(settings) - sizeof(uint32_t));
+
+ setBank(XTREMIUM_BANK_BOOTLOADER);
+
+ if (checksum != settings.checksum || versioning::compareVersion(settings.version, settingsManager::getVersion()) != 0)
+ {
+ settingsManager::initSettings();
+ settingsManager::saveSettings();
+ }
+
+ setLedColor(settingsManager::getLedColor());
+}
+
+void modchipXtremium::saveSettings(settingsState& settings)
+{
+ setBank(XTREMIUM_SETTINGS_BANK);
+
+ settings.checksum = crc32::calculate(((uint8_t*)&settings) + sizeof(uint32_t), sizeof(settings) - sizeof(uint32_t));
+ utils::dataContainer* settingsData = new utils::dataContainer((char*)&settings, sizeof(settings), sizeof(settings));
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+
+ setLedColor(LED_COLOR_AMBER);
+ sectorErase(XTREMIUM_SETTINGS_OFFSET);
+
+ setLedColor(LED_COLOR_BLUE);
+ for (uint32_t i = 0; i < settingsData->size; i++)
+ {
+ uint8_t value = (uint8_t)settingsData->data[i];
+ lpcMemMap[0xAAAA] = 0xAA;
+ lpcMemMap[0x5555] = 0x55;
+ lpcMemMap[0xAAAA] = 0xA0;
+ lpcMemMap[XTREMIUM_SETTINGS_OFFSET + i] = value;
+ while (lpcMemMap[XTREMIUM_SETTINGS_OFFSET + i] != value);
+ }
+ lpcMemMap[0] = 0xF0;
+
+ setBank(XTREMIUM_BANK_BOOTLOADER);
+
+ setLedColor(settingsManager::getLedColor());
+}
+
+#endif
+
+utils::dataContainer* modchipXtremium::getInstallerLogo()
+{
+ setBank(XTREMIUM_INSTALLER_LOGO_BANK);
+
+ setLedColor(LED_COLOR_WHITE);
+
+ utils::dataContainer* installerLogo = new utils::dataContainer(32768);
+
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+ memcpy(installerLogo->data, (void*)&lpcMemMap[XTREMIUM_INSTALLER_LOGO_OFFSET], installerLogo->size);
+
+ setBank(XTREMIUM_BANK_BOOTLOADER);
+
+#ifndef TOOLS
+ setLedColor(settingsManager::getLedColor());
+#else
+ setLedColor(LED_COLOR_GREEN);
+#endif
+ return installerLogo;
+}
+
+displayDriver* modchipXtremium::getDisplayDriver(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ uint8_t lcdModel = settingsManager::getLcdModel(current);
+ if (lcdMode == 1)
+ {
+ if (lcdModel == 0)
+ {
+ return displayFactory::getDisplay(displayVariantSPI2PARXtremium);
+ }
+ }
+ if (lcdMode == 2)
+ {
+ if (lcdModel == 0)
+ {
+ return displayFactory::getDisplay(displayVariantHD44780LPC);
+ }
+ if (lcdModel == 1)
+ {
+ return displayFactory::getDisplay(displayVariantLCDXXXXLPC);
+ }
+ }
+ return NULL;
+}
+
+supportInfo modchipXtremium::getSupportInfo(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ supportInfo info;
+ info.supportsLed = true;
+ info.supportsLcd = true;
+
+ bool lcdInfo = false;
+ bool backlight = false;
+ bool contrast = false;
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver != NULL)
+ {
+ driver->getSupport(lcdInfo, backlight, contrast);
+ }
+ info.supportsLcdInfo = lcdInfo;
+ info.supportsLcdBacklight = backlight;
+ info.supportsLcdContrast = contrast;
+
+ info.supportsRecovery = false;
+ return info;
+}
+
+uint8_t modchipXtremium::getLcdModeCount()
+{
+ return 2;
+}
+
+char* modchipXtremium::getLcdModeString(uint8_t lcdMode)
+{
+ if (lcdMode == 1)
+ {
+ return strdup("SPI2PAR");
+ }
+ return strdup("Disabled");
+}
+
+uint8_t modchipXtremium::getLcdModelCount(bool current)
+{
+ uint8_t lcdMode = settingsManager::getLcdMode(current);
+ if (lcdMode == 1)
+ {
+ return 1;
+ }
+ if (lcdMode == 2)
+ {
+ return 2;
+ }
+ return 0;
+}
+
+char* modchipXtremium::getLcdModelString(bool current, uint8_t lcdModel)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return strdup("");
+ }
+ return driver->getModel();
+}
+
+uint8_t modchipXtremium::getLcdAddressCount(bool current)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return 0;
+ }
+ return driver->getI2cAddressCount();
+}
+
+char* modchipXtremium::getLcdAddressString(bool current, uint8_t lcdAddress)
+{
+ displayDriver* driver = getDisplayDriver(current);
+ if (driver == NULL)
+ {
+ return strdup("");
+ }
+ uint8_t address = driver->getI2cAddress(lcdAddress);
+ char* result = stringUtility::formatString("0x%2X", address);
+ return result;
+}
+
+void modchipXtremium::lcdSetCursorPosition(uint8_t row, uint8_t col)
+{
+ if (row > 3)
+ {
+ row = 3;
+ }
+ if (col > 19)
+ {
+ col = 19;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ EnterCriticalSection(&mMutex);
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setCursorPosition(row, col);
+ LeaveCriticalSection(&mMutex);
+}
+
+void modchipXtremium::lcdInit()
+{
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ EnterCriticalSection(&mMutex);
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->init();
+ LeaveCriticalSection(&mMutex);
+}
+
+void modchipXtremium::lcdPrintMessage(const char* message)
+{
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ EnterCriticalSection(&mMutex);
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->printMessage(message);
+ LeaveCriticalSection(&mMutex);
+}
+
+void modchipXtremium::lcdSetBacklight(uint8_t value)
+{
+ if (value > 100)
+ {
+ value = 100;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ EnterCriticalSection(&mMutex);
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setBacklight(value);
+ LeaveCriticalSection(&mMutex);
+}
+
+void modchipXtremium::lcdSetContrast(uint8_t value)
+{
+ if (value > 100)
+ {
+ value = 100;
+ }
+ displayDriver* driver = getDisplayDriver(true);
+ if (driver == NULL)
+ {
+ return;
+ }
+ EnterCriticalSection(&mMutex);
+ driver->setAddress(settingsManager::getLcdAddress(true));
+ driver->setContrast(value);
+ LeaveCriticalSection(&mMutex);
+}
+
+// Private
+
+void modchipXtremium::setBank(uint8_t bank)
+{
+ EnterCriticalSection(&mMutex);
+ displaySPI2PARXtremium::getInstance()->setBankValue(bank);
+ uint8_t spi = displaySPI2PARXtremium::getInstance()->getSpiValue();
+ outputByte(XTREMIUM_REGISTER_BANKING, (spi | bank));
+ LeaveCriticalSection(&mMutex);
+}
+
+uint8_t modchipXtremium::getBank()
+{
+ EnterCriticalSection(&mMutex);
+ uint8_t bank = (inputByte(XTREMIUM_REGISTER_BANKING) & 0x0f);
+ displaySPI2PARXtremium::getInstance()->setBankValue(bank);
+ LeaveCriticalSection(&mMutex);
+ return bank;
+}
+
+bool modchipXtremium::isEraseMemOffset(uint32_t memOffset)
+{
+ if (memOffset >= 0x000000 && memOffset <= 0x1effff)
+ {
+ return (memOffset % 65536) == 0;
+ }
+ if (memOffset >= 0x1f0000 && memOffset <= 0x1f7fff)
+ {
+ return (memOffset % 32768) == 0;
+ }
+ if (memOffset >= 0x1f8000 && memOffset <= 0x1fbfff)
+ {
+ return (memOffset % 8192) == 0;
+ }
+ if (memOffset >= 0x1fc000 && memOffset <= 0x1fffff)
+ {
+ return (memOffset % 16384) == 0;
+ }
+ return false;
+}
+
+bool modchipXtremium::isProtectedMemOffset(uint32_t memOffset)
+{
+ if (memOffset >= 0x1c0000 && memOffset <= 0x1dffff)
+ {
+ return true;
+ }
+ return false;
+}
+
+void modchipXtremium::sectorErase(uint32_t offset)
+{
+ if (isProtectedMemOffset(offset))
+ {
+ return;
+ }
+ volatile uint8_t* lpcMemMap = (volatile uint8_t *)LPC_MEMORY_BASE;
+ lpcMemMap[0xAAAA] = 0xAA;
+ lpcMemMap[0x5555] = 0x55;
+ lpcMemMap[0xAAAA] = 0x80;
+ lpcMemMap[0xAAAA] = 0xAA;
+ lpcMemMap[0x5555] = 0x55;
+ lpcMemMap[offset] = 0x30;
+ while(lpcMemMap[0] != lpcMemMap[0]);
+ lpcMemMap[0] = 0xF0;
+}
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXtremium.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXtremium.h
new file mode 100644
index 0000000..48b1c25
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/modchipXtremium.h
@@ -0,0 +1,73 @@
+#pragma once
+
+#include "modchip.h"
+#include "xboxInternals.h"
+
+#ifndef TOOLS
+#include "settingsManager.h"
+#endif
+
+class modchipXtremium : public modchip
+{
+public:
+
+ modchipXtremium();
+ void setLedColor(uint8_t ledColor);
+
+ uint32_t getSlotCount();
+ uint32_t getFlashSize(bool recovery);
+ void disableRecovery();
+ bool isValidBankSize(uint32_t size);
+ bool isValidFlashSize(bool recovery, uint32_t size);
+ uint32_t getBankSize(uint8_t bank);
+ uint32_t getBankMemOffset(uint8_t bank);
+ uint32_t getBankStartOffset(uint8_t bank);
+ uint8_t getBankFromIdAndSlots(uint8_t id, uint8_t slots);
+ utils::dataContainer* readBank(uint8_t bank);
+ void eraseBank(uint8_t bank);
+ void writeBank(uint8_t bank, utils::dataContainer* dataContainer);
+ bool verifyBank(uint8_t bank, utils::dataContainer* dataContainer);
+
+ uint8_t getFlashBankCount(bool recovery);
+ uint8_t getFlashBank(bool recovery, uint8_t bank);
+ bankType getFlashBankType(bool recovery, uint8_t bank);
+ utils::dataContainer* readFlash(bool recovery);
+
+ void launchBank(uint8_t bank, uint8_t ledColor);
+ void launchTsop();
+ void launchRecovery();
+
+#ifndef TOOLS
+ void loadSettings(settingsState& settings);
+ void saveSettings(settingsState& settings);
+#endif
+
+ utils::dataContainer* getInstallerLogo();
+
+ displayDriver* getDisplayDriver(bool current);
+ supportInfo getSupportInfo(bool current);
+ uint8_t getLcdModeCount();
+ char* getLcdModeString(uint8_t lcdMode);
+ uint8_t getLcdModelCount(bool current);
+ char* getLcdModelString(bool current, uint8_t lcdModel);
+ uint8_t getLcdAddressCount(bool current);
+ char* getLcdAddressString(bool current, uint8_t lcdAddress);
+
+ void lcdSetCursorPosition(uint8_t row, uint8_t col);
+ void lcdInit();
+ void lcdPrintMessage(const char* message);
+ void lcdSetBacklight(uint8_t value);
+ void lcdSetContrast(uint8_t value);
+
+private:
+
+ void setBank(uint8_t bank);
+ uint8_t getBank();
+ bool isEraseMemOffset(uint32_t memOffset);
+ bool isProtectedMemOffset(uint32_t memOffset);
+ void sectorErase(uint32_t offset);
+
+private:
+
+ CRITICAL_SECTION mMutex;
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/network.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/network.cpp
new file mode 100644
index 0000000..abbd81f
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/network.cpp
@@ -0,0 +1,170 @@
+#include "network.h"
+#include "context.h"
+#include "socketUtility.h"
+#include "ftpServer.h"
+#include "httpServer.h"
+#include "settingsManager.h"
+#include "xboxInternals.h"
+
+void network::init()
+{
+ if ((XNetGetEthernetLinkStatus() & XNET_ETHERNET_LINK_ACTIVE) > 0 && context::getNetworkInitialized() == false)
+ {
+ configure();
+
+ XNetStartupParams xnsp;
+ memset(&xnsp, 0, sizeof(xnsp));
+ xnsp.cfgSizeOfStruct = sizeof(XNetStartupParams);
+ xnsp.cfgFlags = XNET_STARTUP_BYPASS_SECURITY;
+
+ xnsp.cfgPrivatePoolSizeInPages = 64;
+ xnsp.cfgEnetReceiveQueueLength = 16;
+ xnsp.cfgIpFragMaxSimultaneous = 16;
+ xnsp.cfgIpFragMaxPacketDiv256 = 32;
+ xnsp.cfgSockMaxSockets = 64;
+
+ xnsp.cfgSockDefaultRecvBufsizeInK = RECV_SOCKET_BUFFER_SIZE_IN_K;
+ xnsp.cfgSockDefaultSendBufsizeInK = SEND_SOCKET_BUFFER_SIZE_IN_K;
+
+ XNetStartup(&xnsp);
+
+ WSADATA wsaData;
+ const int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
+ if (result != 0)
+ {
+ utils::debugPrint("Error: Socket startup failed: %i", result);
+ }
+
+ ftpServer::init();
+
+#ifndef TOOLS
+ httpServer::init();
+#endif
+
+ context::setNetworkInitialized(true);
+ }
+}
+
+void network::configure()
+{
+ XNetConfigParams netConfigParams;
+ XNetLoadConfigParams(&netConfigParams);
+ bool isXboxVersion2 = netConfigParams.V2_Tag == 0x58425632;
+ bool isDirty = false;
+
+ uint32_t flag = settingsManager::getNetworkMode() == networkModeStatic ? XDK_NETWORK_CONFIG_MANUAL_IP : 0;
+
+ uint32_t ipAddress = settingsManager::getNetworkMode() == networkModeStatic ? settingsManager::getNetworkAddress() : 0;
+ uint32_t* ip = isXboxVersion2 ? &netConfigParams.V2_IP : &netConfigParams.V1_IP;
+ if (*ip != ipAddress)
+ {
+ *ip = ipAddress;
+ isDirty = true;
+ }
+
+ uint32_t* subnet = isXboxVersion2 ? &netConfigParams.V2_Subnetmask : &netConfigParams.V1_Subnetmask;
+ if (*subnet != settingsManager::getNetworkSubnet())
+ {
+ *subnet = settingsManager::getNetworkSubnet();
+ isDirty = true;
+ }
+
+ uint32_t* gateway = isXboxVersion2 ? &netConfigParams.V2_Defaultgateway : &netConfigParams.V1_Defaultgateway;
+ if (*gateway != settingsManager::getNetworkGateway())
+ {
+ *gateway = settingsManager::getNetworkGateway();
+ isDirty = true;
+ }
+
+ if (settingsManager::getNetworkMode() == networkModeStatic || settingsManager::getNetworkMode() == networkModeDynamicManualDns)
+ {
+ uint32_t* primaryDns = isXboxVersion2 ? &netConfigParams.V2_DNS1 : &netConfigParams.V1_DNS1;
+ if (*primaryDns != settingsManager::getNetworkPrimaryDns())
+ {
+ *primaryDns = settingsManager::getNetworkPrimaryDns();
+ isDirty = true;
+ }
+
+ uint32_t* secondaryDns = isXboxVersion2 ? &netConfigParams.V2_DNS2 : &netConfigParams.V1_DNS2;
+ if (*secondaryDns != settingsManager::getNetworkSecondaryDns())
+ {
+ *secondaryDns = settingsManager::getNetworkSecondaryDns();
+ isDirty = true;
+ }
+
+ flag |= XDK_NETWORK_CONFIG_MANUAL_DNS;
+ }
+
+ if (netConfigParams.Flag != flag)
+ {
+ netConfigParams.Flag = flag;
+ isDirty = true;
+ }
+
+ if (isDirty)
+ {
+ XNetSaveConfigParams(&netConfigParams);
+ }
+}
+
+void network::restart()
+{
+ context::setNetworkInitialized(false);
+ ftpServer::close();
+ httpServer::close();
+ WSACleanup();
+ XNetCleanup();
+ init();
+}
+
+bool network::isReady()
+{
+ if (context::getNetworkInitialized() == false)
+ {
+ return false;
+ }
+ XNADDR addr;
+ memset(&addr, 0, sizeof(addr));
+ DWORD dwState = XNetGetTitleXnAddr(&addr);
+ return dwState != XNET_GET_XNADDR_PENDING;
+}
+
+uint32_t network::getAddress()
+{
+ XNetConfigStatus status;
+ memset(&status, 0, sizeof(status));
+ XNetGetConfigStatus(&status);
+ return status.ina.S_un.S_addr;
+}
+
+uint32_t network::getSubnet()
+{
+ XNetConfigStatus status;
+ memset(&status, 0, sizeof(status));
+ XNetGetConfigStatus(&status);
+ return status.inaMask.S_un.S_addr;
+}
+
+uint32_t network::getGateway()
+{
+ XNetConfigStatus status;
+ memset(&status, 0, sizeof(status));
+ XNetGetConfigStatus(&status);
+ return status.inaGateway.S_un.S_addr;
+}
+
+uint32_t network::getPrimaryDns()
+{
+ XNetConfigStatus status;
+ memset(&status, 0, sizeof(status));
+ XNetGetConfigStatus(&status);
+ return status.inaDnsSecondary.S_un.S_addr;
+}
+
+uint32_t network::getSecondaryDns()
+{
+ XNetConfigStatus status;
+ memset(&status, 0, sizeof(status));
+ XNetGetConfigStatus(&status);
+ return status.inaDnsSecondary.S_un.S_addr;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/network.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/network.h
new file mode 100644
index 0000000..db3f6ef
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/network.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "xboxInternals.h"
+
+class network
+{
+public:
+ static void init();
+ static void restart();
+ static bool isReady();
+ static uint32_t getAddress();
+ static uint32_t getSubnet();
+ static uint32_t getGateway();
+ static uint32_t getPrimaryDns();
+ static uint32_t getSecondaryDns();
+private:
+ static void configure();
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/pointerMap.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/pointerMap.h
new file mode 100644
index 0000000..ee28319
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/pointerMap.h
@@ -0,0 +1,150 @@
+#pragma once
+
+#include "xboxinternals.h"
+#include "pointerVector.h"
+#include "stringUtility.h"
+#include
+
+#define MAP_SIZE_INCREMENT 100
+
+template
+class pointerMap
+{
+public:
+
+ pointerMap(bool useDelete)
+ {
+ mUseDelete = useDelete;
+ mSize = 0;
+ mKeyValuePairs = (keyValuePair*)malloc(sizeof(keyValuePair) * MAP_SIZE_INCREMENT);
+ if (mKeyValuePairs == NULL)
+ {
+ mMaxSize = 0;
+ return;
+ }
+ mMaxSize = MAP_SIZE_INCREMENT;
+ }
+
+ ~pointerMap()
+ {
+ for (uint32_t i = 0; i < mSize; i++)
+ {
+ free(mKeyValuePairs[i].key);
+ if (mUseDelete == true)
+ {
+ delete(mKeyValuePairs[i].value);
+ }
+ else
+ {
+ free(mKeyValuePairs[i].value);
+ }
+ }
+ free(mKeyValuePairs);
+ }
+
+ void add(const char* key, T1 value)
+ {
+ if (mSize == mMaxSize)
+ {
+ keyValuePair* reallocedKeyValuePairs = (keyValuePair*)realloc(mKeyValuePairs, sizeof(keyValuePair) * (mMaxSize + MAP_SIZE_INCREMENT));
+ if (reallocedKeyValuePairs == NULL)
+ {
+ return;
+ }
+ mMaxSize += MAP_SIZE_INCREMENT;
+ mKeyValuePairs = reallocedKeyValuePairs;
+ }
+
+ mKeyValuePairs[mSize].key = strdup(key);
+ mKeyValuePairs[mSize].value = value;
+ mSize++;
+ }
+
+ void add(uint32_t key, T1 value)
+ {
+ char* keyValue = stringUtility::formatString("%ui", key);
+ add(keyValue, value);
+ free(keyValue);
+ }
+
+ T1 get(const char* key)
+ {
+ for (uint32_t i = 0; i < mSize; i++)
+ {
+ if (stringUtility::equals(mKeyValuePairs[i].key, key, false) == true)
+ {
+ return mKeyValuePairs[i].value;
+ }
+ }
+ return NULL;
+ }
+
+ T1 get(uint32_t key)
+ {
+ char* keyValue = stringUtility::formatString("%ui", key);
+ T1 result = get(keyValue);
+ free(keyValue);
+ return result;
+ }
+
+ void removeKey(const char* key)
+ {
+ for (uint32_t i = 0; i < mSize; i++)
+ {
+ if (stringUtility::equals(mKeyValuePairs[i].key, key, false) == true)
+ {
+ free(mKeyValuePairs[i].key);
+ if (mUseDelete == true)
+ {
+ delete(mKeyValuePairs[i].value);
+ }
+ else
+ {
+ free(mKeyValuePairs[i].value);
+ }
+ for (uint32_t j = i; j < mSize - 1; j++)
+ {
+ mKeyValuePairs[j].key = mKeyValuePairs[j + 1].key;
+ mKeyValuePairs[j].value = mKeyValuePairs[j + 1].value;
+ }
+ mSize--;
+ }
+ }
+ }
+
+ void removeKey(uint32_t key)
+ {
+ char* keyValue = stringUtility::formatString("%ui", key);
+ removeKey(keyValue);
+ free(keyValue);
+ }
+
+ uint32_t count()
+ {
+ return mSize;
+ }
+
+ pointerVector* keys()
+ {
+ pointerVector* keys = new pointerVector(false);
+ for (uint32_t i = 0; i < mSize; i++)
+ {
+ keys->add(strdup(mKeyValuePairs[i].key));
+ }
+ return keys;
+ }
+
+private:
+
+ typedef struct keyValuePair {
+ char* key;
+ T1 value;
+ } keyValuePair;
+
+ keyValuePair* mKeyValuePairs;
+ bool mUseDelete;
+ uint32_t mSize;
+ uint32_t mMaxSize;
+};
+
+
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/pointerVector.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/pointerVector.h
new file mode 100644
index 0000000..6b8e8cd
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/pointerVector.h
@@ -0,0 +1,119 @@
+#pragma once
+
+#include "xboxinternals.h"
+
+#define VECTOR_SIZE_INCREMENT 100
+
+template
+class pointerVector
+{
+public:
+
+ pointerVector(bool useDelete)
+ {
+ mUseDelete = useDelete;
+ mSize = 0;
+ mValueContainers = (valueContainer*)malloc(sizeof(valueContainer) * VECTOR_SIZE_INCREMENT);
+ if (mValueContainers == NULL)
+ {
+ mMaxSize = 0;
+ return;
+ }
+ mMaxSize = VECTOR_SIZE_INCREMENT;
+ }
+
+ ~pointerVector()
+ {
+ for (uint32_t i = 0; i < mSize; i++)
+ {
+ if (mUseDelete == true)
+ {
+ delete(mValueContainers[i].value);
+ }
+ else
+ {
+ free(mValueContainers[i].value);
+ }
+ }
+ free(mValueContainers);
+ }
+
+ void add(T1 value)
+ {
+ if (mSize == mMaxSize)
+ {
+ valueContainer* reallocedValueContainers = (valueContainer*)realloc(mValueContainers, sizeof(valueContainer) * (mMaxSize + VECTOR_SIZE_INCREMENT));
+ if (reallocedValueContainers == NULL)
+ {
+ return;
+ }
+ mMaxSize += VECTOR_SIZE_INCREMENT;
+ mValueContainers = reallocedValueContainers;
+ }
+
+ mValueContainers[mSize].value = value;
+ mSize++;
+ }
+
+ T1 get(uint32_t index)
+ {
+ return mValueContainers[index].value;
+ }
+
+ void remove(uint32_t index)
+ {
+ if (mUseDelete == true)
+ {
+ delete(mValueContainers[index].value);
+ }
+ else
+ {
+ free(mValueContainers[index].value);
+ }
+ for (uint32_t j = index; j < mSize - 1; j++)
+ {
+ mValueContainers[j].value = mValueContainers[j + 1].value;
+ }
+ mSize--;
+ }
+
+ void swap(uint32_t index1, uint32_t index2)
+ {
+ T1 temp = mValueContainers[index1].value;
+ mValueContainers[index1].value = mValueContainers[index2].value;
+ mValueContainers[index2].value = temp;
+ }
+
+ uint32_t count()
+ {
+ return mSize;
+ }
+
+ void clear()
+ {
+ for (uint32_t i = 0; i < mSize; i++)
+ {
+ if (mUseDelete == true)
+ {
+ delete(mValueContainers[i].value);
+ }
+ else
+ {
+ free(mValueContainers[i].value);
+ }
+ }
+ mSize = 0;
+ }
+
+private:
+
+ typedef struct valueContainer {
+ T1 value;
+ } valueContainer;
+
+ valueContainer* mValueContainers;
+ bool mUseDelete;
+ uint32_t mSize;
+ uint32_t mMaxSize;
+};
+
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/resources.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/resources.h
new file mode 100644
index 0000000..9aee22a
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/resources.h
@@ -0,0 +1,25 @@
+#pragma once
+
+//https://notisrac.github.io/FileToCArray/
+
+#include "Assets/Font/freesans_sfn.h"
+
+#include "Assets/Web/cerbiosini_html.h"
+#include "Assets/Web/cerbiosini_js.h"
+#include "Assets/Web/pico_css.h"
+#include "Assets/Web/favicon_ico.h"
+#include "Assets/Web/main_css.h"
+#include "Assets/Web/flash_html.h"
+#include "Assets/Web/flash_js.h"
+#include "Assets/Web/index_html.h"
+#include "Assets/Web/index_js.h"
+#include "Assets/Web/launch_html.h"
+#include "Assets/Web/launch_js.h"
+#include "Assets/Web/download_html.h"
+#include "Assets/Web/download_js.h"
+#include "Assets/Web/downloads_html.h"
+#include "Assets/Web/downloads_js.h"
+#include "Assets/Web/remove_html.h"
+#include "Assets/Web/remove_js.h"
+#include "Assets/Web/remoteview_html.h"
+#include "Assets/Web/remoteview_js.h"
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/rtcManager.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/rtcManager.cpp
new file mode 100644
index 0000000..37fa7cb
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/rtcManager.cpp
@@ -0,0 +1,132 @@
+#include "rtcManager.h"
+#include "xboxinternals.h"
+
+#define RTC_ADDRESS 0xD0
+#define EXTRACT_DATE_VALUE(value) ((((value & 0xf0) >> 4) * 10) + (value & 0x0f))
+#define COMPOSE_DATE_VALUE(value) ((((value - (value % 10)) / 10) << 4) | (value % 10))
+
+uint8_t rtcManager::readByte(uint8_t reg)
+{
+ const int rtcAddess = 0x68;
+ uint32_t temp = 0;
+ HalReadSMBusByte(RTC_ADDRESS, reg, &temp);
+ return (uint8_t)temp;
+}
+
+void rtcManager::writeByte(uint8_t reg, uint8_t value)
+{
+ HalWriteSMBusByte(RTC_ADDRESS, reg, value);
+}
+
+void rtcManager::setDateTime(rtcDateTime dateTime)
+{
+ SYSTEMTIME localSystemTime;
+ localSystemTime.wMilliseconds = 0;
+ localSystemTime.wSecond = dateTime.sec;
+ localSystemTime.wMinute = dateTime.min;
+ localSystemTime.wHour = dateTime.hour;
+ localSystemTime.wDayOfWeek = dateTime.dotw;
+ localSystemTime.wDay = dateTime.day;
+ localSystemTime.wMonth = dateTime.month;
+ localSystemTime.wYear = 2000 + dateTime.year;
+
+ FILETIME localFileTime;
+ SystemTimeToFileTime(&localSystemTime, &localFileTime);
+
+ FILETIME utcFileTime;
+ LocalFileTimeToFileTime(&localFileTime, &utcFileTime);
+
+ SYSTEMTIME utcSystemTime;
+ FileTimeToSystemTime(&utcFileTime, &utcSystemTime);
+
+ writeByte(0, COMPOSE_DATE_VALUE(utcSystemTime.wSecond));
+ writeByte(1, COMPOSE_DATE_VALUE(utcSystemTime.wMinute));
+ writeByte(2, COMPOSE_DATE_VALUE(utcSystemTime.wHour));
+ writeByte(3, (uint8_t)utcSystemTime.wDayOfWeek);
+ writeByte(4, COMPOSE_DATE_VALUE(utcSystemTime.wDay));
+ writeByte(5, COMPOSE_DATE_VALUE(utcSystemTime.wMonth));
+ writeByte(6, COMPOSE_DATE_VALUE(utcSystemTime.wYear % 100));
+}
+
+rtcDateTime rtcManager::getDateTime()
+{
+ SYSTEMTIME utcSystemTime;
+ uint8_t value;
+
+ utcSystemTime.wMilliseconds = 0;
+ value = readByte(0);
+ utcSystemTime.wSecond = min(EXTRACT_DATE_VALUE(value), 59);
+ value = readByte(1);
+ utcSystemTime.wMinute = min(EXTRACT_DATE_VALUE(value), 59);
+ value = readByte(2);
+ utcSystemTime.wHour = min(EXTRACT_DATE_VALUE(value & 0x3f), 23);
+ value = readByte(3);
+ utcSystemTime.wDayOfWeek = value & 0x7;
+ value = readByte(4);
+ utcSystemTime.wDay = max(min(EXTRACT_DATE_VALUE(value), 31), 1);
+ value = readByte(5);
+ utcSystemTime.wMonth = max(min(EXTRACT_DATE_VALUE(value), 12), 1);
+ value = readByte(6);
+ utcSystemTime.wYear = 2000 + EXTRACT_DATE_VALUE(value);
+
+ FILETIME utcFileTime;
+ SystemTimeToFileTime(&utcSystemTime, &utcFileTime);
+
+ FILETIME localFileTime;
+ FileTimeToLocalFileTime(&utcFileTime, &localFileTime);
+
+ SYSTEMTIME localSystemTime;
+ FileTimeToSystemTime(&localFileTime, &localSystemTime);
+
+ rtcDateTime dateTime;
+ dateTime.sec = (uint8_t)localSystemTime.wSecond;
+ dateTime.min = (uint8_t)localSystemTime.wMinute;
+ dateTime.hour = (uint8_t)localSystemTime.wHour;
+ dateTime.dotw = (uint8_t)localSystemTime.wDayOfWeek;
+ dateTime.day = (uint8_t)localSystemTime.wDay;
+ dateTime.month = (uint8_t)localSystemTime.wMonth;
+ dateTime.year = (uint8_t)(localSystemTime.wYear % 100);
+ return dateTime;
+}
+
+void rtcManager::setXboxDateTime(rtcDateTime dateTime)
+{
+ SYSTEMTIME localSystemTime;
+ localSystemTime.wMilliseconds = 0;
+ localSystemTime.wSecond = dateTime.sec;
+ localSystemTime.wMinute = dateTime.min;
+ localSystemTime.wHour = dateTime.hour;
+ localSystemTime.wDayOfWeek = dateTime.dotw;
+ localSystemTime.wDay = dateTime.day;
+ localSystemTime.wMonth = dateTime.month;
+ localSystemTime.wYear = 2000 + dateTime.year;
+
+ FILETIME localFileTime;
+ SystemTimeToFileTime(&localSystemTime, &localFileTime);
+
+ FILETIME utcFileTime;
+ LocalFileTimeToFileTime(&localFileTime, &utcFileTime);
+ NtSetSystemTime(&utcFileTime, NULL);
+}
+
+rtcDateTime rtcManager::getXboxDateTime()
+{
+ FILETIME utcFileTime;
+ KeQuerySystemTime(&utcFileTime);
+
+ FILETIME localFileTime;
+ FileTimeToLocalFileTime(&utcFileTime, &localFileTime);
+
+ SYSTEMTIME localSystemTime;
+ FileTimeToSystemTime(&localFileTime, &localSystemTime);
+
+ rtcDateTime dateTime;
+ dateTime.sec = (uint8_t)localSystemTime.wSecond;
+ dateTime.min = (uint8_t)localSystemTime.wMinute;
+ dateTime.hour = (uint8_t)localSystemTime.wHour;
+ dateTime.dotw = (uint8_t)localSystemTime.wDayOfWeek;
+ dateTime.day = (uint8_t)localSystemTime.wDay;
+ dateTime.month = (uint8_t)localSystemTime.wMonth;
+ dateTime.year = (uint8_t)(localSystemTime.wYear % 100);
+ return dateTime;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/rtcManager.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/rtcManager.h
new file mode 100644
index 0000000..e1af5b9
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/rtcManager.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "xboxinternals.h"
+
+typedef struct rtcDateTime
+{
+ uint8_t hour;
+ uint8_t min;
+ uint8_t sec;
+ uint8_t year;
+ uint8_t month;
+ uint8_t day;
+ uint8_t dotw;
+} rtcDateTime;
+
+class rtcManager
+{
+public:
+ static uint8_t readByte(uint8_t reg);
+ static void writeByte(uint8_t reg, uint8_t value);
+ static void setDateTime(rtcDateTime dateTime);
+ static rtcDateTime getDateTime();
+ static void setXboxDateTime(rtcDateTime dateTime);
+ static rtcDateTime getXboxDateTime();
+};
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/settingsManager.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/settingsManager.cpp
new file mode 100644
index 0000000..2da67ab
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/settingsManager.cpp
@@ -0,0 +1,653 @@
+#include "settingsManager.h"
+#include "modchip.h"
+#include "modchipXenium.h"
+#include "context.h"
+#include "versioning.h"
+#include "crc32.h"
+#include "stringUtility.h"
+#include "utils.h"
+#include "Threads\lcdRender.h"
+
+#include
+#include
+
+#define SETTINGS_OFFSET (0x1f8000 - 0x1c0000)
+#define INSTALLER_LOGO_OFFSET (0x1f0000 - 0x1c0000)
+
+namespace
+{
+ settingsState mSettingsCurrent;
+ settingsState mSettingsShadow;
+}
+
+semver settingsManager::getVersion()
+{
+ semver version;
+ memset(&version, 0, sizeof(version));
+ version.major = 1;
+ version.minor = 5;
+ version.patch = 0;
+ return version;
+}
+
+char* settingsManager::getVersionSting(semver version)
+{
+ return stringUtility::formatString("%i.%i.%i", version.major, version.minor, version.patch);
+}
+
+#ifdef _DEBUG
+#define TEST
+#endif
+
+void settingsManager::initSettings()
+{
+ memset(&mSettingsCurrent, 0, sizeof(mSettingsCurrent));
+ mSettingsCurrent.version = getVersion();
+ mSettingsCurrent.autoBootDelay = 5;
+ mSettingsCurrent.musicVolume = 75;
+ mSettingsCurrent.soundVolume = 100;
+ mSettingsCurrent.minFanSpeed = 10;
+ mSettingsCurrent.ledColor = 2;
+ mSettingsCurrent.lcdBacklight = 100;
+ mSettingsCurrent.lcdContrast = 80;
+ mSettingsCurrent.driveSetup = 1;
+ mSettingsCurrent.udmaModeMaster = 2;
+ mSettingsCurrent.udmaModeSlave = 2;
+ mSettingsCurrent.splashDelay = 6;
+//#ifdef TEST
+// mSettingsCurrent.banks[0].slots = 1;
+// stringUtility::copyString(&mSettingsCurrent.banks[0].name[0], "Bank 1 Rom", 41);
+// mSettingsCurrent.banks[1].slots = 1;
+// stringUtility::copyString(&mSettingsCurrent.banks[1].name[0], "Bank 2 Rom", 41);
+// mSettingsCurrent.banks[2].slots = 1;
+// stringUtility::copyString(&mSettingsCurrent.banks[2].name[0], "Bank 3 Rom", 41);
+// mSettingsCurrent.banks[3].slots = 1;
+// stringUtility::copyString(&mSettingsCurrent.banks[3].name[0], "Bank 4 Rom", 41);
+//
+// stringUtility::copyString(&mSettingsCurrent.skinName[0], "TeamResurgent-Animated", 51);
+// stringUtility::copyString(&mSettingsCurrent.soundPackName[0], "Cybernoid", 51);
+//
+//#endif
+ memcpy(&mSettingsShadow, &mSettingsCurrent, sizeof(mSettingsCurrent));
+}
+
+void settingsManager::loadSettings()
+{
+#ifndef TOOLS
+ context::getModchip()->loadSettings(mSettingsCurrent);
+ memcpy(&mSettingsShadow, &mSettingsCurrent, sizeof(mSettingsCurrent));
+#else
+ initSettings();
+#endif
+}
+
+void settingsManager::saveSettings()
+{
+#ifndef TOOLS
+ context::getModchip()->saveSettings(mSettingsShadow);
+ memcpy(&mSettingsCurrent, &mSettingsShadow, sizeof(mSettingsCurrent));
+#endif
+}
+
+bool settingsManager::shouldSave()
+{
+ uint8_t* first = ((uint8_t*)&mSettingsCurrent) + sizeof(uint32_t);
+ uint8_t* second = ((uint8_t*)&mSettingsShadow) + sizeof(uint32_t);
+ for (int i = 0; i < sizeof(mSettingsCurrent) - sizeof(uint32_t); i++)
+ {
+ if (first[i] != second[i])
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+utils::dataContainer* settingsManager::getInstallerLogoData()
+{
+ return context::getModchip()->getInstallerLogo();
+}
+
+uint32_t settingsManager::getFreeSlots()
+{
+ uint32_t slotCount = context::getModchip()->getSlotCount();
+ uint32_t freeSlots = slotCount;
+ for (uint32_t i = 0; i < slotCount; i++)
+ {
+ freeSlots = freeSlots - mSettingsCurrent.banks[i].slots;
+ }
+ return freeSlots;
+}
+
+char* settingsManager::getFreeSlotsJson()
+{
+ char* freeSlotsJson = stringUtility::formatString("{\"freeslots\":%lu}", getFreeSlots());
+ return freeSlotsJson;
+}
+
+bankInfo settingsManager::getBankInfo(uint8_t id)
+{
+ return mSettingsCurrent.banks[id];
+}
+
+pointerVector* settingsManager::getBankInfos()
+{
+ pointerVector* bankInfos = new pointerVector(true);
+
+ uint32_t totalSlots = context::getModchip()->getSlotCount();
+ for (uint32_t i = 0; i < totalSlots; i++)
+ {
+ if (mSettingsCurrent.banks[i].slots == 0)
+ {
+ continue;
+ }
+
+ bankDetails* bank = new bankDetails();
+ bank->id = (uint8_t)i;
+ bank->ledColor = mSettingsCurrent.banks[i].ledColor;
+ bank->slots = mSettingsCurrent.banks[i].slots;
+ bank->name = strdup(&mSettingsCurrent.banks[i].name[0]);
+ bank->autoBoot = mSettingsCurrent.banks[i].autoBoot == 1;
+ bankInfos->add(bank);
+ }
+
+ return bankInfos;
+}
+
+char* settingsManager::getBankInfosJson()
+{
+ pointerVector* bankInfos = getBankInfos();
+
+ char* bankInfoJson = strdup("[");
+ for (uint32_t i = 0; i < bankInfos->count(); i++)
+ {
+ bankDetails* bank = bankInfos->get(i);
+ if (bank->slots > 0)
+ {
+ char* temp = stringUtility::formatString("%s%s{\"id\":%i,\"name\":\"%s\",\"slots\":%i}", bankInfoJson, i == 0 ? "" : ",", bank->id, bank->name, bank->slots);
+ free(bankInfoJson);
+ bankInfoJson = temp;
+ }
+ }
+
+ char* result = stringUtility::formatString("%s]", bankInfoJson);
+ free(bankInfoJson);
+
+ delete(bankInfos);
+ return result;
+}
+
+void settingsManager::toggleAutoBootBank(uint8_t id)
+{
+ for (int i = 0; i < MAX_SLOTS; i++)
+ {
+ if (i == id)
+ {
+ mSettingsShadow.banks[i].autoBoot = !mSettingsShadow.banks[i].autoBoot;
+ }
+ else
+ {
+ mSettingsShadow.banks[i].autoBoot = false;
+ }
+ }
+ saveSettings();
+}
+
+bool settingsManager::hasAutoBootBank()
+{
+ for (int i = 0; i < MAX_SLOTS; i++)
+ {
+ if (mSettingsCurrent.banks[i].slots > 0 && mSettingsCurrent.banks[i].autoBoot)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void settingsManager::deleteBank(uint8_t id)
+{
+ memset(&mSettingsShadow.banks[id], 0, sizeof(bankInfo));
+ saveSettings();
+}
+
+void settingsManager::optimizeBanks(uint8_t slotsNeeded)
+{
+ if (slotsNeeded == 1)
+ {
+ utils::debugPrint("No need to optimize for only 1 slot");
+ return;
+ }
+
+ if (getFreeSlots() < slotsNeeded)
+ {
+ utils::debugPrint("Not enough free slots to be worth optimizing");
+ return;
+ }
+
+ for (uint8_t i = 0; i < 3; i++)
+ {
+ uint8_t slotCheck = 1 << i;
+ while (true)
+ {
+ // Exit if we now have space for what we need
+ uint8_t bankId = 0;
+ bool needsOptimize = tryGetFreeBank(slotsNeeded, bankId) == false;
+ if (needsOptimize == false)
+ {
+ return;
+ }
+
+ // Work out first free bank and last used bank for current itteration of slots
+ uint8_t freeBank = 0;
+ if (tryGetFreeBank(slotCheck, freeBank) == false)
+ {
+ break;
+ }
+ uint8_t lastUsedBank = 0;
+ if (tryGetLastUsedBank(slotCheck, lastUsedBank) == false)
+ {
+ break;
+ }
+
+ // Exit if no free slots before last used
+ if (freeBank > lastUsedBank)
+ {
+ break;
+ }
+
+ // Move banks
+ uint8_t destBank = context::getModchip()->getBankFromIdAndSlots(freeBank, slotCheck);
+ uint8_t sourceBank = context::getModchip()->getBankFromIdAndSlots(lastUsedBank, slotCheck);
+ utils::dataContainer* bankData = context::getModchip()->readBank(sourceBank);
+ context::getModchip()->eraseBank(destBank);
+ context::getModchip()->writeBank(destBank, bankData);
+ delete(bankData);
+
+ memcpy(&mSettingsShadow.banks[freeBank], &mSettingsShadow.banks[lastUsedBank], sizeof(bankInfo));
+ memset(&mSettingsShadow.banks[lastUsedBank], 0, sizeof(bankInfo));
+
+ utils::debugPrint("Moved bank %i to %i\n", lastUsedBank, freeBank);
+ }
+ }
+ saveSettings();
+}
+
+bool settingsManager::tryGetLastUsedBank(uint8_t slotsNeeded, uint8_t& bankId)
+{
+ bool found = false;
+ uint8_t lastBank = 0;
+
+ uint8_t bank = 0;
+ while (bank < context::getModchip()->getSlotCount())
+ {
+ uint8_t slotsUsed = mSettingsCurrent.banks[bank].slots;
+ if (slotsUsed == slotsNeeded)
+ {
+ found = true;
+ lastBank = bank;
+ }
+ bank += slotsNeeded;
+ }
+
+ bankId = lastBank;
+ return found;
+}
+
+bool settingsManager::tryGetFreeBank(uint8_t slotsNeeded, uint8_t& bankId)
+{
+ uint32_t freeSlots = getFreeSlots();
+
+ if (freeSlots < slotsNeeded)
+ {
+ utils::debugPrint("Not enough free slots\n");
+ return false;
+ }
+
+ uint8_t bank = 0;
+ while (bank < context::getModchip()->getSlotCount())
+ {
+ uint8_t slotsToSkip = slotsNeeded;
+ bool spaceFound = true;
+ for (uint32_t i = 0; i < slotsNeeded; i++)
+ {
+ uint8_t slotsUsed = mSettingsCurrent.banks[bank + i].slots;
+ if (slotsUsed == 0)
+ {
+ continue;
+ }
+ slotsToSkip = max(slotsUsed, slotsNeeded);
+ spaceFound = false;
+ break;
+ }
+ if (spaceFound == true)
+ {
+ bankId = bank;
+ return true;
+ }
+ bank += slotsToSkip;
+ }
+
+ return false;
+}
+
+void settingsManager::eraseBank(uint8_t bankId, uint32_t size)
+{
+ uint8_t slotsNeeded = (uint8_t)(size >> 18);
+ uint8_t bank = context::getModchip()->getBankFromIdAndSlots(bankId, slotsNeeded);
+ context::getModchip()->eraseBank(bank);
+}
+
+void settingsManager::writeBank(uint8_t bankId, utils::dataContainer* dataContainer, const char *name, uint8_t ledColor)
+{
+ uint8_t slotsNeeded = (uint8_t)(dataContainer->size >> 18);
+ uint8_t bank = context::getModchip()->getBankFromIdAndSlots(bankId, slotsNeeded);
+ context::getModchip()->writeBank(bank, dataContainer);
+ mSettingsShadow.banks[bankId].ledColor = ledColor;
+ mSettingsShadow.banks[bankId].slots = slotsNeeded;
+ char* nameCopy = strdup(name);
+ stringUtility::copyString((char*)&mSettingsShadow.banks[bankId].name[0], nameCopy, 40);
+ free(nameCopy);
+ saveSettings();
+}
+
+bool settingsManager::verifyBank(uint8_t bankId, utils::dataContainer* dataContainer)
+{
+ uint8_t slotsNeeded = (uint8_t)(dataContainer->size >> 18);
+ uint8_t bank = context::getModchip()->getBankFromIdAndSlots(bankId, slotsNeeded);
+ bool result = context::getModchip()->verifyBank(bank, dataContainer);
+ return result;
+}
+
+utils::dataContainer* settingsManager::readBank(uint8_t bankId)
+{
+ uint8_t slots = mSettingsCurrent.banks[bankId].slots;
+ uint8_t bank = context::getModchip()->getBankFromIdAndSlots(bankId, slots);
+ utils::dataContainer* result = context::getModchip()->readBank(bank);
+ return result;
+}
+
+void settingsManager::launchBank(uint8_t bankId)
+{
+ lcdRender::waitStop();
+ bankInfo bankInfo = settingsManager::getBankInfo(bankId);
+ if (bankInfo.slots > 0)
+ {
+ uint8_t bank = context::getModchip()->getBankFromIdAndSlots(bankId, bankInfo.slots);
+ context::getModchip()->launchBank(bank, bankInfo.ledColor);
+ }
+}
+
+void settingsManager::launchTsop()
+{
+ lcdRender::waitStop();
+ context::getModchip()->launchTsop();
+}
+
+void settingsManager::launchRecovery()
+{
+ lcdRender::waitStop();
+ context::getModchip()->launchRecovery();
+}
+
+void settingsManager::editBank(uint8_t bankId, const char *name, uint8_t ledColor)
+{
+ mSettingsShadow.banks[bankId].ledColor = ledColor;
+ char* nameCopy = strdup(name);
+ stringUtility::copyString((char*)&mSettingsShadow.banks[bankId].name[0], nameCopy, 40);
+ free(nameCopy);
+
+ saveSettings();
+}
+
+networkModeEnum settingsManager::getNetworkMode()
+{
+ return (networkModeEnum)mSettingsCurrent.network.networkMode;
+}
+
+uint32_t settingsManager::getNetworkAddress()
+{
+ return mSettingsCurrent.network.address;
+}
+
+uint32_t settingsManager::getNetworkSubnet()
+{
+ return mSettingsCurrent.network.subnet;
+}
+
+uint32_t settingsManager::getNetworkGateway()
+{
+ return mSettingsCurrent.network.gateway;
+}
+
+uint32_t settingsManager::getNetworkPrimaryDns()
+{
+ return mSettingsCurrent.network.primaryDns;
+}
+
+uint32_t settingsManager::getNetworkSecondaryDns()
+{
+ return mSettingsCurrent.network.secondaryDns;
+}
+
+void settingsManager::setNetwork(networkModeEnum networkMode, uint32_t address, uint32_t subnet, uint32_t gateway, uint32_t primaryDns, uint32_t secondaryDns)
+{
+ mSettingsShadow.network.networkMode = (uint32_t)networkMode;
+ mSettingsShadow.network.address = address;
+ mSettingsShadow.network.address = address;
+ mSettingsShadow.network.subnet = subnet;
+ mSettingsShadow.network.gateway = gateway;
+ mSettingsShadow.network.primaryDns = primaryDns;
+ mSettingsShadow.network.secondaryDns = secondaryDns;
+ saveSettings();
+}
+
+char* settingsManager::getSkinName()
+{
+ return strdup(&mSettingsCurrent.skinName[0]);
+}
+
+void settingsManager::setSkinName(const char* skinName)
+{
+ memset(&mSettingsShadow.skinName[0], 0, sizeof(mSettingsShadow.skinName));
+ strncpy(&mSettingsShadow.skinName[0], skinName, 50);
+ saveSettings();
+}
+
+char* settingsManager::getSoundPackName()
+{
+ return strdup(&mSettingsCurrent.soundPackName[0]);
+}
+
+void settingsManager::setSoundPackName(const char* soundPackName)
+{
+ memset(&mSettingsShadow.soundPackName[0], 0, sizeof(mSettingsShadow.soundPackName));
+ strncpy(&mSettingsShadow.soundPackName[0], soundPackName, 50);
+ saveSettings();
+}
+
+uint32_t settingsManager::getSnakeHiScore()
+{
+ return mSettingsCurrent.snakeHiScore;
+}
+
+void settingsManager::setSnakeHiScore(uint32_t playerScore)
+{
+ mSettingsShadow.snakeHiScore = playerScore;
+ saveSettings();
+}
+
+uint32_t settingsManager::getInvadersHiScore()
+{
+ return mSettingsCurrent.invadersHiScore;
+}
+
+void settingsManager::setInvadersHiScore(uint32_t playerScore)
+{
+ mSettingsShadow.invadersHiScore = playerScore;
+ saveSettings();
+}
+
+uint8_t settingsManager::getAutoBootDelay()
+{
+ return mSettingsCurrent.autoBootDelay;
+}
+
+void settingsManager::setAutoBootDelay(uint8_t autoBootDelay)
+{
+ mSettingsShadow.autoBootDelay = autoBootDelay;
+ saveSettings();
+}
+
+uint8_t settingsManager::getMusicVolume()
+{
+ return mSettingsCurrent.musicVolume;
+}
+
+void settingsManager::setMusicVolume(uint8_t volume)
+{
+ mSettingsShadow.musicVolume = volume;
+ saveSettings();
+}
+
+uint8_t settingsManager::getSoundVolume()
+{
+ return mSettingsCurrent.soundVolume;
+}
+
+void settingsManager::setSoundVolume(uint8_t volume)
+{
+ mSettingsShadow.soundVolume = volume;
+ saveSettings();
+}
+
+uint8_t settingsManager::getMinFanSpeed()
+{
+ return mSettingsCurrent.minFanSpeed;
+}
+
+void settingsManager::setMinFanSpeed(uint8_t minFanSpeed)
+{
+ mSettingsShadow.minFanSpeed = minFanSpeed;
+ saveSettings();
+}
+
+uint8_t settingsManager::getLedColor()
+{
+ return mSettingsCurrent.ledColor;
+}
+
+void settingsManager::setLedColor(uint8_t ledColor)
+{
+ mSettingsShadow.ledColor = ledColor;
+ saveSettings();
+}
+
+uint8_t settingsManager::getLcdMode(bool current)
+{
+ return current ? mSettingsCurrent.lcdMode : mSettingsShadow.lcdMode;
+}
+
+void settingsManager::setLcdMode(uint8_t lcdMode)
+{
+ mSettingsShadow.lcdMode = lcdMode;
+}
+
+uint8_t settingsManager::getLcdModel(bool current)
+{
+ return current ? mSettingsCurrent.lcdModel : mSettingsShadow.lcdModel;
+}
+
+void settingsManager::setLcdModel(uint8_t lcdModel)
+{
+ mSettingsShadow.lcdModel = lcdModel;
+}
+
+uint8_t settingsManager::getLcdAddress(bool current)
+{
+ return current ? mSettingsCurrent.lcdAddress : mSettingsShadow.lcdAddress;
+}
+
+void settingsManager::setLcdAddress(uint8_t lcdAddress)
+{
+ mSettingsShadow.lcdAddress = lcdAddress;
+}
+
+uint8_t settingsManager::getLcdBacklight(bool current)
+{
+ return current ? mSettingsCurrent.lcdBacklight : mSettingsShadow.lcdBacklight;
+}
+
+void settingsManager::setLcdBacklight(uint8_t backlight)
+{
+ mSettingsShadow.lcdBacklight = backlight;
+}
+
+uint8_t settingsManager::getLcdContrast(bool current)
+{
+ return current ? mSettingsCurrent.lcdContrast : mSettingsShadow.lcdContrast;
+}
+
+void settingsManager::setLcdContrast(uint8_t contrast)
+{
+ mSettingsShadow.lcdContrast = contrast;
+}
+
+bool settingsManager::getRtcEnable()
+{
+ return mSettingsCurrent.rtcEnable == 1;
+}
+
+void settingsManager::setRtcEnable(bool enable)
+{
+ mSettingsShadow.rtcEnable = enable ? 1 : 0;
+ saveSettings();
+}
+
+uint8_t settingsManager::getDriveSetup()
+{
+ return mSettingsCurrent.driveSetup;
+}
+
+void settingsManager::setDriveSetup(uint8_t driveSetup)
+{
+ mSettingsShadow.driveSetup = driveSetup;
+ saveSettings();
+}
+
+uint8_t settingsManager::getUdmaMode(bool master)
+{
+ return master ? mSettingsCurrent.udmaModeMaster : mSettingsCurrent.udmaModeSlave;
+}
+
+void settingsManager::setUdmaMode(uint8_t udmaMode, bool master)
+{
+ if(master) {
+ mSettingsShadow.udmaModeMaster = udmaMode;
+ } else {
+ mSettingsShadow.udmaModeSlave = udmaMode;
+ }
+ saveSettings();
+}
+
+uint8_t settingsManager::getSplashDelay()
+{
+ return mSettingsCurrent.splashDelay;
+}
+
+void settingsManager::setSplashDelay(uint8_t splashDelay)
+{
+ mSettingsShadow.splashDelay = splashDelay;
+ saveSettings();
+}
+
+bool settingsManager::getVgaEnable()
+{
+ return mSettingsCurrent.vgaEnable == 1;
+}
+
+void settingsManager::setVgaEnable(bool enable)
+{
+ mSettingsShadow.vgaEnable = enable ? 1 : 0;
+ saveSettings();
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/settingsManager.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/settingsManager.h
new file mode 100644
index 0000000..97ec9c0
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/settingsManager.h
@@ -0,0 +1,164 @@
+#pragma once
+
+#include "xboxinternals.h"
+#include "versioning.h"
+#include "utils.h"
+#include "pointerVector.h"
+
+#include
+
+#define MAX_SLOTS 16
+
+#pragma pack(push,1)
+
+typedef struct bankInfo
+{
+ uint8_t ledColor;
+ uint8_t slots;
+ uint8_t autoBoot;
+ uint8_t reserved0;
+ char name[64];
+} bankInfo;
+
+enum networkModeEnum
+{
+ networkModeDynamicAutoDns = 0,
+ networkModeDynamicManualDns = 1,
+ networkModeStatic = 2,
+};
+
+typedef struct networkInfo
+{
+ uint32_t networkMode;
+ uint32_t address;
+ uint32_t subnet;
+ uint32_t gateway;
+ uint32_t primaryDns;
+ uint32_t secondaryDns;
+} networkInfo;
+
+typedef struct settingsState
+{
+ uint32_t checksum;
+ semver version;
+ bankInfo banks[MAX_SLOTS];
+ networkInfo network;
+ uint32_t snakeHiScore;
+ uint32_t invadersHiScore;
+ char skinName[64];
+ char soundPackName[64];
+ uint8_t autoBootDelay;
+ uint8_t musicVolume;
+ uint8_t soundVolume;
+ uint8_t minFanSpeed;
+ uint8_t ledColor;
+ uint8_t lcdMode;
+ uint8_t lcdModel;
+ uint8_t lcdAddress;
+ uint8_t lcdBacklight;
+ uint8_t lcdContrast;
+ uint8_t rtcEnable;
+ uint8_t driveSetup;
+ uint8_t udmaModeMaster;
+ uint8_t udmaModeSlave;
+ uint8_t splashDelay;
+ uint8_t vgaEnable;
+ uint8_t reserved0;
+ uint8_t reserved1;
+ uint8_t reserved2;
+} settingsState;
+
+#pragma pack(pop)
+
+typedef struct bankDetails
+{
+ uint8_t id;
+ uint8_t ledColor;
+ uint8_t slots;
+ char* name;
+ bool autoBoot;
+
+ bankDetails() : id(0), ledColor(0), slots(0), name(NULL), autoBoot(false) {}
+
+ ~bankDetails()
+ {
+ free(this->name);
+ }
+
+} bankDetails;
+
+class settingsManager
+{
+public:
+ static semver getVersion();
+ static char* getVersionSting(semver version);
+ static void initSettings();
+ static void loadSettings();
+ static void saveSettings();
+ static bool shouldSave();
+ static utils::dataContainer* getInstallerLogoData();
+ static uint32_t getFreeSlots();
+ static char* getFreeSlotsJson();
+ static bankInfo getBankInfo(uint8_t id);
+ static pointerVector* getBankInfos();
+ static char* getBankInfosJson();
+ static void toggleAutoBootBank(uint8_t id);
+ static bool hasAutoBootBank();
+ static void deleteBank(uint8_t id);
+ static void optimizeBanks(uint8_t slotsNeeded);
+ static bool tryGetLastUsedBank(uint8_t slotsNeeded, uint8_t& bankId);
+ static bool tryGetFreeBank(uint8_t slotsNeeded, uint8_t& bankId);
+ static void eraseBank(uint8_t bankId, uint32_t size);
+ static void writeBank(uint8_t bankId, utils::dataContainer* dataContainer, const char *name, uint8_t ledColor);
+ static bool verifyBank(uint8_t bankId, utils::dataContainer* dataContainer);
+ static utils::dataContainer* readBank(uint8_t bankId);
+ static void launchBank(uint8_t id);
+ static void launchTsop();
+ static void launchRecovery();
+ static void editBank(uint8_t bankId, const char *name, uint8_t ledColor);
+ static networkModeEnum getNetworkMode();
+ static uint32_t getNetworkAddress();
+ static uint32_t getNetworkSubnet();
+ static uint32_t getNetworkPrimaryDns();
+ static uint32_t getNetworkSecondaryDns();
+ static uint32_t getNetworkGateway();
+ static void setNetwork(networkModeEnum networkMode, uint32_t address, uint32_t subnet, uint32_t gateway, uint32_t primaryDns, uint32_t secondaryDns);
+ static char* getSkinName();
+ static void setSkinName(const char* skinName);
+ static char* getSoundPackName();
+ static void setSoundPackName(const char* soundPackName);
+ static uint32_t getSnakeHiScore();
+ static void setSnakeHiScore(uint32_t playerScore);
+ static uint32_t getInvadersHiScore();
+ static void setInvadersHiScore(uint32_t playerScore);
+ static uint8_t getAutoBootDelay();
+ static void setAutoBootDelay(uint8_t autoBootDelay);
+ static uint8_t getMusicVolume();
+ static void setMusicVolume(uint8_t volume);
+ static uint8_t getSoundVolume();
+ static void setSoundVolume(uint8_t volume);
+ static uint8_t getMinFanSpeed();
+ static void setMinFanSpeed(uint8_t minFanSpeed);
+ static uint8_t getLedColor();
+ static void setLedColor(uint8_t ledColor);
+ static uint8_t getLcdMode(bool current);
+ static void setLcdMode(uint8_t lcdMode);
+ static uint8_t getLcdModel(bool current);
+ static void setLcdModel(uint8_t lcdModel);
+ static uint8_t getLcdAddress(bool current);
+ static void setLcdAddress(uint8_t lcdAddress);
+ static uint8_t getLcdBacklight(bool current);
+ static void setLcdBacklight(uint8_t backlight);
+ static uint8_t getLcdContrast(bool current);
+ static void setLcdContrast(uint8_t contrast);
+ static bool getRtcEnable();
+ static void setRtcEnable(bool enable);
+ static uint8_t getDriveSetup();
+ static void setDriveSetup(uint8_t driveSetup);
+ static uint8_t getUdmaMode(bool master = true);
+ static void setUdmaMode(uint8_t udmaMode, bool master = true);
+ static uint8_t getSplashDelay();
+ static void setSplashDelay(uint8_t splashDelay);
+ static bool getVgaEnable();
+ static void setVgaEnable(bool enable);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/socketUtility.cpp b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/socketUtility.cpp
new file mode 100644
index 0000000..503e56e
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/socketUtility.cpp
@@ -0,0 +1,303 @@
+#include "socketUtility.h"
+#include "utils.h"
+
+bool socketUtility::createSocket(int af, int type, int protocol, uint64_t& result)
+{
+ result = socket(af, type, protocol);
+ if (result < 0)
+ {
+ utils::debugPrint("Error: Create socket failed: %i", WSAGetLastError());
+ return false;
+ }
+ return true;
+}
+
+uint64_t socketUtility::createSocket(sockaddr_in sockaddr_in, bool allow_reuse)
+{
+ const uint64_t listen_socket = socket(AF_INET, SOCK_STREAM, 0);
+ if (listen_socket == INVALID_SOCKET)
+ {
+ utils::debugPrint("Error: Create socket failed: %i", WSAGetLastError());
+ return NULL;
+ }
+
+ int result;
+
+ unsigned long allowLocalAddressReuse = 1;
+ result = setsockopt((SOCKET)listen_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&allowLocalAddressReuse, sizeof(allowLocalAddressReuse));
+ if (result != 0)
+ {
+ utils::debugPrint("Error: Set socket option SO_REUSEADDR failed: %i", WSAGetLastError());
+ return NULL;
+ }
+
+ unsigned long nonBlocking = 1;
+ if (ioctlsocket((SOCKET)listen_socket, FIONBIO, &nonBlocking) == SOCKET_ERROR)
+ {
+ utils::debugPrint("Error: IO control socket non-blocking failed: %i", WSAGetLastError());
+ return NULL;
+ }
+
+ result = bind((SOCKET)listen_socket, (sockaddr*)&sockaddr_in, sizeof(sockaddr_in));
+ if (result == SOCKET_ERROR)
+ {
+ utils::debugPrint("Error: Socket bind failed: %i", WSAGetLastError());
+ return NULL;
+ }
+
+ result = listen((SOCKET)listen_socket, 10);
+ if (result == SOCKET_ERROR)
+ {
+ utils::debugPrint("Error: Socket listen failed: %i", WSAGetLastError());
+ return NULL;
+ }
+
+ return listen_socket;
+}
+
+bool socketUtility::connectSocket(uint64_t socket, sockaddr_in* socket_addr_in)
+{
+ const int result = connect((SOCKET)socket, (sockaddr*)socket_addr_in, sizeof(SOCKADDR_IN));
+ if (result < 0)
+ {
+ utils::debugPrint("Error: Connect socket failed: %i", WSAGetLastError());
+ return false;
+ }
+ return true;
+}
+
+bool socketUtility::connectSocket(uint64_t socket, sockaddr* socket_addr)
+{
+ const int result = connect((SOCKET)socket, socket_addr, sizeof(sockaddr));
+ if (result < 0)
+ {
+ utils::debugPrint("Error: Connect socket failed: %i", WSAGetLastError());
+ return false;
+ }
+ return true;
+}
+
+bool socketUtility::acceptSocket(uint64_t socket, uint64_t& result)
+{
+ result = accept((SOCKET)socket, NULL, 0);
+ if (result < 0)
+ {
+ utils::debugPrint("Error: Accept socket failed: %i", WSAGetLastError());
+ return false;
+ }
+ return true;
+}
+
+bool socketUtility::acceptSocket(uint64_t socket, sockaddr_in* socket_addr_in, uint64_t& result)
+{
+ int dw = sizeof(sockaddr_in);
+ result = accept((SOCKET)socket, (sockaddr*)socket_addr_in, &dw);
+ if (result < 0)
+ {
+ utils::debugPrint("Error: Accept socket failed: %i", WSAGetLastError());
+ return false;
+ }
+ return true;
+}
+
+bool socketUtility::acceptSocket(uint64_t socket, sockaddr* socket_addr, uint64_t& result)
+{
+ int dw = sizeof(sockaddr);
+ result = accept((SOCKET)socket, socket_addr, &dw);
+ if (result < 0)
+ {
+ utils::debugPrint("Error: Accept socket failed: %i", WSAGetLastError());
+ return false;
+ }
+ return true;
+}
+
+bool socketUtility::setSocketRecvSize(uint64_t socket, uint32_t &recv_size)
+{
+ uint32_t recvBufferSize = RECV_SOCKET_BUFFER_SIZE;
+ int result = setsockopt((SOCKET)socket, SOL_SOCKET, SO_RCVBUF, (char*)&recvBufferSize, sizeof(uint32_t));
+ if (result < 0)
+ {
+ utils::debugPrint("Error: Set socket option SO_RCVBUF failed: %i", WSAGetLastError());
+ }
+
+ int isize = sizeof(recvBufferSize);
+ result = getsockopt((SOCKET)socket, SOL_SOCKET, SO_RCVBUF, (char*)&recvBufferSize, (int*)&isize);
+ if (result < 0)
+ {
+ recvBufferSize = 8192;
+ }
+
+ recv_size = recvBufferSize;
+ return true;
+}
+
+bool socketUtility::setSocketSendSize(uint64_t socket, uint32_t &send_size)
+{
+ uint32_t sendBufferSize = SEND_SOCKET_BUFFER_SIZE;
+ int result = setsockopt((SOCKET)socket, SOL_SOCKET, SO_SNDBUF, (char*)&sendBufferSize, sizeof(uint32_t));
+ if (result < 0)
+ {
+ utils::debugPrint("Error: Set socket option SO_SNDBUF failed: %i", WSAGetLastError());
+ }
+
+ int isize = sizeof(sendBufferSize);
+ result = getsockopt((SOCKET)socket, SOL_SOCKET, SO_SNDBUF, (char*)&sendBufferSize, (int*)&isize);
+ if (result < 0)
+ {
+ sendBufferSize = 8192;
+ }
+
+ send_size = sendBufferSize;
+ return true;
+}
+
+bool socketUtility::getReadQueueLength(uint64_t socket, int &queue_length)
+{
+ DWORD temp;
+ int result = ioctlsocket((SOCKET)socket, FIONREAD, &temp);
+ if (result < 0)
+ {
+ utils::debugPrint("Error: Get read queue length failed: %i", WSAGetLastError());
+ queue_length = 0;
+ return false;
+ }
+ queue_length = temp;
+ return true;
+}
+
+bool socketUtility::bindSocket(uint64_t socket, sockaddr_in* socket_addr_in)
+{
+ int result = bind((SOCKET)socket, (sockaddr*)socket_addr_in, sizeof(sockaddr_in));
+ if (result < 0)
+ {
+ utils::debugPrint("Error: Bind socket failed: %i", WSAGetLastError());
+ return false;
+ }
+ return true;
+}
+
+bool socketUtility::bindSocket(uint64_t socket, sockaddr* socket_addr)
+{
+ int result = bind((SOCKET)socket, socket_addr, sizeof(sockaddr));
+ if (result < 0)
+ {
+ utils::debugPrint("Error: Bind socket failed: %i", WSAGetLastError());
+ return false;
+ }
+ return true;
+}
+
+bool socketUtility::listenSocket(uint64_t socket, int count)
+{
+ int result = listen((SOCKET)socket, count);
+ if (result < 0)
+ {
+ utils::debugPrint("Error: Listen socket failed: %i", WSAGetLastError());
+ return false;
+ }
+ return true;
+}
+
+bool socketUtility::closeSocket(uint64_t& socket)
+{
+ if (!socket)
+ {
+ return true;
+ }
+ int result = closesocket((SOCKET)socket);
+ if (result < 0)
+ {
+ utils::debugPrint("Error: Close socket failed: %i", WSAGetLastError());
+ socket = 0;
+ return false;
+ }
+ socket = 0;
+ return true;
+}
+
+bool socketUtility::getSocketName(uint64_t socket, sockaddr_in* socket_addr_in)
+{
+ int size = sizeof(sockaddr_in);
+ int result = getsockname((SOCKET)socket, (sockaddr*)socket_addr_in, &size);
+ if (result < 0)
+ {
+ utils::debugPrint("Error: Get socket name failed: %i", WSAGetLastError());
+ return false;
+ }
+ return true;
+}
+
+bool socketUtility::getSocketName(uint64_t socket, sockaddr* socket_addr)
+{
+ int size = sizeof(sockaddr);
+ const int result = getsockname((SOCKET)socket, socket_addr, &size);
+ if (result < 0)
+ {
+ utils::debugPrint("Error: Get socket name failed: %i", WSAGetLastError());
+ return false;
+ }
+ return true;
+}
+
+int socketUtility::getAvailableDataSize(const uint64_t socket)
+{
+ unsigned long available_data = 0;
+ ioctlsocket((SOCKET)socket, FIONREAD, &available_data);
+ return (int)available_data;
+}
+
+int socketUtility::receiveSocketData(const uint64_t socket, char* buffer, const int size)
+{
+ const int bytes_received = recv((SOCKET)socket, buffer, size, 0);
+ if (bytes_received == SOCKET_ERROR)
+ {
+ utils::debugPrint("Error: Socket receive failed: %i\n", WSAGetLastError());
+ }
+ return bytes_received;
+}
+
+int socketUtility::sendSocketData(const uint64_t socket, const char* buffer, const int size)
+{
+ const int bytes_sent = send((SOCKET)socket, buffer, size, 0);
+ if (bytes_sent == SOCKET_ERROR)
+ {
+ utils::debugPrint("Error: Socket send failed: %i\n", WSAGetLastError());
+ }
+ return bytes_sent;
+}
+
+int socketUtility::getReadStatus(const uint64_t socket)
+{
+ static const timeval instantSpeedPlease = { 0,0 };
+ fd_set a = { 1, {(SOCKET)socket} };
+
+ int result = select(0, &a, 0, 0, &instantSpeedPlease);
+ if (result == SOCKET_ERROR)
+ {
+ result = WSAGetLastError();
+ }
+
+ if (result != 0 && result != 1)
+ {
+ utils::debugPrint("Error: getReadStatus failed: %i\n", result);
+ return SOCKET_ERROR;
+ }
+ return result;
+}
+
+int socketUtility::endBrokerSocket(uint64_t socket)
+{
+ int result = shutdown((SOCKET)socket, SD_BOTH);
+ if (result != 0)
+ {
+ utils::debugPrint("Error: Socket shutdown failed: %i", WSAGetLastError());
+ }
+ result = closesocket((SOCKET)socket);
+ if (result != 0)
+ {
+ utils::debugPrint("Error: Close socket failed: %i", WSAGetLastError());
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
\ No newline at end of file
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/socketUtility.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/socketUtility.h
new file mode 100644
index 0000000..807ba34
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/socketUtility.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#include "xboxinternals.h"
+
+#include
+#include
+
+#define RECV_SOCKET_BUFFER_SIZE_IN_K 64
+#define RECV_SOCKET_BUFFER_SIZE RECV_SOCKET_BUFFER_SIZE_IN_K * 1024
+#define SEND_SOCKET_BUFFER_SIZE_IN_K 64
+#define SEND_SOCKET_BUFFER_SIZE SEND_SOCKET_BUFFER_SIZE_IN_K * 1024
+
+class socketUtility
+{
+public:
+ static bool createSocket(int af, int type, int protocol, uint64_t& result);
+ static uint64_t createSocket(sockaddr_in sockaddr_in, bool allow_reuse);
+ static bool connectSocket(uint64_t socket, sockaddr_in* socket_addr_in);
+ static bool connectSocket(uint64_t socket, sockaddr* socket_addr);
+ static bool acceptSocket(uint64_t socket, uint64_t&result);
+ static bool acceptSocket(uint64_t socket, sockaddr_in* socket_addr_in, uint64_t& result);
+ static bool acceptSocket(uint64_t socket, sockaddr* socket_addr, uint64_t& result);
+ static bool setSocketRecvSize(uint64_t socket, uint32_t &recv_size);
+ static bool setSocketSendSize(uint64_t socket, uint32_t &send_size);
+ static bool getReadQueueLength(uint64_t socket, int &queue_length);
+ static bool bindSocket(uint64_t socket, sockaddr_in*socket_addr_in);
+ static bool bindSocket(uint64_t socket, sockaddr* socket_addr);
+ static bool listenSocket(uint64_t socket, int count);
+ static bool closeSocket(uint64_t& socket);
+ static bool getSocketName(uint64_t socket, sockaddr_in* socket_addr_in);
+ static bool getSocketName(uint64_t socket, sockaddr* socket_addr);
+
+
+ static int getAvailableDataSize(const uint64_t socket);
+ static int receiveSocketData(uint64_t socket, char* buffer, int size);
+ static int sendSocketData(uint64_t socket, const char* buffer, int size);
+ static int getReadStatus(const uint64_t socket);
+ static int endBrokerSocket(uint64_t socket);
+};
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/ssfn.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/ssfn.h
new file mode 100644
index 0000000..afc9fd1
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/ssfn.h
@@ -0,0 +1,1532 @@
+/*
+ * ssfn.h
+ * https://gitlab.com/bztsrc/scalable-font2
+ *
+ * Copyright (C) 2020 - 2022 bzt
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * @brief Scalable Screen Font renderers
+ *
+ */
+
+#ifndef _SSFN_H_
+#define _SSFN_H_
+
+#define SSFN_VERSION 0x0200
+
+/* if stdint.h was not included before us */
+// #ifndef _STDINT_H
+// typedef unsigned char uint8_t;
+// typedef unsigned short int uint16_t;
+// typedef short int int16_t;
+// typedef unsigned int uint32_t;
+// // #ifndef _UINT64_T
+// // typedef unsigned long int uint64_t;
+// // #endif
+// #endif
+
+/***** file format *****/
+
+/* magic bytes */
+#define SSFN_MAGIC "SFN2"
+#define SSFN_COLLECTION "SFNC"
+#define SSFN_ENDMAGIC "2NFS"
+
+/* ligatures area */
+#define SSFN_LIG_FIRST 0xF000
+#define SSFN_LIG_LAST 0xF8FF
+
+/* font family group in font type byte */
+#define SSFN_TYPE_FAMILY(x) ((x)&15)
+#define SSFN_FAMILY_SERIF 0
+#define SSFN_FAMILY_SANS 1
+#define SSFN_FAMILY_DECOR 2
+#define SSFN_FAMILY_MONOSPACE 3
+#define SSFN_FAMILY_HAND 4
+
+/* font style flags in font type byte */
+#define SSFN_TYPE_STYLE(x) (((x)>>4)&15)
+#define SSFN_STYLE_REGULAR 0
+#define SSFN_STYLE_BOLD 1
+#define SSFN_STYLE_ITALIC 2
+#define SSFN_STYLE_USRDEF1 4 /* user defined variant 1 */
+#define SSFN_STYLE_USRDEF2 8 /* user defined variant 2 */
+
+/* contour commands */
+#define SSFN_CONTOUR_MOVE 0
+#define SSFN_CONTOUR_LINE 1
+#define SSFN_CONTOUR_QUAD 2
+#define SSFN_CONTOUR_CUBIC 3
+
+/* glyph fragments, kerning groups and hinting grid info */
+#define SSFN_FRAG_CONTOUR 0
+#define SSFN_FRAG_BITMAP 1
+#define SSFN_FRAG_PIXMAP 2
+#define SSFN_FRAG_KERNING 3
+#define SSFN_FRAG_HINTING 4
+
+/* main SSFN header, 32 bytes */
+#ifndef _MSC_VER
+#define _pack __attribute__((packed))
+#else
+#define _pack
+#pragma pack(push)
+#pragma pack(1)
+#endif
+typedef struct {
+ uint8_t magic[4]; /* SSFN magic bytes */
+ uint32_t size; /* total size in bytes */
+ uint8_t type; /* font family and style */
+ uint8_t features; /* format features and revision */
+ uint8_t width; /* overall width of the font */
+ uint8_t height; /* overall height of the font */
+ uint8_t baseline; /* horizontal baseline in grid pixels */
+ uint8_t underline; /* position of under line in grid pixels */
+ uint16_t fragments_offs; /* offset of fragments table */
+ uint32_t characters_offs; /* characters table offset */
+ uint32_t ligature_offs; /* ligatures table offset */
+ uint32_t kerning_offs; /* kerning table offset */
+ uint32_t cmap_offs; /* color map offset */
+} _pack ssfn_font_t;
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif
+
+/***** renderer API *****/
+#define SSFN_FAMILY_ANY 0xff /* select the first loaded font */
+#define SSFN_FAMILY_BYNAME 0xfe /* select font by its unique name */
+
+/* additional styles not stored in fonts */
+#define SSFN_STYLE_UNDERLINE 16 /* under line glyph */
+#define SSFN_STYLE_STHROUGH 32 /* strike through glyph */
+#define SSFN_STYLE_NOAA 64 /* no anti-aliasing */
+#define SSFN_STYLE_NOKERN 128 /* no kerning */
+#define SSFN_STYLE_NODEFGLYPH 256 /* don't draw default glyph */
+#define SSFN_STYLE_NOCACHE 512 /* don't cache rasterized glyph */
+#define SSFN_STYLE_NOHINTING 1024 /* no auto hinting grid (not used as of now) */
+#define SSFN_STYLE_RTL 2048 /* render right-to-left */
+#define SSFN_STYLE_ABS_SIZE 4096 /* scale absoulte height */
+#define SSFN_STYLE_NOSMOOTH 8192 /* no edge-smoothing for bitmaps */
+#define SSFN_STYLE_A 16384 /* keep original alpha channel */
+
+/* error codes */
+#define SSFN_OK 0 /* success */
+#define SSFN_ERR_ALLOC -1 /* allocation error */
+#define SSFN_ERR_BADFILE -2 /* bad SSFN file format */
+#define SSFN_ERR_NOFACE -3 /* no font face selected */
+#define SSFN_ERR_INVINP -4 /* invalid input */
+#define SSFN_ERR_BADSTYLE -5 /* bad style */
+#define SSFN_ERR_BADSIZE -6 /* bad size */
+#define SSFN_ERR_NOGLYPH -7 /* glyph (or kerning info) not found */
+
+#define SSFN_SIZE_MAX 192 /* biggest size we can render */
+#define SSFN_ITALIC_DIV 4 /* italic angle divisor, glyph top side pushed width / this pixels */
+#define SSFN_PREC 4 /* precision in bits */
+
+/* destination frame buffer context */
+typedef struct {
+ uint8_t *ptr; /* pointer to the buffer */
+ int w; /* width (positive: ARGB, negative: ABGR pixels) */
+ int h; /* height */
+ uint16_t p; /* pitch, bytes per line */
+ int x; /* cursor x */
+ int y; /* cursor y */
+ uint32_t fg; /* foreground color */
+ uint32_t bg; /* background color */
+} ssfn_buf_t;
+
+/* cached bitmap struct */
+#define SSFN_DATA_MAX 65536
+typedef struct {
+ uint16_t p; /* data buffer pitch, bytes per line */
+ uint8_t h; /* data buffer height */
+ uint8_t o; /* overlap of glyph, scaled to size */
+ uint8_t x; /* advance x, scaled to size */
+ uint8_t y; /* advance y, scaled to size */
+ uint8_t a; /* ascender, scaled to size */
+ uint8_t d; /* descender, scaled to size */
+ uint8_t data[SSFN_DATA_MAX]; /* data buffer */
+} ssfn_glyph_t;
+
+/* character metrics */
+typedef struct {
+ uint8_t t; /* type and overlap */
+ uint8_t n; /* number of fragments */
+ uint8_t w; /* width */
+ uint8_t h; /* height */
+ uint8_t x; /* advance x */
+ uint8_t y; /* advance y */
+} ssfn_chr_t;
+
+#ifdef SSFN_PROFILING
+#include
+#include
+#endif
+
+/* renderer context */
+typedef struct {
+#ifdef SSFN_MAXLINES
+ const ssfn_font_t *fnt[5][16]; /* static font registry */
+#else
+ const ssfn_font_t **fnt[5]; /* dynamic font registry */
+#endif
+ const ssfn_font_t *s; /* explicitly selected font */
+ const ssfn_font_t *f; /* font selected by best match */
+ ssfn_glyph_t ga; /* glyph sketch area */
+ ssfn_glyph_t *g; /* current glyph pointer */
+#ifdef SSFN_MAXLINES
+ uint16_t p[SSFN_MAXLINES*2];
+#else
+ ssfn_glyph_t ***c[17]; /* glyph cache */
+ uint16_t *p;
+ char **bufs; /* allocated extra buffers */
+#endif
+ ssfn_chr_t *rc; /* pointer to current character */
+ int numbuf, lenbuf, np, ap, ox, oy, ax;
+ int mx, my, lx, ly; /* move to coordinates, last coordinates */
+ int len[5]; /* number of fonts in registry */
+ int family; /* required family */
+ int style; /* required style */
+ int size; /* required size */
+ int line; /* calculate line height */
+#ifdef SSFN_PROFILING
+ uint64_t lookup, raster, blit, kern;/* profiling accumulators */
+#endif
+} ssfn_t;
+
+/***** API function protoypes *****/
+
+uint32_t ssfn_utf8(char **str); /* decode UTF-8 sequence */
+
+/* normal renderer */
+int ssfn_load(ssfn_t *ctx, const void *data); /* add an SSFN to context */
+int ssfn_select(ssfn_t *ctx, int family, const char *name, int style, int size); /* select font to use */
+int ssfn_render(ssfn_t *ctx, ssfn_buf_t *dst, const char *str); /* render a glyph to a pixel buffer */
+int ssfn_bbox(ssfn_t *ctx, const char *str, int *w, int *h, int *left, int *top); /* get bounding box */
+ssfn_buf_t *ssfn_text(ssfn_t *ctx, const char *str, unsigned int fg); /* renders text to a newly allocated buffer */
+int ssfn_mem(ssfn_t *ctx); /* return how much memory is used */
+void ssfn_free(ssfn_t *ctx); /* free context */
+#define ssfn_error(err) (err<0&&err>=-7?ssfn_errstr[-err]:"Unknown error") /* return string for error code */
+extern const char *ssfn_errstr[];
+
+/* simple renderer */
+extern ssfn_font_t *ssfn_src; /* font buffer */
+extern ssfn_buf_t ssfn_dst; /* destination frame buffer */
+int ssfn_putc(uint32_t unicode); /* render console bitmap font */
+
+/***** renderer implementations *****/
+
+/*** these go for both renderers ***/
+#if (defined(SSFN_IMPLEMENTATION) || defined(SSFN_CONSOLEBITMAP_PALETTE) || \
+ defined(SSFN_CONSOLEBITMAP_HICOLOR) || defined(SSFN_CONSOLEBITMAP_TRUECOLOR)) && !defined(SSFN_COMMON)
+#define SSFN_COMMON
+
+/**
+ * Error code strings
+ */
+const char *ssfn_errstr[] = { "",
+ "Memory allocation error",
+ "Bad file format",
+ "No font face found",
+ "Invalid input value",
+ "Invalid style",
+ "Invalid size",
+ "Glyph not found"
+};
+
+/**
+ * Decode an UTF-8 multibyte, advance string pointer and return UNICODE. Watch out, no input checks
+ *
+ * @param **s pointer to an UTF-8 string pointer
+ * @return unicode, and *s moved to next multibyte sequence
+ */
+uint32_t ssfn_utf8(char **s)
+{
+ uint32_t c = **s;
+
+ if((**s & 128) != 0) {
+ if(!(**s & 32)) { c = ((**s & 0x1F)<<6)|(*(*s+1) & 0x3F); *s += 1; } else
+ if(!(**s & 16)) { c = ((**s & 0xF)<<12)|((*(*s+1) & 0x3F)<<6)|(*(*s+2) & 0x3F); *s += 2; } else
+ if(!(**s & 8)) { c = ((**s & 0x7)<<18)|((*(*s+1) & 0x3F)<<12)|((*(*s+2) & 0x3F)<<6)|(*(*s+3) & 0x3F); *s += 3; }
+ else c = 0;
+ }
+ (*s)++;
+ return c;
+}
+#endif
+
+#ifdef SSFN_IMPLEMENTATION
+/*** normal renderer (ca. 28k, fully featured with error checking) ***/
+
+// # ifndef NULL
+// # define NULL (void*)0
+// # endif
+// # ifndef size_t
+// typedef __SIZE_TYPE__ size_t;
+// # endif
+// # ifndef inline
+// # define inline __inline__
+// # endif
+
+//#ifndef _STRING_H_
+//extern int memcmp (const void *__s1, const void *__s2, size_t __n) __THROW;
+//extern void *memset (void *__s, int __c, size_t __n) __THROW;
+//#endif
+
+/* Clang does not have built-ins */
+# ifndef SSFN_memcmp
+# ifdef __builtin_memcmp
+# define SSFN_memcmp __builtin_memcmp
+# else
+# ifndef SSFN_MAXLINES
+# define SSFN_memcmp memcmp
+# else
+static int SSFN_memcmp(const void *__s1, const void *__s2, size_t __n)
+{ unsigned char *a = (unsigned char *)__s1, *b = (unsigned char *)__s2;
+ if(__n > 0) { while(__n-- > 0) { if(*a != *b) { return *a - *b; } a++; b++; } } return 0; }
+# endif
+# endif
+# endif
+
+# ifndef SSFN_memset
+# ifdef __builtin_memset
+# define SSFN_memset __builtin_memset
+# else
+# ifndef SSFN_MAXLINES
+# define SSFN_memset memset
+# else
+static void *SSFN_memset(void *__s, int __c, size_t __n)
+{ unsigned char *a = (unsigned char*)__s; if(__n > 0) { while(__n-- > 0) *a++ = __c; } return (unsigned char*)__s; }
+# endif
+# endif
+# endif
+
+# ifndef SSFN_MAXLINES
+
+# ifndef SSFN_realloc
+# ifdef __builtin_realloc
+# define SSFN_realloc __builtin_realloc
+# else
+# define SSFN_realloc realloc
+ extern void *realloc (void *__ptr, size_t __size) __THROW;
+# endif
+# endif
+
+# ifndef SSFN_free
+# ifdef __builtin_free
+# define SSFN_free __builtin_free
+# else
+# define SSFN_free free
+ extern void free (void *p) __THROW;
+# endif
+# endif
+
+# endif /* if !SSFN_MAXLINES */
+
+/*** Private functions ***/
+
+/* parse character table */
+static uint8_t *_ssfn_c(const ssfn_font_t *font, const char *str, int *len, uint32_t *unicode)
+{
+ uint32_t i, j, u = 0xffffffff;
+ uint16_t *l;
+ uint8_t *ptr, *s;
+
+ *len = 0; *unicode = 0;
+ if(!font || !font->characters_offs || !str || !*str) return NULL;
+
+ if(font->ligature_offs) {
+ for(l = (uint16_t*)((uint8_t*)font + font->ligature_offs), i = 0; l[i] && u == 0xffffffff; i++) {
+ for(ptr = (uint8_t*)font + l[i], s = (uint8_t*)str; *ptr && *ptr == *s; ptr++, s++);
+ if(!*ptr) { u = SSFN_LIG_FIRST + i; break; }
+ }
+ }
+ if(u == 0xffffffff) {
+ /* inline ssfn_utf8 to workaround -O2 bug in gcc 11.1 */
+ s = (uint8_t*)str; u = *s;
+ if((*s & 128) != 0) {
+ if(!(*s & 32)) { u = ((*s & 0x1F)<<6)|(*(s+1) & 0x3F); s++; } else
+ if(!(*s & 16)) { u = ((*s & 0xF)<<12)|((*(s+1) & 0x3F)<<6)|(*(s+2) & 0x3F); s += 2; } else
+ if(!(*s & 8)) { u = ((*s & 0x7)<<18)|((*(s+1) & 0x3F)<<12)|((*(s+2) & 0x3F)<<6)|(*(s+3) & 0x3F); s += 3; }
+ else u = 0;
+ }
+ s++;
+ }
+ *len = (int)(s - (uint8_t*)str);
+ *unicode = u;
+ for(ptr = (uint8_t*)font + font->characters_offs, i = 0; i < 0x110000; i++) {
+ if(ptr[0] == 0xFF) { i += 65535; ptr++; }
+ else if((ptr[0] & 0xC0) == 0xC0) { j = (((ptr[0] & 0x3F) << 8) | ptr[1]); i += j; ptr += 2; }
+ else if((ptr[0] & 0xC0) == 0x80) { j = (ptr[0] & 0x3F); i += j; ptr++; }
+ else {
+ if(i == u) return ptr;
+ ptr += 6 + ptr[1] * (ptr[0] & 0x40 ? 6 : 5);
+ }
+ }
+ return NULL;
+}
+
+/* add a line to contour */
+static void _ssfn_l(ssfn_t *ctx, int p, int h, int x, int y)
+{
+ if(x < 0 || y < 0 || x >= p || y >= h || (
+ ((ctx->lx + (1 << (SSFN_PREC-1))) >> SSFN_PREC) == ((x + (1 << (SSFN_PREC-1))) >> SSFN_PREC) &&
+ ((ctx->ly + (1 << (SSFN_PREC-1))) >> SSFN_PREC) == ((y + (1 << (SSFN_PREC-1))) >> SSFN_PREC))) return;
+#ifdef SSFN_MAXLINES
+ if(ctx->np >= SSFN_MAXLINES*2-2) return;
+#else
+ if(ctx->ap <= ctx->np) {
+ ctx->ap = ctx->np + 512;
+ ctx->p = (uint16_t*)SSFN_realloc(ctx->p, ctx->ap * sizeof(uint16_t));
+ if(!ctx->p) { ctx->ap = ctx->np = 0; return; }
+ }
+#endif
+ if(!ctx->np) {
+ ctx->p[0] = ctx->mx;
+ ctx->p[1] = ctx->my;
+ ctx->np += 2;
+ }
+ ctx->p[ctx->np+0] = x;
+ ctx->p[ctx->np+1] = y;
+ ctx->np += 2;
+ ctx->lx = x; ctx->ly = y;
+}
+
+/* add a Bezier curve to contour */
+static void _ssfn_b(ssfn_t *ctx, int p,int h, int x0,int y0, int x1,int y1, int x2,int y2, int x3,int y3, int l)
+{
+ int m0x, m0y, m1x, m1y, m2x, m2y, m3x, m3y, m4x, m4y,m5x, m5y;
+ if(l<4 && (x0!=x3 || y0!=y3)) {
+ m0x = ((x1-x0)/2) + x0; m0y = ((y1-y0)/2) + y0;
+ m1x = ((x2-x1)/2) + x1; m1y = ((y2-y1)/2) + y1;
+ m2x = ((x3-x2)/2) + x2; m2y = ((y3-y2)/2) + y2;
+ m3x = ((m1x-m0x)/2) + m0x; m3y = ((m1y-m0y)/2) + m0y;
+ m4x = ((m2x-m1x)/2) + m1x; m4y = ((m2y-m1y)/2) + m1y;
+ m5x = ((m4x-m3x)/2) + m3x; m5y = ((m4y-m3y)/2) + m3y;
+ _ssfn_b(ctx, p,h, x0,y0, m0x,m0y, m3x,m3y, m5x,m5y, l+1);
+ _ssfn_b(ctx, p,h, m5x,m5y, m4x,m4y, m2x,m2y, x3,y3, l+1);
+ }
+ if(l) _ssfn_l(ctx, p,h, x3, y3);
+}
+
+#ifndef SSFN_MAXLINES
+static void _ssfn_fc(ssfn_t *ctx)
+{
+ int i, j, k;
+ if(!ctx) return;
+ for(k = 0; k <= 16; k++)
+ if(ctx->c[k]) {
+ for(j = 0; j < 256; j++)
+ if(ctx->c[k][j]) {
+ for(i = 0; i < 256; i++)
+ if(ctx->c[k][j][i]) SSFN_free(ctx->c[k][j][i]);
+ SSFN_free(ctx->c[k][j]);
+ }
+ SSFN_free(ctx->c[k]);
+ ctx->c[k] = NULL;
+ }
+}
+
+/*
+ * gzip deflate uncompressor from stb_image.h with minor modifications to reduce dependency
+ * stb_image - v2.23 - public domain image loader - http://nothings.org/stb_image.h
+ */
+#define SSFN__ZFAST_BITS 9
+#define SSFN__ZFAST_MASK ((1 << SSFN__ZFAST_BITS) - 1)
+
+typedef struct
+{
+ uint16_t fast[1 << SSFN__ZFAST_BITS];
+ uint16_t firstcode[16];
+ int maxcode[17];
+ uint16_t firstsymbol[16];
+ unsigned char size[288];
+ uint16_t value[288];
+} _ssfn__zhuffman;
+
+inline static int _ssfn__bitreverse16(int n)
+{
+ n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1);
+ n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2);
+ n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4);
+ n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8);
+ return n;
+}
+
+inline static int _ssfn__bit_reverse(int v, int bits)
+{
+ return _ssfn__bitreverse16(v) >> (16-bits);
+}
+
+static int _ssfn__zbuild_huffman(_ssfn__zhuffman *z, unsigned char *sizelist, int num)
+{
+ int i,k=0;
+ int code, next_code[16], sizes[17];
+
+ SSFN_memset(sizes, 0, sizeof(sizes));
+ SSFN_memset(z->fast, 0, sizeof(z->fast));
+ for (i=0; i < num; ++i)
+ ++sizes[sizelist[i]];
+ sizes[0] = 0;
+ for (i=1; i < 16; ++i)
+ if (sizes[i] > (1 << i))
+ return 0;
+ code = 0;
+ for (i=1; i < 16; ++i) {
+ next_code[i] = code;
+ z->firstcode[i] = (uint16_t) code;
+ z->firstsymbol[i] = (uint16_t) k;
+ code = (code + sizes[i]);
+ if (sizes[i])
+ if (code-1 >= (1 << i)) return 0;
+ z->maxcode[i] = code << (16-i);
+ code <<= 1;
+ k += sizes[i];
+ }
+ z->maxcode[16] = 0x10000;
+ for (i=0; i < num; ++i) {
+ int s = sizelist[i];
+ if (s) {
+ int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s];
+ uint16_t fastv = (uint16_t) ((s << 9) | i);
+ z->size [c] = (unsigned char) s;
+ z->value[c] = (uint16_t) i;
+ if (s <= SSFN__ZFAST_BITS) {
+ int j = _ssfn__bit_reverse(next_code[s],s);
+ while (j < (1 << SSFN__ZFAST_BITS)) {
+ z->fast[j] = fastv;
+ j += (1 << s);
+ }
+ }
+ ++next_code[s];
+ }
+ }
+ return 1;
+}
+
+typedef struct
+{
+ unsigned char *zbuffer;
+ int num_bits;
+ uint32_t code_buffer;
+
+ char *zout;
+ char *zout_start;
+ char *zout_end;
+
+ _ssfn__zhuffman z_length, z_distance;
+} _ssfn__zbuf;
+
+inline static unsigned char _ssfn__zget8(_ssfn__zbuf *z)
+{
+ return *z->zbuffer++;
+}
+
+static void _ssfn__fill_bits(_ssfn__zbuf *z)
+{
+ do {
+ z->code_buffer |= (unsigned int) _ssfn__zget8(z) << z->num_bits;
+ z->num_bits += 8;
+ } while (z->num_bits <= 24);
+}
+
+inline static unsigned int _ssfn__zreceive(_ssfn__zbuf *z, int n)
+{
+ unsigned int k;
+ if (z->num_bits < n) _ssfn__fill_bits(z);
+ k = z->code_buffer & ((1 << n) - 1);
+ z->code_buffer >>= n;
+ z->num_bits -= n;
+ return k;
+}
+
+static int _ssfn__zhuffman_decode_slowpath(_ssfn__zbuf *a, _ssfn__zhuffman *z)
+{
+ int b,s,k;
+ k = _ssfn__bit_reverse(a->code_buffer, 16);
+ for (s=SSFN__ZFAST_BITS+1; ; ++s)
+ if (k < z->maxcode[s])
+ break;
+ if (s == 16) return -1;
+ b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s];
+ a->code_buffer >>= s;
+ a->num_bits -= s;
+ return z->value[b];
+}
+
+inline static int _ssfn__zhuffman_decode(_ssfn__zbuf *a, _ssfn__zhuffman *z)
+{
+ int b,s;
+ if (a->num_bits < 16) _ssfn__fill_bits(a);
+ b = z->fast[a->code_buffer & SSFN__ZFAST_MASK];
+ if (b) {
+ s = b >> 9;
+ a->code_buffer >>= s;
+ a->num_bits -= s;
+ return b & 511;
+ }
+ return _ssfn__zhuffman_decode_slowpath(a, z);
+}
+
+static int _ssfn__zexpand(_ssfn__zbuf *z, char *zout)
+{
+ char *q;
+ unsigned int cur, limit;
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wuse-after-free"
+#endif
+ z->zout = zout; cur = (unsigned int) (z->zout - z->zout_start); limit = (unsigned int) (z->zout_end - z->zout_start);
+ if(limit == 8) { if(z->zout_start[0] != 'S' || z->zout_start[1] != 'F' || z->zout_start[2] != 'N') return 0; limit = *((uint32_t*)&z->zout_start[4]); } else return 0;
+ q = (char *) SSFN_realloc(z->zout_start, limit);
+ if (q == NULL) return 0;
+ z->zout_start = q; z->zout = q + cur; z->zout_end = q + limit;
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+ return 1;
+}
+
+static int _ssfn__zlength_base[31]={3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0};
+static int _ssfn__zlength_extra[31]={0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0};
+static int _ssfn__zdist_base[32]={1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0};
+static int _ssfn__zdist_extra[32]={0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+static int _ssfn__parse_huffman_block(_ssfn__zbuf *a)
+{
+ char *zout = a->zout;
+ for(;;) {
+ int z = _ssfn__zhuffman_decode(a, &a->z_length);
+ if (z < 256) {
+ if (z < 0) return 0;
+ if (zout >= a->zout_end) { if (!_ssfn__zexpand(a, zout)) return 0; zout = a->zout; }
+ *zout++ = (char) z;
+ } else {
+ unsigned char *p;
+ int len,dist;
+ if (z == 256) { a->zout = zout; return 1; }
+ z -= 257;
+ len = _ssfn__zlength_base[z];
+ if (_ssfn__zlength_extra[z]) len += _ssfn__zreceive(a, _ssfn__zlength_extra[z]);
+ z = _ssfn__zhuffman_decode(a, &a->z_distance);
+ if (z < 0) return 0;
+ dist = _ssfn__zdist_base[z];
+ if (_ssfn__zdist_extra[z]) dist += _ssfn__zreceive(a, _ssfn__zdist_extra[z]);
+ if (zout - a->zout_start < dist) return 0;
+ if (zout + len > a->zout_end) {
+ if (!_ssfn__zexpand(a, zout)) return 0;
+ zout = a->zout;
+ }
+ p = (unsigned char *) (zout - dist);
+ if (dist == 1) {unsigned char v = *p;if (len) { do *zout++ = v; while (--len); }
+ } else { if (len) { do *zout++ = *p++; while (--len); } }
+ }
+ }
+}
+
+static int _ssfn__compute_huffman_codes(_ssfn__zbuf *a)
+{
+ static unsigned char length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };
+ _ssfn__zhuffman z_codelength;
+ unsigned char lencodes[286+32+137];
+ unsigned char codelength_sizes[19];
+ int i,n;
+
+ int hlit = _ssfn__zreceive(a,5) + 257;
+ int hdist = _ssfn__zreceive(a,5) + 1;
+ int hclen = _ssfn__zreceive(a,4) + 4;
+ int ntot = hlit + hdist;
+
+ SSFN_memset(codelength_sizes, 0, sizeof(codelength_sizes));
+ for (i=0; i < hclen; ++i) {
+ int s = _ssfn__zreceive(a,3);
+ codelength_sizes[length_dezigzag[i]] = (unsigned char) s;
+ }
+ if (!_ssfn__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0;
+
+ n = 0;
+ while (n < ntot) {
+ int c = _ssfn__zhuffman_decode(a, &z_codelength);
+ if (c < 0 || c >= 19) return 0;
+ if (c < 16)
+ lencodes[n++] = (unsigned char) c;
+ else {
+ unsigned char fill = 0;
+ if (c == 16) {
+ c = _ssfn__zreceive(a,2)+3;
+ if (n == 0) return 0;
+ fill = lencodes[n-1];
+ } else
+ if (c == 17) c = _ssfn__zreceive(a,3)+3;
+ else { c = _ssfn__zreceive(a,7)+11; }
+ if (ntot - n < c) return 0;
+ SSFN_memset(lencodes+n, fill, c);
+ n += c;
+ }
+ }
+ if (n != ntot) return 0;
+ if (!_ssfn__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0;
+ if (!_ssfn__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0;
+ return 1;
+}
+
+inline static int _ssfn__parse_uncompressed_block(_ssfn__zbuf *a)
+{
+ unsigned char header[4];
+ int len,nlen,k;
+ if (a->num_bits & 7)
+ _ssfn__zreceive(a, a->num_bits & 7);
+ k = 0;
+ while (a->num_bits > 0) {
+ header[k++] = (unsigned char) (a->code_buffer & 255);
+ a->code_buffer >>= 8;
+ a->num_bits -= 8;
+ }
+ while (k < 4)
+ header[k++] = _ssfn__zget8(a);
+ len = header[1] * 256 + header[0];
+ nlen = header[3] * 256 + header[2];
+ if (nlen != (len ^ 0xffff)) return 0;
+ if (a->zout + len > a->zout_end)
+ if (!_ssfn__zexpand(a, a->zout)) return 0;
+ for(k = 0; k < len; k++)
+ a->zout[k] = a->zbuffer[k];
+ a->zbuffer += len;
+ a->zout += len;
+ return 1;
+}
+
+static unsigned char _ssfn__zdefault_length[288], _ssfn__zdefault_distance[32];
+static void _ssfn__init_zdefaults(void)
+{
+ int i;
+ for (i=0; i <= 143; ++i) _ssfn__zdefault_length[i] = 8;
+ for ( ; i <= 255; ++i) _ssfn__zdefault_length[i] = 9;
+ for ( ; i <= 279; ++i) _ssfn__zdefault_length[i] = 7;
+ for ( ; i <= 287; ++i) _ssfn__zdefault_length[i] = 8;
+
+ for (i=0; i <= 31; ++i) _ssfn__zdefault_distance[i] = 5;
+}
+
+static int _ssfn__parse_zlib(_ssfn__zbuf *a)
+{
+ int fin, type;
+ a->num_bits = 0;
+ a->code_buffer = 0;
+ do {
+ fin = _ssfn__zreceive(a,1);
+ type = _ssfn__zreceive(a,2);
+ if (type == 0) { if (!_ssfn__parse_uncompressed_block(a)) return 0; }
+ else if (type == 3) { return 0; }
+ else {
+ if (type == 1) {
+ if (!_ssfn__zbuild_huffman(&a->z_length , _ssfn__zdefault_length , 288)) return 0;
+ if (!_ssfn__zbuild_huffman(&a->z_distance, _ssfn__zdefault_distance, 32)) return 0;
+ } else {
+ if (!_ssfn__compute_huffman_codes(a)) return 0;
+ }
+ if (!_ssfn__parse_huffman_block(a)) return 0;
+ }
+ } while (!fin);
+ return 1;
+}
+
+char *_ssfn_zlib_decode(const char *buffer)
+{
+ _ssfn__zbuf a;
+ char *p = (char *) SSFN_realloc(NULL, 8);
+ if (p == NULL) return NULL;
+ a.zbuffer = (unsigned char *) buffer;
+ a.zout_start = p; a.zout = p; a.zout_end = p + 8;
+ _ssfn__init_zdefaults();
+ if (_ssfn__parse_zlib(&a)) { return a.zout_start; } else { SSFN_free(a.zout_start); return NULL; }
+}
+#endif /* if !SSFN_MAXLINES */
+
+/*** Public API implementation ***/
+
+/**
+ * Load a font or font collection into renderer context
+ *
+ * @param ctx rendering context
+ * @param font SSFN font or font collection in memory
+ * @return error code
+ */
+int ssfn_load(ssfn_t *ctx, const void *data)
+{
+ const ssfn_font_t *font = (const ssfn_font_t *)data;
+ ssfn_font_t *fnt, *end;
+ int family;
+#ifndef SSFN_MAXLINES
+ uint8_t c, r, *ptr = (uint8_t *)font;
+#endif
+ if(!ctx || !font)
+ return SSFN_ERR_INVINP;
+ if(((uint8_t *)font)[0] == 0x1f && ((uint8_t *)font)[1] == 0x8b) {
+#ifdef SSFN_MAXLINES
+ return SSFN_ERR_BADFILE;
+#else
+ ptr += 2;
+ if(*ptr++ != 8) return SSFN_ERR_BADFILE;
+ c = *ptr++; ptr += 6;
+ if(c & 4) { r = *ptr++; r += (*ptr++ << 8); ptr += r; }
+ if(c & 8) { while(*ptr++ != 0); }
+ if(c & 16) { while(*ptr++ != 0); }
+ font = (ssfn_font_t*)_ssfn_zlib_decode((const char*)ptr);
+ if(!font) return SSFN_ERR_BADFILE;
+ ctx->bufs = (char**)SSFN_realloc(ctx->bufs, (ctx->numbuf + 1) * sizeof(char*));
+ if(!ctx->bufs) { ctx->numbuf = 0; return SSFN_ERR_ALLOC; }
+ ctx->bufs[ctx->numbuf++] = (char*)font;
+ ctx->lenbuf += font->size;
+#endif
+ }
+ if(!SSFN_memcmp(font->magic, SSFN_COLLECTION, 4)) {
+ end = (ssfn_font_t*)((uint8_t*)font + font->size);
+ for(fnt = (ssfn_font_t*)((uint8_t*)font + 8); fnt < end && !ssfn_load(ctx, (const void *)fnt);
+ fnt = (ssfn_font_t*)((uint8_t*)fnt + fnt->size));
+ } else {
+ family = SSFN_TYPE_FAMILY(font->type);
+ if(SSFN_memcmp(font->magic, SSFN_MAGIC, 4) || SSFN_memcmp((uint8_t*)font + font->size - 4, SSFN_ENDMAGIC, 4) ||
+ family > SSFN_FAMILY_HAND || font->fragments_offs >= font->size || font->characters_offs >= font->size ||
+ font->ligature_offs >= font->size || font->kerning_offs >= font->size || font->cmap_offs >= font->size ||
+ font->fragments_offs >= font->characters_offs) {
+ return SSFN_ERR_BADFILE;
+ } else {
+ ctx->len[family]++;
+#ifdef SSFN_MAXLINES
+ if(ctx->len[family] > 15) return SSFN_ERR_ALLOC;
+#else
+ ctx->fnt[family] = (const ssfn_font_t**)SSFN_realloc(ctx->fnt[family], ctx->len[family]*sizeof(void*));
+ if(!ctx->fnt[family]) {
+ ctx->len[family] = 0;
+ return SSFN_ERR_ALLOC;
+ } else
+#endif
+ ctx->fnt[family][ctx->len[family]-1] = font;
+ }
+#ifndef SSFN_MAXLINES
+ _ssfn_fc(ctx);
+#endif
+ }
+ return SSFN_OK;
+}
+
+/**
+ * Free renderer context
+ *
+ * @param ctx rendering context
+ */
+void ssfn_free(ssfn_t *ctx)
+{
+#ifndef SSFN_MAXLINES
+ int i;
+#endif
+ if(!ctx) return;
+#ifndef SSFN_MAXLINES
+ _ssfn_fc(ctx);
+ if(ctx->bufs) {
+ for(i = 0; i < ctx->numbuf; i++)
+ if(ctx->bufs[i]) SSFN_free(ctx->bufs[i]);
+ SSFN_free(ctx->bufs);
+ }
+ for(i = 0; i < 5; i++)
+ if(ctx->fnt[i]) SSFN_free(ctx->fnt[i]);
+ if(ctx->p) SSFN_free(ctx->p);
+#endif
+ SSFN_memset(ctx, 0, sizeof(ssfn_t));
+}
+
+/**
+ * Returns how much memory a context consumes
+ *
+ * @param ctx rendering context
+ * @return total memory used by that context in bytes
+ */
+int ssfn_mem(ssfn_t *ctx)
+{
+#ifdef SSFN_MAXLINES
+ return ctx ? sizeof(ssfn_t) : 0;
+#else
+ int i, j, k, ret = sizeof(ssfn_t);
+
+ if(!ctx) return 0;
+ for(i = 0; i < 5; i++) ret += ctx->len[i] * sizeof(ssfn_font_t*);
+ ret += ctx->lenbuf;
+ for(k = 0; k <= 16; k++) {
+ if(ctx->c[k]) {
+ for(j = 0; j < 256; j++)
+ if(ctx->c[k][j]) {
+ for(i = 0; i < 256; i++)
+ if(ctx->c[k][j][i]) ret += 8 + ctx->c[k][j][i]->p * ctx->c[k][j][i]->h;
+ ret += 256 * sizeof(void*);
+ }
+ ret += 256 * sizeof(void*);
+ }
+ }
+ if(ctx->p) ret += ctx->ap * sizeof(uint16_t);
+ return ret;
+#endif
+}
+
+/**
+ * Set up rendering parameters
+ *
+ * @param ctx rendering context
+ * @param family one of SSFN_FAMILY_*
+ * @param name NULL or UTF-8 string if family is SSFN_FAMILY_BYNAME
+ * @param style OR'd values of SSFN_STYLE_*
+ * @param size how big glyph it should render, 8 - 192
+ * @return error code
+ */
+int ssfn_select(ssfn_t *ctx, int family, const char *name, int style, int size)
+{
+ int i, j, l;
+
+ if(!ctx) return SSFN_ERR_INVINP;
+#ifndef SSFN_MAXLINES
+ _ssfn_fc(ctx);
+#endif
+ if((style & ~0x5FFF)) return SSFN_ERR_BADSTYLE;
+ if(size < 8 || size > SSFN_SIZE_MAX) return SSFN_ERR_BADSIZE;
+
+ if(family == SSFN_FAMILY_BYNAME) {
+ if(!name || !name[0]) return SSFN_ERR_INVINP;
+ for(l=0; name[l]; l++);
+ for(i=0; i < 5; i++) {
+ for(j=0; j < ctx->len[i]; j++) {
+ if(!SSFN_memcmp(name, (uint8_t*)&ctx->fnt[i][j]->magic + sizeof(ssfn_font_t), l)) {
+ ctx->s = ctx->fnt[i][j];
+ goto familyfound;
+ }
+ }
+ }
+ return SSFN_ERR_NOFACE;
+ } else {
+ if(family != SSFN_FAMILY_ANY && (family > SSFN_FAMILY_HAND || !ctx->len[family])) return SSFN_ERR_NOFACE;
+ ctx->s = NULL;
+ }
+familyfound:
+ ctx->f = NULL;
+ ctx->family = family;
+ ctx->style = style;
+ ctx->size = size;
+ ctx->line = 0;
+ return SSFN_OK;
+}
+
+/**
+ * Render a glyph to a pixel buffer
+ *
+ * @param ctx rendering context
+ * @param dst destination buffer
+ * @param str pointer to an UTF-8 string
+ * @return number of bytes parsed in str (zero means end of string) or error code
+ */
+
+int ssfn_render(ssfn_t *ctx, ssfn_buf_t *dst, const char *str)
+{
+ ssfn_font_t **fl;
+ uint8_t *ptr = NULL, *frg, *end, *tmp, color, ci = 0, cb = 0, cs, dec[65536];
+ uint16_t r[640];
+ uint32_t unicode, P, O, *Op, *Ol;
+ unsigned long int sR, sG, sB, sA;
+ int ret = 0, i, j, k, l, p, m, n, o, s, x, y, w, h, H, a, A, b, B, nr, uix, uax;
+ int ox, oy, y0, y1, Y0, Y1, x0, x1, X0, X1, X2, xs, ys, yp, pc, fB, fG, fR, fA, bB, bG, bR, dB, dG, dR, dA;
+#ifdef SSFN_PROFILING
+ struct timeval tv0, tv1, tvd;
+ gettimeofday(&tv0, NULL);
+#endif
+#define PUTPIXEL O = *Ol;bR = (O >> (16 - cs)) & 0xFF; bG = (O >> 8) & 0xFF; bB = (O >> cs) & 0xFF;\
+ bB += ((fB - bB) * fA) >> 8; bG += ((fG - bG) * fA) >> 8; bR += ((fR - bR) * fA) >> 8;\
+ *Ol = (ctx->style & SSFN_STYLE_A ? O & 0xFF000000 : ((uint32_t)fA << 24)) | (bR << (16 - cs)) | (bG << 8) | (bB << cs);
+
+ if(!ctx || !str) return SSFN_ERR_INVINP;
+ if(!*str) return 0;
+ if(*str == '\r') { dst->x = 0; return 1; }
+ if(*str == '\n') { dst->x = 0; dst->y += ctx->line ? ctx->line : ctx->size; return 1; }
+
+ if(ctx->s) {
+ ctx->f = ctx->s;
+ ptr = _ssfn_c(ctx->f, str, &ret, &unicode);
+ } else {
+ /* find best match */
+ p = ctx->family;
+ ctx->f = NULL;
+again: if(p >= SSFN_FAMILY_BYNAME) { n = 0; m = 4; } else n = m = p;
+ for(; n <= m; n++) {
+ fl = (ssfn_font_t **)ctx->fnt[n];
+ if(ctx->style & 3) {
+ /* check if we have a specific ctx->f for the requested style and size */
+ for(i=0;ilen[n];i++)
+ if(((fl[i]->type>>4) & 3) == (ctx->style & 3) && fl[i]->height == ctx->size &&
+ (ptr = _ssfn_c(fl[i], str, &ret, &unicode))) { ctx->f = fl[i]; break; }
+ /* if not, check if we have the requested size (for bitmap fonts) */
+ if(!ptr)
+ for(i=0;ilen[n];i++)
+ if(fl[i]->height == ctx->size && (ptr = _ssfn_c(fl[i], str, &ret, &unicode))) { ctx->f = fl[i]; break; }
+ /* if neither size+style nor size matched, look for style match */
+ if(!ptr)
+ for(i=0;ilen[n];i++)
+ if(((fl[i]->type>>4) & 3) == (ctx->style & 3) && (ptr = _ssfn_c(fl[i], str, &ret, &unicode)))
+ { ctx->f = fl[i]; break; }
+ /* if bold italic was requested, check if we have at least bold or italic */
+ if(!ptr && (ctx->style & 3) == 3)
+ for(i=0;ilen[n];i++)
+ if(((fl[i]->type>>4) & 3) && (ptr = _ssfn_c(fl[i], str, &ret, &unicode))) { ctx->f = fl[i]; break; }
+ }
+ /* last resort, get the first ctx->f which has a glyph for this multibyte, no matter style */
+ if(!ptr) {
+ for(i=0;ilen[n];i++)
+ if((ptr = _ssfn_c(fl[i], str, &ret, &unicode))) { ctx->f = fl[i]; break; }
+ }
+ }
+ /* if glyph still not found, try any family group */
+ if(!ptr && p != SSFN_FAMILY_ANY) { p = SSFN_FAMILY_ANY; goto again; }
+ }
+ if(!ptr) {
+ if(ctx->style & SSFN_STYLE_NODEFGLYPH) return SSFN_ERR_NOGLYPH;
+ else {
+ unicode = 0;
+ if(ctx->family >= SSFN_FAMILY_BYNAME) { n = 0; m = 4; } else n = m = ctx->family;
+ for(; n <= m && !ptr; n++)
+ if(ctx->len[n] && ctx->fnt[n][0] && !(*((uint8_t*)ctx->fnt[n][0] + ctx->fnt[n][0]->characters_offs) & 0x80))
+ { ctx->f = ctx->fnt[n][0]; ptr = (uint8_t*)ctx->f + ctx->f->characters_offs; }
+ }
+ if(!ptr) return SSFN_ERR_NOGLYPH;
+ }
+ if(!ctx->f || !ctx->f->height || !ctx->size) return SSFN_ERR_NOFACE;
+ if((unicode >> 16) > 0x10) return SSFN_ERR_INVINP;
+ ctx->rc = (ssfn_chr_t*)ptr; ptr += sizeof(ssfn_chr_t);
+ H = (ctx->style & SSFN_STYLE_ABS_SIZE) || SSFN_TYPE_FAMILY(ctx->f->type) == SSFN_FAMILY_MONOSPACE || !ctx->f->baseline ?
+ ctx->size : ctx->size * ctx->f->height / ctx->f->baseline;
+
+#ifdef SSFN_PROFILING
+ gettimeofday(&tv1, NULL); tvd.tv_sec = tv1.tv_sec - tv0.tv_sec; tvd.tv_usec = tv1.tv_usec - tv0.tv_usec;
+ if(tvd.tv_usec < 0) { tvd.tv_sec--; tvd.tv_usec += 1000000L; }
+ ctx->lookup += tvd.tv_sec * 1000000L + tvd.tv_usec;
+ memcpy(&tv0, &tv1, sizeof(struct timeval));
+#endif
+ /* render glyph into cache */
+#ifndef SSFN_MAXLINES
+ if(!(ctx->style & SSFN_STYLE_NOCACHE) && ctx->c[unicode >> 16] && ctx->c[unicode >> 16][(unicode >> 8) & 0xFF] &&
+ ctx->c[unicode >> 16][(unicode >> 8) & 0xFF][unicode & 0xFF]) {
+ ctx->g = ctx->c[unicode >> 16][(unicode >> 8) & 0xFF][unicode & 0xFF];
+ } else
+#endif
+ {
+ h = ctx->style & SSFN_STYLE_NOAA ? H : (ctx->size > ctx->f->height ? (ctx->size + 4) & ~3 : ctx->f->height);
+ ci = (ctx->style & SSFN_STYLE_ITALIC) && !(SSFN_TYPE_STYLE(ctx->f->type) & SSFN_STYLE_ITALIC);
+ cb = (ctx->style & SSFN_STYLE_BOLD) && !(SSFN_TYPE_STYLE(ctx->f->type) & SSFN_STYLE_BOLD) ? (ctx->f->height+64)>>6 : 0;
+ w = (ctx->rc->w * h + ctx->f->height - 1) / ctx->f->height;
+ if(w > SSFN_SIZE_MAX) { h = h * SSFN_SIZE_MAX / w; w = SSFN_SIZE_MAX; }
+ p = w + (ci ? h / SSFN_ITALIC_DIV : 0) + cb;
+ /* failsafe, should never happen */
+ if(p * h >= SSFN_DATA_MAX) return SSFN_ERR_BADSIZE;
+#ifndef SSFN_MAXLINES
+ if(!(ctx->style & SSFN_STYLE_NOCACHE)) {
+ if(!ctx->c[unicode >> 16]) {
+ ctx->c[unicode >> 16] = (ssfn_glyph_t***)SSFN_realloc(NULL, 256 * sizeof(void*));
+ if(!ctx->c[unicode >> 16]) return SSFN_ERR_ALLOC;
+ SSFN_memset(ctx->c[unicode >> 16], 0, 256 * sizeof(void*));
+ }
+ if(!ctx->c[unicode >> 16][(unicode >> 8) & 0xFF]) {
+ ctx->c[unicode >> 16][(unicode >> 8) & 0xFF] = (ssfn_glyph_t**)SSFN_realloc(NULL, 256 * sizeof(void*));
+ if(!ctx->c[unicode >> 16][(unicode >> 8) & 0xFF]) return SSFN_ERR_ALLOC;
+ SSFN_memset(ctx->c[unicode >> 16][(unicode >> 8) & 0xFF], 0, 256 * sizeof(void*));
+ }
+ ctx->g = ctx->c[unicode >> 16][(unicode >> 8) & 0xFF][unicode & 0xFF] = (ssfn_glyph_t*)SSFN_realloc(NULL, p * h + 8);
+ if(!ctx->c[unicode >> 16][(unicode >> 8) & 0xFF][unicode & 0xFF]) return SSFN_ERR_ALLOC;
+ } else
+#endif
+ ctx->g = &ctx->ga;
+ x = (ctx->rc->x > 0 && ci ? (ctx->f->height - ctx->f->baseline) * h / SSFN_ITALIC_DIV / ctx->f->height : 0);
+ ctx->g->p = p;
+ ctx->g->h = h;
+ ctx->g->x = (ctx->rc->x + x > 255 ? 255 : ctx->rc->x + x);
+ ctx->g->y = ctx->rc->y;
+ ctx->g->o = (ctx->rc->t & 0x3F) + x;
+ SSFN_memset(&ctx->g->data, 0xFF, p * h);
+ color = 0xFE; ctx->g->a = ctx->g->d = 0;
+ for(n = 0; n < ctx->rc->n; n++) {
+ if(ptr[0] == 255 && ptr[1] == 255) { color = ptr[2]; ptr += ctx->rc->t & 0x40 ? 6 : 5; continue; }
+ x = ((ptr[0] + cb) << SSFN_PREC) * h / ctx->f->height; y = (ptr[1] << SSFN_PREC) * h / ctx->f->height;
+ if(ctx->rc->t & 0x40) { m = (ptr[5] << 24) | (ptr[4] << 16) | (ptr[3] << 8) | ptr[2]; ptr += 6; }
+ else { m = (ptr[4] << 16) | (ptr[3] << 8) | ptr[2]; ptr += 5; }
+ frg = (uint8_t*)ctx->f + m;
+ if(!(frg[0] & 0x80)) {
+ /* contour */
+ j = (frg[0] & 0x3F);
+ if(frg[0] & 0x40) { j <<= 8; j |= frg[1]; frg++; }
+ j++; frg++; tmp = frg; frg += (j+3)/4; ctx->np = 0;
+ for(i = 0; i < j; i++) {
+ k = (frg[0] << SSFN_PREC) * h / ctx->f->height + x; m = (frg[1] << SSFN_PREC) * h / ctx->f->height + y;
+ switch((tmp[i >> 2] >> ((i & 3) << 1)) & 3) {
+ case SSFN_CONTOUR_MOVE: ctx->mx = ctx->lx = k; ctx->my = ctx->ly = m; frg += 2; break;
+ case SSFN_CONTOUR_LINE: _ssfn_l(ctx, p << SSFN_PREC, h << SSFN_PREC, k, m); frg += 2; break;
+ case SSFN_CONTOUR_QUAD:
+ a = (frg[2] << SSFN_PREC) * h / ctx->f->height + x; A = (frg[3] << SSFN_PREC) * h / ctx->f->height + y;
+ _ssfn_b(ctx, p << SSFN_PREC,h << SSFN_PREC, ctx->lx,ctx->ly, ((a-ctx->lx)/2)+ctx->lx,
+ ((A-ctx->ly)/2)+ctx->ly, ((k-a)/2)+a,((A-m)/2)+m, k,m, 0);
+ frg += 4;
+ break;
+ case SSFN_CONTOUR_CUBIC:
+ a = (frg[2] << SSFN_PREC) * h / ctx->f->height + x; A = (frg[3] << SSFN_PREC) * h / ctx->f->height + y;
+ b = (frg[4] << SSFN_PREC) * h / ctx->f->height + x; B = (frg[5] << SSFN_PREC) * h / ctx->f->height + y;
+ _ssfn_b(ctx, p << SSFN_PREC,h << SSFN_PREC, ctx->lx,ctx->ly, a,A, b,B, k,m, 0);
+ frg += 6;
+ break;
+ }
+ }
+ /* close path */
+ if(ctx->mx != ctx->lx || ctx->my != ctx->ly) { ctx->p[ctx->np+0] = ctx->mx; ctx->p[ctx->np+1] = ctx->my; ctx->np += 2; }
+ /* add rasterized vector layers to cached glyph */
+ if(ctx->np > 4) {
+ for(b = A = B = o = 0; b < h; b++, B += p) {
+ a = b << SSFN_PREC;
+ for(nr = 0, i = 0; i < ctx->np - 3; i += 2) {
+ if( (ctx->p[i+1] < a && ctx->p[i+3] >= a) ||
+ (ctx->p[i+3] < a && ctx->p[i+1] >= a)) {
+ if((ctx->p[i+1] >> SSFN_PREC) == (ctx->p[i+3] >> SSFN_PREC))
+ x = (((int)ctx->p[i]+(int)ctx->p[i+2])>>1);
+ else
+ x = ((int)ctx->p[i]) + ((a - (int)ctx->p[i+1])*
+ ((int)ctx->p[i+2] - (int)ctx->p[i])/
+ ((int)ctx->p[i+3] - (int)ctx->p[i+1]));
+ x >>= SSFN_PREC;
+ if(ci) x += (h - b) / SSFN_ITALIC_DIV;
+ if(cb && !o) {
+ if(ctx->g->data[B + x] != color) { o = -cb; A = cb; }
+ else { o = cb; A = -cb; }
+ }
+ for(k = 0; k < nr && x > r[k]; k++);
+ for(l = nr; l > k; l--) r[l] = r[l-1];
+ r[k] = x;
+ nr++;
+ }
+ }
+ if(nr > 1 && nr & 1) { r[nr - 2] = r[nr - 1]; nr--; }
+ if(nr) {
+ if(ctx->g->d < y + b) ctx->g->d = y + b;
+ for(i = 0; i < nr - 1; i += 2) {
+ l = r[i] + o; m = r[i + 1] + A;
+ if(l < 0) l = 0;
+ if(m > p) m = p;
+ if(i > 0 && l < r[i - 1] + A) l = r[i - 1] + A;
+ for(; l < m; l++)
+ ctx->g->data[B + l] = ctx->g->data[B + l] == color ? 0xFF : color;
+ }
+ }
+ }
+ }
+ } else if((frg[0] & 0x60) == 0x00) {
+ /* bitmap */
+ B = ((frg[0] & 0x1F) + 1) << 3; A = frg[1] + 1; x >>= SSFN_PREC; y >>= SSFN_PREC;
+ b = B * h / ctx->f->height; a = A * h / ctx->f->height;
+ if(ctx->g->d < y + a) ctx->g->d = y + a;
+ frg += 2;
+ for(j = 0; j < a; j++) {
+ k = j * A / a;
+ l = (y + j) * p + x + (ci ? (h - y - j) / SSFN_ITALIC_DIV : 0);
+ for(i = 0; i < b; i++) {
+ m = i * B / b;
+ if(frg[(k * B + m) >> 3] & (1 << (m & 7))) {
+ for(o = 0; o <= cb; o++)
+ ctx->g->data[l + i + o] = color;
+ }
+ }
+ }
+ if(!(ctx->style & (SSFN_STYLE_NOAA|SSFN_STYLE_NOSMOOTH))) {
+ m = color == 0xFD ? 0xFC : 0xFD; o = y * p + p + x;
+ for(k = h; k > ctx->f->height + 4; k -= 2*ctx->f->height) {
+ for(j = 1, l = o; j < a - 1; j++, l += p)
+ for(i = 1; i < b - 1; i++) {
+ if(ctx->g->data[l + i] == 0xFF && (ctx->g->data[l + i - p] == color ||
+ ctx->g->data[l + i + p] == color) && (ctx->g->data[l + i - 1] == color ||
+ ctx->g->data[l + i + 1] == color)) ctx->g->data[l + i] = m;
+ }
+ for(j = 1, l = o; j < a - 1; j++, l += p)
+ for(i = 1; i < b - 1; i++) {
+ if(ctx->g->data[l + i] == m) ctx->g->data[l + i] = color;
+ }
+ }
+ }
+ } else if((frg[0] & 0x60) == 0x20) {
+ /* pixmap */
+ k = (((frg[0] & 0x1F) << 8) | frg[1]) + 1; B = frg[2] + 1; A = frg[3] + 1; x >>= SSFN_PREC; y >>= SSFN_PREC;
+ b = B * h / ctx->f->height; a = A * h / ctx->f->height;
+ if(ctx->g->d < y + a) ctx->g->d = y + a;
+ frg += 4; end = frg + k; i = 0;
+ while(frg < end) {
+ l = ((*frg++) & 0x7F) + 1;
+ if(frg[-1] & 0x80) {
+ while(l--) dec[i++] = *frg;
+ frg++;
+ } else while(l--) dec[i++] = *frg++;
+ }
+ for(j = 0; j < a; j++) {
+ k = j * A / a * B;
+ l = (y + j) * p + x + (ci ? (h - y - j) / SSFN_ITALIC_DIV : 0);
+ for(i = 0; i < b; i++) {
+ m = dec[k + i * B / b];
+ if(m != 0xFF) ctx->g->data[l + i] = m;
+ }
+ }
+ }
+ color = 0xFE;
+ }
+ ctx->g->a = ctx->f->baseline;
+ if(ctx->g->d > ctx->g->a + 1) ctx->g->d -= ctx->g->a + 1; else ctx->g->d = 0;
+#ifdef SSFN_DEBUGGLYPH
+ printf("\nU+%06X size %d p %d h %d base %d under %d overlap %d ascender %d descender %d advance x %d advance y %d cb %d\n",
+ unicode, ctx->size,p,h,ctx->f->baseline,ctx->f->underline,ctx->g->o,ctx->g->a,ctx->g->d,ctx->g->x,ctx->g->y,cb);
+ for(j = 0; j < h; j++) { printf("%3d: ", j); for(i = 0; i < p; i++) { if(ctx->g->data[j*p+i] == 0xFF) printf(j == ctx->g->a ? "_" : "."); else printf("%x", ctx->g->data[j*p+i] & 0xF); } printf("\n"); }
+#endif
+#ifdef SSFN_PROFILING
+ gettimeofday(&tv1, NULL); tvd.tv_sec = tv1.tv_sec - tv0.tv_sec; tvd.tv_usec = tv1.tv_usec - tv0.tv_usec;
+ if(tvd.tv_usec < 0) { tvd.tv_sec--; tvd.tv_usec += 1000000L; }
+ ctx->raster += tvd.tv_sec * 1000000L + tvd.tv_usec;
+ memcpy(&tv0, &tv1, sizeof(struct timeval));
+#endif
+ }
+ if(dst) {
+ /* blit glyph from cache into buffer */
+ h = H;
+ if(h > ctx->line) ctx->line = h;
+ w = ctx->g->p * h / ctx->g->h;
+ s = ((ctx->g->x - ctx->g->o) * h + ctx->f->height - 1) / ctx->f->height;
+ n = ctx->size > 16 ? 2 : 1;
+ if(w < n) w = n;
+ if(s < n) s = n;
+ if(ctx->g->x) {
+ ctx->ox = ox = ((ctx->g->o * h + ctx->f->height - 1) / ctx->f->height) + (ctx->style & SSFN_STYLE_RTL ? w : 0);
+ ctx->oy = oy = (ctx->g->a * h + ctx->f->height - 1) / ctx->f->height;
+ } else { ctx->ox = ox = w / 2; ctx->oy = oy = 0; }
+ if(dst->ptr) {
+ j = dst->w < 0 ? -dst->w : dst->w;
+ cs = dst->w < 0 ? 16 : 0;
+ cb = (h + 64) >> 6; uix = w > s ? w : s; uax = 0;
+ n = (ctx->f->underline * h + ctx->f->height - 1) / ctx->f->height;
+#ifdef SSFN_DEBUGGLYPH
+ printf("Scaling to w %d h %d (glyph %d %d, cache %d %d, font %d)\n",
+ w,h,ctx->rc->w,ctx->rc->h,ctx->g->p,ctx->g->h,ctx->f->height);
+#endif
+ fR = (dst->fg >> 16) & 0xFF; fG = (dst->fg >> 8) & 0xFF; fB = (dst->fg >> 0) & 0xFF; fA = (dst->fg >> 24) & 0xFF;
+ bR = (dst->bg >> 16) & 0xFF; bG = (dst->bg >> 8) & 0xFF; bB = (dst->bg >> 0) & 0xFF; O = 0xFF000000;
+ Op = (uint32_t*)(dst->ptr + dst->p * (dst->y - oy) + ((dst->x - ox) << 2));
+ for (y = 0; y < h && dst->y + y - oy < dst->h; y++, Op += dst->p >> 2) {
+ if(dst->y + y - oy < 0) continue;
+ y0 = (y << 8) * ctx->g->h / h; Y0 = y0 >> 8; y1 = ((y + 1) << 8) * ctx->g->h / h; Y1 = y1 >> 8; Ol = Op;
+ for (x = 0; x < w && dst->x + x - ox < j; x++, Ol++) {
+ if(dst->x + x - ox < 0) continue;
+ m = 0; sR = sG = sB = sA = 0;
+ if(!dst->bg) {
+ /* real linear frame buffers should be accessed only as uint32_t on 32 bit boundary */
+ O = *Ol;
+ bR = (O >> (16 - cs)) & 0xFF;
+ bG = (O >> 8) & 0xFF;
+ bB = (O >> cs) & 0xFF;
+ }
+ x0 = (x << 8) * ctx->g->p / w; X0 = x0 >> 8; x1 = ((x + 1) << 8) * ctx->g->p / w; X1 = x1 >> 8;
+ for(ys = y0; ys < y1; ys += 256) {
+ if(ys >> 8 == Y0) { yp = 256 - (ys & 0xFF); ys &= ~0xFF; if(yp > y1 - y0) yp = y1 - y0; }
+ else if(ys >> 8 == Y1) yp = y1 & 0xFF; else yp = 256;
+ X2 = (ys >> 8) * ctx->g->p;
+ for(xs = x0; xs < x1; xs += 256) {
+ if (xs >> 8 == X0) {
+ k = 256 - (xs & 0xFF); xs &= ~0xFF; if(k > x1 - x0) k = x1 - x0; pc = k == 256 ? yp : (k * yp)>>8;
+ } else
+ if (xs >> 8 == X1) { k = x1 & 0xFF; pc = k == 256 ? yp : (k * yp) >> 8; }
+ else pc = yp;
+ m += pc;
+ k = ctx->g->data[X2 + (xs >> 8)];
+ if(k == 0xFF) {
+ sB += bB * pc; sG += bG * pc; sR += bR * pc; sA += 255;
+ } else {
+ if(k == 0xFE || !ctx->f->cmap_offs) {
+ dB = fB; dG = fG; dR = fR; dA = fA;
+ } else {
+ P = *((uint32_t*)((uint8_t*)ctx->f + ctx->f->cmap_offs + (k << 2)));
+ dR = (P >> 16) & 0xFF; dG = (P >> 8) & 0xFF; dB = (P >> 0) & 0xFF; dA = (P >> 24) & 0xFF;
+ }
+ if(dA == 255) {
+ sB += dB * pc; sG += dG * pc; sR += dR * pc; sA += dA * pc;
+ } else {
+ sB += (dB * dA + bB * (255 - dA)) * pc / 255; sG += (dG * dA + bG * (255 - dA)) * pc / 255;
+ sR += (dR * dA + bR * (255 - dA)) * pc / 255; sA += dA * pc;
+ }
+ }
+ }
+ }
+ if(m) { sR /= m; sG /= m; sB /= m; sA /= m; } else { sR >>= 8; sG >>= 8; sB >>= 8; sA >>= 8; }
+ if(ctx->style & SSFN_STYLE_NOAA) sA = sA > 127 ? 255 : 0;
+ if(sA > 15) {
+ *Ol = (ctx->style & SSFN_STYLE_A ? O & 0xFF000000 : ((sA > 255 ? 255 : sA) << 24)) |
+ ((sR > 255 ? 255 : sR) << (16 - cs)) | ((sG > 255 ? 255 : sG) << 8) | ((sB > 255 ? 255 : sB) << cs);
+ if(y == n) { if(uix > x) { uix = x; } if(uax < x) { uax = x; } }
+ }
+ }
+ }
+ if(ctx->style & SSFN_STYLE_UNDERLINE) {
+ uix -= cb + 1; uax += cb + 2;
+ if(uax < uix) uax = uix + 1;
+ k = (w > s ? w : s);
+ Op = (uint32_t*)(dst->ptr + dst->p * (dst->y - oy + n) + ((dst->x - ox - 1) << 2));
+ for (y = n; y < n + cb && dst->y + y - oy < dst->h; y++, Op += dst->p >> 2) {
+ if(dst->y + y - oy < 0) continue;
+ for (Ol = Op, x = 0; x <= k && dst->x + x - ox < j; x++, Ol++) {
+ if(dst->x + x - ox < 0 || (x > uix && x < uax)) continue;
+ PUTPIXEL;
+ }
+ }
+ }
+ if(ctx->style & SSFN_STYLE_STHROUGH) {
+ n = (h >> 1); k = (w > s ? w : s) + 1;
+ Op = (uint32_t*)(dst->ptr + dst->p * (dst->y - oy + n) + ((dst->x - ox - 1) << 2));
+ for (y = n; y < n + cb && dst->y + y - oy < dst->h; y++, Op += dst->p >> 2) {
+ if(dst->y + y - oy < 0) continue;
+ for (Ol = Op, x = 0; x <= k && dst->x + x - ox < j; x++, Ol++) {
+ if(dst->x + x - ox < 0) continue;
+ PUTPIXEL;
+ }
+ }
+ }
+#ifdef SSFN_PROFILING
+ gettimeofday(&tv1, NULL); tvd.tv_sec = tv1.tv_sec - tv0.tv_sec;tvd.tv_usec = tv1.tv_usec - tv0.tv_usec;
+ if(tvd.tv_usec < 0) { tvd.tv_sec--; tvd.tv_usec += 1000000L; }
+ ctx->blit += tvd.tv_sec * 1000000L + tvd.tv_usec;
+ memcpy(&tv0, &tv1, sizeof(struct timeval));
+#endif
+ }
+ /* add advance and kerning */
+ ctx->ax = (ctx->style & SSFN_STYLE_RTL ? -s : s);
+ dst->x += ctx->ax;
+ dst->y += (ctx->g->y * h + ctx->f->height - 1) / ctx->f->height;
+ ptr = (uint8_t*)str + ret;
+ if(!(ctx->style & SSFN_STYLE_NOKERN) && ctx->f->kerning_offs && _ssfn_c(ctx->f, (const char*)ptr, &i, &P) && P > 32) {
+ ptr = (uint8_t*)ctx->rc + sizeof(ssfn_chr_t);
+ /* check all kerning fragments, because we might have both vertical and horizontal kerning offsets */
+ for(n = 0; n < ctx->rc->n; n++) {
+ if(ptr[0] == 255 && ptr[1] == 255) { ptr += ctx->rc->t & 0x40 ? 6 : 5; continue; }
+ x = ptr[0];
+ if(ctx->rc->t & 0x40) { m = (ptr[5] << 24) | (ptr[4] << 16) | (ptr[3] << 8) | ptr[2]; ptr += 6; }
+ else { m = (ptr[4] << 16) | (ptr[3] << 8) | ptr[2]; ptr += 5; }
+ frg = (uint8_t*)ctx->f + m;
+ if((frg[0] & 0xE0) == 0xC0) {
+ k = (((frg[0] & 0x1F) << 8) | frg[1]) + 1; frg += 2;
+ while(k--) {
+ m = ((frg[2] & 0xF) << 16) | (frg[1] << 8) | frg[0];
+ if(P >= (uint32_t)m && P <= (uint32_t)(((frg[5] & 0xF) << 16) | (frg[4] << 8) | frg[3])) {
+ P -= m;
+ m = ctx->f->kerning_offs + ((((frg[2] >> 4) & 0xF) << 24) | (((frg[5] >> 4) & 0xF) << 16) |
+ (frg[7] << 8) | frg[6]);
+ tmp = (uint8_t*)ctx->f + m;
+ while(tmp < (uint8_t*)ctx->f + ctx->f->size - 4) {
+ if((uint32_t)(tmp[0] & 0x7F) < P) {
+ P -= (tmp[0] & 0x7F) + 1;
+ tmp += 2 + (tmp[0] & 0x80 ? 0 : tmp[0] & 0x7F);
+ } else {
+ y = (int)((signed char)tmp[1 + ((tmp[0] & 0x80) ? 0 : P)]) * h / ctx->f->height;
+ if(x) dst->x += y; else dst->y += y;
+ break;
+ }
+ }
+ break;
+ }
+ frg += 8;
+ }
+ }
+ }
+#ifdef SSFN_PROFILING
+ gettimeofday(&tv1, NULL); tvd.tv_sec = tv1.tv_sec - tv0.tv_sec; tvd.tv_usec = tv1.tv_usec - tv0.tv_usec;
+ if(tvd.tv_usec < 0) { tvd.tv_sec--; tvd.tv_usec += 1000000L; }
+ ctx->kern += tvd.tv_sec * 1000000L + tvd.tv_usec;
+#endif
+ }
+ }
+ return ret;
+}
+
+/**
+ * Get the bounding box for a string
+
+ * @param ctx rendering context
+ * @param str string to measure
+ * @param w returned width
+ * @param h returned height
+ * @param left returned left margin
+ * @param top returned ascender
+ * @return error code
+ */
+int ssfn_bbox(ssfn_t *ctx, const char *str, int *w, int *h, int *left, int *top)
+{
+ ssfn_buf_t buf;
+ int ret, f = 1, l = 0, t = 0;
+
+ if(!ctx || !str) return SSFN_ERR_INVINP;
+ if(w) {*w = 0;} if(h) {*h = 0;} if(top) {*top = 0;} if(left) {*left = 0;}
+ if(!*str) return SSFN_OK;
+ SSFN_memset(&buf, 0, sizeof(ssfn_buf_t)); ctx->line = 0;
+ while((ret = ssfn_render(ctx, &buf, str))) {
+ if(ret < 0 || !ctx->g) return ret;
+ if(f) { f = 0; l = ctx->ox; buf.x += l; }
+ if(ctx->g->x) {
+ if(ctx->oy > t) t = ctx->oy;
+ } else {
+ if(buf.w < ctx->g->p) buf.w = ctx->g->p;
+ buf.h += ctx->g->y ? ctx->g->y : ctx->g->h;
+ }
+ str += ret;
+ }
+ if((ctx->style & SSFN_STYLE_ITALIC) && !(SSFN_TYPE_STYLE(ctx->f->type) & SSFN_STYLE_ITALIC))
+ buf.x += ctx->size / SSFN_ITALIC_DIV - l;
+ if(ctx->g->x) { if(w) {*w = buf.x;} if(h) {*h = ctx->line;} if(left) {*left = l;} if(top) {*top = t;} }
+ else { if(w) {*w = buf.w;} if(h) {*h = buf.y;} if(top) {*top = 0;} if(left) {*left = 0;} }
+ return SSFN_OK;
+}
+
+/**
+ * Render text to a newly allocated pixel buffer
+ *
+ * @param ctx rendering context
+ * @param str string to measure
+ * @return a newly allocated pixel buffer or NULL
+ */
+ssfn_buf_t *ssfn_text(ssfn_t *ctx, const char *str, unsigned int fg)
+{
+#ifndef SSFN_MAXLINES
+ ssfn_buf_t *buf;
+ int ret;
+
+ if(!ctx || !str) return NULL;
+ buf = (ssfn_buf_t*)SSFN_realloc(NULL, sizeof(ssfn_buf_t));
+ if(!buf) return NULL;
+ SSFN_memset(buf, 0, sizeof(ssfn_buf_t));
+ buf->fg = fg;
+ if(!*str || ssfn_bbox(ctx, str, (int*)&buf->w, (int*)&buf->h, (int*)&buf->x, (int*)&buf->y) != SSFN_OK)
+ return buf;
+ buf->p = buf->w * (uint8_t)sizeof(uint32_t);
+ buf->ptr = (uint8_t*)SSFN_realloc(NULL, buf->p * buf->h);
+ SSFN_memset(buf->ptr, 0, buf->p * buf->h);
+ ctx->style &= ~SSFN_STYLE_A;
+ while((ret = ssfn_render(ctx, buf, str)) > 0)
+ str += ret;
+ if(ret != SSFN_OK) { SSFN_free(buf->ptr); SSFN_free(buf); return NULL; }
+ return buf;
+#else
+ (void)ctx;
+ (void)str;
+ (void)fg;
+ return NULL;
+#endif
+}
+
+#endif /* SSFN_IMPLEMENTATION */
+
+#if defined(SSFN_CONSOLEBITMAP_PALETTE) || defined(SSFN_CONSOLEBITMAP_HICOLOR) || defined(SSFN_CONSOLEBITMAP_TRUECOLOR)
+/*** special console bitmap font renderer (ca. 1.5k, no dependencies, no memory allocation and no error checking) ***/
+
+/**
+ * public variables to configure
+ */
+ssfn_font_t *ssfn_src; /* font buffer with an inflated bitmap font */
+ssfn_buf_t ssfn_dst; /* destination frame buffer */
+
+/**
+ * Minimal OS kernel console renderer
+ *
+ * @param unicode character
+ * @return error code
+ */
+int ssfn_putc(uint32_t unicode)
+{
+# ifdef SSFN_CONSOLEBITMAP_PALETTE
+# define SSFN_PIXEL uint8_t
+# else
+# ifdef SSFN_CONSOLEBITMAP_HICOLOR
+# define SSFN_PIXEL uint16_t
+# else
+# define SSFN_PIXEL uint32_t
+# endif
+# endif
+ register SSFN_PIXEL *o, *p;
+ register uint8_t *ptr, *chr = NULL, *frg;
+ register int i, j, k, l, m, y = 0, w, s = ssfn_dst.p / sizeof(SSFN_PIXEL);
+
+ if(!ssfn_src || ssfn_src->magic[0] != 'S' || ssfn_src->magic[1] != 'F' || ssfn_src->magic[2] != 'N' ||
+ ssfn_src->magic[3] != '2' || !ssfn_dst.ptr || !ssfn_dst.p) return SSFN_ERR_INVINP;
+ w = ssfn_dst.w < 0 ? -ssfn_dst.w : ssfn_dst.w;
+ for(ptr = (uint8_t*)ssfn_src + ssfn_src->characters_offs, i = 0; i < 0x110000; i++) {
+ if(ptr[0] == 0xFF) { i += 65535; ptr++; }
+ else if((ptr[0] & 0xC0) == 0xC0) { j = (((ptr[0] & 0x3F) << 8) | ptr[1]); i += j; ptr += 2; }
+ else if((ptr[0] & 0xC0) == 0x80) { j = (ptr[0] & 0x3F); i += j; ptr++; }
+ else { if((uint32_t)i == unicode) { chr = ptr; break; } ptr += 6 + ptr[1] * (ptr[0] & 0x40 ? 6 : 5); }
+ }
+#ifdef SSFN_CONSOLEBITMAP_CONTROL
+ i = ssfn_src->height; j = ssfn_dst.h - i - (ssfn_dst.h % i);
+ if(chr && w) {
+ if(unicode == '\t') ssfn_dst.x -= ssfn_dst.x % chr[4];
+ if(ssfn_dst.x + chr[4] > w) { ssfn_dst.x = 0; ssfn_dst.y += i; }
+ }
+ if(unicode == '\n') ssfn_dst.y += i;
+ if(j > 0 && ssfn_dst.y > j) {
+ ssfn_dst.y = j;
+ for(k = 0; k < j; k++)
+ for(l = 0; l < ssfn_dst.p; l++) ssfn_dst.ptr[k * ssfn_dst.p + l] = ssfn_dst.ptr[(k + i) * ssfn_dst.p + l];
+ }
+ if(unicode == '\r' || unicode == '\n') { ssfn_dst.x = 0; return SSFN_OK; }
+#endif
+ if(!chr) return SSFN_ERR_NOGLYPH;
+ ptr = chr + 6; o = (SSFN_PIXEL*)(ssfn_dst.ptr + ssfn_dst.y * ssfn_dst.p + ssfn_dst.x * sizeof(SSFN_PIXEL));
+ for(i = 0; i < chr[1]; i++, ptr += chr[0] & 0x40 ? 6 : 5) {
+ if(ptr[0] == 255 && ptr[1] == 255) continue;
+ frg = (uint8_t*)ssfn_src + (chr[0] & 0x40 ? ((ptr[5] << 24) | (ptr[4] << 16) | (ptr[3] << 8) | ptr[2]) :
+ ((ptr[4] << 16) | (ptr[3] << 8) | ptr[2]));
+ if((frg[0] & 0xE0) != 0x80) continue;
+ if(ssfn_dst.bg) {
+ for(; y < ptr[1] && (!ssfn_dst.h || ssfn_dst.y + y < ssfn_dst.h); y++, o += s) {
+ for(p = o, j = 0; j < chr[2] && (!w || ssfn_dst.x + j < w); j++, p++)
+ *p = ssfn_dst.bg;
+ }
+ } else { o += (int)(ptr[1] - y) * s; y = ptr[1]; }
+ k = ((frg[0] & 0x1F) + 1) << 3; j = frg[1] + 1; frg += 2;
+ for(m = 1; j && (!ssfn_dst.h || ssfn_dst.y + y < ssfn_dst.h); j--, y++, o += s)
+ for(p = o, l = 0; l < k; l++, p++, m <<= 1) {
+ if(m > 0x80) { frg++; m = 1; }
+ if(ssfn_dst.x + l >= 0 && (!w || ssfn_dst.x + l < w)) {
+ if(*frg & m) *p = ssfn_dst.fg; else
+ if(ssfn_dst.bg) *p = ssfn_dst.bg;
+ }
+ }
+ }
+ if(ssfn_dst.bg)
+ for(; y < chr[3] && (!ssfn_dst.h || ssfn_dst.y + y < ssfn_dst.h); y++, o += s) {
+ for(p = o, j = 0; j < chr[2] && (!w || ssfn_dst.x + j < w); j++, p++)
+ *p = ssfn_dst.bg;
+ }
+ ssfn_dst.x += chr[4]; ssfn_dst.y += chr[5];
+ return SSFN_OK;
+}
+
+#endif /* SSFN_CONSOLEBITMAP */
+
+/* */
+#endif /* _SSFN_H_ */
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/stb.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/stb.h
new file mode 100644
index 0000000..03aec96
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/stb.h
@@ -0,0 +1,14454 @@
+/* stb.h - v2.37 - Sean's Tool Box -- public domain -- http://nothings.org/stb.h
+ no warranty is offered or implied; use this code at your own risk
+
+ This is a single header file with a bunch of useful utilities
+ for getting stuff done in C/C++.
+
+ Documentation: http://nothings.org/stb/stb_h.html
+ Unit tests: http://nothings.org/stb/stb.c
+
+ ============================================================================
+ You MUST
+
+ #define STB_DEFINE
+
+ in EXACTLY _one_ C or C++ file that includes this header, BEFORE the
+ include, like this:
+
+ #define STB_DEFINE
+ #include "stb.h"
+
+ All other files should just #include "stb.h" without the #define.
+ ============================================================================
+
+Version History
+
+ 2.36 various fixes
+ 2.35 fix clang-cl issues with swprintf
+ 2.34 fix warnings
+ 2.33 more fixes to random numbers
+ 2.32 stb_intcmprev, stb_uidict, fix random numbers on Linux
+ 2.31 stb_ucharcmp
+ 2.30 MinGW fix
+ 2.29 attempt to fix use of swprintf()
+ 2.28 various new functionality
+ 2.27 test _WIN32 not WIN32 in STB_THREADS
+ 2.26 various warning & bugfixes
+ 2.25 various warning & bugfixes
+ 2.24 various warning & bugfixes
+ 2.23 fix 2.22
+ 2.22 64-bit fixes from '!='; fix stb_sdict_copy() to have preferred name
+ 2.21 utf-8 decoder rejects "overlong" encodings; attempted 64-bit improvements
+ 2.20 fix to hash "copy" function--reported by someone with handle "!="
+ 2.19 ???
+ 2.18 stb_readdir_subdirs_mask
+ 2.17 stb_cfg_dir
+ 2.16 fix stb_bgio_, add stb_bgio_stat(); begin a streaming wrapper
+ 2.15 upgraded hash table template to allow:
+ - aggregate keys (explicit comparison func for EMPTY and DEL keys)
+ - "static" implementations (so they can be culled if unused)
+ 2.14 stb_mprintf
+ 2.13 reduce identifiable strings in STB_NO_STB_STRINGS
+ 2.12 fix STB_ONLY -- lots of uint32s, TRUE/FALSE things had crept in
+ 2.11 fix bug in stb_dirtree_get() which caused "c://path" sorts of stuff
+ 2.10 STB_F(), STB_I() inline constants (also KI,KU,KF,KD)
+ 2.09 stb_box_face_vertex_axis_side
+ 2.08 bugfix stb_trimwhite()
+ 2.07 colored printing in windows (why are we in 1985?)
+ 2.06 comparison functions are now functions-that-return-functions and
+ accept a struct-offset as a parameter (not thread-safe)
+ 2.05 compile and pass tests under Linux (but no threads); thread cleanup
+ 2.04 stb_cubic_bezier_1d, smoothstep, avoid dependency on registry
+ 2.03 ?
+ 2.02 remove integrated documentation
+ 2.01 integrate various fixes; stb_force_uniprocessor
+ 2.00 revised stb_dupe to use multiple hashes
+ 1.99 stb_charcmp
+ 1.98 stb_arr_deleten, stb_arr_insertn
+ 1.97 fix stb_newell_normal()
+ 1.96 stb_hash_number()
+ 1.95 hack stb__rec_max; clean up recursion code to use new functions
+ 1.94 stb_dirtree; rename stb_extra to stb_ptrmap
+ 1.93 stb_sem_new() API cleanup (no blockflag-starts blocked; use 'extra')
+ 1.92 stb_threadqueue--multi reader/writer queue, fixed size or resizeable
+ 1.91 stb_bgio_* for reading disk asynchronously
+ 1.90 stb_mutex uses CRITICAL_REGION; new stb_sync primitive for thread
+ joining; workqueue supports stb_sync instead of stb_semaphore
+ 1.89 support ';' in constant-string wildcards; stb_mutex wrapper (can
+ implement with EnterCriticalRegion eventually)
+ 1.88 portable threading API (only for win32 so far); worker thread queue
+ 1.87 fix wildcard handling in stb_readdir_recursive
+ 1.86 support ';' in wildcards
+ 1.85 make stb_regex work with non-constant strings;
+ beginnings of stb_introspect()
+ 1.84 (forgot to make notes)
+ 1.83 whoops, stb_keep_if_different wasn't deleting the temp file
+ 1.82 bring back stb_compress from stb_file.h for cmirror
+ 1.81 various bugfixes, STB_FASTMALLOC_INIT inits FASTMALLOC in release
+ 1.80 stb_readdir returns utf8; write own utf8-utf16 because lib was wrong
+ 1.79 stb_write
+ 1.78 calloc() support for malloc wrapper, STB_FASTMALLOC
+ 1.77 STB_FASTMALLOC
+ 1.76 STB_STUA - Lua-like language; (stb_image, stb_csample, stb_bilinear)
+ 1.75 alloc/free array of blocks; stb_hheap bug; a few stb_ps_ funcs;
+ hash*getkey, hash*copy; stb_bitset; stb_strnicmp; bugfix stb_bst
+ 1.74 stb_replaceinplace; use stdlib C function to convert utf8 to UTF-16
+ 1.73 fix performance bug & leak in stb_ischar (C++ port lost a 'static')
+ 1.72 remove stb_block, stb_block_manager, stb_decompress (to stb_file.h)
+ 1.71 stb_trimwhite, stb_tokens_nested, etc.
+ 1.70 back out 1.69 because it might problemize mixed builds; stb_filec()
+ 1.69 (stb_file returns 'char *' in C++)
+ 1.68 add a special 'tree root' data type for stb_bst; stb_arr_end
+ 1.67 full C++ port. (stb_block_manager)
+ 1.66 stb_newell_normal
+ 1.65 stb_lex_item_wild -- allow wildcard items which MUST match entirely
+ 1.64 stb_data
+ 1.63 stb_log_name
+ 1.62 stb_define_sort; C++ cleanup
+ 1.61 stb_hash_fast -- Paul Hsieh's hash function (beats Bob Jenkins'?)
+ 1.60 stb_delete_directory_recursive
+ 1.59 stb_readdir_recursive
+ 1.58 stb_bst variant with parent pointer for O(1) iteration, not O(log N)
+ 1.57 replace LCG random with Mersenne Twister (found a public domain one)
+ 1.56 stb_perfect_hash, stb_ischar, stb_regex
+ 1.55 new stb_bst API allows multiple BSTs per node (e.g. secondary keys)
+ 1.54 bugfix: stb_define_hash, stb_wildmatch, regexp
+ 1.53 stb_define_hash; recoded stb_extra, stb_sdict use it
+ 1.52 stb_rand_define, stb_bst, stb_reverse
+ 1.51 fix 'stb_arr_setlen(NULL, 0)'
+ 1.50 stb_wordwrap
+ 1.49 minor improvements to enable the scripting language
+ 1.48 better approach for stb_arr using stb_malloc; more invasive, clearer
+ 1.47 stb_lex (lexes stb.h at 1.5ML/s on 3Ghz P4; 60/70% of optimal/flex)
+ 1.46 stb_wrapper_*, STB_MALLOC_WRAPPER
+ 1.45 lightly tested DFA acceleration of regexp searching
+ 1.44 wildcard matching & searching; regexp matching & searching
+ 1.43 stb_temp
+ 1.42 allow stb_arr to use stb_malloc/realloc; note this is global
+ 1.41 make it compile in C++; (disable stb_arr in C++)
+ 1.40 stb_dupe tweak; stb_swap; stb_substr
+ 1.39 stb_dupe; improve stb_file_max to be less stupid
+ 1.38 stb_sha1_file: generate sha1 for file, even > 4GB
+ 1.37 stb_file_max; partial support for utf8 filenames in Windows
+ 1.36 remove STB__NO_PREFIX - poor interaction with IDE, not worth it
+ streamline stb_arr to make it separately publishable
+ 1.35 bugfixes for stb_sdict, stb_malloc(0), stristr
+ 1.34 (streaming interfaces for stb_compress)
+ 1.33 stb_alloc; bug in stb_getopt; remove stb_overflow
+ 1.32 (stb_compress returns, smaller&faster; encode window & 64-bit len)
+ 1.31 stb_prefix_count
+ 1.30 (STB__NO_PREFIX - remove stb_ prefixes for personal projects)
+ 1.29 stb_fput_varlen64, etc.
+ 1.28 stb_sha1
+ 1.27 ?
+ 1.26 stb_extra
+ 1.25 ?
+ 1.24 stb_copyfile
+ 1.23 stb_readdir
+ 1.22 ?
+ 1.21 ?
+ 1.20 ?
+ 1.19 ?
+ 1.18 ?
+ 1.17 ?
+ 1.16 ?
+ 1.15 stb_fixpath, stb_splitpath, stb_strchr2
+ 1.14 stb_arr
+ 1.13 ?stb, stb_log, stb_fatal
+ 1.12 ?stb_hash2
+ 1.11 miniML
+ 1.10 stb_crc32, stb_adler32
+ 1.09 stb_sdict
+ 1.08 stb_bitreverse, stb_ispow2, stb_big32
+ stb_fopen, stb_fput_varlen, stb_fput_ranged
+ stb_fcmp, stb_feq
+ 1.07 (stb_encompress)
+ 1.06 stb_compress
+ 1.05 stb_tokens, (stb_hheap)
+ 1.04 stb_rand
+ 1.03 ?(s-strings)
+ 1.02 ?stb_filelen, stb_tokens
+ 1.01 stb_tolower
+ 1.00 stb_hash, stb_intcmp
+ stb_file, stb_stringfile, stb_fgets
+ stb_prefix, stb_strlower, stb_strtok
+ stb_image
+ (stb_array), (stb_arena)
+
+Parenthesized items have since been removed.
+
+LICENSE
+
+ See end of file for license information.
+
+CREDITS
+
+ Written by Sean Barrett.
+
+ Fixes:
+ Philipp Wiesemann
+ Robert Nix
+ r-lyeh
+ blackpawn
+ github:Mojofreem
+ Ryan Whitworth
+ Vincent Isambart
+ Mike Sartain
+ Eugene Opalev
+ Tim Sjostrand
+ github:infatum
+ Dave Butler (Croepha)
+ Ethan Lee (flibitijibibo)
+ Brian Collins
+ Kyle Langley
+*/
+
+#include
+
+#ifndef STB__INCLUDE_STB_H
+#define STB__INCLUDE_STB_H
+
+#define STB_VERSION 1
+
+#ifdef STB_INTROSPECT
+ #define STB_DEFINE
+#endif
+
+#ifdef STB_DEFINE_THREADS
+ #ifndef STB_DEFINE
+ #define STB_DEFINE
+ #endif
+ #ifndef STB_THREADS
+ #define STB_THREADS
+ #endif
+#endif
+
+#if defined(_WIN32) && !defined(__MINGW32__)
+ #ifndef _CRT_SECURE_NO_WARNINGS
+ #define _CRT_SECURE_NO_WARNINGS
+ #endif
+ #ifndef _CRT_NONSTDC_NO_DEPRECATE
+ #define _CRT_NONSTDC_NO_DEPRECATE
+ #endif
+ #ifndef _CRT_NON_CONFORMING_SWPRINTFS
+ #define _CRT_NON_CONFORMING_SWPRINTFS
+ #endif
+ #if !defined(_MSC_VER) || _MSC_VER > 1700
+ #include // _BitScanReverse
+ #endif
+#endif
+
+#include // stdlib could have min/max
+#include // need FILE
+#include // stb_define_hash needs memcpy/memset
+#include // stb_dirtree
+#ifdef __MINGW32__
+ #include // O_RDWR
+#endif
+
+#ifdef STB_PERSONAL
+ typedef int Bool;
+ #define False 0
+ #define True 1
+#endif
+
+#ifdef STB_MALLOC_WRAPPER_PAGED
+ #define STB_MALLOC_WRAPPER_DEBUG
+#endif
+#ifdef STB_MALLOC_WRAPPER_DEBUG
+ #define STB_MALLOC_WRAPPER
+#endif
+#ifdef STB_MALLOC_WRAPPER_FASTMALLOC
+ #define STB_FASTMALLOC
+ #define STB_MALLOC_WRAPPER
+#endif
+
+#ifdef STB_FASTMALLOC
+ #ifndef _WIN32
+ #undef STB_FASTMALLOC
+ #endif
+#endif
+
+#ifdef STB_DEFINE
+ #include
+ #include
+ #include
+ #include
+ #include
+ #ifndef _WIN32
+ #include
+ #else
+ #include // _mktemp
+ #include // _rmdir
+ #endif
+ #include // stat()/_stat()
+ #include // stat()/_stat()
+#endif
+
+#define stb_min(a,b) ((a) < (b) ? (a) : (b))
+#define stb_max(a,b) ((a) > (b) ? (a) : (b))
+
+#ifndef STB_ONLY
+ #if !defined(__cplusplus) && !defined(min) && !defined(max)
+ #define min(x,y) stb_min(x,y)
+ #define max(x,y) stb_max(x,y)
+ #endif
+
+ #ifndef M_PI
+ #define M_PI 3.14159265358979323846f
+ #endif
+
+ #ifndef TRUE
+ #define TRUE 1
+ #define FALSE 0
+ #endif
+
+ #ifndef deg2rad
+ #define deg2rad(a) ((a)*(M_PI/180))
+ #endif
+ #ifndef rad2deg
+ #define rad2deg(a) ((a)*(180/M_PI))
+ #endif
+
+ #ifndef swap
+ #ifndef __cplusplus
+ #define swap(TYPE,a,b) \
+ do { TYPE stb__t; stb__t = (a); (a) = (b); (b) = stb__t; } while (0)
+ #endif
+ #endif
+
+ typedef unsigned char uint8 ;
+ typedef signed char int8 ;
+ typedef unsigned short uint16;
+ typedef signed short int16;
+ #if defined(STB_USE_LONG_FOR_32_BIT_INT) || defined(STB_LONG32)
+ typedef unsigned long uint32;
+ typedef signed long int32;
+ #else
+ typedef unsigned int uint32;
+ typedef signed int int32;
+ #endif
+
+ typedef unsigned char uchar ;
+ typedef unsigned short ushort;
+ typedef unsigned int uint ;
+ typedef unsigned long ulong ;
+
+ // produce compile errors if the sizes aren't right
+ typedef char stb__testsize16[sizeof(int16)==2];
+ typedef char stb__testsize32[sizeof(int32)==4];
+#endif
+
+#ifndef STB_TRUE
+ #define STB_TRUE 1
+ #define STB_FALSE 0
+#endif
+
+// if we're STB_ONLY, can't rely on uint32 or even uint, so all the
+// variables we'll use herein need typenames prefixed with 'stb':
+typedef unsigned char stb_uchar;
+typedef unsigned char stb_uint8;
+typedef unsigned int stb_uint;
+typedef unsigned short stb_uint16;
+typedef short stb_int16;
+typedef signed char stb_int8;
+#if defined(STB_USE_LONG_FOR_32_BIT_INT) || defined(STB_LONG32)
+ typedef unsigned long stb_uint32;
+ typedef long stb_int32;
+#else
+ typedef unsigned int stb_uint32;
+ typedef int stb_int32;
+#endif
+typedef char stb__testsize2_16[sizeof(stb_uint16)==2 ? 1 : -1];
+typedef char stb__testsize2_32[sizeof(stb_uint32)==4 ? 1 : -1];
+
+#ifdef _MSC_VER
+ typedef unsigned __int64 stb_uint64;
+ typedef __int64 stb_int64;
+ #define STB_IMM_UINT64(literalui64) (literalui64##ui64)
+ #define STB_IMM_INT64(literali64) (literali64##i64)
+#else
+ // ??
+ typedef unsigned long long stb_uint64;
+ typedef long long stb_int64;
+ #define STB_IMM_UINT64(literalui64) (literalui64##ULL)
+ #define STB_IMM_INT64(literali64) (literali64##LL)
+#endif
+typedef char stb__testsize2_64[sizeof(stb_uint64)==8 ? 1 : -1];
+
+// add platform-specific ways of checking for sizeof(char*) == 8,
+// and make those define STB_PTR64
+#if defined(_WIN64) || defined(__x86_64__) || defined(__ia64__) || defined(__LP64__)
+ #define STB_PTR64
+#endif
+
+#ifdef STB_PTR64
+typedef char stb__testsize2_ptr[sizeof(char *) == 8];
+typedef stb_uint64 stb_uinta;
+typedef stb_int64 stb_inta;
+#else
+typedef char stb__testsize2_ptr[sizeof(char *) == 4];
+typedef stb_uint32 stb_uinta;
+typedef stb_int32 stb_inta;
+#endif
+typedef char stb__testsize2_uinta[sizeof(stb_uinta)==sizeof(char*) ? 1 : -1];
+
+// if so, we should define an int type that is the pointer size. until then,
+// we'll have to make do with this (which is not the same at all!)
+
+typedef union
+{
+ unsigned int i;
+ void * p;
+} stb_uintptr;
+
+
+#ifdef __cplusplus
+ #define STB_EXTERN extern "C"
+#else
+ #define STB_EXTERN extern
+#endif
+
+// check for well-known debug defines
+#if defined(DEBUG) || defined(_DEBUG) || defined(DBG)
+ #ifndef NDEBUG
+ #define STB_DEBUG
+ #endif
+#endif
+
+#ifdef STB_DEBUG
+ #include
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// C library function platform handling
+//
+
+#ifdef STB_DEFINE
+
+#if defined(_WIN32) && defined(__STDC_WANT_SECURE_LIB__)
+static FILE * stb_p_fopen(const char *filename, const char *mode)
+{
+ FILE *f;
+ if (0 == fopen_s(&f, filename, mode))
+ return f;
+ else
+ return NULL;
+}
+static FILE * stb_p_wfopen(const wchar_t *filename, const wchar_t *mode)
+{
+ FILE *f;
+ if (0 == _wfopen_s(&f, filename, mode))
+ return f;
+ else
+ return NULL;
+}
+static char *stb_p_strcpy_s(char *a, size_t size, const char *b)
+{
+ strcpy_s(a,size,b);
+ return a;
+}
+static char *stb_p_strncpy_s(char *a, size_t size, const char *b, size_t count)
+{
+ strncpy_s(a,size,b,count);
+ return a;
+}
+#define stb_p_mktemp(s) (_mktemp_s(s, strlen(s)+1) == 0)
+#define stb_p_sprintf sprintf_s
+#define stb_p_size(x) ,(x)
+#else
+#define stb_p_fopen fopen
+#define stb_p_wfopen _wfopen
+#define stb_p_strcpy_s(a,s,b) strcpy(a,b)
+#define stb_p_strncpy_s(a,s,b,c) strncpy(a,b,c)
+#define stb_p_mktemp(s) (mktemp(s) != NULL)
+
+#define stb_p_sprintf sprintf
+#define stb_p_size(x)
+#endif
+
+#if defined(_WIN32)
+#define stb_p_vsnprintf _vsnprintf
+#else
+#define stb_p_vsnprintf vsnprintf
+#endif
+#endif // STB_DEFINE
+
+#if defined(_WIN32) && (_MSC_VER >= 1300)
+#define stb_p_stricmp _stricmp
+#define stb_p_strnicmp _strnicmp
+#define stb_p_strdup _strdup
+#else
+#define stb_p_strdup strdup
+#define stb_p_stricmp stricmp
+#define stb_p_strnicmp strnicmp
+#endif
+
+STB_EXTERN void stb_wrapper_malloc(void *newp, size_t sz, char *file, int line);
+STB_EXTERN void stb_wrapper_free(void *oldp, char *file, int line);
+STB_EXTERN void stb_wrapper_realloc(void *oldp, void *newp, size_t sz, char *file, int line);
+STB_EXTERN void stb_wrapper_calloc(size_t num, size_t sz, char *file, int line);
+STB_EXTERN void stb_wrapper_listall(void (*func)(void *ptr, size_t sz, char *file, int line));
+STB_EXTERN void stb_wrapper_dump(char *filename);
+STB_EXTERN size_t stb_wrapper_allocsize(void *oldp);
+STB_EXTERN void stb_wrapper_check(void *oldp);
+
+#ifdef STB_DEFINE
+// this is a special function used inside malloc wrapper
+// to do allocations that aren't tracked (to avoid
+// reentrancy). Of course if someone _else_ wraps realloc,
+// this breaks, but if they're doing that AND the malloc
+// wrapper they need to explicitly check for reentrancy.
+//
+// only define realloc_raw() and we do realloc(NULL,sz)
+// for malloc() and realloc(p,0) for free().
+static void * stb__realloc_raw(void *p, int sz)
+{
+ if (p == NULL) return malloc(sz);
+ if (sz == 0) { free(p); return NULL; }
+ return realloc(p,sz);
+}
+#endif
+
+#ifdef _WIN32
+STB_EXTERN void * stb_smalloc(size_t sz);
+STB_EXTERN void stb_sfree(void *p);
+STB_EXTERN void * stb_srealloc(void *p, size_t sz);
+STB_EXTERN void * stb_scalloc(size_t n, size_t sz);
+STB_EXTERN char * stb_sstrdup(char *s);
+#endif
+
+#ifdef STB_FASTMALLOC
+#define malloc stb_smalloc
+#define free stb_sfree
+#define realloc stb_srealloc
+#define strdup stb_sstrdup
+#define calloc stb_scalloc
+#endif
+
+#ifndef STB_MALLOC_ALLCHECK
+ #define stb__check(p) 1
+#else
+ #ifndef STB_MALLOC_WRAPPER
+ #error STB_MALLOC_ALLCHECK requires STB_MALLOC_WRAPPER
+ #else
+ #define stb__check(p) stb_mcheck(p)
+ #endif
+#endif
+
+#ifdef STB_MALLOC_WRAPPER
+ STB_EXTERN void * stb__malloc(size_t, char *, int);
+ STB_EXTERN void * stb__realloc(void *, size_t, char *, int);
+ STB_EXTERN void * stb__calloc(size_t n, size_t s, char *, int);
+ STB_EXTERN void stb__free(void *, char *file, int);
+ STB_EXTERN char * stb__strdup(char *s, char *file, int);
+ STB_EXTERN void stb_malloc_checkall(void);
+ STB_EXTERN void stb_malloc_check_counter(int init_delay, int rep_delay);
+ #ifndef STB_MALLOC_WRAPPER_DEBUG
+ #define stb_mcheck(p) 1
+ #else
+ STB_EXTERN int stb_mcheck(void *);
+ #endif
+
+
+ #ifdef STB_DEFINE
+
+ #ifdef STB_MALLOC_WRAPPER_DEBUG
+ #define STB__PAD 32
+ #define STB__BIAS 16
+ #define STB__SIG 0x51b01234
+ #define STB__FIXSIZE(sz) (((sz+3) & ~3) + STB__PAD)
+ #define STB__ptr(x,y) ((char *) (x) + (y))
+ #else
+ #define STB__ptr(x,y) (x)
+ #define STB__FIXSIZE(sz) (sz)
+ #endif
+
+ #ifdef STB_MALLOC_WRAPPER_DEBUG
+ int stb_mcheck(void *p)
+ {
+ unsigned int sz;
+ if (p == NULL) return 1;
+ p = ((char *) p) - STB__BIAS;
+ sz = * (unsigned int *) p;
+ assert(* (unsigned int *) STB__ptr(p,4) == STB__SIG);
+ assert(* (unsigned int *) STB__ptr(p,8) == STB__SIG);
+ assert(* (unsigned int *) STB__ptr(p,12) == STB__SIG);
+ assert(* (unsigned int *) STB__ptr(p,sz-4) == STB__SIG+1);
+ assert(* (unsigned int *) STB__ptr(p,sz-8) == STB__SIG+1);
+ assert(* (unsigned int *) STB__ptr(p,sz-12) == STB__SIG+1);
+ assert(* (unsigned int *) STB__ptr(p,sz-16) == STB__SIG+1);
+ stb_wrapper_check(STB__ptr(p, STB__BIAS));
+ return 1;
+ }
+
+ static void stb__check2(void *p, size_t sz, char *file, int line)
+ {
+ stb_mcheck(p);
+ }
+
+ void stb_malloc_checkall(void)
+ {
+ stb_wrapper_listall(stb__check2);
+ }
+ #else
+ void stb_malloc_checkall(void) { }
+ #endif
+
+ static int stb__malloc_wait=(1 << 30), stb__malloc_next_wait = (1 << 30), stb__malloc_iter;
+ void stb_malloc_check_counter(int init_delay, int rep_delay)
+ {
+ stb__malloc_wait = init_delay;
+ stb__malloc_next_wait = rep_delay;
+ }
+
+ void stb_mcheck_all(void)
+ {
+ #ifdef STB_MALLOC_WRAPPER_DEBUG
+ ++stb__malloc_iter;
+ if (--stb__malloc_wait <= 0) {
+ stb_malloc_checkall();
+ stb__malloc_wait = stb__malloc_next_wait;
+ }
+ #endif
+ }
+
+ #ifdef STB_MALLOC_WRAPPER_PAGED
+ #define STB__WINDOWS_PAGE (1 << 12)
+ #ifndef _WINDOWS_
+ STB_EXTERN __declspec(dllimport) void * __stdcall VirtualAlloc(void *p, unsigned long size, unsigned long type, unsigned long protect);
+ STB_EXTERN __declspec(dllimport) int __stdcall VirtualFree(void *p, unsigned long size, unsigned long freetype);
+ #endif
+ #endif
+
+ static void *stb__malloc_final(size_t sz)
+ {
+ #ifdef STB_MALLOC_WRAPPER_PAGED
+ size_t aligned = (sz + STB__WINDOWS_PAGE - 1) & ~(STB__WINDOWS_PAGE-1);
+ char *p = VirtualAlloc(NULL, aligned + STB__WINDOWS_PAGE, 0x2000, 0x04); // RESERVE, READWRITE
+ if (p == NULL) return p;
+ VirtualAlloc(p, aligned, 0x1000, 0x04); // COMMIT, READWRITE
+ return p;
+ #else
+ return malloc(sz);
+ #endif
+ }
+
+ static void stb__free_final(void *p)
+ {
+ #ifdef STB_MALLOC_WRAPPER_PAGED
+ VirtualFree(p, 0, 0x8000); // RELEASE
+ #else
+ free(p);
+ #endif
+ }
+
+ int stb__malloc_failure;
+ #ifdef STB_MALLOC_WRAPPER_PAGED
+ static void *stb__realloc_final(void *p, size_t sz, size_t old_sz)
+ {
+ void *q = stb__malloc_final(sz);
+ if (q == NULL)
+ return ++stb__malloc_failure, q;
+ // @TODO: deal with p being smaller!
+ memcpy(q, p, sz < old_sz ? sz : old_sz);
+ stb__free_final(p);
+ return q;
+ }
+ #endif
+
+ void stb__free(void *p, char *file, int line)
+ {
+ stb_mcheck_all();
+ if (!p) return;
+ #ifdef STB_MALLOC_WRAPPER_DEBUG
+ stb_mcheck(p);
+ #endif
+ stb_wrapper_free(p,file,line);
+ #ifdef STB_MALLOC_WRAPPER_DEBUG
+ p = STB__ptr(p,-STB__BIAS);
+ * (unsigned int *) STB__ptr(p,0) = 0xdeadbeef;
+ * (unsigned int *) STB__ptr(p,4) = 0xdeadbeef;
+ * (unsigned int *) STB__ptr(p,8) = 0xdeadbeef;
+ * (unsigned int *) STB__ptr(p,12) = 0xdeadbeef;
+ #endif
+ stb__free_final(p);
+ }
+
+ void * stb__malloc(size_t sz, char *file, int line)
+ {
+ void *p;
+ stb_mcheck_all();
+ if (sz == 0) return NULL;
+ p = stb__malloc_final(STB__FIXSIZE(sz));
+ if (p == NULL) p = stb__malloc_final(STB__FIXSIZE(sz));
+ if (p == NULL) p = stb__malloc_final(STB__FIXSIZE(sz));
+ if (p == NULL) {
+ ++stb__malloc_failure;
+ #ifdef STB_MALLOC_WRAPPER_DEBUG
+ stb_malloc_checkall();
+ #endif
+ return p;
+ }
+ #ifdef STB_MALLOC_WRAPPER_DEBUG
+ * (int *) STB__ptr(p,0) = STB__FIXSIZE(sz);
+ * (unsigned int *) STB__ptr(p,4) = STB__SIG;
+ * (unsigned int *) STB__ptr(p,8) = STB__SIG;
+ * (unsigned int *) STB__ptr(p,12) = STB__SIG;
+ * (unsigned int *) STB__ptr(p,STB__FIXSIZE(sz)-4) = STB__SIG+1;
+ * (unsigned int *) STB__ptr(p,STB__FIXSIZE(sz)-8) = STB__SIG+1;
+ * (unsigned int *) STB__ptr(p,STB__FIXSIZE(sz)-12) = STB__SIG+1;
+ * (unsigned int *) STB__ptr(p,STB__FIXSIZE(sz)-16) = STB__SIG+1;
+ p = STB__ptr(p, STB__BIAS);
+ #endif
+ stb_wrapper_malloc(p,sz,file,line);
+ return p;
+ }
+
+ void * stb__realloc(void *p, size_t sz, char *file, int line)
+ {
+ void *q;
+
+ stb_mcheck_all();
+ if (p == NULL) return stb__malloc(sz,file,line);
+ if (sz == 0 ) { stb__free(p,file,line); return NULL; }
+
+ #ifdef STB_MALLOC_WRAPPER_DEBUG
+ stb_mcheck(p);
+ p = STB__ptr(p,-STB__BIAS);
+ #endif
+ #ifdef STB_MALLOC_WRAPPER_PAGED
+ {
+ size_t n = stb_wrapper_allocsize(STB__ptr(p,STB__BIAS));
+ if (!n)
+ stb_wrapper_check(STB__ptr(p,STB__BIAS));
+ q = stb__realloc_final(p, STB__FIXSIZE(sz), STB__FIXSIZE(n));
+ }
+ #else
+ q = realloc(p, STB__FIXSIZE(sz));
+ #endif
+ if (q == NULL)
+ return ++stb__malloc_failure, q;
+ #ifdef STB_MALLOC_WRAPPER_DEBUG
+ * (int *) STB__ptr(q,0) = STB__FIXSIZE(sz);
+ * (unsigned int *) STB__ptr(q,4) = STB__SIG;
+ * (unsigned int *) STB__ptr(q,8) = STB__SIG;
+ * (unsigned int *) STB__ptr(q,12) = STB__SIG;
+ * (unsigned int *) STB__ptr(q,STB__FIXSIZE(sz)-4) = STB__SIG+1;
+ * (unsigned int *) STB__ptr(q,STB__FIXSIZE(sz)-8) = STB__SIG+1;
+ * (unsigned int *) STB__ptr(q,STB__FIXSIZE(sz)-12) = STB__SIG+1;
+ * (unsigned int *) STB__ptr(q,STB__FIXSIZE(sz)-16) = STB__SIG+1;
+
+ q = STB__ptr(q, STB__BIAS);
+ p = STB__ptr(p, STB__BIAS);
+ #endif
+ stb_wrapper_realloc(p,q,sz,file,line);
+ return q;
+ }
+
+ STB_EXTERN int stb_log2_ceil(size_t);
+ static void *stb__calloc(size_t n, size_t sz, char *file, int line)
+ {
+ void *q;
+ stb_mcheck_all();
+ if (n == 0 || sz == 0) return NULL;
+ if (stb_log2_ceil(n) + stb_log2_ceil(sz) >= 32) return NULL;
+ q = stb__malloc(n*sz, file, line);
+ if (q) memset(q, 0, n*sz);
+ return q;
+ }
+
+ char * stb__strdup(char *s, char *file, int line)
+ {
+ char *p;
+ stb_mcheck_all();
+ p = stb__malloc(strlen(s)+1, file, line);
+ if (!p) return p;
+ stb_p_strcpy_s(p, strlen(s)+1, s);
+ return p;
+ }
+ #endif // STB_DEFINE
+
+ #ifdef STB_FASTMALLOC
+ #undef malloc
+ #undef realloc
+ #undef free
+ #undef strdup
+ #undef calloc
+ #endif
+
+ // include everything that might define these, BEFORE making macros
+ #include
+ #include
+ #include
+
+ #define malloc(s) stb__malloc ( s, __FILE__, __LINE__)
+ #define realloc(p,s) stb__realloc(p,s, __FILE__, __LINE__)
+ #define calloc(n,s) stb__calloc (n,s, __FILE__, __LINE__)
+ #define free(p) stb__free (p, __FILE__, __LINE__)
+ #define strdup(p) stb__strdup (p, __FILE__, __LINE__)
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Windows pretty display
+//
+
+STB_EXTERN void stbprint(const char *fmt, ...);
+STB_EXTERN char *stb_sprintf(const char *fmt, ...);
+STB_EXTERN char *stb_mprintf(const char *fmt, ...);
+STB_EXTERN int stb_snprintf(char *s, size_t n, const char *fmt, ...);
+STB_EXTERN int stb_vsnprintf(char *s, size_t n, const char *fmt, va_list v);
+
+#ifdef STB_DEFINE
+int stb_vsnprintf(char *s, size_t n, const char *fmt, va_list v)
+{
+ int res;
+ #ifdef _WIN32
+ #ifdef __STDC_WANT_SECURE_LIB__
+ res = _vsnprintf_s(s, n, _TRUNCATE, fmt, v);
+ #else
+ res = stb_p_vsnprintf(s,n,fmt,v);
+ #endif
+ #else
+ res = vsnprintf(s,n,fmt,v);
+ #endif
+ if (n) s[n-1] = 0;
+ // Unix returns length output would require, Windows returns negative when truncated.
+ return (res >= (int) n || res < 0) ? -1 : res;
+}
+
+int stb_snprintf(char *s, size_t n, const char *fmt, ...)
+{
+ int res;
+ va_list v;
+ va_start(v,fmt);
+ res = stb_vsnprintf(s, n, fmt, v);
+ va_end(v);
+ return res;
+}
+
+char *stb_sprintf(const char *fmt, ...)
+{
+ static char buffer[1024];
+ va_list v;
+ va_start(v,fmt);
+ stb_vsnprintf(buffer,1024,fmt,v);
+ va_end(v);
+ return buffer;
+}
+
+char *stb_mprintf(const char *fmt, ...)
+{
+ static char buffer[1024];
+ va_list v;
+ va_start(v,fmt);
+ stb_vsnprintf(buffer,1024,fmt,v);
+ va_end(v);
+ return stb_p_strdup(buffer);
+}
+
+#ifdef _WIN32
+
+#ifndef _WINDOWS_
+STB_EXTERN __declspec(dllimport) int __stdcall WriteConsoleA(void *, const void *, unsigned int, unsigned int *, void *);
+STB_EXTERN __declspec(dllimport) void * __stdcall GetStdHandle(unsigned int);
+STB_EXTERN __declspec(dllimport) int __stdcall SetConsoleTextAttribute(void *, unsigned short);
+#endif
+
+static void stb__print_one(void *handle, char *s, ptrdiff_t len)
+{
+ if (len)
+ if (0==WriteConsoleA(handle, s, (unsigned) len, NULL,NULL))
+ // if it fails, maybe redirected, so output normally...
+ // but it's supriously reporting failure now on Win7 and later
+ {}//fwrite(s, 1, (unsigned) len, stdout);
+}
+
+static void stb__print(char *s)
+{
+ void *handle = GetStdHandle((unsigned int) -11); // STD_OUTPUT_HANDLE
+ int pad=0; // number of padding characters to add
+
+ char *t = s;
+ while (*s) {
+ int lpad;
+ while (*s && *s != '{') {
+ if (pad) {
+ if (*s == '\r' || *s == '\n')
+ pad = 0;
+ else if (s[0] == ' ' && s[1] == ' ') {
+ stb__print_one(handle, t, s-t);
+ t = s;
+ while (pad) {
+ stb__print_one(handle, t, 1);
+ --pad;
+ }
+ }
+ }
+ ++s;
+ }
+ if (!*s) break;
+ stb__print_one(handle, t, s-t);
+ if (s[1] == '{') {
+ ++s;
+ continue;
+ }
+
+ if (s[1] == '#') {
+ t = s+3;
+ if (isxdigit(s[2]))
+ if (isdigit(s[2]))
+ SetConsoleTextAttribute(handle, s[2] - '0');
+ else
+ SetConsoleTextAttribute(handle, tolower(s[2]) - 'a' + 10);
+ else {
+ SetConsoleTextAttribute(handle, 0x0f);
+ t=s+2;
+ }
+ } else if (s[1] == '!') {
+ SetConsoleTextAttribute(handle, 0x0c);
+ t = s+2;
+ } else if (s[1] == '@') {
+ SetConsoleTextAttribute(handle, 0x09);
+ t = s+2;
+ } else if (s[1] == '$') {
+ SetConsoleTextAttribute(handle, 0x0a);
+ t = s+2;
+ } else {
+ SetConsoleTextAttribute(handle, 0x08); // 0,7,8,15 => shades of grey
+ t = s+1;
+ }
+
+ lpad = (int) (t-s);
+ s = t;
+ while (*s && *s != '}') ++s;
+ if (!*s) break;
+ stb__print_one(handle, t, s-t);
+ if (s[1] == '}') {
+ t = s+2;
+ } else {
+ pad += 1+lpad;
+ t = s+1;
+ }
+ s=t;
+ SetConsoleTextAttribute(handle, 0x07);
+ }
+ stb__print_one(handle, t, s-t);
+ SetConsoleTextAttribute(handle, 0x07);
+}
+
+void stbprint(const char *fmt, ...)
+{
+ int res;
+ char buffer[1024];
+ char *tbuf = buffer;
+ va_list v;
+
+ va_start(v,fmt);
+ res = stb_vsnprintf(buffer, sizeof(buffer), fmt, v);
+ va_end(v);
+
+ if (res < 0) {
+ tbuf = (char *) malloc(16384);
+ va_start(v,fmt);
+ res = stb_vsnprintf(tbuf,16384, fmt, v);
+ va_end(v);
+ tbuf[16383] = 0;
+ }
+
+ stb__print(tbuf);
+
+ if (tbuf != buffer)
+ free(tbuf);
+}
+
+#else // _WIN32
+void stbprint(const char *fmt, ...)
+{
+ va_list v;
+ va_start(v,fmt);
+ vprintf(fmt,v);
+ va_end(v);
+}
+#endif // _WIN32
+#endif // STB_DEFINE
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Windows UTF8 filename handling
+//
+// Windows stupidly treats 8-bit filenames as some dopey code page,
+// rather than utf-8. If we want to use utf8 filenames, we have to
+// convert them to WCHAR explicitly and call WCHAR versions of the
+// file functions. So, ok, we do.
+
+
+#ifdef _WIN32
+ #define stb__fopen(x,y) stb_p_wfopen((const wchar_t *)stb__from_utf8(x), (const wchar_t *)stb__from_utf8_alt(y))
+ #define stb__windows(x,y) x
+#else
+ #define stb__fopen(x,y) stb_p_fopen(x,y)
+ #define stb__windows(x,y) y
+#endif
+
+
+typedef unsigned short stb__wchar;
+
+STB_EXTERN stb__wchar * stb_from_utf8(stb__wchar *buffer, const char *str, int n);
+STB_EXTERN char * stb_to_utf8 (char *buffer, const stb__wchar *str, int n);
+
+STB_EXTERN stb__wchar *stb__from_utf8(const char *str);
+STB_EXTERN stb__wchar *stb__from_utf8_alt(const char *str);
+STB_EXTERN char *stb__to_utf8(const stb__wchar *str);
+
+
+#ifdef STB_DEFINE
+stb__wchar * stb_from_utf8(stb__wchar *buffer, const char *ostr, int n)
+{
+ unsigned char *str = (unsigned char *) ostr;
+ stb_uint32 c;
+ int i=0;
+ --n;
+ while (*str) {
+ if (i >= n)
+ return NULL;
+ if (!(*str & 0x80))
+ buffer[i++] = *str++;
+ else if ((*str & 0xe0) == 0xc0) {
+ if (*str < 0xc2) return NULL;
+ c = (*str++ & 0x1f) << 6;
+ if ((*str & 0xc0) != 0x80) return NULL;
+ buffer[i++] = c + (*str++ & 0x3f);
+ } else if ((*str & 0xf0) == 0xe0) {
+ if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return NULL;
+ if (*str == 0xed && str[1] > 0x9f) return NULL; // str[1] < 0x80 is checked below
+ c = (*str++ & 0x0f) << 12;
+ if ((*str & 0xc0) != 0x80) return NULL;
+ c += (*str++ & 0x3f) << 6;
+ if ((*str & 0xc0) != 0x80) return NULL;
+ buffer[i++] = c + (*str++ & 0x3f);
+ } else if ((*str & 0xf8) == 0xf0) {
+ if (*str > 0xf4) return NULL;
+ if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return NULL;
+ if (*str == 0xf4 && str[1] > 0x8f) return NULL; // str[1] < 0x80 is checked below
+ c = (*str++ & 0x07) << 18;
+ if ((*str & 0xc0) != 0x80) return NULL;
+ c += (*str++ & 0x3f) << 12;
+ if ((*str & 0xc0) != 0x80) return NULL;
+ c += (*str++ & 0x3f) << 6;
+ if ((*str & 0xc0) != 0x80) return NULL;
+ c += (*str++ & 0x3f);
+ // utf-8 encodings of values used in surrogate pairs are invalid
+ if ((c & 0xFFFFF800) == 0xD800) return NULL;
+ if (c >= 0x10000) {
+ c -= 0x10000;
+ if (i + 2 > n) return NULL;
+ buffer[i++] = 0xD800 | (0x3ff & (c >> 10));
+ buffer[i++] = 0xDC00 | (0x3ff & (c ));
+ }
+ } else
+ return NULL;
+ }
+ buffer[i] = 0;
+ return buffer;
+}
+
+char * stb_to_utf8(char *buffer, const stb__wchar *str, int n)
+{
+ int i=0;
+ --n;
+ while (*str) {
+ if (*str < 0x80) {
+ if (i+1 > n) return NULL;
+ buffer[i++] = (char) *str++;
+ } else if (*str < 0x800) {
+ if (i+2 > n) return NULL;
+ buffer[i++] = 0xc0 + (*str >> 6);
+ buffer[i++] = 0x80 + (*str & 0x3f);
+ str += 1;
+ } else if (*str >= 0xd800 && *str < 0xdc00) {
+ stb_uint32 c;
+ if (i+4 > n) return NULL;
+ c = ((str[0] - 0xd800) << 10) + ((str[1]) - 0xdc00) + 0x10000;
+ buffer[i++] = 0xf0 + (c >> 18);
+ buffer[i++] = 0x80 + ((c >> 12) & 0x3f);
+ buffer[i++] = 0x80 + ((c >> 6) & 0x3f);
+ buffer[i++] = 0x80 + ((c ) & 0x3f);
+ str += 2;
+ } else if (*str >= 0xdc00 && *str < 0xe000) {
+ return NULL;
+ } else {
+ if (i+3 > n) return NULL;
+ buffer[i++] = 0xe0 + (*str >> 12);
+ buffer[i++] = 0x80 + ((*str >> 6) & 0x3f);
+ buffer[i++] = 0x80 + ((*str ) & 0x3f);
+ str += 1;
+ }
+ }
+ buffer[i] = 0;
+ return buffer;
+}
+
+stb__wchar *stb__from_utf8(const char *str)
+{
+ static stb__wchar buffer[4096];
+ return stb_from_utf8(buffer, str, 4096);
+}
+
+stb__wchar *stb__from_utf8_alt(const char *str)
+{
+ static stb__wchar buffer[4096];
+ return stb_from_utf8(buffer, str, 4096);
+}
+
+char *stb__to_utf8(const stb__wchar *str)
+{
+ static char buffer[4096];
+ return stb_to_utf8(buffer, str, 4096);
+}
+
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Miscellany
+//
+
+STB_EXTERN void stb_fatal(const char *fmt, ...);
+STB_EXTERN void stb_(char *fmt, ...);
+STB_EXTERN void stb_append_to_file(char *file, char *fmt, ...);
+STB_EXTERN void stb_log(int active);
+STB_EXTERN void stb_log_fileline(int active);
+STB_EXTERN void stb_log_name(char *filename);
+
+STB_EXTERN void stb_swap(void *p, void *q, size_t sz);
+STB_EXTERN void *stb_copy(void *p, size_t sz);
+STB_EXTERN void stb_pointer_array_free(void *p, int len);
+STB_EXTERN void **stb_array_block_alloc(int count, int blocksize);
+
+#define stb_arrcount(x) (sizeof(x)/sizeof((x)[0]))
+
+
+STB_EXTERN int stb__record_fileline(const char *f, int n);
+
+#ifdef STB_DEFINE
+
+static char *stb__file;
+static int stb__line;
+
+int stb__record_fileline(const char *f, int n)
+{
+ stb__file = (char*) f;
+ stb__line = n;
+ return 0;
+}
+
+void stb_fatal(const char *s, ...)
+{
+ va_list a;
+ if (stb__file)
+ fprintf(stderr, "[%s:%d] ", stb__file, stb__line);
+ va_start(a,s);
+ fputs("Fatal error: ", stderr);
+ vfprintf(stderr, s, a);
+ va_end(a);
+ fputs("\n", stderr);
+ #ifdef STB_DEBUG
+ #ifdef _MSC_VER
+ #ifndef STB_PTR64
+ __asm int 3; // trap to debugger!
+ #else
+ __debugbreak();
+ #endif
+ #else
+ __builtin_trap();
+ #endif
+ #endif
+ exit(1);
+}
+
+static int stb__log_active=1, stb__log_fileline=1;
+
+void stb_log(int active)
+{
+ stb__log_active = active;
+}
+
+void stb_log_fileline(int active)
+{
+ stb__log_fileline = active;
+}
+
+#ifdef STB_NO_STB_STRINGS
+const char *stb__log_filename = "temp.log";
+#else
+const char *stb__log_filename = "stb.log";
+#endif
+
+void stb_log_name(char *s)
+{
+ stb__log_filename = s;
+}
+
+void stb_(char *s, ...)
+{
+ if (stb__log_active) {
+ FILE *f = stb_p_fopen(stb__log_filename, "a");
+ if (f) {
+ va_list a;
+ if (stb__log_fileline && stb__file)
+ fprintf(f, "[%s:%4d] ", stb__file, stb__line);
+ va_start(a,s);
+ vfprintf(f, s, a);
+ va_end(a);
+ fputs("\n", f);
+ fclose(f);
+ }
+ }
+}
+
+void stb_append_to_file(char *filename, char *s, ...)
+{
+ FILE *f = stb_p_fopen(filename, "a");
+ if (f) {
+ va_list a;
+ va_start(a,s);
+ vfprintf(f, s, a);
+ va_end(a);
+ fputs("\n", f);
+ fclose(f);
+ }
+}
+
+
+typedef struct { char d[4]; } stb__4;
+typedef struct { char d[8]; } stb__8;
+
+// optimize the small cases, though you shouldn't be calling this for those!
+void stb_swap(void *p, void *q, size_t sz)
+{
+ char buffer[256];
+ if (p == q) return;
+ if (sz == 4) {
+ stb__4 temp = * ( stb__4 *) p;
+ * (stb__4 *) p = * ( stb__4 *) q;
+ * (stb__4 *) q = temp;
+ return;
+ } else if (sz == 8) {
+ stb__8 temp = * ( stb__8 *) p;
+ * (stb__8 *) p = * ( stb__8 *) q;
+ * (stb__8 *) q = temp;
+ return;
+ }
+
+ while (sz > sizeof(buffer)) {
+ stb_swap(p, q, sizeof(buffer));
+ p = (char *) p + sizeof(buffer);
+ q = (char *) q + sizeof(buffer);
+ sz -= sizeof(buffer);
+ }
+
+ memcpy(buffer, p , sz);
+ memcpy(p , q , sz);
+ memcpy(q , buffer, sz);
+}
+
+void *stb_copy(void *p, size_t sz)
+{
+ void *q = malloc(sz);
+ memcpy(q, p, sz);
+ return q;
+}
+
+void stb_pointer_array_free(void *q, int len)
+{
+ void **p = (void **) q;
+ int i;
+ for (i=0; i < len; ++i)
+ free(p[i]);
+}
+
+void **stb_array_block_alloc(int count, int blocksize)
+{
+ int i;
+ char *p = (char *) malloc(sizeof(void *) * count + count * blocksize);
+ void **q;
+ if (p == NULL) return NULL;
+ q = (void **) p;
+ p += sizeof(void *) * count;
+ for (i=0; i < count; ++i)
+ q[i] = p + i * blocksize;
+ return q;
+}
+#endif
+
+#ifdef STB_DEBUG
+ // tricky hack to allow recording FILE,LINE even in varargs functions
+ #define STB__RECORD_FILE(x) (stb__record_fileline(__FILE__, __LINE__),(x))
+ #define stb_log STB__RECORD_FILE(stb_log)
+ #define stb_ STB__RECORD_FILE(stb_)
+ #ifndef STB_FATAL_CLEAN
+ #define stb_fatal STB__RECORD_FILE(stb_fatal)
+ #endif
+ #define STB__DEBUG(x) x
+#else
+ #define STB__DEBUG(x)
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// stb_temp
+//
+
+#define stb_temp(block, sz) stb__temp(block, sizeof(block), (sz))
+
+STB_EXTERN void * stb__temp(void *b, int b_sz, int want_sz);
+STB_EXTERN void stb_tempfree(void *block, void *ptr);
+
+#ifdef STB_DEFINE
+
+void * stb__temp(void *b, int b_sz, int want_sz)
+{
+ if (b_sz >= want_sz)
+ return b;
+ else
+ return malloc(want_sz);
+}
+
+void stb_tempfree(void *b, void *p)
+{
+ if (p != b)
+ free(p);
+}
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// math/sampling operations
+//
+
+
+#define stb_lerp(t,a,b) ( (a) + (t) * (float) ((b)-(a)) )
+#define stb_unlerp(t,a,b) ( ((t) - (a)) / (float) ((b) - (a)) )
+
+#define stb_clamp(x,xmin,xmax) ((x) < (xmin) ? (xmin) : (x) > (xmax) ? (xmax) : (x))
+
+STB_EXTERN void stb_newell_normal(float *normal, int num_vert, float **vert, int normalize);
+STB_EXTERN int stb_box_face_vertex_axis_side(int face_number, int vertex_number, int axis);
+STB_EXTERN void stb_linear_controller(float *curpos, float target_pos, float acc, float deacc, float dt);
+
+STB_EXTERN int stb_float_eq(float x, float y, float delta, int max_ulps);
+STB_EXTERN int stb_is_prime(unsigned int m);
+STB_EXTERN unsigned int stb_power_of_two_nearest_prime(int n);
+
+STB_EXTERN float stb_smoothstep(float t);
+STB_EXTERN float stb_cubic_bezier_1d(float t, float p0, float p1, float p2, float p3);
+
+STB_EXTERN double stb_linear_remap(double x, double a, double b,
+ double c, double d);
+
+#ifdef STB_DEFINE
+float stb_smoothstep(float t)
+{
+ return (3 - 2*t)*(t*t);
+}
+
+float stb_cubic_bezier_1d(float t, float p0, float p1, float p2, float p3)
+{
+ float it = 1-t;
+ return it*it*it*p0 + 3*it*it*t*p1 + 3*it*t*t*p2 + t*t*t*p3;
+}
+
+void stb_newell_normal(float *normal, int num_vert, float **vert, int normalize)
+{
+ int i,j;
+ float p;
+ normal[0] = normal[1] = normal[2] = 0;
+ for (i=num_vert-1,j=0; j < num_vert; i=j++) {
+ float *u = vert[i];
+ float *v = vert[j];
+ normal[0] += (u[1] - v[1]) * (u[2] + v[2]);
+ normal[1] += (u[2] - v[2]) * (u[0] + v[0]);
+ normal[2] += (u[0] - v[0]) * (u[1] + v[1]);
+ }
+ if (normalize) {
+ p = normal[0]*normal[0] + normal[1]*normal[1] + normal[2]*normal[2];
+ p = (float) (1.0 / sqrt(p));
+ normal[0] *= p;
+ normal[1] *= p;
+ normal[2] *= p;
+ }
+}
+
+int stb_box_face_vertex_axis_side(int face_number, int vertex_number, int axis)
+{
+ static int box_vertices[6][4][3] =
+ {
+ { { 1,1,1 }, { 1,0,1 }, { 1,0,0 }, { 1,1,0 } },
+ { { 0,0,0 }, { 0,0,1 }, { 0,1,1 }, { 0,1,0 } },
+ { { 0,0,0 }, { 0,1,0 }, { 1,1,0 }, { 1,0,0 } },
+ { { 0,0,0 }, { 1,0,0 }, { 1,0,1 }, { 0,0,1 } },
+ { { 1,1,1 }, { 0,1,1 }, { 0,0,1 }, { 1,0,1 } },
+ { { 1,1,1 }, { 1,1,0 }, { 0,1,0 }, { 0,1,1 } },
+ };
+ assert(face_number >= 0 && face_number < 6);
+ assert(vertex_number >= 0 && vertex_number < 4);
+ assert(axis >= 0 && axis < 3);
+ return box_vertices[face_number][vertex_number][axis];
+}
+
+void stb_linear_controller(float *curpos, float target_pos, float acc, float deacc, float dt)
+{
+ float sign = 1, p, cp = *curpos;
+ if (cp == target_pos) return;
+ if (target_pos < cp) {
+ target_pos = -target_pos;
+ cp = -cp;
+ sign = -1;
+ }
+ // first decelerate
+ if (cp < 0) {
+ p = cp + deacc * dt;
+ if (p > 0) {
+ p = 0;
+ dt = dt - cp / deacc;
+ if (dt < 0) dt = 0;
+ } else {
+ dt = 0;
+ }
+ cp = p;
+ }
+ // now accelerate
+ p = cp + acc*dt;
+ if (p > target_pos) p = target_pos;
+ *curpos = p * sign;
+ // @TODO: testing
+}
+
+float stb_quadratic_controller(float target_pos, float curpos, float maxvel, float maxacc, float dt, float *curvel)
+{
+ return 0; // @TODO
+}
+
+int stb_float_eq(float x, float y, float delta, int max_ulps)
+{
+ if (fabs(x-y) <= delta) return 1;
+ if (abs(*(int *)&x - *(int *)&y) <= max_ulps) return 1;
+ return 0;
+}
+
+int stb_is_prime(unsigned int m)
+{
+ unsigned int i,j;
+ if (m < 2) return 0;
+ if (m == 2) return 1;
+ if (!(m & 1)) return 0;
+ if (m % 3 == 0) return (m == 3);
+ for (i=5; (j=i*i), j <= m && j > i; i += 6) {
+ if (m % i == 0) return 0;
+ if (m % (i+2) == 0) return 0;
+ }
+ return 1;
+}
+
+unsigned int stb_power_of_two_nearest_prime(int n)
+{
+ static signed char tab[32] = { 0,0,0,0,1,0,-1,0,1,-1,-1,3,-1,0,-1,2,1,
+ 0,2,0,-1,-4,-1,5,-1,18,-2,15,2,-1,2,0 };
+ if (!tab[0]) {
+ int i;
+ for (i=0; i < 32; ++i)
+ tab[i] = (1 << i) + 2*tab[i] - 1;
+ tab[1] = 2;
+ tab[0] = 1;
+ }
+ if (n >= 32) return 0xfffffffb;
+ return tab[n];
+}
+
+double stb_linear_remap(double x, double x_min, double x_max,
+ double out_min, double out_max)
+{
+ return stb_lerp(stb_unlerp(x,x_min,x_max),out_min,out_max);
+}
+#endif
+
+// create a macro so it's faster, but you can get at the function pointer
+#define stb_linear_remap(t,a,b,c,d) stb_lerp(stb_unlerp(t,a,b),c,d)
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// bit operations
+//
+
+#define stb_big32(c) (((c)[0]<<24) + (c)[1]*65536 + (c)[2]*256 + (c)[3])
+#define stb_little32(c) (((c)[3]<<24) + (c)[2]*65536 + (c)[1]*256 + (c)[0])
+#define stb_big16(c) ((c)[0]*256 + (c)[1])
+#define stb_little16(c) ((c)[1]*256 + (c)[0])
+
+STB_EXTERN int stb_bitcount(unsigned int a);
+STB_EXTERN unsigned int stb_bitreverse8(unsigned char n);
+STB_EXTERN unsigned int stb_bitreverse(unsigned int n);
+
+STB_EXTERN int stb_is_pow2(size_t);
+STB_EXTERN int stb_log2_ceil(size_t);
+STB_EXTERN int stb_log2_floor(size_t);
+
+STB_EXTERN int stb_lowbit8(unsigned int n);
+STB_EXTERN int stb_highbit8(unsigned int n);
+
+#ifdef STB_DEFINE
+int stb_bitcount(unsigned int a)
+{
+ a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2
+ a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4
+ a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits
+ a = (a + (a >> 8)); // max 16 per 8 bits
+ a = (a + (a >> 16)); // max 32 per 8 bits
+ return a & 0xff;
+}
+
+unsigned int stb_bitreverse8(unsigned char n)
+{
+ n = ((n & 0xAA) >> 1) + ((n & 0x55) << 1);
+ n = ((n & 0xCC) >> 2) + ((n & 0x33) << 2);
+ return (unsigned char) ((n >> 4) + (n << 4));
+}
+
+unsigned int stb_bitreverse(unsigned int n)
+{
+ n = ((n & 0xAAAAAAAA) >> 1) | ((n & 0x55555555) << 1);
+ n = ((n & 0xCCCCCCCC) >> 2) | ((n & 0x33333333) << 2);
+ n = ((n & 0xF0F0F0F0) >> 4) | ((n & 0x0F0F0F0F) << 4);
+ n = ((n & 0xFF00FF00) >> 8) | ((n & 0x00FF00FF) << 8);
+ return (n >> 16) | (n << 16);
+}
+
+int stb_is_pow2(size_t n)
+{
+ return (n & (n-1)) == 0;
+}
+
+// tricky use of 4-bit table to identify 5 bit positions (note the '-1')
+// 3-bit table would require another tree level; 5-bit table wouldn't save one
+#if defined(_WIN32) && !defined(__MINGW32__)
+#pragma warning(push)
+#pragma warning(disable: 4035) // disable warning about no return value
+int stb_log2_floor(size_t n)
+{
+ #if _MSC_VER > 1700
+ unsigned long i;
+ #ifdef STB_PTR64
+ _BitScanReverse64(&i, n);
+ #else
+ _BitScanReverse(&i, n);
+ #endif
+ return i != 0 ? i : -1;
+ #else
+ __asm {
+ bsr eax,n
+ jnz done
+ mov eax,-1
+ }
+ done:;
+ #endif
+}
+#pragma warning(pop)
+#else
+int stb_log2_floor(size_t n)
+{
+ static signed char log2_4[16] = { -1,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3 };
+
+#ifdef STB_PTR64
+ if (n >= ((size_t) 1u << 32))
+ return stb_log2_floor(n >> 32);
+#endif
+
+ // 2 compares if n < 16, 3 compares otherwise
+ if (n < (1U << 14))
+ if (n < (1U << 4)) return 0 + log2_4[n ];
+ else if (n < (1U << 9)) return 5 + log2_4[n >> 5];
+ else return 10 + log2_4[n >> 10];
+ else if (n < (1U << 24))
+ if (n < (1U << 19)) return 15 + log2_4[n >> 15];
+ else return 20 + log2_4[n >> 20];
+ else if (n < (1U << 29)) return 25 + log2_4[n >> 25];
+ else return 30 + log2_4[n >> 30];
+}
+#endif
+
+// define ceil from floor
+int stb_log2_ceil(size_t n)
+{
+ if (stb_is_pow2(n)) return stb_log2_floor(n);
+ else return 1 + stb_log2_floor(n);
+}
+
+int stb_highbit8(unsigned int n)
+{
+ return stb_log2_ceil(n&255);
+}
+
+int stb_lowbit8(unsigned int n)
+{
+ static signed char lowbit4[16] = { -1,0,1,0, 2,0,1,0, 3,0,1,0, 2,0,1,0 };
+ int k = lowbit4[n & 15];
+ if (k >= 0) return k;
+ k = lowbit4[(n >> 4) & 15];
+ if (k >= 0) return k+4;
+ return k;
+}
+#endif
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// qsort Compare Routines
+//
+
+#ifdef _WIN32
+ #define stb_stricmp(a,b) stb_p_stricmp(a,b)
+ #define stb_strnicmp(a,b,n) stb_p_strnicmp(a,b,n)
+#else
+ #define stb_stricmp(a,b) strcasecmp(a,b)
+ #define stb_strnicmp(a,b,n) strncasecmp(a,b,n)
+#endif
+
+
+STB_EXTERN int (*stb_intcmp(int offset))(const void *a, const void *b);
+STB_EXTERN int (*stb_intcmprev(int offset))(const void *a, const void *b);
+STB_EXTERN int (*stb_qsort_strcmp(int offset))(const void *a, const void *b);
+STB_EXTERN int (*stb_qsort_stricmp(int offset))(const void *a, const void *b);
+STB_EXTERN int (*stb_floatcmp(int offset))(const void *a, const void *b);
+STB_EXTERN int (*stb_doublecmp(int offset))(const void *a, const void *b);
+STB_EXTERN int (*stb_charcmp(int offset))(const void *a, const void *b);
+
+#ifdef STB_DEFINE
+static int stb__intcmpoffset, stb__ucharcmpoffset, stb__strcmpoffset;
+static int stb__floatcmpoffset, stb__doublecmpoffset;
+static int stb__memcmpoffset, stb__memcmpsize;
+
+int stb__intcmp(const void *a, const void *b)
+{
+ const int p = *(const int *) ((const char *) a + stb__intcmpoffset);
+ const int q = *(const int *) ((const char *) b + stb__intcmpoffset);
+ return p < q ? -1 : p > q;
+}
+
+int stb__intcmprev(const void *a, const void *b)
+{
+ const int p = *(const int *) ((const char *) a + stb__intcmpoffset);
+ const int q = *(const int *) ((const char *) b + stb__intcmpoffset);
+ return q < p ? -1 : q > p;
+}
+
+int stb__ucharcmp(const void *a, const void *b)
+{
+ const int p = *(const unsigned char *) ((const char *) a + stb__ucharcmpoffset);
+ const int q = *(const unsigned char *) ((const char *) b + stb__ucharcmpoffset);
+ return p < q ? -1 : p > q;
+}
+
+int stb__floatcmp(const void *a, const void *b)
+{
+ const float p = *(const float *) ((const char *) a + stb__floatcmpoffset);
+ const float q = *(const float *) ((const char *) b + stb__floatcmpoffset);
+ return p < q ? -1 : p > q;
+}
+
+int stb__doublecmp(const void *a, const void *b)
+{
+ const double p = *(const double *) ((const char *) a + stb__doublecmpoffset);
+ const double q = *(const double *) ((const char *) b + stb__doublecmpoffset);
+ return p < q ? -1 : p > q;
+}
+
+int stb__qsort_strcmp(const void *a, const void *b)
+{
+ const char *p = *(const char **) ((const char *) a + stb__strcmpoffset);
+ const char *q = *(const char **) ((const char *) b + stb__strcmpoffset);
+ return strcmp(p,q);
+}
+
+int stb__qsort_stricmp(const void *a, const void *b)
+{
+ const char *p = *(const char **) ((const char *) a + stb__strcmpoffset);
+ const char *q = *(const char **) ((const char *) b + stb__strcmpoffset);
+ return stb_stricmp(p,q);
+}
+
+int stb__memcmp(const void *a, const void *b)
+{
+ return memcmp((char *) a + stb__memcmpoffset, (char *) b + stb__memcmpoffset, stb__memcmpsize);
+}
+
+int (*stb_intcmp(int offset))(const void *, const void *)
+{
+ stb__intcmpoffset = offset;
+ return &stb__intcmp;
+}
+
+int (*stb_intcmprev(int offset))(const void *, const void *)
+{
+ stb__intcmpoffset = offset;
+ return &stb__intcmprev;
+}
+
+int (*stb_ucharcmp(int offset))(const void *, const void *)
+{
+ stb__ucharcmpoffset = offset;
+ return &stb__ucharcmp;
+}
+
+int (*stb_qsort_strcmp(int offset))(const void *, const void *)
+{
+ stb__strcmpoffset = offset;
+ return &stb__qsort_strcmp;
+}
+
+int (*stb_qsort_stricmp(int offset))(const void *, const void *)
+{
+ stb__strcmpoffset = offset;
+ return &stb__qsort_stricmp;
+}
+
+int (*stb_floatcmp(int offset))(const void *, const void *)
+{
+ stb__floatcmpoffset = offset;
+ return &stb__floatcmp;
+}
+
+int (*stb_doublecmp(int offset))(const void *, const void *)
+{
+ stb__doublecmpoffset = offset;
+ return &stb__doublecmp;
+}
+
+int (*stb_memcmp(int offset, int size))(const void *, const void *)
+{
+ stb__memcmpoffset = offset;
+ stb__memcmpsize = size;
+ return &stb__memcmp;
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Binary Search Toolkit
+//
+
+typedef struct
+{
+ int minval, maxval, guess;
+ int mode, step;
+} stb_search;
+
+STB_EXTERN int stb_search_binary(stb_search *s, int minv, int maxv, int find_smallest);
+STB_EXTERN int stb_search_open(stb_search *s, int minv, int find_smallest);
+STB_EXTERN int stb_probe(stb_search *s, int compare, int *result); // return 0 when done
+
+#ifdef STB_DEFINE
+enum
+{
+ STB_probe_binary_smallest,
+ STB_probe_binary_largest,
+ STB_probe_open_smallest,
+ STB_probe_open_largest,
+};
+
+static int stb_probe_guess(stb_search *s, int *result)
+{
+ switch(s->mode) {
+ case STB_probe_binary_largest:
+ if (s->minval == s->maxval) {
+ *result = s->minval;
+ return 0;
+ }
+ assert(s->minval < s->maxval);
+ // if a < b, then a < p <= b
+ s->guess = s->minval + (((unsigned) s->maxval - s->minval + 1) >> 1);
+ break;
+
+ case STB_probe_binary_smallest:
+ if (s->minval == s->maxval) {
+ *result = s->minval;
+ return 0;
+ }
+ assert(s->minval < s->maxval);
+ // if a < b, then a <= p < b
+ s->guess = s->minval + (((unsigned) s->maxval - s->minval) >> 1);
+ break;
+ case STB_probe_open_smallest:
+ case STB_probe_open_largest:
+ s->guess = s->maxval; // guess the current maxval
+ break;
+ }
+ *result = s->guess;
+ return 1;
+}
+
+int stb_probe(stb_search *s, int compare, int *result)
+{
+ switch(s->mode) {
+ case STB_probe_open_smallest:
+ case STB_probe_open_largest: {
+ if (compare <= 0) {
+ // then it lies within minval & maxval
+ if (s->mode == STB_probe_open_smallest)
+ s->mode = STB_probe_binary_smallest;
+ else
+ s->mode = STB_probe_binary_largest;
+ } else {
+ // otherwise, we need to probe larger
+ s->minval = s->maxval + 1;
+ s->maxval = s->minval + s->step;
+ s->step += s->step;
+ }
+ break;
+ }
+ case STB_probe_binary_smallest: {
+ // if compare < 0, then s->minval <= a < p
+ // if compare = 0, then s->minval <= a <= p
+ // if compare > 0, then p < a <= s->maxval
+ if (compare <= 0)
+ s->maxval = s->guess;
+ else
+ s->minval = s->guess+1;
+ break;
+ }
+ case STB_probe_binary_largest: {
+ // if compare < 0, then s->minval <= a < p
+ // if compare = 0, then p <= a <= s->maxval
+ // if compare > 0, then p < a <= s->maxval
+ if (compare < 0)
+ s->maxval = s->guess-1;
+ else
+ s->minval = s->guess;
+ break;
+ }
+ }
+ return stb_probe_guess(s, result);
+}
+
+int stb_search_binary(stb_search *s, int minv, int maxv, int find_smallest)
+{
+ int r;
+ if (maxv < minv) return minv-1;
+ s->minval = minv;
+ s->maxval = maxv;
+ s->mode = find_smallest ? STB_probe_binary_smallest : STB_probe_binary_largest;
+ stb_probe_guess(s, &r);
+ return r;
+}
+
+int stb_search_open(stb_search *s, int minv, int find_smallest)
+{
+ int r;
+ s->step = 4;
+ s->minval = minv;
+ s->maxval = minv+s->step;
+ s->mode = find_smallest ? STB_probe_open_smallest : STB_probe_open_largest;
+ stb_probe_guess(s, &r);
+ return r;
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// String Processing
+//
+
+#define stb_prefixi(s,t) (0==stb_strnicmp((s),(t),strlen(t)))
+
+enum stb_splitpath_flag
+{
+ STB_PATH = 1,
+ STB_FILE = 2,
+ STB_EXT = 4,
+ STB_PATH_FILE = STB_PATH + STB_FILE,
+ STB_FILE_EXT = STB_FILE + STB_EXT,
+ STB_EXT_NO_PERIOD = 8,
+};
+
+STB_EXTERN char * stb_skipwhite(char *s);
+STB_EXTERN char * stb_trimwhite(char *s);
+STB_EXTERN char * stb_skipnewline(char *s);
+STB_EXTERN char * stb_strncpy(char *s, char *t, int n);
+STB_EXTERN char * stb_substr(char *t, int n);
+STB_EXTERN char * stb_duplower(char *s);
+STB_EXTERN void stb_tolower (char *s);
+STB_EXTERN char * stb_strchr2 (char *s, char p1, char p2);
+STB_EXTERN char * stb_strrchr2(char *s, char p1, char p2);
+STB_EXTERN char * stb_strtok(char *output, char *src, char *delimit);
+STB_EXTERN char * stb_strtok_keep(char *output, char *src, char *delimit);
+STB_EXTERN char * stb_strtok_invert(char *output, char *src, char *allowed);
+STB_EXTERN char * stb_dupreplace(char *s, char *find, char *replace);
+STB_EXTERN void stb_replaceinplace(char *s, char *find, char *replace);
+STB_EXTERN char * stb_splitpath(char *output, char *src, int flag);
+STB_EXTERN char * stb_splitpathdup(char *src, int flag);
+STB_EXTERN char * stb_replacedir(char *output, char *src, char *dir);
+STB_EXTERN char * stb_replaceext(char *output, char *src, char *ext);
+STB_EXTERN void stb_fixpath(char *path);
+STB_EXTERN char * stb_shorten_path_readable(char *path, int max_len);
+STB_EXTERN int stb_suffix (char *s, char *t);
+STB_EXTERN int stb_suffixi(char *s, char *t);
+STB_EXTERN int stb_prefix (char *s, char *t);
+STB_EXTERN char * stb_strichr(char *s, char t);
+STB_EXTERN char * stb_stristr(char *s, char *t);
+STB_EXTERN int stb_prefix_count(char *s, char *t);
+STB_EXTERN const char * stb_plural(int n); // "s" or ""
+STB_EXTERN size_t stb_strscpy(char *d, const char *s, size_t n);
+
+STB_EXTERN char **stb_tokens(char *src, char *delimit, int *count);
+STB_EXTERN char **stb_tokens_nested(char *src, char *delimit, int *count, char *nest_in, char *nest_out);
+STB_EXTERN char **stb_tokens_nested_empty(char *src, char *delimit, int *count, char *nest_in, char *nest_out);
+STB_EXTERN char **stb_tokens_allowempty(char *src, char *delimit, int *count);
+STB_EXTERN char **stb_tokens_stripwhite(char *src, char *delimit, int *count);
+STB_EXTERN char **stb_tokens_withdelim(char *src, char *delimit, int *count);
+STB_EXTERN char **stb_tokens_quoted(char *src, char *delimit, int *count);
+// with 'quoted', allow delimiters to appear inside quotation marks, and don't
+// strip whitespace inside them (and we delete the quotation marks unless they
+// appear back to back, in which case they're considered escaped)
+
+#ifdef STB_DEFINE
+
+size_t stb_strscpy(char *d, const char *s, size_t n)
+{
+ size_t len = strlen(s);
+ if (len >= n) {
+ if (n) d[0] = 0;
+ return 0;
+ }
+ stb_p_strcpy_s(d,n,s);
+ return len;
+}
+
+const char *stb_plural(int n)
+{
+ return n == 1 ? "" : "s";
+}
+
+int stb_prefix(char *s, char *t)
+{
+ while (*t)
+ if (*s++ != *t++)
+ return STB_FALSE;
+ return STB_TRUE;
+}
+
+int stb_prefix_count(char *s, char *t)
+{
+ int c=0;
+ while (*t) {
+ if (*s++ != *t++)
+ break;
+ ++c;
+ }
+ return c;
+}
+
+int stb_suffix(char *s, char *t)
+{
+ size_t n = strlen(s);
+ size_t m = strlen(t);
+ if (m <= n)
+ return 0 == strcmp(s+n-m, t);
+ else
+ return 0;
+}
+
+int stb_suffixi(char *s, char *t)
+{
+ size_t n = strlen(s);
+ size_t m = strlen(t);
+ if (m <= n)
+ return 0 == stb_stricmp(s+n-m, t);
+ else
+ return 0;
+}
+
+// originally I was using this table so that I could create known sentinel
+// values--e.g. change whitetable[0] to be true if I was scanning for whitespace,
+// and false if I was scanning for nonwhite. I don't appear to be using that
+// functionality anymore (I do for tokentable, though), so just replace it
+// with isspace()
+char *stb_skipwhite(char *s)
+{
+ while (isspace((unsigned char) *s)) ++s;
+ return s;
+}
+
+char *stb_skipnewline(char *s)
+{
+ if (s[0] == '\r' || s[0] == '\n') {
+ if (s[0]+s[1] == '\r' + '\n') ++s;
+ ++s;
+ }
+ return s;
+}
+
+char *stb_trimwhite(char *s)
+{
+ int i,n;
+ s = stb_skipwhite(s);
+ n = (int) strlen(s);
+ for (i=n-1; i >= 0; --i)
+ if (!isspace(s[i]))
+ break;
+ s[i+1] = 0;
+ return s;
+}
+
+char *stb_strncpy(char *s, char *t, int n)
+{
+ stb_p_strncpy_s(s,n+1,t,n);
+ s[n] = 0;
+ return s;
+}
+
+char *stb_substr(char *t, int n)
+{
+ char *a;
+ int z = (int) strlen(t);
+ if (z < n) n = z;
+ a = (char *) malloc(n+1);
+ stb_p_strncpy_s(a,n+1,t,n);
+ a[n] = 0;
+ return a;
+}
+
+char *stb_duplower(char *s)
+{
+ char *p = stb_p_strdup(s), *q = p;
+ while (*q) {
+ *q = tolower(*q);
+ ++q;
+ }
+ return p;
+}
+
+void stb_tolower(char *s)
+{
+ while (*s) {
+ *s = tolower(*s);
+ ++s;
+ }
+}
+
+char *stb_strchr2(char *s, char x, char y)
+{
+ for(; *s; ++s)
+ if (*s == x || *s == y)
+ return s;
+ return NULL;
+}
+
+char *stb_strrchr2(char *s, char x, char y)
+{
+ char *r = NULL;
+ for(; *s; ++s)
+ if (*s == x || *s == y)
+ r = s;
+ return r;
+}
+
+char *stb_strichr(char *s, char t)
+{
+ if (tolower(t) == toupper(t))
+ return strchr(s,t);
+ return stb_strchr2(s, (char) tolower(t), (char) toupper(t));
+}
+
+char *stb_stristr(char *s, char *t)
+{
+ size_t n = strlen(t);
+ char *z;
+ if (n==0) return s;
+ while ((z = stb_strichr(s, *t)) != NULL) {
+ if (0==stb_strnicmp(z, t, n))
+ return z;
+ s = z+1;
+ }
+ return NULL;
+}
+
+static char *stb_strtok_raw(char *output, char *src, char *delimit, int keep, int invert)
+{
+ if (invert) {
+ while (*src && strchr(delimit, *src) != NULL) {
+ *output++ = *src++;
+ }
+ } else {
+ while (*src && strchr(delimit, *src) == NULL) {
+ *output++ = *src++;
+ }
+ }
+ *output = 0;
+ if (keep)
+ return src;
+ else
+ return *src ? src+1 : src;
+}
+
+char *stb_strtok(char *output, char *src, char *delimit)
+{
+ return stb_strtok_raw(output, src, delimit, 0, 0);
+}
+
+char *stb_strtok_keep(char *output, char *src, char *delimit)
+{
+ return stb_strtok_raw(output, src, delimit, 1, 0);
+}
+
+char *stb_strtok_invert(char *output, char *src, char *delimit)
+{
+ return stb_strtok_raw(output, src, delimit, 1,1);
+}
+
+static char **stb_tokens_raw(char *src_, char *delimit, int *count,
+ int stripwhite, int allow_empty, char *start, char *end)
+{
+ int nested = 0;
+ unsigned char *src = (unsigned char *) src_;
+ static char stb_tokentable[256]; // rely on static initializion to 0
+ static char stable[256],etable[256];
+ char *out;
+ char **result;
+ int num=0;
+ unsigned char *s;
+
+ s = (unsigned char *) delimit; while (*s) stb_tokentable[*s++] = 1;
+ if (start) {
+ s = (unsigned char *) start; while (*s) stable[*s++] = 1;
+ s = (unsigned char *) end; if (s) while (*s) stable[*s++] = 1;
+ s = (unsigned char *) end; if (s) while (*s) etable[*s++] = 1;
+ }
+ stable[0] = 1;
+
+ // two passes through: the first time, counting how many
+ s = (unsigned char *) src;
+ while (*s) {
+ // state: just found delimiter
+ // skip further delimiters
+ if (!allow_empty) {
+ stb_tokentable[0] = 0;
+ while (stb_tokentable[*s])
+ ++s;
+ if (!*s) break;
+ }
+ ++num;
+ // skip further non-delimiters
+ stb_tokentable[0] = 1;
+ if (stripwhite == 2) { // quoted strings
+ while (!stb_tokentable[*s]) {
+ if (*s != '"')
+ ++s;
+ else {
+ ++s;
+ if (*s == '"')
+ ++s; // "" -> ", not start a string
+ else {
+ // begin a string
+ while (*s) {
+ if (s[0] == '"') {
+ if (s[1] == '"') s += 2; // "" -> "
+ else { ++s; break; } // terminating "
+ } else
+ ++s;
+ }
+ }
+ }
+ }
+ } else
+ while (nested || !stb_tokentable[*s]) {
+ if (stable[*s]) {
+ if (!*s) break;
+ if (end ? etable[*s] : nested)
+ --nested;
+ else
+ ++nested;
+ }
+ ++s;
+ }
+ if (allow_empty) {
+ if (*s) ++s;
+ }
+ }
+ // now num has the actual count... malloc our output structure
+ // need space for all the strings: strings won't be any longer than
+ // original input, since for every '\0' there's at least one delimiter
+ result = (char **) malloc(sizeof(*result) * (num+1) + (s-src+1));
+ if (result == NULL) return result;
+ out = (char *) (result + (num+1));
+ // second pass: copy out the data
+ s = (unsigned char *) src;
+ num = 0;
+ nested = 0;
+ while (*s) {
+ char *last_nonwhite;
+ // state: just found delimiter
+ // skip further delimiters
+ if (!allow_empty) {
+ stb_tokentable[0] = 0;
+ if (stripwhite)
+ while (stb_tokentable[*s] || isspace(*s))
+ ++s;
+ else
+ while (stb_tokentable[*s])
+ ++s;
+ } else if (stripwhite) {
+ while (isspace(*s)) ++s;
+ }
+ if (!*s) break;
+ // we're past any leading delimiters and whitespace
+ result[num] = out;
+ ++num;
+ // copy non-delimiters
+ stb_tokentable[0] = 1;
+ last_nonwhite = out-1;
+ if (stripwhite == 2) {
+ while (!stb_tokentable[*s]) {
+ if (*s != '"') {
+ if (!isspace(*s)) last_nonwhite = out;
+ *out++ = *s++;
+ } else {
+ ++s;
+ if (*s == '"') {
+ if (!isspace(*s)) last_nonwhite = out;
+ *out++ = *s++; // "" -> ", not start string
+ } else {
+ // begin a quoted string
+ while (*s) {
+ if (s[0] == '"') {
+ if (s[1] == '"') { *out++ = *s; s += 2; }
+ else { ++s; break; } // terminating "
+ } else
+ *out++ = *s++;
+ }
+ last_nonwhite = out-1; // all in quotes counts as non-white
+ }
+ }
+ }
+ } else {
+ while (nested || !stb_tokentable[*s]) {
+ if (!isspace(*s)) last_nonwhite = out;
+ if (stable[*s]) {
+ if (!*s) break;
+ if (end ? etable[*s] : nested)
+ --nested;
+ else
+ ++nested;
+ }
+ *out++ = *s++;
+ }
+ }
+
+ if (stripwhite) // rewind to last non-whitespace char
+ out = last_nonwhite+1;
+ *out++ = '\0';
+
+ if (*s) ++s; // skip delimiter
+ }
+ s = (unsigned char *) delimit; while (*s) stb_tokentable[*s++] = 0;
+ if (start) {
+ s = (unsigned char *) start; while (*s) stable[*s++] = 1;
+ s = (unsigned char *) end; if (s) while (*s) stable[*s++] = 1;
+ s = (unsigned char *) end; if (s) while (*s) etable[*s++] = 1;
+ }
+ if (count != NULL) *count = num;
+ result[num] = 0;
+ return result;
+}
+
+char **stb_tokens(char *src, char *delimit, int *count)
+{
+ return stb_tokens_raw(src,delimit,count,0,0,0,0);
+}
+
+char **stb_tokens_nested(char *src, char *delimit, int *count, char *nest_in, char *nest_out)
+{
+ return stb_tokens_raw(src,delimit,count,0,0,nest_in,nest_out);
+}
+
+char **stb_tokens_nested_empty(char *src, char *delimit, int *count, char *nest_in, char *nest_out)
+{
+ return stb_tokens_raw(src,delimit,count,0,1,nest_in,nest_out);
+}
+
+char **stb_tokens_allowempty(char *src, char *delimit, int *count)
+{
+ return stb_tokens_raw(src,delimit,count,0,1,0,0);
+}
+
+char **stb_tokens_stripwhite(char *src, char *delimit, int *count)
+{
+ return stb_tokens_raw(src,delimit,count,1,1,0,0);
+}
+
+char **stb_tokens_quoted(char *src, char *delimit, int *count)
+{
+ return stb_tokens_raw(src,delimit,count,2,1,0,0);
+}
+
+char *stb_dupreplace(char *src, char *find, char *replace)
+{
+ size_t len_find = strlen(find);
+ size_t len_replace = strlen(replace);
+ int count = 0;
+
+ char *s,*p,*q;
+
+ s = strstr(src, find);
+ if (s == NULL) return stb_p_strdup(src);
+ do {
+ ++count;
+ s = strstr(s + len_find, find);
+ } while (s != NULL);
+
+ p = (char *) malloc(strlen(src) + count * (len_replace - len_find) + 1);
+ if (p == NULL) return p;
+ q = p;
+ s = src;
+ for (;;) {
+ char *t = strstr(s, find);
+ if (t == NULL) {
+ stb_p_strcpy_s(q,strlen(src)+count*(len_replace-len_find)+1,s);
+ assert(strlen(p) == strlen(src) + count*(len_replace-len_find));
+ return p;
+ }
+ memcpy(q, s, t-s);
+ q += t-s;
+ memcpy(q, replace, len_replace);
+ q += len_replace;
+ s = t + len_find;
+ }
+}
+
+void stb_replaceinplace(char *src, char *find, char *replace)
+{
+ size_t len_find = strlen(find);
+ size_t len_replace = strlen(replace);
+ int delta;
+
+ char *s,*p,*q;
+
+ delta = (int) (len_replace - len_find);
+ assert(delta <= 0);
+ if (delta > 0) return;
+
+ p = strstr(src, find);
+ if (p == NULL) return;
+
+ s = q = p;
+ while (*s) {
+ memcpy(q, replace, len_replace);
+ p += len_find;
+ q += len_replace;
+ s = strstr(p, find);
+ if (s == NULL) s = p + strlen(p);
+ memmove(q, p, s-p);
+ q += s-p;
+ p = s;
+ }
+ *q = 0;
+}
+
+void stb_fixpath(char *path)
+{
+ for(; *path; ++path)
+ if (*path == '\\')
+ *path = '/';
+}
+
+void stb__add_section(char *buffer, char *data, ptrdiff_t curlen, ptrdiff_t newlen)
+{
+ if (newlen < curlen) {
+ ptrdiff_t z1 = newlen >> 1, z2 = newlen-z1;
+ memcpy(buffer, data, z1-1);
+ buffer[z1-1] = '.';
+ buffer[z1-0] = '.';
+ memcpy(buffer+z1+1, data+curlen-z2+1, z2-1);
+ } else
+ memcpy(buffer, data, curlen);
+}
+
+char * stb_shorten_path_readable(char *path, int len)
+{
+ static char buffer[1024];
+ ptrdiff_t n = strlen(path),n1,n2,r1,r2;
+ char *s;
+ if (n <= len) return path;
+ if (len > 1024) return path;
+ s = stb_strrchr2(path, '/', '\\');
+ if (s) {
+ n1 = s - path + 1;
+ n2 = n - n1;
+ ++s;
+ } else {
+ n1 = 0;
+ n2 = n;
+ s = path;
+ }
+ // now we need to reduce r1 and r2 so that they fit in len
+ if (n1 < len>>1) {
+ r1 = n1;
+ r2 = len - r1;
+ } else if (n2 < len >> 1) {
+ r2 = n2;
+ r1 = len - r2;
+ } else {
+ r1 = n1 * len / n;
+ r2 = n2 * len / n;
+ if (r1 < len>>2) r1 = len>>2, r2 = len-r1;
+ if (r2 < len>>2) r2 = len>>2, r1 = len-r2;
+ }
+ assert(r1 <= n1 && r2 <= n2);
+ if (n1)
+ stb__add_section(buffer, path, n1, r1);
+ stb__add_section(buffer+r1, s, n2, r2);
+ buffer[len] = 0;
+ return buffer;
+}
+
+static char *stb__splitpath_raw(char *buffer, char *path, int flag)
+{
+ ptrdiff_t len=0,x,y, n = (int) strlen(path), f1,f2;
+ char *s = stb_strrchr2(path, '/', '\\');
+ char *t = strrchr(path, '.');
+ if (s && t && t < s) t = NULL;
+ if (s) ++s;
+
+ if (flag == STB_EXT_NO_PERIOD)
+ flag |= STB_EXT;
+
+ if (!(flag & (STB_PATH | STB_FILE | STB_EXT))) return NULL;
+
+ f1 = s == NULL ? 0 : s-path; // start of filename
+ f2 = t == NULL ? n : t-path; // just past end of filename
+
+ if (flag & STB_PATH) {
+ x = 0; if (f1 == 0 && flag == STB_PATH) len=2;
+ } else if (flag & STB_FILE) {
+ x = f1;
+ } else {
+ x = f2;
+ if (flag & STB_EXT_NO_PERIOD)
+ if (path[x] == '.')
+ ++x;
+ }
+
+ if (flag & STB_EXT)
+ y = n;
+ else if (flag & STB_FILE)
+ y = f2;
+ else
+ y = f1;
+
+ if (buffer == NULL) {
+ buffer = (char *) malloc(y-x + len + 1);
+ if (!buffer) return NULL;
+ }
+
+ if (len) { stb_p_strcpy_s(buffer, 3, "./"); return buffer; }
+ stb_strncpy(buffer, path+(int)x, (int)(y-x));
+ return buffer;
+}
+
+char *stb_splitpath(char *output, char *src, int flag)
+{
+ return stb__splitpath_raw(output, src, flag);
+}
+
+char *stb_splitpathdup(char *src, int flag)
+{
+ return stb__splitpath_raw(NULL, src, flag);
+}
+
+char *stb_replacedir(char *output, char *src, char *dir)
+{
+ char buffer[4096];
+ stb_splitpath(buffer, src, STB_FILE | STB_EXT);
+ if (dir)
+ stb_p_sprintf(output stb_p_size(9999), "%s/%s", dir, buffer);
+ else
+ stb_p_strcpy_s(output, sizeof(buffer), buffer); // @UNSAFE
+ return output;
+}
+
+char *stb_replaceext(char *output, char *src, char *ext)
+{
+ char buffer[4096];
+ stb_splitpath(buffer, src, STB_PATH | STB_FILE);
+ if (ext)
+ stb_p_sprintf(output stb_p_size(9999), "%s.%s", buffer, ext[0] == '.' ? ext+1 : ext);
+ else
+ stb_p_strcpy_s(output, sizeof(buffer), buffer); // @UNSAFE
+ return output;
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// stb_alloc - hierarchical allocator
+//
+// inspired by http://swapped.cc/halloc
+//
+//
+// When you alloc a given block through stb_alloc, you have these choices:
+//
+// 1. does it have a parent?
+// 2. can it have children?
+// 3. can it be freed directly?
+// 4. is it transferrable?
+// 5. what is its alignment?
+//
+// Here are interesting combinations of those:
+//
+// children free transfer alignment
+// arena Y Y N n/a
+// no-overhead, chunked N N N normal
+// string pool alloc N N N 1
+// parent-ptr, chunked Y N N normal
+// low-overhead, unchunked N Y Y normal
+// general purpose alloc Y Y Y normal
+//
+// Unchunked allocations will probably return 16-aligned pointers. If
+// we 16-align the results, we have room for 4 pointers. For smaller
+// allocations that allow finer alignment, we can reduce the pointers.
+//
+// The strategy is that given a pointer, assuming it has a header (only
+// the no-overhead allocations have no header), we can determine the
+// type of the header fields, and the number of them, by stepping backwards
+// through memory and looking at the tags in the bottom bits.
+//
+// Implementation strategy:
+// chunked allocations come from the middle of chunks, and can't
+// be freed. thefore they do not need to be on a sibling chain.
+// they may need child pointers if they have children.
+//
+// chunked, with-children
+// void *parent;
+//
+// unchunked, no-children -- reduced storage
+// void *next_sibling;
+// void *prev_sibling_nextp;
+//
+// unchunked, general
+// void *first_child;
+// void *next_sibling;
+// void *prev_sibling_nextp;
+// void *chunks;
+//
+// so, if we code each of these fields with different bit patterns
+// (actually same one for next/prev/child), then we can identify which
+// each one is from the last field.
+
+STB_EXTERN void stb_free(void *p);
+STB_EXTERN void *stb_malloc_global(size_t size);
+STB_EXTERN void *stb_malloc(void *context, size_t size);
+STB_EXTERN void *stb_malloc_nofree(void *context, size_t size);
+STB_EXTERN void *stb_malloc_leaf(void *context, size_t size);
+STB_EXTERN void *stb_malloc_raw(void *context, size_t size);
+STB_EXTERN void *stb_realloc(void *ptr, size_t newsize);
+
+STB_EXTERN void stb_reassign(void *new_context, void *ptr);
+STB_EXTERN void stb_malloc_validate(void *p, void *parent);
+
+extern int stb_alloc_chunk_size ;
+extern int stb_alloc_count_free ;
+extern int stb_alloc_count_alloc;
+extern int stb_alloc_alignment ;
+
+#ifdef STB_DEFINE
+
+int stb_alloc_chunk_size = 65536;
+int stb_alloc_count_free = 0;
+int stb_alloc_count_alloc = 0;
+int stb_alloc_alignment = -16;
+
+typedef struct stb__chunk
+{
+ struct stb__chunk *next;
+ int data_left;
+ int alloc;
+} stb__chunk;
+
+typedef struct
+{
+ void * next;
+ void ** prevn;
+} stb__nochildren;
+
+typedef struct
+{
+ void ** prevn;
+ void * child;
+ void * next;
+ stb__chunk *chunks;
+} stb__alloc;
+
+typedef struct
+{
+ stb__alloc *parent;
+} stb__chunked;
+
+#define STB__PARENT 1
+#define STB__CHUNKS 2
+
+typedef enum
+{
+ STB__nochildren = 0,
+ STB__chunked = STB__PARENT,
+ STB__alloc = STB__CHUNKS,
+
+ STB__chunk_raw = 4,
+} stb__alloc_type;
+
+// these functions set the bottom bits of a pointer efficiently
+#define STB__DECODE(x,v) ((void *) ((char *) (x) - (v)))
+#define STB__ENCODE(x,v) ((void *) ((char *) (x) + (v)))
+
+#define stb__parent(z) (stb__alloc *) STB__DECODE((z)->parent, STB__PARENT)
+#define stb__chunks(z) (stb__chunk *) STB__DECODE((z)->chunks, STB__CHUNKS)
+
+#define stb__setparent(z,p) (z)->parent = (stb__alloc *) STB__ENCODE((p), STB__PARENT)
+#define stb__setchunks(z,c) (z)->chunks = (stb__chunk *) STB__ENCODE((c), STB__CHUNKS)
+
+static stb__alloc stb__alloc_global =
+{
+ NULL,
+ NULL,
+ NULL,
+ (stb__chunk *) STB__ENCODE(NULL, STB__CHUNKS)
+};
+
+static stb__alloc_type stb__identify(void *p)
+{
+ void **q = (void **) p;
+ return (stb__alloc_type) ((stb_uinta) q[-1] & 3);
+}
+
+static void *** stb__prevn(void *p)
+{
+ if (stb__identify(p) == STB__alloc) {
+ stb__alloc *s = (stb__alloc *) p - 1;
+ return &s->prevn;
+ } else {
+ stb__nochildren *s = (stb__nochildren *) p - 1;
+ return &s->prevn;
+ }
+}
+
+void stb_free(void *p)
+{
+ if (p == NULL) return;
+
+ // count frees so that unit tests can see what's happening
+ ++stb_alloc_count_free;
+
+ switch(stb__identify(p)) {
+ case STB__chunked:
+ // freeing a chunked-block with children does nothing;
+ // they only get freed when the parent does
+ // surely this is wrong, and it should free them immediately?
+ // otherwise how are they getting put on the right chain?
+ return;
+ case STB__nochildren: {
+ stb__nochildren *s = (stb__nochildren *) p - 1;
+ // unlink from sibling chain
+ *(s->prevn) = s->next;
+ if (s->next)
+ *stb__prevn(s->next) = s->prevn;
+ free(s);
+ return;
+ }
+ case STB__alloc: {
+ stb__alloc *s = (stb__alloc *) p - 1;
+ stb__chunk *c, *n;
+ void *q;
+
+ // unlink from sibling chain, if any
+ *(s->prevn) = s->next;
+ if (s->next)
+ *stb__prevn(s->next) = s->prevn;
+
+ // first free chunks
+ c = (stb__chunk *) stb__chunks(s);
+ while (c != NULL) {
+ n = c->next;
+ stb_alloc_count_free += c->alloc;
+ free(c);
+ c = n;
+ }
+
+ // validating
+ stb__setchunks(s,NULL);
+ s->prevn = NULL;
+ s->next = NULL;
+
+ // now free children
+ while ((q = s->child) != NULL) {
+ stb_free(q);
+ }
+
+ // now free self
+ free(s);
+ return;
+ }
+ default:
+ assert(0); /* NOTREACHED */
+ }
+}
+
+void stb_malloc_validate(void *p, void *parent)
+{
+ if (p == NULL) return;
+
+ switch(stb__identify(p)) {
+ case STB__chunked:
+ return;
+ case STB__nochildren: {
+ stb__nochildren *n = (stb__nochildren *) p - 1;
+ if (n->prevn)
+ assert(*n->prevn == p);
+ if (n->next) {
+ assert(*stb__prevn(n->next) == &n->next);
+ stb_malloc_validate(n, parent);
+ }
+ return;
+ }
+ case STB__alloc: {
+ stb__alloc *s = (stb__alloc *) p - 1;
+
+ if (s->prevn)
+ assert(*s->prevn == p);
+
+ if (s->child) {
+ assert(*stb__prevn(s->child) == &s->child);
+ stb_malloc_validate(s->child, p);
+ }
+
+ if (s->next) {
+ assert(*stb__prevn(s->next) == &s->next);
+ stb_malloc_validate(s->next, parent);
+ }
+ return;
+ }
+ default:
+ assert(0); /* NOTREACHED */
+ }
+}
+
+static void * stb__try_chunk(stb__chunk *c, int size, int align, int pre_align)
+{
+ char *memblock = (char *) (c+1), *q;
+ stb_inta iq;
+ int start_offset;
+
+ // we going to allocate at the end of the chunk, not the start. confusing,
+ // but it means we don't need both a 'limit' and a 'cur', just a 'cur'.
+ // the block ends at: p + c->data_left
+ // then we move back by size
+ start_offset = c->data_left - size;
+
+ // now we need to check the alignment of that
+ q = memblock + start_offset;
+ iq = (stb_inta) q;
+ assert(sizeof(q) == sizeof(iq));
+
+ // suppose align = 2
+ // then we need to retreat iq far enough that (iq & (2-1)) == 0
+ // to get (iq & (align-1)) = 0 requires subtracting (iq & (align-1))
+
+ start_offset -= iq & (align-1);
+ assert(((stb_uinta) (memblock+start_offset) & (align-1)) == 0);
+
+ // now, if that + pre_align works, go for it!
+ start_offset -= pre_align;
+
+ if (start_offset >= 0) {
+ c->data_left = start_offset;
+ return memblock + start_offset;
+ }
+
+ return NULL;
+}
+
+static void stb__sort_chunks(stb__alloc *src)
+{
+ // of the first two chunks, put the chunk with more data left in it first
+ stb__chunk *c = stb__chunks(src), *d;
+ if (c == NULL) return;
+ d = c->next;
+ if (d == NULL) return;
+ if (c->data_left > d->data_left) return;
+
+ c->next = d->next;
+ d->next = c;
+ stb__setchunks(src, d);
+}
+
+static void * stb__alloc_chunk(stb__alloc *src, int size, int align, int pre_align)
+{
+ void *p;
+ stb__chunk *c = stb__chunks(src);
+
+ if (c && size <= stb_alloc_chunk_size) {
+
+ p = stb__try_chunk(c, size, align, pre_align);
+ if (p) { ++c->alloc; return p; }
+
+ // try a second chunk to reduce wastage
+ if (c->next) {
+ p = stb__try_chunk(c->next, size, align, pre_align);
+ if (p) { ++c->alloc; return p; }
+
+ // put the bigger chunk first, since the second will get buried
+ // the upshot of this is that, until it gets allocated from, chunk #2
+ // is always the largest remaining chunk. (could formalize
+ // this with a heap!)
+ stb__sort_chunks(src);
+ c = stb__chunks(src);
+ }
+ }
+
+ // allocate a new chunk
+ {
+ stb__chunk *n;
+
+ int chunk_size = stb_alloc_chunk_size;
+ // we're going to allocate a new chunk to put this in
+ if (size > chunk_size)
+ chunk_size = size;
+
+ assert(sizeof(*n) + pre_align <= 16);
+
+ // loop trying to allocate a large enough chunk
+ // the loop is because the alignment may cause problems if it's big...
+ // and we don't know what our chunk alignment is going to be
+ while (1) {
+ n = (stb__chunk *) malloc(16 + chunk_size);
+ if (n == NULL) return NULL;
+
+ n->data_left = chunk_size - sizeof(*n);
+
+ p = stb__try_chunk(n, size, align, pre_align);
+ if (p != NULL) {
+ n->next = c;
+ stb__setchunks(src, n);
+
+ // if we just used up the whole block immediately,
+ // move the following chunk up
+ n->alloc = 1;
+ if (size == chunk_size)
+ stb__sort_chunks(src);
+
+ return p;
+ }
+
+ free(n);
+ chunk_size += 16+align;
+ }
+ }
+}
+
+static stb__alloc * stb__get_context(void *context)
+{
+ if (context == NULL) {
+ return &stb__alloc_global;
+ } else {
+ int u = stb__identify(context);
+ // if context is chunked, grab parent
+ if (u == STB__chunked) {
+ stb__chunked *s = (stb__chunked *) context - 1;
+ return stb__parent(s);
+ } else {
+ return (stb__alloc *) context - 1;
+ }
+ }
+}
+
+static void stb__insert_alloc(stb__alloc *src, stb__alloc *s)
+{
+ s->prevn = &src->child;
+ s->next = src->child;
+ src->child = s+1;
+ if (s->next)
+ *stb__prevn(s->next) = &s->next;
+}
+
+static void stb__insert_nochild(stb__alloc *src, stb__nochildren *s)
+{
+ s->prevn = &src->child;
+ s->next = src->child;
+ src->child = s+1;
+ if (s->next)
+ *stb__prevn(s->next) = &s->next;
+}
+
+static void * malloc_base(void *context, size_t size, stb__alloc_type t, int align)
+{
+ void *p;
+
+ stb__alloc *src = stb__get_context(context);
+
+ if (align <= 0) {
+ // compute worst-case C packed alignment
+ // e.g. a 24-byte struct is 8-aligned
+ int align_proposed = 1 << stb_lowbit8((unsigned int) size);
+
+ if (align_proposed < 0)
+ align_proposed = 4;
+
+ if (align_proposed == 0) {
+ if (size == 0)
+ align_proposed = 1;
+ else
+ align_proposed = 256;
+ }
+
+ // a negative alignment means 'don't align any larger
+ // than this'; so -16 means we align 1,2,4,8, or 16
+
+ if (align < 0) {
+ if (align_proposed > -align)
+ align_proposed = -align;
+ }
+
+ align = align_proposed;
+ }
+
+ assert(stb_is_pow2(align));
+
+ // don't cause misalignment when allocating nochildren
+ if (t == STB__nochildren && align > 8)
+ t = STB__alloc;
+
+ switch (t) {
+ case STB__alloc: {
+ stb__alloc *s = (stb__alloc *) malloc(size + sizeof(*s));
+ if (s == NULL) return NULL;
+ p = s+1;
+ s->child = NULL;
+ stb__insert_alloc(src, s);
+
+ stb__setchunks(s,NULL);
+ break;
+ }
+
+ case STB__nochildren: {
+ stb__nochildren *s = (stb__nochildren *) malloc(size + sizeof(*s));
+ if (s == NULL) return NULL;
+ p = s+1;
+ stb__insert_nochild(src, s);
+ break;
+ }
+
+ case STB__chunk_raw: {
+ p = stb__alloc_chunk(src, (int) size, align, 0);
+ if (p == NULL) return NULL;
+ break;
+ }
+
+ case STB__chunked: {
+ stb__chunked *s;
+ if (align < sizeof(stb_uintptr)) align = sizeof(stb_uintptr);
+ s = (stb__chunked *) stb__alloc_chunk(src, (int) size, align, sizeof(*s));
+ if (s == NULL) return NULL;
+ stb__setparent(s, src);
+ p = s+1;
+ break;
+ }
+
+ default: p = NULL; assert(0); /* NOTREACHED */
+ }
+
+ ++stb_alloc_count_alloc;
+ return p;
+}
+
+void *stb_malloc_global(size_t size)
+{
+ return malloc_base(NULL, size, STB__alloc, stb_alloc_alignment);
+}
+
+void *stb_malloc(void *context, size_t size)
+{
+ return malloc_base(context, size, STB__alloc, stb_alloc_alignment);
+}
+
+void *stb_malloc_nofree(void *context, size_t size)
+{
+ return malloc_base(context, size, STB__chunked, stb_alloc_alignment);
+}
+
+void *stb_malloc_leaf(void *context, size_t size)
+{
+ return malloc_base(context, size, STB__nochildren, stb_alloc_alignment);
+}
+
+void *stb_malloc_raw(void *context, size_t size)
+{
+ return malloc_base(context, size, STB__chunk_raw, stb_alloc_alignment);
+}
+
+char *stb_malloc_string(void *context, size_t size)
+{
+ return (char *) malloc_base(context, size, STB__chunk_raw, 1);
+}
+
+void *stb_realloc(void *ptr, size_t newsize)
+{
+ stb__alloc_type t;
+
+ if (ptr == NULL) return stb_malloc(NULL, newsize);
+ if (newsize == 0) { stb_free(ptr); return NULL; }
+
+ t = stb__identify(ptr);
+ assert(t == STB__alloc || t == STB__nochildren);
+
+ if (t == STB__alloc) {
+ stb__alloc *s = (stb__alloc *) ptr - 1;
+
+ s = (stb__alloc *) realloc(s, newsize + sizeof(*s));
+ if (s == NULL) return NULL;
+
+ ptr = s+1;
+
+ // update pointers
+ (*s->prevn) = ptr;
+ if (s->next)
+ *stb__prevn(s->next) = &s->next;
+
+ if (s->child)
+ *stb__prevn(s->child) = &s->child;
+
+ return ptr;
+ } else {
+ stb__nochildren *s = (stb__nochildren *) ptr - 1;
+
+ s = (stb__nochildren *) realloc(ptr, newsize + sizeof(s));
+ if (s == NULL) return NULL;
+
+ // update pointers
+ (*s->prevn) = s+1;
+ if (s->next)
+ *stb__prevn(s->next) = &s->next;
+
+ return s+1;
+ }
+}
+
+void *stb_realloc_c(void *context, void *ptr, size_t newsize)
+{
+ if (ptr == NULL) return stb_malloc(context, newsize);
+ if (newsize == 0) { stb_free(ptr); return NULL; }
+ // @TODO: verify you haven't changed contexts
+ return stb_realloc(ptr, newsize);
+}
+
+void stb_reassign(void *new_context, void *ptr)
+{
+ stb__alloc *src = stb__get_context(new_context);
+
+ stb__alloc_type t = stb__identify(ptr);
+ assert(t == STB__alloc || t == STB__nochildren);
+
+ if (t == STB__alloc) {
+ stb__alloc *s = (stb__alloc *) ptr - 1;
+
+ // unlink from old
+ *(s->prevn) = s->next;
+ if (s->next)
+ *stb__prevn(s->next) = s->prevn;
+
+ stb__insert_alloc(src, s);
+ } else {
+ stb__nochildren *s = (stb__nochildren *) ptr - 1;
+
+ // unlink from old
+ *(s->prevn) = s->next;
+ if (s->next)
+ *stb__prevn(s->next) = s->prevn;
+
+ stb__insert_nochild(src, s);
+ }
+}
+
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// stb_arr
+//
+// An stb_arr is directly useable as a pointer (use the actual type in your
+// definition), but when it resizes, it returns a new pointer and you can't
+// use the old one, so you have to be careful to copy-in-out as necessary.
+//
+// Use a NULL pointer as a 0-length array.
+//
+// float *my_array = NULL, *temp;
+//
+// // add elements on the end one at a time
+// stb_arr_push(my_array, 0.0f);
+// stb_arr_push(my_array, 1.0f);
+// stb_arr_push(my_array, 2.0f);
+//
+// assert(my_array[1] == 2.0f);
+//
+// // add an uninitialized element at the end, then assign it
+// *stb_arr_add(my_array) = 3.0f;
+//
+// // add three uninitialized elements at the end
+// temp = stb_arr_addn(my_array,3);
+// temp[0] = 4.0f;
+// temp[1] = 5.0f;
+// temp[2] = 6.0f;
+//
+// assert(my_array[5] == 5.0f);
+//
+// // remove the last one
+// stb_arr_pop(my_array);
+//
+// assert(stb_arr_len(my_array) == 6);
+
+
+#ifdef STB_MALLOC_WRAPPER
+ #define STB__PARAMS , char *file, int line
+ #define STB__ARGS , file, line
+#else
+ #define STB__PARAMS
+ #define STB__ARGS
+#endif
+
+// calling this function allocates an empty stb_arr attached to p
+// (whereas NULL isn't attached to anything)
+STB_EXTERN void stb_arr_malloc(void **target, void *context);
+
+// call this function with a non-NULL value to have all successive
+// stbs that are created be attached to the associated parent. Note
+// that once a given stb_arr is non-empty, it stays attached to its
+// current parent, even if you call this function again.
+// it turns the previous value, so you can restore it
+STB_EXTERN void* stb_arr_malloc_parent(void *p);
+
+// simple functions written on top of other functions
+#define stb_arr_empty(a) ( stb_arr_len(a) == 0 )
+#define stb_arr_add(a) ( stb_arr_addn((a),1) )
+#define stb_arr_push(a,v) ( *stb_arr_add(a)=(v) )
+
+typedef struct
+{
+ int len, limit;
+ int stb_malloc;
+ unsigned int signature;
+} stb__arr;
+
+#define stb_arr_signature 0x51bada7b // ends with 0123 in decimal
+
+// access the header block stored before the data
+#define stb_arrhead(a) /*lint --e(826)*/ (((stb__arr *) (a)) - 1)
+#define stb_arrhead2(a) /*lint --e(826)*/ (((stb__arr *) (a)) - 1)
+
+#ifdef STB_DEBUG
+#define stb_arr_check(a) assert(!a || stb_arrhead(a)->signature == stb_arr_signature)
+#define stb_arr_check2(a) assert(!a || stb_arrhead2(a)->signature == stb_arr_signature)
+#else
+#define stb_arr_check(a) ((void) 0)
+#define stb_arr_check2(a) ((void) 0)
+#endif
+
+// ARRAY LENGTH
+
+// get the array length; special case if pointer is NULL
+#define stb_arr_len(a) (a ? stb_arrhead(a)->len : 0)
+#define stb_arr_len2(a) ((stb__arr *) (a) ? stb_arrhead2(a)->len : 0)
+#define stb_arr_lastn(a) (stb_arr_len(a)-1)
+
+// check whether a given index is valid -- tests 0 <= i < stb_arr_len(a)
+#define stb_arr_valid(a,i) (a ? (int) (i) < stb_arrhead(a)->len : 0)
+
+// change the array length so is is exactly N entries long, creating
+// uninitialized entries as needed
+#define stb_arr_setlen(a,n) \
+ (stb__arr_setlen((void **) &(a), sizeof(a[0]), (n)))
+
+// change the array length so that N is a valid index (that is, so
+// it is at least N entries long), creating uninitialized entries as needed
+#define stb_arr_makevalid(a,n) \
+ (stb_arr_len(a) < (n)+1 ? stb_arr_setlen(a,(n)+1),(a) : (a))
+
+// remove the last element of the array, returning it
+#define stb_arr_pop(a) ((stb_arr_check(a), (a))[--stb_arrhead(a)->len])
+
+// access the last element in the array
+#define stb_arr_last(a) ((stb_arr_check(a), (a))[stb_arr_len(a)-1])
+
+// is iterator at end of list?
+#define stb_arr_end(a,i) ((i) >= &(a)[stb_arr_len(a)])
+
+// (internal) change the allocated length of the array
+#define stb_arr__grow(a,n) (stb_arr_check(a), stb_arrhead(a)->len += (n))
+
+// add N new uninitialized elements to the end of the array
+#define stb_arr__addn(a,n) /*lint --e(826)*/ \
+ ((stb_arr_len(a)+(n) > stb_arrcurmax(a)) \
+ ? (stb__arr_addlen((void **) &(a),sizeof(*a),(n)),0) \
+ : ((stb_arr__grow(a,n), 0)))
+
+// add N new uninitialized elements to the end of the array, and return
+// a pointer to the first new one
+#define stb_arr_addn(a,n) (stb_arr__addn((a),n),(a)+stb_arr_len(a)-(n))
+
+// add N new uninitialized elements starting at index 'i'
+#define stb_arr_insertn(a,i,n) (stb__arr_insertn((void **) &(a), sizeof(*a), (i), (n)))
+
+// insert an element at i
+#define stb_arr_insert(a,i,v) (stb__arr_insertn((void **) &(a), sizeof(*a), (i), (1)), ((a)[i] = v))
+
+// delete N elements from the middle starting at index 'i'
+#define stb_arr_deleten(a,i,n) (stb__arr_deleten((void **) &(a), sizeof(*a), (i), (n)))
+
+// delete the i'th element
+#define stb_arr_delete(a,i) stb_arr_deleten(a,i,1)
+
+// delete the i'th element, swapping down from the end
+#define stb_arr_fastdelete(a,i) \
+ (stb_swap(&a[i], &a[stb_arrhead(a)->len-1], sizeof(*a)), stb_arr_pop(a))
+
+
+// ARRAY STORAGE
+
+// get the array maximum storage; special case if NULL
+#define stb_arrcurmax(a) (a ? stb_arrhead(a)->limit : 0)
+#define stb_arrcurmax2(a) (a ? stb_arrhead2(a)->limit : 0)
+
+// set the maxlength of the array to n in anticipation of further growth
+#define stb_arr_setsize(a,n) (stb_arr_check(a), stb__arr_setsize((void **) &(a),sizeof((a)[0]),n))
+
+// make sure maxlength is large enough for at least N new allocations
+#define stb_arr_atleast(a,n) (stb_arr_len(a)+(n) > stb_arrcurmax(a) \
+ ? stb_arr_setsize((a), (n)) : 0)
+
+// make a copy of a given array (copies contents via 'memcpy'!)
+#define stb_arr_copy(a) stb__arr_copy(a, sizeof((a)[0]))
+
+// compute the storage needed to store all the elements of the array
+#define stb_arr_storage(a) (stb_arr_len(a) * sizeof((a)[0]))
+
+#define stb_arr_for(v,arr) for((v)=(arr); (v) < (arr)+stb_arr_len(arr); ++(v))
+
+// IMPLEMENTATION
+
+STB_EXTERN void stb_arr_free_(void **p);
+STB_EXTERN void *stb__arr_copy_(void *p, int elem_size);
+STB_EXTERN void stb__arr_setsize_(void **p, int size, int limit STB__PARAMS);
+STB_EXTERN void stb__arr_setlen_(void **p, int size, int newlen STB__PARAMS);
+STB_EXTERN void stb__arr_addlen_(void **p, int size, int addlen STB__PARAMS);
+STB_EXTERN void stb__arr_deleten_(void **p, int size, int loc, int n STB__PARAMS);
+STB_EXTERN void stb__arr_insertn_(void **p, int size, int loc, int n STB__PARAMS);
+
+#define stb_arr_free(p) stb_arr_free_((void **) &(p))
+#define stb__arr_copy stb__arr_copy_
+
+#ifndef STB_MALLOC_WRAPPER
+ #define stb__arr_setsize stb__arr_setsize_
+ #define stb__arr_setlen stb__arr_setlen_
+ #define stb__arr_addlen stb__arr_addlen_
+ #define stb__arr_deleten stb__arr_deleten_
+ #define stb__arr_insertn stb__arr_insertn_
+#else
+ #define stb__arr_addlen(p,s,n) stb__arr_addlen_(p,s,n,__FILE__,__LINE__)
+ #define stb__arr_setlen(p,s,n) stb__arr_setlen_(p,s,n,__FILE__,__LINE__)
+ #define stb__arr_setsize(p,s,n) stb__arr_setsize_(p,s,n,__FILE__,__LINE__)
+ #define stb__arr_deleten(p,s,i,n) stb__arr_deleten_(p,s,i,n,__FILE__,__LINE__)
+ #define stb__arr_insertn(p,s,i,n) stb__arr_insertn_(p,s,i,n,__FILE__,__LINE__)
+#endif
+
+#ifdef STB_DEFINE
+static void *stb__arr_context;
+
+void *stb_arr_malloc_parent(void *p)
+{
+ void *q = stb__arr_context;
+ stb__arr_context = p;
+ return q;
+}
+
+void stb_arr_malloc(void **target, void *context)
+{
+ stb__arr *q = (stb__arr *) stb_malloc(context, sizeof(*q));
+ q->len = q->limit = 0;
+ q->stb_malloc = 1;
+ q->signature = stb_arr_signature;
+ *target = (void *) (q+1);
+}
+
+static void * stb__arr_malloc(int size)
+{
+ if (stb__arr_context)
+ return stb_malloc(stb__arr_context, size);
+ return malloc(size);
+}
+
+void * stb__arr_copy_(void *p, int elem_size)
+{
+ stb__arr *q;
+ if (p == NULL) return p;
+ q = (stb__arr *) stb__arr_malloc(sizeof(*q) + elem_size * stb_arrhead2(p)->limit);
+ stb_arr_check2(p);
+ memcpy(q, stb_arrhead2(p), sizeof(*q) + elem_size * stb_arrhead2(p)->len);
+ q->stb_malloc = !!stb__arr_context;
+ return q+1;
+}
+
+void stb_arr_free_(void **pp)
+{
+ void *p = *pp;
+ stb_arr_check2(p);
+ if (p) {
+ stb__arr *q = stb_arrhead2(p);
+ if (q->stb_malloc)
+ stb_free(q);
+ else
+ free(q);
+ }
+ *pp = NULL;
+}
+
+static void stb__arrsize_(void **pp, int size, int limit, int len STB__PARAMS)
+{
+ void *p = *pp;
+ stb__arr *a;
+ stb_arr_check2(p);
+ if (p == NULL) {
+ if (len == 0 && size == 0) return;
+ a = (stb__arr *) stb__arr_malloc(sizeof(*a) + size*limit);
+ a->limit = limit;
+ a->len = len;
+ a->stb_malloc = !!stb__arr_context;
+ a->signature = stb_arr_signature;
+ } else {
+ a = stb_arrhead2(p);
+ a->len = len;
+ if (a->limit < limit) {
+ void *p;
+ if (a->limit >= 4 && limit < a->limit * 2)
+ limit = a->limit * 2;
+ if (a->stb_malloc)
+ p = stb_realloc(a, sizeof(*a) + limit*size);
+ else
+ #ifdef STB_MALLOC_WRAPPER
+ p = stb__realloc(a, sizeof(*a) + limit*size, file, line);
+ #else
+ p = realloc(a, sizeof(*a) + limit*size);
+ #endif
+ if (p) {
+ a = (stb__arr *) p;
+ a->limit = limit;
+ } else {
+ // throw an error!
+ }
+ }
+ }
+ a->len = stb_min(a->len, a->limit);
+ *pp = a+1;
+}
+
+void stb__arr_setsize_(void **pp, int size, int limit STB__PARAMS)
+{
+ void *p = *pp;
+ stb_arr_check2(p);
+ stb__arrsize_(pp, size, limit, stb_arr_len2(p) STB__ARGS);
+}
+
+void stb__arr_setlen_(void **pp, int size, int newlen STB__PARAMS)
+{
+ void *p = *pp;
+ stb_arr_check2(p);
+ if (stb_arrcurmax2(p) < newlen || p == NULL) {
+ stb__arrsize_(pp, size, newlen, newlen STB__ARGS);
+ } else {
+ stb_arrhead2(p)->len = newlen;
+ }
+}
+
+void stb__arr_addlen_(void **p, int size, int addlen STB__PARAMS)
+{
+ stb__arr_setlen_(p, size, stb_arr_len2(*p) + addlen STB__ARGS);
+}
+
+void stb__arr_insertn_(void **pp, int size, int i, int n STB__PARAMS)
+{
+ void *p = *pp;
+ if (n) {
+ int z;
+
+ if (p == NULL) {
+ stb__arr_addlen_(pp, size, n STB__ARGS);
+ return;
+ }
+
+ z = stb_arr_len2(p);
+ stb__arr_addlen_(&p, size, n STB__ARGS);
+ memmove((char *) p + (i+n)*size, (char *) p + i*size, size * (z-i));
+ }
+ *pp = p;
+}
+
+void stb__arr_deleten_(void **pp, int size, int i, int n STB__PARAMS)
+{
+ void *p = *pp;
+ if (n) {
+ memmove((char *) p + i*size, (char *) p + (i+n)*size, size * (stb_arr_len2(p)-(i+n)));
+ stb_arrhead2(p)->len -= n;
+ }
+ *pp = p;
+}
+
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Hashing
+//
+// typical use for this is to make a power-of-two hash table.
+//
+// let N = size of table (2^n)
+// let H = stb_hash(str)
+// let S = stb_rehash(H) | 1
+//
+// then hash probe sequence P(i) for i=0..N-1
+// P(i) = (H + S*i) & (N-1)
+//
+// the idea is that H has 32 bits of hash information, but the
+// table has only, say, 2^20 entries so only uses 20 of the bits.
+// then by rehashing the original H we get 2^12 different probe
+// sequences for a given initial probe location. (So it's optimal
+// for 64K tables and its optimality decreases past that.)
+//
+// ok, so I've added something that generates _two separate_
+// 32-bit hashes simultaneously which should scale better to
+// very large tables.
+
+
+STB_EXTERN unsigned int stb_hash(char *str);
+STB_EXTERN unsigned int stb_hashptr(void *p);
+STB_EXTERN unsigned int stb_hashlen(char *str, int len);
+STB_EXTERN unsigned int stb_rehash_improved(unsigned int v);
+STB_EXTERN unsigned int stb_hash_fast(void *p, int len);
+STB_EXTERN unsigned int stb_hash2(char *str, unsigned int *hash2_ptr);
+STB_EXTERN unsigned int stb_hash_number(unsigned int hash);
+
+#define stb_rehash(x) ((x) + ((x) >> 6) + ((x) >> 19))
+
+#ifdef STB_DEFINE
+unsigned int stb_hash(char *str)
+{
+ unsigned int hash = 0;
+ while (*str)
+ hash = (hash << 7) + (hash >> 25) + *str++;
+ return hash + (hash >> 16);
+}
+
+unsigned int stb_hashlen(char *str, int len)
+{
+ unsigned int hash = 0;
+ while (len-- > 0 && *str)
+ hash = (hash << 7) + (hash >> 25) + *str++;
+ return hash + (hash >> 16);
+}
+
+unsigned int stb_hashptr(void *p)
+{
+ unsigned int x = (unsigned int)(size_t) p;
+
+ // typically lacking in low bits and high bits
+ x = stb_rehash(x);
+ x += x << 16;
+
+ // pearson's shuffle
+ x ^= x << 3;
+ x += x >> 5;
+ x ^= x << 2;
+ x += x >> 15;
+ x ^= x << 10;
+ return stb_rehash(x);
+}
+
+unsigned int stb_rehash_improved(unsigned int v)
+{
+ return stb_hashptr((void *)(size_t) v);
+}
+
+unsigned int stb_hash2(char *str, unsigned int *hash2_ptr)
+{
+ unsigned int hash1 = 0x3141592c;
+ unsigned int hash2 = 0x77f044ed;
+ while (*str) {
+ hash1 = (hash1 << 7) + (hash1 >> 25) + *str;
+ hash2 = (hash2 << 11) + (hash2 >> 21) + *str;
+ ++str;
+ }
+ *hash2_ptr = hash2 + (hash1 >> 16);
+ return hash1 + (hash2 >> 16);
+}
+
+// Paul Hsieh hash
+#define stb__get16(p) ((p)[0] | ((p)[1] << 8))
+
+unsigned int stb_hash_fast(void *p, int len)
+{
+ unsigned char *q = (unsigned char *) p;
+ unsigned int hash = len;
+
+ if (len <= 0 || q == NULL) return 0;
+
+ /* Main loop */
+ for (;len > 3; len -= 4) {
+ unsigned int val;
+ hash += stb__get16(q);
+ val = (stb__get16(q+2) << 11);
+ hash = (hash << 16) ^ hash ^ val;
+ q += 4;
+ hash += hash >> 11;
+ }
+
+ /* Handle end cases */
+ switch (len) {
+ case 3: hash += stb__get16(q);
+ hash ^= hash << 16;
+ hash ^= q[2] << 18;
+ hash += hash >> 11;
+ break;
+ case 2: hash += stb__get16(q);
+ hash ^= hash << 11;
+ hash += hash >> 17;
+ break;
+ case 1: hash += q[0];
+ hash ^= hash << 10;
+ hash += hash >> 1;
+ break;
+ case 0: break;
+ }
+
+ /* Force "avalanching" of final 127 bits */
+ hash ^= hash << 3;
+ hash += hash >> 5;
+ hash ^= hash << 4;
+ hash += hash >> 17;
+ hash ^= hash << 25;
+ hash += hash >> 6;
+
+ return hash;
+}
+
+unsigned int stb_hash_number(unsigned int hash)
+{
+ hash ^= hash << 3;
+ hash += hash >> 5;
+ hash ^= hash << 4;
+ hash += hash >> 17;
+ hash ^= hash << 25;
+ hash += hash >> 6;
+ return hash;
+}
+
+#endif
+
+#ifdef STB_PERFECT_HASH
+//////////////////////////////////////////////////////////////////////////////
+//
+// Perfect hashing for ints/pointers
+//
+// This is mainly useful for making faster pointer-indexed tables
+// that don't change frequently. E.g. for stb_ischar().
+//
+
+typedef struct
+{
+ stb_uint32 addend;
+ stb_uint multiplicand;
+ stb_uint b_mask;
+ stb_uint8 small_bmap[16];
+ stb_uint16 *large_bmap;
+
+ stb_uint table_mask;
+ stb_uint32 *table;
+} stb_perfect;
+
+STB_EXTERN int stb_perfect_create(stb_perfect *,unsigned int*,int n);
+STB_EXTERN void stb_perfect_destroy(stb_perfect *);
+STB_EXTERN int stb_perfect_hash(stb_perfect *, unsigned int x);
+extern int stb_perfect_hash_max_failures;
+
+#ifdef STB_DEFINE
+
+int stb_perfect_hash_max_failures;
+
+int stb_perfect_hash(stb_perfect *p, unsigned int x)
+{
+ stb_uint m = x * p->multiplicand;
+ stb_uint y = x >> 16;
+ stb_uint bv = (m >> 24) + y;
+ stb_uint av = (m + y) >> 12;
+ if (p->table == NULL) return -1; // uninitialized table fails
+ bv &= p->b_mask;
+ av &= p->table_mask;
+ if (p->large_bmap)
+ av ^= p->large_bmap[bv];
+ else
+ av ^= p->small_bmap[bv];
+ return p->table[av] == x ? av : -1;
+}
+
+static void stb__perfect_prehash(stb_perfect *p, stb_uint x, stb_uint16 *a, stb_uint16 *b)
+{
+ stb_uint m = x * p->multiplicand;
+ stb_uint y = x >> 16;
+ stb_uint bv = (m >> 24) + y;
+ stb_uint av = (m + y) >> 12;
+ bv &= p->b_mask;
+ av &= p->table_mask;
+ *b = bv;
+ *a = av;
+}
+
+static unsigned long stb__perfect_rand(void)
+{
+ static unsigned long stb__rand;
+ stb__rand = stb__rand * 2147001325 + 715136305;
+ return 0x31415926 ^ ((stb__rand >> 16) + (stb__rand << 16));
+}
+
+typedef struct {
+ unsigned short count;
+ unsigned short b;
+ unsigned short map;
+ unsigned short *entries;
+} stb__slot;
+
+static int stb__slot_compare(const void *p, const void *q)
+{
+ stb__slot *a = (stb__slot *) p;
+ stb__slot *b = (stb__slot *) q;
+ return a->count > b->count ? -1 : a->count < b->count; // sort large to small
+}
+
+int stb_perfect_create(stb_perfect *p, unsigned int *v, int n)
+{
+ unsigned int buffer1[64], buffer2[64], buffer3[64], buffer4[64], buffer5[32];
+ unsigned short *as = (unsigned short *) stb_temp(buffer1, sizeof(*v)*n);
+ unsigned short *bs = (unsigned short *) stb_temp(buffer2, sizeof(*v)*n);
+ unsigned short *entries = (unsigned short *) stb_temp(buffer4, sizeof(*entries) * n);
+ int size = 1 << stb_log2_ceil(n), bsize=8;
+ int failure = 0,i,j,k;
+
+ assert(n <= 32768);
+ p->large_bmap = NULL;
+
+ for(;;) {
+ stb__slot *bcount = (stb__slot *) stb_temp(buffer3, sizeof(*bcount) * bsize);
+ unsigned short *bloc = (unsigned short *) stb_temp(buffer5, sizeof(*bloc) * bsize);
+ unsigned short *e;
+ int bad=0;
+
+ p->addend = stb__perfect_rand();
+ p->multiplicand = stb__perfect_rand() | 1;
+ p->table_mask = size-1;
+ p->b_mask = bsize-1;
+ p->table = (stb_uint32 *) malloc(size * sizeof(*p->table));
+
+ for (i=0; i < bsize; ++i) {
+ bcount[i].b = i;
+ bcount[i].count = 0;
+ bcount[i].map = 0;
+ }
+ for (i=0; i < n; ++i) {
+ stb__perfect_prehash(p, v[i], as+i, bs+i);
+ ++bcount[bs[i]].count;
+ }
+ qsort(bcount, bsize, sizeof(*bcount), stb__slot_compare);
+ e = entries; // now setup up their entries index
+ for (i=0; i < bsize; ++i) {
+ bcount[i].entries = e;
+ e += bcount[i].count;
+ bcount[i].count = 0;
+ bloc[bcount[i].b] = i;
+ }
+ // now fill them out
+ for (i=0; i < n; ++i) {
+ int b = bs[i];
+ int w = bloc[b];
+ bcount[w].entries[bcount[w].count++] = i;
+ }
+ stb_tempfree(buffer5,bloc);
+ // verify
+ for (i=0; i < bsize; ++i)
+ for (j=0; j < bcount[i].count; ++j)
+ assert(bs[bcount[i].entries[j]] == bcount[i].b);
+ memset(p->table, 0, size*sizeof(*p->table));
+
+ // check if any b has duplicate a
+ for (i=0; i < bsize; ++i) {
+ if (bcount[i].count > 1) {
+ for (j=0; j < bcount[i].count; ++j) {
+ if (p->table[as[bcount[i].entries[j]]])
+ bad = 1;
+ p->table[as[bcount[i].entries[j]]] = 1;
+ }
+ for (j=0; j < bcount[i].count; ++j) {
+ p->table[as[bcount[i].entries[j]]] = 0;
+ }
+ if (bad) break;
+ }
+ }
+
+ if (!bad) {
+ // go through the bs and populate the table, first fit
+ for (i=0; i < bsize; ++i) {
+ if (bcount[i].count) {
+ // go through the candidate table[b] values
+ for (j=0; j < size; ++j) {
+ // go through the a values and see if they fit
+ for (k=0; k < bcount[i].count; ++k) {
+ int a = as[bcount[i].entries[k]];
+ if (p->table[(a^j)&p->table_mask]) {
+ break; // fails
+ }
+ }
+ // if succeeded, accept
+ if (k == bcount[i].count) {
+ bcount[i].map = j;
+ for (k=0; k < bcount[i].count; ++k) {
+ int a = as[bcount[i].entries[k]];
+ p->table[(a^j)&p->table_mask] = 1;
+ }
+ break;
+ }
+ }
+ if (j == size)
+ break; // no match for i'th entry, so break out in failure
+ }
+ }
+ if (i == bsize) {
+ // success... fill out map
+ if (bsize <= 16 && size <= 256) {
+ p->large_bmap = NULL;
+ for (i=0; i < bsize; ++i)
+ p->small_bmap[bcount[i].b] = (stb_uint8) bcount[i].map;
+ } else {
+ p->large_bmap = (unsigned short *) malloc(sizeof(*p->large_bmap) * bsize);
+ for (i=0; i < bsize; ++i)
+ p->large_bmap[bcount[i].b] = bcount[i].map;
+ }
+
+ // initialize table to v[0], so empty slots will fail
+ for (i=0; i < size; ++i)
+ p->table[i] = v[0];
+
+ for (i=0; i < n; ++i)
+ if (p->large_bmap)
+ p->table[as[i] ^ p->large_bmap[bs[i]]] = v[i];
+ else
+ p->table[as[i] ^ p->small_bmap[bs[i]]] = v[i];
+
+ // and now validate that none of them collided
+ for (i=0; i < n; ++i)
+ assert(stb_perfect_hash(p, v[i]) >= 0);
+
+ stb_tempfree(buffer3, bcount);
+ break;
+ }
+ }
+ free(p->table);
+ p->table = NULL;
+ stb_tempfree(buffer3, bcount);
+
+ ++failure;
+ if (failure >= 4 && bsize < size) bsize *= 2;
+ if (failure >= 8 && (failure & 3) == 0 && size < 4*n) {
+ size *= 2;
+ bsize *= 2;
+ }
+ if (failure == 6) {
+ // make sure the input data is unique, so we don't infinite loop
+ unsigned int *data = (unsigned int *) stb_temp(buffer3, n * sizeof(*data));
+ memcpy(data, v, sizeof(*data) * n);
+ qsort(data, n, sizeof(*data), stb_intcmp(0));
+ for (i=1; i < n; ++i) {
+ if (data[i] == data[i-1])
+ size = 0; // size is return value, so 0 it
+ }
+ stb_tempfree(buffer3, data);
+ if (!size) break;
+ }
+ }
+
+ if (failure > stb_perfect_hash_max_failures)
+ stb_perfect_hash_max_failures = failure;
+
+ stb_tempfree(buffer1, as);
+ stb_tempfree(buffer2, bs);
+ stb_tempfree(buffer4, entries);
+
+ return size;
+}
+
+void stb_perfect_destroy(stb_perfect *p)
+{
+ if (p->large_bmap) free(p->large_bmap);
+ if (p->table ) free(p->table);
+ p->large_bmap = NULL;
+ p->table = NULL;
+ p->b_mask = 0;
+ p->table_mask = 0;
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Perfect hash clients
+
+STB_EXTERN int stb_ischar(char s, char *set);
+
+#ifdef STB_DEFINE
+
+int stb_ischar(char c, char *set)
+{
+ static unsigned char bit[8] = { 1,2,4,8,16,32,64,128 };
+ static stb_perfect p;
+ static unsigned char (*tables)[256];
+ static char ** sets = NULL;
+
+ int z = stb_perfect_hash(&p, (int)(size_t) set);
+ if (z < 0) {
+ int i,k,n,j,f;
+ // special code that means free all existing data
+ if (set == NULL) {
+ stb_arr_free(sets);
+ free(tables);
+ tables = NULL;
+ stb_perfect_destroy(&p);
+ return 0;
+ }
+ stb_arr_push(sets, set);
+ stb_perfect_destroy(&p);
+ n = stb_perfect_create(&p, (unsigned int *) (char **) sets, stb_arr_len(sets));
+ assert(n != 0);
+ k = (n+7) >> 3;
+ tables = (unsigned char (*)[256]) realloc(tables, sizeof(*tables) * k);
+ memset(tables, 0, sizeof(*tables) * k);
+ for (i=0; i < stb_arr_len(sets); ++i) {
+ k = stb_perfect_hash(&p, (int)(size_t) sets[i]);
+ assert(k >= 0);
+ n = k >> 3;
+ f = bit[k&7];
+ for (j=0; !j || sets[i][j]; ++j) {
+ tables[n][(unsigned char) sets[i][j]] |= f;
+ }
+ }
+ z = stb_perfect_hash(&p, (int)(size_t) set);
+ }
+ return tables[z >> 3][(unsigned char) c] & bit[z & 7];
+}
+
+#endif
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Instantiated data structures
+//
+// This is an attempt to implement a templated data structure.
+//
+// Hash table: call stb_define_hash(TYPE,N,KEY,K1,K2,HASH,VALUE)
+// TYPE -- will define a structure type containing the hash table
+// N -- the name, will prefix functions named:
+// N create
+// N destroy
+// N get
+// N set, N add, N update,
+// N remove
+// KEY -- the type of the key. 'x == y' must be valid
+// K1,K2 -- keys never used by the app, used as flags in the hashtable
+// HASH -- a piece of code ending with 'return' that hashes key 'k'
+// VALUE -- the type of the value. 'x = y' must be valid
+//
+// Note that stb_define_hash_base can be used to define more sophisticated
+// hash tables, e.g. those that make copies of the key or use special
+// comparisons (e.g. strcmp).
+
+#define STB_(prefix,name) stb__##prefix##name
+#define STB__(prefix,name) prefix##name
+#define STB__use(x) x
+#define STB__skip(x)
+
+#define stb_declare_hash(PREFIX,TYPE,N,KEY,VALUE) \
+ typedef struct stb__st_##TYPE TYPE;\
+ PREFIX int STB__(N, init)(TYPE *h, int count);\
+ PREFIX int STB__(N, memory_usage)(TYPE *h);\
+ PREFIX TYPE * STB__(N, create)(void);\
+ PREFIX TYPE * STB__(N, copy)(TYPE *h);\
+ PREFIX void STB__(N, destroy)(TYPE *h);\
+ PREFIX int STB__(N,get_flag)(TYPE *a, KEY k, VALUE *v);\
+ PREFIX VALUE STB__(N,get)(TYPE *a, KEY k);\
+ PREFIX int STB__(N, set)(TYPE *a, KEY k, VALUE v);\
+ PREFIX int STB__(N, add)(TYPE *a, KEY k, VALUE v);\
+ PREFIX int STB__(N, update)(TYPE*a,KEY k,VALUE v);\
+ PREFIX int STB__(N, remove)(TYPE *a, KEY k, VALUE *v);
+
+#define STB_nocopy(x) (x)
+#define STB_nodelete(x) 0
+#define STB_nofields
+#define STB_nonullvalue(x)
+#define STB_nullvalue(x) x
+#define STB_safecompare(x) x
+#define STB_nosafe(x)
+#define STB_noprefix
+
+#ifdef __GNUC__
+#define STB__nogcc(x)
+#else
+#define STB__nogcc(x) x
+#endif
+
+#define stb_define_hash_base(PREFIX,TYPE,FIELDS,N,NC,LOAD_FACTOR, \
+ KEY,EMPTY,DEL,COPY,DISPOSE,SAFE, \
+ VCOMPARE,CCOMPARE,HASH, \
+ VALUE,HASVNULL,VNULL) \
+ \
+typedef struct \
+{ \
+ KEY k; \
+ VALUE v; \
+} STB_(N,_hashpair); \
+ \
+STB__nogcc( typedef struct stb__st_##TYPE TYPE; ) \
+struct stb__st_##TYPE { \
+ FIELDS \
+ STB_(N,_hashpair) *table; \
+ unsigned int mask; \
+ int count, limit; \
+ int deleted; \
+ \
+ int delete_threshhold; \
+ int grow_threshhold; \
+ int shrink_threshhold; \
+ unsigned char alloced, has_empty, has_del; \
+ VALUE ev; VALUE dv; \
+}; \
+ \
+static unsigned int STB_(N, hash)(KEY k) \
+{ \
+ HASH \
+} \
+ \
+PREFIX int STB__(N, init)(TYPE *h, int count) \
+{ \
+ int i; \
+ if (count < 4) count = 4; \
+ h->limit = count; \
+ h->count = 0; \
+ h->mask = count-1; \
+ h->deleted = 0; \
+ h->grow_threshhold = (int) (count * LOAD_FACTOR); \
+ h->has_empty = h->has_del = 0; \
+ h->alloced = 0; \
+ if (count <= 64) \
+ h->shrink_threshhold = 0; \
+ else \
+ h->shrink_threshhold = (int) (count * (LOAD_FACTOR/2.25)); \
+ h->delete_threshhold = (int) (count * (1-LOAD_FACTOR)/2); \
+ h->table = (STB_(N,_hashpair)*) malloc(sizeof(h->table[0]) * count); \
+ if (h->table == NULL) return 0; \
+ /* ideally this gets turned into a memset32 automatically */ \
+ for (i=0; i < count; ++i) \
+ h->table[i].k = EMPTY; \
+ return 1; \
+} \
+ \
+PREFIX int STB__(N, memory_usage)(TYPE *h) \
+{ \
+ return sizeof(*h) + h->limit * sizeof(h->table[0]); \
+} \
+ \
+PREFIX TYPE * STB__(N, create)(void) \
+{ \
+ TYPE *h = (TYPE *) malloc(sizeof(*h)); \
+ if (h) { \
+ if (STB__(N, init)(h, 16)) \
+ h->alloced = 1; \
+ else { free(h); h=NULL; } \
+ } \
+ return h; \
+} \
+ \
+PREFIX void STB__(N, destroy)(TYPE *a) \
+{ \
+ int i; \
+ for (i=0; i < a->limit; ++i) \
+ if (!CCOMPARE(a->table[i].k,EMPTY) && !CCOMPARE(a->table[i].k, DEL)) \
+ DISPOSE(a->table[i].k); \
+ free(a->table); \
+ if (a->alloced) \
+ free(a); \
+} \
+ \
+static void STB_(N, rehash)(TYPE *a, int count); \
+ \
+PREFIX int STB__(N,get_flag)(TYPE *a, KEY k, VALUE *v) \
+{ \
+ unsigned int h = STB_(N, hash)(k); \
+ unsigned int n = h & a->mask, s; \
+ if (CCOMPARE(k,EMPTY)){ if (a->has_empty) *v = a->ev; return a->has_empty;}\
+ if (CCOMPARE(k,DEL)) { if (a->has_del ) *v = a->dv; return a->has_del; }\
+ if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \
+ SAFE(if (!CCOMPARE(a->table[n].k,DEL))) \
+ if (VCOMPARE(a->table[n].k,k)) { *v = a->table[n].v; return 1; } \
+ s = stb_rehash(h) | 1; \
+ for(;;) { \
+ n = (n + s) & a->mask; \
+ if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \
+ SAFE(if (CCOMPARE(a->table[n].k,DEL)) continue;) \
+ if (VCOMPARE(a->table[n].k,k)) \
+ { *v = a->table[n].v; return 1; } \
+ } \
+} \
+ \
+HASVNULL( \
+ PREFIX VALUE STB__(N,get)(TYPE *a, KEY k) \
+ { \
+ VALUE v; \
+ if (STB__(N,get_flag)(a,k,&v)) return v; \
+ else return VNULL; \
+ } \
+) \
+ \
+PREFIX int STB__(N,getkey)(TYPE *a, KEY k, KEY *kout) \
+{ \
+ unsigned int h = STB_(N, hash)(k); \
+ unsigned int n = h & a->mask, s; \
+ if (CCOMPARE(k,EMPTY)||CCOMPARE(k,DEL)) return 0; \
+ if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \
+ SAFE(if (!CCOMPARE(a->table[n].k,DEL))) \
+ if (VCOMPARE(a->table[n].k,k)) { *kout = a->table[n].k; return 1; } \
+ s = stb_rehash(h) | 1; \
+ for(;;) { \
+ n = (n + s) & a->mask; \
+ if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \
+ SAFE(if (CCOMPARE(a->table[n].k,DEL)) continue;) \
+ if (VCOMPARE(a->table[n].k,k)) \
+ { *kout = a->table[n].k; return 1; } \
+ } \
+} \
+ \
+static int STB_(N,addset)(TYPE *a, KEY k, VALUE v, \
+ int allow_new, int allow_old, int copy) \
+{ \
+ unsigned int h = STB_(N, hash)(k); \
+ unsigned int n = h & a->mask; \
+ int b = -1; \
+ if (CCOMPARE(k,EMPTY)) { \
+ if (a->has_empty ? allow_old : allow_new) { \
+ n=a->has_empty; a->ev = v; a->has_empty = 1; return !n; \
+ } else return 0; \
+ } \
+ if (CCOMPARE(k,DEL)) { \
+ if (a->has_del ? allow_old : allow_new) { \
+ n=a->has_del; a->dv = v; a->has_del = 1; return !n; \
+ } else return 0; \
+ } \
+ if (!CCOMPARE(a->table[n].k, EMPTY)) { \
+ unsigned int s; \
+ if (CCOMPARE(a->table[n].k, DEL)) \
+ b = n; \
+ else if (VCOMPARE(a->table[n].k,k)) { \
+ if (allow_old) \
+ a->table[n].v = v; \
+ return !allow_new; \
+ } \
+ s = stb_rehash(h) | 1; \
+ for(;;) { \
+ n = (n + s) & a->mask; \
+ if (CCOMPARE(a->table[n].k, EMPTY)) break; \
+ if (CCOMPARE(a->table[n].k, DEL)) { \
+ if (b < 0) b = n; \
+ } else if (VCOMPARE(a->table[n].k,k)) { \
+ if (allow_old) \
+ a->table[n].v = v; \
+ return !allow_new; \
+ } \
+ } \
+ } \
+ if (!allow_new) return 0; \
+ if (b < 0) b = n; else --a->deleted; \
+ a->table[b].k = copy ? COPY(k) : k; \
+ a->table[b].v = v; \
+ ++a->count; \
+ if (a->count > a->grow_threshhold) \
+ STB_(N,rehash)(a, a->limit*2); \
+ return 1; \
+} \
+ \
+PREFIX int STB__(N, set)(TYPE *a, KEY k, VALUE v){return STB_(N,addset)(a,k,v,1,1,1);}\
+PREFIX int STB__(N, add)(TYPE *a, KEY k, VALUE v){return STB_(N,addset)(a,k,v,1,0,1);}\
+PREFIX int STB__(N, update)(TYPE*a,KEY k,VALUE v){return STB_(N,addset)(a,k,v,0,1,1);}\
+ \
+PREFIX int STB__(N, remove)(TYPE *a, KEY k, VALUE *v) \
+{ \
+ unsigned int h = STB_(N, hash)(k); \
+ unsigned int n = h & a->mask, s; \
+ if (CCOMPARE(k,EMPTY)) { if (a->has_empty) { if(v)*v = a->ev; a->has_empty=0; return 1; } return 0; } \
+ if (CCOMPARE(k,DEL)) { if (a->has_del ) { if(v)*v = a->dv; a->has_del =0; return 1; } return 0; } \
+ if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \
+ if (SAFE(CCOMPARE(a->table[n].k,DEL) || ) !VCOMPARE(a->table[n].k,k)) { \
+ s = stb_rehash(h) | 1; \
+ for(;;) { \
+ n = (n + s) & a->mask; \
+ if (CCOMPARE(a->table[n].k,EMPTY)) return 0; \
+ SAFE(if (CCOMPARE(a->table[n].k, DEL)) continue;) \
+ if (VCOMPARE(a->table[n].k,k)) break; \
+ } \
+ } \
+ DISPOSE(a->table[n].k); \
+ a->table[n].k = DEL; \
+ --a->count; \
+ ++a->deleted; \
+ if (v != NULL) \
+ *v = a->table[n].v; \
+ if (a->count < a->shrink_threshhold) \
+ STB_(N, rehash)(a, a->limit >> 1); \
+ else if (a->deleted > a->delete_threshhold) \
+ STB_(N, rehash)(a, a->limit); \
+ return 1; \
+} \
+ \
+PREFIX TYPE * STB__(NC, copy)(TYPE *a) \
+{ \
+ int i; \
+ TYPE *h = (TYPE *) malloc(sizeof(*h)); \
+ if (!h) return NULL; \
+ if (!STB__(N, init)(h, a->limit)) { free(h); return NULL; } \
+ h->count = a->count; \
+ h->deleted = a->deleted; \
+ h->alloced = 1; \
+ h->ev = a->ev; h->dv = a->dv; \
+ h->has_empty = a->has_empty; h->has_del = a->has_del; \
+ memcpy(h->table, a->table, h->limit * sizeof(h->table[0])); \
+ for (i=0; i < a->limit; ++i) \
+ if (!CCOMPARE(h->table[i].k,EMPTY) && !CCOMPARE(h->table[i].k,DEL)) \
+ h->table[i].k = COPY(h->table[i].k); \
+ return h; \
+} \
+ \
+static void STB_(N, rehash)(TYPE *a, int count) \
+{ \
+ int i; \
+ TYPE b; \
+ STB__(N, init)(&b, count); \
+ for (i=0; i < a->limit; ++i) \
+ if (!CCOMPARE(a->table[i].k,EMPTY) && !CCOMPARE(a->table[i].k,DEL)) \
+ STB_(N,addset)(&b, a->table[i].k, a->table[i].v,1,1,0); \
+ free(a->table); \
+ a->table = b.table; \
+ a->mask = b.mask; \
+ a->count = b.count; \
+ a->limit = b.limit; \
+ a->deleted = b.deleted; \
+ a->delete_threshhold = b.delete_threshhold; \
+ a->grow_threshhold = b.grow_threshhold; \
+ a->shrink_threshhold = b.shrink_threshhold; \
+}
+
+#define STB_equal(a,b) ((a) == (b))
+
+#define stb_define_hash(TYPE,N,KEY,EMPTY,DEL,HASH,VALUE) \
+ stb_define_hash_base(STB_noprefix, TYPE,STB_nofields,N,NC,0.85f, \
+ KEY,EMPTY,DEL,STB_nocopy,STB_nodelete,STB_nosafe, \
+ STB_equal,STB_equal,HASH, \
+ VALUE,STB_nonullvalue,0)
+
+#define stb_define_hash_vnull(TYPE,N,KEY,EMPTY,DEL,HASH,VALUE,VNULL) \
+ stb_define_hash_base(STB_noprefix, TYPE,STB_nofields,N,NC,0.85f, \
+ KEY,EMPTY,DEL,STB_nocopy,STB_nodelete,STB_nosafe, \
+ STB_equal,STB_equal,HASH, \
+ VALUE,STB_nullvalue,VNULL)
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// stb_ptrmap
+//
+// An stb_ptrmap data structure is an O(1) hash table between pointers. One
+// application is to let you store "extra" data associated with pointers,
+// which is why it was originally called stb_extra.
+
+stb_declare_hash(STB_EXTERN, stb_ptrmap, stb_ptrmap_, void *, void *)
+stb_declare_hash(STB_EXTERN, stb_idict, stb_idict_, stb_int32, stb_int32)
+stb_declare_hash(STB_EXTERN, stb_uidict, stbi_uidict_, stb_uint32, stb_uint32)
+
+STB_EXTERN void stb_ptrmap_delete(stb_ptrmap *e, void (*free_func)(void *));
+STB_EXTERN stb_ptrmap *stb_ptrmap_new(void);
+
+STB_EXTERN stb_idict * stb_idict_new_size(int size);
+STB_EXTERN void stb_idict_remove_all(stb_idict *e);
+STB_EXTERN void stb_uidict_reset(stb_uidict *e);
+
+#ifdef STB_DEFINE
+
+#define STB_EMPTY ((void *) 2)
+#define STB_EDEL ((void *) 6)
+
+stb_define_hash_base(STB_noprefix,stb_ptrmap, STB_nofields, stb_ptrmap_,stb_ptrmap_,0.85f,
+ void *,STB_EMPTY,STB_EDEL,STB_nocopy,STB_nodelete,STB_nosafe,
+ STB_equal,STB_equal,return stb_hashptr(k);,
+ void *,STB_nullvalue,NULL)
+
+stb_ptrmap *stb_ptrmap_new(void)
+{
+ return stb_ptrmap_create();
+}
+
+void stb_ptrmap_delete(stb_ptrmap *e, void (*free_func)(void *))
+{
+ int i;
+ if (free_func)
+ for (i=0; i < e->limit; ++i)
+ if (e->table[i].k != STB_EMPTY && e->table[i].k != STB_EDEL) {
+ if (free_func == free)
+ free(e->table[i].v); // allow STB_MALLOC_WRAPPER to operate
+ else
+ free_func(e->table[i].v);
+ }
+ stb_ptrmap_destroy(e);
+}
+
+// extra fields needed for stua_dict
+#define STB_IEMPTY ((int) 1)
+#define STB_IDEL ((int) 3)
+stb_define_hash_base(STB_noprefix, stb_idict, short type; short gc; STB_nofields, stb_idict_,stb_idict_,0.95f,
+ stb_int32,STB_IEMPTY,STB_IDEL,STB_nocopy,STB_nodelete,STB_nosafe,
+ STB_equal,STB_equal,
+ return stb_rehash_improved(k);,stb_int32,STB_nonullvalue,0)
+
+stb_idict * stb_idict_new_size(int size)
+{
+ stb_idict *e = (stb_idict *) malloc(sizeof(*e));
+ if (e) {
+ if (!stb_is_pow2(size))
+ size = 1 << stb_log2_ceil(size);
+ stb_idict_init(e, size);
+ e->alloced = 1;
+ }
+ return e;
+}
+
+void stb_idict_remove_all(stb_idict *e)
+{
+ int n;
+ for (n=0; n < e->limit; ++n)
+ e->table[n].k = STB_IEMPTY;
+ e->has_empty = e->has_del = 0;
+ e->count = 0;
+ e->deleted = 0;
+}
+
+stb_define_hash_base(STB_noprefix, stb_uidict, STB_nofields, stb_uidict_,stb_uidict_,0.85f,
+ stb_int32,0xffffffff,0xfffffffe,STB_nocopy,STB_nodelete,STB_nosafe,
+ STB_equal,STB_equal,
+ return stb_rehash_improved(k);,stb_uint32,STB_nonullvalue,0)
+
+void stb_uidict_reset(stb_uidict *e)
+{
+ int n;
+ for (n=0; n < e->limit; ++n)
+ e->table[n].k = 0xffffffff;
+ e->has_empty = e->has_del = 0;
+ e->count = 0;
+ e->deleted = 0;
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// stb_sparse_ptr_matrix
+//
+// An stb_ptrmap data structure is an O(1) hash table storing an arbitrary
+// block of data for a given pair of pointers.
+//
+// If create=0, returns
+
+typedef struct stb__st_stb_spmatrix stb_spmatrix;
+
+STB_EXTERN stb_spmatrix * stb_sparse_ptr_matrix_new(int val_size);
+STB_EXTERN void stb_sparse_ptr_matrix_free(stb_spmatrix *z);
+STB_EXTERN void * stb_sparse_ptr_matrix_get(stb_spmatrix *z, void *a, void *b, int create);
+
+#ifdef STB_DEFINE
+typedef struct
+{
+ void *a;
+ void *b;
+} stb__ptrpair;
+
+static stb__ptrpair stb__ptrpair_empty = { (void *) 1, (void *) 1 };
+static stb__ptrpair stb__ptrpair_del = { (void *) 2, (void *) 2 };
+
+#define STB__equal_ptrpair(x,y) ((x).a == (y).a && (x).b == (y).b)
+
+stb_define_hash_base(STB_noprefix, stb_spmatrix, int val_size; void *arena;, stb__spmatrix_,stb__spmatrix_, 0.85,
+ stb__ptrpair, stb__ptrpair_empty, stb__ptrpair_del,
+ STB_nocopy, STB_nodelete, STB_nosafe,
+ STB__equal_ptrpair, STB__equal_ptrpair, return stb_rehash(stb_hashptr(k.a))+stb_hashptr(k.b);,
+ void *, STB_nullvalue, 0)
+
+stb_spmatrix *stb_sparse_ptr_matrix_new(int val_size)
+{
+ stb_spmatrix *m = stb__spmatrix_create();
+ if (m) m->val_size = val_size;
+ if (m) m->arena = stb_malloc_global(1);
+ return m;
+}
+
+void stb_sparse_ptr_matrix_free(stb_spmatrix *z)
+{
+ if (z->arena) stb_free(z->arena);
+ stb__spmatrix_destroy(z);
+}
+
+void *stb_sparse_ptr_matrix_get(stb_spmatrix *z, void *a, void *b, int create)
+{
+ stb__ptrpair t = { a,b };
+ void *data = stb__spmatrix_get(z, t);
+ if (!data && create) {
+ data = stb_malloc_raw(z->arena, z->val_size);
+ if (!data) return NULL;
+ memset(data, 0, z->val_size);
+ stb__spmatrix_add(z, t, data);
+ }
+ return data;
+}
+#endif
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// SDICT: Hash Table for Strings (symbol table)
+//
+// if "use_arena=1", then strings will be copied
+// into blocks and never freed until the sdict is freed;
+// otherwise they're malloc()ed and free()d on the fly.
+// (specify use_arena=1 if you never stb_sdict_remove)
+
+stb_declare_hash(STB_EXTERN, stb_sdict, stb_sdict_, char *, void *)
+
+STB_EXTERN stb_sdict * stb_sdict_new(int use_arena);
+STB_EXTERN stb_sdict * stb_sdict_copy(stb_sdict*);
+STB_EXTERN void stb_sdict_delete(stb_sdict *);
+STB_EXTERN void * stb_sdict_change(stb_sdict *, char *str, void *p);
+STB_EXTERN int stb_sdict_count(stb_sdict *d);
+
+STB_EXTERN int stb_sdict_internal_limit(stb_sdict *d);
+STB_EXTERN char * stb_sdict_internal_key(stb_sdict *d, int n);
+STB_EXTERN void * stb_sdict_internal_value(stb_sdict *d, int n);
+
+#define stb_sdict_for(d,i,q,z) \
+ for(i=0; i < stb_sdict_internal_limit(d) ? (q=stb_sdict_internal_key(d,i),z=stb_sdict_internal_value(d,i),1) : 0; ++i) \
+ if (q==NULL||q==(void *) 1);else // reversed makes macro friendly
+
+#ifdef STB_DEFINE
+
+// if in same translation unit, for speed, don't call accessors
+#undef stb_sdict_for
+#define stb_sdict_for(d,i,q,z) \
+ for(i=0; i < (d)->limit ? (q=(d)->table[i].k,z=(d)->table[i].v,1) : 0; ++i) \
+ if (q==NULL||q==(void *) 1);else // reversed makes macro friendly
+
+#define STB_DEL ((void *) 1)
+#define STB_SDEL ((char *) 1)
+
+#define stb_sdict__copy(x) \
+ stb_p_strcpy_s(a->arena ? stb_malloc_string(a->arena, strlen(x)+1) \
+ : (char *) malloc(strlen(x)+1), strlen(x)+1, x)
+
+#define stb_sdict__dispose(x) if (!a->arena) free(x)
+
+stb_define_hash_base(STB_noprefix, stb_sdict, void*arena;, stb_sdict_,stb_sdictinternal_, 0.85f,
+ char *, NULL, STB_SDEL, stb_sdict__copy, stb_sdict__dispose,
+ STB_safecompare, !strcmp, STB_equal, return stb_hash(k);,
+ void *, STB_nullvalue, NULL)
+
+int stb_sdict_count(stb_sdict *a)
+{
+ return a->count;
+}
+
+int stb_sdict_internal_limit(stb_sdict *a)
+{
+ return a->limit;
+}
+char* stb_sdict_internal_key(stb_sdict *a, int n)
+{
+ return a->table[n].k;
+}
+void* stb_sdict_internal_value(stb_sdict *a, int n)
+{
+ return a->table[n].v;
+}
+
+stb_sdict * stb_sdict_new(int use_arena)
+{
+ stb_sdict *d = stb_sdict_create();
+ if (d == NULL) return NULL;
+ d->arena = use_arena ? stb_malloc_global(1) : NULL;
+ return d;
+}
+
+stb_sdict* stb_sdict_copy(stb_sdict *old)
+{
+ stb_sdict *n;
+ void *old_arena = old->arena;
+ void *new_arena = old_arena ? stb_malloc_global(1) : NULL;
+ old->arena = new_arena;
+ n = stb_sdictinternal_copy(old);
+ old->arena = old_arena;
+ if (n)
+ n->arena = new_arena;
+ else if (new_arena)
+ stb_free(new_arena);
+ return n;
+}
+
+
+void stb_sdict_delete(stb_sdict *d)
+{
+ if (d->arena)
+ stb_free(d->arena);
+ stb_sdict_destroy(d);
+}
+
+void * stb_sdict_change(stb_sdict *d, char *str, void *p)
+{
+ void *q = stb_sdict_get(d, str);
+ stb_sdict_set(d, str, p);
+ return q;
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Instantiated data structures
+//
+// This is an attempt to implement a templated data structure.
+// What you do is define a struct foo, and then include several
+// pointer fields to struct foo in your struct. Then you call
+// the instantiator, which creates the functions that implement
+// the data structure. This requires massive undebuggable #defines,
+// so we limit the cases where we do this.
+//
+// AA tree is an encoding of a 2-3 tree whereas RB trees encode a 2-3-4 tree;
+// much simpler code due to fewer cases.
+
+#define stb__bst_parent(x) x
+#define stb__bst_noparent(x)
+
+#define stb_bst_fields(N) \
+ *STB_(N,left), *STB_(N,right); \
+ unsigned char STB_(N,level)
+
+#define stb_bst_fields_parent(N) \
+ *STB_(N,left), *STB_(N,right), *STB_(N,parent); \
+ unsigned char STB_(N,level)
+
+#define STB__level(N,x) ((x) ? (x)->STB_(N,level) : 0)
+
+#define stb_bst_base(TYPE, N, TREE, M, compare, PAR) \
+ \
+static int STB_(N,_compare)(TYPE *p, TYPE *q) \
+{ \
+ compare \
+} \
+ \
+static void STB_(N,setleft)(TYPE *q, TYPE *v) \
+{ \
+ q->STB_(N,left) = v; \
+ PAR(if (v) v->STB_(N,parent) = q;) \
+} \
+ \
+static void STB_(N,setright)(TYPE *q, TYPE *v) \
+{ \
+ q->STB_(N,right) = v; \
+ PAR(if (v) v->STB_(N,parent) = q;) \
+} \
+ \
+static TYPE *STB_(N,skew)(TYPE *q) \
+{ \
+ if (q == NULL) return q; \
+ if (q->STB_(N,left) \
+ && q->STB_(N,left)->STB_(N,level) == q->STB_(N,level)) { \
+ TYPE *p = q->STB_(N,left); \
+ STB_(N,setleft)(q, p->STB_(N,right)); \
+ STB_(N,setright)(p, q); \
+ return p; \
+ } \
+ return q; \
+} \
+ \
+static TYPE *STB_(N,split)(TYPE *p) \
+{ \
+ TYPE *q = p->STB_(N,right); \
+ if (q && q->STB_(N,right) \
+ && q->STB_(N,right)->STB_(N,level) == p->STB_(N,level)) { \
+ STB_(N,setright)(p, q->STB_(N,left)); \
+ STB_(N,setleft)(q,p); \
+ ++q->STB_(N,level); \
+ return q; \
+ } \
+ return p; \
+} \
+ \
+TYPE *STB__(N,insert)(TYPE *tree, TYPE *item) \
+{ \
+ int c; \
+ if (tree == NULL) { \
+ item->STB_(N,left) = NULL; \
+ item->STB_(N,right) = NULL; \
+ item->STB_(N,level) = 1; \
+ PAR(item->STB_(N,parent) = NULL;) \
+ return item; \
+ } \
+ c = STB_(N,_compare)(item,tree); \
+ if (c == 0) { \
+ if (item != tree) { \
+ STB_(N,setleft)(item, tree->STB_(N,left)); \
+ STB_(N,setright)(item, tree->STB_(N,right)); \
+ item->STB_(N,level) = tree->STB_(N,level); \
+ PAR(item->STB_(N,parent) = NULL;) \
+ } \
+ return item; \
+ } \
+ if (c < 0) \
+ STB_(N,setleft )(tree, STB__(N,insert)(tree->STB_(N,left), item)); \
+ else \
+ STB_(N,setright)(tree, STB__(N,insert)(tree->STB_(N,right), item)); \
+ tree = STB_(N,skew)(tree); \
+ tree = STB_(N,split)(tree); \
+ PAR(tree->STB_(N,parent) = NULL;) \
+ return tree; \
+} \
+ \
+TYPE *STB__(N,remove)(TYPE *tree, TYPE *item) \
+{ \
+ static TYPE *delnode, *leaf, *restore; \
+ if (tree == NULL) return NULL; \
+ leaf = tree; \
+ if (STB_(N,_compare)(item, tree) < 0) { \
+ STB_(N,setleft)(tree, STB__(N,remove)(tree->STB_(N,left), item)); \
+ } else { \
+ TYPE *r; \
+ delnode = tree; \
+ r = STB__(N,remove)(tree->STB_(N,right), item); \
+ /* maybe move 'leaf' up to this location */ \
+ if (restore == tree) { tree = leaf; leaf = restore = NULL; } \
+ STB_(N,setright)(tree,r); \
+ assert(tree->STB_(N,right) != tree); \
+ } \
+ if (tree == leaf) { \
+ if (delnode == item) { \
+ tree = tree->STB_(N,right); \
+ assert(leaf->STB_(N,left) == NULL); \
+ /* move leaf (the right sibling) up to delnode */ \
+ STB_(N,setleft )(leaf, item->STB_(N,left )); \
+ STB_(N,setright)(leaf, item->STB_(N,right)); \
+ leaf->STB_(N,level) = item->STB_(N,level); \
+ if (leaf != item) \
+ restore = delnode; \
+ } \
+ delnode = NULL; \
+ } else { \
+ if (STB__level(N,tree->STB_(N,left) ) < tree->STB_(N,level)-1 || \
+ STB__level(N,tree->STB_(N,right)) < tree->STB_(N,level)-1) { \
+ --tree->STB_(N,level); \
+ if (STB__level(N,tree->STB_(N,right)) > tree->STB_(N,level)) \
+ tree->STB_(N,right)->STB_(N,level) = tree->STB_(N,level); \
+ tree = STB_(N,skew)(tree); \
+ STB_(N,setright)(tree, STB_(N,skew)(tree->STB_(N,right))); \
+ if (tree->STB_(N,right)) \
+ STB_(N,setright)(tree->STB_(N,right), \
+ STB_(N,skew)(tree->STB_(N,right)->STB_(N,right))); \
+ tree = STB_(N,split)(tree); \
+ if (tree->STB_(N,right)) \
+ STB_(N,setright)(tree, STB_(N,split)(tree->STB_(N,right))); \
+ } \
+ } \
+ PAR(if (tree) tree->STB_(N,parent) = NULL;) \
+ return tree; \
+} \
+ \
+TYPE *STB__(N,last)(TYPE *tree) \
+{ \
+ if (tree) \
+ while (tree->STB_(N,right)) tree = tree->STB_(N,right); \
+ return tree; \
+} \
+ \
+TYPE *STB__(N,first)(TYPE *tree) \
+{ \
+ if (tree) \
+ while (tree->STB_(N,left)) tree = tree->STB_(N,left); \
+ return tree; \
+} \
+ \
+TYPE *STB__(N,next)(TYPE *tree, TYPE *item) \
+{ \
+ TYPE *next = NULL; \
+ if (item->STB_(N,right)) \
+ return STB__(N,first)(item->STB_(N,right)); \
+ PAR( \
+ while(item->STB_(N,parent)) { \
+ TYPE *up = item->STB_(N,parent); \
+ if (up->STB_(N,left) == item) return up; \
+ item = up; \
+ } \
+ return NULL; \
+ ) \
+ while (tree != item) { \
+ if (STB_(N,_compare)(item, tree) < 0) { \
+ next = tree; \
+ tree = tree->STB_(N,left); \
+ } else { \
+ tree = tree->STB_(N,right); \
+ } \
+ } \
+ return next; \
+} \
+ \
+TYPE *STB__(N,prev)(TYPE *tree, TYPE *item) \
+{ \
+ TYPE *next = NULL; \
+ if (item->STB_(N,left)) \
+ return STB__(N,last)(item->STB_(N,left)); \
+ PAR( \
+ while(item->STB_(N,parent)) { \
+ TYPE *up = item->STB_(N,parent); \
+ if (up->STB_(N,right) == item) return up; \
+ item = up; \
+ } \
+ return NULL; \
+ ) \
+ while (tree != item) { \
+ if (STB_(N,_compare)(item, tree) < 0) { \
+ tree = tree->STB_(N,left); \
+ } else { \
+ next = tree; \
+ tree = tree->STB_(N,right); \
+ } \
+ } \
+ return next; \
+} \
+ \
+STB__DEBUG( \
+ void STB__(N,_validate)(TYPE *tree, int root) \
+ { \
+ if (tree == NULL) return; \
+ PAR(if(root) assert(tree->STB_(N,parent) == NULL);) \
+ assert(STB__level(N,tree->STB_(N,left) ) == tree->STB_(N,level)-1); \
+ assert(STB__level(N,tree->STB_(N,right)) <= tree->STB_(N,level)); \
+ assert(STB__level(N,tree->STB_(N,right)) >= tree->STB_(N,level)-1); \
+ if (tree->STB_(N,right)) { \
+ assert(STB__level(N,tree->STB_(N,right)->STB_(N,right)) \
+ != tree->STB_(N,level)); \
+ PAR(assert(tree->STB_(N,right)->STB_(N,parent) == tree);) \
+ } \
+ PAR(if(tree->STB_(N,left)) assert(tree->STB_(N,left)->STB_(N,parent) == tree);) \
+ STB__(N,_validate)(tree->STB_(N,left) ,0); \
+ STB__(N,_validate)(tree->STB_(N,right),0); \
+ } \
+) \
+ \
+typedef struct \
+{ \
+ TYPE *root; \
+} TREE; \
+ \
+void STB__(M,Insert)(TREE *tree, TYPE *item) \
+{ tree->root = STB__(N,insert)(tree->root, item); } \
+void STB__(M,Remove)(TREE *tree, TYPE *item) \
+{ tree->root = STB__(N,remove)(tree->root, item); } \
+TYPE *STB__(M,Next)(TREE *tree, TYPE *item) \
+{ return STB__(N,next)(tree->root, item); } \
+TYPE *STB__(M,Prev)(TREE *tree, TYPE *item) \
+{ return STB__(N,prev)(tree->root, item); } \
+TYPE *STB__(M,First)(TREE *tree) { return STB__(N,first)(tree->root); } \
+TYPE *STB__(M,Last) (TREE *tree) { return STB__(N,last) (tree->root); } \
+void STB__(M,Init)(TREE *tree) { tree->root = NULL; }
+
+
+#define stb_bst_find(N,tree,fcompare) \
+{ \
+ int c; \
+ while (tree != NULL) { \
+ fcompare \
+ if (c == 0) return tree; \
+ if (c < 0) tree = tree->STB_(N,left); \
+ else tree = tree->STB_(N,right); \
+ } \
+ return NULL; \
+}
+
+#define stb_bst_raw(TYPE,N,TREE,M,vfield,VTYPE,compare,PAR) \
+ stb_bst_base(TYPE,N,TREE,M, \
+ VTYPE a = p->vfield; VTYPE b = q->vfield; return (compare);, PAR ) \
+ \
+TYPE *STB__(N,find)(TYPE *tree, VTYPE a) \
+ stb_bst_find(N,tree,VTYPE b = tree->vfield; c = (compare);) \
+TYPE *STB__(M,Find)(TREE *tree, VTYPE a) \
+{ return STB__(N,find)(tree->root, a); }
+
+#define stb_bst(TYPE,N,TREE,M,vfield,VTYPE,compare) \
+ stb_bst_raw(TYPE,N,TREE,M,vfield,VTYPE,compare,stb__bst_noparent)
+#define stb_bst_parent(TYPE,N,TREE,M,vfield,VTYPE,compare) \
+ stb_bst_raw(TYPE,N,TREE,M,vfield,VTYPE,compare,stb__bst_parent)
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Pointer Nulling
+//
+// This lets you automatically NULL dangling pointers to "registered"
+// objects. Note that you have to make sure you call the appropriate
+// functions when you free or realloc blocks of memory that contain
+// pointers or pointer targets. stb.h can automatically do this for
+// stb_arr, or for all frees/reallocs if it's wrapping them.
+//
+
+#ifdef STB_NPTR
+
+STB_EXTERN void stb_nptr_set(void *address_of_pointer, void *value_to_write);
+STB_EXTERN void stb_nptr_didset(void *address_of_pointer);
+
+STB_EXTERN void stb_nptr_didfree(void *address_being_freed, int len);
+STB_EXTERN void stb_nptr_free(void *address_being_freed, int len);
+
+STB_EXTERN void stb_nptr_didrealloc(void *new_address, void *old_address, int len);
+STB_EXTERN void stb_nptr_recache(void); // recache all known pointers
+ // do this after pointer sets outside your control, slow
+
+#ifdef STB_DEFINE
+// for fast updating on free/realloc, we need to be able to find
+// all the objects (pointers and targets) within a given block;
+// this precludes hashing
+
+// we use a three-level hierarchy of memory to minimize storage:
+// level 1: 65536 pointers to stb__memory_node (always uses 256 KB)
+// level 2: each stb__memory_node represents a 64K block of memory
+// with 256 stb__memory_leafs (worst case 64MB)
+// level 3: each stb__memory_leaf represents 256 bytes of memory
+// using a list of target locations and a list of pointers
+// (which are hopefully fairly short normally!)
+
+// this approach won't work in 64-bit, which has a much larger address
+// space. need to redesign
+
+#define STB__NPTR_ROOT_LOG2 16
+#define STB__NPTR_ROOT_NUM (1 << STB__NPTR_ROOT_LOG2)
+#define STB__NPTR_ROOT_SHIFT (32 - STB__NPTR_ROOT_LOG2)
+
+#define STB__NPTR_NODE_LOG2 5
+#define STB__NPTR_NODE_NUM (1 << STB__NPTR_NODE_LOG2)
+#define STB__NPTR_NODE_MASK (STB__NPTR_NODE_NUM-1)
+#define STB__NPTR_NODE_SHIFT (STB__NPTR_ROOT_SHIFT - STB__NPTR_NODE_LOG2)
+#define STB__NPTR_NODE_OFFSET(x) (((x) >> STB__NPTR_NODE_SHIFT) & STB__NPTR_NODE_MASK)
+
+typedef struct stb__st_nptr
+{
+ void *ptr; // address of actual pointer
+ struct stb__st_nptr *next; // next pointer with same target
+ struct stb__st_nptr **prev; // prev pointer with same target, address of 'next' field (or first)
+ struct stb__st_nptr *next_in_block;
+} stb__nptr;
+
+typedef struct stb__st_nptr_target
+{
+ void *ptr; // address of target
+ stb__nptr *first; // address of first nptr pointing to this
+ struct stb__st_nptr_target *next_in_block;
+} stb__nptr_target;
+
+typedef struct
+{
+ stb__nptr *pointers;
+ stb__nptr_target *targets;
+} stb__memory_leaf;
+
+typedef struct
+{
+ stb__memory_leaf *children[STB__NPTR_NODE_NUM];
+} stb__memory_node;
+
+stb__memory_node *stb__memtab_root[STB__NPTR_ROOT_NUM];
+
+static stb__memory_leaf *stb__nptr_find_leaf(void *mem)
+{
+ stb_uint32 address = (stb_uint32) mem;
+ stb__memory_node *z = stb__memtab_root[address >> STB__NPTR_ROOT_SHIFT];
+ if (z)
+ return z->children[STB__NPTR_NODE_OFFSET(address)];
+ else
+ return NULL;
+}
+
+static void * stb__nptr_alloc(int size)
+{
+ return stb__realloc_raw(0,size);
+}
+
+static void stb__nptr_free(void *p)
+{
+ stb__realloc_raw(p,0);
+}
+
+static stb__memory_leaf *stb__nptr_make_leaf(void *mem)
+{
+ stb_uint32 address = (stb_uint32) mem;
+ stb__memory_node *z = stb__memtab_root[address >> STB__NPTR_ROOT_SHIFT];
+ stb__memory_leaf *f;
+ if (!z) {
+ int i;
+ z = (stb__memory_node *) stb__nptr_alloc(sizeof(*stb__memtab_root[0]));
+ stb__memtab_root[address >> STB__NPTR_ROOT_SHIFT] = z;
+ for (i=0; i < 256; ++i)
+ z->children[i] = 0;
+ }
+ f = (stb__memory_leaf *) stb__nptr_alloc(sizeof(*f));
+ z->children[STB__NPTR_NODE_OFFSET(address)] = f;
+ f->pointers = NULL;
+ f->targets = NULL;
+ return f;
+}
+
+static stb__nptr_target *stb__nptr_find_target(void *target, int force)
+{
+ stb__memory_leaf *p = stb__nptr_find_leaf(target);
+ if (p) {
+ stb__nptr_target *t = p->targets;
+ while (t) {
+ if (t->ptr == target)
+ return t;
+ t = t->next_in_block;
+ }
+ }
+ if (force) {
+ stb__nptr_target *t = (stb__nptr_target*) stb__nptr_alloc(sizeof(*t));
+ if (!p) p = stb__nptr_make_leaf(target);
+ t->ptr = target;
+ t->first = NULL;
+ t->next_in_block = p->targets;
+ p->targets = t;
+ return t;
+ } else
+ return NULL;
+}
+
+static stb__nptr *stb__nptr_find_pointer(void *ptr, int force)
+{
+ stb__memory_leaf *p = stb__nptr_find_leaf(ptr);
+ if (p) {
+ stb__nptr *t = p->pointers;
+ while (t) {
+ if (t->ptr == ptr)
+ return t;
+ t = t->next_in_block;
+ }
+ }
+ if (force) {
+ stb__nptr *t = (stb__nptr *) stb__nptr_alloc(sizeof(*t));
+ if (!p) p = stb__nptr_make_leaf(ptr);
+ t->ptr = ptr;
+ t->next = NULL;
+ t->prev = NULL;
+ t->next_in_block = p->pointers;
+ p->pointers = t;
+ return t;
+ } else
+ return NULL;
+}
+
+void stb_nptr_set(void *address_of_pointer, void *value_to_write)
+{
+ if (*(void **)address_of_pointer != value_to_write) {
+ *(void **) address_of_pointer = value_to_write;
+ stb_nptr_didset(address_of_pointer);
+ }
+}
+
+void stb_nptr_didset(void *address_of_pointer)
+{
+ // first unlink from old chain
+ void *new_address;
+ stb__nptr *p = stb__nptr_find_pointer(address_of_pointer, 1); // force building if doesn't exist
+ if (p->prev) { // if p->prev is NULL, we just built it, or it was NULL
+ *(p->prev) = p->next;
+ if (p->next) p->next->prev = p->prev;
+ }
+ // now add to new chain
+ new_address = *(void **)address_of_pointer;
+ if (new_address != NULL) {
+ stb__nptr_target *t = stb__nptr_find_target(new_address, 1);
+ p->next = t->first;
+ if (p->next) p->next->prev = &p->next;
+ p->prev = &t->first;
+ t->first = p;
+ } else {
+ p->prev = NULL;
+ p->next = NULL;
+ }
+}
+
+void stb__nptr_block(void *address, int len, void (*function)(stb__memory_leaf *f, int datum, void *start, void *end), int datum)
+{
+ void *end_address = (void *) ((char *) address + len - 1);
+ stb__memory_node *n;
+ stb_uint32 start = (stb_uint32) address;
+ stb_uint32 end = start + len - 1;
+
+ int b0 = start >> STB__NPTR_ROOT_SHIFT;
+ int b1 = end >> STB__NPTR_ROOT_SHIFT;
+ int b=b0,i,e0,e1;
+
+ e0 = STB__NPTR_NODE_OFFSET(start);
+
+ if (datum <= 0) {
+ // first block
+ n = stb__memtab_root[b0];
+ if (n) {
+ if (b0 != b1)
+ e1 = STB__NPTR_NODE_NUM-1;
+ else
+ e1 = STB__NPTR_NODE_OFFSET(end);
+ for (i=e0; i <= e1; ++i)
+ if (n->children[i])
+ function(n->children[i], datum, address, end_address);
+ }
+ if (b1 > b0) {
+ // blocks other than the first and last block
+ for (b=b0+1; b < b1; ++b) {
+ n = stb__memtab_root[b];
+ if (n)
+ for (i=0; i <= STB__NPTR_NODE_NUM-1; ++i)
+ if (n->children[i])
+ function(n->children[i], datum, address, end_address);
+ }
+ // last block
+ n = stb__memtab_root[b1];
+ if (n) {
+ e1 = STB__NPTR_NODE_OFFSET(end);
+ for (i=0; i <= e1; ++i)
+ if (n->children[i])
+ function(n->children[i], datum, address, end_address);
+ }
+ }
+ } else {
+ if (b1 > b0) {
+ // last block
+ n = stb__memtab_root[b1];
+ if (n) {
+ e1 = STB__NPTR_NODE_OFFSET(end);
+ for (i=e1; i >= 0; --i)
+ if (n->children[i])
+ function(n->children[i], datum, address, end_address);
+ }
+ // blocks other than the first and last block
+ for (b=b1-1; b > b0; --b) {
+ n = stb__memtab_root[b];
+ if (n)
+ for (i=STB__NPTR_NODE_NUM-1; i >= 0; --i)
+ if (n->children[i])
+ function(n->children[i], datum, address, end_address);
+ }
+ }
+ // first block
+ n = stb__memtab_root[b0];
+ if (n) {
+ if (b0 != b1)
+ e1 = STB__NPTR_NODE_NUM-1;
+ else
+ e1 = STB__NPTR_NODE_OFFSET(end);
+ for (i=e1; i >= e0; --i)
+ if (n->children[i])
+ function(n->children[i], datum, address, end_address);
+ }
+ }
+}
+
+static void stb__nptr_delete_pointers(stb__memory_leaf *f, int offset, void *start, void *end)
+{
+ stb__nptr **p = &f->pointers;
+ while (*p) {
+ stb__nptr *n = *p;
+ if (n->ptr >= start && n->ptr <= end) {
+ // unlink
+ if (n->prev) {
+ *(n->prev) = n->next;
+ if (n->next) n->next->prev = n->prev;
+ }
+ *p = n->next_in_block;
+ stb__nptr_free(n);
+ } else
+ p = &(n->next_in_block);
+ }
+}
+
+static void stb__nptr_delete_targets(stb__memory_leaf *f, int offset, void *start, void *end)
+{
+ stb__nptr_target **p = &f->targets;
+ while (*p) {
+ stb__nptr_target *n = *p;
+ if (n->ptr >= start && n->ptr <= end) {
+ // null pointers
+ stb__nptr *z = n->first;
+ while (z) {
+ stb__nptr *y = z->next;
+ z->prev = NULL;
+ z->next = NULL;
+ *(void **) z->ptr = NULL;
+ z = y;
+ }
+ // unlink this target
+ *p = n->next_in_block;
+ stb__nptr_free(n);
+ } else
+ p = &(n->next_in_block);
+ }
+}
+
+void stb_nptr_didfree(void *address_being_freed, int len)
+{
+ // step one: delete all pointers in this block
+ stb__nptr_block(address_being_freed, len, stb__nptr_delete_pointers, 0);
+ // step two: NULL all pointers to this block; do this second to avoid NULLing deleted pointers
+ stb__nptr_block(address_being_freed, len, stb__nptr_delete_targets, 0);
+}
+
+void stb_nptr_free(void *address_being_freed, int len)
+{
+ free(address_being_freed);
+ stb_nptr_didfree(address_being_freed, len);
+}
+
+static void stb__nptr_move_targets(stb__memory_leaf *f, int offset, void *start, void *end)
+{
+ stb__nptr_target **t = &f->targets;
+ while (*t) {
+ stb__nptr_target *n = *t;
+ if (n->ptr >= start && n->ptr <= end) {
+ stb__nptr *z;
+ stb__memory_leaf *f;
+ // unlink n
+ *t = n->next_in_block;
+ // update n to new address
+ n->ptr = (void *) ((char *) n->ptr + offset);
+ f = stb__nptr_find_leaf(n->ptr);
+ if (!f) f = stb__nptr_make_leaf(n->ptr);
+ n->next_in_block = f->targets;
+ f->targets = n;
+ // now go through all pointers and make them point here
+ z = n->first;
+ while (z) {
+ *(void**) z->ptr = n->ptr;
+ z = z->next;
+ }
+ } else
+ t = &(n->next_in_block);
+ }
+}
+
+static void stb__nptr_move_pointers(stb__memory_leaf *f, int offset, void *start, void *end)
+{
+ stb__nptr **p = &f->pointers;
+ while (*p) {
+ stb__nptr *n = *p;
+ if (n->ptr >= start && n->ptr <= end) {
+ // unlink
+ *p = n->next_in_block;
+ n->ptr = (void *) ((int) n->ptr + offset);
+ // move to new block
+ f = stb__nptr_find_leaf(n->ptr);
+ if (!f) f = stb__nptr_make_leaf(n->ptr);
+ n->next_in_block = f->pointers;
+ f->pointers = n;
+ } else
+ p = &(n->next_in_block);
+ }
+}
+
+void stb_nptr_realloc(void *new_address, void *old_address, int len)
+{
+ if (new_address == old_address) return;
+
+ // have to move the pointers first, because moving the targets
+ // requires writing to the pointers-to-the-targets, and if some of those moved too,
+ // we need to make sure we don't write to the old memory
+
+ // step one: move all pointers within the block
+ stb__nptr_block(old_address, len, stb__nptr_move_pointers, (char *) new_address - (char *) old_address);
+ // step two: move all targets within the block
+ stb__nptr_block(old_address, len, stb__nptr_move_targets, (char *) new_address - (char *) old_address);
+}
+
+void stb_nptr_move(void *new_address, void *old_address)
+{
+ stb_nptr_realloc(new_address, old_address, 1);
+}
+
+void stb_nptr_recache(void)
+{
+ int i,j;
+ for (i=0; i < STB__NPTR_ROOT_NUM; ++i)
+ if (stb__memtab_root[i])
+ for (j=0; j < STB__NPTR_NODE_NUM; ++j)
+ if (stb__memtab_root[i]->children[j]) {
+ stb__nptr *p = stb__memtab_root[i]->children[j]->pointers;
+ while (p) {
+ stb_nptr_didset(p->ptr);
+ p = p->next_in_block;
+ }
+ }
+}
+
+#endif // STB_DEFINE
+#endif // STB_NPTR
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// File Processing
+//
+
+
+#ifdef _WIN32
+ #define stb_rename(x,y) _wrename((const wchar_t *)stb__from_utf8(x), (const wchar_t *)stb__from_utf8_alt(y))
+#else
+ #define stb_rename rename
+#endif
+
+STB_EXTERN void stb_fput_varlen64(FILE *f, stb_uint64 v);
+STB_EXTERN stb_uint64 stb_fget_varlen64(FILE *f);
+STB_EXTERN int stb_size_varlen64(stb_uint64 v);
+
+
+#define stb_filec (char *) stb_file
+#define stb_fileu (unsigned char *) stb_file
+STB_EXTERN void * stb_file(char *filename, size_t *length);
+STB_EXTERN void * stb_file_max(char *filename, size_t *length);
+STB_EXTERN size_t stb_filelen(FILE *f);
+STB_EXTERN int stb_filewrite(char *filename, void *data, size_t length);
+STB_EXTERN int stb_filewritestr(char *filename, char *data);
+STB_EXTERN char ** stb_stringfile(char *filename, int *len);
+STB_EXTERN char ** stb_stringfile_trimmed(char *name, int *len, char comm);
+STB_EXTERN char * stb_fgets(char *buffer, int buflen, FILE *f);
+STB_EXTERN char * stb_fgets_malloc(FILE *f);
+STB_EXTERN int stb_fexists(char *filename);
+STB_EXTERN int stb_fcmp(char *s1, char *s2);
+STB_EXTERN int stb_feq(char *s1, char *s2);
+STB_EXTERN time_t stb_ftimestamp(char *filename);
+
+STB_EXTERN int stb_fullpath(char *abs, int abs_size, char *rel);
+STB_EXTERN FILE * stb_fopen(char *filename, const char *mode);
+STB_EXTERN int stb_fclose(FILE *f, int keep);
+
+enum
+{
+ stb_keep_no = 0,
+ stb_keep_yes = 1,
+ stb_keep_if_different = 2,
+};
+
+STB_EXTERN int stb_copyfile(char *src, char *dest);
+
+STB_EXTERN void stb_fput_varlen64(FILE *f, stb_uint64 v);
+STB_EXTERN stb_uint64 stb_fget_varlen64(FILE *f);
+STB_EXTERN int stb_size_varlen64(stb_uint64 v);
+
+STB_EXTERN void stb_fwrite32(FILE *f, stb_uint32 datum);
+STB_EXTERN void stb_fput_varlen (FILE *f, int v);
+STB_EXTERN void stb_fput_varlenu(FILE *f, unsigned int v);
+STB_EXTERN int stb_fget_varlen (FILE *f);
+STB_EXTERN stb_uint stb_fget_varlenu(FILE *f);
+STB_EXTERN void stb_fput_ranged (FILE *f, int v, int b, stb_uint n);
+STB_EXTERN int stb_fget_ranged (FILE *f, int b, stb_uint n);
+STB_EXTERN int stb_size_varlen (int v);
+STB_EXTERN int stb_size_varlenu(unsigned int v);
+STB_EXTERN int stb_size_ranged (int b, stb_uint n);
+
+STB_EXTERN int stb_fread(void *data, size_t len, size_t count, void *f);
+STB_EXTERN int stb_fwrite(void *data, size_t len, size_t count, void *f);
+
+#if 0
+typedef struct
+{
+ FILE *base_file;
+ char *buffer;
+ int buffer_size;
+ int buffer_off;
+ int buffer_left;
+} STBF;
+
+STB_EXTERN STBF *stb_tfopen(char *filename, char *mode);
+STB_EXTERN int stb_tfread(void *data, size_t len, size_t count, STBF *f);
+STB_EXTERN int stb_tfwrite(void *data, size_t len, size_t count, STBF *f);
+#endif
+
+#ifdef STB_DEFINE
+
+#if 0
+STBF *stb_tfopen(char *filename, char *mode)
+{
+ STBF *z;
+ FILE *f = stb_p_fopen(filename, mode);
+ if (!f) return NULL;
+ z = (STBF *) malloc(sizeof(*z));
+ if (!z) { fclose(f); return NULL; }
+ z->base_file = f;
+ if (!strcmp(mode, "rb") || !strcmp(mode, "wb")) {
+ z->buffer_size = 4096;
+ z->buffer_off = z->buffer_size;
+ z->buffer_left = 0;
+ z->buffer = malloc(z->buffer_size);
+ if (!z->buffer) { free(z); fclose(f); return NULL; }
+ } else {
+ z->buffer = 0;
+ z->buffer_size = 0;
+ z->buffer_left = 0;
+ }
+ return z;
+}
+
+int stb_tfread(void *data, size_t len, size_t count, STBF *f)
+{
+ int total = len*count, done=0;
+ if (!total) return 0;
+ if (total <= z->buffer_left) {
+ memcpy(data, z->buffer + z->buffer_off, total);
+ z->buffer_off += total;
+ z->buffer_left -= total;
+ return count;
+ } else {
+ char *out = (char *) data;
+
+ // consume all buffered data
+ memcpy(data, z->buffer + z->buffer_off, z->buffer_left);
+ done = z->buffer_left;
+ out += z->buffer_left;
+ z->buffer_left=0;
+
+ if (total-done > (z->buffer_size >> 1)) {
+ done += fread(out
+ }
+ }
+}
+#endif
+
+void stb_fwrite32(FILE *f, stb_uint32 x)
+{
+ fwrite(&x, 4, 1, f);
+}
+
+#if defined(_WIN32)
+ #define stb__stat _stat
+#else
+ #define stb__stat stat
+#endif
+
+int stb_fexists(char *filename)
+{
+ struct stb__stat buf;
+ return stb__windows(
+ _wstat((const wchar_t *)stb__from_utf8(filename), &buf),
+ stat(filename,&buf)
+ ) == 0;
+}
+
+time_t stb_ftimestamp(char *filename)
+{
+ struct stb__stat buf;
+ if (stb__windows(
+ _wstat((const wchar_t *)stb__from_utf8(filename), &buf),
+ stat(filename,&buf)
+ ) == 0)
+ {
+ return buf.st_mtime;
+ } else {
+ return 0;
+ }
+}
+
+size_t stb_filelen(FILE *f)
+{
+ long len, pos;
+ pos = ftell(f);
+ fseek(f, 0, SEEK_END);
+ len = ftell(f);
+ fseek(f, pos, SEEK_SET);
+ return (size_t) len;
+}
+
+void *stb_file(char *filename, size_t *length)
+{
+ FILE *f = stb__fopen(filename, "rb");
+ char *buffer;
+ size_t len, len2;
+ if (!f) return NULL;
+ len = stb_filelen(f);
+ buffer = (char *) malloc(len+2); // nul + extra
+ len2 = fread(buffer, 1, len, f);
+ if (len2 == len) {
+ if (length) *length = len;
+ buffer[len] = 0;
+ } else {
+ free(buffer);
+ buffer = NULL;
+ }
+ fclose(f);
+ return buffer;
+}
+
+int stb_filewrite(char *filename, void *data, size_t length)
+{
+ FILE *f = stb_fopen(filename, "wb");
+ if (f) {
+ unsigned char *data_ptr = (unsigned char *) data;
+ size_t remaining = length;
+ while (remaining > 0) {
+ size_t len2 = remaining > 65536 ? 65536 : remaining;
+ size_t len3 = fwrite(data_ptr, 1, len2, f);
+ if (len2 != len3) {
+ fprintf(stderr, "Failed while writing %s\n", filename);
+ break;
+ }
+ remaining -= len2;
+ data_ptr += len2;
+ }
+ stb_fclose(f, stb_keep_if_different);
+ }
+ return f != NULL;
+}
+
+int stb_filewritestr(char *filename, char *data)
+{
+ return stb_filewrite(filename, data, strlen(data));
+}
+
+void * stb_file_max(char *filename, size_t *length)
+{
+ FILE *f = stb__fopen(filename, "rb");
+ char *buffer;
+ size_t len, maxlen;
+ if (!f) return NULL;
+ maxlen = *length;
+ buffer = (char *) malloc(maxlen+1);
+ len = fread(buffer, 1, maxlen, f);
+ buffer[len] = 0;
+ fclose(f);
+ *length = len;
+ return buffer;
+}
+
+char ** stb_stringfile(char *filename, int *plen)
+{
+ FILE *f = stb__fopen(filename, "rb");
+ char *buffer, **list=NULL, *s;
+ size_t len, count, i;
+
+ if (!f) return NULL;
+ len = stb_filelen(f);
+ buffer = (char *) malloc(len+1);
+ len = fread(buffer, 1, len, f);
+ buffer[len] = 0;
+ fclose(f);
+
+ // two passes through: first time count lines, second time set them
+ for (i=0; i < 2; ++i) {
+ s = buffer;
+ if (i == 1)
+ list[0] = s;
+ count = 1;
+ while (*s) {
+ if (*s == '\n' || *s == '\r') {
+ // detect if both cr & lf are together
+ int crlf = (s[0] + s[1]) == ('\n' + '\r');
+ if (i == 1) *s = 0;
+ if (crlf) ++s;
+ if (s[1]) { // it's not over yet
+ if (i == 1) list[count] = s+1;
+ ++count;
+ }
+ }
+ ++s;
+ }
+ if (i == 0) {
+ list = (char **) malloc(sizeof(*list) * (count+1) + len+1);
+ if (!list) return NULL;
+ list[count] = 0;
+ // recopy the file so there's just a single allocation to free
+ memcpy(&list[count+1], buffer, len+1);
+ free(buffer);
+ buffer = (char *) &list[count+1];
+ if (plen) *plen = (int) count;
+ }
+ }
+ return list;
+}
+
+char ** stb_stringfile_trimmed(char *name, int *len, char comment)
+{
+ int i,n,o=0;
+ char **s = stb_stringfile(name, &n);
+ if (s == NULL) return NULL;
+ for (i=0; i < n; ++i) {
+ char *p = stb_skipwhite(s[i]);
+ if (*p && *p != comment)
+ s[o++] = p;
+ }
+ s[o] = NULL;
+ if (len) *len = o;
+ return s;
+}
+
+char * stb_fgets(char *buffer, int buflen, FILE *f)
+{
+ char *p;
+ buffer[0] = 0;
+ p = fgets(buffer, buflen, f);
+ if (p) {
+ int n = (int) (strlen(p)-1);
+ if (n >= 0)
+ if (p[n] == '\n')
+ p[n] = 0;
+ }
+ return p;
+}
+
+char * stb_fgets_malloc(FILE *f)
+{
+ // avoid reallocing for small strings
+ char quick_buffer[800];
+ quick_buffer[sizeof(quick_buffer)-2] = 0;
+ if (!fgets(quick_buffer, sizeof(quick_buffer), f))
+ return NULL;
+
+ if (quick_buffer[sizeof(quick_buffer)-2] == 0) {
+ size_t n = strlen(quick_buffer);
+ if (n > 0 && quick_buffer[n-1] == '\n')
+ quick_buffer[n-1] = 0;
+ return stb_p_strdup(quick_buffer);
+ } else {
+ char *p;
+ char *a = stb_p_strdup(quick_buffer);
+ size_t len = sizeof(quick_buffer)-1;
+
+ while (!feof(f)) {
+ if (a[len-1] == '\n') break;
+ a = (char *) realloc(a, len*2);
+ p = &a[len];
+ p[len-2] = 0;
+ if (!fgets(p, (int) len, f))
+ break;
+ if (p[len-2] == 0) {
+ len += strlen(p);
+ break;
+ }
+ len = len + (len-1);
+ }
+ if (a[len-1] == '\n')
+ a[len-1] = 0;
+ return a;
+ }
+}
+
+int stb_fullpath(char *abs, int abs_size, char *rel)
+{
+ #ifdef _WIN32
+ return _fullpath(abs, rel, abs_size) != NULL;
+ #else
+ if (rel[0] == '/' || rel[0] == '~') {
+ if ((int) strlen(rel) >= abs_size)
+ return 0;
+ stb_p_strcpy_s(abs,65536,rel);
+ return STB_TRUE;
+ } else {
+ int n;
+ getcwd(abs, abs_size);
+ n = strlen(abs);
+ if (n+(int) strlen(rel)+2 <= abs_size) {
+ abs[n] = '/';
+ stb_p_strcpy_s(abs+n+1, 65536,rel);
+ return STB_TRUE;
+ } else {
+ return STB_FALSE;
+ }
+ }
+ #endif
+}
+
+static int stb_fcmp_core(FILE *f, FILE *g)
+{
+ char buf1[1024],buf2[1024];
+ int n1,n2, res=0;
+
+ while (1) {
+ n1 = (int) fread(buf1, 1, sizeof(buf1), f);
+ n2 = (int) fread(buf2, 1, sizeof(buf2), g);
+ res = memcmp(buf1,buf2,stb_min(n1,n2));
+ if (res)
+ break;
+ if (n1 != n2) {
+ res = n1 < n2 ? -1 : 1;
+ break;
+ }
+ if (n1 == 0)
+ break;
+ }
+
+ fclose(f);
+ fclose(g);
+ return res;
+}
+
+int stb_fcmp(char *s1, char *s2)
+{
+ FILE *f = stb__fopen(s1, "rb");
+ FILE *g = stb__fopen(s2, "rb");
+
+ if (f == NULL || g == NULL) {
+ if (f) fclose(f);
+ if (g) {
+ fclose(g);
+ return STB_TRUE;
+ }
+ return f != NULL;
+ }
+
+ return stb_fcmp_core(f,g);
+}
+
+int stb_feq(char *s1, char *s2)
+{
+ FILE *f = stb__fopen(s1, "rb");
+ FILE *g = stb__fopen(s2, "rb");
+
+ if (f == NULL || g == NULL) {
+ if (f) fclose(f);
+ if (g) fclose(g);
+ return f == g;
+ }
+
+ // feq is faster because it shortcuts if they're different length
+ if (stb_filelen(f) != stb_filelen(g)) {
+ fclose(f);
+ fclose(g);
+ return 0;
+ }
+
+ return !stb_fcmp_core(f,g);
+}
+
+static stb_ptrmap *stb__files;
+
+typedef struct
+{
+ char *temp_name;
+ char *name;
+ int errors;
+} stb__file_data;
+
+static FILE *stb__open_temp_file(char *temp_name, char *src_name, const char *mode)
+{
+ size_t p;
+#ifdef _MSC_VER
+ int j;
+#endif
+ FILE *f;
+ // try to generate a temporary file in the same directory
+ p = strlen(src_name)-1;
+ while (p > 0 && src_name[p] != '/' && src_name[p] != '\\'
+ && src_name[p] != ':' && src_name[p] != '~')
+ --p;
+ ++p;
+
+ memcpy(temp_name, src_name, p);
+
+ #ifdef _MSC_VER
+ // try multiple times to make a temp file... just in
+ // case some other process makes the name first
+ for (j=0; j < 32; ++j) {
+ stb_p_strcpy_s(temp_name+p, 65536, "stmpXXXXXX");
+ if (!stb_p_mktemp(temp_name))
+ return 0;
+
+ f = stb_p_fopen(temp_name, mode);
+ if (f != NULL)
+ break;
+ }
+ #else
+ {
+ stb_p_strcpy_s(temp_name+p, 65536, "stmpXXXXXX");
+ #ifdef __MINGW32__
+ int fd = open(stb_p_mktemp(temp_name), O_RDWR);
+ #else
+ int fd = mkstemp(temp_name);
+ #endif
+ if (fd == -1) return NULL;
+ f = fdopen(fd, mode);
+ if (f == NULL) {
+ unlink(temp_name);
+ close(fd);
+ return NULL;
+ }
+ }
+ #endif
+ return f;
+}
+
+
+FILE * stb_fopen(char *filename, const char *mode)
+{
+ FILE *f;
+ char name_full[4096];
+ char temp_full[sizeof(name_full) + 12];
+
+ // @TODO: if the file doesn't exist, we can also use the fastpath here
+ if (mode[0] != 'w' && !strchr(mode, '+'))
+ return stb__fopen(filename, mode);
+
+ // save away the full path to the file so if the program
+ // changes the cwd everything still works right! unix has
+ // better ways to do this, but we have to work in windows
+ name_full[0] = '\0'; // stb_fullpath reads name_full[0]
+ if (stb_fullpath(name_full, sizeof(name_full), filename)==0)
+ return 0;
+
+ f = stb__open_temp_file(temp_full, name_full, mode);
+ if (f != NULL) {
+ stb__file_data *d = (stb__file_data *) malloc(sizeof(*d));
+ if (!d) { assert(0); /* NOTREACHED */fclose(f); return NULL; }
+ if (stb__files == NULL) stb__files = stb_ptrmap_create();
+ d->temp_name = stb_p_strdup(temp_full);
+ d->name = stb_p_strdup(name_full);
+ d->errors = 0;
+ stb_ptrmap_add(stb__files, f, d);
+ return f;
+ }
+
+ return NULL;
+}
+
+int stb_fclose(FILE *f, int keep)
+{
+ stb__file_data *d;
+
+ int ok = STB_FALSE;
+ if (f == NULL) return 0;
+
+ if (ferror(f))
+ keep = stb_keep_no;
+
+ fclose(f);
+
+ if (stb__files && stb_ptrmap_remove(stb__files, f, (void **) &d)) {
+ if (stb__files->count == 0) {
+ stb_ptrmap_destroy(stb__files);
+ stb__files = NULL;
+ }
+ } else
+ return STB_TRUE; // not special
+
+ if (keep == stb_keep_if_different) {
+ // check if the files are identical
+ if (stb_feq(d->name, d->temp_name)) {
+ keep = stb_keep_no;
+ ok = STB_TRUE; // report success if no change
+ }
+ }
+
+ if (keep == stb_keep_no) {
+ remove(d->temp_name);
+ } else {
+ if (!stb_fexists(d->name)) {
+ // old file doesn't exist, so just move the new file over it
+ stb_rename(d->temp_name, d->name);
+ } else {
+ // don't delete the old file yet in case there are troubles! First rename it!
+ char preserved_old_file[4096];
+
+ // generate a temp filename in the same directory (also creates it, which we don't need)
+ FILE *dummy = stb__open_temp_file(preserved_old_file, d->name, "wb");
+ if (dummy != NULL) {
+ // we don't actually want the open file
+ fclose(dummy);
+
+ // discard what we just created
+ remove(preserved_old_file); // if this fails, there's nothing we can do, and following logic handles it as best as possible anyway
+
+ // move the existing file to the preserved name
+ if (0 != stb_rename(d->name, preserved_old_file)) { // 0 on success
+ // failed, state is:
+ // filename -> old file
+ // tempname -> new file
+ // keep tempname around so we don't lose data
+ } else {
+ // state is:
+ // preserved -> old file
+ // tempname -> new file
+ // move the new file to the old name
+ if (0 == stb_rename(d->temp_name, d->name)) {
+ // state is:
+ // preserved -> old file
+ // filename -> new file
+ ok = STB_TRUE;
+
+ // 'filename -> new file' has always been the goal, so clean up
+ remove(preserved_old_file); // nothing to be done if it fails
+ } else {
+ // couldn't rename, so try renaming preserved file back
+
+ // state is:
+ // preserved -> old file
+ // tempname -> new file
+ stb_rename(preserved_old_file, d->name);
+ // if the rename failed, there's nothing more we can do
+ }
+ }
+ } else {
+ // we couldn't get a temp filename. do this the naive way; the worst case failure here
+ // leaves the filename pointing to nothing and the new file as a tempfile
+ remove(d->name);
+ stb_rename(d->temp_name, d->name);
+ }
+ }
+ }
+
+ free(d->temp_name);
+ free(d->name);
+ free(d);
+
+ return ok;
+}
+
+int stb_copyfile(char *src, char *dest)
+{
+ char raw_buffer[1024];
+ char *buffer;
+ int buf_size = 65536;
+
+ FILE *f, *g;
+
+ // if file already exists at destination, do nothing
+ if (stb_feq(src, dest)) return STB_TRUE;
+
+ // open file
+ f = stb__fopen(src, "rb");
+ if (f == NULL) return STB_FALSE;
+
+ // open file for writing
+ g = stb__fopen(dest, "wb");
+ if (g == NULL) {
+ fclose(f);
+ return STB_FALSE;
+ }
+
+ buffer = (char *) malloc(buf_size);
+ if (buffer == NULL) {
+ buffer = raw_buffer;
+ buf_size = sizeof(raw_buffer);
+ }
+
+ while (!feof(f)) {
+ size_t n = fread(buffer, 1, buf_size, f);
+ if (n != 0)
+ fwrite(buffer, 1, n, g);
+ }
+
+ fclose(f);
+ if (buffer != raw_buffer)
+ free(buffer);
+
+ fclose(g);
+ return STB_TRUE;
+}
+
+// varlen:
+// v' = (v >> 31) + (v < 0 ? ~v : v)<<1; // small abs(v) => small v'
+// output v as big endian v'+k for v' <= k:
+// 1 byte : v' <= 0x00000080 ( -64 <= v < 64) 7 bits
+// 2 bytes: v' <= 0x00004000 (-8192 <= v < 8192) 14 bits
+// 3 bytes: v' <= 0x00200000 21 bits
+// 4 bytes: v' <= 0x10000000 28 bits
+// the number of most significant 1-bits in the first byte
+// equals the number of bytes after the first
+
+#define stb__varlen_xform(v) (v<0 ? (~v << 1)+1 : (v << 1))
+
+int stb_size_varlen(int v) { return stb_size_varlenu(stb__varlen_xform(v)); }
+int stb_size_varlenu(unsigned int v)
+{
+ if (v < 0x00000080) return 1;
+ if (v < 0x00004000) return 2;
+ if (v < 0x00200000) return 3;
+ if (v < 0x10000000) return 4;
+ return 5;
+}
+
+void stb_fput_varlen(FILE *f, int v) { stb_fput_varlenu(f, stb__varlen_xform(v)); }
+
+void stb_fput_varlenu(FILE *f, unsigned int z)
+{
+ if (z >= 0x10000000) fputc(0xF0,f);
+ if (z >= 0x00200000) fputc((z < 0x10000000 ? 0xE0 : 0)+(z>>24),f);
+ if (z >= 0x00004000) fputc((z < 0x00200000 ? 0xC0 : 0)+(z>>16),f);
+ if (z >= 0x00000080) fputc((z < 0x00004000 ? 0x80 : 0)+(z>> 8),f);
+ fputc(z,f);
+}
+
+#define stb_fgetc(f) ((unsigned char) fgetc(f))
+
+int stb_fget_varlen(FILE *f)
+{
+ unsigned int z = stb_fget_varlenu(f);
+ return (z & 1) ? ~(z>>1) : (z>>1);
+}
+
+unsigned int stb_fget_varlenu(FILE *f)
+{
+ unsigned int z;
+ unsigned char d;
+ d = stb_fgetc(f);
+
+ if (d >= 0x80) {
+ if (d >= 0xc0) {
+ if (d >= 0xe0) {
+ if (d == 0xf0) z = stb_fgetc(f) << 24;
+ else z = (d - 0xe0) << 24;
+ z += stb_fgetc(f) << 16;
+ }
+ else
+ z = (d - 0xc0) << 16;
+ z += stb_fgetc(f) << 8;
+ } else
+ z = (d - 0x80) << 8;
+ z += stb_fgetc(f);
+ } else
+ z = d;
+ return z;
+}
+
+stb_uint64 stb_fget_varlen64(FILE *f)
+{
+ stb_uint64 z;
+ unsigned char d;
+ d = stb_fgetc(f);
+
+ if (d >= 0x80) {
+ if (d >= 0xc0) {
+ if (d >= 0xe0) {
+ if (d >= 0xf0) {
+ if (d >= 0xf8) {
+ if (d >= 0xfc) {
+ if (d >= 0xfe) {
+ if (d >= 0xff)
+ z = (stb_uint64) stb_fgetc(f) << 56;
+ else
+ z = (stb_uint64) (d - 0xfe) << 56;
+ z |= (stb_uint64) stb_fgetc(f) << 48;
+ } else z = (stb_uint64) (d - 0xfc) << 48;
+ z |= (stb_uint64) stb_fgetc(f) << 40;
+ } else z = (stb_uint64) (d - 0xf8) << 40;
+ z |= (stb_uint64) stb_fgetc(f) << 32;
+ } else z = (stb_uint64) (d - 0xf0) << 32;
+ z |= (stb_uint) stb_fgetc(f) << 24;
+ } else z = (stb_uint) (d - 0xe0) << 24;
+ z |= (stb_uint) stb_fgetc(f) << 16;
+ } else z = (stb_uint) (d - 0xc0) << 16;
+ z |= (stb_uint) stb_fgetc(f) << 8;
+ } else z = (stb_uint) (d - 0x80) << 8;
+ z |= stb_fgetc(f);
+ } else
+ z = d;
+
+ return (z & 1) ? ~(z >> 1) : (z >> 1);
+}
+
+int stb_size_varlen64(stb_uint64 v)
+{
+ if (v < 0x00000080) return 1;
+ if (v < 0x00004000) return 2;
+ if (v < 0x00200000) return 3;
+ if (v < 0x10000000) return 4;
+ if (v < STB_IMM_UINT64(0x0000000800000000)) return 5;
+ if (v < STB_IMM_UINT64(0x0000040000000000)) return 6;
+ if (v < STB_IMM_UINT64(0x0002000000000000)) return 7;
+ if (v < STB_IMM_UINT64(0x0100000000000000)) return 8;
+ return 9;
+}
+
+void stb_fput_varlen64(FILE *f, stb_uint64 v)
+{
+ stb_uint64 z = stb__varlen_xform(v);
+ int first=1;
+ if (z >= STB_IMM_UINT64(0x100000000000000)) {
+ fputc(0xff,f);
+ first=0;
+ }
+ if (z >= STB_IMM_UINT64(0x02000000000000)) fputc((first ? 0xFE : 0)+(char)(z>>56),f), first=0;
+ if (z >= STB_IMM_UINT64(0x00040000000000)) fputc((first ? 0xFC : 0)+(char)(z>>48),f), first=0;
+ if (z >= STB_IMM_UINT64(0x00000800000000)) fputc((first ? 0xF8 : 0)+(char)(z>>40),f), first=0;
+ if (z >= STB_IMM_UINT64(0x00000010000000)) fputc((first ? 0xF0 : 0)+(char)(z>>32),f), first=0;
+ if (z >= STB_IMM_UINT64(0x00000000200000)) fputc((first ? 0xE0 : 0)+(char)(z>>24),f), first=0;
+ if (z >= STB_IMM_UINT64(0x00000000004000)) fputc((first ? 0xC0 : 0)+(char)(z>>16),f), first=0;
+ if (z >= STB_IMM_UINT64(0x00000000000080)) fputc((first ? 0x80 : 0)+(char)(z>> 8),f), first=0;
+ fputc((char)z,f);
+}
+
+void stb_fput_ranged(FILE *f, int v, int b, stb_uint n)
+{
+ v -= b;
+ if (n <= (1 << 31))
+ assert((stb_uint) v < n);
+ if (n > (1 << 24)) fputc(v >> 24, f);
+ if (n > (1 << 16)) fputc(v >> 16, f);
+ if (n > (1 << 8)) fputc(v >> 8, f);
+ fputc(v,f);
+}
+
+int stb_fget_ranged(FILE *f, int b, stb_uint n)
+{
+ unsigned int v=0;
+ if (n > (1 << 24)) v += stb_fgetc(f) << 24;
+ if (n > (1 << 16)) v += stb_fgetc(f) << 16;
+ if (n > (1 << 8)) v += stb_fgetc(f) << 8;
+ v += stb_fgetc(f);
+ return b+v;
+}
+
+int stb_size_ranged(int b, stb_uint n)
+{
+ if (n > (1 << 24)) return 4;
+ if (n > (1 << 16)) return 3;
+ if (n > (1 << 8)) return 2;
+ return 1;
+}
+
+void stb_fput_string(FILE *f, char *s)
+{
+ size_t len = strlen(s);
+ stb_fput_varlenu(f, (unsigned int) len);
+ fwrite(s, 1, len, f);
+}
+
+// inverse of the above algorithm
+char *stb_fget_string(FILE *f, void *p)
+{
+ char *s;
+ int len = stb_fget_varlenu(f);
+ if (len > 4096) return NULL;
+ s = p ? stb_malloc_string(p, len+1) : (char *) malloc(len+1);
+ fread(s, 1, len, f);
+ s[len] = 0;
+ return s;
+}
+
+char *stb_strdup(char *str, void *pool)
+{
+ size_t len = strlen(str);
+ char *p = stb_malloc_string(pool, len+1);
+ stb_p_strcpy_s(p, len+1, str);
+ return p;
+}
+
+// strip the trailing '/' or '\\' from a directory so we can refer to it
+// as a file for _stat()
+char *stb_strip_final_slash(char *t)
+{
+ if (t[0]) {
+ char *z = t + strlen(t) - 1;
+ // *z is the last character
+ if (*z == '\\' || *z == '/')
+ if (z != t+2 || t[1] != ':') // but don't strip it if it's e.g. "c:/"
+ *z = 0;
+ if (*z == '\\')
+ *z = '/'; // canonicalize to make sure it matches db
+ }
+ return t;
+}
+
+char *stb_strip_final_slash_regardless(char *t)
+{
+ if (t[0]) {
+ char *z = t + strlen(t) - 1;
+ // *z is the last character
+ if (*z == '\\' || *z == '/')
+ *z = 0;
+ if (*z == '\\')
+ *z = '/'; // canonicalize to make sure it matches db
+ }
+ return t;
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Options parsing
+//
+
+STB_EXTERN char **stb_getopt_param(int *argc, char **argv, char *param);
+STB_EXTERN char **stb_getopt(int *argc, char **argv);
+STB_EXTERN void stb_getopt_free(char **opts);
+
+#ifdef STB_DEFINE
+
+void stb_getopt_free(char **opts)
+{
+ int i;
+ char ** o2 = opts;
+ for (i=0; i < stb_arr_len(o2); ++i)
+ free(o2[i]);
+ stb_arr_free(o2);
+}
+
+char **stb_getopt(int *argc, char **argv)
+{
+ return stb_getopt_param(argc, argv, (char*) "");
+}
+
+char **stb_getopt_param(int *argc, char **argv, char *param)
+{
+ char ** opts=NULL;
+ int i,j=1;
+ for (i=1; i < *argc; ++i) {
+ if (argv[i][0] != '-') {
+ argv[j++] = argv[i];
+ } else {
+ if (argv[i][1] == 0) { // plain - == don't parse further options
+ ++i;
+ while (i < *argc)
+ argv[j++] = argv[i++];
+ break;
+ } else if (argv[i][1] == '-') {
+ // copy argument through including initial '-' for clarity
+ stb_arr_push(opts, stb_p_strdup(argv[i]));
+ } else {
+ int k;
+ char *q = argv[i]; // traverse options list
+ for (k=1; q[k]; ++k) {
+ char *s;
+ if (strchr(param, q[k])) { // does it take a parameter?
+ char *t = &q[k+1], z = q[k];
+ size_t len=0;
+ if (*t == 0) {
+ if (i == *argc-1) { // takes a parameter, but none found
+ *argc = 0;
+ stb_getopt_free(opts);
+ return NULL;
+ }
+ t = argv[++i];
+ } else
+ k += (int) strlen(t);
+ len = strlen(t);
+ s = (char *) malloc(len+2);
+ if (!s) return NULL;
+ s[0] = z;
+ stb_p_strcpy_s(s+1, len+2, t);
+ } else {
+ // no parameter
+ s = (char *) malloc(2);
+ if (!s) return NULL;
+ s[0] = q[k];
+ s[1] = 0;
+ }
+ stb_arr_push(opts, s);
+ }
+ }
+ }
+ }
+ stb_arr_push(opts, NULL);
+ *argc = j;
+ return opts;
+}
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Portable directory reading
+//
+
+STB_EXTERN char **stb_readdir_files (char *dir);
+STB_EXTERN char **stb_readdir_files_mask(char *dir, char *wild);
+STB_EXTERN char **stb_readdir_subdirs(char *dir);
+STB_EXTERN char **stb_readdir_subdirs_mask(char *dir, char *wild);
+STB_EXTERN void stb_readdir_free (char **files);
+STB_EXTERN char **stb_readdir_recursive(char *dir, char *filespec);
+STB_EXTERN void stb_delete_directory_recursive(char *dir);
+
+#ifdef STB_DEFINE
+
+#ifdef _MSC_VER
+#include
+#else
+#include
+#include
+#endif
+
+void stb_readdir_free(char **files)
+{
+ char **f2 = files;
+ int i;
+ for (i=0; i < stb_arr_len(f2); ++i)
+ free(f2[i]);
+ stb_arr_free(f2);
+}
+
+static int isdotdirname(char *name)
+{
+ if (name[0] == '.')
+ return (name[1] == '.') ? !name[2] : !name[1];
+ return 0;
+}
+
+STB_EXTERN int stb_wildmatchi(char *expr, char *candidate);
+static char **readdir_raw(char *dir, int return_subdirs, char *mask)
+{
+ char **results = NULL;
+ char buffer[4096], with_slash[4096];
+ size_t n;
+
+ #ifdef _MSC_VER
+ stb__wchar *ws;
+ struct _wfinddata_t data;
+ #ifdef _WIN64
+ const intptr_t none = -1;
+ intptr_t z;
+ #else
+ const long none = -1;
+ long z;
+ #endif
+ #else // !_MSC_VER
+ const DIR *none = NULL;
+ DIR *z;
+ #endif
+
+ n = stb_strscpy(buffer,dir,sizeof(buffer));
+ if (!n || n >= sizeof(buffer))
+ return NULL;
+ stb_fixpath(buffer);
+
+ if (n > 0 && (buffer[n-1] != '/')) {
+ buffer[n++] = '/';
+ }
+ buffer[n] = 0;
+ if (!stb_strscpy(with_slash,buffer,sizeof(with_slash)))
+ return NULL;
+
+ #ifdef _MSC_VER
+ if (!stb_strscpy(buffer+n,"*.*",sizeof(buffer)-n))
+ return NULL;
+ ws = stb__from_utf8(buffer);
+ z = _wfindfirst((wchar_t *)ws, &data);
+ #else
+ z = opendir(dir);
+ #endif
+
+ if (z != none) {
+ int nonempty = STB_TRUE;
+ #ifndef _MSC_VER
+ struct dirent *data = readdir(z);
+ nonempty = (data != NULL);
+ #endif
+
+ if (nonempty) {
+
+ do {
+ int is_subdir;
+ #ifdef _MSC_VER
+ char *name = stb__to_utf8((stb__wchar *)data.name);
+ if (name == NULL) {
+ fprintf(stderr, "%s to convert '%S' to %s!\n", "Unable", data.name, "utf8");
+ continue;
+ }
+ is_subdir = !!(data.attrib & _A_SUBDIR);
+ #else
+ char *name = data->d_name;
+ if (!stb_strscpy(buffer+n,name,sizeof(buffer)-n))
+ break;
+ // Could follow DT_LNK, but would need to check for recursive links.
+ is_subdir = !!(data->d_type & DT_DIR);
+ #endif
+
+ if (is_subdir == return_subdirs) {
+ if (!is_subdir || !isdotdirname(name)) {
+ if (!mask || stb_wildmatchi(mask, name)) {
+ char buffer[4096],*p=buffer;
+ if ( stb_snprintf(buffer, sizeof(buffer), "%s%s", with_slash, name) < 0 )
+ break;
+ if (buffer[0] == '.' && buffer[1] == '/')
+ p = buffer+2;
+ stb_arr_push(results, stb_p_strdup(p));
+ }
+ }
+ }
+ }
+ #ifdef _MSC_VER
+ while (0 == _wfindnext(z, &data));
+ #else
+ while ((data = readdir(z)) != NULL);
+ #endif
+ }
+ #ifdef _MSC_VER
+ _findclose(z);
+ #else
+ closedir(z);
+ #endif
+ }
+ return results;
+}
+
+char **stb_readdir_files (char *dir) { return readdir_raw(dir, 0, NULL); }
+char **stb_readdir_subdirs(char *dir) { return readdir_raw(dir, 1, NULL); }
+char **stb_readdir_files_mask(char *dir, char *wild) { return readdir_raw(dir, 0, wild); }
+char **stb_readdir_subdirs_mask(char *dir, char *wild) { return readdir_raw(dir, 1, wild); }
+
+int stb__rec_max=0x7fffffff;
+static char **stb_readdir_rec(char **sofar, char *dir, char *filespec)
+{
+ char **files;
+ char ** dirs;
+ char **p;
+
+ if (stb_arr_len(sofar) >= stb__rec_max) return sofar;
+
+ files = stb_readdir_files_mask(dir, filespec);
+ stb_arr_for(p, files) {
+ stb_arr_push(sofar, stb_p_strdup(*p));
+ if (stb_arr_len(sofar) >= stb__rec_max) break;
+ }
+ stb_readdir_free(files);
+ if (stb_arr_len(sofar) >= stb__rec_max) return sofar;
+
+ dirs = stb_readdir_subdirs(dir);
+ stb_arr_for(p, dirs)
+ sofar = stb_readdir_rec(sofar, *p, filespec);
+ stb_readdir_free(dirs);
+ return sofar;
+}
+
+char **stb_readdir_recursive(char *dir, char *filespec)
+{
+ return stb_readdir_rec(NULL, dir, filespec);
+}
+
+void stb_delete_directory_recursive(char *dir)
+{
+ char **list = stb_readdir_subdirs(dir);
+ int i;
+ for (i=0; i < stb_arr_len(list); ++i)
+ stb_delete_directory_recursive(list[i]);
+ stb_arr_free(list);
+ list = stb_readdir_files(dir);
+ for (i=0; i < stb_arr_len(list); ++i)
+ if (!remove(list[i])) {
+ // on windows, try again after making it writeable; don't ALWAYS
+ // do this first since that would be slow in the normal case
+ #ifdef _MSC_VER
+ _chmod(list[i], _S_IWRITE);
+ remove(list[i]);
+ #endif
+ }
+ stb_arr_free(list);
+ stb__windows(_rmdir,rmdir)(dir);
+}
+
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// construct trees from filenames; useful for cmirror summaries
+
+typedef struct stb_dirtree2 stb_dirtree2;
+
+struct stb_dirtree2
+{
+ stb_dirtree2 **subdirs;
+
+ // make convenient for stb_summarize_tree
+ int num_subdir;
+ float weight;
+
+ // actual data
+ char *fullpath;
+ char *relpath;
+ char **files;
+};
+
+STB_EXTERN stb_dirtree2 *stb_dirtree2_from_files_relative(char *src, char **filelist, int count);
+STB_EXTERN stb_dirtree2 *stb_dirtree2_from_files(char **filelist, int count);
+STB_EXTERN int stb_dir_is_prefix(char *dir, int dirlen, char *file);
+
+#ifdef STB_DEFINE
+
+int stb_dir_is_prefix(char *dir, int dirlen, char *file)
+{
+ if (dirlen == 0) return STB_TRUE;
+ if (stb_strnicmp(dir, file, dirlen)) return STB_FALSE;
+ if (file[dirlen] == '/' || file[dirlen] == '\\') return STB_TRUE;
+ return STB_FALSE;
+}
+
+stb_dirtree2 *stb_dirtree2_from_files_relative(char *src, char **filelist, int count)
+{
+ char buffer1[1024];
+ int i;
+ int dlen = (int) strlen(src), elen;
+ stb_dirtree2 *d;
+ char ** descendents = NULL;
+ char ** files = NULL;
+ char *s;
+ if (!count) return NULL;
+ // first find all the ones that belong here... note this is will take O(NM) with N files and M subdirs
+ for (i=0; i < count; ++i) {
+ if (stb_dir_is_prefix(src, dlen, filelist[i])) {
+ stb_arr_push(descendents, filelist[i]);
+ }
+ }
+ if (descendents == NULL)
+ return NULL;
+ elen = dlen;
+ // skip a leading slash
+ if (elen == 0 && (descendents[0][0] == '/' || descendents[0][0] == '\\'))
+ ++elen;
+ else if (elen)
+ ++elen;
+ // now extract all the ones that have their root here
+ for (i=0; i < stb_arr_len(descendents);) {
+ if (!stb_strchr2(descendents[i]+elen, '/', '\\')) {
+ stb_arr_push(files, descendents[i]);
+ descendents[i] = descendents[stb_arr_len(descendents)-1];
+ stb_arr_pop(descendents);
+ } else
+ ++i;
+ }
+ // now create a record
+ d = (stb_dirtree2 *) malloc(sizeof(*d));
+ d->files = files;
+ d->subdirs = NULL;
+ d->fullpath = stb_p_strdup(src);
+ s = stb_strrchr2(d->fullpath, '/', '\\');
+ if (s)
+ ++s;
+ else
+ s = d->fullpath;
+ d->relpath = s;
+ // now create the children
+ qsort(descendents, stb_arr_len(descendents), sizeof(char *), stb_qsort_stricmp(0));
+ buffer1[0] = 0;
+ for (i=0; i < stb_arr_len(descendents); ++i) {
+ char buffer2[1024];
+ char *s = descendents[i] + elen, *t;
+ t = stb_strchr2(s, '/', '\\');
+ assert(t);
+ stb_strncpy(buffer2, descendents[i], (int) (t-descendents[i]+1));
+ if (stb_stricmp(buffer1, buffer2)) {
+ stb_dirtree2 *t = stb_dirtree2_from_files_relative(buffer2, descendents, stb_arr_len(descendents));
+ assert(t != NULL);
+ stb_p_strcpy_s(buffer1, sizeof(buffer1), buffer2);
+ stb_arr_push(d->subdirs, t);
+ }
+ }
+ d->num_subdir = stb_arr_len(d->subdirs);
+ d->weight = 0;
+ return d;
+}
+
+stb_dirtree2 *stb_dirtree2_from_files(char **filelist, int count)
+{
+ return stb_dirtree2_from_files_relative((char*) "", filelist, count);
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Checksums: CRC-32, ADLER32, SHA-1
+//
+// CRC-32 and ADLER32 allow streaming blocks
+// SHA-1 requires either a complete buffer, max size 2^32 - 73
+// or it can checksum directly from a file, max 2^61
+
+#define STB_ADLER32_SEED 1
+#define STB_CRC32_SEED 0 // note that we logical NOT this in the code
+
+STB_EXTERN stb_uint
+ stb_adler32(stb_uint adler32, stb_uchar *buffer, stb_uint buflen);
+STB_EXTERN stb_uint
+ stb_crc32_block(stb_uint crc32, stb_uchar *buffer, stb_uint len);
+STB_EXTERN stb_uint stb_crc32(unsigned char *buffer, stb_uint len);
+
+STB_EXTERN void stb_sha1(
+ unsigned char output[20], unsigned char *buffer, unsigned int len);
+STB_EXTERN int stb_sha1_file(unsigned char output[20], char *file);
+
+STB_EXTERN void stb_sha1_readable(char display[27], unsigned char sha[20]);
+
+#ifdef STB_DEFINE
+stb_uint stb_crc32_block(stb_uint crc, unsigned char *buffer, stb_uint len)
+{
+ static stb_uint crc_table[256];
+ stb_uint i,j,s;
+ crc = ~crc;
+
+ if (crc_table[1] == 0)
+ for(i=0; i < 256; i++) {
+ for (s=i, j=0; j < 8; ++j)
+ s = (s >> 1) ^ (s & 1 ? 0xedb88320 : 0);
+ crc_table[i] = s;
+ }
+ for (i=0; i < len; ++i)
+ crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
+ return ~crc;
+}
+
+stb_uint stb_crc32(unsigned char *buffer, stb_uint len)
+{
+ return stb_crc32_block(0, buffer, len);
+}
+
+stb_uint stb_adler32(stb_uint adler32, stb_uchar *buffer, stb_uint buflen)
+{
+ const unsigned long ADLER_MOD = 65521;
+ unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
+ unsigned long blocklen, i;
+
+ blocklen = buflen % 5552;
+ while (buflen) {
+ for (i=0; i + 7 < blocklen; i += 8) {
+ s1 += buffer[0], s2 += s1;
+ s1 += buffer[1], s2 += s1;
+ s1 += buffer[2], s2 += s1;
+ s1 += buffer[3], s2 += s1;
+ s1 += buffer[4], s2 += s1;
+ s1 += buffer[5], s2 += s1;
+ s1 += buffer[6], s2 += s1;
+ s1 += buffer[7], s2 += s1;
+
+ buffer += 8;
+ }
+
+ for (; i < blocklen; ++i)
+ s1 += *buffer++, s2 += s1;
+
+ s1 %= ADLER_MOD, s2 %= ADLER_MOD;
+ buflen -= blocklen;
+ blocklen = 5552;
+ }
+ return (s2 << 16) + s1;
+}
+
+static void stb__sha1(stb_uchar *chunk, stb_uint h[5])
+{
+ int i;
+ stb_uint a,b,c,d,e;
+ stb_uint w[80];
+
+ for (i=0; i < 16; ++i)
+ w[i] = stb_big32(&chunk[i*4]);
+ for (i=16; i < 80; ++i) {
+ stb_uint t;
+ t = w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16];
+ w[i] = (t + t) | (t >> 31);
+ }
+
+ a = h[0];
+ b = h[1];
+ c = h[2];
+ d = h[3];
+ e = h[4];
+
+ #define STB__SHA1(k,f) \
+ { \
+ stb_uint temp = (a << 5) + (a >> 27) + (f) + e + (k) + w[i]; \
+ e = d; \
+ d = c; \
+ c = (b << 30) + (b >> 2); \
+ b = a; \
+ a = temp; \
+ }
+
+ i=0;
+ for (; i < 20; ++i) STB__SHA1(0x5a827999, d ^ (b & (c ^ d)) );
+ for (; i < 40; ++i) STB__SHA1(0x6ed9eba1, b ^ c ^ d );
+ for (; i < 60; ++i) STB__SHA1(0x8f1bbcdc, (b & c) + (d & (b ^ c)) );
+ for (; i < 80; ++i) STB__SHA1(0xca62c1d6, b ^ c ^ d );
+
+ #undef STB__SHA1
+
+ h[0] += a;
+ h[1] += b;
+ h[2] += c;
+ h[3] += d;
+ h[4] += e;
+}
+
+void stb_sha1(stb_uchar output[20], stb_uchar *buffer, stb_uint len)
+{
+ unsigned char final_block[128];
+ stb_uint end_start, final_len, j;
+ int i;
+
+ stb_uint h[5];
+
+ h[0] = 0x67452301;
+ h[1] = 0xefcdab89;
+ h[2] = 0x98badcfe;
+ h[3] = 0x10325476;
+ h[4] = 0xc3d2e1f0;
+
+ // we need to write padding to the last one or two
+ // blocks, so build those first into 'final_block'
+
+ // we have to write one special byte, plus the 8-byte length
+
+ // compute the block where the data runs out
+ end_start = len & ~63;
+
+ // compute the earliest we can encode the length
+ if (((len+9) & ~63) == end_start) {
+ // it all fits in one block, so fill a second-to-last block
+ end_start -= 64;
+ }
+
+ final_len = end_start + 128;
+
+ // now we need to copy the data in
+ assert(end_start + 128 >= len+9);
+ assert(end_start < len || len < 64-9);
+
+ j = 0;
+ if (end_start > len)
+ j = (stb_uint) - (int) end_start;
+
+ for (; end_start + j < len; ++j)
+ final_block[j] = buffer[end_start + j];
+ final_block[j++] = 0x80;
+ while (j < 128-5) // 5 byte length, so write 4 extra padding bytes
+ final_block[j++] = 0;
+ // big-endian size
+ final_block[j++] = len >> 29;
+ final_block[j++] = len >> 21;
+ final_block[j++] = len >> 13;
+ final_block[j++] = len >> 5;
+ final_block[j++] = len << 3;
+ assert(j == 128 && end_start + j == final_len);
+
+ for (j=0; j < final_len; j += 64) { // 512-bit chunks
+ if (j+64 >= end_start+64)
+ stb__sha1(&final_block[j - end_start], h);
+ else
+ stb__sha1(&buffer[j], h);
+ }
+
+ for (i=0; i < 5; ++i) {
+ output[i*4 + 0] = h[i] >> 24;
+ output[i*4 + 1] = h[i] >> 16;
+ output[i*4 + 2] = h[i] >> 8;
+ output[i*4 + 3] = h[i] >> 0;
+ }
+}
+
+#ifdef _MSC_VER
+int stb_sha1_file(stb_uchar output[20], char *file)
+{
+ int i;
+ stb_uint64 length=0;
+ unsigned char buffer[128];
+
+ FILE *f = stb__fopen(file, "rb");
+ stb_uint h[5];
+
+ if (f == NULL) return 0; // file not found
+
+ h[0] = 0x67452301;
+ h[1] = 0xefcdab89;
+ h[2] = 0x98badcfe;
+ h[3] = 0x10325476;
+ h[4] = 0xc3d2e1f0;
+
+ for(;;) {
+ size_t n = fread(buffer, 1, 64, f);
+ if (n == 64) {
+ stb__sha1(buffer, h);
+ length += n;
+ } else {
+ int block = 64;
+
+ length += n;
+
+ buffer[n++] = 0x80;
+
+ // if there isn't enough room for the length, double the block
+ if (n + 8 > 64)
+ block = 128;
+
+ // pad to end
+ memset(buffer+n, 0, block-8-n);
+
+ i = block - 8;
+ buffer[i++] = (stb_uchar) (length >> 53);
+ buffer[i++] = (stb_uchar) (length >> 45);
+ buffer[i++] = (stb_uchar) (length >> 37);
+ buffer[i++] = (stb_uchar) (length >> 29);
+ buffer[i++] = (stb_uchar) (length >> 21);
+ buffer[i++] = (stb_uchar) (length >> 13);
+ buffer[i++] = (stb_uchar) (length >> 5);
+ buffer[i++] = (stb_uchar) (length << 3);
+ assert(i == block);
+ stb__sha1(buffer, h);
+ if (block == 128)
+ stb__sha1(buffer+64, h);
+ else
+ assert(block == 64);
+ break;
+ }
+ }
+ fclose(f);
+
+ for (i=0; i < 5; ++i) {
+ output[i*4 + 0] = h[i] >> 24;
+ output[i*4 + 1] = h[i] >> 16;
+ output[i*4 + 2] = h[i] >> 8;
+ output[i*4 + 3] = h[i] >> 0;
+ }
+
+ return 1;
+}
+#endif // _MSC_VER
+
+// client can truncate this wherever they like
+void stb_sha1_readable(char display[27], unsigned char sha[20])
+{
+ char encoding[65] = "0123456789abcdefghijklmnopqrstuv"
+ "wxyzABCDEFGHIJKLMNOPQRSTUVWXYZ%$";
+ int num_bits = 0, acc=0;
+ int i=0,o=0;
+ while (o < 26) {
+ int v;
+ // expand the accumulator
+ if (num_bits < 6) {
+ assert(i != 20);
+ acc += sha[i++] << num_bits;
+ num_bits += 8;
+ }
+ v = acc & ((1 << 6) - 1);
+ display[o++] = encoding[v];
+ acc >>= 6;
+ num_bits -= 6;
+ }
+ assert(num_bits == 20*8 - 26*6);
+ display[o++] = encoding[acc];
+}
+
+#endif // STB_DEFINE
+
+///////////////////////////////////////////////////////////
+//
+// simplified WINDOWS registry interface... hopefully
+// we'll never actually use this?
+
+#if defined(_WIN32)
+
+STB_EXTERN void * stb_reg_open(const char *mode, const char *where); // mode: "rHKLM" or "rHKCU" or "w.."
+STB_EXTERN void stb_reg_close(void *reg);
+STB_EXTERN int stb_reg_read(void *zreg, const char *str, void *data, unsigned long len);
+STB_EXTERN int stb_reg_read_string(void *zreg, const char *str, char *data, int len);
+STB_EXTERN void stb_reg_write(void *zreg, const char *str, const void *data, unsigned long len);
+STB_EXTERN void stb_reg_write_string(void *zreg, const char *str, const char *data);
+
+#if defined(STB_DEFINE) && !defined(STB_NO_REGISTRY)
+
+#define STB_HAS_REGISTRY
+
+#ifndef _WINDOWS_
+
+#define HKEY void *
+
+STB_EXTERN __declspec(dllimport) long __stdcall RegCloseKey ( HKEY hKey );
+STB_EXTERN __declspec(dllimport) long __stdcall RegCreateKeyExA ( HKEY hKey, const char * lpSubKey,
+ int Reserved, char * lpClass, int dwOptions,
+ int samDesired, void *lpSecurityAttributes, HKEY * phkResult, int * lpdwDisposition );
+STB_EXTERN __declspec(dllimport) long __stdcall RegDeleteKeyA ( HKEY hKey, const char * lpSubKey );
+STB_EXTERN __declspec(dllimport) long __stdcall RegQueryValueExA ( HKEY hKey, const char * lpValueName,
+ int * lpReserved, unsigned long * lpType, unsigned char * lpData, unsigned long * lpcbData );
+STB_EXTERN __declspec(dllimport) long __stdcall RegSetValueExA ( HKEY hKey, const char * lpValueName,
+ int Reserved, int dwType, const unsigned char* lpData, int cbData );
+STB_EXTERN __declspec(dllimport) long __stdcall RegOpenKeyExA ( HKEY hKey, const char * lpSubKey,
+ int ulOptions, int samDesired, HKEY * phkResult );
+
+#endif // _WINDOWS_
+
+#define STB__REG_OPTION_NON_VOLATILE 0
+#define STB__REG_KEY_ALL_ACCESS 0x000f003f
+#define STB__REG_KEY_READ 0x00020019
+
+#ifdef _M_AMD64
+#define STB__HKEY_CURRENT_USER 0x80000001ull
+#define STB__HKEY_LOCAL_MACHINE 0x80000002ull
+#else
+#define STB__HKEY_CURRENT_USER 0x80000001
+#define STB__HKEY_LOCAL_MACHINE 0x80000002
+#endif
+
+void *stb_reg_open(const char *mode, const char *where)
+{
+ long res;
+ HKEY base;
+ HKEY zreg;
+ if (!stb_stricmp(mode+1, "cu") || !stb_stricmp(mode+1, "hkcu"))
+ base = (HKEY) STB__HKEY_CURRENT_USER;
+ else if (!stb_stricmp(mode+1, "lm") || !stb_stricmp(mode+1, "hklm"))
+ base = (HKEY) STB__HKEY_LOCAL_MACHINE;
+ else
+ return NULL;
+
+ if (mode[0] == 'r')
+ res = RegOpenKeyExA(base, where, 0, STB__REG_KEY_READ, &zreg);
+ else if (mode[0] == 'w')
+ res = RegCreateKeyExA(base, where, 0, NULL, STB__REG_OPTION_NON_VOLATILE, STB__REG_KEY_ALL_ACCESS, NULL, &zreg, NULL);
+ else
+ return NULL;
+
+ return res ? NULL : zreg;
+}
+
+void stb_reg_close(void *reg)
+{
+ RegCloseKey((HKEY) reg);
+}
+
+#define STB__REG_SZ 1
+#define STB__REG_BINARY 3
+#define STB__REG_DWORD 4
+
+int stb_reg_read(void *zreg, const char *str, void *data, unsigned long len)
+{
+ unsigned long type;
+ unsigned long alen = len;
+ if (0 == RegQueryValueExA((HKEY) zreg, str, 0, &type, (unsigned char *) data, &len))
+ if (type == STB__REG_BINARY || type == STB__REG_SZ || type == STB__REG_DWORD) {
+ if (len < alen)
+ *((char *) data + len) = 0;
+ return 1;
+ }
+ return 0;
+}
+
+void stb_reg_write(void *zreg, const char *str, const void *data, unsigned long len)
+{
+ if (zreg)
+ RegSetValueExA((HKEY) zreg, str, 0, STB__REG_BINARY, (const unsigned char *) data, len);
+}
+
+int stb_reg_read_string(void *zreg, const char *str, char *data, int len)
+{
+ if (!stb_reg_read(zreg, str, data, len)) return 0;
+ data[len-1] = 0; // force a 0 at the end of the string no matter what
+ return 1;
+}
+
+void stb_reg_write_string(void *zreg, const char *str, const char *data)
+{
+ if (zreg)
+ RegSetValueExA((HKEY) zreg, str, 0, STB__REG_SZ, (const unsigned char *) data, (int) strlen(data)+1);
+}
+#endif // STB_DEFINE
+#endif // _WIN32
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// stb_cfg - This is like the registry, but the config info
+// is all stored in plain old files where we can
+// backup and restore them easily. The LOCATION of
+// the config files is gotten from... the registry!
+
+#ifndef STB_NO_STB_STRINGS
+typedef struct stb_cfg_st stb_cfg;
+
+STB_EXTERN stb_cfg * stb_cfg_open(char *config, const char *mode); // mode = "r", "w"
+STB_EXTERN void stb_cfg_close(stb_cfg *cfg);
+STB_EXTERN int stb_cfg_read(stb_cfg *cfg, char *key, void *value, int len);
+STB_EXTERN void stb_cfg_write(stb_cfg *cfg, char *key, void *value, int len);
+STB_EXTERN int stb_cfg_read_string(stb_cfg *cfg, char *key, char *value, int len);
+STB_EXTERN void stb_cfg_write_string(stb_cfg *cfg, char *key, char *value);
+STB_EXTERN int stb_cfg_delete(stb_cfg *cfg, char *key);
+STB_EXTERN void stb_cfg_set_directory(char *dir);
+
+#ifdef STB_DEFINE
+
+typedef struct
+{
+ char *key;
+ void *value;
+ int value_len;
+} stb__cfg_item;
+
+struct stb_cfg_st
+{
+ stb__cfg_item *data;
+ char *loaded_file; // this needs to be freed
+ FILE *f; // write the data to this file on close
+};
+
+static const char *stb__cfg_sig = "sTbCoNfIg!\0\0";
+static char stb__cfg_dir[512];
+STB_EXTERN void stb_cfg_set_directory(char *dir)
+{
+ stb_p_strcpy_s(stb__cfg_dir, sizeof(stb__cfg_dir), dir);
+}
+
+STB_EXTERN stb_cfg * stb_cfg_open(char *config, const char *mode)
+{
+ size_t len;
+ stb_cfg *z;
+ char file[512];
+ if (mode[0] != 'r' && mode[0] != 'w') return NULL;
+
+ if (!stb__cfg_dir[0]) {
+ #ifdef _WIN32
+ stb_p_strcpy_s(stb__cfg_dir, sizeof(stb__cfg_dir), "c:/stb");
+ #else
+ strcpy(stb__cfg_dir, "~/.stbconfig");
+ #endif
+
+ #ifdef STB_HAS_REGISTRY
+ {
+ void *reg = stb_reg_open("rHKLM", "Software\\SilverSpaceship\\stb");
+ if (reg) {
+ stb_reg_read_string(reg, "config_dir", stb__cfg_dir, sizeof(stb__cfg_dir));
+ stb_reg_close(reg);
+ }
+ }
+ #endif
+ }
+
+ stb_p_sprintf(file stb_p_size(sizeof(file)), "%s/%s.cfg", stb__cfg_dir, config);
+
+ z = (stb_cfg *) stb_malloc(0, sizeof(*z));
+ z->data = NULL;
+
+ z->loaded_file = stb_filec(file, &len);
+ if (z->loaded_file) {
+ char *s = z->loaded_file;
+ if (!memcmp(s, stb__cfg_sig, 12)) {
+ char *s = z->loaded_file + 12;
+ while (s < z->loaded_file + len) {
+ stb__cfg_item a;
+ int n = *(stb_int16 *) s;
+ a.key = s+2;
+ s = s+2 + n;
+ a.value_len = *(int *) s;
+ s += 4;
+ a.value = s;
+ s += a.value_len;
+ stb_arr_push(z->data, a);
+ }
+ assert(s == z->loaded_file + len);
+ }
+ }
+
+ if (mode[0] == 'w')
+ z->f = stb_p_fopen(file, "wb");
+ else
+ z->f = NULL;
+
+ return z;
+}
+
+void stb_cfg_close(stb_cfg *z)
+{
+ if (z->f) {
+ int i;
+ // write the file out
+ fwrite(stb__cfg_sig, 12, 1, z->f);
+ for (i=0; i < stb_arr_len(z->data); ++i) {
+ stb_int16 n = (stb_int16) strlen(z->data[i].key)+1;
+ fwrite(&n, 2, 1, z->f);
+ fwrite(z->data[i].key, n, 1, z->f);
+ fwrite(&z->data[i].value_len, 4, 1, z->f);
+ fwrite(z->data[i].value, z->data[i].value_len, 1, z->f);
+ }
+ fclose(z->f);
+ }
+ stb_arr_free(z->data);
+ stb_free(z);
+}
+
+int stb_cfg_read(stb_cfg *z, char *key, void *value, int len)
+{
+ int i;
+ for (i=0; i < stb_arr_len(z->data); ++i) {
+ if (!stb_stricmp(z->data[i].key, key)) {
+ int n = stb_min(len, z->data[i].value_len);
+ memcpy(value, z->data[i].value, n);
+ if (n < len)
+ *((char *) value + n) = 0;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void stb_cfg_write(stb_cfg *z, char *key, void *value, int len)
+{
+ int i;
+ for (i=0; i < stb_arr_len(z->data); ++i)
+ if (!stb_stricmp(z->data[i].key, key))
+ break;
+ if (i == stb_arr_len(z->data)) {
+ stb__cfg_item p;
+ p.key = stb_strdup(key, z);
+ p.value = NULL;
+ p.value_len = 0;
+ stb_arr_push(z->data, p);
+ }
+ z->data[i].value = stb_malloc(z, len);
+ z->data[i].value_len = len;
+ memcpy(z->data[i].value, value, len);
+}
+
+int stb_cfg_delete(stb_cfg *z, char *key)
+{
+ int i;
+ for (i=0; i < stb_arr_len(z->data); ++i)
+ if (!stb_stricmp(z->data[i].key, key)) {
+ stb_arr_fastdelete(z->data, i);
+ return 1;
+ }
+ return 0;
+}
+
+int stb_cfg_read_string(stb_cfg *z, char *key, char *value, int len)
+{
+ if (!stb_cfg_read(z, key, value, len)) return 0;
+ value[len-1] = 0;
+ return 1;
+}
+
+void stb_cfg_write_string(stb_cfg *z, char *key, char *value)
+{
+ stb_cfg_write(z, key, value, (int) strlen(value)+1);
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// stb_dirtree - load a description of a directory tree
+// uses a cache and stat()s the directories for changes
+// MUCH faster on NTFS, _wrong_ on FAT32, so should
+// ignore the db on FAT32
+
+#ifdef _WIN32
+
+typedef struct
+{
+ char * path; // full path from passed-in root
+ time_t last_modified;
+ int num_files;
+ int flag;
+} stb_dirtree_dir;
+
+typedef struct
+{
+ char *name; // name relative to path
+ int dir; // index into dirs[] array
+ stb_int64 size; // size, max 4GB
+ time_t last_modified;
+ int flag;
+} stb_dirtree_file;
+
+typedef struct
+{
+ stb_dirtree_dir *dirs;
+ stb_dirtree_file *files;
+
+ // internal use
+ void * string_pool; // used to free data en masse
+} stb_dirtree;
+
+extern void stb_dirtree_free ( stb_dirtree *d );
+extern stb_dirtree *stb_dirtree_get ( char *dir);
+extern stb_dirtree *stb_dirtree_get_dir ( char *dir, char *cache_dir);
+extern stb_dirtree *stb_dirtree_get_with_file ( char *dir, char *cache_file);
+
+// get a list of all the files recursively underneath 'dir'
+//
+// cache_file is used to store a copy of the directory tree to speed up
+// later calls. It must be unique to 'dir' and the current working
+// directory! Otherwise who knows what will happen (a good solution
+// is to put it _in_ dir, but this API doesn't force that).
+//
+// Also, it might be possible to break this if you have two different processes
+// do a call to stb_dirtree_get() with the same cache file at about the same
+// time, but I _think_ it might just work.
+
+// i needed to build an identical data structure representing the state of
+// a mirrored copy WITHOUT bothering to rescan it (i.e. we're mirroring to
+// it WITHOUT scanning it, e.g. it's over the net), so this requires access
+// to all of the innards.
+extern void stb_dirtree_db_add_dir(stb_dirtree *active, char *path, time_t last);
+extern void stb_dirtree_db_add_file(stb_dirtree *active, char *name, int dir, stb_int64 size, time_t last);
+extern void stb_dirtree_db_read(stb_dirtree *target, char *filename, char *dir);
+extern void stb_dirtree_db_write(stb_dirtree *target, char *filename, char *dir);
+
+#ifdef STB_DEFINE
+static void stb__dirtree_add_dir(char *path, time_t last, stb_dirtree *active)
+{
+ stb_dirtree_dir d;
+ d.last_modified = last;
+ d.num_files = 0;
+ d.path = stb_strdup(path, active->string_pool);
+ stb_arr_push(active->dirs, d);
+}
+
+static void stb__dirtree_add_file(char *name, int dir, stb_int64 size, time_t last, stb_dirtree *active)
+{
+ stb_dirtree_file f;
+ f.dir = dir;
+ f.size = size;
+ f.last_modified = last;
+ f.name = stb_strdup(name, active->string_pool);
+ ++active->dirs[dir].num_files;
+ stb_arr_push(active->files, f);
+}
+
+// version 02 supports > 4GB files
+static char stb__signature[12] = { 's', 'T', 'b', 'D', 'i', 'R', 't', 'R', 'e', 'E', '0', '2' };
+
+static void stb__dirtree_save_db(char *filename, stb_dirtree *data, char *root)
+{
+ int i, num_dirs_final=0, num_files_final;
+ char *info = root ? root : (char*)"";
+ int *remap;
+ FILE *f = stb_p_fopen(filename, "wb");
+ if (!f) return;
+
+ fwrite(stb__signature, sizeof(stb__signature), 1, f);
+ fwrite(info, strlen(info)+1, 1, f);
+ // need to be slightly tricky and not write out NULLed directories, nor the root
+
+ // build remapping table of all dirs we'll be writing out
+ remap = (int *) malloc(sizeof(remap[0]) * stb_arr_len(data->dirs));
+ for (i=0; i < stb_arr_len(data->dirs); ++i) {
+ if (data->dirs[i].path == NULL || (root && 0==stb_stricmp(data->dirs[i].path, root))) {
+ remap[i] = -1;
+ } else {
+ remap[i] = num_dirs_final++;
+ }
+ }
+
+ fwrite(&num_dirs_final, 4, 1, f);
+ for (i=0; i < stb_arr_len(data->dirs); ++i) {
+ if (remap[i] >= 0) {
+ fwrite(&data->dirs[i].last_modified, 4, 1, f);
+ stb_fput_string(f, data->dirs[i].path);
+ }
+ }
+
+ num_files_final = 0;
+ for (i=0; i < stb_arr_len(data->files); ++i)
+ if (remap[data->files[i].dir] >= 0 && data->files[i].name)
+ ++num_files_final;
+
+ fwrite(&num_files_final, 4, 1, f);
+ for (i=0; i < stb_arr_len(data->files); ++i) {
+ if (remap[data->files[i].dir] >= 0 && data->files[i].name) {
+ stb_fput_ranged(f, remap[data->files[i].dir], 0, num_dirs_final);
+ stb_fput_varlen64(f, data->files[i].size);
+ fwrite(&data->files[i].last_modified, 4, 1, f);
+ stb_fput_string(f, data->files[i].name);
+ }
+ }
+
+ fclose(f);
+}
+
+// note: stomps any existing data, rather than appending
+static void stb__dirtree_load_db(char *filename, stb_dirtree *data, char *dir)
+{
+ char sig[2048];
+ int i,n;
+ FILE *f = stb_p_fopen(filename, "rb");
+
+ if (!f) return;
+
+ data->string_pool = stb_malloc(0,1);
+
+ fread(sig, sizeof(stb__signature), 1, f);
+ if (memcmp(stb__signature, sig, sizeof(stb__signature))) { fclose(f); return; }
+ if (!fread(sig, strlen(dir)+1, 1, f)) { fclose(f); return; }
+ if (stb_stricmp(sig,dir)) { fclose(f); return; }
+
+ // we can just read them straight in, because they're guaranteed to be valid
+ fread(&n, 4, 1, f);
+ stb_arr_setlen(data->dirs, n);
+ for(i=0; i < stb_arr_len(data->dirs); ++i) {
+ fread(&data->dirs[i].last_modified, 4, 1, f);
+ data->dirs[i].path = stb_fget_string(f, data->string_pool);
+ if (data->dirs[i].path == NULL) goto bail;
+ }
+ fread(&n, 4, 1, f);
+ stb_arr_setlen(data->files, n);
+ for (i=0; i < stb_arr_len(data->files); ++i) {
+ data->files[i].dir = stb_fget_ranged(f, 0, stb_arr_len(data->dirs));
+ data->files[i].size = stb_fget_varlen64(f);
+ fread(&data->files[i].last_modified, 4, 1, f);
+ data->files[i].name = stb_fget_string(f, data->string_pool);
+ if (data->files[i].name == NULL) goto bail;
+ }
+
+ if (0) {
+ bail:
+ stb_arr_free(data->dirs);
+ stb_arr_free(data->files);
+ }
+ fclose(f);
+}
+
+FILE *hlog;
+
+static int stb__dircount, stb__dircount_mask, stb__showfile;
+static void stb__dirtree_scandir(char *path, time_t last_time, stb_dirtree *active)
+{
+ // this is dumb depth first; theoretically it might be faster
+ // to fully traverse each directory before visiting its children,
+ // but it's complicated and didn't seem like a gain in the test app
+
+ int n;
+
+ struct _wfinddatai64_t c_file;
+ long hFile;
+ stb__wchar full_path[1024];
+ int has_slash;
+ if (stb__showfile) printf("<");
+
+ has_slash = (path[0] && path[strlen(path)-1] == '/');
+
+ // @TODO: do this concatenation without using swprintf to avoid this mess:
+#if (defined(_MSC_VER) && _MSC_VER < 1400) // || (defined(__clang__))
+ // confusingly, Windows Kits\10 needs to go down this path?!?
+ // except now it doesn't, I don't know what changed
+ if (has_slash)
+ swprintf(full_path, L"%s*", stb__from_utf8(path));
+ else
+ swprintf(full_path, L"%s/*", stb__from_utf8(path));
+#else
+ if (has_slash)
+ swprintf((wchar_t *) full_path, (size_t) 1024, L"%s*", (wchar_t *) stb__from_utf8(path));
+ else
+ swprintf((wchar_t *) full_path, (size_t) 1024, L"%s/*", (wchar_t *) stb__from_utf8(path));
+#endif
+
+ // it's possible this directory is already present: that means it was in the
+ // cache, but its parent wasn't... in that case, we're done with it
+ if (stb__showfile) printf("C[%d]", stb_arr_len(active->dirs));
+ for (n=0; n < stb_arr_len(active->dirs); ++n)
+ if (0 == stb_stricmp(active->dirs[n].path, path)) {
+ if (stb__showfile) printf("D");
+ return;
+ }
+ if (stb__showfile) printf("E");
+
+ // otherwise, we need to add it
+ stb__dirtree_add_dir(path, last_time, active);
+ n = stb_arr_lastn(active->dirs);
+
+ if (stb__showfile) printf("[");
+ if( (hFile = (long) _wfindfirsti64( (wchar_t *) full_path, &c_file )) != -1L ) {
+ do {
+ if (stb__showfile) printf(")");
+ if (c_file.attrib & _A_SUBDIR) {
+ // ignore subdirectories starting with '.', e.g. "." and ".."
+ if (c_file.name[0] != '.') {
+ char *new_path = (char *) full_path;
+ char *temp = stb__to_utf8((stb__wchar *) c_file.name);
+
+ if (has_slash)
+ stb_p_sprintf(new_path stb_p_size(sizeof(full_path)), "%s%s", path, temp);
+ else
+ stb_p_sprintf(new_path stb_p_size(sizeof(full_path)), "%s/%s", path, temp);
+
+ if (stb__dircount_mask) {
+ ++stb__dircount;
+ if (!(stb__dircount & stb__dircount_mask)) {
+ char dummy_path[128], *pad;
+ stb_strncpy(dummy_path, new_path, sizeof(dummy_path)-1);
+ if (strlen(dummy_path) > 96) {
+ stb_p_strcpy_s(dummy_path+96/2-1,128, "...");
+ stb_p_strcpy_s(dummy_path+96/2+2,128, new_path + strlen(new_path)-96/2+2);
+ }
+ pad = dummy_path + strlen(dummy_path);
+ while (pad < dummy_path+98)
+ *pad++ = ' ';
+ *pad = 0;
+ printf("%s\r", dummy_path);
+ #if 0
+ if (hlog == 0) {
+ hlog = stb_p_fopen("c:/x/temp.log", "w");
+ fprintf(hlog, "%s\n", dummy_path);
+ }
+ #endif
+ }
+ }
+
+ stb__dirtree_scandir(new_path, c_file.time_write, active);
+ }
+ } else {
+ char *temp = stb__to_utf8((stb__wchar *) c_file.name);
+ stb__dirtree_add_file(temp, n, c_file.size, c_file.time_write, active);
+ }
+ if (stb__showfile) printf("(");
+ } while( _wfindnexti64( hFile, &c_file ) == 0 );
+ if (stb__showfile) printf("]");
+ _findclose( hFile );
+ }
+ if (stb__showfile) printf(">\n");
+}
+
+// scan the database and see if it's all valid
+static int stb__dirtree_update_db(stb_dirtree *db, stb_dirtree *active)
+{
+ int changes_detected = STB_FALSE;
+ int i;
+ int *remap;
+ int *rescan=NULL;
+ remap = (int *) malloc(sizeof(remap[0]) * stb_arr_len(db->dirs));
+ memset(remap, 0, sizeof(remap[0]) * stb_arr_len(db->dirs));
+ rescan = NULL;
+
+ for (i=0; i < stb_arr_len(db->dirs); ++i) {
+ struct _stat info;
+ if (stb__dircount_mask) {
+ ++stb__dircount;
+ if (!(stb__dircount & stb__dircount_mask)) {
+ printf(".");
+ }
+ }
+ if (0 == _stat(db->dirs[i].path, &info)) {
+ if (info.st_mode & _S_IFDIR) {
+ // it's still a directory, as expected
+ int n = abs((int) (info.st_mtime - db->dirs[i].last_modified));
+ if (n > 1 && n != 3600) { // the 3600 is a hack because sometimes this jumps for no apparent reason, even when no time zone or DST issues are at play
+ // it's changed! force a rescan
+ // we don't want to scan it until we've stat()d its
+ // subdirs, though, so we queue it
+ if (stb__showfile) printf("Changed: %s - %08x:%08x\n", db->dirs[i].path, (unsigned int) db->dirs[i].last_modified, (unsigned int) info.st_mtime);
+ stb_arr_push(rescan, i);
+ // update the last_mod time
+ db->dirs[i].last_modified = info.st_mtime;
+ // ignore existing files in this dir
+ remap[i] = -1;
+ changes_detected = STB_TRUE;
+ } else {
+ // it hasn't changed, just copy it through unchanged
+ stb__dirtree_add_dir(db->dirs[i].path, db->dirs[i].last_modified, active);
+ remap[i] = stb_arr_lastn(active->dirs);
+ }
+ } else {
+ // this path used to refer to a directory, but now it's a file!
+ // assume that the parent directory is going to be forced to rescan anyway
+ goto delete_entry;
+ }
+ } else {
+ delete_entry:
+ // directory no longer exists, so don't copy it
+ // we don't free it because it's in the string pool now
+ db->dirs[i].path = NULL;
+ remap[i] = -1;
+ changes_detected = STB_TRUE;
+ }
+ }
+
+ // at this point, we have:
+ //
+ // holds a list of directory indices that need to be scanned due to being out of date
+ // holds the directory index in for each dir in , if it exists; -1 if not
+ // directories in are not in yet
+
+ // so we can go ahead and remap all the known files right now
+ for (i=0; i < stb_arr_len(db->files); ++i) {
+ int dir = db->files[i].dir;
+ if (remap[dir] >= 0) {
+ stb__dirtree_add_file(db->files[i].name, remap[dir], db->files[i].size, db->files[i].last_modified, active);
+ }
+ }
+
+ // at this point we're done with db->files, and done with remap
+ free(remap);
+
+ // now scan those directories using the standard scan
+ for (i=0; i < stb_arr_len(rescan); ++i) {
+ int z = rescan[i];
+ stb__dirtree_scandir(db->dirs[z].path, db->dirs[z].last_modified, active);
+ }
+ stb_arr_free(rescan);
+
+ return changes_detected;
+}
+
+static void stb__dirtree_free_raw(stb_dirtree *d)
+{
+ stb_free(d->string_pool);
+ stb_arr_free(d->dirs);
+ stb_arr_free(d->files);
+}
+
+stb_dirtree *stb_dirtree_get_with_file(char *dir, char *cache_file)
+{
+ stb_dirtree *output = (stb_dirtree *) malloc(sizeof(*output));
+ stb_dirtree db,active;
+ int prev_dir_count, cache_mismatch;
+
+ char *stripped_dir; // store the directory name without a trailing '/' or '\\'
+
+ // load the database of last-known state on disk
+ db.string_pool = NULL;
+ db.files = NULL;
+ db.dirs = NULL;
+
+ stripped_dir = stb_strip_final_slash(stb_p_strdup(dir));
+
+ if (cache_file != NULL)
+ stb__dirtree_load_db(cache_file, &db, stripped_dir);
+ else if (stb__showfile)
+ printf("No cache file\n");
+
+ active.files = NULL;
+ active.dirs = NULL;
+ active.string_pool = stb_malloc(0,1); // @TODO: share string pools between both?
+
+ // check all the directories in the database; make note if
+ // anything we scanned had changed, and rescan those things
+ cache_mismatch = stb__dirtree_update_db(&db, &active);
+
+ // check the root tree
+ prev_dir_count = stb_arr_len(active.dirs); // record how many directories we've seen
+
+ stb__dirtree_scandir(stripped_dir, 0, &active); // no last_modified time available for root
+
+ if (stb__dircount_mask)
+ printf(" \r");
+
+ // done with the DB; write it back out if any changes, i.e. either
+ // 1. any inconsistency found between cached information and actual disk
+ // or 2. if scanning the root found any new directories--which we detect because
+ // more than one directory got added to the active db during that scan
+ if (cache_mismatch || stb_arr_len(active.dirs) > prev_dir_count+1)
+ stb__dirtree_save_db(cache_file, &active, stripped_dir);
+
+ free(stripped_dir);
+
+ stb__dirtree_free_raw(&db);
+
+ *output = active;
+ return output;
+}
+
+stb_dirtree *stb_dirtree_get_dir(char *dir, char *cache_dir)
+{
+ int i;
+ stb_uint8 sha[20];
+ char dir_lower[1024];
+ char cache_file[1024],*s;
+ if (cache_dir == NULL)
+ return stb_dirtree_get_with_file(dir, NULL);
+ stb_p_strcpy_s(dir_lower, sizeof(dir_lower), dir);
+ stb_tolower(dir_lower);
+ stb_sha1(sha, (unsigned char *) dir_lower, (unsigned int) strlen(dir_lower));
+ stb_p_strcpy_s(cache_file, sizeof(cache_file), cache_dir);
+ s = cache_file + strlen(cache_file);
+ if (s[-1] != '/' && s[-1] != '\\') *s++ = '/';
+ stb_p_strcpy_s(s, sizeof(cache_file), "dirtree_");
+ s += strlen(s);
+ for (i=0; i < 8; ++i) {
+ char *hex = (char*)"0123456789abcdef";
+ stb_uint z = sha[i];
+ *s++ = hex[z >> 4];
+ *s++ = hex[z & 15];
+ }
+ stb_p_strcpy_s(s, sizeof(cache_file), ".bin");
+ return stb_dirtree_get_with_file(dir, cache_file);
+}
+
+stb_dirtree *stb_dirtree_get(char *dir)
+{
+ char cache_dir[256];
+ stb_p_strcpy_s(cache_dir, sizeof(cache_dir), "c:/bindata");
+ #ifdef STB_HAS_REGISTRY
+ {
+ void *reg = stb_reg_open("rHKLM", "Software\\SilverSpaceship\\stb");
+ if (reg) {
+ stb_reg_read(reg, "dirtree", cache_dir, sizeof(cache_dir));
+ stb_reg_close(reg);
+ }
+ }
+ #endif
+ return stb_dirtree_get_dir(dir, cache_dir);
+}
+
+void stb_dirtree_free(stb_dirtree *d)
+{
+ stb__dirtree_free_raw(d);
+ free(d);
+}
+
+void stb_dirtree_db_add_dir(stb_dirtree *active, char *path, time_t last)
+{
+ stb__dirtree_add_dir(path, last, active);
+}
+
+void stb_dirtree_db_add_file(stb_dirtree *active, char *name, int dir, stb_int64 size, time_t last)
+{
+ stb__dirtree_add_file(name, dir, size, last, active);
+}
+
+void stb_dirtree_db_read(stb_dirtree *target, char *filename, char *dir)
+{
+ char *s = stb_strip_final_slash(stb_p_strdup(dir));
+ target->dirs = 0;
+ target->files = 0;
+ target->string_pool = 0;
+ stb__dirtree_load_db(filename, target, s);
+ free(s);
+}
+
+void stb_dirtree_db_write(stb_dirtree *target, char *filename, char *dir)
+{
+ stb__dirtree_save_db(filename, target, 0); // don't strip out any directories
+}
+
+#endif // STB_DEFINE
+
+#endif // _WIN32
+#endif // STB_NO_STB_STRINGS
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// STB_MALLOC_WRAPPER
+//
+// you can use the wrapper functions with your own malloc wrapper,
+// or define STB_MALLOC_WRAPPER project-wide to have
+// malloc/free/realloc/strdup all get vectored to it
+
+// this has too many very specific error messages you could google for and find in stb.h,
+// so don't use it if they don't want any stb.h-identifiable strings
+#if defined(STB_DEFINE) && !defined(STB_NO_STB_STRINGS)
+
+typedef struct
+{
+ void *p;
+ char *file;
+ int line;
+ size_t size;
+} stb_malloc_record;
+
+#ifndef STB_MALLOC_HISTORY_COUNT
+#define STB_MALLOC_HISTORY_COUNT 50 // 800 bytes
+#endif
+
+stb_malloc_record *stb__allocations;
+static int stb__alloc_size, stb__alloc_limit, stb__alloc_mask;
+int stb__alloc_count;
+
+stb_malloc_record stb__alloc_history[STB_MALLOC_HISTORY_COUNT];
+int stb__history_pos;
+
+static int stb__hashfind(void *p)
+{
+ stb_uint32 h = stb_hashptr(p);
+ int s,n = h & stb__alloc_mask;
+ if (stb__allocations[n].p == p)
+ return n;
+ s = stb_rehash(h)|1;
+ for(;;) {
+ if (stb__allocations[n].p == NULL)
+ return -1;
+ n = (n+s) & stb__alloc_mask;
+ if (stb__allocations[n].p == p)
+ return n;
+ }
+}
+
+size_t stb_wrapper_allocsize(void *p)
+{
+ int n = stb__hashfind(p);
+ if (n < 0) return 0;
+ return stb__allocations[n].size;
+}
+
+static int stb__historyfind(void *p)
+{
+ int n = stb__history_pos;
+ int i;
+ for (i=0; i < STB_MALLOC_HISTORY_COUNT; ++i) {
+ if (--n < 0) n = STB_MALLOC_HISTORY_COUNT-1;
+ if (stb__alloc_history[n].p == p)
+ return n;
+ }
+ return -1;
+}
+
+static void stb__add_alloc(void *p, size_t sz, char *file, int line);
+static void stb__grow_alloc(void)
+{
+ int i,old_num = stb__alloc_size;
+ stb_malloc_record *old = stb__allocations;
+ if (stb__alloc_size == 0)
+ stb__alloc_size = 64;
+ else
+ stb__alloc_size *= 2;
+
+ stb__allocations = (stb_malloc_record *) stb__realloc_raw(NULL, stb__alloc_size * sizeof(stb__allocations[0]));
+ if (stb__allocations == NULL)
+ stb_fatal("Internal error: couldn't grow malloc wrapper table");
+ memset(stb__allocations, 0, stb__alloc_size * sizeof(stb__allocations[0]));
+ stb__alloc_limit = (stb__alloc_size*3)>>2;
+ stb__alloc_mask = stb__alloc_size-1;
+
+ stb__alloc_count = 0;
+
+ for (i=0; i < old_num; ++i)
+ if (old[i].p > STB_DEL) {
+ stb__add_alloc(old[i].p, old[i].size, old[i].file, old[i].line);
+ assert(stb__hashfind(old[i].p) >= 0);
+ }
+ for (i=0; i < old_num; ++i)
+ if (old[i].p > STB_DEL)
+ assert(stb__hashfind(old[i].p) >= 0);
+ stb__realloc_raw(old, 0);
+}
+
+static void stb__add_alloc(void *p, size_t sz, char *file, int line)
+{
+ stb_uint32 h;
+ int n;
+ if (stb__alloc_count >= stb__alloc_limit)
+ stb__grow_alloc();
+ h = stb_hashptr(p);
+ n = h & stb__alloc_mask;
+ if (stb__allocations[n].p > STB_DEL) {
+ int s = stb_rehash(h)|1;
+ do {
+ n = (n+s) & stb__alloc_mask;
+ } while (stb__allocations[n].p > STB_DEL);
+ }
+ assert(stb__allocations[n].p == NULL || stb__allocations[n].p == STB_DEL);
+ stb__allocations[n].p = p;
+ stb__allocations[n].size = sz;
+ stb__allocations[n].line = line;
+ stb__allocations[n].file = file;
+ ++stb__alloc_count;
+}
+
+static void stb__remove_alloc(int n, char *file, int line)
+{
+ stb__alloc_history[stb__history_pos] = stb__allocations[n];
+ stb__alloc_history[stb__history_pos].file = file;
+ stb__alloc_history[stb__history_pos].line = line;
+ if (++stb__history_pos == STB_MALLOC_HISTORY_COUNT)
+ stb__history_pos = 0;
+ stb__allocations[n].p = STB_DEL;
+ --stb__alloc_count;
+}
+
+void stb_wrapper_malloc(void *p, size_t sz, char *file, int line)
+{
+ if (!p) return;
+ stb__add_alloc(p,sz,file,line);
+}
+
+void stb_wrapper_free(void *p, char *file, int line)
+{
+ int n;
+
+ if (p == NULL) return;
+
+ n = stb__hashfind(p);
+
+ if (n >= 0)
+ stb__remove_alloc(n, file, line);
+ else {
+ // tried to free something we hadn't allocated!
+ n = stb__historyfind(p);
+ assert(0); /* NOTREACHED */
+ if (n >= 0)
+ stb_fatal("Attempted to free %d-byte block %p at %s:%d previously freed/realloced at %s:%d",
+ stb__alloc_history[n].size, p,
+ file, line,
+ stb__alloc_history[n].file, stb__alloc_history[n].line);
+ else
+ stb_fatal("Attempted to free unknown block %p at %s:%d", p, file,line);
+ }
+}
+
+void stb_wrapper_check(void *p)
+{
+ int n;
+
+ if (p == NULL) return;
+
+ n = stb__hashfind(p);
+
+ if (n >= 0) return;
+
+ for (n=0; n < stb__alloc_size; ++n)
+ if (stb__allocations[n].p == p)
+ stb_fatal("Internal error: pointer %p was allocated, but hash search failed", p);
+
+ // tried to free something that wasn't allocated!
+ n = stb__historyfind(p);
+ if (n >= 0)
+ stb_fatal("Checked %d-byte block %p previously freed/realloced at %s:%d",
+ stb__alloc_history[n].size, p,
+ stb__alloc_history[n].file, stb__alloc_history[n].line);
+ stb_fatal("Checked unknown block %p");
+}
+
+void stb_wrapper_realloc(void *p, void *q, size_t sz, char *file, int line)
+{
+ int n;
+ if (p == NULL) { stb_wrapper_malloc(q, sz, file, line); return; }
+ if (q == NULL) return; // nothing happened
+
+ n = stb__hashfind(p);
+ if (n == -1) {
+ // tried to free something we hadn't allocated!
+ // this is weird, though, because we got past the realloc!
+ n = stb__historyfind(p);
+ assert(0); /* NOTREACHED */
+ if (n >= 0)
+ stb_fatal("Attempted to realloc %d-byte block %p at %s:%d previously freed/realloced at %s:%d",
+ stb__alloc_history[n].size, p,
+ file, line,
+ stb__alloc_history[n].file, stb__alloc_history[n].line);
+ else
+ stb_fatal("Attempted to realloc unknown block %p at %s:%d", p, file,line);
+ } else {
+ if (q == p) {
+ stb__allocations[n].size = sz;
+ stb__allocations[n].file = file;
+ stb__allocations[n].line = line;
+ } else {
+ stb__remove_alloc(n, file, line);
+ stb__add_alloc(q,sz,file,line);
+ }
+ }
+}
+
+void stb_wrapper_listall(void (*func)(void *ptr, size_t sz, char *file, int line))
+{
+ int i;
+ for (i=0; i < stb__alloc_size; ++i)
+ if (stb__allocations[i].p > STB_DEL)
+ func(stb__allocations[i].p , stb__allocations[i].size,
+ stb__allocations[i].file, stb__allocations[i].line);
+}
+
+void stb_wrapper_dump(char *filename)
+{
+ int i;
+ FILE *f = stb_p_fopen(filename, "w");
+ if (!f) return;
+ for (i=0; i < stb__alloc_size; ++i)
+ if (stb__allocations[i].p > STB_DEL)
+ fprintf(f, "%p %7d - %4d %s\n",
+ stb__allocations[i].p , (int) stb__allocations[i].size,
+ stb__allocations[i].line, stb__allocations[i].file);
+}
+#endif // STB_DEFINE
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// stb_pointer_set
+//
+//
+// For data structures that support querying by key, data structure
+// classes always hand-wave away the issue of what to do if two entries
+// have the same key: basically, store a linked list of all the nodes
+// which have the same key (a LISP-style list).
+//
+// The thing is, it's not that trivial. If you have an O(log n)
+// lookup data structure, but then n/4 items have the same value,
+// you don't want to spend O(n) time scanning that list when
+// deleting an item if you already have a pointer to the item.
+// (You have to spend O(n) time enumerating all the items with
+// a given key, sure, and you can't accelerate deleting a particular
+// item if you only have the key, not a pointer to the item.)
+//
+// I'm going to call this data structure, whatever it turns out to
+// be, a "pointer set", because we don't store any associated data for
+// items in this data structure, we just answer the question of
+// whether an item is in it or not (it's effectively one bit per pointer).
+// Technically they don't have to be pointers; you could cast ints
+// to (void *) if you want, but you can't store 0 or 1 because of the
+// hash table.
+//
+// Since the fastest data structure we might want to add support for
+// identical-keys to is a hash table with O(1)-ish lookup time,
+// that means that the conceptual "linked list of all items with
+// the same indexed value" that we build needs to have the same
+// performance; that way when we index a table we think is arbitrary
+// ints, but in fact half of them are 0, we don't get screwed.
+//
+// Therefore, it needs to be a hash table, at least when it gets
+// large. On the other hand, when the data has totally arbitrary ints
+// or floats, there won't be many collisions, and we'll have tons of
+// 1-item bitmaps. That will be grossly inefficient as hash tables;
+// trade-off; the hash table is reasonably efficient per-item when
+// it's large, but not when it's small. So we need to do something
+// Judy-like and use different strategies depending on the size.
+//
+// Like Judy, we'll use the bottom bit to encode the strategy:
+//
+// bottom bits:
+// 00 - direct pointer
+// 01 - 4-item bucket (16 bytes, no length, NULLs)
+// 10 - N-item array
+// 11 - hash table
+
+typedef struct stb_ps stb_ps;
+
+STB_EXTERN int stb_ps_find (stb_ps *ps, void *value);
+STB_EXTERN stb_ps * stb_ps_add (stb_ps *ps, void *value);
+STB_EXTERN stb_ps * stb_ps_remove(stb_ps *ps, void *value);
+STB_EXTERN stb_ps * stb_ps_remove_any(stb_ps *ps, void **value);
+STB_EXTERN void stb_ps_delete(stb_ps *ps);
+STB_EXTERN int stb_ps_count (stb_ps *ps);
+
+STB_EXTERN stb_ps * stb_ps_copy (stb_ps *ps);
+STB_EXTERN int stb_ps_subset(stb_ps *bigger, stb_ps *smaller);
+STB_EXTERN int stb_ps_eq (stb_ps *p0, stb_ps *p1);
+
+STB_EXTERN void ** stb_ps_getlist (stb_ps *ps, int *count);
+STB_EXTERN int stb_ps_writelist(stb_ps *ps, void **list, int size );
+
+// enum and fastlist don't allocate storage, but you must consume the
+// list before there's any chance the data structure gets screwed up;
+STB_EXTERN int stb_ps_enum (stb_ps *ps, void *data,
+ int (*func)(void *value, void*data) );
+STB_EXTERN void ** stb_ps_fastlist(stb_ps *ps, int *count);
+// result:
+// returns a list, *count is the length of that list,
+// but some entries of the list may be invalid;
+// test with 'stb_ps_fastlist_valid(x)'
+
+#define stb_ps_fastlist_valid(x) ((stb_uinta) (x) > 1)
+
+#ifdef STB_DEFINE
+
+enum
+{
+ STB_ps_direct = 0,
+ STB_ps_bucket = 1,
+ STB_ps_array = 2,
+ STB_ps_hash = 3,
+};
+
+#define STB_BUCKET_SIZE 4
+
+typedef struct
+{
+ void *p[STB_BUCKET_SIZE];
+} stb_ps_bucket;
+#define GetBucket(p) ((stb_ps_bucket *) ((char *) (p) - STB_ps_bucket))
+#define EncodeBucket(p) ((stb_ps *) ((char *) (p) + STB_ps_bucket))
+
+static void stb_bucket_free(stb_ps_bucket *b)
+{
+ free(b);
+}
+
+static stb_ps_bucket *stb_bucket_create2(void *v0, void *v1)
+{
+ stb_ps_bucket *b = (stb_ps_bucket*) malloc(sizeof(*b));
+ b->p[0] = v0;
+ b->p[1] = v1;
+ b->p[2] = NULL;
+ b->p[3] = NULL;
+ return b;
+}
+
+static stb_ps_bucket * stb_bucket_create3(void **v)
+{
+ stb_ps_bucket *b = (stb_ps_bucket*) malloc(sizeof(*b));
+ b->p[0] = v[0];
+ b->p[1] = v[1];
+ b->p[2] = v[2];
+ b->p[3] = NULL;
+ return b;
+}
+
+
+// could use stb_arr, but this will save us memory
+typedef struct
+{
+ int count;
+ void *p[1];
+} stb_ps_array;
+#define GetArray(p) ((stb_ps_array *) ((char *) (p) - STB_ps_array))
+#define EncodeArray(p) ((stb_ps *) ((char *) (p) + STB_ps_array))
+
+static int stb_ps_array_max = 13;
+
+typedef struct
+{
+ int size, mask;
+ int count, count_deletes;
+ int grow_threshhold;
+ int shrink_threshhold;
+ int rehash_threshhold;
+ int any_offset;
+ void *table[1];
+} stb_ps_hash;
+#define GetHash(p) ((stb_ps_hash *) ((char *) (p) - STB_ps_hash))
+#define EncodeHash(p) ((stb_ps *) ((char *) (p) + STB_ps_hash))
+
+#define stb_ps_empty(v) (((stb_uint32) v) <= 1)
+
+static stb_ps_hash *stb_ps_makehash(int size, int old_size, void **old_data)
+{
+ int i;
+ stb_ps_hash *h = (stb_ps_hash *) malloc(sizeof(*h) + (size-1) * sizeof(h->table[0]));
+ assert(stb_is_pow2(size));
+ h->size = size;
+ h->mask = size-1;
+ h->shrink_threshhold = (int) (0.3f * size);
+ h-> grow_threshhold = (int) (0.8f * size);
+ h->rehash_threshhold = (int) (0.9f * size);
+ h->count = 0;
+ h->count_deletes = 0;
+ h->any_offset = 0;
+ memset(h->table, 0, size * sizeof(h->table[0]));
+ for (i=0; i < old_size; ++i)
+ if (!stb_ps_empty((size_t)old_data[i]))
+ stb_ps_add(EncodeHash(h), old_data[i]);
+ return h;
+}
+
+void stb_ps_delete(stb_ps *ps)
+{
+ switch (3 & (int)(size_t) ps) {
+ case STB_ps_direct: break;
+ case STB_ps_bucket: stb_bucket_free(GetBucket(ps)); break;
+ case STB_ps_array : free(GetArray(ps)); break;
+ case STB_ps_hash : free(GetHash(ps)); break;
+ }
+}
+
+stb_ps *stb_ps_copy(stb_ps *ps)
+{
+ int i;
+ // not a switch: order based on expected performance/power-law distribution
+ switch (3 & (int)(size_t) ps) {
+ case STB_ps_direct: return ps;
+ case STB_ps_bucket: {
+ stb_ps_bucket *n = (stb_ps_bucket *) malloc(sizeof(*n));
+ *n = *GetBucket(ps);
+ return EncodeBucket(n);
+ }
+ case STB_ps_array: {
+ stb_ps_array *a = GetArray(ps);
+ stb_ps_array *n = (stb_ps_array *) malloc(sizeof(*n) + stb_ps_array_max * sizeof(n->p[0]));
+ n->count = a->count;
+ for (i=0; i < a->count; ++i)
+ n->p[i] = a->p[i];
+ return EncodeArray(n);
+ }
+ case STB_ps_hash: {
+ stb_ps_hash *h = GetHash(ps);
+ stb_ps_hash *n = stb_ps_makehash(h->size, h->size, h->table);
+ return EncodeHash(n);
+ }
+ }
+ assert(0); /* NOTREACHED */
+ return NULL;
+}
+
+int stb_ps_find(stb_ps *ps, void *value)
+{
+ int i, code = 3 & (int)(size_t) ps;
+ assert((3 & (int)(size_t) value) == STB_ps_direct);
+ assert(stb_ps_fastlist_valid(value));
+ // not a switch: order based on expected performance/power-law distribution
+ if (code == STB_ps_direct)
+ return value == ps;
+ if (code == STB_ps_bucket) {
+ stb_ps_bucket *b = GetBucket(ps);
+ assert(STB_BUCKET_SIZE == 4);
+ if (b->p[0] == value || b->p[1] == value ||
+ b->p[2] == value || b->p[3] == value)
+ return STB_TRUE;
+ return STB_FALSE;
+ }
+ if (code == STB_ps_array) {
+ stb_ps_array *a = GetArray(ps);
+ for (i=0; i < a->count; ++i)
+ if (a->p[i] == value)
+ return STB_TRUE;
+ return STB_FALSE;
+ } else {
+ stb_ps_hash *h = GetHash(ps);
+ stb_uint32 hash = stb_hashptr(value);
+ stb_uint32 s, n = hash & h->mask;
+ void **t = h->table;
+ if (t[n] == value) return STB_TRUE;
+ if (t[n] == NULL) return STB_FALSE;
+ s = stb_rehash(hash) | 1;
+ do {
+ n = (n + s) & h->mask;
+ if (t[n] == value) return STB_TRUE;
+ } while (t[n] != NULL);
+ return STB_FALSE;
+ }
+}
+
+stb_ps * stb_ps_add (stb_ps *ps, void *value)
+{
+ #ifdef STB_DEBUG
+ assert(!stb_ps_find(ps,value));
+ #endif
+ if (value == NULL) return ps; // ignore NULL adds to avoid bad breakage
+ assert((3 & (int)(size_t) value) == STB_ps_direct);
+ assert(stb_ps_fastlist_valid(value));
+ assert(value != STB_DEL); // STB_DEL is less likely
+
+ switch (3 & (int)(size_t) ps) {
+ case STB_ps_direct:
+ if (ps == NULL) return (stb_ps *) value;
+ return EncodeBucket(stb_bucket_create2(ps,value));
+
+ case STB_ps_bucket: {
+ stb_ps_bucket *b = GetBucket(ps);
+ stb_ps_array *a;
+ assert(STB_BUCKET_SIZE == 4);
+ if (b->p[0] == NULL) { b->p[0] = value; return ps; }
+ if (b->p[1] == NULL) { b->p[1] = value; return ps; }
+ if (b->p[2] == NULL) { b->p[2] = value; return ps; }
+ if (b->p[3] == NULL) { b->p[3] = value; return ps; }
+ a = (stb_ps_array *) malloc(sizeof(*a) + 7 * sizeof(a->p[0])); // 8 slots, must be 2^k
+ memcpy(a->p, b, sizeof(*b));
+ a->p[4] = value;
+ a->count = 5;
+ stb_bucket_free(b);
+ return EncodeArray(a);
+ }
+
+ case STB_ps_array: {
+ stb_ps_array *a = GetArray(ps);
+ if (a->count == stb_ps_array_max) {
+ // promote from array to hash
+ stb_ps_hash *h = stb_ps_makehash(2 << stb_log2_ceil(a->count), a->count, a->p);
+ free(a);
+ return stb_ps_add(EncodeHash(h), value);
+ }
+ // do we need to resize the array? the array doubles in size when it
+ // crosses a power-of-two
+ if ((a->count & (a->count-1))==0) {
+ int newsize = a->count*2;
+ // clamp newsize to max if:
+ // 1. it's larger than max
+ // 2. newsize*1.5 is larger than max (to avoid extra resizing)
+ if (newsize + a->count > stb_ps_array_max)
+ newsize = stb_ps_array_max;
+ a = (stb_ps_array *) realloc(a, sizeof(*a) + (newsize-1) * sizeof(a->p[0]));
+ }
+ a->p[a->count++] = value;
+ return EncodeArray(a);
+ }
+ case STB_ps_hash: {
+ stb_ps_hash *h = GetHash(ps);
+ stb_uint32 hash = stb_hashptr(value);
+ stb_uint32 n = hash & h->mask;
+ void **t = h->table;
+ // find first NULL or STB_DEL entry
+ if (!stb_ps_empty((size_t)t[n])) {
+ stb_uint32 s = stb_rehash(hash) | 1;
+ do {
+ n = (n + s) & h->mask;
+ } while (!stb_ps_empty((size_t)t[n]));
+ }
+ if (t[n] == STB_DEL)
+ -- h->count_deletes;
+ t[n] = value;
+ ++ h->count;
+ if (h->count == h->grow_threshhold) {
+ stb_ps_hash *h2 = stb_ps_makehash(h->size*2, h->size, t);
+ free(h);
+ return EncodeHash(h2);
+ }
+ if (h->count + h->count_deletes == h->rehash_threshhold) {
+ stb_ps_hash *h2 = stb_ps_makehash(h->size, h->size, t);
+ free(h);
+ return EncodeHash(h2);
+ }
+ return ps;
+ }
+ }
+ return NULL; /* NOTREACHED */
+}
+
+stb_ps *stb_ps_remove(stb_ps *ps, void *value)
+{
+ #ifdef STB_DEBUG
+ assert(stb_ps_find(ps, value));
+ #endif
+ assert((3 & (int)(size_t) value) == STB_ps_direct);
+ if (value == NULL) return ps; // ignore NULL removes to avoid bad breakage
+ switch (3 & (int)(size_t) ps) {
+ case STB_ps_direct:
+ return ps == value ? NULL : ps;
+ case STB_ps_bucket: {
+ stb_ps_bucket *b = GetBucket(ps);
+ int count=0;
+ assert(STB_BUCKET_SIZE == 4);
+ if (b->p[0] == value) b->p[0] = NULL; else count += (b->p[0] != NULL);
+ if (b->p[1] == value) b->p[1] = NULL; else count += (b->p[1] != NULL);
+ if (b->p[2] == value) b->p[2] = NULL; else count += (b->p[2] != NULL);
+ if (b->p[3] == value) b->p[3] = NULL; else count += (b->p[3] != NULL);
+ if (count == 1) { // shrink bucket at size 1
+ value = b->p[0];
+ if (value == NULL) value = b->p[1];
+ if (value == NULL) value = b->p[2];
+ if (value == NULL) value = b->p[3];
+ assert(value != NULL);
+ stb_bucket_free(b);
+ return (stb_ps *) value; // return STB_ps_direct of value
+ }
+ return ps;
+ }
+ case STB_ps_array: {
+ stb_ps_array *a = GetArray(ps);
+ int i;
+ for (i=0; i < a->count; ++i) {
+ if (a->p[i] == value) {
+ a->p[i] = a->p[--a->count];
+ if (a->count == 3) { // shrink to bucket!
+ stb_ps_bucket *b = stb_bucket_create3(a->p);
+ free(a);
+ return EncodeBucket(b);
+ }
+ return ps;
+ }
+ }
+ return ps;
+ }
+ case STB_ps_hash: {
+ stb_ps_hash *h = GetHash(ps);
+ stb_uint32 hash = stb_hashptr(value);
+ stb_uint32 s, n = hash & h->mask;
+ void **t = h->table;
+ if (t[n] != value) {
+ s = stb_rehash(hash) | 1;
+ do {
+ n = (n + s) & h->mask;
+ } while (t[n] != value);
+ }
+ t[n] = STB_DEL;
+ -- h->count;
+ ++ h->count_deletes;
+ // should we shrink down to an array?
+ if (h->count < stb_ps_array_max) {
+ int n = 1 << stb_log2_floor(stb_ps_array_max);
+ if (h->count < n) {
+ stb_ps_array *a = (stb_ps_array *) malloc(sizeof(*a) + (n-1) * sizeof(a->p[0]));
+ int i,j=0;
+ for (i=0; i < h->size; ++i)
+ if (!stb_ps_empty((size_t)t[i]))
+ a->p[j++] = t[i];
+ assert(j == h->count);
+ a->count = j;
+ free(h);
+ return EncodeArray(a);
+ }
+ }
+ if (h->count == h->shrink_threshhold) {
+ stb_ps_hash *h2 = stb_ps_makehash(h->size >> 1, h->size, t);
+ free(h);
+ return EncodeHash(h2);
+ }
+ return ps;
+ }
+ }
+ return ps; /* NOTREACHED */
+}
+
+stb_ps *stb_ps_remove_any(stb_ps *ps, void **value)
+{
+ assert(ps != NULL);
+ switch (3 & (int)(size_t) ps) {
+ case STB_ps_direct:
+ *value = ps;
+ return NULL;
+ case STB_ps_bucket: {
+ stb_ps_bucket *b = GetBucket(ps);
+ int count=0, slast=0, last=0;
+ assert(STB_BUCKET_SIZE == 4);
+ if (b->p[0]) { ++count; last = 0; }
+ if (b->p[1]) { ++count; slast = last; last = 1; }
+ if (b->p[2]) { ++count; slast = last; last = 2; }
+ if (b->p[3]) { ++count; slast = last; last = 3; }
+ *value = b->p[last];
+ b->p[last] = 0;
+ if (count == 2) {
+ void *leftover = b->p[slast]; // second to last
+ stb_bucket_free(b);
+ return (stb_ps *) leftover;
+ }
+ return ps;
+ }
+ case STB_ps_array: {
+ stb_ps_array *a = GetArray(ps);
+ *value = a->p[a->count-1];
+ if (a->count == 4)
+ return stb_ps_remove(ps, *value);
+ --a->count;
+ return ps;
+ }
+ case STB_ps_hash: {
+ stb_ps_hash *h = GetHash(ps);
+ void **t = h->table;
+ stb_uint32 n = h->any_offset;
+ while (stb_ps_empty((size_t)t[n]))
+ n = (n + 1) & h->mask;
+ *value = t[n];
+ h->any_offset = (n+1) & h->mask;
+ // check if we need to skip down to the previous type
+ if (h->count-1 < stb_ps_array_max || h->count-1 == h->shrink_threshhold)
+ return stb_ps_remove(ps, *value);
+ t[n] = STB_DEL;
+ -- h->count;
+ ++ h->count_deletes;
+ return ps;
+ }
+ }
+ return ps; /* NOTREACHED */
+}
+
+
+void ** stb_ps_getlist(stb_ps *ps, int *count)
+{
+ int i,n=0;
+ void **p = NULL;
+ switch (3 & (int)(size_t) ps) {
+ case STB_ps_direct:
+ if (ps == NULL) { *count = 0; return NULL; }
+ p = (void **) malloc(sizeof(*p) * 1);
+ p[0] = ps;
+ *count = 1;
+ return p;
+ case STB_ps_bucket: {
+ stb_ps_bucket *b = GetBucket(ps);
+ p = (void **) malloc(sizeof(*p) * STB_BUCKET_SIZE);
+ for (i=0; i < STB_BUCKET_SIZE; ++i)
+ if (b->p[i] != NULL)
+ p[n++] = b->p[i];
+ break;
+ }
+ case STB_ps_array: {
+ stb_ps_array *a = GetArray(ps);
+ p = (void **) malloc(sizeof(*p) * a->count);
+ memcpy(p, a->p, sizeof(*p) * a->count);
+ *count = a->count;
+ return p;
+ }
+ case STB_ps_hash: {
+ stb_ps_hash *h = GetHash(ps);
+ p = (void **) malloc(sizeof(*p) * h->count);
+ for (i=0; i < h->size; ++i)
+ if (!stb_ps_empty((size_t)h->table[i]))
+ p[n++] = h->table[i];
+ break;
+ }
+ }
+ *count = n;
+ return p;
+}
+
+int stb_ps_writelist(stb_ps *ps, void **list, int size )
+{
+ int i,n=0;
+ switch (3 & (int)(size_t) ps) {
+ case STB_ps_direct:
+ if (ps == NULL || size <= 0) return 0;
+ list[0] = ps;
+ return 1;
+ case STB_ps_bucket: {
+ stb_ps_bucket *b = GetBucket(ps);
+ for (i=0; i < STB_BUCKET_SIZE; ++i)
+ if (b->p[i] != NULL && n < size)
+ list[n++] = b->p[i];
+ return n;
+ }
+ case STB_ps_array: {
+ stb_ps_array *a = GetArray(ps);
+ n = stb_min(size, a->count);
+ memcpy(list, a->p, sizeof(*list) * n);
+ return n;
+ }
+ case STB_ps_hash: {
+ stb_ps_hash *h = GetHash(ps);
+ if (size <= 0) return 0;
+ for (i=0; i < h->count; ++i) {
+ if (!stb_ps_empty((size_t)h->table[i])) {
+ list[n++] = h->table[i];
+ if (n == size) break;
+ }
+ }
+ return n;
+ }
+ }
+ return 0; /* NOTREACHED */
+}
+
+int stb_ps_enum(stb_ps *ps, void *data, int (*func)(void *value, void *data))
+{
+ int i;
+ switch (3 & (int)(size_t) ps) {
+ case STB_ps_direct:
+ if (ps == NULL) return STB_TRUE;
+ return func(ps, data);
+ case STB_ps_bucket: {
+ stb_ps_bucket *b = GetBucket(ps);
+ for (i=0; i < STB_BUCKET_SIZE; ++i)
+ if (b->p[i] != NULL)
+ if (!func(b->p[i], data))
+ return STB_FALSE;
+ return STB_TRUE;
+ }
+ case STB_ps_array: {
+ stb_ps_array *a = GetArray(ps);
+ for (i=0; i < a->count; ++i)
+ if (!func(a->p[i], data))
+ return STB_FALSE;
+ return STB_TRUE;
+ }
+ case STB_ps_hash: {
+ stb_ps_hash *h = GetHash(ps);
+ for (i=0; i < h->count; ++i)
+ if (!stb_ps_empty((size_t)h->table[i]))
+ if (!func(h->table[i], data))
+ return STB_FALSE;
+ return STB_TRUE;
+ }
+ }
+ return STB_TRUE; /* NOTREACHED */
+}
+
+int stb_ps_count (stb_ps *ps)
+{
+ switch (3 & (int)(size_t) ps) {
+ case STB_ps_direct:
+ return ps != NULL;
+ case STB_ps_bucket: {
+ stb_ps_bucket *b = GetBucket(ps);
+ return (b->p[0] != NULL) + (b->p[1] != NULL) +
+ (b->p[2] != NULL) + (b->p[3] != NULL);
+ }
+ case STB_ps_array: {
+ stb_ps_array *a = GetArray(ps);
+ return a->count;
+ }
+ case STB_ps_hash: {
+ stb_ps_hash *h = GetHash(ps);
+ return h->count;
+ }
+ }
+ return 0;
+}
+
+void ** stb_ps_fastlist(stb_ps *ps, int *count)
+{
+ static void *storage;
+
+ switch (3 & (int)(size_t) ps) {
+ case STB_ps_direct:
+ if (ps == NULL) { *count = 0; return NULL; }
+ storage = ps;
+ *count = 1;
+ return &storage;
+ case STB_ps_bucket: {
+ stb_ps_bucket *b = GetBucket(ps);
+ *count = STB_BUCKET_SIZE;
+ return b->p;
+ }
+ case STB_ps_array: {
+ stb_ps_array *a = GetArray(ps);
+ *count = a->count;
+ return a->p;
+ }
+ case STB_ps_hash: {
+ stb_ps_hash *h = GetHash(ps);
+ *count = h->size;
+ return h->table;
+ }
+ }
+ return NULL; /* NOTREACHED */
+}
+
+int stb_ps_subset(stb_ps *bigger, stb_ps *smaller)
+{
+ int i, listlen;
+ void **list = stb_ps_fastlist(smaller, &listlen);
+ for(i=0; i < listlen; ++i)
+ if (stb_ps_fastlist_valid(list[i]))
+ if (!stb_ps_find(bigger, list[i]))
+ return 0;
+ return 1;
+}
+
+int stb_ps_eq(stb_ps *p0, stb_ps *p1)
+{
+ if (stb_ps_count(p0) != stb_ps_count(p1))
+ return 0;
+ return stb_ps_subset(p0, p1);
+}
+
+#undef GetBucket
+#undef GetArray
+#undef GetHash
+
+#undef EncodeBucket
+#undef EncodeArray
+#undef EncodeHash
+
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Random Numbers via Meresenne Twister or LCG
+//
+
+STB_EXTERN unsigned int stb_srandLCG(unsigned int seed);
+STB_EXTERN unsigned int stb_randLCG(void);
+STB_EXTERN double stb_frandLCG(void);
+
+STB_EXTERN void stb_srand(unsigned int seed);
+STB_EXTERN unsigned int stb_rand(void);
+STB_EXTERN double stb_frand(void);
+STB_EXTERN void stb_shuffle(void *p, size_t n, size_t sz,
+ unsigned int seed);
+STB_EXTERN void stb_reverse(void *p, size_t n, size_t sz);
+
+STB_EXTERN unsigned int stb_randLCG_explicit(unsigned int seed);
+
+#define stb_rand_define(x,y) \
+ \
+ unsigned int x(void) \
+ { \
+ static unsigned int stb__rand = y; \
+ stb__rand = stb__rand * 2147001325 + 715136305; /* BCPL */ \
+ return 0x31415926 ^ ((stb__rand >> 16) + (stb__rand << 16)); \
+ }
+
+#ifdef STB_DEFINE
+unsigned int stb_randLCG_explicit(unsigned int seed)
+{
+ return seed * 2147001325 + 715136305;
+}
+
+static unsigned int stb__rand_seed=0;
+
+unsigned int stb_srandLCG(unsigned int seed)
+{
+ unsigned int previous = stb__rand_seed;
+ stb__rand_seed = seed;
+ return previous;
+}
+
+unsigned int stb_randLCG(void)
+{
+ stb__rand_seed = stb__rand_seed * 2147001325 + 715136305; // BCPL generator
+ // shuffle non-random bits to the middle, and xor to decorrelate with seed
+ return 0x31415926 ^ ((stb__rand_seed >> 16) + (stb__rand_seed << 16));
+}
+
+double stb_frandLCG(void)
+{
+ return stb_randLCG() / ((double) (1 << 16) * (1 << 16));
+}
+
+void stb_shuffle(void *p, size_t n, size_t sz, unsigned int seed)
+{
+ char *a;
+ unsigned int old_seed;
+ int i;
+ if (seed)
+ old_seed = stb_srandLCG(seed);
+ a = (char *) p + (n-1) * sz;
+
+ for (i=(int) n; i > 1; --i) {
+ int j = stb_randLCG() % i;
+ stb_swap(a, (char *) p + j * sz, sz);
+ a -= sz;
+ }
+ if (seed)
+ stb_srandLCG(old_seed);
+}
+
+void stb_reverse(void *p, size_t n, size_t sz)
+{
+ size_t i,j = n-1;
+ for (i=0; i < j; ++i,--j) {
+ stb_swap((char *) p + i * sz, (char *) p + j * sz, sz);
+ }
+}
+
+// public domain Mersenne Twister by Michael Brundage
+#define STB__MT_LEN 624
+
+int stb__mt_index = STB__MT_LEN*sizeof(int)+1;
+unsigned int stb__mt_buffer[STB__MT_LEN];
+
+void stb_srand(unsigned int seed)
+{
+ int i;
+ stb__mt_buffer[0]= seed & 0xffffffffUL;
+ for (i=1 ; i < STB__MT_LEN; ++i)
+ stb__mt_buffer[i] = (1812433253UL * (stb__mt_buffer[i-1] ^ (stb__mt_buffer[i-1] >> 30)) + i);
+ stb__mt_index = STB__MT_LEN*sizeof(unsigned int);
+}
+
+#define STB__MT_IA 397
+#define STB__MT_IB (STB__MT_LEN - STB__MT_IA)
+#define STB__UPPER_MASK 0x80000000
+#define STB__LOWER_MASK 0x7FFFFFFF
+#define STB__MATRIX_A 0x9908B0DF
+#define STB__TWIST(b,i,j) ((b)[i] & STB__UPPER_MASK) | ((b)[j] & STB__LOWER_MASK)
+#define STB__MAGIC(s) (((s)&1)*STB__MATRIX_A)
+
+unsigned int stb_rand()
+{
+ unsigned int * b = stb__mt_buffer;
+ int idx = stb__mt_index;
+ unsigned int s,r;
+ int i;
+
+ if (idx >= STB__MT_LEN*sizeof(unsigned int)) {
+ if (idx > STB__MT_LEN*sizeof(unsigned int))
+ stb_srand(0);
+ idx = 0;
+ i = 0;
+ for (; i < STB__MT_IB; i++) {
+ s = STB__TWIST(b, i, i+1);
+ b[i] = b[i + STB__MT_IA] ^ (s >> 1) ^ STB__MAGIC(s);
+ }
+ for (; i < STB__MT_LEN-1; i++) {
+ s = STB__TWIST(b, i, i+1);
+ b[i] = b[i - STB__MT_IB] ^ (s >> 1) ^ STB__MAGIC(s);
+ }
+
+ s = STB__TWIST(b, STB__MT_LEN-1, 0);
+ b[STB__MT_LEN-1] = b[STB__MT_IA-1] ^ (s >> 1) ^ STB__MAGIC(s);
+ }
+ stb__mt_index = idx + sizeof(unsigned int);
+
+ r = *(unsigned int *)((unsigned char *)b + idx);
+
+ r ^= (r >> 11);
+ r ^= (r << 7) & 0x9D2C5680;
+ r ^= (r << 15) & 0xEFC60000;
+ r ^= (r >> 18);
+
+ return r;
+}
+
+double stb_frand(void)
+{
+ return stb_rand() / ((double) (1 << 16) * (1 << 16));
+}
+
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// stb_dupe
+//
+// stb_dupe is a duplicate-finding system for very, very large data
+// structures--large enough that sorting is too slow, but not so large
+// that we can't keep all the data in memory. using it works as follows:
+//
+// 1. create an stb_dupe:
+// provide a hash function
+// provide an equality function
+// provide an estimate for the size
+// optionally provide a comparison function
+//
+// 2. traverse your data, 'adding' pointers to the stb_dupe
+//
+// 3. finish and ask for duplicates
+//
+// the stb_dupe will discard its intermediate data and build
+// a collection of sorted lists of duplicates, with non-duplicate
+// entries omitted entirely
+//
+//
+// Implementation strategy:
+//
+// while collecting the N items, we keep a hash table of approximate
+// size sqrt(N). (if you tell use the N up front, the hash table is
+// just that size exactly)
+//
+// each entry in the hash table is just an stb__arr of pointers (no need
+// to use stb_ps, because we don't need to delete from these)
+//
+// for step 3, for each entry in the hash table, we apply stb_dupe to it
+// recursively. once the size gets small enough (or doesn't decrease
+// significantly), we switch to either using qsort() on the comparison
+// function, or else we just do the icky N^2 gather
+
+
+typedef struct stb_dupe stb_dupe;
+
+typedef int (*stb_compare_func)(void *a, void *b);
+typedef int (*stb_hash_func)(void *a, unsigned int seed);
+
+STB_EXTERN void stb_dupe_free(stb_dupe *sd);
+STB_EXTERN stb_dupe *stb_dupe_create(stb_hash_func hash,
+ stb_compare_func eq, int size, stb_compare_func ineq);
+STB_EXTERN void stb_dupe_add(stb_dupe *sd, void *item);
+STB_EXTERN void stb_dupe_finish(stb_dupe *sd);
+STB_EXTERN int stb_dupe_numsets(stb_dupe *sd);
+STB_EXTERN void **stb_dupe_set(stb_dupe *sd, int num);
+STB_EXTERN int stb_dupe_set_count(stb_dupe *sd, int num);
+
+struct stb_dupe
+{
+ void ***hash_table;
+ int hash_size;
+ int size_log2;
+ int population;
+
+ int hash_shift;
+ stb_hash_func hash;
+
+ stb_compare_func eq;
+ stb_compare_func ineq;
+
+ void ***dupes;
+};
+
+#ifdef STB_DEFINE
+
+int stb_dupe_numsets(stb_dupe *sd)
+{
+ assert(sd->hash_table == NULL);
+ return stb_arr_len(sd->dupes);
+}
+
+void **stb_dupe_set(stb_dupe *sd, int num)
+{
+ assert(sd->hash_table == NULL);
+ return sd->dupes[num];
+}
+
+int stb_dupe_set_count(stb_dupe *sd, int num)
+{
+ assert(sd->hash_table == NULL);
+ return stb_arr_len(sd->dupes[num]);
+}
+
+stb_dupe *stb_dupe_create(stb_hash_func hash, stb_compare_func eq, int size,
+ stb_compare_func ineq)
+{
+ int i, hsize;
+ stb_dupe *sd = (stb_dupe *) malloc(sizeof(*sd));
+
+ sd->size_log2 = 4;
+ hsize = 1 << sd->size_log2;
+ while (hsize * hsize < size) {
+ ++sd->size_log2;
+ hsize *= 2;
+ }
+
+ sd->hash = hash;
+ sd->eq = eq;
+ sd->ineq = ineq;
+ sd->hash_shift = 0;
+
+ sd->population = 0;
+ sd->hash_size = hsize;
+ sd->hash_table = (void ***) malloc(sizeof(*sd->hash_table) * hsize);
+ for (i=0; i < hsize; ++i)
+ sd->hash_table[i] = NULL;
+
+ sd->dupes = NULL;
+
+ return sd;
+}
+
+void stb_dupe_add(stb_dupe *sd, void *item)
+{
+ stb_uint32 hash = sd->hash(item, sd->hash_shift);
+ int z = hash & (sd->hash_size-1);
+ stb_arr_push(sd->hash_table[z], item);
+ ++sd->population;
+}
+
+void stb_dupe_free(stb_dupe *sd)
+{
+ int i;
+ for (i=0; i < stb_arr_len(sd->dupes); ++i)
+ if (sd->dupes[i])
+ stb_arr_free(sd->dupes[i]);
+ stb_arr_free(sd->dupes);
+ free(sd);
+}
+
+static stb_compare_func stb__compare;
+
+static int stb__dupe_compare(const void *a, const void *b)
+{
+ void *p = *(void **) a;
+ void *q = *(void **) b;
+
+ return stb__compare(p,q);
+}
+
+void stb_dupe_finish(stb_dupe *sd)
+{
+ int i,j,k;
+ assert(sd->dupes == NULL);
+ for (i=0; i < sd->hash_size; ++i) {
+ void ** list = sd->hash_table[i];
+ if (list != NULL) {
+ int n = stb_arr_len(list);
+ // @TODO: measure to find good numbers instead of just making them up!
+ int thresh = (sd->ineq ? 200 : 20);
+ // if n is large enough to be worth it, and n is smaller than
+ // before (so we can guarantee we'll use a smaller hash table);
+ // and there are enough hash bits left, assuming full 32-bit hash
+ if (n > thresh && n < (sd->population >> 3) && sd->hash_shift + sd->size_log2*2 < 32) {
+
+ // recursively process this row using stb_dupe, O(N log log N)
+
+ stb_dupe *d = stb_dupe_create(sd->hash, sd->eq, n, sd->ineq);
+ d->hash_shift = stb_randLCG_explicit(sd->hash_shift);
+ for (j=0; j < n; ++j)
+ stb_dupe_add(d, list[j]);
+ stb_arr_free(sd->hash_table[i]);
+ stb_dupe_finish(d);
+ for (j=0; j < stb_arr_len(d->dupes); ++j) {
+ stb_arr_push(sd->dupes, d->dupes[j]);
+ d->dupes[j] = NULL; // take over ownership
+ }
+ stb_dupe_free(d);
+
+ } else if (sd->ineq) {
+
+ // process this row using qsort(), O(N log N)
+ stb__compare = sd->ineq;
+ qsort(list, n, sizeof(list[0]), stb__dupe_compare);
+
+ // find equal subsequences of the list
+ for (j=0; j < n-1; ) {
+ // find a subsequence from j..k
+ for (k=j; k < n; ++k)
+ // only use ineq so eq can be left undefined
+ if (sd->ineq(list[j], list[k]))
+ break;
+ // k is the first one not in the subsequence
+ if (k-j > 1) {
+ void **mylist = NULL;
+ stb_arr_setlen(mylist, k-j);
+ memcpy(mylist, list+j, sizeof(list[j]) * (k-j));
+ stb_arr_push(sd->dupes, mylist);
+ }
+ j = k;
+ }
+ stb_arr_free(sd->hash_table[i]);
+ } else {
+
+ // process this row using eq(), O(N^2)
+ for (j=0; j < n; ++j) {
+ if (list[j] != NULL) {
+ void **output = NULL;
+ for (k=j+1; k < n; ++k) {
+ if (sd->eq(list[j], list[k])) {
+ if (output == NULL)
+ stb_arr_push(output, list[j]);
+ stb_arr_push(output, list[k]);
+ list[k] = NULL;
+ }
+ }
+ list[j] = NULL;
+ if (output)
+ stb_arr_push(sd->dupes, output);
+ }
+ }
+ stb_arr_free(sd->hash_table[i]);
+ }
+ }
+ }
+ free(sd->hash_table);
+ sd->hash_table = NULL;
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// templatized Sort routine
+//
+// This is an attempt to implement a templated sorting algorithm.
+// To use it, you have to explicitly instantiate it as a _function_,
+// then you call that function. This allows the comparison to be inlined,
+// giving the sort similar performance to C++ sorts.
+//
+// It implements quicksort with three-way-median partitioning (generally
+// well-behaved), with a final insertion sort pass.
+//
+// When you define the compare expression, you should assume you have
+// elements of your array pointed to by 'a' and 'b', and perform the comparison
+// on those. OR you can use one or more statements; first say '0;', then
+// write whatever code you want, and compute the result into a variable 'c'.
+
+#define stb_declare_sort(FUNCNAME, TYPE) \
+ void FUNCNAME(TYPE *p, int n)
+#define stb_define_sort(FUNCNAME,TYPE,COMPARE) \
+ stb__define_sort( void, FUNCNAME,TYPE,COMPARE)
+#define stb_define_sort_static(FUNCNAME,TYPE,COMPARE) \
+ stb__define_sort(static void, FUNCNAME,TYPE,COMPARE)
+
+#define stb__define_sort(MODE, FUNCNAME, TYPE, COMPARE) \
+ \
+static void STB_(FUNCNAME,_ins_sort)(TYPE *p, int n) \
+{ \
+ int i,j; \
+ for (i=1; i < n; ++i) { \
+ TYPE t = p[i], *a = &t; \
+ j = i; \
+ while (j > 0) { \
+ TYPE *b = &p[j-1]; \
+ int c = COMPARE; \
+ if (!c) break; \
+ p[j] = p[j-1]; \
+ --j; \
+ } \
+ if (i != j) \
+ p[j] = t; \
+ } \
+} \
+ \
+static void STB_(FUNCNAME,_quicksort)(TYPE *p, int n) \
+{ \
+ /* threshold for transitioning to insertion sort */ \
+ while (n > 12) { \
+ TYPE *a,*b,t; \
+ int c01,c12,c,m,i,j; \
+ \
+ /* compute median of three */ \
+ m = n >> 1; \
+ a = &p[0]; \
+ b = &p[m]; \
+ c = COMPARE; \
+ c01 = c; \
+ a = &p[m]; \
+ b = &p[n-1]; \
+ c = COMPARE; \
+ c12 = c; \
+ /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ \
+ if (c01 != c12) { \
+ /* otherwise, we'll need to swap something else to middle */ \
+ int z; \
+ a = &p[0]; \
+ b = &p[n-1]; \
+ c = COMPARE; \
+ /* 0>mid && midn => n; 0 0 */ \
+ /* 0n: 0>n => 0; 0 n */ \
+ z = (c == c12) ? 0 : n-1; \
+ t = p[z]; \
+ p[z] = p[m]; \
+ p[m] = t; \
+ } \
+ /* now p[m] is the median-of-three */ \
+ /* swap it to the beginning so it won't move around */ \
+ t = p[0]; \
+ p[0] = p[m]; \
+ p[m] = t; \
+ \
+ /* partition loop */ \
+ i=1; \
+ j=n-1; \
+ for(;;) { \
+ /* handling of equality is crucial here */ \
+ /* for sentinels & efficiency with duplicates */ \
+ b = &p[0]; \
+ for (;;++i) { \
+ a=&p[i]; \
+ c = COMPARE; \
+ if (!c) break; \
+ } \
+ a = &p[0]; \
+ for (;;--j) { \
+ b=&p[j]; \
+ c = COMPARE; \
+ if (!c) break; \
+ } \
+ /* make sure we haven't crossed */ \
+ if (i >= j) break; \
+ t = p[i]; \
+ p[i] = p[j]; \
+ p[j] = t; \
+ \
+ ++i; \
+ --j; \
+ } \
+ /* recurse on smaller side, iterate on larger */ \
+ if (j < (n-i)) { \
+ STB_(FUNCNAME,_quicksort)(p,j); \
+ p = p+i; \
+ n = n-i; \
+ } else { \
+ STB_(FUNCNAME,_quicksort)(p+i, n-i); \
+ n = j; \
+ } \
+ } \
+} \
+ \
+MODE FUNCNAME(TYPE *p, int n) \
+{ \
+ STB_(FUNCNAME, _quicksort)(p, n); \
+ STB_(FUNCNAME, _ins_sort)(p, n); \
+} \
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// stb_bitset an array of booleans indexed by integers
+//
+
+typedef stb_uint32 stb_bitset;
+
+STB_EXTERN stb_bitset *stb_bitset_new(int value, int len);
+
+#define stb_bitset_clearall(arr,len) (memset(arr, 0, 4 * (len)))
+#define stb_bitset_setall(arr,len) (memset(arr, 255, 4 * (len)))
+
+#define stb_bitset_setbit(arr,n) ((arr)[(n) >> 5] |= (1 << (n & 31)))
+#define stb_bitset_clearbit(arr,n) ((arr)[(n) >> 5] &= ~(1 << (n & 31)))
+#define stb_bitset_testbit(arr,n) ((arr)[(n) >> 5] & (1 << (n & 31)))
+
+STB_EXTERN stb_bitset *stb_bitset_union(stb_bitset *p0, stb_bitset *p1, int len);
+
+STB_EXTERN int *stb_bitset_getlist(stb_bitset *out, int start, int end);
+
+STB_EXTERN int stb_bitset_eq(stb_bitset *p0, stb_bitset *p1, int len);
+STB_EXTERN int stb_bitset_disjoint(stb_bitset *p0, stb_bitset *p1, int len);
+STB_EXTERN int stb_bitset_disjoint_0(stb_bitset *p0, stb_bitset *p1, int len);
+STB_EXTERN int stb_bitset_subset(stb_bitset *bigger, stb_bitset *smaller, int len);
+STB_EXTERN int stb_bitset_unioneq_changed(stb_bitset *p0, stb_bitset *p1, int len);
+
+#ifdef STB_DEFINE
+int stb_bitset_eq(stb_bitset *p0, stb_bitset *p1, int len)
+{
+ int i;
+ for (i=0; i < len; ++i)
+ if (p0[i] != p1[i]) return 0;
+ return 1;
+}
+
+int stb_bitset_disjoint(stb_bitset *p0, stb_bitset *p1, int len)
+{
+ int i;
+ for (i=0; i < len; ++i)
+ if (p0[i] & p1[i]) return 0;
+ return 1;
+}
+
+int stb_bitset_disjoint_0(stb_bitset *p0, stb_bitset *p1, int len)
+{
+ int i;
+ for (i=0; i < len; ++i)
+ if ((p0[i] | p1[i]) != 0xffffffff) return 0;
+ return 1;
+}
+
+int stb_bitset_subset(stb_bitset *bigger, stb_bitset *smaller, int len)
+{
+ int i;
+ for (i=0; i < len; ++i)
+ if ((bigger[i] & smaller[i]) != smaller[i]) return 0;
+ return 1;
+}
+
+stb_bitset *stb_bitset_union(stb_bitset *p0, stb_bitset *p1, int len)
+{
+ int i;
+ stb_bitset *d = (stb_bitset *) malloc(sizeof(*d) * len);
+ for (i=0; i < len; ++i) d[i] = p0[i] | p1[i];
+ return d;
+}
+
+int stb_bitset_unioneq_changed(stb_bitset *p0, stb_bitset *p1, int len)
+{
+ int i, changed=0;
+ for (i=0; i < len; ++i) {
+ stb_bitset d = p0[i] | p1[i];
+ if (d != p0[i]) {
+ p0[i] = d;
+ changed = 1;
+ }
+ }
+ return changed;
+}
+
+stb_bitset *stb_bitset_new(int value, int len)
+{
+ int i;
+ stb_bitset *d = (stb_bitset *) malloc(sizeof(*d) * len);
+ if (value) value = 0xffffffff;
+ for (i=0; i < len; ++i) d[i] = value;
+ return d;
+}
+
+int *stb_bitset_getlist(stb_bitset *out, int start, int end)
+{
+ int *list = NULL;
+ int i;
+ for (i=start; i < end; ++i)
+ if (stb_bitset_testbit(out, i))
+ stb_arr_push(list, i);
+ return list;
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// stb_wordwrap quality word-wrapping for fixed-width fonts
+//
+
+STB_EXTERN int stb_wordwrap(int *pairs, int pair_max, int count, char *str);
+STB_EXTERN int *stb_wordwrapalloc(int count, char *str);
+
+#ifdef STB_DEFINE
+
+int stb_wordwrap(int *pairs, int pair_max, int count, char *str)
+{
+ int n=0,i=0, start=0,nonwhite=0;
+ if (pairs == NULL) pair_max = 0x7ffffff0;
+ else pair_max *= 2;
+ // parse
+ for(;;) {
+ int s=i; // first whitespace char; last nonwhite+1
+ int w; // word start
+ // accept whitespace
+ while (isspace(str[i])) {
+ if (str[i] == '\n' || str[i] == '\r') {
+ if (str[i] + str[i+1] == '\n' + '\r') ++i;
+ if (n >= pair_max) return -1;
+ if (pairs) pairs[n] = start, pairs[n+1] = s-start;
+ n += 2;
+ nonwhite=0;
+ start = i+1;
+ s = start;
+ }
+ ++i;
+ }
+ if (i >= start+count) {
+ // we've gone off the end using whitespace
+ if (nonwhite) {
+ if (n >= pair_max) return -1;
+ if (pairs) pairs[n] = start, pairs[n+1] = s-start;
+ n += 2;
+ start = s = i;
+ nonwhite=0;
+ } else {
+ // output all the whitespace
+ while (i >= start+count) {
+ if (n >= pair_max) return -1;
+ if (pairs) pairs[n] = start, pairs[n+1] = count;
+ n += 2;
+ start += count;
+ }
+ s = start;
+ }
+ }
+
+ if (str[i] == 0) break;
+ // now scan out a word and see if it fits
+ w = i;
+ while (str[i] && !isspace(str[i])) {
+ ++i;
+ }
+ // wrapped?
+ if (i > start + count) {
+ // huge?
+ if (i-s <= count) {
+ if (n >= pair_max) return -1;
+ if (pairs) pairs[n] = start, pairs[n+1] = s-start;
+ n += 2;
+ start = w;
+ } else {
+ // This word is longer than one line. If we wrap it onto N lines
+ // there are leftover chars. do those chars fit on the cur line?
+ // But if we have leading whitespace, we force it to start here.
+ if ((w-start) + ((i-w) % count) <= count || !nonwhite) {
+ // output a full line
+ if (n >= pair_max) return -1;
+ if (pairs) pairs[n] = start, pairs[n+1] = count;
+ n += 2;
+ start += count;
+ w = start;
+ } else {
+ // output a partial line, trimming trailing whitespace
+ if (s != start) {
+ if (n >= pair_max) return -1;
+ if (pairs) pairs[n] = start, pairs[n+1] = s-start;
+ n += 2;
+ start = w;
+ }
+ }
+ // now output full lines as needed
+ while (start + count <= i) {
+ if (n >= pair_max) return -1;
+ if (pairs) pairs[n] = start, pairs[n+1] = count;
+ n += 2;
+ start += count;
+ }
+ }
+ }
+ nonwhite=1;
+ }
+ if (start < i) {
+ if (n >= pair_max) return -1;
+ if (pairs) pairs[n] = start, pairs[n+1] = i-start;
+ n += 2;
+ }
+ return n>>1;
+}
+
+int *stb_wordwrapalloc(int count, char *str)
+{
+ int n = stb_wordwrap(NULL,0,count,str);
+ int *z = NULL;
+ stb_arr_setlen(z, n*2);
+ stb_wordwrap(z, n, count, str);
+ return z;
+}
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// stb_match: wildcards and regexping
+//
+
+STB_EXTERN int stb_wildmatch (char *expr, char *candidate);
+STB_EXTERN int stb_wildmatchi(char *expr, char *candidate);
+STB_EXTERN int stb_wildfind (char *expr, char *candidate);
+STB_EXTERN int stb_wildfindi (char *expr, char *candidate);
+
+STB_EXTERN int stb_regex(char *regex, char *candidate);
+
+typedef struct stb_matcher stb_matcher;
+
+STB_EXTERN stb_matcher *stb_regex_matcher(char *regex);
+STB_EXTERN int stb_matcher_match(stb_matcher *m, char *str);
+STB_EXTERN int stb_matcher_find(stb_matcher *m, char *str);
+STB_EXTERN void stb_matcher_free(stb_matcher *f);
+
+STB_EXTERN stb_matcher *stb_lex_matcher(void);
+STB_EXTERN int stb_lex_item(stb_matcher *m, const char *str, int result);
+STB_EXTERN int stb_lex_item_wild(stb_matcher *matcher, const char *regex, int result);
+STB_EXTERN int stb_lex(stb_matcher *m, char *str, int *len);
+
+
+
+#ifdef STB_DEFINE
+
+static int stb__match_qstring(char *candidate, char *qstring, int qlen, int insensitive)
+{
+ int i;
+ if (insensitive) {
+ for (i=0; i < qlen; ++i)
+ if (qstring[i] == '?') {
+ if (!candidate[i]) return 0;
+ } else
+ if (tolower(qstring[i]) != tolower(candidate[i]))
+ return 0;
+ } else {
+ for (i=0; i < qlen; ++i)
+ if (qstring[i] == '?') {
+ if (!candidate[i]) return 0;
+ } else
+ if (qstring[i] != candidate[i])
+ return 0;
+ }
+ return 1;
+}
+
+static int stb__find_qstring(char *candidate, char *qstring, int qlen, int insensitive)
+{
+ char c;
+
+ int offset=0;
+ while (*qstring == '?') {
+ ++qstring;
+ --qlen;
+ ++candidate;
+ if (qlen == 0) return 0;
+ if (*candidate == 0) return -1;
+ }
+
+ c = *qstring++;
+ --qlen;
+ if (insensitive) c = tolower(c);
+
+ while (candidate[offset]) {
+ if (c == (insensitive ? tolower(candidate[offset]) : candidate[offset]))
+ if (stb__match_qstring(candidate+offset+1, qstring, qlen, insensitive))
+ return offset;
+ ++offset;
+ }
+
+ return -1;
+}
+
+int stb__wildmatch_raw2(char *expr, char *candidate, int search, int insensitive)
+{
+ int where=0;
+ int start = -1;
+
+ if (!search) {
+ // parse to first '*'
+ if (*expr != '*')
+ start = 0;
+ while (*expr != '*') {
+ if (!*expr)
+ return *candidate == 0 ? 0 : -1;
+ if (*expr == '?') {
+ if (!*candidate) return -1;
+ } else {
+ if (insensitive) {
+ if (tolower(*candidate) != tolower(*expr))
+ return -1;
+ } else
+ if (*candidate != *expr)
+ return -1;
+ }
+ ++candidate, ++expr, ++where;
+ }
+ } else {
+ // 0-length search string
+ if (!*expr)
+ return 0;
+ }
+
+ assert(search || *expr == '*');
+ if (!search)
+ ++expr;
+
+ // implicit '*' at this point
+
+ while (*expr) {
+ int o=0;
+ // combine redundant * characters
+ while (expr[0] == '*') ++expr;
+
+ // ok, at this point, expr[-1] == '*',
+ // and expr[0] != '*'
+
+ if (!expr[0]) return start >= 0 ? start : 0;
+
+ // now find next '*'
+ o = 0;
+ while (expr[o] != '*') {
+ if (expr[o] == 0)
+ break;
+ ++o;
+ }
+ // if no '*', scan to end, then match at end
+ if (expr[o] == 0 && !search) {
+ int z;
+ for (z=0; z < o; ++z)
+ if (candidate[z] == 0)
+ return -1;
+ while (candidate[z])
+ ++z;
+ // ok, now check if they match
+ if (stb__match_qstring(candidate+z-o, expr, o, insensitive))
+ return start >= 0 ? start : 0;
+ return -1;
+ } else {
+ // if yes '*', then do stb__find_qmatch on the intervening chars
+ int n = stb__find_qstring(candidate, expr, o, insensitive);
+ if (n < 0)
+ return -1;
+ if (start < 0)
+ start = where + n;
+ expr += o;
+ candidate += n+o;
+ }
+
+ if (*expr == 0) {
+ assert(search);
+ return start;
+ }
+
+ assert(*expr == '*');
+ ++expr;
+ }
+
+ return start >= 0 ? start : 0;
+}
+
+int stb__wildmatch_raw(char *expr, char *candidate, int search, int insensitive)
+{
+ char buffer[256];
+ // handle multiple search strings
+ char *s = strchr(expr, ';');
+ char *last = expr;
+ while (s) {
+ int z;
+ // need to allow for non-writeable strings... assume they're small
+ if (s - last < 256) {
+ stb_strncpy(buffer, last, (int) (s-last+1));
+ z = stb__wildmatch_raw2(buffer, candidate, search, insensitive);
+ } else {
+ *s = 0;
+ z = stb__wildmatch_raw2(last, candidate, search, insensitive);
+ *s = ';';
+ }
+ if (z >= 0) return z;
+ last = s+1;
+ s = strchr(last, ';');
+ }
+ return stb__wildmatch_raw2(last, candidate, search, insensitive);
+}
+
+int stb_wildmatch(char *expr, char *candidate)
+{
+ return stb__wildmatch_raw(expr, candidate, 0,0) >= 0;
+}
+
+int stb_wildmatchi(char *expr, char *candidate)
+{
+ return stb__wildmatch_raw(expr, candidate, 0,1) >= 0;
+}
+
+int stb_wildfind(char *expr, char *candidate)
+{
+ return stb__wildmatch_raw(expr, candidate, 1,0);
+}
+
+int stb_wildfindi(char *expr, char *candidate)
+{
+ return stb__wildmatch_raw(expr, candidate, 1,1);
+}
+
+typedef struct
+{
+ stb_int16 transition[256];
+} stb_dfa;
+
+// an NFA node represents a state you're in; it then has
+// an arbitrary number of edges dangling off of it
+// note this isn't utf8-y
+typedef struct
+{
+ stb_int16 match; // character/set to match
+ stb_uint16 node; // output node to go to
+} stb_nfa_edge;
+
+typedef struct
+{
+ stb_int16 goal; // does reaching this win the prize?
+ stb_uint8 active; // is this in the active list
+ stb_nfa_edge *out;
+ stb_uint16 *eps; // list of epsilon closures
+} stb_nfa_node;
+
+#define STB__DFA_UNDEF -1
+#define STB__DFA_GOAL -2
+#define STB__DFA_END -3
+#define STB__DFA_MGOAL -4
+#define STB__DFA_VALID 0
+
+#define STB__NFA_STOP_GOAL -1
+
+// compiled regexp
+struct stb_matcher
+{
+ stb_uint16 start_node;
+ stb_int16 dfa_start;
+ stb_uint32 *charset;
+ int num_charset;
+ int match_start;
+ stb_nfa_node *nodes;
+ int does_lex;
+
+ // dfa matcher
+ stb_dfa * dfa;
+ stb_uint32 * dfa_mapping;
+ stb_int16 * dfa_result;
+ int num_words_per_dfa;
+};
+
+static int stb__add_node(stb_matcher *matcher)
+{
+ stb_nfa_node z;
+ z.active = 0;
+ z.eps = 0;
+ z.goal = 0;
+ z.out = 0;
+ stb_arr_push(matcher->nodes, z);
+ return stb_arr_len(matcher->nodes)-1;
+}
+
+static void stb__add_epsilon(stb_matcher *matcher, int from, int to)
+{
+ assert(from != to);
+ if (matcher->nodes[from].eps == NULL)
+ stb_arr_malloc((void **) &matcher->nodes[from].eps, matcher);
+ stb_arr_push(matcher->nodes[from].eps, to);
+}
+
+static void stb__add_edge(stb_matcher *matcher, int from, int to, int type)
+{
+ stb_nfa_edge z = { (stb_int16)type, (stb_uint16)to };
+ if (matcher->nodes[from].out == NULL)
+ stb_arr_malloc((void **) &matcher->nodes[from].out, matcher);
+ stb_arr_push(matcher->nodes[from].out, z);
+}
+
+static char *stb__reg_parse_alt(stb_matcher *m, int s, char *r, stb_uint16 *e);
+static char *stb__reg_parse(stb_matcher *matcher, int start, char *regex, stb_uint16 *end)
+{
+ int n;
+ int last_start = -1;
+ stb_uint16 last_end = start;
+
+ while (*regex) {
+ switch (*regex) {
+ case '(':
+ last_start = last_end;
+ regex = stb__reg_parse_alt(matcher, last_end, regex+1, &last_end);
+ if (regex == NULL || *regex != ')')
+ return NULL;
+ ++regex;
+ break;
+
+ case '|':
+ case ')':
+ *end = last_end;
+ return regex;
+
+ case '?':
+ if (last_start < 0) return NULL;
+ stb__add_epsilon(matcher, last_start, last_end);
+ ++regex;
+ break;
+
+ case '*':
+ if (last_start < 0) return NULL;
+ stb__add_epsilon(matcher, last_start, last_end);
+
+ // fall through
+
+ case '+':
+ if (last_start < 0) return NULL;
+ stb__add_epsilon(matcher, last_end, last_start);
+ // prevent links back to last_end from chaining to last_start
+ n = stb__add_node(matcher);
+ stb__add_epsilon(matcher, last_end, n);
+ last_end = n;
+ ++regex;
+ break;
+
+ case '{': // not supported!
+ // @TODO: given {n,m}, clone last_start to last_end m times,
+ // and include epsilons from start to first m-n blocks
+ return NULL;
+
+ case '\\':
+ ++regex;
+ if (!*regex) return NULL;
+
+ // fallthrough
+ default: // match exactly this character
+ n = stb__add_node(matcher);
+ stb__add_edge(matcher, last_end, n, *regex);
+ last_start = last_end;
+ last_end = n;
+ ++regex;
+ break;
+
+ case '$':
+ n = stb__add_node(matcher);
+ stb__add_edge(matcher, last_end, n, '\n');
+ last_start = last_end;
+ last_end = n;
+ ++regex;
+ break;
+
+ case '.':
+ n = stb__add_node(matcher);
+ stb__add_edge(matcher, last_end, n, -1);
+ last_start = last_end;
+ last_end = n;
+ ++regex;
+ break;
+
+ case '[': {
+ stb_uint8 flags[256];
+ int invert = 0,z;
+ ++regex;
+ if (matcher->num_charset == 0) {
+ matcher->charset = (stb_uint *) stb_malloc(matcher, sizeof(*matcher->charset) * 256);
+ memset(matcher->charset, 0, sizeof(*matcher->charset) * 256);
+ }
+
+ memset(flags,0,sizeof(flags));
+
+ // leading ^ is special
+ if (*regex == '^')
+ ++regex, invert = 1;
+
+ // leading ] is special
+ if (*regex == ']') {
+ flags[(int) ']'] = 1;
+ ++regex;
+ }
+ while (*regex != ']') {
+ stb_uint a;
+ if (!*regex) return NULL;
+ a = *regex++;
+ if (regex[0] == '-' && regex[1] != ']') {
+ stb_uint i,b = regex[1];
+ regex += 2;
+ if (b == 0) return NULL;
+ if (a > b) return NULL;
+ for (i=a; i <= b; ++i)
+ flags[i] = 1;
+ } else
+ flags[a] = 1;
+ }
+ ++regex;
+ if (invert) {
+ int i;
+ for (i=0; i < 256; ++i)
+ flags[i] = 1-flags[i];
+ }
+
+ // now check if any existing charset matches
+ for (z=0; z < matcher->num_charset; ++z) {
+ int i, k[2] = { 0, 1 << z};
+ for (i=0; i < 256; ++i) {
+ unsigned int f = k[flags[i]];
+ if ((matcher->charset[i] & k[1]) != f)
+ break;
+ }
+ if (i == 256) break;
+ }
+
+ if (z == matcher->num_charset) {
+ int i;
+ ++matcher->num_charset;
+ if (matcher->num_charset > 32) {
+ assert(0); /* NOTREACHED */
+ return NULL; // too many charsets, oops
+ }
+ for (i=0; i < 256; ++i)
+ if (flags[i])
+ matcher->charset[i] |= (1 << z);
+ }
+
+ n = stb__add_node(matcher);
+ stb__add_edge(matcher, last_end, n, -2 - z);
+ last_start = last_end;
+ last_end = n;
+ break;
+ }
+ }
+ }
+ *end = last_end;
+ return regex;
+}
+
+static char *stb__reg_parse_alt(stb_matcher *matcher, int start, char *regex, stb_uint16 *end)
+{
+ stb_uint16 last_end = start;
+ stb_uint16 main_end;
+
+ int head, tail;
+
+ head = stb__add_node(matcher);
+ stb__add_epsilon(matcher, start, head);
+
+ regex = stb__reg_parse(matcher, head, regex, &last_end);
+ if (regex == NULL) return NULL;
+ if (*regex == 0 || *regex == ')') {
+ *end = last_end;
+ return regex;
+ }
+
+ main_end = last_end;
+ tail = stb__add_node(matcher);
+
+ stb__add_epsilon(matcher, last_end, tail);
+
+ // start alternatives from the same starting node; use epsilon
+ // transitions to combine their endings
+ while(*regex && *regex != ')') {
+ assert(*regex == '|');
+ head = stb__add_node(matcher);
+ stb__add_epsilon(matcher, start, head);
+ regex = stb__reg_parse(matcher, head, regex+1, &last_end);
+ if (regex == NULL)
+ return NULL;
+ stb__add_epsilon(matcher, last_end, tail);
+ }
+
+ *end = tail;
+ return regex;
+}
+
+static char *stb__wild_parse(stb_matcher *matcher, int start, char *str, stb_uint16 *end)
+{
+ int n;
+ stb_uint16 last_end;
+
+ last_end = stb__add_node(matcher);
+ stb__add_epsilon(matcher, start, last_end);
+
+ while (*str) {
+ switch (*str) {
+ // fallthrough
+ default: // match exactly this character
+ n = stb__add_node(matcher);
+ if (toupper(*str) == tolower(*str)) {
+ stb__add_edge(matcher, last_end, n, *str);
+ } else {
+ stb__add_edge(matcher, last_end, n, tolower(*str));
+ stb__add_edge(matcher, last_end, n, toupper(*str));
+ }
+ last_end = n;
+ ++str;
+ break;
+
+ case '?':
+ n = stb__add_node(matcher);
+ stb__add_edge(matcher, last_end, n, -1);
+ last_end = n;
+ ++str;
+ break;
+
+ case '*':
+ n = stb__add_node(matcher);
+ stb__add_edge(matcher, last_end, n, -1);
+ stb__add_epsilon(matcher, last_end, n);
+ stb__add_epsilon(matcher, n, last_end);
+ last_end = n;
+ ++str;
+ break;
+ }
+ }
+
+ // now require end of string to match
+ n = stb__add_node(matcher);
+ stb__add_edge(matcher, last_end, n, 0);
+ last_end = n;
+
+ *end = last_end;
+ return str;
+}
+
+static int stb__opt(stb_matcher *m, int n)
+{
+ for(;;) {
+ stb_nfa_node *p = &m->nodes[n];
+ if (p->goal) return n;
+ if (stb_arr_len(p->out)) return n;
+ if (stb_arr_len(p->eps) != 1) return n;
+ n = p->eps[0];
+ }
+}
+
+static void stb__optimize(stb_matcher *m)
+{
+ // if the target of any edge is a node with exactly
+ // one out-epsilon, shorten it
+ int i,j;
+ for (i=0; i < stb_arr_len(m->nodes); ++i) {
+ stb_nfa_node *p = &m->nodes[i];
+ for (j=0; j < stb_arr_len(p->out); ++j)
+ p->out[j].node = stb__opt(m,p->out[j].node);
+ for (j=0; j < stb_arr_len(p->eps); ++j)
+ p->eps[j] = stb__opt(m,p->eps[j] );
+ }
+ m->start_node = stb__opt(m,m->start_node);
+}
+
+void stb_matcher_free(stb_matcher *f)
+{
+ stb_free(f);
+}
+
+static stb_matcher *stb__alloc_matcher(void)
+{
+ stb_matcher *matcher = (stb_matcher *) stb_malloc(0,sizeof(*matcher));
+
+ matcher->start_node = 0;
+ stb_arr_malloc((void **) &matcher->nodes, matcher);
+ matcher->num_charset = 0;
+ matcher->match_start = 0;
+ matcher->does_lex = 0;
+
+ matcher->dfa_start = STB__DFA_UNDEF;
+ stb_arr_malloc((void **) &matcher->dfa, matcher);
+ stb_arr_malloc((void **) &matcher->dfa_mapping, matcher);
+ stb_arr_malloc((void **) &matcher->dfa_result, matcher);
+
+ stb__add_node(matcher);
+
+ return matcher;
+}
+
+static void stb__lex_reset(stb_matcher *matcher)
+{
+ // flush cached dfa data
+ stb_arr_setlen(matcher->dfa, 0);
+ stb_arr_setlen(matcher->dfa_mapping, 0);
+ stb_arr_setlen(matcher->dfa_result, 0);
+ matcher->dfa_start = STB__DFA_UNDEF;
+}
+
+stb_matcher *stb_regex_matcher(char *regex)
+{
+ char *z;
+ stb_uint16 end;
+ stb_matcher *matcher = stb__alloc_matcher();
+ if (*regex == '^') {
+ matcher->match_start = 1;
+ ++regex;
+ }
+
+ z = stb__reg_parse_alt(matcher, matcher->start_node, regex, &end);
+
+ if (!z || *z) {
+ stb_free(matcher);
+ return NULL;
+ }
+
+ ((matcher->nodes)[(int) end]).goal = STB__NFA_STOP_GOAL;
+
+ return matcher;
+}
+
+stb_matcher *stb_lex_matcher(void)
+{
+ stb_matcher *matcher = stb__alloc_matcher();
+
+ matcher->match_start = 1;
+ matcher->does_lex = 1;
+
+ return matcher;
+}
+
+int stb_lex_item(stb_matcher *matcher, const char *regex, int result)
+{
+ char *z;
+ stb_uint16 end;
+
+ z = stb__reg_parse_alt(matcher, matcher->start_node, (char*) regex, &end);
+
+ if (z == NULL)
+ return 0;
+
+ stb__lex_reset(matcher);
+
+ matcher->nodes[(int) end].goal = result;
+ return 1;
+}
+
+int stb_lex_item_wild(stb_matcher *matcher, const char *regex, int result)
+{
+ char *z;
+ stb_uint16 end;
+
+ z = stb__wild_parse(matcher, matcher->start_node, (char*) regex, &end);
+
+ if (z == NULL)
+ return 0;
+
+ stb__lex_reset(matcher);
+
+ matcher->nodes[(int) end].goal = result;
+ return 1;
+}
+
+static void stb__clear(stb_matcher *m, stb_uint16 *list)
+{
+ int i;
+ for (i=0; i < stb_arr_len(list); ++i)
+ m->nodes[(int) list[i]].active = 0;
+}
+
+static int stb__clear_goalcheck(stb_matcher *m, stb_uint16 *list)
+{
+ int i, t=0;
+ for (i=0; i < stb_arr_len(list); ++i) {
+ t += m->nodes[(int) list[i]].goal;
+ m->nodes[(int) list[i]].active = 0;
+ }
+ return t;
+}
+
+static stb_uint16 * stb__add_if_inactive(stb_matcher *m, stb_uint16 *list, int n)
+{
+ if (!m->nodes[n].active) {
+ stb_arr_push(list, n);
+ m->nodes[n].active = 1;
+ }
+ return list;
+}
+
+static stb_uint16 * stb__eps_closure(stb_matcher *m, stb_uint16 *list)
+{
+ int i,n = stb_arr_len(list);
+
+ for(i=0; i < n; ++i) {
+ stb_uint16 *e = m->nodes[(int) list[i]].eps;
+ if (e) {
+ int j,k = stb_arr_len(e);
+ for (j=0; j < k; ++j)
+ list = stb__add_if_inactive(m, list, e[j]);
+ n = stb_arr_len(list);
+ }
+ }
+
+ return list;
+}
+
+int stb_matcher_match(stb_matcher *m, char *str)
+{
+ int result = 0;
+ int i,j,y,z;
+ stb_uint16 *previous = NULL;
+ stb_uint16 *current = NULL;
+ stb_uint16 *temp;
+
+ stb_arr_setsize(previous, 4);
+ stb_arr_setsize(current, 4);
+
+ previous = stb__add_if_inactive(m, previous, m->start_node);
+ previous = stb__eps_closure(m,previous);
+ stb__clear(m, previous);
+
+ while (*str && stb_arr_len(previous)) {
+ y = stb_arr_len(previous);
+ for (i=0; i < y; ++i) {
+ stb_nfa_node *n = &m->nodes[(int) previous[i]];
+ z = stb_arr_len(n->out);
+ for (j=0; j < z; ++j) {
+ if (n->out[j].match >= 0) {
+ if (n->out[j].match == *str)
+ current = stb__add_if_inactive(m, current, n->out[j].node);
+ } else if (n->out[j].match == -1) {
+ if (*str != '\n')
+ current = stb__add_if_inactive(m, current, n->out[j].node);
+ } else if (n->out[j].match < -1) {
+ int z = -n->out[j].match - 2;
+ if (m->charset[(stb_uint8) *str] & (1 << z))
+ current = stb__add_if_inactive(m, current, n->out[j].node);
+ }
+ }
+ }
+ stb_arr_setlen(previous, 0);
+
+ temp = previous;
+ previous = current;
+ current = temp;
+
+ previous = stb__eps_closure(m,previous);
+ stb__clear(m, previous);
+
+ ++str;
+ }
+
+ // transition to pick up a '$' at the end
+ y = stb_arr_len(previous);
+ for (i=0; i < y; ++i)
+ m->nodes[(int) previous[i]].active = 1;
+
+ for (i=0; i < y; ++i) {
+ stb_nfa_node *n = &m->nodes[(int) previous[i]];
+ z = stb_arr_len(n->out);
+ for (j=0; j < z; ++j) {
+ if (n->out[j].match == '\n')
+ current = stb__add_if_inactive(m, current, n->out[j].node);
+ }
+ }
+
+ previous = stb__eps_closure(m,previous);
+ stb__clear(m, previous);
+
+ y = stb_arr_len(previous);
+ for (i=0; i < y; ++i)
+ if (m->nodes[(int) previous[i]].goal)
+ result = 1;
+
+ stb_arr_free(previous);
+ stb_arr_free(current);
+
+ return result && *str == 0;
+}
+
+stb_int16 stb__get_dfa_node(stb_matcher *m, stb_uint16 *list)
+{
+ stb_uint16 node;
+ stb_uint32 data[8], *state, *newstate;
+ int i,j,n;
+
+ state = (stb_uint32 *) stb_temp(data, m->num_words_per_dfa * 4);
+ memset(state, 0, m->num_words_per_dfa*4);
+
+ n = stb_arr_len(list);
+ for (i=0; i < n; ++i) {
+ int x = list[i];
+ state[x >> 5] |= 1 << (x & 31);
+ }
+
+ // @TODO use a hash table
+ n = stb_arr_len(m->dfa_mapping);
+ i=j=0;
+ for(; j < n; ++i, j += m->num_words_per_dfa) {
+ // @TODO special case for <= 32
+ if (!memcmp(state, m->dfa_mapping + j, m->num_words_per_dfa*4)) {
+ node = i;
+ goto done;
+ }
+ }
+
+ assert(stb_arr_len(m->dfa) == i);
+ node = i;
+
+ newstate = stb_arr_addn(m->dfa_mapping, m->num_words_per_dfa);
+ memcpy(newstate, state, m->num_words_per_dfa*4);
+
+ // set all transitions to 'unknown'
+ stb_arr_add(m->dfa);
+ memset(m->dfa[i].transition, -1, sizeof(m->dfa[i].transition));
+
+ if (m->does_lex) {
+ int result = -1;
+ n = stb_arr_len(list);
+ for (i=0; i < n; ++i) {
+ if (m->nodes[(int) list[i]].goal > result)
+ result = m->nodes[(int) list[i]].goal;
+ }
+
+ stb_arr_push(m->dfa_result, result);
+ }
+
+done:
+ stb_tempfree(data, state);
+ return node;
+}
+
+static int stb__matcher_dfa(stb_matcher *m, char *str_c, int *len)
+{
+ stb_uint8 *str = (stb_uint8 *) str_c;
+ stb_int16 node,prevnode;
+ stb_dfa *trans;
+ int match_length = 0;
+ stb_int16 match_result=0;
+
+ if (m->dfa_start == STB__DFA_UNDEF) {
+ stb_uint16 *list;
+
+ m->num_words_per_dfa = (stb_arr_len(m->nodes)+31) >> 5;
+ stb__optimize(m);
+
+ list = stb__add_if_inactive(m, NULL, m->start_node);
+ list = stb__eps_closure(m,list);
+ if (m->does_lex) {
+ m->dfa_start = stb__get_dfa_node(m,list);
+ stb__clear(m, list);
+ // DON'T allow start state to be a goal state!
+ // this allows people to specify regexes that can match 0
+ // characters without them actually matching (also we don't
+ // check _before_ advancing anyway
+ if (m->dfa_start <= STB__DFA_MGOAL)
+ m->dfa_start = -(m->dfa_start - STB__DFA_MGOAL);
+ } else {
+ if (stb__clear_goalcheck(m, list))
+ m->dfa_start = STB__DFA_GOAL;
+ else
+ m->dfa_start = stb__get_dfa_node(m,list);
+ }
+ stb_arr_free(list);
+ }
+
+ prevnode = STB__DFA_UNDEF;
+ node = m->dfa_start;
+ trans = m->dfa;
+
+ if (m->dfa_start == STB__DFA_GOAL)
+ return 1;
+
+ for(;;) {
+ assert(node >= STB__DFA_VALID);
+
+ // fast inner DFA loop; especially if STB__DFA_VALID is 0
+
+ do {
+ prevnode = node;
+ node = trans[node].transition[*str++];
+ } while (node >= STB__DFA_VALID);
+
+ assert(node >= STB__DFA_MGOAL - stb_arr_len(m->dfa));
+ assert(node < stb_arr_len(m->dfa));
+
+ // special case for lex: need _longest_ match, so notice goal
+ // state without stopping
+ if (node <= STB__DFA_MGOAL) {
+ match_length = (int) (str - (stb_uint8 *) str_c);
+ node = -(node - STB__DFA_MGOAL);
+ match_result = node;
+ continue;
+ }
+
+ // slow NFA->DFA conversion
+
+ // or we hit the goal or the end of the string, but those
+ // can only happen once per search...
+
+ if (node == STB__DFA_UNDEF) {
+ // build a list -- @TODO special case <= 32 states
+ // heck, use a more compact data structure for <= 16 and <= 8 ?!
+
+ // @TODO keep states/newstates around instead of reallocating them
+ stb_uint16 *states = NULL;
+ stb_uint16 *newstates = NULL;
+ int i,j,y,z;
+ stb_uint32 *flags = &m->dfa_mapping[prevnode * m->num_words_per_dfa];
+ assert(prevnode != STB__DFA_UNDEF);
+ stb_arr_setsize(states, 4);
+ stb_arr_setsize(newstates,4);
+ for (j=0; j < m->num_words_per_dfa; ++j) {
+ for (i=0; i < 32; ++i) {
+ if (*flags & (1 << i))
+ stb_arr_push(states, j*32+i);
+ }
+ ++flags;
+ }
+ // states is now the states we were in in the previous node;
+ // so now we can compute what node it transitions to on str[-1]
+
+ y = stb_arr_len(states);
+ for (i=0; i < y; ++i) {
+ stb_nfa_node *n = &m->nodes[(int) states[i]];
+ z = stb_arr_len(n->out);
+ for (j=0; j < z; ++j) {
+ if (n->out[j].match >= 0) {
+ if (n->out[j].match == str[-1] || (str[-1] == 0 && n->out[j].match == '\n'))
+ newstates = stb__add_if_inactive(m, newstates, n->out[j].node);
+ } else if (n->out[j].match == -1) {
+ if (str[-1] != '\n' && str[-1])
+ newstates = stb__add_if_inactive(m, newstates, n->out[j].node);
+ } else if (n->out[j].match < -1) {
+ int z = -n->out[j].match - 2;
+ if (m->charset[str[-1]] & (1 << z))
+ newstates = stb__add_if_inactive(m, newstates, n->out[j].node);
+ }
+ }
+ }
+ // AND add in the start state!
+ if (!m->match_start || (str[-1] == '\n' && !m->does_lex))
+ newstates = stb__add_if_inactive(m, newstates, m->start_node);
+ // AND epsilon close it
+ newstates = stb__eps_closure(m, newstates);
+ // if it's a goal state, then that's all there is to it
+ if (stb__clear_goalcheck(m, newstates)) {
+ if (m->does_lex) {
+ match_length = (int) (str - (stb_uint8 *) str_c);
+ node = stb__get_dfa_node(m,newstates);
+ match_result = node;
+ node = -node + STB__DFA_MGOAL;
+ trans = m->dfa; // could have gotten realloc()ed
+ } else
+ node = STB__DFA_GOAL;
+ } else if (str[-1] == 0 || stb_arr_len(newstates) == 0) {
+ node = STB__DFA_END;
+ } else {
+ node = stb__get_dfa_node(m,newstates);
+ trans = m->dfa; // could have gotten realloc()ed
+ }
+ trans[prevnode].transition[str[-1]] = node;
+ if (node <= STB__DFA_MGOAL)
+ node = -(node - STB__DFA_MGOAL);
+ stb_arr_free(newstates);
+ stb_arr_free(states);
+ }
+
+ if (node == STB__DFA_GOAL) {
+ return 1;
+ }
+ if (node == STB__DFA_END) {
+ if (m->does_lex) {
+ if (match_result) {
+ if (len) *len = match_length;
+ return m->dfa_result[(int) match_result];
+ }
+ }
+ return 0;
+ }
+
+ assert(node != STB__DFA_UNDEF);
+ }
+}
+
+int stb_matcher_find(stb_matcher *m, char *str)
+{
+ assert(m->does_lex == 0);
+ return stb__matcher_dfa(m, str, NULL);
+}
+
+int stb_lex(stb_matcher *m, char *str, int *len)
+{
+ assert(m->does_lex);
+ return stb__matcher_dfa(m, str, len);
+}
+
+#ifdef STB_PERFECT_HASH
+int stb_regex(char *regex, char *str)
+{
+ static stb_perfect p;
+ static stb_matcher ** matchers;
+ static char ** regexps;
+ static char ** regexp_cache;
+ static unsigned short *mapping;
+ int z = stb_perfect_hash(&p, (int)(size_t) regex);
+ if (z >= 0) {
+ if (strcmp(regex, regexp_cache[(int) mapping[z]])) {
+ int i = mapping[z];
+ stb_matcher_free(matchers[i]);
+ free(regexp_cache[i]);
+ regexps[i] = regex;
+ regexp_cache[i] = stb_p_strdup(regex);
+ matchers[i] = stb_regex_matcher(regex);
+ }
+ } else {
+ int i,n;
+ if (regex == NULL) {
+ for (i=0; i < stb_arr_len(matchers); ++i) {
+ stb_matcher_free(matchers[i]);
+ free(regexp_cache[i]);
+ }
+ stb_arr_free(matchers);
+ stb_arr_free(regexps);
+ stb_arr_free(regexp_cache);
+ stb_perfect_destroy(&p);
+ free(mapping); mapping = NULL;
+ return -1;
+ }
+ stb_arr_push(regexps, regex);
+ stb_arr_push(regexp_cache, stb_p_strdup(regex));
+ stb_arr_push(matchers, stb_regex_matcher(regex));
+ stb_perfect_destroy(&p);
+ n = stb_perfect_create(&p, (unsigned int *) (char **) regexps, stb_arr_len(regexps));
+ mapping = (unsigned short *) realloc(mapping, n * sizeof(*mapping));
+ for (i=0; i < stb_arr_len(regexps); ++i)
+ mapping[stb_perfect_hash(&p, (int)(size_t) regexps[i])] = i;
+ z = stb_perfect_hash(&p, (int)(size_t) regex);
+ }
+ return stb_matcher_find(matchers[(int) mapping[z]], str);
+}
+#endif
+#endif // STB_DEFINE
+
+
+#if 0
+//////////////////////////////////////////////////////////////////////////////
+//
+// C source-code introspection
+//
+
+// runtime structure
+typedef struct
+{
+ char *name;
+ char *type; // base type
+ char *comment; // content of comment field
+ int size; // size of base type
+ int offset; // field offset
+ int arrcount[8]; // array sizes; -1 = pointer indirection; 0 = end of list
+} stb_info_field;
+
+typedef struct
+{
+ char *structname;
+ int size;
+ int num_fields;
+ stb_info_field *fields;
+} stb_info_struct;
+
+extern stb_info_struct stb_introspect_output[];
+
+//
+
+STB_EXTERN void stb_introspect_precompiled(stb_info_struct *compiled);
+STB_EXTERN void stb__introspect(char *path, char *file);
+
+#define stb_introspect_ship() stb__introspect(NULL, NULL, stb__introspect_output)
+
+#ifdef STB_SHIP
+#define stb_introspect() stb_introspect_ship()
+#define stb_introspect_path(p) stb_introspect_ship()
+#else
+// bootstrapping: define stb_introspect() (or 'path') the first time
+#define stb_introspect() stb__introspect(NULL, __FILE__, NULL)
+#define stb_introspect_auto() stb__introspect(NULL, __FILE__, stb__introspect_output)
+
+#define stb_introspect_path(p) stb__introspect(p, __FILE__, NULL)
+#define stb_introspect_path(p) stb__introspect(p, __FILE__, NULL)
+#endif
+
+#ifdef STB_DEFINE
+
+#ifndef STB_INTROSPECT_CPP
+ #ifdef __cplusplus
+ #define STB_INTROSPECT_CPP 1
+ #else
+ #define STB_INTROSPECT_CPP 0
+ #endif
+#endif
+
+void stb_introspect_precompiled(stb_info_struct *compiled)
+{
+
+}
+
+
+static void stb__introspect_filename(char *buffer, char *path)
+{
+ #if STB_INTROSPECT_CPP
+ stb_p_sprintf(buffer stb_p_size(9999), "%s/stb_introspect.cpp", path);
+ #else
+ stb_p_sprintf(buffer stb_p_size(9999), "%s/stb_introspect.c", path);
+ #endif
+}
+
+static void stb__introspect_compute(char *path, char *file)
+{
+ int i;
+ char ** include_list = NULL;
+ char ** introspect_list = NULL;
+ FILE *f;
+ f = stb_p_fopen(file, "w");
+ if (!f) return;
+
+ fputs("// if you get compiler errors, change the following 0 to a 1:\n", f);
+ fputs("#define STB_INTROSPECT_INVALID 0\n\n", f);
+ fputs("// this will force the code to compile, and force the introspector\n", f);
+ fputs("// to run and then exit, allowing you to recompile\n\n\n", f);
+ fputs("#include \"stb.h\"\n\n",f );
+ fputs("#if STB_INTROSPECT_INVALID\n", f);
+ fputs(" stb_info_struct stb__introspect_output[] = { (void *) 1 }\n", f);
+ fputs("#else\n\n", f);
+ for (i=0; i < stb_arr_len(include_list); ++i)
+ fprintf(f, " #include \"%s\"\n", include_list[i]);
+
+ fputs(" stb_info_struct stb__introspect_output[] =\n{\n", f);
+ for (i=0; i < stb_arr_len(introspect_list); ++i)
+ fprintf(f, " stb_introspect_%s,\n", introspect_list[i]);
+ fputs(" };\n", f);
+ fputs("#endif\n", f);
+ fclose(f);
+}
+
+static stb_info_struct *stb__introspect_info;
+
+#ifndef STB_SHIP
+
+#endif
+
+void stb__introspect(char *path, char *file, stb_info_struct *compiled)
+{
+ static int first=1;
+ if (!first) return;
+ first=0;
+
+ stb__introspect_info = compiled;
+
+ #ifndef STB_SHIP
+ if (path || file) {
+ int bail_flag = compiled && compiled[0].structname == (void *) 1;
+ int needs_building = bail_flag;
+ struct stb__stat st;
+ char buffer[1024], buffer2[1024];
+ if (!path) {
+ stb_splitpath(buffer, file, STB_PATH);
+ path = buffer;
+ }
+ // bail if the source path doesn't exist
+ if (!stb_fexists(path)) return;
+
+ stb__introspect_filename(buffer2, path);
+
+ // get source/include files timestamps, compare to output-file timestamp;
+ // if mismatched, regenerate
+
+ if (stb__stat(buffer2, &st))
+ needs_building = STB_TRUE;
+
+ {
+ // find any file that contains an introspection command and is newer
+ // if needs_building is already true, we don't need to do this test,
+ // but we still need these arrays, so go ahead and get them
+ char **all[3];
+ all[0] = stb_readdir_files_mask(path, "*.h");
+ all[1] = stb_readdir_files_mask(path, "*.c");
+ all[2] = stb_readdir_files_mask(path, "*.cpp");
+ int i,j;
+ if (needs_building) {
+ for (j=0; j < 3; ++j) {
+ for (i=0; i < stb_arr_len(all[j]); ++i) {
+ struct stb__stat st2;
+ if (!stb__stat(all[j][i], &st2)) {
+ if (st.st_mtime < st2.st_mtime) {
+ char *z = stb_filec(all[j][i], NULL);
+ int found=STB_FALSE;
+ while (y) {
+ y = strstr(y, "//si");
+ if (y && isspace(y[4])) {
+ found = STB_TRUE;
+ break;
+ }
+ }
+ needs_building = STB_TRUE;
+ goto done;
+ }
+ }
+ }
+ }
+ done:;
+ }
+ char *z = stb_filec(all[i], NULL), *y = z;
+ int found=STB_FALSE;
+ while (y) {
+ y = strstr(y, "//si");
+ if (y && isspace(y[4])) {
+ found = STB_TRUE;
+ break;
+ }
+ }
+ if (found)
+ stb_arr_push(introspect_h, stb_p_strdup(all[i]));
+ free(z);
+ }
+ }
+ stb_readdir_free(all);
+ if (!needs_building) {
+ for (i=0; i < stb_arr_len(introspect_h); ++i) {
+ struct stb__stat st2;
+ if (!stb__stat(introspect_h[i], &st2))
+ if (st.st_mtime < st2.st_mtime)
+ needs_building = STB_TRUE;
+ }
+ }
+
+ if (needs_building) {
+ stb__introspect_compute(path, buffer2);
+ }
+ }
+ }
+ #endif
+}
+#endif
+#endif
+
+#ifdef STB_INTROSPECT
+// compile-time code-generator
+#define INTROSPECT(x) int main(int argc, char **argv) { stb__introspect(__FILE__); return 0; }
+#define FILE(x)
+
+void stb__introspect(char *filename)
+{
+ char *file = stb_file(filename, NULL);
+ char *s = file, *t, **p;
+ char *out_name = "stb_introspect.c";
+ char *out_path;
+ STB_ARR(char) filelist = NULL;
+ int i,n;
+ if (!file) stb_fatal("Couldn't open %s", filename);
+
+ out_path = stb_splitpathdup(filename, STB_PATH);
+
+ // search for the macros
+ while (*s) {
+ char buffer[256];
+ while (*s && !isupper(*s)) ++s;
+ s = stb_strtok_invert(buffer, s, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ s = stb_skipwhite(s);
+ if (*s == '(') {
+ ++s;
+ t = strchr(s, ')');
+ if (t == NULL) stb_fatal("Error parsing %s", filename);
+
+ }
+ }
+}
+
+
+
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// STB-C sliding-window dictionary compression
+//
+// This uses a DEFLATE-style sliding window, but no bitwise entropy.
+// Everything is on byte boundaries, so you could then apply a byte-wise
+// entropy code, though that's nowhere near as effective.
+//
+// An STB-C stream begins with a 16-byte header:
+// 4 bytes: 0x57 0xBC 0x00 0x00
+// 8 bytes: big-endian size of decompressed data, 64-bits
+// 4 bytes: big-endian size of window (how far back decompressor may need)
+//
+// The following symbols appear in the stream (these were determined ad hoc,
+// not by analysis):
+//
+// [dict] 00000100 yyyyyyyy yyyyyyyy yyyyyyyy xxxxxxxx xxxxxxxx
+// [END] 00000101 11111010 cccccccc cccccccc cccccccc cccccccc
+// [dict] 00000110 yyyyyyyy yyyyyyyy yyyyyyyy xxxxxxxx
+// [literals] 00000111 zzzzzzzz zzzzzzzz
+// [literals] 00001zzz zzzzzzzz
+// [dict] 00010yyy yyyyyyyy yyyyyyyy xxxxxxxx xxxxxxxx
+// [dict] 00011yyy yyyyyyyy yyyyyyyy xxxxxxxx
+// [literals] 001zzzzz
+// [dict] 01yyyyyy yyyyyyyy xxxxxxxx
+// [dict] 1xxxxxxx yyyyyyyy
+//
+// xxxxxxxx: match length - 1
+// yyyyyyyy: backwards distance - 1
+// zzzzzzzz: num literals - 1
+// cccccccc: adler32 checksum of decompressed data
+// (all big-endian)
+
+
+STB_EXTERN stb_uint stb_decompress_length(stb_uchar *input);
+STB_EXTERN stb_uint stb_decompress(stb_uchar *out,stb_uchar *in,stb_uint len);
+STB_EXTERN stb_uint stb_compress (stb_uchar *out,stb_uchar *in,stb_uint len);
+STB_EXTERN void stb_compress_window(int z);
+STB_EXTERN void stb_compress_hashsize(unsigned int z);
+
+STB_EXTERN int stb_compress_tofile(char *filename, char *in, stb_uint len);
+STB_EXTERN int stb_compress_intofile(FILE *f, char *input, stb_uint len);
+STB_EXTERN char *stb_decompress_fromfile(char *filename, stb_uint *len);
+
+STB_EXTERN int stb_compress_stream_start(FILE *f);
+STB_EXTERN void stb_compress_stream_end(int close);
+STB_EXTERN void stb_write(char *data, int data_len);
+
+#ifdef STB_DEFINE
+
+stb_uint stb_decompress_length(stb_uchar *input)
+{
+ return (input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11];
+}
+
+//////////////////// decompressor ///////////////////////
+
+// simple implementation that just writes whole thing into big block
+
+static unsigned char *stb__barrier;
+static unsigned char *stb__barrier2;
+static unsigned char *stb__barrier3;
+static unsigned char *stb__barrier4;
+
+static stb_uchar *stb__dout;
+static void stb__match(stb_uchar *data, stb_uint length)
+{
+ // INVERSE of memmove... write each byte before copying the next...
+ assert (stb__dout + length <= stb__barrier);
+ if (stb__dout + length > stb__barrier) { stb__dout += length; return; }
+ if (data < stb__barrier4) { stb__dout = stb__barrier+1; return; }
+ while (length--) *stb__dout++ = *data++;
+}
+
+static void stb__lit(stb_uchar *data, stb_uint length)
+{
+ assert (stb__dout + length <= stb__barrier);
+ if (stb__dout + length > stb__barrier) { stb__dout += length; return; }
+ if (data < stb__barrier2) { stb__dout = stb__barrier+1; return; }
+ memcpy(stb__dout, data, length);
+ stb__dout += length;
+}
+
+#define stb__in2(x) ((i[x] << 8) + i[(x)+1])
+#define stb__in3(x) ((i[x] << 16) + stb__in2((x)+1))
+#define stb__in4(x) ((i[x] << 24) + stb__in3((x)+1))
+
+static stb_uchar *stb_decompress_token(stb_uchar *i)
+{
+ if (*i >= 0x20) { // use fewer if's for cases that expand small
+ if (*i >= 0x80) stb__match(stb__dout-i[1]-1, i[0] - 0x80 + 1), i += 2;
+ else if (*i >= 0x40) stb__match(stb__dout-(stb__in2(0) - 0x4000 + 1), i[2]+1), i += 3;
+ else /* *i >= 0x20 */ stb__lit(i+1, i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1);
+ } else { // more ifs for cases that expand large, since overhead is amortized
+ if (*i >= 0x18) stb__match(stb__dout-(stb__in3(0) - 0x180000 + 1), i[3]+1), i += 4;
+ else if (*i >= 0x10) stb__match(stb__dout-(stb__in3(0) - 0x100000 + 1), stb__in2(3)+1), i += 5;
+ else if (*i >= 0x08) stb__lit(i+2, stb__in2(0) - 0x0800 + 1), i += 2 + (stb__in2(0) - 0x0800 + 1);
+ else if (*i == 0x07) stb__lit(i+3, stb__in2(1) + 1), i += 3 + (stb__in2(1) + 1);
+ else if (*i == 0x06) stb__match(stb__dout-(stb__in3(1)+1), i[4]+1), i += 5;
+ else if (*i == 0x04) stb__match(stb__dout-(stb__in3(1)+1), stb__in2(4)+1), i += 6;
+ }
+ return i;
+}
+
+stb_uint stb_decompress(stb_uchar *output, stb_uchar *i, stb_uint length)
+{
+ stb_uint olen;
+ if (stb__in4(0) != 0x57bC0000) return 0;
+ if (stb__in4(4) != 0) return 0; // error! stream is > 4GB
+ olen = stb_decompress_length(i);
+ stb__barrier2 = i;
+ stb__barrier3 = i+length;
+ stb__barrier = output + olen;
+ stb__barrier4 = output;
+ i += 16;
+
+ stb__dout = output;
+ while (1) {
+ stb_uchar *old_i = i;
+ i = stb_decompress_token(i);
+ if (i == old_i) {
+ if (*i == 0x05 && i[1] == 0xfa) {
+ assert(stb__dout == output + olen);
+ if (stb__dout != output + olen) return 0;
+ if (stb_adler32(1, output, olen) != (stb_uint) stb__in4(2))
+ return 0;
+ return olen;
+ } else {
+ assert(0); /* NOTREACHED */
+ return 0;
+ }
+ }
+ assert(stb__dout <= output + olen);
+ if (stb__dout > output + olen)
+ return 0;
+ }
+}
+
+char *stb_decompress_fromfile(char *filename, unsigned int *len)
+{
+ unsigned int n;
+ char *q;
+ unsigned char *p;
+ FILE *f = stb_p_fopen(filename, "rb"); if (f == NULL) return NULL;
+ fseek(f, 0, SEEK_END);
+ n = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ p = (unsigned char * ) malloc(n); if (p == NULL) return NULL;
+ fread(p, 1, n, f);
+ fclose(f);
+ if (p == NULL) return NULL;
+ if (p[0] != 0x57 || p[1] != 0xBc || p[2] || p[3]) { free(p); return NULL; }
+ q = (char *) malloc(stb_decompress_length(p)+1);
+ if (!q) { free(p); return NULL; }
+ *len = stb_decompress((unsigned char *) q, p, n);
+ if (*len) q[*len] = 0;
+ free(p);
+ return q;
+}
+
+#if 0
+// streaming decompressor
+
+static struct
+{
+ stb__uchar *in_buffer;
+ stb__uchar *match;
+
+ stb__uint pending_literals;
+ stb__uint pending_match;
+} xx;
+
+
+
+static void stb__match(stb_uchar *data, stb_uint length)
+{
+ // INVERSE of memmove... write each byte before copying the next...
+ assert (stb__dout + length <= stb__barrier);
+ if (stb__dout + length > stb__barrier) { stb__dout += length; return; }
+ if (data < stb__barrier2) { stb__dout = stb__barrier+1; return; }
+ while (length--) *stb__dout++ = *data++;
+}
+
+static void stb__lit(stb_uchar *data, stb_uint length)
+{
+ assert (stb__dout + length <= stb__barrier);
+ if (stb__dout + length > stb__barrier) { stb__dout += length; return; }
+ if (data < stb__barrier2) { stb__dout = stb__barrier+1; return; }
+ memcpy(stb__dout, data, length);
+ stb__dout += length;
+}
+
+static void sx_match(stb_uchar *data, stb_uint length)
+{
+ xx.match = data;
+ xx.pending_match = length;
+}
+
+static void sx_lit(stb_uchar *data, stb_uint length)
+{
+ xx.pending_lit = length;
+}
+
+static int stb_decompress_token_state(void)
+{
+ stb__uchar *i = xx.in_buffer;
+
+ if (*i >= 0x20) { // use fewer if's for cases that expand small
+ if (*i >= 0x80) sx_match(stb__dout-i[1]-1, i[0] - 0x80 + 1), i += 2;
+ else if (*i >= 0x40) sx_match(stb__dout-(stb__in2(0) - 0x4000 + 1), i[2]+1), i += 3;
+ else /* *i >= 0x20 */ sx_lit(i+1, i[0] - 0x20 + 1), i += 1;
+ } else { // more ifs for cases that expand large, since overhead is amortized
+ if (*i >= 0x18) sx_match(stb__dout-(stb__in3(0) - 0x180000 + 1), i[3]+1), i += 4;
+ else if (*i >= 0x10) sx_match(stb__dout-(stb__in3(0) - 0x100000 + 1), stb__in2(3)+1), i += 5;
+ else if (*i >= 0x08) sx_lit(i+2, stb__in2(0) - 0x0800 + 1), i += 2;
+ else if (*i == 0x07) sx_lit(i+3, stb__in2(1) + 1), i += 3;
+ else if (*i == 0x06) sx_match(stb__dout-(stb__in3(1)+1), i[4]+1), i += 5;
+ else if (*i == 0x04) sx_match(stb__dout-(stb__in3(1)+1), stb__in2(4)+1), i += 6;
+ else return 0;
+ }
+ xx.in_buffer = i;
+ return 1;
+}
+#endif
+
+
+
+//////////////////// compressor ///////////////////////
+
+static unsigned int stb_matchlen(stb_uchar *m1, stb_uchar *m2, stb_uint maxlen)
+{
+ stb_uint i;
+ for (i=0; i < maxlen; ++i)
+ if (m1[i] != m2[i]) return i;
+ return i;
+}
+
+// simple implementation that just takes the source data in a big block
+
+static stb_uchar *stb__out;
+static FILE *stb__outfile;
+static stb_uint stb__outbytes;
+
+static void stb__write(unsigned char v)
+{
+ fputc(v, stb__outfile);
+ ++stb__outbytes;
+}
+
+#define stb_out(v) (stb__out ? (void)(*stb__out++ = (stb_uchar) (v)) : stb__write((stb_uchar) (v)))
+
+static void stb_out2(stb_uint v)
+{
+ stb_out(v >> 8);
+ stb_out(v);
+}
+
+static void stb_out3(stb_uint v) { stb_out(v >> 16); stb_out(v >> 8); stb_out(v); }
+static void stb_out4(stb_uint v) { stb_out(v >> 24); stb_out(v >> 16);
+ stb_out(v >> 8 ); stb_out(v); }
+
+static void outliterals(stb_uchar *in, ptrdiff_t numlit)
+{
+ while (numlit > 65536) {
+ outliterals(in,65536);
+ in += 65536;
+ numlit -= 65536;
+ }
+
+ if (numlit == 0) ;
+ else if (numlit <= 32) stb_out (0x000020 + (stb_uint) numlit-1);
+ else if (numlit <= 2048) stb_out2(0x000800 + (stb_uint) numlit-1);
+ else /* numlit <= 65536) */ stb_out3(0x070000 + (stb_uint) numlit-1);
+
+ if (stb__out) {
+ memcpy(stb__out,in,numlit);
+ stb__out += numlit;
+ } else
+ fwrite(in, 1, numlit, stb__outfile);
+}
+
+static int stb__window = 0x40000; // 256K
+void stb_compress_window(int z)
+{
+ if (z >= 0x1000000) z = 0x1000000; // limit of implementation
+ if (z < 0x100) z = 0x100; // insanely small
+ stb__window = z;
+}
+
+static int stb_not_crap(int best, int dist)
+{
+ return ((best > 2 && dist <= 0x00100)
+ || (best > 5 && dist <= 0x04000)
+ || (best > 7 && dist <= 0x80000));
+}
+
+static stb_uint stb__hashsize = 32768;
+void stb_compress_hashsize(unsigned int y)
+{
+ unsigned int z = 1024;
+ while (z < y) z <<= 1;
+ stb__hashsize = z >> 2; // pass in bytes, store #pointers
+}
+
+// note that you can play with the hashing functions all you
+// want without needing to change the decompressor
+#define stb__hc(q,h,c) (((h) << 7) + ((h) >> 25) + q[c])
+#define stb__hc2(q,h,c,d) (((h) << 14) + ((h) >> 18) + (q[c] << 7) + q[d])
+#define stb__hc3(q,c,d,e) ((q[c] << 14) + (q[d] << 7) + q[e])
+
+static stb_uint32 stb__running_adler;
+
+static int stb_compress_chunk(stb_uchar *history,
+ stb_uchar *start,
+ stb_uchar *end,
+ int length,
+ int *pending_literals,
+ stb_uchar **chash,
+ stb_uint mask)
+{
+ int window = stb__window;
+ stb_uint match_max;
+ stb_uchar *lit_start = start - *pending_literals;
+ stb_uchar *q = start;
+
+ #define STB__SCRAMBLE(h) (((h) + ((h) >> 16)) & mask)
+
+ // stop short of the end so we don't scan off the end doing
+ // the hashing; this means we won't compress the last few bytes
+ // unless they were part of something longer
+ while (q < start+length && q+12 < end) {
+ int m;
+ stb_uint h1,h2,h3,h4, h;
+ stb_uchar *t;
+ int best = 2, dist=0;
+
+ if (q+65536 > end)
+ match_max = (stb_uint) (end-q);
+ else
+ match_max = 65536u;
+
+ #define stb__nc(b,d) ((d) <= window && ((b) > 9 || stb_not_crap(b,d)))
+
+ #define STB__TRY(t,p) /* avoid retrying a match we already tried */ \
+ if (p ? dist != (int) (q-t) : 1) \
+ if ((m = (int) stb_matchlen(t, q, match_max)) > best)\
+ if (stb__nc(m,(int) (q-(t)))) \
+ best = m, dist = (int) (q - (t))
+
+ // rather than search for all matches, only try 4 candidate locations,
+ // chosen based on 4 different hash functions of different lengths.
+ // this strategy is inspired by LZO; hashing is unrolled here using the
+ // 'hc' macro
+ h = stb__hc3(q,0, 1, 2); h1 = STB__SCRAMBLE(h);
+ t = chash[h1]; if (t) STB__TRY(t,0);
+ h = stb__hc2(q,h, 3, 4); h2 = STB__SCRAMBLE(h);
+ h = stb__hc2(q,h, 5, 6); t = chash[h2]; if (t) STB__TRY(t,1);
+ h = stb__hc2(q,h, 7, 8); h3 = STB__SCRAMBLE(h);
+ h = stb__hc2(q,h, 9,10); t = chash[h3]; if (t) STB__TRY(t,1);
+ h = stb__hc2(q,h,11,12); h4 = STB__SCRAMBLE(h);
+ t = chash[h4]; if (t) STB__TRY(t,1);
+
+ // because we use a shared hash table, can only update it
+ // _after_ we've probed all of them
+ chash[h1] = chash[h2] = chash[h3] = chash[h4] = q;
+
+ if (best > 2)
+ assert(dist > 0);
+
+ // see if our best match qualifies
+ if (best < 3) { // fast path literals
+ ++q;
+ } else if (best > 2 && best <= 0x80 && dist <= 0x100) {
+ outliterals(lit_start, q-lit_start); lit_start = (q += best);
+ stb_out(0x80 + best-1);
+ stb_out(dist-1);
+ } else if (best > 5 && best <= 0x100 && dist <= 0x4000) {
+ outliterals(lit_start, q-lit_start); lit_start = (q += best);
+ stb_out2(0x4000 + dist-1);
+ stb_out(best-1);
+ } else if (best > 7 && best <= 0x100 && dist <= 0x80000) {
+ outliterals(lit_start, q-lit_start); lit_start = (q += best);
+ stb_out3(0x180000 + dist-1);
+ stb_out(best-1);
+ } else if (best > 8 && best <= 0x10000 && dist <= 0x80000) {
+ outliterals(lit_start, q-lit_start); lit_start = (q += best);
+ stb_out3(0x100000 + dist-1);
+ stb_out2(best-1);
+ } else if (best > 9 && dist <= 0x1000000) {
+ if (best > 65536) best = 65536;
+ outliterals(lit_start, q-lit_start); lit_start = (q += best);
+ if (best <= 0x100) {
+ stb_out(0x06);
+ stb_out3(dist-1);
+ stb_out(best-1);
+ } else {
+ stb_out(0x04);
+ stb_out3(dist-1);
+ stb_out2(best-1);
+ }
+ } else { // fallback literals if no match was a balanced tradeoff
+ ++q;
+ }
+ }
+
+ // if we didn't get all the way, add the rest to literals
+ if (q-start < length)
+ q = start+length;
+
+ // the literals are everything from lit_start to q
+ *pending_literals = (int) (q - lit_start);
+
+ stb__running_adler = stb_adler32(stb__running_adler, start, (int) (q - start));
+ return (int) (q - start);
+}
+
+static int stb_compress_inner(stb_uchar *input, stb_uint length)
+{
+ int literals = 0;
+ stb_uint len,i;
+
+ stb_uchar **chash;
+ chash = (stb_uchar**) malloc(stb__hashsize * sizeof(stb_uchar*));
+ if (chash == NULL) return 0; // failure
+ for (i=0; i < stb__hashsize; ++i)
+ chash[i] = NULL;
+
+ // stream signature
+ stb_out(0x57); stb_out(0xbc);
+ stb_out2(0);
+
+ stb_out4(0); // 64-bit length requires 32-bit leading 0
+ stb_out4(length);
+ stb_out4(stb__window);
+
+ stb__running_adler = 1;
+
+ len = stb_compress_chunk(input, input, input+length, length, &literals, chash, stb__hashsize-1);
+ assert(len == length);
+
+ outliterals(input+length - literals, literals);
+
+ free(chash);
+
+ stb_out2(0x05fa); // end opcode
+
+ stb_out4(stb__running_adler);
+
+ return 1; // success
+}
+
+stb_uint stb_compress(stb_uchar *out, stb_uchar *input, stb_uint length)
+{
+ stb__out = out;
+ stb__outfile = NULL;
+
+ stb_compress_inner(input, length);
+
+ return (stb_uint) (stb__out - out);
+}
+
+int stb_compress_tofile(char *filename, char *input, unsigned int length)
+{
+ //int maxlen = length + 512 + (length >> 2); // total guess
+ //char *buffer = (char *) malloc(maxlen);
+ //int blen = stb_compress((stb_uchar*)buffer, (stb_uchar*)input, length);
+
+ stb__out = NULL;
+ stb__outfile = stb_p_fopen(filename, "wb");
+ if (!stb__outfile) return 0;
+
+ stb__outbytes = 0;
+
+ if (!stb_compress_inner((stb_uchar*)input, length))
+ return 0;
+
+ fclose(stb__outfile);
+
+ return stb__outbytes;
+}
+
+int stb_compress_intofile(FILE *f, char *input, unsigned int length)
+{
+ //int maxlen = length + 512 + (length >> 2); // total guess
+ //char *buffer = (char*)malloc(maxlen);
+ //int blen = stb_compress((stb_uchar*)buffer, (stb_uchar*)input, length);
+
+ stb__out = NULL;
+ stb__outfile = f;
+ if (!stb__outfile) return 0;
+
+ stb__outbytes = 0;
+
+ if (!stb_compress_inner((stb_uchar*)input, length))
+ return 0;
+
+ return stb__outbytes;
+}
+
+////////////////////// streaming I/O version /////////////////////
+
+
+static size_t stb_out_backpatch_id(void)
+{
+ if (stb__out)
+ return (size_t) stb__out;
+ else
+ return ftell(stb__outfile);
+}
+
+static void stb_out_backpatch(size_t id, stb_uint value)
+{
+ stb_uchar data[4] = { (stb_uchar)(value >> 24), (stb_uchar)(value >> 16), (stb_uchar)(value >> 8), (stb_uchar)(value) };
+ if (stb__out) {
+ memcpy((void *) id, data, 4);
+ } else {
+ stb_uint where = ftell(stb__outfile);
+ fseek(stb__outfile, (long) id, SEEK_SET);
+ fwrite(data, 4, 1, stb__outfile);
+ fseek(stb__outfile, where, SEEK_SET);
+ }
+}
+
+// ok, the wraparound buffer was a total failure. let's instead
+// use a copying-in-place buffer, which lets us share the code.
+// This is way less efficient but it'll do for now.
+
+static struct
+{
+ stb_uchar *buffer;
+ int size; // physical size of buffer in bytes
+
+ int valid; // amount of valid data in bytes
+ int start; // bytes of data already output
+
+ int window;
+ int fsize;
+
+ int pending_literals; // bytes not-quite output but counted in start
+ int length_id;
+
+ stb_uint total_bytes;
+
+ stb_uchar **chash;
+ stb_uint hashmask;
+} xtb;
+
+static int stb_compress_streaming_start(void)
+{
+ stb_uint i;
+ xtb.size = stb__window * 3;
+ xtb.buffer = (stb_uchar*)malloc(xtb.size);
+ if (!xtb.buffer) return 0;
+
+ xtb.chash = (stb_uchar**)malloc(sizeof(*xtb.chash) * stb__hashsize);
+ if (!xtb.chash) {
+ free(xtb.buffer);
+ return 0;
+ }
+
+ for (i=0; i < stb__hashsize; ++i)
+ xtb.chash[i] = NULL;
+
+ xtb.hashmask = stb__hashsize-1;
+
+ xtb.valid = 0;
+ xtb.start = 0;
+ xtb.window = stb__window;
+ xtb.fsize = stb__window;
+ xtb.pending_literals = 0;
+ xtb.total_bytes = 0;
+
+ // stream signature
+ stb_out(0x57); stb_out(0xbc); stb_out2(0);
+
+ stb_out4(0); // 64-bit length requires 32-bit leading 0
+
+ xtb.length_id = (int) stb_out_backpatch_id();
+ stb_out4(0); // we don't know the output length yet
+
+ stb_out4(stb__window);
+
+ stb__running_adler = 1;
+
+ return 1;
+}
+
+static int stb_compress_streaming_end(void)
+{
+ // flush out any remaining data
+ stb_compress_chunk(xtb.buffer, xtb.buffer+xtb.start, xtb.buffer+xtb.valid,
+ xtb.valid-xtb.start, &xtb.pending_literals, xtb.chash, xtb.hashmask);
+
+ // write out pending literals
+ outliterals(xtb.buffer + xtb.valid - xtb.pending_literals, xtb.pending_literals);
+
+ stb_out2(0x05fa); // end opcode
+ stb_out4(stb__running_adler);
+
+ stb_out_backpatch(xtb.length_id, xtb.total_bytes);
+
+ free(xtb.buffer);
+ free(xtb.chash);
+ return 1;
+}
+
+void stb_write(char *data, int data_len)
+{
+ stb_uint i;
+
+ // @TODO: fast path for filling the buffer and doing nothing else
+ // if (xtb.valid + data_len < xtb.size)
+
+ xtb.total_bytes += data_len;
+
+ while (data_len) {
+ // fill buffer
+ if (xtb.valid < xtb.size) {
+ int amt = xtb.size - xtb.valid;
+ if (data_len < amt) amt = data_len;
+ memcpy(xtb.buffer + xtb.valid, data, amt);
+ data_len -= amt;
+ data += amt;
+ xtb.valid += amt;
+ }
+ if (xtb.valid < xtb.size)
+ return;
+
+ // at this point, the buffer is full
+
+ // if we can process some data, go for it; make sure
+ // we leave an 'fsize's worth of data, though
+ if (xtb.start + xtb.fsize < xtb.valid) {
+ int amount = (xtb.valid - xtb.fsize) - xtb.start;
+ int n;
+ assert(amount > 0);
+ n = stb_compress_chunk(xtb.buffer, xtb.buffer + xtb.start, xtb.buffer + xtb.valid,
+ amount, &xtb.pending_literals, xtb.chash, xtb.hashmask);
+ xtb.start += n;
+ }
+
+ assert(xtb.start + xtb.fsize >= xtb.valid);
+ // at this point, our future size is too small, so we
+ // need to flush some history. we, in fact, flush exactly
+ // one window's worth of history
+
+ {
+ int flush = xtb.window;
+ assert(xtb.start >= flush);
+ assert(xtb.valid >= flush);
+
+ // if 'pending literals' extends back into the shift region,
+ // write them out
+ if (xtb.start - xtb.pending_literals < flush) {
+ outliterals(xtb.buffer + xtb.start - xtb.pending_literals, xtb.pending_literals);
+ xtb.pending_literals = 0;
+ }
+
+ // now shift the window
+ memmove(xtb.buffer, xtb.buffer + flush, xtb.valid - flush);
+ xtb.start -= flush;
+ xtb.valid -= flush;
+
+ for (i=0; i <= xtb.hashmask; ++i)
+ if (xtb.chash[i] < xtb.buffer + flush)
+ xtb.chash[i] = NULL;
+ else
+ xtb.chash[i] -= flush;
+ }
+ // and now that we've made room for more data, go back to the top
+ }
+}
+
+int stb_compress_stream_start(FILE *f)
+{
+ stb__out = NULL;
+ stb__outfile = f;
+
+ if (f == NULL)
+ return 0;
+
+ if (!stb_compress_streaming_start())
+ return 0;
+
+ return 1;
+}
+
+void stb_compress_stream_end(int close)
+{
+ stb_compress_streaming_end();
+ if (close && stb__outfile) {
+ fclose(stb__outfile);
+ }
+}
+
+#endif // STB_DEFINE
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// File abstraction... tired of not having this... we can write
+// compressors to be layers over these that auto-close their children.
+
+
+typedef struct stbfile
+{
+ int (*getbyte)(struct stbfile *); // -1 on EOF
+ unsigned int (*getdata)(struct stbfile *, void *block, unsigned int len);
+
+ int (*putbyte)(struct stbfile *, int byte);
+ unsigned int (*putdata)(struct stbfile *, void *block, unsigned int len);
+
+ unsigned int (*size)(struct stbfile *);
+
+ unsigned int (*tell)(struct stbfile *);
+ void (*backpatch)(struct stbfile *, unsigned int tell, void *block, unsigned int len);
+
+ void (*close)(struct stbfile *);
+
+ FILE *f; // file to fread/fwrite
+ unsigned char *buffer; // input/output buffer
+ unsigned char *indata, *inend; // input buffer
+ union {
+ int various;
+ void *ptr;
+ };
+} stbfile;
+
+STB_EXTERN unsigned int stb_getc(stbfile *f); // read
+STB_EXTERN int stb_putc(stbfile *f, int ch); // write
+STB_EXTERN unsigned int stb_getdata(stbfile *f, void *buffer, unsigned int len); // read
+STB_EXTERN unsigned int stb_putdata(stbfile *f, void *buffer, unsigned int len); // write
+STB_EXTERN unsigned int stb_tell(stbfile *f); // read
+STB_EXTERN unsigned int stb_size(stbfile *f); // read/write
+STB_EXTERN void stb_backpatch(stbfile *f, unsigned int tell, void *buffer, unsigned int len); // write
+
+#ifdef STB_DEFINE
+
+unsigned int stb_getc(stbfile *f) { return f->getbyte(f); }
+int stb_putc(stbfile *f, int ch) { return f->putbyte(f, ch); }
+
+unsigned int stb_getdata(stbfile *f, void *buffer, unsigned int len)
+{
+ return f->getdata(f, buffer, len);
+}
+unsigned int stb_putdata(stbfile *f, void *buffer, unsigned int len)
+{
+ return f->putdata(f, buffer, len);
+}
+void stb_close(stbfile *f)
+{
+ f->close(f);
+ free(f);
+}
+unsigned int stb_tell(stbfile *f) { return f->tell(f); }
+unsigned int stb_size(stbfile *f) { return f->size(f); }
+void stb_backpatch(stbfile *f, unsigned int tell, void *buffer, unsigned int len)
+{
+ f->backpatch(f,tell,buffer,len);
+}
+
+// FILE * implementation
+static int stb__fgetbyte(stbfile *f) { return fgetc(f->f); }
+static int stb__fputbyte(stbfile *f, int ch) { return fputc(ch, f->f)==0; }
+static unsigned int stb__fgetdata(stbfile *f, void *buffer, unsigned int len) { return (unsigned int) fread(buffer,1,len,f->f); }
+static unsigned int stb__fputdata(stbfile *f, void *buffer, unsigned int len) { return (unsigned int) fwrite(buffer,1,len,f->f); }
+static unsigned int stb__fsize(stbfile *f) { return (unsigned int) stb_filelen(f->f); }
+static unsigned int stb__ftell(stbfile *f) { return (unsigned int) ftell(f->f); }
+static void stb__fbackpatch(stbfile *f, unsigned int where, void *buffer, unsigned int len)
+{
+ fseek(f->f, where, SEEK_SET);
+ fwrite(buffer, 1, len, f->f);
+ fseek(f->f, 0, SEEK_END);
+}
+static void stb__fclose(stbfile *f) { fclose(f->f); }
+
+stbfile *stb_openf(FILE *f)
+{
+ stbfile m = { stb__fgetbyte, stb__fgetdata,
+ stb__fputbyte, stb__fputdata,
+ stb__fsize, stb__ftell, stb__fbackpatch, stb__fclose,
+ 0,0,0, };
+ stbfile *z = (stbfile *) malloc(sizeof(*z));
+ if (z) {
+ *z = m;
+ z->f = f;
+ }
+ return z;
+}
+
+static int stb__nogetbyte(stbfile *f) { assert(0); return -1; }
+static unsigned int stb__nogetdata(stbfile *f, void *buffer, unsigned int len) { assert(0); return 0; }
+static int stb__noputbyte(stbfile *f, int ch) { assert(0); return 0; }
+static unsigned int stb__noputdata(stbfile *f, void *buffer, unsigned int len) { assert(0); return 0; }
+static void stb__nobackpatch(stbfile *f, unsigned int where, void *buffer, unsigned int len) { assert(0); }
+
+static int stb__bgetbyte(stbfile *s)
+{
+ if (s->indata < s->inend)
+ return *s->indata++;
+ else
+ return -1;
+}
+
+static unsigned int stb__bgetdata(stbfile *s, void *buffer, unsigned int len)
+{
+ if (s->indata + len > s->inend)
+ len = (unsigned int) (s->inend - s->indata);
+ memcpy(buffer, s->indata, len);
+ s->indata += len;
+ return len;
+}
+static unsigned int stb__bsize(stbfile *s) { return (unsigned int) (s->inend - s->buffer); }
+static unsigned int stb__btell(stbfile *s) { return (unsigned int) (s->indata - s->buffer); }
+
+static void stb__bclose(stbfile *s)
+{
+ if (s->various)
+ free(s->buffer);
+}
+
+stbfile *stb_open_inbuffer(void *buffer, unsigned int len)
+{
+ stbfile m = { stb__bgetbyte, stb__bgetdata,
+ stb__noputbyte, stb__noputdata,
+ stb__bsize, stb__btell, stb__nobackpatch, stb__bclose };
+ stbfile *z = (stbfile *) malloc(sizeof(*z));
+ if (z) {
+ *z = m;
+ z->buffer = (unsigned char *) buffer;
+ z->indata = z->buffer;
+ z->inend = z->indata + len;
+ }
+ return z;
+}
+
+stbfile *stb_open_inbuffer_free(void *buffer, unsigned int len)
+{
+ stbfile *z = stb_open_inbuffer(buffer, len);
+ if (z)
+ z->various = 1; // free
+ return z;
+}
+
+#ifndef STB_VERSION
+// if we've been cut-and-pasted elsewhere, you get a limited
+// version of stb_open, without the 'k' flag and utf8 support
+static void stb__fclose2(stbfile *f)
+{
+ fclose(f->f);
+}
+
+stbfile *stb_open(char *filename, char *mode)
+{
+ FILE *f = stb_p_fopen(filename, mode);
+ stbfile *s;
+ if (f == NULL) return NULL;
+ s = stb_openf(f);
+ if (s)
+ s->close = stb__fclose2;
+ return s;
+}
+#else
+// the full version depends on some code in stb.h; this
+// also includes the memory buffer output format implemented with stb_arr
+static void stb__fclose2(stbfile *f)
+{
+ stb_fclose(f->f, f->various);
+}
+
+stbfile *stb_open(char *filename, char *mode)
+{
+ FILE *f = stb_fopen(filename, mode[0] == 'k' ? mode+1 : mode);
+ stbfile *s;
+ if (f == NULL) return NULL;
+ s = stb_openf(f);
+ if (s) {
+ s->close = stb__fclose2;
+ s->various = mode[0] == 'k' ? stb_keep_if_different : stb_keep_yes;
+ }
+ return s;
+}
+
+static int stb__aputbyte(stbfile *f, int ch)
+{
+ stb_arr_push(f->buffer, ch);
+ return 1;
+}
+static unsigned int stb__aputdata(stbfile *f, void *data, unsigned int len)
+{
+ memcpy(stb_arr_addn(f->buffer, (int) len), data, len);
+ return len;
+}
+static unsigned int stb__asize(stbfile *f) { return stb_arr_len(f->buffer); }
+static void stb__abackpatch(stbfile *f, unsigned int where, void *data, unsigned int len)
+{
+ memcpy(f->buffer+where, data, len);
+}
+static void stb__aclose(stbfile *f)
+{
+ *(unsigned char **) f->ptr = f->buffer;
+}
+
+stbfile *stb_open_outbuffer(unsigned char **update_on_close)
+{
+ stbfile m = { stb__nogetbyte, stb__nogetdata,
+ stb__aputbyte, stb__aputdata,
+ stb__asize, stb__asize, stb__abackpatch, stb__aclose };
+ stbfile *z = (stbfile *) malloc(sizeof(*z));
+ if (z) {
+ z->ptr = update_on_close;
+ *z = m;
+ }
+ return z;
+}
+#endif
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Arithmetic coder... based on cbloom's notes on the subject, should be
+// less code than a huffman code.
+
+typedef struct
+{
+ unsigned int range_low;
+ unsigned int range_high;
+ unsigned int code, range; // decode
+ int buffered_u8;
+ int pending_ffs;
+ stbfile *output;
+} stb_arith;
+
+STB_EXTERN void stb_arith_init_encode(stb_arith *a, stbfile *out);
+STB_EXTERN void stb_arith_init_decode(stb_arith *a, stbfile *in);
+STB_EXTERN stbfile *stb_arith_encode_close(stb_arith *a);
+STB_EXTERN stbfile *stb_arith_decode_close(stb_arith *a);
+
+STB_EXTERN void stb_arith_encode(stb_arith *a, unsigned int totalfreq, unsigned int freq, unsigned int cumfreq);
+STB_EXTERN void stb_arith_encode_log2(stb_arith *a, unsigned int totalfreq2, unsigned int freq, unsigned int cumfreq);
+STB_EXTERN unsigned int stb_arith_decode_value(stb_arith *a, unsigned int totalfreq);
+STB_EXTERN void stb_arith_decode_advance(stb_arith *a, unsigned int totalfreq, unsigned int freq, unsigned int cumfreq);
+STB_EXTERN unsigned int stb_arith_decode_value_log2(stb_arith *a, unsigned int totalfreq2);
+STB_EXTERN void stb_arith_decode_advance_log2(stb_arith *a, unsigned int totalfreq2, unsigned int freq, unsigned int cumfreq);
+
+STB_EXTERN void stb_arith_encode_byte(stb_arith *a, int byte);
+STB_EXTERN int stb_arith_decode_byte(stb_arith *a);
+
+// this is a memory-inefficient way of doing things, but it's
+// fast(?) and simple
+typedef struct
+{
+ unsigned short cumfreq;
+ unsigned short samples;
+} stb_arith_symstate_item;
+
+typedef struct
+{
+ int num_sym;
+ unsigned int pow2;
+ int countdown;
+ stb_arith_symstate_item data[1];
+} stb_arith_symstate;
+
+#ifdef STB_DEFINE
+void stb_arith_init_encode(stb_arith *a, stbfile *out)
+{
+ a->range_low = 0;
+ a->range_high = 0xffffffff;
+ a->pending_ffs = -1; // means no buffered character currently, to speed up normal case
+ a->output = out;
+}
+
+static void stb__arith_carry(stb_arith *a)
+{
+ int i;
+ assert(a->pending_ffs != -1); // can't carry with no data
+ stb_putc(a->output, a->buffered_u8);
+ for (i=0; i < a->pending_ffs; ++i)
+ stb_putc(a->output, 0);
+}
+
+static void stb__arith_putbyte(stb_arith *a, int byte)
+{
+ if (a->pending_ffs) {
+ if (a->pending_ffs == -1) { // means no buffered data; encoded for fast path efficiency
+ if (byte == 0xff)
+ stb_putc(a->output, byte); // just write it immediately
+ else {
+ a->buffered_u8 = byte;
+ a->pending_ffs = 0;
+ }
+ } else if (byte == 0xff) {
+ ++a->pending_ffs;
+ } else {
+ int i;
+ stb_putc(a->output, a->buffered_u8);
+ for (i=0; i < a->pending_ffs; ++i)
+ stb_putc(a->output, 0xff);
+ }
+ } else if (byte == 0xff) {
+ ++a->pending_ffs;
+ } else {
+ // fast path
+ stb_putc(a->output, a->buffered_u8);
+ a->buffered_u8 = byte;
+ }
+}
+
+static void stb__arith_flush(stb_arith *a)
+{
+ if (a->pending_ffs >= 0) {
+ int i;
+ stb_putc(a->output, a->buffered_u8);
+ for (i=0; i < a->pending_ffs; ++i)
+ stb_putc(a->output, 0xff);
+ }
+}
+
+static void stb__renorm_encoder(stb_arith *a)
+{
+ stb__arith_putbyte(a, a->range_low >> 24);
+ a->range_low <<= 8;
+ a->range_high = (a->range_high << 8) | 0xff;
+}
+
+static void stb__renorm_decoder(stb_arith *a)
+{
+ int c = stb_getc(a->output);
+ a->code = (a->code << 8) + (c >= 0 ? c : 0); // if EOF, insert 0
+}
+
+void stb_arith_encode(stb_arith *a, unsigned int totalfreq, unsigned int freq, unsigned int cumfreq)
+{
+ unsigned int range = a->range_high - a->range_low;
+ unsigned int old = a->range_low;
+ range /= totalfreq;
+ a->range_low += range * cumfreq;
+ a->range_high = a->range_low + range*freq;
+ if (a->range_low < old)
+ stb__arith_carry(a);
+ while (a->range_high - a->range_low < 0x1000000)
+ stb__renorm_encoder(a);
+}
+
+void stb_arith_encode_log2(stb_arith *a, unsigned int totalfreq2, unsigned int freq, unsigned int cumfreq)
+{
+ unsigned int range = a->range_high - a->range_low;
+ unsigned int old = a->range_low;
+ range >>= totalfreq2;
+ a->range_low += range * cumfreq;
+ a->range_high = a->range_low + range*freq;
+ if (a->range_low < old)
+ stb__arith_carry(a);
+ while (a->range_high - a->range_low < 0x1000000)
+ stb__renorm_encoder(a);
+}
+
+unsigned int stb_arith_decode_value(stb_arith *a, unsigned int totalfreq)
+{
+ unsigned int freqsize = a->range / totalfreq;
+ unsigned int z = a->code / freqsize;
+ return z >= totalfreq ? totalfreq-1 : z;
+}
+
+void stb_arith_decode_advance(stb_arith *a, unsigned int totalfreq, unsigned int freq, unsigned int cumfreq)
+{
+ unsigned int freqsize = a->range / totalfreq; // @OPTIMIZE, share with above divide somehow?
+ a->code -= freqsize * cumfreq;
+ a->range = freqsize * freq;
+ while (a->range < 0x1000000)
+ stb__renorm_decoder(a);
+}
+
+unsigned int stb_arith_decode_value_log2(stb_arith *a, unsigned int totalfreq2)
+{
+ unsigned int freqsize = a->range >> totalfreq2;
+ unsigned int z = a->code / freqsize;
+ return z >= (1U<range >> totalfreq2;
+ a->code -= freqsize * cumfreq;
+ a->range = freqsize * freq;
+ while (a->range < 0x1000000)
+ stb__renorm_decoder(a);
+}
+
+stbfile *stb_arith_encode_close(stb_arith *a)
+{
+ // put exactly as many bytes as we'll read, so we can turn on/off arithmetic coding in a stream
+ stb__arith_putbyte(a, a->range_low >> 24);
+ stb__arith_putbyte(a, a->range_low >> 16);
+ stb__arith_putbyte(a, a->range_low >> 8);
+ stb__arith_putbyte(a, a->range_low >> 0);
+ stb__arith_flush(a);
+ return a->output;
+}
+
+stbfile *stb_arith_decode_close(stb_arith *a)
+{
+ return a->output;
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Threads
+//
+
+#ifndef _WIN32
+#ifdef STB_THREADS
+#error "threads not implemented except for Windows"
+#endif
+#endif
+
+// call this function to free any global variables for memory testing
+STB_EXTERN void stb_thread_cleanup(void);
+
+typedef void * (*stb_thread_func)(void *);
+
+// do not rely on these types, this is an implementation detail.
+// compare against STB_THREAD_NULL and ST_SEMAPHORE_NULL
+typedef void *stb_thread;
+typedef void *stb_semaphore;
+typedef void *stb_mutex;
+typedef struct stb__sync *stb_sync;
+
+#define STB_SEMAPHORE_NULL NULL
+#define STB_THREAD_NULL NULL
+#define STB_MUTEX_NULL NULL
+#define STB_SYNC_NULL NULL
+
+// get the number of processors (limited to those in the affinity mask for this process).
+STB_EXTERN int stb_processor_count(void);
+// force to run on a single core -- needed for RDTSC to work, e.g. for iprof
+STB_EXTERN void stb_force_uniprocessor(void);
+
+// stb_work functions: queue up work to be done by some worker threads
+
+// set number of threads to serve the queue; you can change this on the fly,
+// but if you decrease it, it won't decrease until things currently on the
+// queue are finished
+STB_EXTERN void stb_work_numthreads(int n);
+// set maximum number of units in the queue; you can only set this BEFORE running any work functions
+STB_EXTERN int stb_work_maxunits(int n);
+// enqueue some work to be done (can do this from any thread, or even from a piece of work);
+// return value of f is stored in *return_code if non-NULL
+STB_EXTERN int stb_work(stb_thread_func f, void *d, volatile void **return_code);
+// as above, but stb_sync_reach is called on 'rel' after work is complete
+STB_EXTERN int stb_work_reach(stb_thread_func f, void *d, volatile void **return_code, stb_sync rel);
+
+
+// necessary to call this when using volatile to order writes/reads
+STB_EXTERN void stb_barrier(void);
+
+// support for independent queues with their own threads
+
+typedef struct stb__workqueue stb_workqueue;
+
+STB_EXTERN stb_workqueue*stb_workq_new(int numthreads, int max_units);
+STB_EXTERN stb_workqueue*stb_workq_new_flags(int numthreads, int max_units, int no_add_mutex, int no_remove_mutex);
+STB_EXTERN void stb_workq_delete(stb_workqueue *q);
+STB_EXTERN void stb_workq_numthreads(stb_workqueue *q, int n);
+STB_EXTERN int stb_workq(stb_workqueue *q, stb_thread_func f, void *d, volatile void **return_code);
+STB_EXTERN int stb_workq_reach(stb_workqueue *q, stb_thread_func f, void *d, volatile void **return_code, stb_sync rel);
+STB_EXTERN int stb_workq_length(stb_workqueue *q);
+
+STB_EXTERN stb_thread stb_create_thread (stb_thread_func f, void *d);
+STB_EXTERN stb_thread stb_create_thread2(stb_thread_func f, void *d, volatile void **return_code, stb_semaphore rel);
+STB_EXTERN void stb_destroy_thread(stb_thread t);
+
+STB_EXTERN stb_semaphore stb_sem_new(int max_val);
+STB_EXTERN stb_semaphore stb_sem_new_extra(int max_val, int start_val);
+STB_EXTERN void stb_sem_delete (stb_semaphore s);
+STB_EXTERN void stb_sem_waitfor(stb_semaphore s);
+STB_EXTERN void stb_sem_release(stb_semaphore s);
+
+STB_EXTERN stb_mutex stb_mutex_new(void);
+STB_EXTERN void stb_mutex_delete(stb_mutex m);
+STB_EXTERN void stb_mutex_begin(stb_mutex m);
+STB_EXTERN void stb_mutex_end(stb_mutex m);
+
+STB_EXTERN stb_sync stb_sync_new(void);
+STB_EXTERN void stb_sync_delete(stb_sync s);
+STB_EXTERN int stb_sync_set_target(stb_sync s, int count);
+STB_EXTERN void stb_sync_reach_and_wait(stb_sync s); // wait for 'target' reachers
+STB_EXTERN int stb_sync_reach(stb_sync s);
+
+typedef struct stb__threadqueue stb_threadqueue;
+#define STB_THREADQ_DYNAMIC 0
+STB_EXTERN stb_threadqueue *stb_threadq_new(int item_size, int num_items, int many_add, int many_remove);
+STB_EXTERN void stb_threadq_delete(stb_threadqueue *tq);
+STB_EXTERN int stb_threadq_get(stb_threadqueue *tq, void *output);
+STB_EXTERN void stb_threadq_get_block(stb_threadqueue *tq, void *output);
+STB_EXTERN int stb_threadq_add(stb_threadqueue *tq, void *input);
+// can return FALSE if STB_THREADQ_DYNAMIC and attempt to grow fails
+STB_EXTERN int stb_threadq_add_block(stb_threadqueue *tq, void *input);
+
+#ifdef STB_THREADS
+#ifdef STB_DEFINE
+
+typedef struct
+{
+ stb_thread_func f;
+ void *d;
+ volatile void **return_val;
+ stb_semaphore sem;
+} stb__thread;
+
+// this is initialized along all possible paths to create threads, therefore
+// it's always initialized before any other threads are create, therefore
+// it's free of races AS LONG AS you only create threads through stb_*
+static stb_mutex stb__threadmutex, stb__workmutex;
+
+static void stb__threadmutex_init(void)
+{
+ if (stb__threadmutex == STB_SEMAPHORE_NULL) {
+ stb__threadmutex = stb_mutex_new();
+ stb__workmutex = stb_mutex_new();
+ }
+}
+
+#ifdef STB_THREAD_TEST
+volatile float stb__t1=1, stb__t2;
+
+static void stb__wait(int n)
+{
+ float z = 0;
+ int i;
+ for (i=0; i < n; ++i)
+ z += 1 / (stb__t1+i);
+ stb__t2 = z;
+}
+#else
+#define stb__wait(x)
+#endif
+
+#ifdef _WIN32
+
+// avoid including windows.h -- note that our definitions aren't
+// exactly the same (we don't define the security descriptor struct)
+// so if you want to include windows.h, make sure you do it first.
+#include
+
+#ifndef _WINDOWS_ // check windows.h guard
+#define STB__IMPORT STB_EXTERN __declspec(dllimport)
+#define STB__DW unsigned long
+
+STB__IMPORT int __stdcall TerminateThread(void *, STB__DW);
+STB__IMPORT void * __stdcall CreateSemaphoreA(void *sec, long,long,char*);
+STB__IMPORT int __stdcall CloseHandle(void *);
+STB__IMPORT STB__DW __stdcall WaitForSingleObject(void *, STB__DW);
+STB__IMPORT int __stdcall ReleaseSemaphore(void *, long, long *);
+STB__IMPORT void __stdcall Sleep(STB__DW);
+#endif
+
+// necessary to call this when using volatile to order writes/reads
+void stb_barrier(void)
+{
+ #ifdef MemoryBarrier
+ MemoryBarrier();
+ #else
+ long temp;
+ __asm xchg temp,eax;
+ #endif
+}
+
+static void stb__thread_run(void *t)
+{
+ void *res;
+ stb__thread info = * (stb__thread *) t;
+ free(t);
+ res = info.f(info.d);
+ if (info.return_val)
+ *info.return_val = res;
+ if (info.sem != STB_SEMAPHORE_NULL)
+ stb_sem_release(info.sem);
+}
+
+static stb_thread stb_create_thread_raw(stb_thread_func f, void *d, volatile void **return_code, stb_semaphore rel)
+{
+#ifdef _MT
+#if defined(STB_FASTMALLOC) && !defined(STB_FASTMALLOC_ITS_OKAY_I_ONLY_MALLOC_IN_ONE_THREAD)
+ stb_fatal("Error! Cannot use STB_FASTMALLOC with threads.\n");
+ return STB_THREAD_NULL;
+#else
+ unsigned long id;
+ stb__thread *data = (stb__thread *) malloc(sizeof(*data));
+ if (!data) return NULL;
+ stb__threadmutex_init();
+ data->f = f;
+ data->d = d;
+ data->return_val = return_code;
+ data->sem = rel;
+ id = _beginthread(stb__thread_run, 0, data);
+ if (id == -1) return NULL;
+ return (void *) id;
+#endif
+#else
+#ifdef STB_NO_STB_STRINGS
+ stb_fatal("Invalid compilation");
+#else
+ stb_fatal("Must compile mult-threaded to use stb_thread/stb_work.");
+#endif
+ return NULL;
+#endif
+}
+
+// trivial win32 wrappers
+void stb_destroy_thread(stb_thread t) { TerminateThread(t,0); }
+stb_semaphore stb_sem_new(int maxv) {return CreateSemaphoreA(NULL,0,maxv,NULL); }
+stb_semaphore stb_sem_new_extra(int maxv,int start){return CreateSemaphoreA(NULL,start,maxv,NULL); }
+void stb_sem_delete(stb_semaphore s) { if (s != NULL) CloseHandle(s); }
+void stb_sem_waitfor(stb_semaphore s) { WaitForSingleObject(s, 0xffffffff); } // INFINITE
+void stb_sem_release(stb_semaphore s) { ReleaseSemaphore(s,1,NULL); }
+static void stb__thread_sleep(int ms) { Sleep(ms); }
+
+#ifndef _WINDOWS_
+STB__IMPORT int __stdcall GetProcessAffinityMask(void *, STB__DW *, STB__DW *);
+STB__IMPORT void * __stdcall GetCurrentProcess(void);
+STB__IMPORT int __stdcall SetProcessAffinityMask(void *, STB__DW);
+#endif
+
+int stb_processor_count(void)
+{
+ unsigned long proc,sys;
+ GetProcessAffinityMask(GetCurrentProcess(), &proc, &sys);
+ return stb_bitcount(proc);
+}
+
+void stb_force_uniprocessor(void)
+{
+ unsigned long proc,sys;
+ GetProcessAffinityMask(GetCurrentProcess(), &proc, &sys);
+ if (stb_bitcount(proc) > 1) {
+ int z;
+ for (z=0; z < 32; ++z)
+ if (proc & (1 << z))
+ break;
+ if (z < 32) {
+ proc = 1 << z;
+ SetProcessAffinityMask(GetCurrentProcess(), proc);
+ }
+ }
+}
+
+#ifdef _WINDOWS_
+#define STB_MUTEX_NATIVE
+void *stb_mutex_new(void)
+{
+ CRITICAL_SECTION *p = (CRITICAL_SECTION *) malloc(sizeof(*p));
+ if (p)
+#if _WIN32_WINNT >= 0x0500
+ InitializeCriticalSectionAndSpinCount(p, 500);
+#else
+ InitializeCriticalSection(p);
+#endif
+ return p;
+}
+
+void stb_mutex_delete(void *p)
+{
+ if (p) {
+ DeleteCriticalSection((CRITICAL_SECTION *) p);
+ free(p);
+ }
+}
+
+void stb_mutex_begin(void *p)
+{
+ stb__wait(500);
+ if (p)
+ EnterCriticalSection((CRITICAL_SECTION *) p);
+}
+
+void stb_mutex_end(void *p)
+{
+ if (p)
+ LeaveCriticalSection((CRITICAL_SECTION *) p);
+ stb__wait(500);
+}
+#endif // _WINDOWS_
+
+#if 0
+// for future reference,
+// InterlockedCompareExchange for x86:
+ int cas64_mp(void * dest, void * xcmp, void * xxchg) {
+ __asm
+ {
+ mov esi, [xxchg] ; exchange
+ mov ebx, [esi + 0]
+ mov ecx, [esi + 4]
+
+ mov esi, [xcmp] ; comparand
+ mov eax, [esi + 0]
+ mov edx, [esi + 4]
+
+ mov edi, [dest] ; destination
+ lock cmpxchg8b [edi]
+ jz yyyy;
+
+ mov [esi + 0], eax;
+ mov [esi + 4], edx;
+
+yyyy:
+ xor eax, eax;
+ setz al;
+ };
+
+inline unsigned __int64 _InterlockedCompareExchange64(volatile unsigned __int64 *dest
+ ,unsigned __int64 exchange
+ ,unsigned __int64 comperand)
+{
+ //value returned in eax::edx
+ __asm {
+ lea esi,comperand;
+ lea edi,exchange;
+
+ mov eax,[esi];
+ mov edx,4[esi];
+ mov ebx,[edi];
+ mov ecx,4[edi];
+ mov esi,dest;
+ lock CMPXCHG8B [esi];
+ }
+#endif // #if 0
+
+#endif // _WIN32
+
+stb_thread stb_create_thread2(stb_thread_func f, void *d, volatile void **return_code, stb_semaphore rel)
+{
+ return stb_create_thread_raw(f,d,return_code,rel);
+}
+
+stb_thread stb_create_thread(stb_thread_func f, void *d)
+{
+ return stb_create_thread2(f,d,NULL,STB_SEMAPHORE_NULL);
+}
+
+// mutex implemented by wrapping semaphore
+#ifndef STB_MUTEX_NATIVE
+stb_mutex stb_mutex_new(void) { return stb_sem_new_extra(1,1); }
+void stb_mutex_delete(stb_mutex m) { stb_sem_delete (m); }
+void stb_mutex_begin(stb_mutex m) { stb__wait(500); if (m) stb_sem_waitfor(m); }
+void stb_mutex_end(stb_mutex m) { if (m) stb_sem_release(m); stb__wait(500); }
+#endif
+
+// thread merge operation
+struct stb__sync
+{
+ int target; // target number of threads to hit it
+ int sofar; // total threads that hit it
+ int waiting; // total threads waiting
+
+ stb_mutex start; // mutex to prevent starting again before finishing previous
+ stb_mutex mutex; // mutex while tweaking state
+ stb_semaphore release; // semaphore wake up waiting threads
+ // we have to wake them up one at a time, rather than using a single release
+ // call, because win32 semaphores don't let you dynamically change the max count!
+};
+
+stb_sync stb_sync_new(void)
+{
+ stb_sync s = (stb_sync) malloc(sizeof(*s));
+ if (!s) return s;
+
+ s->target = s->sofar = s->waiting = 0;
+ s->mutex = stb_mutex_new();
+ s->start = stb_mutex_new();
+ s->release = stb_sem_new(1);
+ if (s->mutex == STB_MUTEX_NULL || s->release == STB_SEMAPHORE_NULL || s->start == STB_MUTEX_NULL) {
+ stb_mutex_delete(s->mutex);
+ stb_mutex_delete(s->mutex);
+ stb_sem_delete(s->release);
+ free(s);
+ return NULL;
+ }
+ return s;
+}
+
+void stb_sync_delete(stb_sync s)
+{
+ if (s->waiting) {
+ // it's bad to delete while there are threads waiting!
+ // shall we wait for them to reach, or just bail? just bail
+ assert(0);
+ }
+ stb_mutex_delete(s->mutex);
+ stb_mutex_delete(s->release);
+ free(s);
+}
+
+int stb_sync_set_target(stb_sync s, int count)
+{
+ // don't allow setting a target until the last one is fully released;
+ // note that this can lead to inefficient pipelining, and maybe we'd
+ // be better off ping-ponging between two internal syncs?
+ // I tried seeing how often this happened using TryEnterCriticalSection
+ // and could _never_ get it to happen in imv(stb), even with more threads
+ // than processors. So who knows!
+ stb_mutex_begin(s->start);
+
+ // this mutex is pointless, since it's not valid for threads
+ // to call reach() before anyone calls set_target() anyway
+ stb_mutex_begin(s->mutex);
+
+ assert(s->target == 0); // enforced by start mutex
+ s->target = count;
+ s->sofar = 0;
+ s->waiting = 0;
+ stb_mutex_end(s->mutex);
+ return STB_TRUE;
+}
+
+void stb__sync_release(stb_sync s)
+{
+ if (s->waiting)
+ stb_sem_release(s->release);
+ else {
+ s->target = 0;
+ stb_mutex_end(s->start);
+ }
+}
+
+int stb_sync_reach(stb_sync s)
+{
+ int n;
+ stb_mutex_begin(s->mutex);
+ assert(s->sofar < s->target);
+ n = ++s->sofar; // record this value to avoid possible race if we did 'return s->sofar';
+ if (s->sofar == s->target)
+ stb__sync_release(s);
+ stb_mutex_end(s->mutex);
+ return n;
+}
+
+void stb_sync_reach_and_wait(stb_sync s)
+{
+ stb_mutex_begin(s->mutex);
+ assert(s->sofar < s->target);
+ ++s->sofar;
+ if (s->sofar == s->target) {
+ stb__sync_release(s);
+ stb_mutex_end(s->mutex);
+ } else {
+ ++s->waiting; // we're waiting, so one more waiter
+ stb_mutex_end(s->mutex); // release the mutex to other threads
+
+ stb_sem_waitfor(s->release); // wait for merge completion
+
+ stb_mutex_begin(s->mutex); // on merge completion, grab the mutex
+ --s->waiting; // we're done waiting
+ stb__sync_release(s); // restart the next waiter
+ stb_mutex_end(s->mutex); // and now we're done
+ // this ends the same as the first case, but it's a lot
+ // clearer to understand without sharing the code
+ }
+}
+
+struct stb__threadqueue
+{
+ stb_mutex add, remove;
+ stb_semaphore nonempty, nonfull;
+ int head_blockers; // number of threads blocking--used to know whether to release(avail)
+ int tail_blockers;
+ int head, tail, array_size, growable;
+ int item_size;
+ char *data;
+};
+
+static int stb__tq_wrap(volatile stb_threadqueue *z, int p)
+{
+ if (p == z->array_size)
+ return p - z->array_size;
+ else
+ return p;
+}
+
+int stb__threadq_get_raw(stb_threadqueue *tq2, void *output, int block)
+{
+ volatile stb_threadqueue *tq = (volatile stb_threadqueue *) tq2;
+ if (tq->head == tq->tail && !block) return 0;
+
+ stb_mutex_begin(tq->remove);
+
+ while (tq->head == tq->tail) {
+ if (!block) {
+ stb_mutex_end(tq->remove);
+ return 0;
+ }
+ ++tq->head_blockers;
+ stb_mutex_end(tq->remove);
+
+ stb_sem_waitfor(tq->nonempty);
+
+ stb_mutex_begin(tq->remove);
+ --tq->head_blockers;
+ }
+
+ memcpy(output, tq->data + tq->head*tq->item_size, tq->item_size);
+ stb_barrier();
+ tq->head = stb__tq_wrap(tq, tq->head+1);
+
+ stb_sem_release(tq->nonfull);
+ if (tq->head_blockers) // can't check if actually non-empty due to race?
+ stb_sem_release(tq->nonempty); // if there are other blockers, wake one
+
+ stb_mutex_end(tq->remove);
+ return STB_TRUE;
+}
+
+int stb__threadq_grow(volatile stb_threadqueue *tq)
+{
+ int n;
+ char *p;
+ assert(tq->remove != STB_MUTEX_NULL); // must have this to allow growth!
+ stb_mutex_begin(tq->remove);
+
+ n = tq->array_size * 2;
+ p = (char *) realloc(tq->data, n * tq->item_size);
+ if (p == NULL) {
+ stb_mutex_end(tq->remove);
+ stb_mutex_end(tq->add);
+ return STB_FALSE;
+ }
+ if (tq->tail < tq->head) {
+ memcpy(p + tq->array_size * tq->item_size, p, tq->tail * tq->item_size);
+ tq->tail += tq->array_size;
+ }
+ tq->data = p;
+ tq->array_size = n;
+
+ stb_mutex_end(tq->remove);
+ return STB_TRUE;
+}
+
+int stb__threadq_add_raw(stb_threadqueue *tq2, void *input, int block)
+{
+ int tail,pos;
+ volatile stb_threadqueue *tq = (volatile stb_threadqueue *) tq2;
+ stb_mutex_begin(tq->add);
+ for(;;) {
+ pos = tq->tail;
+ tail = stb__tq_wrap(tq, pos+1);
+ if (tail != tq->head) break;
+
+ // full
+ if (tq->growable) {
+ if (!stb__threadq_grow(tq)) {
+ stb_mutex_end(tq->add);
+ return STB_FALSE; // out of memory
+ }
+ } else if (!block) {
+ stb_mutex_end(tq->add);
+ return STB_FALSE;
+ } else {
+ ++tq->tail_blockers;
+ stb_mutex_end(tq->add);
+
+ stb_sem_waitfor(tq->nonfull);
+
+ stb_mutex_begin(tq->add);
+ --tq->tail_blockers;
+ }
+ }
+ memcpy(tq->data + tq->item_size * pos, input, tq->item_size);
+ stb_barrier();
+ tq->tail = tail;
+ stb_sem_release(tq->nonempty);
+ if (tq->tail_blockers) // can't check if actually non-full due to race?
+ stb_sem_release(tq->nonfull);
+ stb_mutex_end(tq->add);
+ return STB_TRUE;
+}
+
+int stb_threadq_length(stb_threadqueue *tq2)
+{
+ int a,b,n;
+ volatile stb_threadqueue *tq = (volatile stb_threadqueue *) tq2;
+ stb_mutex_begin(tq->add);
+ a = tq->head;
+ b = tq->tail;
+ n = tq->array_size;
+ stb_mutex_end(tq->add);
+ if (a > b) b += n;
+ return b-a;
+}
+
+int stb_threadq_get(stb_threadqueue *tq, void *output)
+{
+ return stb__threadq_get_raw(tq, output, STB_FALSE);
+}
+
+void stb_threadq_get_block(stb_threadqueue *tq, void *output)
+{
+ stb__threadq_get_raw(tq, output, STB_TRUE);
+}
+
+int stb_threadq_add(stb_threadqueue *tq, void *input)
+{
+ return stb__threadq_add_raw(tq, input, STB_FALSE);
+}
+
+int stb_threadq_add_block(stb_threadqueue *tq, void *input)
+{
+ return stb__threadq_add_raw(tq, input, STB_TRUE);
+}
+
+void stb_threadq_delete(stb_threadqueue *tq)
+{
+ if (tq) {
+ free(tq->data);
+ stb_mutex_delete(tq->add);
+ stb_mutex_delete(tq->remove);
+ stb_sem_delete(tq->nonempty);
+ stb_sem_delete(tq->nonfull);
+ free(tq);
+ }
+}
+
+#define STB_THREADQUEUE_DYNAMIC 0
+stb_threadqueue *stb_threadq_new(int item_size, int num_items, int many_add, int many_remove)
+{
+ int error=0;
+ stb_threadqueue *tq = (stb_threadqueue *) malloc(sizeof(*tq));
+ if (tq == NULL) return NULL;
+
+ if (num_items == STB_THREADQUEUE_DYNAMIC) {
+ tq->growable = STB_TRUE;
+ num_items = 32;
+ } else
+ tq->growable = STB_FALSE;
+
+ tq->item_size = item_size;
+ tq->array_size = num_items+1;
+
+ tq->add = tq->remove = STB_MUTEX_NULL;
+ tq->nonempty = tq->nonfull = STB_SEMAPHORE_NULL;
+ tq->data = NULL;
+ if (many_add)
+ { tq->add = stb_mutex_new(); if (tq->add == STB_MUTEX_NULL) goto error; }
+ if (many_remove || tq->growable)
+ { tq->remove = stb_mutex_new(); if (tq->remove == STB_MUTEX_NULL) goto error; }
+ tq->nonempty = stb_sem_new(1); if (tq->nonempty == STB_SEMAPHORE_NULL) goto error;
+ tq->nonfull = stb_sem_new(1); if (tq->nonfull == STB_SEMAPHORE_NULL) goto error;
+ tq->data = (char *) malloc(tq->item_size * tq->array_size);
+ if (tq->data == NULL) goto error;
+
+ tq->head = tq->tail = 0;
+ tq->head_blockers = tq->tail_blockers = 0;
+
+ return tq;
+
+error:
+ stb_threadq_delete(tq);
+ return NULL;
+}
+
+typedef struct
+{
+ stb_thread_func f;
+ void *d;
+ volatile void **retval;
+ stb_sync sync;
+} stb__workinfo;
+
+//static volatile stb__workinfo *stb__work;
+
+struct stb__workqueue
+{
+ int numthreads;
+ stb_threadqueue *tq;
+};
+
+static stb_workqueue *stb__work_global;
+
+static void *stb__thread_workloop(void *p)
+{
+ volatile stb_workqueue *q = (volatile stb_workqueue *) p;
+ for(;;) {
+ void *z;
+ stb__workinfo w;
+ stb_threadq_get_block(q->tq, &w);
+ if (w.f == NULL) // null work is a signal to end the thread
+ return NULL;
+ z = w.f(w.d);
+ if (w.retval) { stb_barrier(); *w.retval = z; }
+ if (w.sync != STB_SYNC_NULL) stb_sync_reach(w.sync);
+ }
+}
+
+stb_workqueue *stb_workq_new(int num_threads, int max_units)
+{
+ return stb_workq_new_flags(num_threads, max_units, 0,0);
+}
+
+stb_workqueue *stb_workq_new_flags(int numthreads, int max_units, int no_add_mutex, int no_remove_mutex)
+{
+ stb_workqueue *q = (stb_workqueue *) malloc(sizeof(*q));
+ if (q == NULL) return NULL;
+ q->tq = stb_threadq_new(sizeof(stb__workinfo), max_units, !no_add_mutex, !no_remove_mutex);
+ if (q->tq == NULL) { free(q); return NULL; }
+ q->numthreads = 0;
+ stb_workq_numthreads(q, numthreads);
+ return q;
+}
+
+void stb_workq_delete(stb_workqueue *q)
+{
+ while (stb_workq_length(q) != 0)
+ stb__thread_sleep(1);
+ stb_threadq_delete(q->tq);
+ free(q);
+}
+
+static int stb__work_maxitems = STB_THREADQUEUE_DYNAMIC;
+
+static void stb_work_init(int num_threads)
+{
+ if (stb__work_global == NULL) {
+ stb__threadmutex_init();
+ stb_mutex_begin(stb__workmutex);
+ stb_barrier();
+ if (*(stb_workqueue * volatile *) &stb__work_global == NULL)
+ stb__work_global = stb_workq_new(num_threads, stb__work_maxitems);
+ stb_mutex_end(stb__workmutex);
+ }
+}
+
+static int stb__work_raw(stb_workqueue *q, stb_thread_func f, void *d, volatile void **return_code, stb_sync rel)
+{
+ stb__workinfo w;
+ if (q == NULL) {
+ stb_work_init(1);
+ q = stb__work_global;
+ }
+ w.f = f;
+ w.d = d;
+ w.retval = return_code;
+ w.sync = rel;
+ return stb_threadq_add(q->tq, &w);
+}
+
+int stb_workq_length(stb_workqueue *q)
+{
+ return stb_threadq_length(q->tq);
+}
+
+int stb_workq(stb_workqueue *q, stb_thread_func f, void *d, volatile void **return_code)
+{
+ if (f == NULL) return 0;
+ return stb_workq_reach(q, f, d, return_code, NULL);
+}
+
+int stb_workq_reach(stb_workqueue *q, stb_thread_func f, void *d, volatile void **return_code, stb_sync rel)
+{
+ if (f == NULL) return 0;
+ return stb__work_raw(q, f, d, return_code, rel);
+}
+
+static void stb__workq_numthreads(stb_workqueue *q, int n)
+{
+ while (q->numthreads < n) {
+ stb_create_thread(stb__thread_workloop, q);
+ ++q->numthreads;
+ }
+ while (q->numthreads > n) {
+ stb__work_raw(q, NULL, NULL, NULL, NULL);
+ --q->numthreads;
+ }
+}
+
+void stb_workq_numthreads(stb_workqueue *q, int n)
+{
+ stb_mutex_begin(stb__threadmutex);
+ stb__workq_numthreads(q,n);
+ stb_mutex_end(stb__threadmutex);
+}
+
+int stb_work_maxunits(int n)
+{
+ if (stb__work_global == NULL) {
+ stb__work_maxitems = n;
+ stb_work_init(1);
+ }
+ return stb__work_maxitems;
+}
+
+int stb_work(stb_thread_func f, void *d, volatile void **return_code)
+{
+ return stb_workq(stb__work_global, f,d,return_code);
+}
+
+int stb_work_reach(stb_thread_func f, void *d, volatile void **return_code, stb_sync rel)
+{
+ return stb_workq_reach(stb__work_global, f,d,return_code,rel);
+}
+
+void stb_work_numthreads(int n)
+{
+ if (stb__work_global == NULL)
+ stb_work_init(n);
+ else
+ stb_workq_numthreads(stb__work_global, n);
+}
+#endif // STB_DEFINE
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Background disk I/O
+//
+//
+
+#define STB_BGIO_READ_ALL (-1)
+STB_EXTERN int stb_bgio_read (char *filename, int offset, int len, stb_uchar **result, int *olen);
+STB_EXTERN int stb_bgio_readf (FILE *f , int offset, int len, stb_uchar **result, int *olen);
+STB_EXTERN int stb_bgio_read_to (char *filename, int offset, int len, stb_uchar *buffer, int *olen);
+STB_EXTERN int stb_bgio_readf_to(FILE *f , int offset, int len, stb_uchar *buffer, int *olen);
+
+typedef struct
+{
+ int have_data;
+ int is_valid;
+ int is_dir;
+ time_t filetime;
+ stb_int64 filesize;
+} stb_bgstat;
+
+STB_EXTERN int stb_bgio_stat (char *filename, stb_bgstat *result);
+
+#ifdef STB_DEFINE
+
+static stb_workqueue *stb__diskio;
+static stb_mutex stb__diskio_mutex;
+
+void stb_thread_cleanup(void)
+{
+ if (stb__work_global) stb_workq_delete(stb__work_global); stb__work_global = NULL;
+ if (stb__threadmutex) stb_mutex_delete(stb__threadmutex); stb__threadmutex = NULL;
+ if (stb__workmutex) stb_mutex_delete(stb__workmutex); stb__workmutex = NULL;
+ if (stb__diskio) stb_workq_delete(stb__diskio); stb__diskio = NULL;
+ if (stb__diskio_mutex)stb_mutex_delete(stb__diskio_mutex);stb__diskio_mutex= NULL;
+}
+
+
+typedef struct
+{
+ char *filename;
+ FILE *f;
+ int offset;
+ int len;
+
+ stb_bgstat *stat_out;
+ stb_uchar *output;
+ stb_uchar **result;
+ int *len_output;
+ int *flag;
+} stb__disk_command;
+
+#define STB__MAX_DISK_COMMAND 100
+static stb__disk_command stb__dc_queue[STB__MAX_DISK_COMMAND];
+static int stb__dc_offset;
+
+void stb__io_init(void)
+{
+ if (!stb__diskio) {
+ stb__threadmutex_init();
+ stb_mutex_begin(stb__threadmutex);
+ stb_barrier();
+ if (*(stb_thread * volatile *) &stb__diskio == NULL) {
+ stb__diskio_mutex = stb_mutex_new();
+ // use many threads so OS can try to schedule seeks
+ stb__diskio = stb_workq_new_flags(16,STB__MAX_DISK_COMMAND,STB_FALSE,STB_FALSE);
+ }
+ stb_mutex_end(stb__threadmutex);
+ }
+}
+
+static void * stb__io_error(stb__disk_command *dc)
+{
+ if (dc->len_output) *dc->len_output = 0;
+ if (dc->result) *dc->result = NULL;
+ if (dc->flag) *dc->flag = -1;
+ return NULL;
+}
+
+static void * stb__io_task(void *p)
+{
+ stb__disk_command *dc = (stb__disk_command *) p;
+ int len;
+ FILE *f;
+ stb_uchar *buf;
+
+ if (dc->stat_out) {
+ struct _stati64 s;
+ if (!_stati64(dc->filename, &s)) {
+ dc->stat_out->filesize = s.st_size;
+ dc->stat_out->filetime = s.st_mtime;
+ dc->stat_out->is_dir = s.st_mode & _S_IFDIR;
+ dc->stat_out->is_valid = (s.st_mode & _S_IFREG) || dc->stat_out->is_dir;
+ } else
+ dc->stat_out->is_valid = 0;
+ stb_barrier();
+ dc->stat_out->have_data = 1;
+ free(dc->filename);
+ return 0;
+ }
+ if (dc->f) {
+ #ifdef WIN32
+ f = _fdopen(_dup(_fileno(dc->f)), "rb");
+ #else
+ f = fdopen(dup(fileno(dc->f)), "rb");
+ #endif
+ if (!f)
+ return stb__io_error(dc);
+ } else {
+ f = fopen(dc->filename, "rb");
+ free(dc->filename);
+ if (!f)
+ return stb__io_error(dc);
+ }
+
+ len = dc->len;
+ if (len < 0) {
+ fseek(f, 0, SEEK_END);
+ len = ftell(f) - dc->offset;
+ }
+
+ if (fseek(f, dc->offset, SEEK_SET)) {
+ fclose(f);
+ return stb__io_error(dc);
+ }
+
+ if (dc->output)
+ buf = dc->output;
+ else {
+ buf = (stb_uchar *) malloc(len);
+ if (buf == NULL) {
+ fclose(f);
+ return stb__io_error(dc);
+ }
+ }
+
+ len = fread(buf, 1, len, f);
+ fclose(f);
+ if (dc->len_output) *dc->len_output = len;
+ if (dc->result) *dc->result = buf;
+ if (dc->flag) *dc->flag = 1;
+
+ return NULL;
+}
+
+int stb__io_add(char *fname, FILE *f, int off, int len, stb_uchar *out, stb_uchar **result, int *olen, int *flag, stb_bgstat *stat)
+{
+ int res;
+ stb__io_init();
+ // do memory allocation outside of mutex
+ if (fname) fname = stb_p_strdup(fname);
+ stb_mutex_begin(stb__diskio_mutex);
+ {
+ stb__disk_command *dc = &stb__dc_queue[stb__dc_offset];
+ dc->filename = fname;
+ dc->f = f;
+ dc->offset = off;
+ dc->len = len;
+ dc->output = out;
+ dc->result = result;
+ dc->len_output = olen;
+ dc->flag = flag;
+ dc->stat_out = stat;
+ res = stb_workq(stb__diskio, stb__io_task, dc, NULL);
+ if (res)
+ stb__dc_offset = (stb__dc_offset + 1 == STB__MAX_DISK_COMMAND ? 0 : stb__dc_offset+1);
+ }
+ stb_mutex_end(stb__diskio_mutex);
+ return res;
+}
+
+int stb_bgio_read(char *filename, int offset, int len, stb_uchar **result, int *olen)
+{
+ return stb__io_add(filename,NULL,offset,len,NULL,result,olen,NULL,NULL);
+}
+
+int stb_bgio_readf(FILE *f, int offset, int len, stb_uchar **result, int *olen)
+{
+ return stb__io_add(NULL,f,offset,len,NULL,result,olen,NULL,NULL);
+}
+
+int stb_bgio_read_to(char *filename, int offset, int len, stb_uchar *buffer, int *olen)
+{
+ return stb__io_add(filename,NULL,offset,len,buffer,NULL,olen,NULL,NULL);
+}
+
+int stb_bgio_readf_to(FILE *f, int offset, int len, stb_uchar *buffer, int *olen)
+{
+ return stb__io_add(NULL,f,offset,len,buffer,NULL,olen,NULL,NULL);
+}
+
+STB_EXTERN int stb_bgio_stat (char *filename, stb_bgstat *result)
+{
+ result->have_data = 0;
+ return stb__io_add(filename,NULL,0,0,0,NULL,0,NULL, result);
+}
+#endif
+#endif
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Fast malloc implementation
+//
+// This is a clone of TCMalloc, but without the thread support.
+// 1. large objects are allocated directly, page-aligned
+// 2. small objects are allocated in homogeonous heaps, 0 overhead
+//
+// We keep an allocation table for pages a la TCMalloc. This would
+// require 4MB for the entire address space, but we only allocate
+// the parts that are in use. The overhead from using homogenous heaps
+// everywhere is 3MB. (That is, if you allocate 1 object of each size,
+// you'll use 3MB.)
+
+#if defined(STB_DEFINE) && ((defined(_WIN32) && !defined(_M_AMD64)) || defined(STB_FASTMALLOC))
+
+#ifdef _WIN32
+ #ifndef _WINDOWS_
+ #ifndef STB__IMPORT
+ #define STB__IMPORT STB_EXTERN __declspec(dllimport)
+ #define STB__DW unsigned long
+ #endif
+ STB__IMPORT void * __stdcall VirtualAlloc(void *p, unsigned long size, unsigned long type, unsigned long protect);
+ STB__IMPORT int __stdcall VirtualFree(void *p, unsigned long size, unsigned long freetype);
+ #endif
+ #define stb__alloc_pages_raw(x) (stb_uint32) VirtualAlloc(NULL, (x), 0x3000, 0x04)
+ #define stb__dealloc_pages_raw(p) VirtualFree((void *) p, 0, 0x8000)
+#else
+ #error "Platform not currently supported"
+#endif
+
+typedef struct stb__span
+{
+ int start, len;
+ struct stb__span *next, *prev;
+ void *first_free;
+ unsigned short list; // 1..256 free; 257..511 sizeclass; 0=large block
+ short allocations; // # outstanding allocations for sizeclass
+} stb__span; // 24
+
+static stb__span **stb__span_for_page;
+static int stb__firstpage, stb__lastpage;
+static void stb__update_page_range(int first, int last)
+{
+ stb__span **sfp;
+ int i, f,l;
+ if (first >= stb__firstpage && last <= stb__lastpage) return;
+ if (stb__span_for_page == NULL) {
+ f = first;
+ l = f+stb_max(last-f, 16384);
+ l = stb_min(l, 1<<20);
+ } else if (last > stb__lastpage) {
+ f = stb__firstpage;
+ l = f + (stb__lastpage - f) * 2;
+ l = stb_clamp(last, l,1<<20);
+ } else {
+ l = stb__lastpage;
+ f = l - (l - stb__firstpage) * 2;
+ f = stb_clamp(f, 0,first);
+ }
+ sfp = (stb__span **) stb__alloc_pages_raw(sizeof(void *) * (l-f));
+ for (i=f; i < stb__firstpage; ++i) sfp[i - f] = NULL;
+ for ( ; i < stb__lastpage ; ++i) sfp[i - f] = stb__span_for_page[i - stb__firstpage];
+ for ( ; i < l ; ++i) sfp[i - f] = NULL;
+ if (stb__span_for_page) stb__dealloc_pages_raw(stb__span_for_page);
+ stb__firstpage = f;
+ stb__lastpage = l;
+ stb__span_for_page = sfp;
+}
+
+static stb__span *stb__span_free=NULL;
+static stb__span *stb__span_first, *stb__span_end;
+static stb__span *stb__span_alloc(void)
+{
+ stb__span *s = stb__span_free;
+ if (s)
+ stb__span_free = s->next;
+ else {
+ if (!stb__span_first) {
+ stb__span_first = (stb__span *) stb__alloc_pages_raw(65536);
+ if (stb__span_first == NULL) return NULL;
+ stb__span_end = stb__span_first + (65536 / sizeof(stb__span));
+ }
+ s = stb__span_first++;
+ if (stb__span_first == stb__span_end) stb__span_first = NULL;
+ }
+ return s;
+}
+
+static stb__span *stb__spanlist[512];
+
+static void stb__spanlist_unlink(stb__span *s)
+{
+ if (s->prev)
+ s->prev->next = s->next;
+ else {
+ int n = s->list;
+ assert(stb__spanlist[n] == s);
+ stb__spanlist[n] = s->next;
+ }
+ if (s->next)
+ s->next->prev = s->prev;
+ s->next = s->prev = NULL;
+ s->list = 0;
+}
+
+static void stb__spanlist_add(int n, stb__span *s)
+{
+ s->list = n;
+ s->next = stb__spanlist[n];
+ s->prev = NULL;
+ stb__spanlist[n] = s;
+ if (s->next) s->next->prev = s;
+}
+
+#define stb__page_shift 12
+#define stb__page_size (1 << stb__page_shift)
+#define stb__page_number(x) ((x) >> stb__page_shift)
+#define stb__page_address(x) ((x) << stb__page_shift)
+
+static void stb__set_span_for_page(stb__span *s)
+{
+ int i;
+ for (i=0; i < s->len; ++i)
+ stb__span_for_page[s->start + i - stb__firstpage] = s;
+}
+
+static stb__span *stb__coalesce(stb__span *a, stb__span *b)
+{
+ assert(a->start + a->len == b->start);
+ if (a->list) stb__spanlist_unlink(a);
+ if (b->list) stb__spanlist_unlink(b);
+ a->len += b->len;
+ b->len = 0;
+ b->next = stb__span_free;
+ stb__span_free = b;
+ stb__set_span_for_page(a);
+ return a;
+}
+
+static void stb__free_span(stb__span *s)
+{
+ stb__span *n = NULL;
+ if (s->start > stb__firstpage) {
+ n = stb__span_for_page[s->start-1 - stb__firstpage];
+ if (n && n->allocations == -2 && n->start + n->len == s->start) s = stb__coalesce(n,s);
+ }
+ if (s->start + s->len < stb__lastpage) {
+ n = stb__span_for_page[s->start + s->len - stb__firstpage];
+ if (n && n->allocations == -2 && s->start + s->len == n->start) s = stb__coalesce(s,n);
+ }
+ s->allocations = -2;
+ stb__spanlist_add(s->len > 256 ? 256 : s->len, s);
+}
+
+static stb__span *stb__alloc_pages(int num)
+{
+ stb__span *s = stb__span_alloc();
+ int p;
+ if (!s) return NULL;
+ p = stb__alloc_pages_raw(num << stb__page_shift);
+ if (p == 0) { s->next = stb__span_free; stb__span_free = s; return 0; }
+ assert(stb__page_address(stb__page_number(p)) == p);
+ p = stb__page_number(p);
+ stb__update_page_range(p, p+num);
+ s->start = p;
+ s->len = num;
+ s->next = NULL;
+ s->prev = NULL;
+ stb__set_span_for_page(s);
+ return s;
+}
+
+static stb__span *stb__alloc_span(int pagecount)
+{
+ int i;
+ stb__span *p = NULL;
+ for(i=pagecount; i < 256; ++i)
+ if (stb__spanlist[i]) {
+ p = stb__spanlist[i];
+ break;
+ }
+ if (!p) {
+ p = stb__spanlist[256];
+ while (p && p->len < pagecount)
+ p = p->next;
+ }
+ if (!p) {
+ p = stb__alloc_pages(pagecount < 16 ? 16 : pagecount);
+ if (p == NULL) return 0;
+ } else
+ stb__spanlist_unlink(p);
+
+ if (p->len > pagecount) {
+ stb__span *q = stb__span_alloc();
+ if (q) {
+ q->start = p->start + pagecount;
+ q->len = p->len - pagecount;
+ p->len = pagecount;
+ for (i=0; i < q->len; ++i)
+ stb__span_for_page[q->start+i - stb__firstpage] = q;
+ stb__spanlist_add(q->len > 256 ? 256 : q->len, q);
+ }
+ }
+ return p;
+}
+
+#define STB__MAX_SMALL_SIZE 32768
+#define STB__MAX_SIZE_CLASSES 256
+
+static unsigned char stb__class_base[32];
+static unsigned char stb__class_shift[32];
+static unsigned char stb__pages_for_class[STB__MAX_SIZE_CLASSES];
+static int stb__size_for_class[STB__MAX_SIZE_CLASSES];
+
+stb__span *stb__get_nonempty_sizeclass(int c)
+{
+ int s = c + 256, i, size, tsize; // remap to span-list index
+ char *z;
+ void *q;
+ stb__span *p = stb__spanlist[s];
+ if (p) {
+ if (p->first_free) return p; // fast path: it's in the first one in list
+ for (p=p->next; p; p=p->next)
+ if (p->first_free) {
+ // move to front for future queries
+ stb__spanlist_unlink(p);
+ stb__spanlist_add(s, p);
+ return p;
+ }
+ }
+ // no non-empty ones, so allocate a new one
+ p = stb__alloc_span(stb__pages_for_class[c]);
+ if (!p) return NULL;
+ // create the free list up front
+ size = stb__size_for_class[c];
+ tsize = stb__pages_for_class[c] << stb__page_shift;
+ i = 0;
+ z = (char *) stb__page_address(p->start);
+ q = NULL;
+ while (i + size <= tsize) {
+ * (void **) z = q; q = z;
+ z += size;
+ i += size;
+ }
+ p->first_free = q;
+ p->allocations = 0;
+ stb__spanlist_add(s,p);
+ return p;
+}
+
+static int stb__sizeclass(size_t sz)
+{
+ int z = stb_log2_floor(sz); // -1 below to group e.g. 13,14,15,16 correctly
+ return stb__class_base[z] + ((sz-1) >> stb__class_shift[z]);
+}
+
+static void stb__init_sizeclass(void)
+{
+ int i, size, overhead;
+ int align_shift = 2; // allow 4-byte and 12-byte blocks as well, vs. TCMalloc
+ int next_class = 1;
+ int last_log = 0;
+
+ for (i = 0; i < align_shift; i++) {
+ stb__class_base [i] = next_class;
+ stb__class_shift[i] = align_shift;
+ }
+
+ for (size = 1 << align_shift; size <= STB__MAX_SMALL_SIZE; size += 1 << align_shift) {
+ i = stb_log2_floor(size);
+ if (i > last_log) {
+ if (size == 16) ++align_shift; // switch from 4-byte to 8-byte alignment
+ else if (size >= 128 && align_shift < 8) ++align_shift;
+ stb__class_base[i] = next_class - ((size-1) >> align_shift);
+ stb__class_shift[i] = align_shift;
+ last_log = i;
+ }
+ stb__size_for_class[next_class++] = size;
+ }
+
+ for (i=1; i <= STB__MAX_SMALL_SIZE; ++i)
+ assert(i <= stb__size_for_class[stb__sizeclass(i)]);
+
+ overhead = 0;
+ for (i = 1; i < next_class; i++) {
+ int s = stb__size_for_class[i];
+ size = stb__page_size;
+ while (size % s > size >> 3)
+ size += stb__page_size;
+ stb__pages_for_class[i] = (unsigned char) (size >> stb__page_shift);
+ overhead += size;
+ }
+ assert(overhead < (4 << 20)); // make sure it's under 4MB of overhead
+}
+
+#ifdef STB_DEBUG
+#define stb__smemset(a,b,c) memset((void *) a, b, c)
+#elif defined(STB_FASTMALLOC_INIT)
+#define stb__smemset(a,b,c) memset((void *) a, b, c)
+#else
+#define stb__smemset(a,b,c)
+#endif
+void *stb_smalloc(size_t sz)
+{
+ stb__span *s;
+ if (sz == 0) return NULL;
+ if (stb__size_for_class[1] == 0) stb__init_sizeclass();
+ if (sz > STB__MAX_SMALL_SIZE) {
+ s = stb__alloc_span((sz + stb__page_size - 1) >> stb__page_shift);
+ if (s == NULL) return NULL;
+ s->list = 0;
+ s->next = s->prev = NULL;
+ s->allocations = -32767;
+ stb__smemset(stb__page_address(s->start), 0xcd, (sz+3)&~3);
+ return (void *) stb__page_address(s->start);
+ } else {
+ void *p;
+ int c = stb__sizeclass(sz);
+ s = stb__spanlist[256+c];
+ if (!s || !s->first_free)
+ s = stb__get_nonempty_sizeclass(c);
+ if (s == NULL) return NULL;
+ p = s->first_free;
+ s->first_free = * (void **) p;
+ ++s->allocations;
+ stb__smemset(p,0xcd, sz);
+ return p;
+ }
+}
+
+int stb_ssize(void *p)
+{
+ stb__span *s;
+ if (p == NULL) return 0;
+ s = stb__span_for_page[stb__page_number((stb_uint) p) - stb__firstpage];
+ if (s->list >= 256) {
+ return stb__size_for_class[s->list - 256];
+ } else {
+ assert(s->list == 0);
+ return s->len << stb__page_shift;
+ }
+}
+
+void stb_sfree(void *p)
+{
+ stb__span *s;
+ if (p == NULL) return;
+ s = stb__span_for_page[stb__page_number((stb_uint) p) - stb__firstpage];
+ if (s->list >= 256) {
+ stb__smemset(p, 0xfe, stb__size_for_class[s->list-256]);
+ * (void **) p = s->first_free;
+ s->first_free = p;
+ if (--s->allocations == 0) {
+ stb__spanlist_unlink(s);
+ stb__free_span(s);
+ }
+ } else {
+ assert(s->list == 0);
+ stb__smemset(p, 0xfe, stb_ssize(p));
+ stb__free_span(s);
+ }
+}
+
+void *stb_srealloc(void *p, size_t sz)
+{
+ size_t cur_size;
+ if (p == NULL) return stb_smalloc(sz);
+ if (sz == 0) { stb_sfree(p); return NULL; }
+ cur_size = stb_ssize(p);
+ if (sz > cur_size || sz <= (cur_size >> 1)) {
+ void *q;
+ if (sz > cur_size && sz < (cur_size << 1)) sz = cur_size << 1;
+ q = stb_smalloc(sz); if (q == NULL) return NULL;
+ memcpy(q, p, sz < cur_size ? sz : cur_size);
+ stb_sfree(p);
+ return q;
+ }
+ return p;
+}
+
+void *stb_scalloc(size_t n, size_t sz)
+{
+ void *p;
+ if (n == 0 || sz == 0) return NULL;
+ if (stb_log2_ceil(n) + stb_log2_ceil(n) >= 32) return NULL;
+ p = stb_smalloc(n*sz);
+ if (p) memset(p, 0, n*sz);
+ return p;
+}
+
+char *stb_sstrdup(char *s)
+{
+ int n = strlen(s);
+ char *p = (char *) stb_smalloc(n+1);
+ if (p) stb_p_strcpy_s(p,n+1,s);
+ return p;
+}
+#endif // STB_DEFINE
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Source code constants
+//
+// This is a trivial system to let you specify constants in source code,
+// then while running you can change the constants.
+//
+// Note that you can't wrap the #defines, because we need to know their
+// names. So we provide a pre-wrapped version without 'STB_' for convenience;
+// to request it, #define STB_CONVENIENT_H, yielding:
+// KI -- integer
+// KU -- unsigned integer
+// KF -- float
+// KD -- double
+// KS -- string constant
+//
+// Defaults to functioning in debug build, not in release builds.
+// To force on, define STB_ALWAYS_H
+
+#ifdef STB_CONVENIENT_H
+#define KI(x) STB_I(x)
+#define KU(x) STB_UI(x)
+#define KF(x) STB_F(x)
+#define KD(x) STB_D(x)
+#define KS(x) STB_S(x)
+#endif
+
+STB_EXTERN void stb_source_path(char *str);
+#ifdef STB_DEFINE
+char *stb__source_path;
+void stb_source_path(char *path)
+{
+ stb__source_path = path;
+}
+
+char *stb__get_sourcefile_path(char *file)
+{
+ static char filebuf[512];
+ if (stb__source_path) {
+ stb_p_sprintf(filebuf stb_p_size(sizeof(filebuf)), "%s/%s", stb__source_path, file);
+ if (stb_fexists(filebuf)) return filebuf;
+ }
+
+ if (stb_fexists(file)) return file;
+
+ stb_p_sprintf(filebuf stb_p_size(sizeof(filebuf)), "../%s", file);
+ if (!stb_fexists(filebuf)) return filebuf;
+
+ return file;
+}
+#endif
+
+#define STB_F(x) ((float) STB_H(x))
+#define STB_UI(x) ((unsigned int) STB_I(x))
+
+#if !defined(STB_DEBUG) && !defined(STB_ALWAYS_H)
+#define STB_D(x) ((double) (x))
+#define STB_I(x) ((int) (x))
+#define STB_S(x) ((char *) (x))
+#else
+#define STB_D(x) stb__double_constant(__FILE__, __LINE__-1, (x))
+#define STB_I(x) stb__int_constant(__FILE__, __LINE__-1, (x))
+#define STB_S(x) stb__string_constant(__FILE__, __LINE__-1, (x))
+
+STB_EXTERN double stb__double_constant(char *file, int line, double x);
+STB_EXTERN int stb__int_constant(char *file, int line, int x);
+STB_EXTERN char * stb__string_constant(char *file, int line, char *str);
+
+#ifdef STB_DEFINE
+
+enum
+{
+ STB__CTYPE_int,
+ STB__CTYPE_uint,
+ STB__CTYPE_float,
+ STB__CTYPE_double,
+ STB__CTYPE_string,
+};
+
+typedef struct
+{
+ int line;
+ int type;
+ union {
+ int ival;
+ double dval;
+ char *sval;
+ };
+} stb__Entry;
+
+typedef struct
+{
+ stb__Entry *entries;
+ char *filename;
+ time_t timestamp;
+ char **file_data;
+ int file_len;
+ unsigned short *line_index;
+} stb__FileEntry;
+
+static void stb__constant_parse(stb__FileEntry *f, int i)
+{
+ char *s;
+ int n;
+ if (!stb_arr_valid(f->entries, i)) return;
+ n = f->entries[i].line;
+ if (n >= f->file_len) return;
+ s = f->file_data[n];
+ switch (f->entries[i].type) {
+ case STB__CTYPE_float:
+ while (*s) {
+ if (!strncmp(s, "STB_D(", 6)) { s+=6; goto matched_float; }
+ if (!strncmp(s, "STB_F(", 6)) { s+=6; goto matched_float; }
+ if (!strncmp(s, "KD(", 3)) { s+=3; goto matched_float; }
+ if (!strncmp(s, "KF(", 3)) { s+=3; goto matched_float; }
+ ++s;
+ }
+ break;
+ matched_float:
+ f->entries[i].dval = strtod(s, NULL);
+ break;
+ case STB__CTYPE_int:
+ while (*s) {
+ if (!strncmp(s, "STB_I(", 6)) { s+=6; goto matched_int; }
+ if (!strncmp(s, "STB_UI(", 7)) { s+=7; goto matched_int; }
+ if (!strncmp(s, "KI(", 3)) { s+=3; goto matched_int; }
+ if (!strncmp(s, "KU(", 3)) { s+=3; goto matched_int; }
+ ++s;
+ }
+ break;
+ matched_int: {
+ int neg=0;
+ s = stb_skipwhite(s);
+ while (*s == '-') { neg = !neg; s = stb_skipwhite(s+1); } // handle '- - 5', pointlessly
+ if (s[0] == '0' && tolower(s[1]) == 'x')
+ f->entries[i].ival = strtol(s, NULL, 16);
+ else if (s[0] == '0')
+ f->entries[i].ival = strtol(s, NULL, 8);
+ else
+ f->entries[i].ival = strtol(s, NULL, 10);
+ if (neg) f->entries[i].ival = -f->entries[i].ival;
+ break;
+ }
+ case STB__CTYPE_string:
+ // @TODO
+ break;
+ }
+}
+
+static stb_sdict *stb__constant_file_hash;
+
+stb__Entry *stb__constant_get_entry(char *filename, int line, int type)
+{
+ int i;
+ stb__FileEntry *f;
+ if (stb__constant_file_hash == NULL)
+ stb__constant_file_hash = stb_sdict_new(STB_TRUE);
+ f = (stb__FileEntry*) stb_sdict_get(stb__constant_file_hash, filename);
+ if (f == NULL) {
+ char *s = stb__get_sourcefile_path(filename);
+ if (s == NULL || !stb_fexists(s)) return 0;
+ f = (stb__FileEntry *) malloc(sizeof(*f));
+ f->timestamp = stb_ftimestamp(s);
+ f->file_data = stb_stringfile(s, &f->file_len);
+ f->filename = stb_p_strdup(s); // cache the full path
+ f->entries = NULL;
+ f->line_index = 0;
+ stb_arr_setlen(f->line_index, f->file_len);
+ memset(f->line_index, 0xff, stb_arr_storage(f->line_index));
+ } else {
+ time_t t = stb_ftimestamp(f->filename);
+ if (f->timestamp != t) {
+ f->timestamp = t;
+ free(f->file_data);
+ f->file_data = stb_stringfile(f->filename, &f->file_len);
+ stb_arr_setlen(f->line_index, f->file_len);
+ for (i=0; i < stb_arr_len(f->entries); ++i)
+ stb__constant_parse(f, i);
+ }
+ }
+
+ if (line >= f->file_len) return 0;
+
+ if (f->line_index[line] >= stb_arr_len(f->entries)) {
+ // need a new entry
+ int n = stb_arr_len(f->entries);
+ stb__Entry e;
+ e.line = line;
+ if (line < f->file_len)
+ f->line_index[line] = n;
+ e.type = type;
+ stb_arr_push(f->entries, e);
+ stb__constant_parse(f, n);
+ }
+ return f->entries + f->line_index[line];
+}
+
+double stb__double_constant(char *file, int line, double x)
+{
+ stb__Entry *e = stb__constant_get_entry(file, line, STB__CTYPE_float);
+ if (!e) return x;
+ return e->dval;
+}
+
+int stb__int_constant(char *file, int line, int x)
+{
+ stb__Entry *e = stb__constant_get_entry(file, line, STB__CTYPE_int);
+ if (!e) return x;
+ return e->ival;
+}
+
+char * stb__string_constant(char *file, int line, char *x)
+{
+ stb__Entry *e = stb__constant_get_entry(file, line, STB__CTYPE_string);
+ if (!e) return x;
+ return e->sval;
+}
+
+#endif // STB_DEFINE
+#endif // !STB_DEBUG && !STB_ALWAYS_H
+
+
+#ifdef STB_STUA
+#error "STUA is no longer supported"
+//////////////////////////////////////////////////////////////////////////
+//
+// stua: little scripting language
+//
+// define STB_STUA to compile it
+//
+// see http://nothings.org/stb/stb_stua.html for documentation
+//
+// basic parsing model:
+//
+// lexical analysis
+// use stb_lex() to parse tokens; keywords get their own tokens
+//
+// parsing:
+// recursive descent parser. too much of a hassle to make an unambiguous
+// LR(1) grammar, and one-pass generation is clumsier (recursive descent
+// makes it easier to e.g. compile nested functions). on the other hand,
+// dictionary syntax required hackery to get extra lookahead.
+//
+// codegen:
+// output into an evaluation tree, using array indices as 'pointers'
+//
+// run:
+// traverse the tree; support for 'break/continue/return' is tricky
+//
+// garbage collection:
+// stu__mark and sweep; explicit stack with non-stu__compile_global_scope roots
+
+typedef stb_int32 stua_obj;
+
+typedef stb_idict stua_dict;
+
+STB_EXTERN void stua_run_script(char *s);
+STB_EXTERN void stua_uninit(void);
+
+extern stua_obj stua_globals;
+
+STB_EXTERN double stua_number(stua_obj z);
+
+STB_EXTERN stua_obj stua_getnil(void);
+STB_EXTERN stua_obj stua_getfalse(void);
+STB_EXTERN stua_obj stua_gettrue(void);
+STB_EXTERN stua_obj stua_string(char *z);
+STB_EXTERN stua_obj stua_make_number(double d);
+STB_EXTERN stua_obj stua_box(int type, void *data, int size);
+
+enum
+{
+ STUA_op_negate=129,
+ STUA_op_shl, STUA_op_ge,
+ STUA_op_shr, STUA_op_le,
+ STUA_op_shru,
+ STUA_op_last
+};
+
+#define STUA_NO_VALUE 2 // equivalent to a tagged NULL
+STB_EXTERN stua_obj (*stua_overload)(int op, stua_obj a, stua_obj b, stua_obj c);
+
+STB_EXTERN stua_obj stua_error(char *err, ...);
+
+STB_EXTERN stua_obj stua_pushroot(stua_obj o);
+STB_EXTERN void stua_poproot ( void );
+
+
+#ifdef STB_DEFINE
+// INTERPRETER
+
+// 31-bit floating point implementation
+// force the (1 << 30) bit (2nd highest bit) to be zero by re-biasing the exponent;
+// then shift and set the bottom bit
+
+static stua_obj stu__floatp(float *f)
+{
+ unsigned int n = *(unsigned int *) f;
+ unsigned int e = n & (0xff << 23);
+
+ assert(sizeof(int) == 4 && sizeof(float) == 4);
+
+ if (!e) // zero?
+ n = n; // no change
+ else if (e < (64 << 23)) // underflow of the packed encoding?
+ n = (n & 0x80000000); // signed 0
+ else if (e > (190 << 23)) // overflow of the encoding? (or INF or NAN)
+ n = (n & 0x80000000) + (127 << 23); // new INF encoding
+ else
+ n -= 0x20000000;
+
+ // now we need to shuffle the bits so that the spare bit is at the bottom
+ assert((n & 0x40000000) == 0);
+ return (n & 0x80000000) + (n << 1) + 1;
+}
+
+static unsigned char stu__getfloat_addend[256];
+static float stu__getfloat(stua_obj v)
+{
+ unsigned int n;
+ unsigned int e = ((unsigned int) v) >> 24;
+
+ n = (int) v >> 1; // preserve high bit
+ n += stu__getfloat_addend[e] << 24;
+ return *(float *) &n;
+}
+
+stua_obj stua_float(float f)
+{
+ return stu__floatp(&f);
+}
+
+static void stu__float_init(void)
+{
+ int i;
+ stu__getfloat_addend[0] = 0; // do nothing to biased exponent of 0
+ for (i=1; i < 127; ++i)
+ stu__getfloat_addend[i] = 32; // undo the -0x20000000
+ stu__getfloat_addend[127] = 64; // convert packed INF to INF (0x3f -> 0x7f)
+
+ for (i=0; i < 128; ++i) // for signed floats, remove the bit we just shifted down
+ stu__getfloat_addend[128+i] = stu__getfloat_addend[i] - 64;
+}
+
+// Tagged data type implementation
+
+ // TAGS:
+#define stu__int_tag 0 // of 2 bits // 00 int
+#define stu__float_tag 1 // of 1 bit // 01 float
+#define stu__ptr_tag 2 // of 2 bits // 10 boxed
+ // 11 float
+
+#define stu__tag(x) ((x) & 3)
+#define stu__number(x) (stu__tag(x) != stu__ptr_tag)
+#define stu__isint(x) (stu__tag(x) == stu__int_tag)
+
+#define stu__int(x) ((x) >> 2)
+#define stu__float(x) (stu__getfloat(x))
+
+#define stu__makeint(v) ((v)*4+stu__int_tag)
+
+// boxed data, and tag support for boxed data
+
+enum
+{
+ STU___float = 1, STU___int = 2,
+ STU___number = 3, STU___string = 4,
+ STU___function = 5, STU___dict = 6,
+ STU___boolean = 7, STU___error = 8,
+};
+
+// boxed data
+#define STU__BOX short type, stua_gc
+typedef struct stu__box { STU__BOX; } stu__box;
+
+stu__box stu__nil = { 0, 1 };
+stu__box stu__true = { STU___boolean, 1, };
+stu__box stu__false = { STU___boolean, 1, };
+
+#define stu__makeptr(v) ((stua_obj) (v) + stu__ptr_tag)
+
+#define stua_nil stu__makeptr(&stu__nil)
+#define stua_true stu__makeptr(&stu__true)
+#define stua_false stu__makeptr(&stu__false)
+
+stua_obj stua_getnil(void) { return stua_nil; }
+stua_obj stua_getfalse(void) { return stua_false; }
+stua_obj stua_gettrue(void) { return stua_true; }
+
+#define stu__ptr(x) ((stu__box *) ((x) - stu__ptr_tag))
+
+#define stu__checkt(t,x) ((t) == STU___float ? ((x) & 1) == stu__float_tag : \
+ (t) == STU___int ? stu__isint(x) : \
+ (t) == STU___number ? stu__number(x) : \
+ stu__tag(x) == stu__ptr_tag && stu__ptr(x)->type == (t))
+
+typedef struct
+{
+ STU__BOX;
+ void *ptr;
+} stu__wrapper;
+
+// implementation of a 'function' or function + closure
+
+typedef struct stu__func
+{
+ STU__BOX;
+ stua_obj closure_source; // 0 - regular function; 4 - C function
+ // if closure, pointer to source function
+ union {
+ stua_obj closure_data; // partial-application data
+ void *store; // pointer to free that holds 'code'
+ stua_obj (*func)(stua_dict *context);
+ } f;
+ // closure ends here
+ short *code;
+ int num_param;
+ stua_obj *param; // list of parameter strings
+} stu__func;
+
+// apply this to 'short *code' to get at data
+#define stu__const(f) ((stua_obj *) (f))
+
+static void stu__free_func(stu__func *f)
+{
+ if (f->closure_source == 0) free(f->f.store);
+ if ((stb_uint) f->closure_source <= 4) free(f->param);
+ free(f);
+}
+
+#define stu__pd(x) ((stua_dict *) stu__ptr(x))
+#define stu__pw(x) ((stu__wrapper *) stu__ptr(x))
+#define stu__pf(x) ((stu__func *) stu__ptr(x))
+
+
+// garbage-collection
+
+
+static stu__box ** stu__gc_ptrlist;
+static stua_obj * stu__gc_root_stack;
+
+stua_obj stua_pushroot(stua_obj o) { stb_arr_push(stu__gc_root_stack, o); return o; }
+void stua_poproot ( void ) { stb_arr_pop(stu__gc_root_stack); }
+
+static stb_sdict *stu__strings;
+static void stu__mark(stua_obj z)
+{
+ int i;
+ stu__box *p = stu__ptr(z);
+ if (p->stua_gc == 1) return; // already marked
+ assert(p->stua_gc == 0);
+ p->stua_gc = 1;
+ switch(p->type) {
+ case STU___function: {
+ stu__func *f = (stu__func *) p;
+ if ((stb_uint) f->closure_source <= 4) {
+ if (f->closure_source == 0) {
+ for (i=1; i <= f->code[0]; ++i)
+ if (!stu__number(((stua_obj *) f->code)[-i]))
+ stu__mark(((stua_obj *) f->code)[-i]);
+ }
+ for (i=0; i < f->num_param; ++i)
+ stu__mark(f->param[i]);
+ } else {
+ stu__mark(f->closure_source);
+ stu__mark(f->f.closure_data);
+ }
+ break;
+ }
+ case STU___dict: {
+ stua_dict *e = (stua_dict *) p;
+ for (i=0; i < e->limit; ++i)
+ if (e->table[i].k != STB_IEMPTY && e->table[i].k != STB_IDEL) {
+ if (!stu__number(e->table[i].k)) stu__mark((int) e->table[i].k);
+ if (!stu__number(e->table[i].v)) stu__mark((int) e->table[i].v);
+ }
+ break;
+ }
+ }
+}
+
+static int stu__num_allocs, stu__size_allocs;
+static stua_obj stu__flow_val = stua_nil; // used for break & return
+
+static void stua_gc(int force)
+{
+ int i;
+ if (!force && stu__num_allocs == 0 && stu__size_allocs == 0) return;
+ stu__num_allocs = stu__size_allocs = 0;
+ //printf("[gc]\n");
+
+ // clear marks
+ for (i=0; i < stb_arr_len(stu__gc_ptrlist); ++i)
+ stu__gc_ptrlist[i]->stua_gc = 0;
+
+ // stu__mark everything reachable
+ stu__nil.stua_gc = stu__true.stua_gc = stu__false.stua_gc = 1;
+ stu__mark(stua_globals);
+ if (!stu__number(stu__flow_val))
+ stu__mark(stu__flow_val);
+ for (i=0; i < stb_arr_len(stu__gc_root_stack); ++i)
+ if (!stu__number(stu__gc_root_stack[i]))
+ stu__mark(stu__gc_root_stack[i]);
+
+ // sweep unreachables
+ for (i=0; i < stb_arr_len(stu__gc_ptrlist);) {
+ stu__box *z = stu__gc_ptrlist[i];
+ if (!z->stua_gc) {
+ switch (z->type) {
+ case STU___dict: stb_idict_destroy((stua_dict *) z); break;
+ case STU___error: free(((stu__wrapper *) z)->ptr); break;
+ case STU___string: stb_sdict_remove(stu__strings, (char*) ((stu__wrapper *) z)->ptr, NULL); free(z); break;
+ case STU___function: stu__free_func((stu__func *) z); break;
+ }
+ // swap in the last item over this, and repeat
+ z = stb_arr_pop(stu__gc_ptrlist);
+ stu__gc_ptrlist[i] = z;
+ } else
+ ++i;
+ }
+}
+
+static void stu__consider_gc(stua_obj x)
+{
+ if (stu__size_allocs < 100000) return;
+ if (stu__num_allocs < 10 && stu__size_allocs < 1000000) return;
+ stb_arr_push(stu__gc_root_stack, x);
+ stua_gc(0);
+ stb_arr_pop(stu__gc_root_stack);
+}
+
+static stua_obj stu__makeobj(int type, void *data, int size, int safe_to_gc)
+{
+ stua_obj x = stu__makeptr(data);
+ ((stu__box *) data)->type = type;
+ stb_arr_push(stu__gc_ptrlist, (stu__box *) data);
+ stu__num_allocs += 1;
+ stu__size_allocs += size;
+ if (safe_to_gc) stu__consider_gc(x);
+ return x;
+}
+
+stua_obj stua_box(int type, void *data, int size)
+{
+ stu__wrapper *p = (stu__wrapper *) malloc(sizeof(*p));
+ p->ptr = data;
+ return stu__makeobj(type, p, size, 0);
+}
+
+// a stu string can be directly compared for equality, because
+// they go into a hash table
+stua_obj stua_string(char *z)
+{
+ stu__wrapper *b = (stu__wrapper *) stb_sdict_get(stu__strings, z);
+ if (b == NULL) {
+ int o = stua_box(STU___string, NULL, strlen(z) + sizeof(*b));
+ b = stu__pw(o);
+ stb_sdict_add(stu__strings, z, b);
+ stb_sdict_getkey(stu__strings, z, (char **) &b->ptr);
+ }
+ return stu__makeptr(b);
+}
+
+// stb_obj dictionary is just an stb_idict
+static void stu__set(stua_dict *d, stua_obj k, stua_obj v)
+{ if (stb_idict_set(d, k, v)) stu__size_allocs += 8; }
+
+static stua_obj stu__get(stua_dict *d, stua_obj k, stua_obj res)
+{
+ stb_idict_get_flag(d, k, &res);
+ return res;
+}
+
+static stua_obj make_string(char *z, int len)
+{
+ stua_obj s;
+ char temp[256], *q = (char *) stb_temp(temp, len+1), *p = q;
+ while (len > 0) {
+ if (*z == '\\') {
+ if (z[1] == 'n') *p = '\n';
+ else if (z[1] == 'r') *p = '\r';
+ else if (z[1] == 't') *p = '\t';
+ else *p = z[1];
+ p += 1; z += 2; len -= 2;
+ } else {
+ *p++ = *z++; len -= 1;
+ }
+ }
+ *p = 0;
+ s = stua_string(q);
+ stb_tempfree(temp, q);
+ return s;
+}
+
+enum token_names
+{
+ T__none=128,
+ ST_shl = STUA_op_shl, ST_ge = STUA_op_ge,
+ ST_shr = STUA_op_shr, ST_le = STUA_op_le,
+ ST_shru = STUA_op_shru, STU__negate = STUA_op_negate,
+ ST__reset_numbering = STUA_op_last,
+ ST_white,
+ ST_id, ST_float, ST_decimal, ST_hex, ST_char,ST_string, ST_number,
+ // make sure the keywords come _AFTER_ ST_id, so stb_lex prefer them
+ ST_if, ST_while, ST_for, ST_eq, ST_nil,
+ ST_then, ST_do, ST_in, ST_ne, ST_true,
+ ST_else, ST_break, ST_let, ST_and, ST_false,
+ ST_elseif, ST_continue, ST_into, ST_or, ST_repeat,
+ ST_end, ST_as, ST_return, ST_var, ST_func,
+ ST_catch, ST__frame,
+ ST__max_terminals,
+
+ STU__defaultparm, STU__seq,
+};
+
+static stua_dict * stu__globaldict;
+ stua_obj stua_globals;
+
+static enum
+{
+ FLOW_normal, FLOW_continue, FLOW_break, FLOW_return, FLOW_error,
+} stu__flow;
+
+stua_obj stua_error(char *z, ...)
+{
+ stua_obj a;
+ char temp[4096], *x;
+ va_list v; va_start(v,z); vsprintf(temp, z, v); va_end(v);
+ x = stb_p_strdup(temp);
+ a = stua_box(STU___error, x, strlen(x));
+ stu__flow = FLOW_error;
+ stu__flow_val = a;
+ return stua_nil;
+}
+
+double stua_number(stua_obj z)
+{
+ return stu__tag(z) == stu__int_tag ? stu__int(z) : stu__float(z);
+}
+
+stua_obj stua_make_number(double d)
+{
+ double e = floor(d);
+ if (e == d && e < (1 << 29) && e >= -(1 << 29))
+ return stu__makeint((int) e);
+ else
+ return stua_float((float) d);
+}
+
+stua_obj (*stua_overload)(int op, stua_obj a, stua_obj b, stua_obj c) = NULL;
+
+static stua_obj stu__op(int op, stua_obj a, stua_obj b, stua_obj c)
+{
+ stua_obj r = STUA_NO_VALUE;
+ if (op == '+') {
+ if (stu__checkt(STU___string, a) && stu__checkt(STU___string, b)) {
+ ;// @TODO: string concatenation
+ } else if (stu__checkt(STU___function, a) && stu__checkt(STU___dict, b)) {
+ stu__func *f = (stu__func *) malloc(12);
+ assert(offsetof(stu__func, code)==12);
+ f->closure_source = a;
+ f->f.closure_data = b;
+ return stu__makeobj(STU___function, f, 16, 1);
+ }
+ }
+ if (stua_overload) r = stua_overload(op,a,b,c);
+ if (stu__flow != FLOW_error && r == STUA_NO_VALUE)
+ stua_error("Typecheck for operator %d", op), r=stua_nil;
+ return r;
+}
+
+#define STU__EVAL2(a,b) \
+ a = stu__eval(stu__f[n+1]); if (stu__flow) break; stua_pushroot(a); \
+ b = stu__eval(stu__f[n+2]); stua_poproot(); if (stu__flow) break;
+
+#define STU__FB(op) \
+ STU__EVAL2(a,b) \
+ if (stu__tag(a) == stu__int_tag && stu__tag(b) == stu__int_tag) \
+ return ((a) op (b)); \
+ if (stu__number(a) && stu__number(b)) \
+ return stua_make_number(stua_number(a) op stua_number(b)); \
+ return stu__op(stu__f[n], a,b, stua_nil)
+
+#define STU__F(op) \
+ STU__EVAL2(a,b) \
+ if (stu__number(a) && stu__number(b)) \
+ return stua_make_number(stua_number(a) op stua_number(b)); \
+ return stu__op(stu__f[n], a,b, stua_nil)
+
+#define STU__I(op) \
+ STU__EVAL2(a,b) \
+ if (stu__tag(a) == stu__int_tag && stu__tag(b) == stu__int_tag) \
+ return stu__makeint(stu__int(a) op stu__int(b)); \
+ return stu__op(stu__f[n], a,b, stua_nil)
+
+#define STU__C(op) \
+ STU__EVAL2(a,b) \
+ if (stu__number(a) && stu__number(b)) \
+ return (stua_number(a) op stua_number(b)) ? stua_true : stua_false; \
+ return stu__op(stu__f[n], a,b, stua_nil)
+
+#define STU__CE(op) \
+ STU__EVAL2(a,b) \
+ return (a op b) ? stua_true : stua_false
+
+static short *stu__f;
+static stua_obj stu__f_obj;
+static stua_dict *stu__c;
+static stua_obj stu__funceval(stua_obj fo, stua_obj co);
+
+static int stu__cond(stua_obj x)
+{
+ if (stu__flow) return 0;
+ if (!stu__checkt(STU___boolean, x))
+ x = stu__op('!', x, stua_nil, stua_nil);
+ if (x == stua_true ) return 1;
+ if (x == stua_false) return 0;
+ stu__flow = FLOW_error;
+ return 0;
+}
+
+// had to manually eliminate tailcall recursion for debugging complex stuff
+#define TAILCALL(x) n = (x); goto top;
+static stua_obj stu__eval(int n)
+{
+top:
+ if (stu__flow >= FLOW_return) return stua_nil; // is this needed?
+ if (n < 0) return stu__const(stu__f)[n];
+ assert(n != 0 && n != 1);
+ switch (stu__f[n]) {
+ stua_obj a,b,c;
+ case ST_catch: a = stu__eval(stu__f[n+1]);
+ if (stu__flow == FLOW_error) { a=stu__flow_val; stu__flow = FLOW_normal; }
+ return a;
+ case ST_var: b = stu__eval(stu__f[n+2]); if (stu__flow) break;
+ stu__set(stu__c, stu__const(stu__f)[stu__f[n+1]], b);
+ return b;
+ case STU__seq: stu__eval(stu__f[n+1]); if (stu__flow) break;
+ TAILCALL(stu__f[n+2]);
+ case ST_if: if (!stu__cond(stu__eval(stu__f[n+1]))) return stua_nil;
+ TAILCALL(stu__f[n+2]);
+ case ST_else: a = stu__cond(stu__eval(stu__f[n+1]));
+ TAILCALL(stu__f[n + 2 + !a]);
+ #define STU__HANDLE_BREAK \
+ if (stu__flow >= FLOW_break) { \
+ if (stu__flow == FLOW_break) { \
+ a = stu__flow_val; \
+ stu__flow = FLOW_normal; \
+ stu__flow_val = stua_nil; \
+ return a; \
+ } \
+ return stua_nil; \
+ }
+ case ST_as: stu__eval(stu__f[n+3]);
+ STU__HANDLE_BREAK
+ // fallthrough!
+ case ST_while: a = stua_nil; stua_pushroot(a);
+ while (stu__cond(stu__eval(stu__f[n+1]))) {
+ stua_poproot();
+ a = stu__eval(stu__f[n+2]);
+ STU__HANDLE_BREAK
+ stu__flow = FLOW_normal; // clear 'continue' flag
+ stua_pushroot(a);
+ if (stu__f[n+3]) stu__eval(stu__f[n+3]);
+ STU__HANDLE_BREAK
+ stu__flow = FLOW_normal; // clear 'continue' flag
+ }
+ stua_poproot();
+ return a;
+ case ST_break: stu__flow = FLOW_break; stu__flow_val = stu__eval(stu__f[n+1]); break;
+ case ST_continue:stu__flow = FLOW_continue; break;
+ case ST_return: stu__flow = FLOW_return; stu__flow_val = stu__eval(stu__f[n+1]); break;
+ case ST__frame: return stu__f_obj;
+ case '[': STU__EVAL2(a,b);
+ if (stu__checkt(STU___dict, a))
+ return stu__get(stu__pd(a), b, stua_nil);
+ return stu__op(stu__f[n], a, b, stua_nil);
+ case '=': a = stu__eval(stu__f[n+2]); if (stu__flow) break;
+ n = stu__f[n+1];
+ if (stu__f[n] == ST_id) {
+ if (!stb_idict_update(stu__c, stu__const(stu__f)[stu__f[n+1]], a))
+ if (!stb_idict_update(stu__globaldict, stu__const(stu__f)[stu__f[n+1]], a))
+ return stua_error("Assignment to undefined variable");
+ } else if (stu__f[n] == '[') {
+ stua_pushroot(a);
+ b = stu__eval(stu__f[n+1]); if (stu__flow) { stua_poproot(); break; }
+ stua_pushroot(b);
+ c = stu__eval(stu__f[n+2]); stua_poproot(); stua_poproot();
+ if (stu__flow) break;
+ if (!stu__checkt(STU___dict, b)) return stua_nil;
+ stu__set(stu__pd(b), c, a);
+ } else {
+ return stu__op(stu__f[n], stu__eval(n), a, stua_nil);
+ }
+ return a;
+ case STU__defaultparm:
+ a = stu__eval(stu__f[n+2]);
+ stu__flow = FLOW_normal;
+ if (stb_idict_add(stu__c, stu__const(stu__f)[stu__f[n+1]], a))
+ stu__size_allocs += 8;
+ return stua_nil;
+ case ST_id: a = stu__get(stu__c, stu__const(stu__f)[stu__f[n+1]], STUA_NO_VALUE); // try local variable
+ return a != STUA_NO_VALUE // else try stu__compile_global_scope variable
+ ? a : stu__get(stu__globaldict, stu__const(stu__f)[stu__f[n+1]], stua_nil);
+ case STU__negate:a = stu__eval(stu__f[n+1]); if (stu__flow) break;
+ return stu__isint(a) ? -a : stu__op(stu__f[n], a, stua_nil, stua_nil);
+ case '~': a = stu__eval(stu__f[n+1]); if (stu__flow) break;
+ return stu__isint(a) ? (~a)&~3 : stu__op(stu__f[n], a, stua_nil, stua_nil);
+ case '!': a = stu__eval(stu__f[n+1]); if (stu__flow) break;
+ a = stu__cond(a); if (stu__flow) break;
+ return a ? stua_true : stua_false;
+ case ST_eq: STU__CE(==); case ST_le: STU__C(<=); case '<': STU__C(<);
+ case ST_ne: STU__CE(!=); case ST_ge: STU__C(>=); case '>': STU__C(>);
+ case '+' : STU__FB(+); case '*': STU__F(*); case '&': STU__I(&); case ST_shl: STU__I(<<);
+ case '-' : STU__FB(-); case '/': STU__F(/); case '|': STU__I(|); case ST_shr: STU__I(>>);
+ case '%': STU__I(%); case '^': STU__I(^);
+ case ST_shru: STU__EVAL2(a,b);
+ if (stu__tag(a) == stu__int_tag && stu__tag(b) == stu__int_tag)
+ return stu__makeint((unsigned) stu__int(a) >> stu__int(b));
+ return stu__op(stu__f[n], a,b, stua_nil);
+ case ST_and: a = stu__eval(stu__f[n+1]); b = stu__cond(a); if (stu__flow) break;
+ return a ? stu__eval(stu__f[n+2]) : a;
+ case ST_or : a = stu__eval(stu__f[n+1]); b = stu__cond(a); if (stu__flow) break;
+ return a ? b : stu__eval(stu__f[n+2]);
+ case'(':case':': STU__EVAL2(a,b);
+ if (!stu__checkt(STU___function, a))
+ return stu__op(stu__f[n], a,b, stua_nil);
+ if (!stu__checkt(STU___dict, b))
+ return stua_nil;
+ if (stu__f[n] == ':')
+ b = stu__makeobj(STU___dict, stb_idict_copy(stu__pd(b)), stb_idict_memory_usage(stu__pd(b)), 0);
+ a = stu__funceval(a,b);
+ return a;
+ case '{' : {
+ stua_dict *d;
+ d = stb_idict_new_size(stu__f[n+1] > 40 ? 64 : 16);
+ if (d == NULL)
+ return stua_nil; // breakpoint fodder
+ c = stu__makeobj(STU___dict, d, 32, 1);
+ stua_pushroot(c);
+ a = stu__f[n+1];
+ for (b=0; b < a; ++b) {
+ stua_obj x = stua_pushroot(stu__eval(stu__f[n+2 + b*2 + 0]));
+ stua_obj y = stu__eval(stu__f[n+2 + b*2 + 1]);
+ stua_poproot();
+ if (stu__flow) { stua_poproot(); return stua_nil; }
+ stu__set(d, x, y);
+ }
+ stua_poproot();
+ return c;
+ }
+ default: if (stu__f[n] < 0) return stu__const(stu__f)[stu__f[n]];
+ assert(0); /* NOTREACHED */ // internal error!
+ }
+ return stua_nil;
+}
+
+int stb__stua_nesting;
+static stua_obj stu__funceval(stua_obj fo, stua_obj co)
+{
+ stu__func *f = stu__pf(fo);
+ stua_dict *context = stu__pd(co);
+ int i,j;
+ stua_obj p;
+ short *tf = stu__f; // save previous function
+ stua_dict *tc = stu__c;
+
+ if (stu__flow == FLOW_error) return stua_nil;
+ assert(stu__flow == FLOW_normal);
+
+ stua_pushroot(fo);
+ stua_pushroot(co);
+ stu__consider_gc(stua_nil);
+
+ while ((stb_uint) f->closure_source > 4) {
+ // add data from closure to context
+ stua_dict *e = (stua_dict *) stu__pd(f->f.closure_data);
+ for (i=0; i < e->limit; ++i)
+ if (e->table[i].k != STB_IEMPTY && e->table[i].k != STB_IDEL)
+ if (stb_idict_add(context, e->table[i].k, e->table[i].v))
+ stu__size_allocs += 8;
+ // use add so if it's already defined, we don't override it; that way
+ // explicit parameters win over applied ones, and most recent applications
+ // win over previous ones
+ f = stu__pf(f->closure_source);
+ }
+
+ for (j=0, i=0; i < f->num_param; ++i)
+ // if it doesn't already exist, add it from the numbered parameters
+ if (stb_idict_add(context, f->param[i], stu__get(context, stu__int(j), stua_nil)))
+ ++j;
+
+ // @TODO: if (stu__get(context, stu__int(f->num_param+1)) != STUA_NO_VALUE) // error: too many parameters
+ // @TODO: ditto too few parameters
+
+ if (f->closure_source == 4)
+ p = f->f.func(context);
+ else {
+ stu__f = f->code, stu__c = context;
+ stu__f_obj = co;
+ ++stb__stua_nesting;
+ if (stu__f[1])
+ p = stu__eval(stu__f[1]);
+ else
+ p = stua_nil;
+ --stb__stua_nesting;
+ stu__f = tf, stu__c = tc; // restore previous function
+ if (stu__flow == FLOW_return) {
+ stu__flow = FLOW_normal;
+ p = stu__flow_val;
+ stu__flow_val = stua_nil;
+ }
+ }
+
+ stua_poproot();
+ stua_poproot();
+
+ return p;
+}
+
+// Parser
+
+static int stu__tok;
+static stua_obj stu__tokval;
+
+static char *stu__curbuf, *stu__bufstart;
+
+static stb_matcher *stu__lex_matcher;
+
+static unsigned char stu__prec[ST__max_terminals], stu__end[ST__max_terminals];
+
+static void stu__nexttoken(void)
+{
+ int len;
+
+retry:
+ stu__tok = stb_lex(stu__lex_matcher, stu__curbuf, &len);
+ if (stu__tok == 0)
+ return;
+ switch(stu__tok) {
+ case ST_white : stu__curbuf += len; goto retry;
+ case T__none : stu__tok = *stu__curbuf; break;
+ case ST_string: stu__tokval = make_string(stu__curbuf+1, len-2); break;
+ case ST_id : stu__tokval = make_string(stu__curbuf, len); break;
+ case ST_hex : stu__tokval = stu__makeint(strtol(stu__curbuf+2,NULL,16)); stu__tok = ST_number; break;
+ case ST_decimal: stu__tokval = stu__makeint(strtol(stu__curbuf ,NULL,10)); stu__tok = ST_number; break;
+ case ST_float : stu__tokval = stua_float((float) atof(stu__curbuf)) ; stu__tok = ST_number; break;
+ case ST_char : stu__tokval = stu__curbuf[2] == '\\' ? stu__curbuf[3] : stu__curbuf[2];
+ if (stu__curbuf[3] == 't') stu__tokval = '\t';
+ if (stu__curbuf[3] == 'n') stu__tokval = '\n';
+ if (stu__curbuf[3] == 'r') stu__tokval = '\r';
+ stu__tokval = stu__makeint(stu__tokval);
+ stu__tok = ST_number;
+ break;
+ }
+ stu__curbuf += len;
+}
+
+static struct { int stu__tok; char *regex; } stu__lexemes[] =
+{
+ ST_white , "([ \t\n\r]|/\\*(.|\n)*\\*/|//[^\r\n]*([\r\n]|$))+",
+ ST_id , "[_a-zA-Z][_a-zA-Z0-9]*",
+ ST_hex , "0x[0-9a-fA-F]+",
+ ST_decimal, "[0-9]+[0-9]*",
+ ST_float , "[0-9]+\\.?[0-9]*([eE][-+]?[0-9]+)?",
+ ST_float , "\\.[0-9]+([eE][-+]?[0-9]+)?",
+ ST_char , "c'(\\\\.|[^\\'])'",
+ ST_string , "\"(\\\\.|[^\\\"\n\r])*\"",
+ ST_string , "\'(\\\\.|[^\\\'\n\r])*\'",
+
+ #define stua_key4(a,b,c,d) ST_##a, #a, ST_##b, #b, ST_##c, #c, ST_##d, #d,
+ stua_key4(if,then,else,elseif) stua_key4(while,do,for,in)
+ stua_key4(func,var,let,break) stua_key4(nil,true,false,end)
+ stua_key4(return,continue,as,repeat) stua_key4(_frame,catch,catch,catch)
+
+ ST_shl, "<<", ST_and, "&&", ST_eq, "==", ST_ge, ">=",
+ ST_shr, ">>", ST_or , "||", ST_ne, "!=", ST_le, "<=",
+ ST_shru,">>>", ST_into, "=>",
+ T__none, ".",
+};
+
+typedef struct
+{
+ stua_obj *data; // constants being compiled
+ short *code; // code being compiled
+ stua_dict *locals;
+ short *non_local_refs;
+} stu__comp_func;
+
+static stu__comp_func stu__pfunc;
+static stu__comp_func *func_stack = NULL;
+static void stu__push_func_comp(void)
+{
+ stb_arr_push(func_stack, stu__pfunc);
+ stu__pfunc.data = NULL;
+ stu__pfunc.code = NULL;
+ stu__pfunc.locals = stb_idict_new_size(16);
+ stu__pfunc.non_local_refs = NULL;
+ stb_arr_push(stu__pfunc.code, 0); // number of data items
+ stb_arr_push(stu__pfunc.code, 1); // starting execution address
+}
+
+static void stu__pop_func_comp(void)
+{
+ stb_arr_free(stu__pfunc.code);
+ stb_arr_free(stu__pfunc.data);
+ stb_idict_destroy(stu__pfunc.locals);
+ stb_arr_free(stu__pfunc.non_local_refs);
+ stu__pfunc = stb_arr_pop(func_stack);
+}
+
+// if an id is a reference to an outer lexical scope, this
+// function returns the "name" of it, and updates the stack
+// structures to make sure the names are propagated in.
+static int stu__nonlocal_id(stua_obj var_obj)
+{
+ stua_obj dummy, var = var_obj;
+ int i, n = stb_arr_len(func_stack), j,k;
+ if (stb_idict_get_flag(stu__pfunc.locals, var, &dummy)) return 0;
+ for (i=n-1; i > 1; --i) {
+ if (stb_idict_get_flag(func_stack[i].locals, var, &dummy))
+ break;
+ }
+ if (i <= 1) return 0; // stu__compile_global_scope
+ j = i; // need to access variable from j'th frame
+ for (i=0; i < stb_arr_len(stu__pfunc.non_local_refs); ++i)
+ if (stu__pfunc.non_local_refs[i] == j) return j-n;
+ stb_arr_push(stu__pfunc.non_local_refs, j-n);
+ // now make sure all the parents propagate it down
+ for (k=n-1; k > 1; --k) {
+ if (j-k >= 0) return j-n; // comes direct from this parent
+ for(i=0; i < stb_arr_len(func_stack[k].non_local_refs); ++i)
+ if (func_stack[k].non_local_refs[i] == j-k)
+ return j-n;
+ stb_arr_push(func_stack[k].non_local_refs, j-k);
+ }
+ assert (k != 1);
+
+ return j-n;
+}
+
+static int stu__off(void) { return stb_arr_len(stu__pfunc.code); }
+static void stu__cc(int a)
+{
+ assert(a >= -2000 && a < 5000);
+ stb_arr_push(stu__pfunc.code, a);
+}
+static int stu__cc1(int a) { stu__cc(a); return stu__off()-1; }
+static int stu__cc2(int a, int b) { stu__cc(a); stu__cc(b); return stu__off()-2; }
+static int stu__cc3(int a, int b, int c) {
+ if (a == '=') assert(c != 0);
+ stu__cc(a); stu__cc(b); stu__cc(c); return stu__off()-3; }
+static int stu__cc4(int a, int b, int c, int d) { stu__cc(a); stu__cc(b); stu__cc(c); stu__cc(d); return stu__off()-4; }
+
+static int stu__cdv(stua_obj p)
+{
+ int i;
+ assert(p != STUA_NO_VALUE);
+ for (i=0; i < stb_arr_len(stu__pfunc.data); ++i)
+ if (stu__pfunc.data[i] == p)
+ break;
+ if (i == stb_arr_len(stu__pfunc.data))
+ stb_arr_push(stu__pfunc.data, p);
+ return ~i;
+}
+
+static int stu__cdt(void)
+{
+ int z = stu__cdv(stu__tokval);
+ stu__nexttoken();
+ return z;
+}
+
+static int stu__seq(int a, int b)
+{
+ return !a ? b : !b ? a : stu__cc3(STU__seq, a,b);
+}
+
+static char stu__comp_err_str[1024];
+static int stu__comp_err_line;
+static int stu__err(char *str, ...)
+{
+ va_list v;
+ char *s = stu__bufstart;
+ stu__comp_err_line = 1;
+ while (s < stu__curbuf) {
+ if (s[0] == '\n' || s[0] == '\r') {
+ if (s[0]+s[1] == '\n' + '\r') ++s;
+ ++stu__comp_err_line;
+ }
+ ++s;
+ }
+ va_start(v, str);
+ vsprintf(stu__comp_err_str, str, v);
+ va_end(v);
+ return 0;
+}
+
+static int stu__accept(int p)
+{
+ if (stu__tok != p) return 0;
+ stu__nexttoken();
+ return 1;
+}
+
+static int stu__demand(int p)
+{
+ if (stu__accept(p)) return 1;
+ return stu__err("Didn't find expected stu__tok");
+}
+
+static int stu__demandv(int p, stua_obj *val)
+{
+ if (stu__tok == p || p==0) {
+ *val = stu__tokval;
+ stu__nexttoken();
+ return 1;
+ } else
+ return 0;
+}
+
+static int stu__expr(int p);
+int stu__nexpr(int p) { stu__nexttoken(); return stu__expr(p); }
+static int stu__statements(int once, int as);
+
+static int stu__parse_if(void) // parse both ST_if and ST_elseif
+{
+ int b,c,a;
+ a = stu__nexpr(1); if (!a) return 0;
+ if (!stu__demand(ST_then)) return stu__err("expecting THEN");
+ b = stu__statements(0,0); if (!b) return 0;
+ if (b == 1) b = -1;
+
+ if (stu__tok == ST_elseif) {
+ return stu__parse_if();
+ } else if (stu__accept(ST_else)) {
+ c = stu__statements(0,0); if (!c) return 0;
+ if (!stu__demand(ST_end)) return stu__err("expecting END after else clause");
+ return stu__cc4(ST_else, a, b, c);
+ } else {
+ if (!stu__demand(ST_end)) return stu__err("expecting END in if statement");
+ return stu__cc3(ST_if, a, b);
+ }
+}
+
+int stu__varinit(int z, int in_globals)
+{
+ int a,b;
+ stu__nexttoken();
+ while (stu__demandv(ST_id, &b)) {
+ if (!stb_idict_add(stu__pfunc.locals, b, 1))
+ if (!in_globals) return stu__err("Redefined variable %s.", stu__pw(b)->ptr);
+ if (stu__accept('=')) {
+ a = stu__expr(1); if (!a) return 0;
+ } else
+ a = stu__cdv(stua_nil);
+ z = stu__seq(z, stu__cc3(ST_var, stu__cdv(b), a));
+ if (!stu__accept(',')) break;
+ }
+ return z;
+}
+
+static int stu__compile_unary(int z, int outparm, int require_inparm)
+{
+ int op = stu__tok, a, b;
+ stu__nexttoken();
+ if (outparm) {
+ if (require_inparm || (stu__tok && stu__tok != ST_end && stu__tok != ST_else && stu__tok != ST_elseif && stu__tok !=';')) {
+ a = stu__expr(1); if (!a) return 0;
+ } else
+ a = stu__cdv(stua_nil);
+ b = stu__cc2(op, a);
+ } else
+ b = stu__cc1(op);
+ return stu__seq(z,b);
+}
+
+static int stu__assign(void)
+{
+ int z;
+ stu__accept(ST_let);
+ z = stu__expr(1); if (!z) return 0;
+ if (stu__accept('=')) {
+ int y,p = (z >= 0 ? stu__pfunc.code[z] : 0);
+ if (z < 0 || (p != ST_id && p != '[')) return stu__err("Invalid lvalue in assignment");
+ y = stu__assign(); if (!y) return 0;
+ z = stu__cc3('=', z, y);
+ }
+ return z;
+}
+
+static int stu__statements(int once, int stop_while)
+{
+ int a,b, c, z=0;
+ for(;;) {
+ switch (stu__tok) {
+ case ST_if : a = stu__parse_if(); if (!a) return 0;
+ z = stu__seq(z, a);
+ break;
+ case ST_while : if (stop_while) return (z ? z:1);
+ a = stu__nexpr(1); if (!a) return 0;
+ if (stu__accept(ST_as)) c = stu__statements(0,0); else c = 0;
+ if (!stu__demand(ST_do)) return stu__err("expecting DO");
+ b = stu__statements(0,0); if (!b) return 0;
+ if (!stu__demand(ST_end)) return stu__err("expecting END");
+ if (b == 1) b = -1;
+ z = stu__seq(z, stu__cc4(ST_while, a, b, c));
+ break;
+ case ST_repeat : stu__nexttoken();
+ c = stu__statements(0,1); if (!c) return 0;
+ if (!stu__demand(ST_while)) return stu__err("expecting WHILE");
+ a = stu__expr(1); if (!a) return 0;
+ if (!stu__demand(ST_do)) return stu__err("expecting DO");
+ b = stu__statements(0,0); if (!b) return 0;
+ if (!stu__demand(ST_end)) return stu__err("expecting END");
+ if (b == 1) b = -1;
+ z = stu__seq(z, stu__cc4(ST_as, a, b, c));
+ break;
+ case ST_catch : a = stu__nexpr(1); if (!a) return 0;
+ z = stu__seq(z, stu__cc2(ST_catch, a));
+ break;
+ case ST_var : z = stu__varinit(z,0); break;
+ case ST_return : z = stu__compile_unary(z,1,1); break;
+ case ST_continue:z = stu__compile_unary(z,0,0); break;
+ case ST_break : z = stu__compile_unary(z,1,0); break;
+ case ST_into : if (z == 0 && !once) return stu__err("=> cannot be first statement in block");
+ a = stu__nexpr(99);
+ b = (a >= 0? stu__pfunc.code[a] : 0);
+ if (a < 0 || (b != ST_id && b != '[')) return stu__err("Invalid lvalue on right side of =>");
+ z = stu__cc3('=', a, z);
+ break;
+ default : if (stu__end[stu__tok]) return once ? 0 : (z ? z:1);
+ a = stu__assign(); if (!a) return 0;
+ stu__accept(';');
+ if (stu__tok && !stu__end[stu__tok]) {
+ if (a < 0)
+ return stu__err("Constant has no effect");
+ if (stu__pfunc.code[a] != '(' && stu__pfunc.code[a] != '=')
+ return stu__err("Expression has no effect");
+ }
+ z = stu__seq(z, a);
+ break;
+ }
+ if (!z) return 0;
+ stu__accept(';');
+ if (once && stu__tok != ST_into) return z;
+ }
+}
+
+static int stu__postexpr(int z, int p);
+static int stu__dictdef(int end, int *count)
+{
+ int z,n=0,i,flags=0;
+ short *dict=NULL;
+ stu__nexttoken();
+ while (stu__tok != end) {
+ if (stu__tok == ST_id) {
+ stua_obj id = stu__tokval;
+ stu__nexttoken();
+ if (stu__tok == '=') {
+ flags |= 1;
+ stb_arr_push(dict, stu__cdv(id));
+ z = stu__nexpr(1); if (!z) return 0;
+ } else {
+ z = stu__cc2(ST_id, stu__cdv(id));
+ z = stu__postexpr(z,1); if (!z) return 0;
+ flags |= 2;
+ stb_arr_push(dict, stu__cdv(stu__makeint(n++)));
+ }
+ } else {
+ z = stu__expr(1); if (!z) return 0;
+ flags |= 2;
+ stb_arr_push(dict, stu__cdv(stu__makeint(n++)));
+ }
+ if (end != ')' && flags == 3) { z=stu__err("can't mix initialized and uninitialized defs"); goto done;}
+ stb_arr_push(dict, z);
+ if (!stu__accept(',')) break;
+ }
+ if (!stu__demand(end))
+ return stu__err(end == ')' ? "Expecting ) at end of function call"
+ : "Expecting } at end of dictionary definition");
+ z = stu__cc2('{', stb_arr_len(dict)/2);
+ for (i=0; i < stb_arr_len(dict); ++i)
+ stu__cc(dict[i]);
+ if (count) *count = n;
+done:
+ stb_arr_free(dict);
+ return z;
+}
+
+static int stu__comp_id(void)
+{
+ int z,d;
+ d = stu__nonlocal_id(stu__tokval);
+ if (d == 0)
+ return z = stu__cc2(ST_id, stu__cdt());
+ // access a non-local frame by naming it with the appropriate int
+ assert(d < 0);
+ z = stu__cdv(d); // relative frame # is the 'variable' in our local frame
+ z = stu__cc2(ST_id, z); // now access that dictionary
+ return stu__cc3('[', z, stu__cdt()); // now access the variable from that dir
+}
+
+static stua_obj stu__funcdef(stua_obj *id, stua_obj *func);
+static int stu__expr(int p)
+{
+ int z;
+ // unary
+ switch (stu__tok) {
+ case ST_number: z = stu__cdt(); break;
+ case ST_string: z = stu__cdt(); break; // @TODO - string concatenation like C
+ case ST_id : z = stu__comp_id(); break;
+ case ST__frame: z = stu__cc1(ST__frame); stu__nexttoken(); break;
+ case ST_func : z = stu__funcdef(NULL,NULL); break;
+ case ST_if : z = stu__parse_if(); break;
+ case ST_nil : z = stu__cdv(stua_nil); stu__nexttoken(); break;
+ case ST_true : z = stu__cdv(stua_true); stu__nexttoken(); break;
+ case ST_false : z = stu__cdv(stua_false); stu__nexttoken(); break;
+ case '-' : z = stu__nexpr(99); if (z) z=stu__cc2(STU__negate,z); else return z; break;
+ case '!' : z = stu__nexpr(99); if (z) z=stu__cc2('!',z); else return z; break;
+ case '~' : z = stu__nexpr(99); if (z) z=stu__cc2('~',z); else return z; break;
+ case '{' : z = stu__dictdef('}', NULL); break;
+ default : return stu__err("Unexpected token");
+ case '(' : stu__nexttoken(); z = stu__statements(0,0); if (!stu__demand(')')) return stu__err("Expecting )");
+ }
+ return stu__postexpr(z,p);
+}
+
+static int stu__postexpr(int z, int p)
+{
+ int q;
+ // postfix
+ while (stu__tok == '(' || stu__tok == '[' || stu__tok == '.') {
+ if (stu__accept('.')) {
+ // MUST be followed by a plain identifier! use [] for other stuff
+ if (stu__tok != ST_id) return stu__err("Must follow . with plain name; try [] instead");
+ z = stu__cc3('[', z, stu__cdv(stu__tokval));
+ stu__nexttoken();
+ } else if (stu__accept('[')) {
+ while (stu__tok != ']') {
+ int r = stu__expr(1); if (!r) return 0;
+ z = stu__cc3('[', z, r);
+ if (!stu__accept(',')) break;
+ }
+ if (!stu__demand(']')) return stu__err("Expecting ]");
+ } else {
+ int n, p = stu__dictdef(')', &n); if (!p) return 0;
+ #if 0 // this is incorrect!
+ if (z > 0 && stu__pfunc.code[z] == ST_id) {
+ stua_obj q = stu__get(stu__globaldict, stu__pfunc.data[-stu__pfunc.code[z+1]-1], stua_nil);
+ if (stu__checkt(STU___function, q))
+ if ((stu__pf(q))->num_param != n)
+ return stu__err("Incorrect number of parameters");
+ }
+ #endif
+ z = stu__cc3('(', z, p);
+ }
+ }
+ // binop - this implementation taken from lcc
+ for (q=stu__prec[stu__tok]; q >= p; --q) {
+ while (stu__prec[stu__tok] == q) {
+ int o = stu__tok, y = stu__nexpr(p+1); if (!y) return 0;
+ z = stu__cc3(o,z,y);
+ }
+ }
+ return z;
+}
+
+static stua_obj stu__finish_func(stua_obj *param, int start)
+{
+ int n, size;
+ stu__func *f = (stu__func *) malloc(sizeof(*f));
+ f->closure_source = 0;
+ f->num_param = stb_arr_len(param);
+ f->param = (int *) stb_copy(param, f->num_param * sizeof(*f->param));
+ size = stb_arr_storage(stu__pfunc.code) + stb_arr_storage(stu__pfunc.data) + sizeof(*f) + 8;
+ f->f.store = malloc(stb_arr_storage(stu__pfunc.code) + stb_arr_storage(stu__pfunc.data));
+ f->code = (short *) ((char *) f->f.store + stb_arr_storage(stu__pfunc.data));
+ memcpy(f->code, stu__pfunc.code, stb_arr_storage(stu__pfunc.code));
+ f->code[1] = start;
+ f->code[0] = stb_arr_len(stu__pfunc.data);
+ for (n=0; n < f->code[0]; ++n)
+ ((stua_obj *) f->code)[-1-n] = stu__pfunc.data[n];
+ return stu__makeobj(STU___function, f, size, 0);
+}
+
+static int stu__funcdef(stua_obj *id, stua_obj *result)
+{
+ int n,z=0,i,q;
+ stua_obj *param = NULL;
+ short *nonlocal;
+ stua_obj v,f=stua_nil;
+ assert(stu__tok == ST_func);
+ stu__nexttoken();
+ if (id) {
+ if (!stu__demandv(ST_id, id)) return stu__err("Expecting function name");
+ } else
+ stu__accept(ST_id);
+ if (!stu__demand('(')) return stu__err("Expecting ( for function parameter");
+ stu__push_func_comp();
+ while (stu__tok != ')') {
+ if (!stu__demandv(ST_id, &v)) { z=stu__err("Expecting parameter name"); goto done; }
+ stb_idict_add(stu__pfunc.locals, v, 1);
+ if (stu__tok == '=') {
+ n = stu__nexpr(1); if (!n) { z=0; goto done; }
+ z = stu__seq(z, stu__cc3(STU__defaultparm, stu__cdv(v), n));
+ } else
+ stb_arr_push(param, v);
+ if (!stu__accept(',')) break;
+ }
+ if (!stu__demand(')')) { z=stu__err("Expecting ) at end of parameter list"); goto done; }
+ n = stu__statements(0,0); if (!n) { z=0; goto done; }
+ if (!stu__demand(ST_end)) { z=stu__err("Expecting END at end of function"); goto done; }
+ if (n == 1) n = 0;
+ n = stu__seq(z,n);
+ f = stu__finish_func(param, n);
+ if (result) { *result = f; z=1; stu__pop_func_comp(); }
+ else {
+ nonlocal = stu__pfunc.non_local_refs;
+ stu__pfunc.non_local_refs = NULL;
+ stu__pop_func_comp();
+ z = stu__cdv(f);
+ if (nonlocal) { // build a closure with references to the needed frames
+ short *initcode = NULL;
+ for (i=0; i < stb_arr_len(nonlocal); ++i) {
+ int k = nonlocal[i], p;
+ stb_arr_push(initcode, stu__cdv(k));
+ if (k == -1) p = stu__cc1(ST__frame);
+ else { p = stu__cdv(stu__makeint(k+1)); p = stu__cc2(ST_id, p); }
+ stb_arr_push(initcode, p);
+ }
+ q = stu__cc2('{', stb_arr_len(nonlocal));
+ for (i=0; i < stb_arr_len(initcode); ++i)
+ stu__cc(initcode[i]);
+ z = stu__cc3('+', z, q);
+ stb_arr_free(initcode);
+ }
+ stb_arr_free(nonlocal);
+ }
+done:
+ stb_arr_free(param);
+ if (!z) stu__pop_func_comp();
+ return z;
+}
+
+static int stu__compile_global_scope(void)
+{
+ stua_obj o;
+ int z=0;
+
+ stu__push_func_comp();
+ while (stu__tok != 0) {
+ if (stu__tok == ST_func) {
+ stua_obj id, f;
+ if (!stu__funcdef(&id,&f))
+ goto error;
+ stu__set(stu__globaldict, id, f);
+ } else if (stu__tok == ST_var) {
+ z = stu__varinit(z,1); if (!z) goto error;
+ } else {
+ int y = stu__statements(1,0); if (!y) goto error;
+ z = stu__seq(z,y);
+ }
+ stu__accept(';');
+ }
+ o = stu__finish_func(NULL, z);
+ stu__pop_func_comp();
+
+ o = stu__funceval(o, stua_globals); // initialize stu__globaldict
+ if (stu__flow == FLOW_error)
+ printf("Error: %s\n", ((stu__wrapper *) stu__ptr(stu__flow_val))->ptr);
+ return 1;
+error:
+ stu__pop_func_comp();
+ return 0;
+}
+
+stua_obj stu__myprint(stua_dict *context)
+{
+ stua_obj x = stu__get(context, stua_string("x"), stua_nil);
+ if ((x & 1) == stu__float_tag) printf("%f", stu__getfloat(x));
+ else if (stu__tag(x) == stu__int_tag) printf("%d", stu__int(x));
+ else {
+ stu__wrapper *s = stu__pw(x);
+ if (s->type == STU___string || s->type == STU___error)
+ printf("%s", s->ptr);
+ else if (s->type == STU___dict) printf("{{dictionary}}");
+ else if (s->type == STU___function) printf("[[function]]");
+ else
+ printf("[[ERROR:%s]]", s->ptr);
+ }
+ return x;
+}
+
+void stua_init(void)
+{
+ if (!stu__globaldict) {
+ int i;
+ stua_obj s;
+ stu__func *f;
+
+ stu__prec[ST_and] = stu__prec[ST_or] = 1;
+ stu__prec[ST_eq ] = stu__prec[ST_ne] = stu__prec[ST_le] =
+ stu__prec[ST_ge] = stu__prec['>' ] = stu__prec['<'] = 2;
+ stu__prec[':'] = 3;
+ stu__prec['&'] = stu__prec['|'] = stu__prec['^'] = 4;
+ stu__prec['+'] = stu__prec['-'] = 5;
+ stu__prec['*'] = stu__prec['/'] = stu__prec['%'] =
+ stu__prec[ST_shl]= stu__prec[ST_shr]= stu__prec[ST_shru]= 6;
+
+ stu__end[')'] = stu__end[ST_end] = stu__end[ST_else] = 1;
+ stu__end[ST_do] = stu__end[ST_elseif] = 1;
+
+ stu__float_init();
+ stu__lex_matcher = stb_lex_matcher();
+ for (i=0; i < sizeof(stu__lexemes)/sizeof(stu__lexemes[0]); ++i)
+ stb_lex_item(stu__lex_matcher, stu__lexemes[i].regex, stu__lexemes[i].stu__tok);
+
+ stu__globaldict = stb_idict_new_size(64);
+ stua_globals = stu__makeobj(STU___dict, stu__globaldict, 0,0);
+ stu__strings = stb_sdict_new(0);
+
+ stu__curbuf = stu__bufstart = "func _print(x) end\n"
+ "func print()\n var x=0 while _frame[x] != nil as x=x+1 do _print(_frame[x]) end end\n";
+ stu__nexttoken();
+ if (!stu__compile_global_scope())
+ printf("Compile error in line %d: %s\n", stu__comp_err_line, stu__comp_err_str);
+
+ s = stu__get(stu__globaldict, stua_string("_print"), stua_nil);
+ if (stu__tag(s) == stu__ptr_tag && stu__ptr(s)->type == STU___function) {
+ f = stu__pf(s);
+ free(f->f.store);
+ f->closure_source = 4;
+ f->f.func = stu__myprint;
+ f->code = NULL;
+ }
+ }
+}
+
+void stua_uninit(void)
+{
+ if (stu__globaldict) {
+ stb_idict_remove_all(stu__globaldict);
+ stb_arr_setlen(stu__gc_root_stack, 0);
+ stua_gc(1);
+ stb_idict_destroy(stu__globaldict);
+ stb_sdict_delete(stu__strings);
+ stb_matcher_free(stu__lex_matcher);
+ stb_arr_free(stu__gc_ptrlist);
+ stb_arr_free(func_stack);
+ stb_arr_free(stu__gc_root_stack);
+ stu__globaldict = NULL;
+ }
+}
+
+void stua_run_script(char *s)
+{
+ stua_init();
+
+ stu__curbuf = stu__bufstart = s;
+ stu__nexttoken();
+
+ stu__flow = FLOW_normal;
+
+ if (!stu__compile_global_scope())
+ printf("Compile error in line %d: %s\n", stu__comp_err_line, stu__comp_err_str);
+ stua_gc(1);
+}
+#endif // STB_DEFINE
+#endif // STB_STUA
+
+#undef STB_EXTERN
+#endif // STB_INCLUDE_STB_H
+
+/*
+------------------------------------------------------------------------------
+This software is available under 2 licenses -- choose whichever you prefer.
+------------------------------------------------------------------------------
+ALTERNATIVE A - MIT License
+Copyright (c) 2017 Sean Barrett
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+------------------------------------------------------------------------------
+ALTERNATIVE B - Public Domain (www.unlicense.org)
+This is free and unencumbered software released into the public domain.
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+software, either in source code form or as a compiled binary, for any purpose,
+commercial or non-commercial, and by any means.
+In jurisdictions that recognize copyright laws, the author or authors of this
+software dedicate any and all copyright interest in the software to the public
+domain. We make this dedication for the benefit of the public at large and to
+the detriment of our heirs and successors. We intend this dedication to be an
+overt act of relinquishment in perpetuity of all present and future rights to
+this software under copyright law.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+------------------------------------------------------------------------------
+*/
diff --git a/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/stb_image.h b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/stb_image.h
new file mode 100644
index 0000000..5e807a0
--- /dev/null
+++ b/PrometheOS/PrometheOS-Firmware-1.5.0/PrometheOSXbe/PrometheOSXbe/stb_image.h
@@ -0,0 +1,7987 @@
+/* stb_image - v2.28 - public domain image loader - http://nothings.org/stb
+ no warranty implied; use at your own risk
+
+ Do this:
+ #define STB_IMAGE_IMPLEMENTATION
+ before you include this file in *one* C or C++ file to create the implementation.
+
+ // i.e. it should look like this:
+ #include ...
+ #include ...
+ #include ...
+ #define STB_IMAGE_IMPLEMENTATION
+ #include "stb_image.h"
+
+ You can #define STBI_ASSERT(x) before the #include to avoid using assert.h.
+ And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free
+
+
+ QUICK NOTES:
+ Primarily of interest to game developers and other people who can
+ avoid problematic images and only need the trivial interface
+
+ JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib)
+ PNG 1/2/4/8/16-bit-per-channel
+
+ TGA (not sure what subset, if a subset)
+ BMP non-1bpp, non-RLE
+ PSD (composited view only, no extra channels, 8/16 bit-per-channel)
+
+ GIF (*comp always reports as 4-channel)
+ HDR (radiance rgbE format)
+ PIC (Softimage PIC)
+ PNM (PPM and PGM binary only)
+
+ Animated GIF still needs a proper API, but here's one way to do it:
+ http://gist.github.com/urraka/685d9a6340b26b830d49
+
+ - decode from memory or through FILE (define STBI_NO_STDIO to remove code)
+ - decode from arbitrary I/O callbacks
+ - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON)
+
+ Full documentation under "DOCUMENTATION" below.
+
+
+LICENSE
+
+ See end of file for license information.
+
+RECENT REVISION HISTORY:
+
+ 2.28 (2023-01-29) many error fixes, security errors, just tons of stuff
+ 2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes
+ 2.26 (2020-07-13) many minor fixes
+ 2.25 (2020-02-02) fix warnings
+ 2.24 (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically
+ 2.23 (2019-08-11) fix clang static analysis warning
+ 2.22 (2019-03-04) gif fixes, fix warnings
+ 2.21 (2019-02-25) fix typo in comment
+ 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs
+ 2.19 (2018-02-11) fix warning
+ 2.18 (2018-01-30) fix warnings
+ 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings
+ 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes
+ 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC
+ 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs
+ 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes
+ 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes
+ 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64
+ RGB-format JPEG; remove white matting in PSD;
+ allocate large structures on the stack;
+ correct channel count for PNG & BMP
+ 2.10 (2016-01-22) avoid warning introduced in 2.09
+ 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED
+
+ See end of file for full revision history.
+
+
+ ============================ Contributors =========================
+
+ Image formats Extensions, features
+ Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info)
+ Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info)
+ Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG)
+ Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks)
+ Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG)
+ Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip)
+ Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD)
+ github:urraka (animated gif) Junggon Kim (PNM comments)
+ Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA)
+ socks-the-fox (16-bit PNG)
+ Jeremy Sawicki (handle all ImageNet JPGs)
+ Optimizations & bugfixes Mikhail Morozov (1-bit BMP)
+ Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query)
+ Arseny Kapoulkine Simon Breuss (16-bit PNM)
+ John-Mark Allen
+ Carmelo J Fdez-Aguera
+
+ Bug & warning fixes
+ Marc LeBlanc David Woo Guillaume George Martins Mozeiko
+ Christpher Lloyd Jerry Jansson Joseph Thomson Blazej Dariusz Roszkowski
+ Phil Jordan Dave Moore Roy Eltham
+ Hayaki Saito Nathan Reed Won Chun
+ Luke Graham Johan Duparc Nick Verigakis the Horde3D community
+ Thomas Ruf Ronny Chevalier github:rlyeh
+ Janez Zemva John Bartholomew Michal Cichon github:romigrou
+ Jonathan Blow Ken Hamada Tero Hanninen github:svdijk
+ Eugene Golushkov Laurent Gomila Cort Stratton github:snagar
+ Aruelien Pocheville Sergio Gonzalez Thibault Reuille github:Zelex
+ Cass Everitt Ryamond Barbiero github:grim210
+ Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw
+ Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus
+ Josh Tobin Neil Bickford Matthew Gregan github:poppolopoppo
+ Julian Raschke Gregory Mullen Christian Floisand github:darealshinji
+ Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007
+ Brad Weinberger Matvey Cherevko github:mosra
+ Luca Sas Alexander Veselov Zack Middleton [reserved]
+ Ryan C. Gordon [reserved] [reserved]
+ DO NOT ADD YOUR NAME HERE
+
+ Jacko Dirks
+
+ To add your name to the credits, pick a random blank space in the middle and fill it.
+ 80% of merge conflicts on stb PRs are due to people adding their name at the end
+ of the credits.
+*/
+
+#ifndef STBI_INCLUDE_STB_IMAGE_H
+#define STBI_INCLUDE_STB_IMAGE_H
+
+// DOCUMENTATION
+//
+// Limitations:
+// - no 12-bit-per-channel JPEG
+// - no JPEGs with arithmetic coding
+// - GIF always returns *comp=4
+//
+// Basic usage (see HDR discussion below for HDR usage):
+// int x,y,n;
+// unsigned char *data = stbi_load(filename, &x, &y, &n, 0);
+// // ... process data if not NULL ...
+// // ... x = width, y = height, n = # 8-bit components per pixel ...
+// // ... replace '0' with '1'..'4' to force that many components per pixel
+// // ... but 'n' will always be the number that it would have been if you said 0
+// stbi_image_free(data);
+//
+// Standard parameters:
+// int *x -- outputs image width in pixels
+// int *y -- outputs image height in pixels
+// int *channels_in_file -- outputs # of image components in image file
+// int desired_channels -- if non-zero, # of image components requested in result
+//
+// The return value from an image loader is an 'unsigned char *' which points
+// to the pixel data, or NULL on an allocation failure or if the image is
+// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels,
+// with each pixel consisting of N interleaved 8-bit components; the first
+// pixel pointed to is top-left-most in the image. There is no padding between
+// image scanlines or between pixels, regardless of format. The number of
+// components N is 'desired_channels' if desired_channels is non-zero, or
+// *channels_in_file otherwise. If desired_channels is non-zero,
+// *channels_in_file has the number of components that _would_ have been
+// output otherwise. E.g. if you set desired_channels to 4, you will always
+// get RGBA output, but you can check *channels_in_file to see if it's trivially
+// opaque because e.g. there were only 3 channels in the source image.
+//
+// An output image with N components has the following components interleaved
+// in this order in each pixel:
+//
+// N=#comp components
+// 1 grey
+// 2 grey, alpha
+// 3 red, green, blue
+// 4 red, green, blue, alpha
+//
+// If image loading fails for any reason, the return value will be NULL,
+// and *x, *y, *channels_in_file will be unchanged. The function
+// stbi_failure_reason() can be queried for an extremely brief, end-user
+// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS
+// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly
+// more user-friendly ones.
+//
+// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized.
+//
+// To query the width, height and component count of an image without having to
+// decode the full file, you can use the stbi_info family of functions:
+//
+// int x,y,n,ok;
+// ok = stbi_info(filename, &x, &y, &n);
+// // returns ok=1 and sets x, y, n if image is a supported format,
+// // 0 otherwise.
+//
+// Note that stb_image pervasively uses ints in its public API for sizes,
+// including sizes of memory buffers. This is now part of the API and thus
+// hard to change without causing breakage. As a result, the various image
+// loaders all have certain limits on image size; these differ somewhat
+// by format but generally boil down to either just under 2GB or just under
+// 1GB. When the decoded image would be larger than this, stb_image decoding
+// will fail.
+//
+// Additionally, stb_image will reject image files that have any of their
+// dimensions set to a larger value than the configurable STBI_MAX_DIMENSIONS,
+// which defaults to 2**24 = 16777216 pixels. Due to the above memory limit,
+// the only way to have an image with such dimensions load correctly
+// is for it to have a rather extreme aspect ratio. Either way, the
+// assumption here is that such larger images are likely to be malformed
+// or malicious. If you do need to load an image with individual dimensions
+// larger than that, and it still fits in the overall size limit, you can
+// #define STBI_MAX_DIMENSIONS on your own to be something larger.
+//
+// ===========================================================================
+//
+// UNICODE:
+//
+// If compiling for Windows and you wish to use Unicode filenames, compile
+// with
+// #define STBI_WINDOWS_UTF8
+// and pass utf8-encoded filenames. Call stbi_convert_wchar_to_utf8 to convert
+// Windows wchar_t filenames to utf8.
+//
+// ===========================================================================
+//
+// Philosophy
+//
+// stb libraries are designed with the following priorities:
+//
+// 1. easy to use
+// 2. easy to maintain
+// 3. good performance
+//
+// Sometimes I let "good performance" creep up in priority over "easy to maintain",
+// and for best performance I may provide less-easy-to-use APIs that give higher
+// performance, in addition to the easy-to-use ones. Nevertheless, it's important
+// to keep in mind that from the standpoint of you, a client of this library,
+// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all.
+//
+// Some secondary priorities arise directly from the first two, some of which
+// provide more explicit reasons why performance can't be emphasized.
+//
+// - Portable ("ease of use")
+// - Small source code footprint ("easy to maintain")
+// - No dependencies ("ease of use")
+//
+// ===========================================================================
+//
+// I/O callbacks
+//
+// I/O callbacks allow you to read from arbitrary sources, like packaged
+// files or some other source. Data read from callbacks are processed
+// through a small internal buffer (currently 128 bytes) to try to reduce
+// overhead.
+//
+// The three functions you must define are "read" (reads some bytes of data),
+// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end).
+//
+// ===========================================================================
+//
+// SIMD support
+//
+// The JPEG decoder will try to automatically use SIMD kernels on x86 when
+// supported by the compiler. For ARM Neon support, you must explicitly
+// request it.
+//
+// (The old do-it-yourself SIMD API is no longer supported in the current
+// code.)
+//
+// On x86, SSE2 will automatically be used when available based on a run-time
+// test; if not, the generic C versions are used as a fall-back. On ARM targets,
+// the typical path is to have separate builds for NEON and non-NEON devices
+// (at least this is true for iOS and Android). Therefore, the NEON support is
+// toggled by a build flag: define STBI_NEON to get NEON loops.
+//
+// If for some reason you do not want to use any of SIMD code, or if
+// you have issues compiling it, you can disable it entirely by
+// defining STBI_NO_SIMD.
+//
+// ===========================================================================
+//
+// HDR image support (disable by defining STBI_NO_HDR)
+//
+// stb_image supports loading HDR images in general, and currently the Radiance
+// .HDR file format specifically. You can still load any file through the existing
+// interface; if you attempt to load an HDR file, it will be automatically remapped
+// to LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1;
+// both of these constants can be reconfigured through this interface:
+//
+// stbi_hdr_to_ldr_gamma(2.2f);
+// stbi_hdr_to_ldr_scale(1.0f);
+//
+// (note, do not use _inverse_ constants; stbi_image will invert them
+// appropriately).
+//
+// Additionally, there is a new, parallel interface for loading files as
+// (linear) floats to preserve the full dynamic range:
+//
+// float *data = stbi_loadf(filename, &x, &y, &n, 0);
+//
+// If you load LDR images through this interface, those images will
+// be promoted to floating point values, run through the inverse of
+// constants corresponding to the above:
+//
+// stbi_ldr_to_hdr_scale(1.0f);
+// stbi_ldr_to_hdr_gamma(2.2f);
+//
+// Finally, given a filename (or an open file or memory block--see header
+// file for details) containing image data, you can query for the "most
+// appropriate" interface to use (that is, whether the image is HDR or
+// not), using:
+//
+// stbi_is_hdr(char *filename);
+//
+// ===========================================================================
+//
+// iPhone PNG support:
+//
+// We optionally support converting iPhone-formatted PNGs (which store
+// premultiplied BGRA) back to RGB, even though they're internally encoded
+// differently. To enable this conversion, call
+// stbi_convert_iphone_png_to_rgb(1).
+//
+// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per
+// pixel to remove any premultiplied alpha *only* if the image file explicitly
+// says there's premultiplied data (currently only happens in iPhone images,
+// and only if iPhone convert-to-rgb processing is on).
+//
+// ===========================================================================
+//
+// ADDITIONAL CONFIGURATION
+//
+// - You can suppress implementation of any of the decoders to reduce
+// your code footprint by #defining one or more of the following
+// symbols before creating the implementation.
+//
+// STBI_NO_JPEG
+// STBI_NO_PNG
+// STBI_NO_BMP
+// STBI_NO_PSD
+// STBI_NO_TGA
+// STBI_NO_GIF
+// STBI_NO_HDR
+// STBI_NO_PIC
+// STBI_NO_PNM (.ppm and .pgm)
+//
+// - You can request *only* certain decoders and suppress all other ones
+// (this will be more forward-compatible, as addition of new decoders
+// doesn't require you to disable them explicitly):
+//
+// STBI_ONLY_JPEG
+// STBI_ONLY_PNG
+// STBI_ONLY_BMP
+// STBI_ONLY_PSD
+// STBI_ONLY_TGA
+// STBI_ONLY_GIF
+// STBI_ONLY_HDR
+// STBI_ONLY_PIC
+// STBI_ONLY_PNM (.ppm and .pgm)
+//
+// - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still
+// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB
+//
+// - If you define STBI_MAX_DIMENSIONS, stb_image will reject images greater
+// than that size (in either width or height) without further processing.
+// This is to let programs in the wild set an upper bound to prevent
+// denial-of-service attacks on untrusted data, as one could generate a
+// valid image of gigantic dimensions and force stb_image to allocate a
+// huge block of memory and spend disproportionate time decoding it. By
+// default this is set to (1 << 24), which is 16777216, but that's still
+// very big.
+
+#ifndef STBI_NO_STDIO
+#include
+#endif // STBI_NO_STDIO
+
+#define STBI_VERSION 1
+
+enum
+{
+ STBI_default = 0, // only used for desired_channels
+
+ STBI_grey = 1,
+ STBI_grey_alpha = 2,
+ STBI_rgb = 3,
+ STBI_rgb_alpha = 4
+};
+
+#include
+typedef unsigned char stbi_uc;
+typedef unsigned short stbi_us;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef STBIDEF
+#ifdef STB_IMAGE_STATIC
+#define STBIDEF static
+#else
+#define STBIDEF extern
+#endif
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// PRIMARY API - works on images of any type
+//
+
+//
+// load image by filename, open file, or memory buffer
+//
+
+typedef struct
+{
+ int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read
+ void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative
+ int (*eof) (void *user); // returns nonzero if we are at end of file/data
+} stbi_io_callbacks;
+
+////////////////////////////////////
+//
+// 8-bits-per-channel interface
+//
+
+STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels);
+
+#ifndef STBI_NO_STDIO
+STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
+// for stbi_load_from_file, file pointer is left pointing immediately after image
+#endif
+
+#ifndef STBI_NO_GIF
+STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp);
+#endif
+
+#ifdef STBI_WINDOWS_UTF8
+STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input);
+#endif
+
+////////////////////////////////////
+//
+// 16-bits-per-channel interface
+//
+
+STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels);
+
+#ifndef STBI_NO_STDIO
+STBIDEF stbi_us *stbi_load_16 (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
+STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
+#endif
+
+////////////////////////////////////
+//
+// float-per-channel interface
+//
+#ifndef STBI_NO_LINEAR
+ STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels);
+ STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels);
+
+ #ifndef STBI_NO_STDIO
+ STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
+ STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
+ #endif
+#endif
+
+#ifndef STBI_NO_HDR
+ STBIDEF void stbi_hdr_to_ldr_gamma(float gamma);
+ STBIDEF void stbi_hdr_to_ldr_scale(float scale);
+#endif // STBI_NO_HDR
+
+#ifndef STBI_NO_LINEAR
+ STBIDEF void stbi_ldr_to_hdr_gamma(float gamma);
+ STBIDEF void stbi_ldr_to_hdr_scale(float scale);
+#endif // STBI_NO_LINEAR
+
+// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR
+STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user);
+STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len);
+#ifndef STBI_NO_STDIO
+STBIDEF int stbi_is_hdr (char const *filename);
+STBIDEF int stbi_is_hdr_from_file(FILE *f);
+#endif // STBI_NO_STDIO
+
+
+// get a VERY brief reason for failure
+// on most compilers (and ALL modern mainstream compilers) this is threadsafe
+STBIDEF const char *stbi_failure_reason (void);
+
+// free the loaded image -- this is just free()
+STBIDEF void stbi_image_free (void *retval_from_stbi_load);
+
+// get image dimensions & components without fully decoding
+STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp);
+STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp);
+STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len);
+STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user);
+
+#ifndef STBI_NO_STDIO
+STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp);
+STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp);
+STBIDEF int stbi_is_16_bit (char const *filename);
+STBIDEF int stbi_is_16_bit_from_file(FILE *f);
+#endif
+
+
+
+// for image formats that explicitly notate that they have premultiplied alpha,
+// we just return the colors as stored in the file. set this flag to force
+// unpremultiplication. results are undefined if the unpremultiply overflow.
+STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply);
+
+// indicate whether we should process iphone images back to canonical format,
+// or just pass them through "as-is"
+STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert);
+
+// flip the image vertically, so the first pixel in the output array is the bottom left
+STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip);
+
+// as above, but only applies to images loaded on the thread that calls the function
+// this function is only available if your compiler supports thread-local variables;
+// calling it will fail to link if your compiler doesn't
+STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply);
+STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert);
+STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip);
+
+// ZLIB client - used by PNG, available for other purposes
+
+STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen);
+STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header);
+STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen);
+STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
+
+STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen);
+STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+//
+//
+//// end header file /////////////////////////////////////////////////////
+#endif // STBI_INCLUDE_STB_IMAGE_H
+
+#ifdef STB_IMAGE_IMPLEMENTATION
+
+#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \
+ || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \
+ || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \
+ || defined(STBI_ONLY_ZLIB)
+ #ifndef STBI_ONLY_JPEG
+ #define STBI_NO_JPEG
+ #endif
+ #ifndef STBI_ONLY_PNG
+ #define STBI_NO_PNG
+ #endif
+ #ifndef STBI_ONLY_BMP
+ #define STBI_NO_BMP
+ #endif
+ #ifndef STBI_ONLY_PSD
+ #define STBI_NO_PSD
+ #endif
+ #ifndef STBI_ONLY_TGA
+ #define STBI_NO_TGA
+ #endif
+ #ifndef STBI_ONLY_GIF
+ #define STBI_NO_GIF
+ #endif
+ #ifndef STBI_ONLY_HDR
+ #define STBI_NO_HDR
+ #endif
+ #ifndef STBI_ONLY_PIC
+ #define STBI_NO_PIC
+ #endif
+ #ifndef STBI_ONLY_PNM
+ #define STBI_NO_PNM
+ #endif
+#endif
+
+#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB)
+#define STBI_NO_ZLIB
+#endif
+
+
+#include