diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..dfe0770
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+# Auto detect text files and perform LF normalization
+* text=auto
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..798ec53
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,21 @@
+################################################################################
+# This .gitignore file was automatically created by Microsoft(R) Visual Studio.
+################################################################################
+
+*.exe
+/.vs
+/Debug
+/Release
+/Speedy E.e424a3cb
+/x64
+/IMAGE08
+/IMAGE16
+/SOUND
+/MOVIE
+/DATA
+/msvc5/*.ncb
+/msvc5/*.opt
+/msvc5/sb2decomp/*.plg
+/msvc5/sb2decomp/Debug
+/msvc5/sb2decomp/Release
+Speedy Eggbert 2 Source.vcxproj.user
\ No newline at end of file
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..0ca5a62
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "dxsdk3"]
+ path = dxsdk3
+ url = https://code.openeggbert.com/backup/dxsdk3
diff --git a/CppProperties.json b/CppProperties.json
new file mode 100644
index 0000000..659bf4e
--- /dev/null
+++ b/CppProperties.json
@@ -0,0 +1,21 @@
+{
+ "configurations": [
+ {
+ "inheritEnvironments": [
+ "msvc_x86"
+ ],
+ "name": "x86-Debug",
+ "includePath": [
+ "${env.INCLUDE}",
+ "${workspaceRoot}\\**"
+ ],
+ "defines": [
+ "WIN32",
+ "_DEBUG",
+ "UNICODE",
+ "_UNICODE"
+ ],
+ "intelliSenseMode": "windows-msvc-x86"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..f288702
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ 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/README.md b/README.md
index a54ae0d..e68acb4 100644
--- a/README.md
+++ b/README.md
@@ -1,76 +1,84 @@
-# Speedy Eggbert 2 Source Code Decomp
+# Free Eggbert
+
+This is fork of: https://github.com/jummy0/sb2-decomp
+
+ 
## Introduction
+
This is decompiled source code of Speedy Eggbert 2.
-This repository is based on the following works:
- - https://github.com/jummy0/sb2-decomp
- - https://github.com/HMVocaloid/Speedy-Eggbert-2-Source-Code-Decomp
-
-As of now (5/17/24), there hasn't been any source code found for SE2. So we are using the released (original) source code from Planet Blupi to compare code and help us with the proccess.
+Currently, no source code has been publicly released for Speedy Blupi. We are using the disassemblers Ghidra and IDA to inspect the game binaries, and comparing with the official Planet Blupi source code.
## Used technologies
- C++
- DirectX 3
+
+## Future
-## Clone with git
+ - Migration from DirectX 3 to SDL2
+ - Migration from Visual Studio 2017 to another IDE
+ - Making it multiplatform (Android and web browser too)
-## Init and update submodules
+## Development
+ Some demangled symbol names are taken from the 2013 Windows Phone version of Speedy Blupi, which we inspected using ILSpy. Big thanks to Ч.У.Ш on the 4PDA forum for archiving this obscure version of the game!!!
+
+ Gameplay is functional, but defective and missing many features.
+
+ These files currently need the **most attention**, in order of priority:
+ - event.cpp
+ - decblupi.cpp
+ - decio.cpp
+ - decdesign.cpp
+ - decblock.cpp
+ - decmove.cpp
+ - decnet.cpp
+ - decor.cpp
+ - misc.cpp
+ These files are tentatively **complete**, but require further testing:
+ - blupi.cpp
+ - button.cpp
+ - jauge.cpp
+ - menu.cpp
+ - movie.cpp
+ - network.cpp
+ - pixmap.cpp
+ - sound.cpp
+ - wave.cpp
+
+## How to setup locally
+
+### Clone with git
+
+#init and update submodules
git submodule init
-
git submodule update
-## How to setup the development environment locally
+### How to setup the development environment locally
-### Install "Microsoft Visual Studio Community 2017"
+#### Install "Microsoft Visual Studio Community 2017"
https://drive.openeggbert.com/other/Visual_Studio_Community_2017.exe
- This (IDE) will be changed in the future
-### Install v140 toolset for desktop
+#### Install v140 toolset for desktop
-### Open the Project
+#### Open the Project
Click on "Speedy Eggbert 2 Source.sln" and select Open with "Microsoft Visual Studio 2017"
Set the Platform to x86 and debugging to Win32.
-### Set "Additional Options"
+#### Set "Additional Options"
Properties / Configuration Properties / C/C++ / Command Line / Additional Options
Add : /wd4700 /wd4703
-### Build
+#### Build
Click with the right mouse button on "Speedy Eggbert 2 Source.sln"
- launch Build/Build Speedy Eggbert 2 Source.sln
-
-## Current status
-
- | CPP File | Progress |
- | -------- | -------- |
- | blupi.cpp | 99% complete |
- | button.cpp | 100% complete |
- | decor.cpp | 80% complete |
- | event.cpp | 70% complete |
- | menu.cpp | 100% complete |
- | misc.cpp | 100% complete |
- | movie.cpp | 100% complete |
- | network.cpp | 100% complete |
- | pixmap.cpp | 99% complete |
- | sound.cpp | 100% complete |
- | text.cpp | 100% complete |
- | wave.cpp | 100% complete |
-
-
-Credit to jummy over at the Blupi Games Fan Server for doing the decompilation work on the game.
-
-## Future
-
- - Migration from DirectX 3 to SDL2
- - Migration from Visual Studio 2017 to another IDE
- - Making it crossplatform
diff --git a/Speedy Eggbert 2 Source.sln b/Speedy Eggbert 2 Source.sln
new file mode 100644
index 0000000..2f3ee7c
--- /dev/null
+++ b/Speedy Eggbert 2 Source.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.8.34330.188
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Speedy Eggbert 2 Source", "Speedy Eggbert 2 Source.vcxproj", "{07F25327-C838-4ACD-ADBA-BE17F75007EF}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {07F25327-C838-4ACD-ADBA-BE17F75007EF}.Debug|x64.ActiveCfg = Debug|x64
+ {07F25327-C838-4ACD-ADBA-BE17F75007EF}.Debug|x64.Build.0 = Debug|x64
+ {07F25327-C838-4ACD-ADBA-BE17F75007EF}.Debug|x86.ActiveCfg = Debug|Win32
+ {07F25327-C838-4ACD-ADBA-BE17F75007EF}.Debug|x86.Build.0 = Debug|Win32
+ {07F25327-C838-4ACD-ADBA-BE17F75007EF}.Release|x64.ActiveCfg = Release|x64
+ {07F25327-C838-4ACD-ADBA-BE17F75007EF}.Release|x64.Build.0 = Release|x64
+ {07F25327-C838-4ACD-ADBA-BE17F75007EF}.Release|x86.ActiveCfg = Release|Win32
+ {07F25327-C838-4ACD-ADBA-BE17F75007EF}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {13496F7E-739E-4004-A5EA-AAF0B184B7C6}
+ EndGlobalSection
+EndGlobal
diff --git a/Speedy Eggbert 2 Source.vcxproj b/Speedy Eggbert 2 Source.vcxproj
new file mode 100644
index 0000000..d1bc820
--- /dev/null
+++ b/Speedy Eggbert 2 Source.vcxproj
@@ -0,0 +1,244 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 17.0
+ Win32Proj
+ {e424a3cb-c8b8-447c-be63-41a57e65b449}
+ SpeedyEggbert2Source
+
+
+
+
+
+ Application
+ true
+ v140_xp
+ NotSet
+
+
+ Application
+ false
+ v140_xp
+ true
+ NotSet
+
+
+ Application
+ true
+ v140_xp
+ NotSet
+
+
+ Application
+ false
+ v140_xp
+ true
+ NotSet
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Level3
+ false
+ _WIN32;WIN32;_CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ dxsdk3\sdk\inc;bass\inc
+ UNICODE;_UNICODE
+
+ Disabled
+ Neither
+ EnableFastChecks
+ false
+
+
+ Windows
+ true
+ /DYNAMICBASE "legacy_stdio_definitions.lib" %(AdditionalOptions) /VERBOSE
+ dxsdk3\sdk\lib;bass\lib;%(AdditionalLibraryDirectories)
+ false
+ dxsdk3/sdk/lib/*.lib;bass/lib/*.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;%(AdditionalDependencies)
+ Default
+ true
+ MultiplyDefinedSymbolOnly
+ false
+ false
+
+
+
+
+ Level3
+ true
+ true
+ true
+ _WIN32;WIN32;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ dxsdk3\sdk\inc;bass\inc
+ UNICODE;_UNICODE
+
+
+ Windows
+ true
+ true
+ true
+ dxsdk3\sdk\lib;bass\lib;%(AdditionalLibraryDirectories)
+ MultiplyDefinedSymbolOnly
+ /DYNAMICBASE "legacy_stdio_definitions.lib" %(AdditionalOptions) /VERBOSE
+ Default
+ dxsdk3/sdk/lib/*.lib;bass/lib/*.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;%(AdditionalDependencies)
+ false
+
+
+
+
+ Level3
+ true
+ _WIN32;WIN32;_CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ dxsdk3\sdk\inc
+ UNICODE;_UNICODE
+
+
+ Windows
+ true
+ dxsdk3\sdk\lib;%(AdditionalLibraryDirectories)
+ Default
+ true
+ MultiplyDefinedSymbolOnly
+ /DYNAMICBASE "legacy_stdio_definitions.lib" %(AdditionalOptions) /VERBOSE
+ dxsdk3/sdk/lib/*.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;%(AdditionalDependencies)
+ false
+ false
+ false
+
+
+
+
+ Level3
+ true
+ true
+ true
+ _WIN32;WIN32;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ dxsdk3\sdk\inc
+ UNICODE;_UNICODE
+
+
+ Windows
+ true
+ true
+ true
+ dxsdk3\sdk\lib;%(AdditionalLibraryDirectories)
+ MultiplyDefinedSymbolOnly
+ /DYNAMICBASE "legacy_stdio_definitions.lib" %(AdditionalOptions) /VERBOSE
+ Default
+ dxsdk3/sdk/lib/*.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;%(AdditionalDependencies)
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Speedy Eggbert 2 Source.vcxproj.filters b/Speedy Eggbert 2 Source.vcxproj.filters
new file mode 100644
index 0000000..df874e5
--- /dev/null
+++ b/Speedy Eggbert 2 Source.vcxproj.filters
@@ -0,0 +1,204 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+ {0ff9ef1b-78f1-41d7-9a2b-813cedd6907d}
+
+
+
+
+ Data
+
+
+ Resource Files
+
+
+ Resource Files
+
+
+ Resource Files
+
+
+ Resource Files
+
+
+ Resource Files
+
+
+ Resource Files
+
+
+ Resource Files
+
+
+ Resource Files
+
+
+ Resource Files
+
+
+ Resource Files
+
+
+ Resource Files
+
+
+ Resource Files
+
+
+ Resource Files
+
+
+ Resource Files
+
+
+ Resource Files
+
+
+
+
+ Resource Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Resource Files
+
+
+
+
+ Resource Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/bass/bass.dll b/bass/bass.dll
new file mode 100644
index 0000000..10114b6
Binary files /dev/null and b/bass/bass.dll differ
diff --git a/bass/bass.txt b/bass/bass.txt
new file mode 100644
index 0000000..fe7bea8
--- /dev/null
+++ b/bass/bass.txt
@@ -0,0 +1,2352 @@
+BASS 2.4
+Copyright (c) 1999-2022 Un4seen Developments Ltd. All rights reserved.
+
+Files that you should have found in the BASS package
+====================================================
+Win32 version
+-------------
+BASS.TXT This file
+BASS.DLL BASS module
+BASS.CHM BASS documentation
+X64\
+ BASS.DLL 64-bit BASS module
+C\ C/C++ API and examples...
+ BASS.H BASS C/C++ header file
+ BASS.LIB BASS import library
+ BASS.SLN Visual Studio solution for examples
+ MAKEFILE Makefile for examples
+ MAKEFILE.IN Makefile helper macros
+ X64\
+ BASS.LIB 64-bit BASS import library
+ 3DTEST\ 3D example
+ ...
+ BASSTEST\ Simple playback example
+ ...
+ CONTEST\ Console example
+ ...
+ CUSTLOOP\ Custom looping example
+ ...
+ DEVLIST\ Device list example
+ ...
+ DSPTEST\ DSP example
+ ...
+ FXTEST\ Effects example
+ ...
+ LIVEFX\ Full-duplex example
+ ...
+ LIVESPEC\ Live version of spectrum analyser example
+ ...
+ MODTEST\ MOD music example
+ ...
+ MULTI\ Multiple device example
+ ...
+ NETRADIO\ Internet streaming example
+ ...
+ PLUGINS\ Plugins example
+ ...
+ RECTEST\ Recording example
+ ...
+ SPEAKERS\ Multi-speaker example
+ ...
+ SPECTRUM\ Spectrum analyser example
+ ...
+ SYNTH\ Low latency custom streaming example
+ ...
+ WRITEWAV\ WAVE writer example
+ ...
+ BIN\ Precompiled examples
+ 3DTEST.EXE
+ BASSTEST.EXE
+ CONTEST.EXE
+ CUSTLOOP.EXE
+ DEVLIST.EXE
+ DSPTEST.EXE
+ FXTEST.EXE
+ LIVEFX.EXE
+ LIVESPEC.EXE
+ MODTEST.EXE
+ MULTI.EXE
+ NETRADIO.EXE
+ RECTEST.EXE
+ SPEAKERS.EXE
+ SPECTRUM.EXE
+ SYNTH.EXE
+ WRITEWAV.EXE
+DELPHI\ Delphi API and examples...
+ BASS.PAS BASS Delphi unit
+ 3DTEST\ 3D example
+ ...
+ BASSTEST\ Simple playback example
+ ...
+ CONTEST\ Console example
+ ...
+ CUSTLOOP\ Custom looping example
+ ...
+ DSPTEST\ DSP example
+ ...
+ FXTEST\ Effects example
+ ...
+ LIVEFX\ Full-duplex example
+ ...
+ LIVESPEC\ Live version of spectrum analyser example
+ ...
+ MULTI\ Multiple device example
+ ...
+ NETRADIO\ Internet streaming example
+ ...
+ PLUGINS\ Plugins example
+ ...
+ RECTEST\ Recording example
+ ...
+ SAMPLEVIS\ Visualisation example
+ ...
+ SPEAKERS\ Multi-speaker example
+ ...
+ SPECTRUM\ Spectrum analyser example
+ ...
+ STREAMTEST\ User stream example
+ ...
+ WRITEWAV\ WAVE writer example
+ ...
+VB\ Visual Basic API and examples...
+ BASS.BAS BASS Visual Basic module
+ 3DTEST\ 3D example
+ ...
+ BASSTEST\ Simple playback example
+ ...
+ CUSTLOOP\ Custom looping example
+ ...
+ DEVLIST\ Device list example
+ ...
+ DSPTEST\ DSP example
+ ...
+ FXTEST\ Effects example
+ ...
+ LIVEFX\ Full-duplex example
+ ...
+ LIVESPEC\ Live version of spectrum analyser example
+ ...
+ MODTEST\ MOD music example
+ ...
+ MULTI\ Multiple device example
+ ...
+ NETRADIO\ Internet streaming example
+ ...
+ PLUGINS\ Plugins example
+ ...
+ RECTEST\ Recording example
+ ...
+ SPEAKERS\ Multi-speaker example
+ ...
+ SPECTRUM\ Spectrum analyser example
+ ...
+ SYNTH\ Low latency custom streaming example
+ ...
+ WRITEWAV\ WAVE writer example
+ ...
+ MEMORY\ Playing from memory example by Jobnik
+ ...
+
+NOTE: You may need to "Unblock" the BASS.CHM file in its "Properties" to view
+ it on Windows 7. The documentation can also be viewed online at the BASS
+ website.
+
+NOTE: The Delphi and VB examples may not always be up to date with the C
+ examples, so the latter should be preferred as references if possible.
+
+NOTE: To run the example EXEs, first you will need to copy BASS.DLL into the
+ same directory as them.
+
+macOS version
+-------------
+BASS.TXT This file
+LIBBASS.DYLIB BASS module
+BASS.CHM BASS documentation
+BASS.H BASS C/C++ header file
+BASS.XCODEPROJ Xcode project for examples
+MAKEFILE Makefile for specific architectures
+CONTEST\ Console example
+ ...
+DEVLIST\ Device list example
+ ...
+DSPTEST\ DSP example
+ ...
+FXTEST\ Effects example
+ ...
+LIVESPEC\ Live version of spectrum analyser example
+ ...
+MULTI\ Multiple device example
+ ...
+NETRADIO\ Internet streaming example
+ ...
+PLUGINS\ Plugins example
+ ...
+RECTEST\ Recording example
+ ...
+SPEAKERS\ Multi-speaker example
+ ...
+SPECTRUM\ Spectrum analyser example
+ ...
+SYNTH\ Low latency custom streaming example
+ ...
+WRITEWAV\ WAVE writer example
+ ...
+
+NOTE: To view the documentation, you will need a CHM viewer. The documentation
+ can also be viewed online at the BASS website.
+
+Linux version
+-------------
+BASS.TXT This file
+BASS.CHM BASS documentation
+BASS.H BASS C/C++ header file
+MAKEFILE Makefile for examples
+MAKEFILE.IN Makefile helper macros
+LIBS\ BASS modules
+ ...
+PASCAL\
+ BASS.PAS BASS Delphi/Pascal unit
+3DTEST\ 3D example
+ ...
+BASSTEST\ Simple playback example
+ ...
+CONTEST\ Console example
+ ...
+CUSTLOOP\ Custom looping example
+ ...
+DEVLIST\ Device list example
+ ...
+DSPTEST\ DSP example
+ ...
+FXTEST\ Effects example
+ ...
+LIVESPEC\ Live version of spectrum analyser example
+ ...
+MODTEST\ MOD music example
+ ...
+MULTI\ Multiple device example
+ ...
+NETRADIO\ Internet streaming example
+ ...
+PLUGINS\ Plugins example
+ ...
+RECTEST\ Recording example
+ ...
+SPEAKERS\ Multi-speaker example
+ ...
+SPECTRUM\ Spectrum analyser example
+ ...
+SYNTH\ Low latency custom streaming example
+ ...
+WRITEWAV\ WAVE writer example
+ ...
+
+NOTE: To view the documentation, you will need a CHM viewer. The documentation
+ can also be viewed online at the BASS website.
+
+Android version
+---------------
+BASS.TXT This file
+BASS.CHM BASS documentation
+LIBS\ BASS modules
+ ...
+C\ C/C++ API...
+ BASS.H BASS C/C++ header file
+JAVA\COM\UN4SEEN\BASS\
+ BASS.JAVA BASS Java class
+EXAMPLES\ Java examples
+ BUILD.GRADLE Android Studio build script for examples
+ SETTINGS.GRADLE
+ PROGUARD-BASS.PRO
+ DSPTEST\ DSP example
+ ...
+ FXTEST\ Effects example
+ ...
+ LIVESPEC\ Live version of spectrum analyser example
+ ...
+ NETRADIO\ Internet streaming example
+ ...
+ PLUGINS\ Plugins example
+ ...
+ RECTEST\ Recording example
+ ...
+ SPECTRUM\ Spectrum analyser example
+ ...
+ BASSLIB\ BASS library wrapper shared by examples
+ ...
+
+NOTE: To view the documentation, you will need a CHM viewer. The documentation
+ can also be viewed online at the BASS website.
+
+iOS version
+-----------
+BASS.TXT This file
+BASS.XCFRAMEWORK BASS framework
+BASS.CHM BASS documentation
+BASS.H BASS C/C++ header file
+
+NOTE: To view the documentation, you will need a CHM viewer. The documentation
+ can also be viewed online at the BASS website.
+
+
+What's the point?
+=================
+BASS is an audio library for use in software on several platforms. Its purpose
+is to provide developers with powerful and efficient sample, stream, MOD music,
+and recording functions. All in a compact DLL that won't bloat your software.
+
+See the documentation for descriptions of all the BASS functions. Also check
+the included example source-codes for some examples of how to use BASS in your
+own programs.
+
+
+Requirements
+============
+Win32 version
+-------------
+Windows 98 or newer is required with an SSE-supporting CPU. BASS can use WASAPI
+or DirectSound for playback and recording. WASAPI is the default on Windows
+Vista and newer, while DirectSound is on older Windows versions. 32-bit and
+64-bit Windows are supported.
+
+macOS version
+-------------
+macOS 10.5 or above is required. The x86_64 / arm64 / i386 architectures are
+supported in a single universal library.
+
+Linux version
+-------------
+BASS requires ALSA for playback and recording, but decoding and silent playback
+on the "No sound" device is still possible without it. The x86 / x86_64 /
+armhf / aarch64 architectures are supported. The x86 build requires SSE, while
+the armhf build requires ARMv6+VFP2 or above.
+
+Android version
+---------------
+Android 2.3 or above is required. BASS can use AAudio, OpenSL ES, or AudioTrack
+for playback (OpenSL ES is used for recording). AAudio is the default on Android
+8.1 and above, while OpenSL ES is on older Android versions. The armeabi-v7a /
+arm64-v8a / x86 / x86_64 architectures are supported.
+
+iOS version
+-----------
+iOS 8 or above is required. armv7 / armv7s / arm64 "device" builds and
+i386 / x86_64 / arm64 "simulator" builds are supported in a single universal
+framework.
+
+
+Main Features
+=============
+* Samples
+ supports WAV/AIFF/MP3/MP2/MP1/OGG and custom generated samples
+
+* Sample streams
+ stream any sample data in 8/16/32 bit, with both "push" and "pull" systems
+
+* File streams
+ MP3/MP2/MP1/OGG/WAV/AIFF file streaming
+
+* Internet file streaming
+ stream files from the internet, including Shout/Icecast
+
+* User file streaming
+ stream files from anywhere using any delivery method
+
+* OS codecs
+ ACM, Media Foundation and CoreAudio codec support for additional audio formats
+
+* Multi-channel streaming
+ support for more than plain stereo, including multi-channel OGG/WAV/AIFF files
+
+* MOD music
+ uses the same engine as XMPlay = best accuracy, speed, and quality
+
+* MO3 music
+ MP3/OGG compressed MOD music
+
+* Add-on system
+ support for more formats is available via add-ons (aka plugins)
+
+* Multiple outputs
+ simultaneously use multiple soundcards, and move channels between them
+
+* Recording
+ flexible recording system, with support for multiple devices
+
+* Decode without playback
+ streams and MOD musics can be outputted in any way you want
+
+* Speaker assignment
+ assign streams and MOD musics to specific speakers
+
+* High precision synchronization
+ synchronize events in your software to the streams and MOD musics
+
+* Effects
+ chorus/compressor/distortion/echo/flanger/gargle/parameq/reverb
+
+* User-defined DSP functions
+ custom effects may be applied to individual streams or the final output mix
+
+* 32 bit floating-point decoding and processing
+ floating-point stream/music decoding, DSP/FX, and recording
+
+* 3D sound
+ play samples/streams/musics in any 3D position
+
+
+Using BASS
+==========
+There is no guarantee that all future BASS versions will be compatible
+with all previous versions, so your program should use BASS_GetVersion
+to check the version that is loaded. This also means that you should
+put the BASS module in the same directory as your executable (not just
+somewhere in the path), to avoid the possibility of a wrong version being
+loaded.
+
+If you are updating your software from a previous BASS version, then
+you should check the "History" section (below), to see if any of the
+functions that you are using have been affected by a change.
+
+Win32 version
+-------------
+C/C++, Delphi, and Visual Basic APIs and example projects are provided. To
+use BASS with another language you will first have to convert the header
+file. Or, as a last resort, you could use LoadLibrary and GetProcAddress.
+
+The downside is that you have to manually import each function that you
+use, with the GetProcAddress function. But it has been made a lot simpler
+to import BASS this way by the use of the BASSDEF #define. Here's a small
+example:
+
+#define BASSDEF(f) (WINAPI *f) // define the functions as pointers
+#include "bass.h"
+...
+HINSTANCE bass=LoadLibrary("BASS.DLL"); // load BASS
+BASS_Init=GetProcAddress(bass,"BASS_Init"); // get BASS_Init
+BASS_Init(-1,44100,0,hWnd,NULL); // call BASS_Init
+
+To use BASS with Borland C++ Builder, you will first have to create a
+Borland C++ Builder import library for it. This is done by using the
+IMPLIB tool that comes with Borland C++ Builder. Simply execute this:
+
+ IMPLIB BASSBCB.LIB BASS.DLL
+
+... and then use BASSBCB.LIB in your projects to import BASS.
+
+To use BASS with LCC-Win32, you will first have to create a compatible
+import library for it. This is done by using the PEDUMP and BUILDLIB
+tools that come with LCC-Win32. Run these 2 commands:
+
+ PEDUMP /EXP BASS.LIB > BASSLCC.EXP
+ BUILDLIB BASSLCC.EXP BASSLCC.LIB
+
+... and then use BASSLCC.LIB in your projects to import BASS.
+
+For the BASS functions that return strings (char*), VB users should use
+the VBStrFromAnsiPtr function to convert the returned pointer into a VB
+string.
+
+macOS version
+-------------
+LIBBASS.DYLIB is a universal binary with support for the x86_64 / arm64 / i386
+architectures. If not all of those architectures are needed, the included
+makefile can be used to extract the wanted one(s). Type "make x86_64" or
+"make arm64" or "make i386" to extract a particular architecture. "make 64bit"
+can be used to extract the x86_64 and arm64 architectures (exclude i386), and
+"make intel" to extract the x86_64 and i386 architectures (exclude arm64). Any
+BASS add-ons placed in the same directory will also be processed.
+
+NOTE: You will need to exclude the i386 architecture (run "make 64bit") for
+ submitting an app to Apple's App Store.
+
+Since BASS 2.4.17, the BASS/add-on libraries use the "@rpath" install path,
+while "@loader_path was used by older versions. If upgrading from an old
+version, you may need to change your copy/embed destination to "Frameworks"
+rather than "Executables", unless your "Runtime Search Paths" setting includes
+"@executable_path" or "@loader_path". The included makefile ("make rpath") can
+be used to update older BASS/add-on versions to use "@rpath".
+
+See the example Xcode project.
+
+Linux version
+-------------
+The LIBBASS.SO file needs to be in the OS's library search path for it to
+be found; simply placing it in the same directory as the executable won't
+necessarily work as it does on other platforms. The BASS libraries should
+also not be placed in the standard library directories to avoid version
+conflicts. To meet those competing requirements, a wrapper script could be
+used to set the "LD_LIBRARY_PATH" environment variable before loading the
+executable. Another option is to set the "rpath" in the executable to tell
+it where to look for libraries, which is what the example makefiles do.
+
+When building for multiple architectures, it is possible to simply try linking
+with all LIBBASS.SO versions, and the linker will use the appropriate one and
+ignore the others.
+
+Android version
+---------------
+The BASS library includes support for use in Java and native code. The
+BASS.JAVA file mirrors BASS.H as much as possible, but there are some
+unavoidable differences, mainly in parameter/return types.
+
+When using ProGuard to obfuscate your Java code, the BASS classes should be
+left alone (see PROGUARD-BASS.PRO).
+
+See the example Android Studio project.
+
+iOS version
+-----------
+The BASS XCFramework should be added to XCode's "Frameworks, Libraries, and
+Embedded Content" section. If you're using an old Xcode version without
+XCFramework support then you can instead directly use the "device" or "simulator"
+framework from within the XCFramework. BASS does not include bitcode, so the
+"Enable Bitcode" option should be set to "No".
+
+
+Latest Version
+==============
+The latest version of BASS can always be found at the BASS website:
+
+ www.un4seen.com
+
+
+Licence
+=======
+BASS is free for non-commercial use. If you are a non-commercial entity
+(eg. an individual) and you are not making any money from your product
+(through sales/advertising/etc), then you can use BASS in it for free.
+If you wish to use BASS in commercial products, then please also see the
+next section.
+
+TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, BASS IS PROVIDED
+"AS IS", WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY
+AND/OR FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS SHALL NOT BE HELD
+LIABLE FOR ANY DAMAGE THAT MAY RESULT FROM THE USE OF BASS. YOU USE
+BASS ENTIRELY AT YOUR OWN RISK.
+
+Usage of BASS indicates that you agree to the above conditions.
+
+All trademarks and other registered names contained in the BASS
+package are the property of their respective owners.
+
+Commercial licensing
+--------------------
+BASS is available for use in your commercial products. The licence
+types available are as follows:
+
+SHAREWARE: Allows the usage of BASS in an unlimited number of your
+shareware ("try before you buy") products, which must sell for no more
+than 40 Euros each. Non-shareware products are also permitted, but the
+product price limit is 10 Euros in that case. The price limit can be
+raised by purchasing duplicate licences, eg. 2 licences doubles it. If
+you are an individual (not a corporation) making and selling your own
+software, this is the licence for you.
+
+SINGLE COMMERCIAL: Allows the usage of BASS in one commercial product.
+
+UNLIMITED COMMERCIAL: Allows the usage of BASS in an unlimited number
+of your commercial products. This licence is on a per-site basis, eg.
+if you are creating products with BASS at 2 sites/locations, then 2
+licences are required.
+
+Please note the products must be end-user products, eg. not components
+used by other products.
+
+These licences only cover your own software, not the publishing of
+other's software. If you publish other's software, its developers (or
+the software itself) will need to be licensed to use BASS.
+
+These licences are on a per-platform basis, with reductions available
+when licensing for multiple platforms. In all cases there are no royalties
+to pay, and you can use future BASS updates without further cost.
+
+These licences do not allow reselling/sublicensing of BASS. For example,
+if a product is a development system, the users of said product are not
+licensed to use BASS in their productions; they will need their own
+licences.
+
+If the standard licences do not meet your requirements, or if you have
+any questions, please get in touch (email: bass@un4seen.com).
+
+Visit the BASS website for the latest pricing:
+
+ www.un4seen.com
+
+
+Credits
+=======
+MP3 decoding is based on minimp3, https://github.com/lieff/minimp3
+
+Ogg Vorbis decoding is based on libogg/vorbis,
+Copyright (c) 2002-2020 Xiph.org Foundation
+
+API/Sample contributors
+-----------------------
+Delphi: Titus Miloi, Rogier Timmermans, Alessandro Cappellozza,
+ Jesse Naranjo, Chris Troesken, Evgeny Melnikov
+Visual Basic: Adam Hoult, Hendrik Knaepen, Arthur Aminov,
+ Peter Hebels, Juan Pablo Franchi
+
+
+History
+=======
+These are the major (and not so major) changes in each release, along with the
+functions/options that are introduced/affected by them. There are other little
+tweaks and fixes made along the way too.
+
+2.4.17 - 12/10/2022
+-------------------
+* "Default" recording device on Windows/macOS
+ BASS_RecordInit
+ BASS_RecordGetDeviceInfo
+ BASS_CONFIG_REC_DEFAULT (BASS_SetConfig option)
+* Recording continues after device format changes on Windows/macOS
+ BASS_RecordStart
+ BASS_SYNC_DEV_FORMAT (BASS_ChannelSetSync type)
+* DSP volume control
+ BASS_ATTRIB_VOLDSP (BASS_ChannelSetAttribute option)
+ BASS_ATTRIB_VOLDSP_PRIORITY (BASS_ChannelSetAttribute option)
+ RECTEST example updated
+* Auto-reconnecting when a download stops before the end
+ BASS_StreamCreateURL
+* Internet streams use HTTP/1.1 instead of HTTP/1.0
+ BASS_StreamCreateURL
+* Download callback changing after stream creation
+ BASS_ATTRIB_DOWNLOADPROC (BASS_ChannelSetAttributeEx option)
+ NETRADIO example updated
+* Thread-specific internet/buffered stream download buffer option
+ BASS_CONFIG_THREAD (BASS_SetConfig option)
+ BASS_CONFIG_NET_BUFFER (BASS_SetConfig option)
+ BASS_StreamCreateURL/FileUser
+* Internet stream creation never waits for pre-buffering
+ BASS_CONFIG_NET_PREBUF_WAIT disabled
+ BASS_StreamCreateURL/FileUser
+* Stalled stream resumption buffer level defaults to prebuffer level
+ BASS_ATTRIB_NET_RESUME (BASS_ChannelSetAttribute option)
+* New simplified channel starting/playing function
+ BASS_ChannelStart
+* Channel remapping fix for various multi-channel source/output combinations
+ BASS_ChannelStart/Play
+* Support for using common add-on name instead of platform-specific filename in plugin loading
+ BASS_PluginLoad
+ NETRADIO example updated
+* Library filename/path retrieval
+ BASS_CONFIG_FILENAME (BASS_GetConfigPtr option)
+ PLUGINS and WRITEWAV examples updated
+* Device info is still available if reinitialization fails
+ BASS_GetInfo
+ BASS_DEVICE_REINIT (BASS_Init flag)
+* Playback ramping-in/out can be disabled separately
+ BASS_ATTRIB_NORAMP (BASS_ChannelSetAttribute option)
+* Default playback ramping setting
+ BASS_CONFIG_NORAMP (BASS_SetConfig option)
+* Error code for when access is denied
+ BASS_ERROR_DENIED
+ BASS_StreamCreateURL
+ BASS_RecordStart
+* REAR2 speaker flags renamed/duplicated to SIDE
+ BASS_SPEAKER_SIDE/SIDELEFT/SIDERIGHT (BASS_MusicLoad/BASS_StreamCreate/File/URL flags)
+* Switch to dynamic library/framework (rather than static) on iOS
+ BASS_PluginLoad
+* Recording routing audio session options on iOS
+ BASS_IOS_SESSION_AIRPLAY/BTHFP/BTA2DP (BASS_CONFIG_IOS_SESSION flags)
+* Audio session deactivation when nothing is playing/recording on iOS
+ BASS_IOS_SESSION_DEACTIVATE (BASS_CONFIG_IOS_SESSION flag)
+* Interrupted status retrieval on iOS
+ BASS_IsStarted
+* Floating-point recording support below Android 5 (already supported above)
+ BASS_RecordStart
+* Internet stream support for Linux systems without /etc/services file
+ BASS_StreamCreateURL
+* Fix for IPv6 addresses in URLs on Windows/Linux/Android
+ BASS_StreamCreateURL
+* Fix for getting volume changes made externally on Linux
+ BASS_GetVolume
+ BASS_RecordGetInput
+* macOS version now uses "@rpath" instead of "@loader_path" install path
+* ARM builds are now included (instead of separate) on Linux
+* Non-FPU ARM architecture support dropped (Windows CE and "softfp" Linux)
+* SSE is required on x86 platforms (Windows 95 dropped)
+
+2.4.16 - 24/6/2021
+------------------
+* DirectSound output mix is now generated by BASS (as with WASAPI output and
+ on other platforms), losing support for DirectSound-specific features but
+ gaining support for all other BASS features
+ BASS_DEVICE_DSOUND (BASS_Init flag)
+* Length trimming
+ BASS_POS_END (BASS_ChannelSetPosition mode)
+ BASS_SYNC_END (BASS_ChannelSetSync type)
+ CUSTLOOP and WRITEWAV examples updated
+* Custom loop start positions
+ BASS_POS_LOOP (BASS_ChannelSetPosition mode)
+ CUSTLOOP example updated
+* Length extending
+ BASS_ATTRIB_TAIL (BASS_ChannelSetAttribute option)
+ BASS_SYNC_END (BASS_ChannelSetSync type)
+* Device reinitialization while retaining BASS channels and 3D settings
+ BASS_DEVICE_REINIT (BASS_Init flag)
+* Retrieval of a device's activity status
+ BASS_IsStarted
+* BASS_DEVICE_3D flag is no longer needed to enable 3D support
+ BASS_Init
+* The "Default" device is now enabled by default on Windows/macOS
+ BASS_CONFIG_DEV_DEFAULT (BASS_SetConfig option)
+* Default communications device indicator on Windows
+ BASS_DEVICE_DEFAULTCOM (BASS_DEVICEINFO flag)
+* Sample channel "newonly" option changed to a flag
+ BASS_SAMCHAN_NEW (BASS_SampleGetChannel flag)
+* Sample playback streams
+ BASS_SAMCHAN_STREAM (BASS_SampleGetChannel flag)
+ BASS_CTYPE_STREAM_SAMPLE
+* Speaker assignment support for samples
+ BASS_SampleGetChannel
+ BASS_ChannelFlags
+* Overriding of default flags during sample channel creation
+ BASS_SampleGetChannel
+* Same sample channel handle when max=1 is now optional
+ BASS_CONFIG_SAMPLE_ONEHANDLE (BASS_SetConfig option)
+* 3D max distance muting can now be toggled
+ BASS_SAMPLE_MUTEMAX (BASS_ChannelFlags flag)
+* Plugin disabling without affecting existing streams
+ BASS_PluginEnable
+* WASAPI recording on Windows (DirectSound is fallback/optional)
+ BASS_CONFIG_REC_WASAPI (BASS_SetConfig option)
+ BASS_RecordInit
+* Minimum recording buffer reduced to 10ms
+ BASS_CONFIG_REC_BUFFER (BASS_SetConfig option)
+* Recording data/level retrieval without removing from buffer when not using a RECORDPROC
+ BASS_DATA_NOREMOVE (BASS_ChannelGetData flag)
+ BASS_LEVEL_NOREMOVE (BASS_ChannelGetLevelEx flag)
+* Support for level measurements longer than 1s from decoding channels
+ BASS_ChannelGetLevelEx
+* Configurable restricted download rate
+ BASS_CONFIG_NET_RESTRATE (BASS_SetConfig option)
+* Thread-specific internet stream timeout options
+ BASS_CONFIG_THREAD (BASS_SetConfig option)
+ BASS_CONFIG_NET_TIMEOUT (BASS_SetConfig option)
+ BASS_CONFIG_NET_READTIMEOUT (BASS_SetConfig option)
+ BASS_StreamCreateURL
+* Configured "User-Agent" header can be overridden in custom request headers
+ BASS_StreamCreateURL
+* Multiple IPs will be tried when available on Linux/Android (already on other platforms)
+ BASS_StreamCreateURL
+* BASS_STREAM_BLOCK applied automatically on files larger than 2GB
+ BASS_StreamCreateURL/FileUser
+* Redirected URL retrieval
+ BASS_TAG_LOCATION (BASS_ChannelGetTags type)
+* Shoutcast metadata is now optional
+ BASS_CONFIG_NET_META (BASS_SetConfig option)
+ BASS_TAG_META (BASS_ChannelGetTags type)
+* Support for a 2nd ID3v2 tag block
+ BASS_TAG_ID3V2_2 (BASS_ChannelGetTags type)
+* OpenMPT channel name retrieval
+ BASS_TAG_MUSIC_CHAN (BASS_ChannelGetTags type)
+* Delayed OGG file scanning when prescanning is disabled/impossible
+ BASS_ChannelGetLength
+ BASS_ChannelSetPosition
+ BASS_CONFIG_OGG_PRESCAN (BASS_SetConfig option)
+* Faster seeking in large OGG files
+ BASS_ChannelSetPosition
+* Unified freeing function for all channel types
+ BASS_ChannelFree
+* User-defined attribute
+ BASS_ATTRIB_USER (BASS_ChannelSetAttributeEx option)
+* Push stream buffer size limiting
+ BASS_ATTRIB_PUSH_LIMIT (BASS_ChannelSetAttribute option)
+* Retrieval of a stream's available file data amount
+ BASS_FILEPOS_AVAILABLE (BASS_StreamGetFilePosition mode)
+* Error code for unsupported URL protocols
+ BASS_ERROR_PROTOCOL (BASS_StreamCreateURL error code)
+* BASS_ERROR_ALREADY error changed to success in some functions
+ BASS_ChannelPause
+ BASS_ChannelSetDevice
+ BASS_ChannelSetLink
+* Support for custom file streaming with Android Media codecs
+ BASS_StreamCreateFileUser
+* Switch to using native APIs for Android Media codecs (Android 5 or above required now)
+ BASS_StreamCreateFile/User/URL
+* BASS_TAG_AM_MIME value changed to fix conflict on Android
+ BASS_TAG_AM_MIME (BASS_ChannelGetTags type)
+* Improved support for single active input recording devices on Linux
+ BASS_RecordGetInputName
+ BASS_RecordGetInput
+ BASS_RecordSetInput
+* Automatic resumption of recordings after an interruption on iOS
+* Fix for Media Foundation AAC streaming with Windows 10 20H1
+ BASS_StreamCreateURL
+ BASS_StreamCreateFileUser
+* Fix for freeze when freeing a stream after BASS_ChannelSetLink failed with BASS_ERROR_ALREADY on it
+ BASS_ChannelSetLink
+* macOS examples rewritten in Objective-C/Cocoa
+* "MP3-FREE" version removed (MP3 patents expired)
+* armv5 (armeabi) architecture support dropped on Android
+
+2.4.15 - 17/12/2019
+-------------------
+* Channel processing granularity option
+ BASS_ATTRIB_GRANULE (BASS_ChannelSetAttribute option)
+* Asynchronous mixtime sync callbacks
+ BASS_SYNC_THREAD (BASS_ChannelSetSync flag)
+* Output device update period can be set in samples
+ BASS_CONFIG_DEV_PERIOD (BASS_SetConfig option)
+* Continuous output when nothing is playing is now optional on macOS/iOS too
+ BASS_CONFIG_DEV_NONSTOP (BASS_SetConfig option)
+* AAudio output support on Android
+ BASS_Init
+ BASS_CONFIG_ANDROID_AAUDIO (BASS_SetConfig option)
+* Support for audio session IDs on Android
+ BASS_CONFIG_ANDROID_SESSIONID (BASS_SetConfig option)
+* ParcelFileDescriptor support on Android
+ BASS_StreamCreateFile
+ BASS_SampleLoad
+ BASS_MusicLoad
+* FloatValue Java class added to receive floating-point values on Android 10
+ BASS_Get3DFactors
+ BASS_RecordGetInput
+ BASS_ChannelGetAttribute
+ BASS_ChannelGet3DAttributes
+* Audio session configuration option on iOS
+ BASS_CONFIG_IOS_SESSION (BASS_SetConfig option)
+* OGG channel type constant renamed/duplicated to VORBIS
+ BASS_CTYPE_STREAM_VORBIS
+* Error code for recognised file formats without audio
+ BASS_ERROR_NOTAUDIO (BASS_StreamCreateFile/User/URL error code)
+* Error code for unstreamable MP4 files due to atom order
+ BASS_ERROR_UNSTREAMABLE (BASS_StreamCreateFileUser/URL error code)
+* Fix for AAC streaming with BASS_STREAM_BLOCK on macOS 10.15 and iOS 13
+ BASS_StreamCreateURL/FileUser
+* Fix for playback rate changing bug when using DirectSound
+ BASS_ATTRIB_FREQ (BASS_ChannelSetAttribute option)
+* armv6 architecture support dropped on iOS
+
+2.4.14 - 16/1/2019
+------------------
+* Support for playback on the "No sound" device
+ BASS_Init
+ BASS_StreamCreateFile/User/URL
+ BASS_SampleLoad/Create
+ BASS_ChannelPlay
+* Improved sample rate conversion quality, including 64 point option
+ BASS_ATTRIB_SRC (BASS_ChannelSetAttribute option)
+ BASS_CONFIG_SRC/_SAMPLE (BASS_SetConfig options)
+* Loopback (output device) recording on Windows Vista and newer
+ BASS_RecordInit
+ BASS_RecordGetDeviceInfo
+ BASS_DEVICE_LOOPBACK (BASS_DEVICEINFO flag)
+ DEVLIST and RECTEST examples updated
+* Native format recording option
+ BASS_RecordStart
+* Access to the 3D output mix for applying DSP/FX
+ STREAMPROC_DEVICE_3D (BASS_StreamCreate option)
+* Retrieval of a device's started/stopped status
+ BASS_IsStarted
+* Sync for when a device stops unexpectedly
+ BASS_SYNC_DEV_FAIL (BASS_ChannelSetSync type)
+* New channel playback state for a paused device
+ BASS_ACTIVE_PAUSED_DEVICE (BASS_ChannelIsActive)
+* Sync for when a device's sample format changes
+ BASS_SYNC_DEV_FORMAT (BASS_ChannelSetSync type)
+* Adjustable output device update period
+ BASS_CONFIG_DEV_PERIOD (BASS_SetConfig option)
+* Nyquist FFT option
+ BASS_DATA_FFT_NYQUIST (BASS_ChannelGetData flag)
+* Plugin-specific flags are ignored in standard stream creation functions
+ BASS_StreamCreateFile/User/URL
+* Pre-buffering during stream creation is now disabled by default
+ BASS_CONFIG_NET_PREBUF_WAIT (BASS_SetConfig option)
+ BASS_StreamCreateURL/FileUser
+* Existing internet streams are unaffected by read timeout config changes
+ BASS_CONFIG_NET_READTIMEOUT (BASS_SetConfig option)
+* Retrieval of the number of existing handles
+ BASS_CONFIG_HANDLES (BASS_GetConfig option)
+* Windows mixer settings are retained by default and optionally not
+ BASS_CONFIG_WASAPI_PERSIST (BASS_SetConfig option)
+* Configurable OpenSSL library filename on Linux/Android
+ BASS_CONFIG_LIBSSL (BASS_SetConfigPtr option)
+* Files can be deleted/renamed while streaming on Windows (already true on other platforms)
+ BASS_StreamCreateFile
+* Fix for bug in playback buffering disabling option
+ BASS_ATTRIB_NOBUFFER (BASS_ChannelSetAttribute option)
+* Fix to support long logarithmic curves in volume effects
+ BASS_FX_VOLUME (BASS_ChannelSetFX type)
+
+2.4.13.8 - 6/2/2018
+-------------------
+* Indication of a file's original sample format being floating-point
+ BASS_ORIGRES_FLOAT (BASS_CHANNELINFO/SAMPLE flag)
+* Some extra sample data is retained to account for device latency in data retrieval
+ BASS_ChannelGetData
+* FFT window is shortened to match amount of available data when less than FFT size
+ BASS_ChannelGetData
+* FFT level adjusted to be approx the same regardless of amount of available data
+ BASS_ChannelGetData
+* Fix for crash when decoding channels are dissociated from a device
+ BASS_NODEVICE (BASS_ChannelSetDevice option)
+
+2.4.13 - 19/12/2017
+-------------------
+* WASAPI output on Windows (DirectSound is fallback/optional)
+ BASS_DEVICE_DSOUND (BASS_Init flag)
+ BASS_CONFIG_DEV_BUFFER/NONSTOP (BASS_SetConfig options)
+ BASS_CONFIG_SRC/_SAMPLE (BASS_SetConfig options)
+ BASS_ATTRIB_SRC/NORAMP (BASS_ChannelSetAttribute options)
+* Default output device following support extended to Windows Vista and macOS
+ BASS_CONFIG_DEV_DEFAULT (BASS_SetConfig option)
+* Seamless playback buffer length changing
+ BASS_ATTRIB_BUFFER (BASS_ChannelSetAttribute option)
+ BASS_ATTRIB_NOBUFFER deprecated
+ SYNTH example updated
+* Access to the final output mix for applying DSP/FX
+ STREAMPROC_DEVICE (BASS_StreamCreate option)
+ BASS_CTYPE_STREAM_DEVICE
+ FXTEST example updated
+* Dissociating of decoding channels from a device
+ BASS_NODEVICE (BASS_ChannelSetDevice option)
+* Volume attribute levels above 1.0 for amplification
+ BASS_ATTRIB_VOL (BASS_ChannelSetAttribute option)
+* Logarithmic attribute slides
+ BASS_SLIDE_LOG (BASS_ChannelSlideAttribute flag)
+* Volume & panning attribute affected level retrieval
+ BASS_LEVEL_VOLPAN (BASS_ChannelGetLevelEx flag)
+* Volume level adjustment effect
+ BASS_FX_VOLUME (BASS_ChannelSetFX type)
+ BASS_FX_VOLUME_PARAM structure
+* Asynchronous pre-buffering
+ BASS_CONFIG_NET_PREBUF_WAIT (BASS_SetConfig option)
+ BASS_StreamCreateURL/FileUser
+ CONTEST and NETRADIO examples updated
+* Decoding channels can be dissociated from a device
+ BASS_ChannelSetDevice
+* Resetting of user file streams/decoders
+ BASS_POS_RESET (BASS_ChannelSetPosition flag)
+* Relative seeking
+ BASS_POS_RELATIVE (BASS_ChannelSetPosition flag)
+* RIFF cue points chunk retrieval
+ BASS_TAG_RIFF_CUE (BASS_ChannelGetTags type)
+ TAG_CUE structure
+* RIFF sample chunk retrieval
+ BASS_TAG_RIFF_SMPL (BASS_ChannelGetTags type)
+ TAG_SMPL structure
+* Support for Category/Description/Grouping/Keywords/Lyrics MP4 tags
+ BASS_TAG_MP4 (BASS_ChannelGetTags type)
+* Separate channel type for dummy streams
+ BASS_CTYPE_STREAM_DUMMY
+* Stalled internet stream buffering progress retrieval
+ BASS_FILEPOS_BUFFERING (BASS_StreamGetFilePosition mode)
+ CONTEST and NETRADIO examples updated
+* Playlist recursion depth config option
+ BASS_CONFIG_NET_PLAYLIST_DEPTH (BASS_SetConfig options)
+* Push file system read functions can now return 0 without ending the file
+ STREAMFILE_BUFFERPUSH (BASS_StreamCreateFileUser system)
+ FILEREADPROC
+* 16 point SRC is used by default when SSE is available
+ BASS_CONFIG_SRC (BASS_SetConfig option)
+* Mono downmixing for all file formats in sample loading
+ BASS_SAMPLE_MONO (BASS_SampleLoad flag)
+* Mono OGG stream downmixing
+ BASS_SAMPLE_MONO (BASS_StreamCreateFile/User/URL flag)
+* Media Foundation availability detection
+ BASS_CONFIG_MF_DISABLE (BASS_GetConfig option)
+ PLUGINS example updated
+* AudioTrack output on Android
+ BASS_DEVICE_AUDIOTRACK (BASS_Init flag)
+* Support for Android Media codecs
+ BASS_StreamCreateFile/User/URL
+ BASS_TAG_AM_MIME/NAME (BASS_ChannelGetTags type)
+ BASS_CONFIG_AM_DISABLE (BASS_SetConfig option)
+* Panning fix for MOD files created with ScreamTracker 3
+ BASS_MusicLoad
+* Fix for compressor and distotion DX8 effects with floating-point data on Windows
+ BASS_FX_DX8_COMPRESSOR/DISTORTION (BASS_ChannelSetFX types)
+* Fix for plugin freeing issue on 64-bit platforms (HPLUGIN is not library address any more)
+ BASS_PluginLoad
+ BASS_PluginFree
+
+2.4.12 - 10/3/2016
+------------------
+* DSP/FX chain order modification
+ BASS_FXSetPriority
+* Average bitrate retrieval
+ BASS_ATTRIB_BITRATE (BASS_ChannelGetAttribute option)
+* Ramping-out when stopping/pausing playback
+ BASS_ChannelStop
+ BASS_ChannelPause
+* Disabling of playback ramping
+ BASS_ATTRIB_NORAMP (BASS_ChannelSetAttribute option)
+* Pre-buffering when playback buffering is disabled
+ BASS_ChannelUpdate
+ BASS_ATTRIB_NOBUFFER (BASS_ChannelSetAttribute option)
+* Net agent and proxy config options now make a copy of the provided string
+ BASS_CONFIG_NET_AGENT/PROXY (BASS_SetConfigPtr options)
+ NETRADIO example updated
+* Unicode net agent and proxy config options on Windows
+ BASS_CONFIG_NET_AGENT/PROXY (BASS_SetConfigPtr options)
+* 32768 sample FFT
+ BASS_DATA_FFT32768 (BASS_ChannelGetData flag)
+* Support for iTunes gapless info in MP3 files
+ BASS_StreamCreateFile/User
+* 529 sample delay removed from start of MP3 files without delay info
+ BASS_StreamCreateFile/User/URL
+* Support for numerical MP4 genre (gnre) tags
+ BASS_TAG_MP4 (BASS_ChannelGetTags type)
+* Support for BASSWMA's tag option when using Media Foundation WMA codec
+ BASS_TAG_WMA (BASS_ChannelGetTags type)
+* OpenMPT author tag retrieval
+ BASS_TAG_MUSIC_AUTH (BASS_ChannelGetTags type)
+* FastTracker2 panning for XM files
+ BASS_MUSIC_FT2PAN (BASS_MusicLoad flag)
+* Support for longer device names on Windows
+ BASS_DEVICEINFO (name member)
+* Checking for floating-point support on platforms that might not have it
+ BASS_CONFIG_FLOAT (BASS_GetConfig option)
+* Attribute size retrieval fix
+ BASS_ChannelGetAttributeEx
+* Fix for missing LC_VERSION_MIN issue with Xcode 7 on OSX, ppc architecture (PowerPC) support dropped
+* LIST example renamed to DEVLIST
+
+2.4.11 - 22/12/2014
+-------------------
+* Support for custom HTTP request headers
+ BASS_StreamCreateURL
+* HTTPS support on Linux/Android
+ BASS_StreamCreateURL
+* Redirection HTTP headers provided during connection
+ BASS_STREAM_STATUS (BASS_StreamCreateURL flag)
+ DOWNLOADPROC
+* Adjustable stalled internet stream resumption buffer level
+ BASS_ATTRIB_NET_RESUME (BASS_ChannelSetAttribute option)
+* Extended level retrieval inc. multi-channel and RMS options
+ BASS_ChannelGetLevelEx
+* Inexact/faster seeking
+ BASS_POS_INEXACT (BASS_ChannelSetPosition flag)
+* Post-stream creation scanning (seek table building)
+ BASS_POS_SCAN (BASS_ChannelSetPosition flag)
+* Extended attribute support
+ BASS_ChannelGet/SetAttributeEx
+* Scanned info retrieval and setting
+ BASS_ATTRIB_SCANINFO (BASS_ChannelGet/SetAttributeEx option)
+* Built-in ADPCM WAVE file support on Linux/Android/WinCE
+ BASS_StreamCreateFile/User/URL
+ BASS_SampleLoad
+* Active MOD channel count retrieval
+ BASS_ATTRIB_MUSIC_ACTIVE (BASS_ChannelGetAttribute option)
+* Fractional sample rates
+ BASS_ATTRIB_FREQ (BASS_ChannelSetAttribute option)
+* Device type information
+ BASS_DEVICE_TYPE_xxx (BASS_DEVICEINFO flags)
+* Unicode support for recording input names
+ BASS_CONFIG_UNICODE (BASS_SetConfig option)
+ BASS_RecordGetInputName
+* File size retrieval
+ BASS_FILEPOS_SIZE (BASS_StreamGetFilePosition mode)
+* Asynchronous file reading buffer level retrieval
+ BASS_FILEPOS_ASYNCBUF (BASS_StreamGetFilePosition mode)
+* MPEG data search limit raised to 1MB
+ BASS_CONFIG_VERIFY (BASS_SetConfig option)
+* Separate MPEG data search limit for internet/buffered streams
+ BASS_CONFIG_VERIFY_NET (BASS_SetConfig option)
+* Support for iTunes gapless info with Media Foundation and CoreAudio codecs
+ BASS_StreamCreateFile/User
+* Airplay receiver enumeration and selection on OSX
+ BASS_DEVICES_AIRPLAY (BASS_GetDeviceInfo flag)
+ BASS_CONFIG_AIRPLAY (BASS_SetConfig option)
+* Media Foundation playback of audio from videos is now optional
+ BASS_CONFIG_MF_VIDEO (BASS_SetConfig option)
+* Optional floating-point or fixed-point data retrieval on Android/WinCE
+ BASS_DATA_FLOAT/FIXED (BASS_ChannelGetData flags)
+* Continuous output when nothing is playing on Linux/Android/WinCE
+ BASS_CONFIG_DEV_NONSTOP (BASS_SetConfig option)
+* Fix for decoding channels being ended when stopping the output device
+ BASS_Stop
+* Fix for Media Foundation internet/buffered streaming on Windows 8
+ BASS_StreamCreateURL
+ BASS_StreamCreateFileUser
+* Improved compatibility with recent PulseAudio versions on Linux
+* LIST and MODTEST examples added
+* MASM API and examples removed (available as separate download)
+
+2.4.10 - 16/2/2013
+------------------
+* Asynchronous file reading/buffering
+ BASS_ASYNCFILE (BASS_StreamCreateFile/User flag)
+ BASS_CONFIG_ASYNCFILE_BUFFER (BASS_SetConfig option)
+* Support for chained OGG files (multiple logical bitstreams)
+ BASS_StreamCreateFile/User
+ BASS_CONFIG_OGG_PRESCAN (BASS_SetConfig option)
+ BASS_POS_OGG (BASS_ChannelSetPosition/ChannelGetLength mode)
+* OGG logical bitstream syncs are no longer automatically "mixtime"
+ BASS_SYNC_OGG_CHANGE (BASS_ChannelSetSync type)
+* Support for Soundtracker MOD files
+ BASS_MusicLoad
+* Complex FFT data
+ BASS_DATA_FFT_COMPLEX (BASS_ChannelGetData flag)
+* Volume levels above 1.0 for decoding channels
+ BASS_ATTRIB_VOL (BASS_ChannelSetAttribute option)
+* Recording device channel count retrieval on Windows/OSX/iOS
+ BASS_RECORDINFO (formats member)
+* Minimum recording period reduced to 5ms
+ BASS_RecordStart
+* Recording device period adjustment on OSX
+ BASS_RecordStart
+* Device UID retrieval on OSX
+ BASS_DEVICEINFO (driver member)
+* The desktop window handle is used when none is provided
+ BASS_Init
+
+2.4.9 - 3/5/2012
+----------------
+* Improved and adjustable sample rate conversion quality
+ BASS_ATTRIB_SRC (BASS_ChannelSetAttribute option)
+ BASS_CONFIG_SRC/_SAMPLE (BASS_SetConfig options)
+* Support for buffered file & internet streams with CoreAudio codecs on OSX/iOS
+ BASS_StreamCreateURL
+ BASS_StreamCreateUser
+* Data and level retrieval from sample channels
+ BASS_ChannelGetData
+ BASS_ChannelGetLevel
+* Oldest sample channel will be overridden when there are multiple candidates
+ BASS_SampleGetChannel
+* Use of the device's output rate with MODs
+ BASS_MusicLoad
+* Optional device output rate setting on OSX/iOS
+ BASS_DEVICE_FREQ (BASS_Init flag)
+* UTF-8 device information on Windows
+ BASS_CONFIG_UNICODE (BASS_SetConfig option)
+* Speaker assignment with panning/balance control on Windows Vista/7
+ BASS_CONFIG_VISTA_SPEAKERS (BASS_SetConfig option)
+ BASS_ATTRIB_PAN (BASS_ChannelGet/Set/SlideAttribute option)
+* Push stream queue level can be checked after using BASS_STREAMPROC_END
+ BASS_StreamPutData
+* Support for ALSA subdevices on Linux
+ BASS_Init
+ BASS_GetDeviceInfo
+ BASS_RecordInit
+ BASS_RecordGetDeviceInfo
+* Device list fix on 64-bit OSX
+ BASS_GetDeviceInfo
+ BASS_RecordGetDeviceInfo
+* BASS_UNICODE support fix on Linux
+ BASS_PluginLoad
+* Internet streaming tweaks/fixes on Windows
+* SYNTH example updated to use device output rate
+* RECTEST example updated (C version) for better Windows Vista/7 support
+* Documentation updated with platform-specific info for Android
+
+2.4.8 - 29/8/2011
+-----------------
+* Support for Media Foundation codecs on Windows 7 and updated Vista
+ BASS_StreamCreateFile/User/URL
+ BASS_TAG_MF (BASS_ChannelGetTags type)
+ PLUGINS example updated
+* Built-in support for MP4 tags on Win32/OSX/iOS (for Media Foundation & CoreAudio AAC/ALAC codecs)
+ BASS_TAG_MP4 (BASS_ChannelGetTags type)
+* WAVE format chunk retrieval
+ BASS_TAG_WAVEFORMAT (BASS_ChannelGetTags type)
+* Adjustable sample channel limit
+ BASS_SampleSetInfo
+* Per-channel CPU usage monitoring
+ BASS_ATTRIB_CPU (BASS_ChannelGetAttribute option)
+* Pre-allocation of push stream queue space
+ BASS_StreamPutData
+* Support for AIFF files with the data chunk before the format info chunk
+ BASS_StreamCreateFile/User/URL
+* Ramping-in disabled for all but the XM format (and MODs in FT2 mode) in "normal" ramping mode
+ BASS_MUSIC_RAMP (BASS_MusicLoad flag)
+* RIFF "INFO" tag reading fix
+ BASS_TAG_RIFF_INFO (BASS_ChannelGetTags type)
+* OSX 10.7 compatibility fix
+* x86_64 architecture support on OSX
+* Delphi dynamic loading unit removed (now available as separate download)
+
+2.4.7 - 30/11/2010
+------------------
+* Decode-to-position seeking
+ BASS_POS_DECODETO (BASS_ChannelSetPosition flag)
+* Support for RIFF "DISP" text tags
+ BASS_TAG_RIFF_DISP (BASS_ChannelGetTags type)
+* Support for APEv1 tags
+ BASS_TAG_APE (BASS_ChannelGetTags type)
+ BASS_TAG_APE_BINARY (BASS_ChannelGetTags type)
+* 16384 sample FFT
+ BASS_DATA_FFT16384 (BASS_ChannelGetData flag)
+* Support for AIFF files larger than 4GB
+ BASS_StreamCreateFile/User/URL
+* Acceptance of self-signed and invalid certificates
+ BASS_StreamCreateURL
+* Internet stream reading timeout
+ BASS_CONFIG_NET_READTIMEOUT (BASS_SetConfig option)
+* Support for removing a DSP within its DSPPROC
+ BASS_ChannelRemoveDSP
+* Buffer bypassing for lower latency output (not available on Windows)
+ BASS_ATTRIB_NOBUFFER (BASS_ChannelSetAttribute option)
+ SYNTH example added (OSX)
+* A "Default" device that follows default device changes on Windows 7
+ BASS_CONFIG_DEV_DEFAULT (BASS_SetConfig option)
+* Xcode examples project added for OSX
+* Documentation updated with platform-specific info for iOS/Linux/WinCE
+
+2.4.6 - 17/6/2010
+-----------------
+* Support for APEv2 tags, including binary
+ BASS_TAG_APE (BASS_ChannelGetTags type)
+ BASS_TAG_APE_BINARY (BASS_ChannelGetTags type)
+* Unicode/IDN URL support
+ BASS_StreamCreateURL
+* Decoding position retrieval
+ BASS_POS_DECODE (BASS_ChannelGetPosition flag)
+* Support for OGG 6/7.1 channel configs
+ BASS_StreamCreateFile/User/URL
+* Support for setting syncs within mixtime SYNCPROCs
+ BASS_ChannelSetSync
+* Support for setting additional DSP/FX within DSPPROCs
+ BASS_ChannelSetDSP/FX
+* DC bias removal in FFT processing
+ BASS_DATA_FFT_REMOVEDC (BASS_ChannelGetData flag)
+* Fix for incorrect (2x) return value when getting FFT data from a 16-bit channel
+ BASS_ChannelGetData
+* Fix for incorrect (STOPPED instead of PAUSED) channel status following BASS_Pause
+ BASS_ChannelIsActive
+
+2.4.5 - 18/12/2009
+------------------
+* Support for little-endian AIFF files
+ BASS_StreamCreateFile/User/URL
+ BASS_SampleLoad
+* Support for 64-bit floating-point WAVE/AIFF files
+ BASS_StreamCreateFile/User/URL
+ BASS_SampleLoad
+* Input volume retrieval failure results in a reading of -1 instead of 1
+ BASS_RecordGetInput
+ RECTEST example updated
+* Input volume support on OSX
+ BASS_RecordSetInput
+ BASS_RecordGetInput
+ RECTEST example updated
+* Fix for deferred input settings on Vista
+ BASS_RecordSetInput
+* Windows MP3 codec given preference over other installed MP3 codecs (MP3-FREE version)
+ BASS_StreamCreateFile/User/URL
+ BASS_SampleLoad
+
+2.4.4 - 13/10/2009
+------------------
+* RIFF/BWF "radio traffic" tag retrieval
+ BASS_TAG_RIFF_CART (BASS_ChannelGetTags type)
+ TAG_CART structure
+* Support for ID3v2 tags in RIFF/WAVE/AIFF files ("ID3 " chunk)
+ BASS_TAG_ID3V2 (BASS_ChannelGetTags type)
+* Pushed fractional samples are refused rather than discarded
+ BASS_StreamPutData
+* DX8 effect emulation on OSX
+ BASS_FX_DX8_CHORUS/DISTORTION/ECHO/FLANGER/PARAMEQ/REVERB (BASS_ChannelSetFX types)
+ FXTEST example added
+* UTF-16 support on OSX
+ BASS_UNICODE (BASS_StreamCreateFile/SampleLoad/MusicLoad/PluginLoad flag)
+
+2.4.3 - 8/5/2009
+----------------
+* MOD order list retrieval
+ BASS_TAG_MUSIC_ORDERS (BASS_ChannelGetTags type)
+* Support for ID3v2 tags in RIFF/WAVE files ("id3 " chunk)
+ BASS_TAG_ID3V2 (BASS_ChannelGetTags type)
+* Improved position reporting precision on Vista
+ BASS_ChannelGetPosition
+* Length retrieval when streaming in blocks (BASS_STREAM_BLOCK)
+ BASS_ChannelGetLength
+* Support for CoreAudio codecs on OSX
+ BASS_StreamCreateFile/User
+ BASS_SampleLoad
+ BASS_TAG_CA_CODEC (BASS_ChannelGetTags type)
+ TAG_CA_CODEC structure
+* 3D algorithm option support on OSX
+ BASS_CONFIG_3DALGORITHM (BASS_SetConfig option)
+
+2.4.2 - 18/9/2008
+-----------------
+* RF64 support
+ BASS_StreamCreateFile/User
+* RIFF/BWF "Broadcast Audio Extension" tag retrieval
+ BASS_TAG_RIFF_BEXT (BASS_ChannelGetTags type)
+ TAG_BEXT structure
+* ID3v1 tag structure
+ TAG_ID3 structure
+* Multiple simultaneous recordings per device on Vista & OSX (as on XP)
+ BASS_RecordStart
+* DX8 effect parameter defaults updated/corrected in documentation
+
+2.4 - 2/4/2008
+--------------
+* "Push" streaming
+ STREAMPROC_PUSH (BASS_StreamCreate option)
+ BASS_StreamPutData
+ LIVEFX and MULTI examples updated
+* "Push" buffered file streaming
+ STREAMFILE_BUFFERPUSH (BASS_StreamCreateFileUser system)
+ BASS_StreamPutFileData
+* STREAMFILEPROC replaced by table of callbacks for each file operation
+ BASS_FILEPROCS (FILECLOSEPROC/FILELENPROC/FILEREADPROC/FILESEEKPROC)
+ STREAMFILEPROC *removed*
+* 64-bit file positioning
+ BASS_SampleLoad
+ BASS_MusicLoad
+ BASS_StreamCreateFile
+ BASS_StreamGetFilePosition
+* File buffer level retrieval
+ BASS_FILEPOS_BUFFER (BASS_StreamGetFilePosition mode)
+* Sinc interpolated MOD music mixing
+ BASS_MUSIC_SINCINTER (BASS_MusicLoad flag)
+* MO3 2.4 support
+ BASS_MusicLoad
+* MOD orders positioning incorporated into channel functions
+ BASS_ChannelGetLength
+ BASS_ChannelSetPosition
+ BASS_ChannelGetPosition
+ BASS_MusicGetOrderPosition *removed*
+ BASS_MusicGetOrders *removed*
+* Channel attribute functions consolidated
+ BASS_ChannelSetAttribute
+ BASS_ChannelGetAttribute
+ BASS_ChannelSlideAttribute
+ BASS_ChannelIsSliding
+ BASS_ChannelSetAttributes *removed*
+ BASS_ChannelGetAttributes *removed*
+ BASS_ChannelSlideAttributes *removed*
+ BASS_ChannelSetEAXMix *removed*
+ BASS_ChannelGetEAXMix *removed*
+ BASS_MusicSetAttribute *removed*
+ BASS_MusicGetAttribute *removed*
+* Floating-point volume and panning
+ BASS_SetVolume
+ BASS_GetVolume
+ BASS_RecordSetInput
+ BASS_RecordGetInput
+ BASS_ATTRIB_PAN/VOL (BASS_ChannelGet/Set/SlideAttribute options)
+ BASS_ATTRIB_MUSIC_VOL_CHAN/INST (BASS_ChannelGet/Set/SlideAttribute options)
+ BASS_SAMPLE (volume/pan/outvol members)
+ BASS_CONFIG_MAXVOL *removed*
+ BASSTEST and RECTEST examples updated
+* Output device volume control on Vista (as on other OS)
+ BASS_SetVolume
+ BASS_GetVolume
+* Multiple update threads
+ BASS_CONFIG_UPDATETHREADS (BASS_SetConfig option)
+ BASSTEST example updated
+* Global volume range increased to 10000
+ BASS_CONFIG_GVOL_SAMPLE/STREAM/MUSIC (BASS_SetConfig options)
+ BASSTEST example updated
+* Setting and retrieving of a sample's data
+ BASS_SampleSetData
+ BASS_SampleGetData
+ BASS_SampleCreate
+ BASS_SampleCreateDone *removed*
+* Channel flag setting mask
+ BASS_ChannelFlags
+ BASS_ChannelSetFlags *removed*
+ SPEAKERS example updated
+* 256 sample FFT
+ BASS_DATA_FFT256 (BASS_ChannelGetData flag)
+* Channel locking to prevent access by other threads
+ BASS_ChannelLock
+* Manual channel buffer updating
+ BASS_ChannelUpdate
+ BASS_ChannelPreBuf *removed*
+* Configurable manual update length
+ BASS_Update
+* Extended device information retrieval and detection of new/removed devices
+ BASS_GetDeviceInfo
+ BASS_RecordGetDeviceInfo
+ BASS_DEVICEINFO structure
+ BASS_GetDeviceDescription *removed*
+ BASS_RecordGetDeviceDescription *removed*
+ BASS_INFO (driver member) *removed*
+ BASS_RECORDINFO (driver member) *removed*
+ MULTI example updated
+* Default device change tracking on Windows (as on OSX)
+ BASS_Init
+ BASS_RecordInit
+* Speaker detection from Windows control panel
+ BASS_DEVICE_CPSPEAKERS (BASS_Init flag)
+* Channel automatically stopped & resumed for DX8 effects
+ BASS_ChannelSetFX
+ BASS_ChannelRemoveFX
+* "double" precision position conversion
+ BASS_ChannelBytes2Seconds
+ BASS_ChannelSeconds2Bytes
+* Separate config functions for pointers
+ BASS_SetConfigPtr
+ BASS_GetConfigPtr
+ BASS_CONFIG_NET_AGENT/PROXY (BASS_SetConfigPtr options)
+* Configurable file format verification length
+ BASS_CONFIG_VERIFY (BASS_SetConfig option)
+* Stream filename retrieval
+ BASS_CHANNELINFO (file member)
+* Channel sample retrieval
+ BASS_CHANNELINFO (sample member)
+* META syncs no longer receive metadata in the "data" parameter
+ BASS_SYNC_META (BASS_ChannelSetSync type)
+* Separate sync for OGG logical bitstream changes (instead of BASS_SYNC_META)
+ BASS_SYNC_OGG_CHANGE (BASS_ChannelSetSync type)
+ NETRADIO example updated (C version)
+* Message syncing removed (use PostMessage instead)
+ BASS_SYNC_MESSAGE (BASS_ChannelSetSync flag) *removed*
+* Data retrieval from stopped/paused channels
+ BASS_ChannelGetData
+* Callback "user" parameters changed to pointers
+ BASS_StreamCreate / STREAMPROC
+ BASS_StreamCreateFileUser
+ BASS_StreamCreateURL / DOWNLOADPROC
+ BASS_RecordStart / RECORDPROC
+ BASS_ChannelSetDSP / DSPPROC
+ BASS_ChannelSetSync / SYNCPROC
+
+2.3.0.3 - 30/7/2007
+-------------------
+* FX state resetting
+ BASS_FXReset
+* PLS/M3U playlist URL processing
+ BASS_CONFIG_NET_PLAYLIST (BASS_SetConfig option)
+ NETRADIO example updated
+* Internet stream connection status retrieval
+ BASS_FILEPOS_CONNECTED (BASS_StreamGetFilePosition mode)
+* Lyrics3v2 tags
+ BASS_TAG_LYRICS3 (BASS_ChannelGetTags type)
+* IT virtual channel configuration
+ BASS_CONFIG_MUSIC_VIRTUAL (BASS_SetConfig option)
+* Accurate speaker detection on Vista
+ BASS_INFO (speakers member)
+* Device output/input rate retrieval on Vista
+ BASS_INFO (freq member)
+ BASS_RECORDINFO (freq member)
+* Syncing upon position changes
+ BASS_SYNC_SETPOS (BASS_ChannelSetSync type)
+* Improved stall handling
+ BASS_SYNC_STALL
+* Invalid decoding channel flags produce an error instead of being ignored
+ BASS_StreamCreate/File/User/URL
+ BASS_MusicLoad
+
+2.3.0.2 - 22/1/2007
+-------------------
+* Retrieval of a sample's existing channel handles
+ BASS_SampleGetChannels
+* 8192 sample FFT
+ BASS_DATA_FFT8192 (BASS_ChannelGetData flag)
+* Adjustable recording buffer
+ BASS_CONFIG_REC_BUFFER (BASS_SetConfig option)
+* Stopping decoding channels before the end
+ BASS_ChannelStop
+* Sample channels created paused to prevent overriding before playback
+ BASS_SampleGetChannel
+* Separate "MP3-FREE" version using the OS's MP3 decoder
+ BASS_CONFIG_MP3_CODEC *removed*
+
+2.3.0.1 - 12/6/2006
+-------------------
+* Ability to move a channel to another device
+ BASS_ChannelSetDevice
+ MULTI example updated
+* Support for ID3v2.4 tags at end of file
+ BASS_TAG_ID3V2 (BASS_ChannelGetTags type)
+
+2.3 - 21/5/2006
+---------------
+* MOD message/instrument/sample text retrieval, merged with stream tag retrieval function
+ BASS_ChannelGetTags
+ BASS_TAG_MUSIC_NAME/MESSAGE/INST/SAMPLE (BASS_ChannelGetTags types)
+ BASS_MusicGetName *removed*
+ BASS_StreamGetTags *removed*
+* Plugin information retrieval
+ BASS_PluginGetInfo
+ BASS_PLUGININFO/FORM structures
+ BASS_CHANNELINFO (plugin member)
+ PLUGINS example updated
+* RIFF/WAVE "INFO" tag retrieval
+ BASS_TAG_RIFF_INFO (BASS_StreamGetTags type)
+* More specific WAVE format information
+ BASS_CTYPE_STREAM_WAV_PCM/FLOAT (channel types)
+ BASS_CTYPE_STREAM_WAV (channel type flag)
+* Proxy server configuration
+ BASS_CONFIG_NET_PROXY (BASS_SetConfig option)
+ BASS_CONFIG_NET_NOPROXY *removed*
+ NETRADIO example updated
+* Passive FTP mode
+ BASS_CONFIG_NET_PASSIVE (BASS_SetConfig option)
+* Agent changes take immediate effect
+ BASS_CONFIG_NET_AGENT (BASS_SetConfig option)
+* Minimum time gap between creating new sample channels
+ BASS_SAMPLE (mingap member)
+ BASS_SampleGetChannel
+* Support for Unicode plugin filenames
+ BASS_PluginLoad
+* Device output/input rate retrieval (MacOSX only)
+ BASS_INFO (freq member)
+ BASS_RECORDINFO (freq member)
+* Extended version info (minor revision)
+ BASS_GetVersion
+* Unsupported codec error code
+ BASS_ERROR_CODEC
+* Optional use of the Windows MP3 codec
+ BASS_CONFIG_MP3_CODEC (BASS_SetConfig option)
+* 3D support for MacOSX
+ BASS_Set3DFactors
+ BASS_Get3DFactors
+ BASS_Set3DPosition
+ BASS_Get3DPosition
+ BASS_Apply3D
+ BASS_ChannelSet3DAttributes
+ BASS_ChannelGet3DAttributes
+ BASS_ChannelSet3DPosition
+ BASS_ChannelGet3DPosition
+ 3DTEST example added (Win32 example also updated)
+* VB version of SYNTH example added
+
+2.2 - 2/10/2005
+---------------
+* Add-on plugin system
+ BASS_PluginLoad
+ BASS_PluginFree
+ BASS_StreamCreateFile/User/URL
+ BASS_SampleLoad
+ PLUGINS example added
+* MOD position & syncing in bytes
+ BASS_ChannelSetPosition
+ BASS_ChannelGetPosition
+ BASS_MusicGetOrderPosition added for orders position
+ BASS_SYNC_MUSICPOS added for orders syncing
+ MAKEMUSICPOS macro/define
+ CUSTLOOP example updated
+* Stream/MOD "length" functions combined (also works with samples), new MOD orders length function
+ BASS_ChannelGetLength
+ BASS_MusicGetOrders
+ BASS_StreamGetLength *removed*
+ BASS_MusicGetLength *removed*
+* Support for AIFF files
+ BASS_StreamCreateFile/User/URL
+ BASS_SampleLoad
+* Support for 24 and 32-bit (integer) WAV files
+ BASS_StreamCreateFile/User/URL
+ BASS_SampleLoad
+* WAV files are no longer converted to the "device" resolution
+ BASS_StreamCreateFile/User/URL
+* Recording master control
+ BASS_RecordGetInput
+ BASS_RecordSetInput
+* Adjustable pre-buffering
+ BASS_ChannelPreBuf
+* Floating-point data retrieval
+ BASS_DATA_FLOAT (BASS_ChannelGetData flag)
+* Support for floating-point samples
+ BASS_SampleLoad
+ BASS_SampleCreate
+* Multi-channel samples
+ BASS_SampleLoad/Create
+ BASS_SAMPLE (chans member)
+* Sample lengths given in bytes
+ BASS_SampleCreate
+ BASS_SAMPLE (length member)
+* MOD music 8-bit resolution option
+ BASS_MusicLoad
+* OGG vendor tag retrieval
+ BASS_TAG_VENDOR (BASS_StreamGetTags type)
+* Configurable "User-Agent" header for internet streams
+ BASS_CONFIG_NET_AGENT (BASS_SetConfig option)
+* Shoutcast metadata is now requested automatically
+ BASS_STREAM_META flag *removed*
+* Download callbacks receive all data from start of file/stream (including any non-audio data)
+ DOWNLOADPROC
+* Length when streaming in blocks is unavailable (BASS_ERROR_NOTAVAIL, not just 0)
+ BASS_ChannelGetLength
+* Support for growing custom file streams
+ BASS_FILE_LEN (STREAMFILEPROC action)
+* Query file action removed
+ BASS_FILE_QUERY *removed*
+* Recording channel syncing
+ BASS_ChannelSetSync
+* Info structure "size" members removed
+ BASS_INFO structure
+ BASS_RECORDINFO structure
+* Little bit of flag reshuffling
+ BASS_MP3_SETPOS renamed to BASS_STREAM_PRESCAN
+ BASS_MUSIC_CALCLEN value changed and renamed to BASS_MUSIC_PRESCAN
+ BASS_MUSIC_POSRESET value changed
+* Add-on API enhancements
+* MacOSX port introduced
+
+2.1 - 28/11/2004
+----------------
+* Improved "mixtime" sync system, allowing custom looping
+ SYNCPROC
+ CUSTLOOP example added
+* FX can now be in the DSP chain, so can be prioritized and applied in floating-point
+ BASS_ChannelSetFX
+ BASS_CONFIG_FLOATDSP (BASS_SetConfig option)
+* Ability to set channel flags (eg. looping) independent of playback
+ BASS_ChannelSetFlags
+ SPEAKERS example updated
+* Stream/MOD "play" and channel "resume" functions combined
+ BASS_ChannelPlay
+ BASS_StreamPlay *removed*
+ BASS_MusicPlay *removed*
+ BASS_MusicPlayEx *removed*
+ BASS_ChannelResume *removed*
+* Stream/MOD pre-buffering functions combined
+ BASS_ChannelPreBuf
+ BASS_StreamPreBuf *removed*
+ BASS_MusicPreBuf *removed*
+* MOD attribute functions combined, with added BPM/speed/globalvolume options
+ BASS_MusicSetAttribute
+ BASS_MusicGetAttribute
+ BASS_MUSIC_ATTRIB_AMPLIFY
+ BASS_MUSIC_ATTRIB_PANSEP
+ BASS_MUSIC_ATTRIB_PSCALER
+ BASS_MUSIC_ATTRIB_BPM
+ BASS_MUSIC_ATTRIB_SPEED
+ BASS_MUSIC_ATTRIB_VOL_GLOBAL
+ BASS_MUSIC_ATTRIB_VOL_CHAN
+ BASS_MUSIC_ATTRIB_VOL_INST
+ BASS_MusicSetAmplify *removed*
+ BASS_MusicSetPanSep *removed*
+ BASS_MusicSetPositionScaler *removed*
+ BASS_MusicSetVolume *removed*
+ BASS_MusicGetVolume *removed*
+* Flag to reset bpm/etc as well as notes when seeking in MOD musics
+ BASS_MUSIC_POSRESETEX (BASS_MusicLoad & BASS_ChannelSetFlags flag)
+* More flexible and concise sample channel creation system
+ BASS_SampleGetChannel
+ BASS_SamplePlay *removed*
+ BASS_SamplePlayEx *removed*
+ BASS_SamplePlay3D *removed*
+ BASS_SamplePlay3DEx *removed*
+* Support for up to 30 speakers
+ BASS_SPEAKER_N macro/define
+* More precise level measurement
+ BASS_ChannelGetLevel
+* Level can now be retrieved from decoding channels
+ BASS_ChannelGetLevel
+* Retrieval of a sample/channel's original sample resolution
+ BASS_SAMPLE (origres member)
+ BASS_CHANNELINFO (origres member)
+* Support for streaming WAV files in "blocks"
+ BASS_StreamCreateURL
+ BASS_StreamCreateFileUser
+* Status info (HTTP/ICY tags) available during connection to server
+ BASS_STREAM_STATUS (BASS_StreamCreateURL flag)
+ DOWNLOADPROC
+ NETRADIO example updated (Delphi version also added)
+* Adjustable internet stream pre-buffering
+ BASS_CONFIG_NET_PREBUF (BASS_SetConfig option)
+* Option to bypass proxy server
+ BASS_CONFIG_NET_NOPROXY (BASS_SetConfig option)
+* Option whether to allow channels to be played after BASS_Pause
+ BASS_CONFIG_PAUSE_NOPLAY (BASS_SetConfig option)
+* Recording channel count now a separate parameter
+ BASS_RecordStart (chans parameter)
+* Synchronizer for when a channel is freed
+ BASS_SYNC_FREE (BASS_ChannelSetSync type)
+* Data start file position retrieval
+ BASS_FILEPOS_START (BASS_StreamGetFilePosition mode)
+* Performance improvements
+ MP2 decoding ~20% faster
+ MP3/MP1 decoding & FFT processing all up to 10% faster
+ OGG decoding ~3% faster
+* C/C++ examples reorganised, with makefiles & VC++ projects
+* Add-on API enhancements
+* More DLL shrinkage :)
+
+2.0 - 31/10/2003
+----------------
+* Multiple output device support
+ BASS_Init (device number changes)
+ BASS_SetDevice
+ BASS_GetDevice
+ BASS_ChannelGetDevice
+ MULTI example updated (VB version also added)
+* Multiple recording device support
+ BASS_RecordSetDevice
+ BASS_RecordGetDevice
+ BASS_RecordStart
+ BASS_ChannelGetDevice
+ HRECORD handle
+ RECORDPROC (handle parameter)
+* Recording with DSP/FX
+ BASS_ChannelSetDSP
+ BASS_ChannelSetFX
+* Recording position retrieval
+ BASS_ChannelGetPosition
+* Start recording paused
+ BASS_RECORD_PAUSE (BASS_RecordStart flag)
+* Multi-channel streams, inc. support for multichannel OGG & WAV files
+ BASS_StreamCreate
+ BASS_StreamCreateFile/User/URL
+* FFT for individual channels, inc. multi-channel streams
+ BASS_DATA_FFT_INDIVIDUAL (BASS_ChannelGetData flag)
+ BASS_DATA_FFT512S/1024S/2048S/4096S *removed*
+* DSP prioritizing
+ BASS_ChannelSetDSP
+ DSPTEST example updated
+* Seeking in internet streamed files
+ BASS_ChannelSetPosition
+* Enhanced custom file stream systems
+ BASS_StreamCreateFileUser
+ BASS_FILE_SEEK (STREAMFILEPROC action)
+ BASS_STREAM_FILEPROC flag *removed*
+* Enhanced custom stream system with automatic stalling/resuming
+ STREAMPROC
+ BASS_STREAMPROC_END (STREAMPROC flag)
+* Synchronizer for stalled/resumed playback
+ BASS_SYNC_STALL (BASS_ChannelSetSync type)
+* Synchronizer for completed download
+ BASS_SYNC_DOWNLOAD (BASS_ChannelSetSync type)
+* End sync support for custom streams
+ BASS_SYNC_END (BASS_ChannelSetSync type)
+* Synchronizer support for decoding channels
+ BASS_ChannelSetSync
+* Unified configuration function
+ BASS_SetConfig
+ BASS_GetConfig
+ BASS_SetBufferLength *removed*
+ BASS_SetNetConfig *removed*
+ BASS_SetGlobalVolumes *removed*
+ BASS_GetGlobalVolumes *removed*
+ BASS_SetLogCurves *removed*
+ BASS_Set3DAlgorithm *removed*
+ BASS_DEVICE_FLOATDSP flag *removed*
+* Internet stream saving to disk replaced by more flexible callback
+ BASS_StreamCreateURL
+ DOWNLOADPROC
+ VB NETRADIO example updated
+* Buffer length retrieval when "streaming in blocks"
+ BASS_FILEPOS_END (BASS_StreamGetFilePosition mode)
+* Individual sample rate setting for MOD musics
+ BASS_MusicLoad
+* Channel type and default sample rate retrieval
+ BASS_ChannelGetInfo (replaces BASS_ChannelGetFlags)
+ BASS_CHANNELINFO
+* MOD music flag retrieval
+ BASS_CHANNELINFO (flags member)
+* Adjustable instrument volumes in MOD musics
+ BASS_MusicSetVolume (replaces BASS_MusicSetChannelVol)
+ BASS_MusicGetVolume (replaces BASS_MusicGetChannelVol)
+* Automatically free a MOD music when it stops or ends
+ BASS_MUSIC_AUTOFREE (BASS_MusicLoad flag)
+* Class GUID added to initialization parameters
+ BASS_Init
+ BASS_SetCLSID *removed*
+* Update period adjustable at any time
+ BASS_CONFIG_UPDATEPERIOD (BASS_SetConfig option)
+ BASS_DEVICE_NOTHREAD flag *removed*
+* Customizable maximum volume setting
+ BASS_CONFIG_MAXVOL (BASS_SetConfig option)
+ BASS_DEVICE_VOL1000 flag *removed*
+* Device volume is now always left as it is during init/freeing
+ BASS_DEVICE_LEAVEVOL flag *removed*
+* Device driver name retrieval
+ BASS_INFO (driver member)
+ BASS_RECORDINFO (driver member)
+* Error codes are local to the current thread
+ BASS_ErrorGetCode
+* Performance improvements
+ MP2 decoding 15-20% faster
+ MP3 decoding ~5% faster
+* Built-in CD functions removed (replaced in BASSCD)
+ BASS_CDDoor *removed*
+ BASS_CDFree *removed*
+ BASS_CDGetID *removed*
+ BASS_CDGetTrackLength *removed*
+ BASS_CDGetTracks *removed*
+ BASS_CDInDrive *removed*
+ BASS_CDInit *removed*
+ BASS_CDPlay *removed*
+* Force channels to use software mixing
+ BASS_SAMPLE_SOFTWARE (BASS_StreamCreate/File/User/URL & BASS_MusicLoad flag)
+* Support for high-pass filter and forward/reverse (S9E/F) IT/MPT effects
+* BASS_MUSIC flags rearranged to mirror BASS_SAMPLE/STREAM counterparts
+* Output automatically started during initialization
+* BASS_ChannelGetData once again accepts any "length" param
+* All function comments have been removed from the API headers to avoid
+ outdated/incorrect information - the documentation should be used.
+* TMT Pascal API removed from main distribution - now available on the website
+* A few more 'K' knocked off the DLL size :)
+
+1.8a - 18/6/2003
+----------------
+* Tweaks 'n' fixes, including...
+ Fixed seeking bug on 32-bit OGG streams
+ Fixed seeking on a decoding channel after it has reached the end
+ Low FPU precision (eg. when using Direct3D) issue addressed
+ Improved speakers (BASS_INFO) detection
+ BASS_ChannelSeconds2Bytes return value is rounded down to nearest sample
+ BASS_ChannelGetData "length" param must equal a whole number of samples
+ Slide syncs are triggered by "-2" volume slides on "autofree" streams
+* Support for Unicode filenames
+ BASS_UNICODE (BASS_SampleLoad/BASS_StreamCreateFile/BASS_MusicLoad flag)
+* 4096 sample FFT
+ BASS_DATA_FFT4096/S (BASS_ChannelGetData flags)
+* Another 'K' knocked off the DLL size
+
+1.8 - 9/3/2003
+--------------
+* 32-bit floating-point channels
+ BASS_SAMPLE_FLOAT (BASS_StreamCreate/File/URL flag)
+ BASS_MUSIC_FLOAT (BASS_MusicLoad flag)
+ BASS_SAMPLE_FLOAT (BASS_RecordStart flag)
+ BASS_DEVICE_FLOATDSP (BASS_Init flag)
+ DSPTEST example updated
+* Support for 32-bit floating-point (type 3) WAV files
+ BASS_StreamCreateFile/URL
+ BASS_SampleLoad
+* Channel speaker assignment
+ BASS_SPEAKER_FRONT (BASS_MusicLoad/BASS_StreamCreate/File/URL flag)
+ BASS_SPEAKER_REAR "
+ BASS_SPEAKER_CENLFE "
+ BASS_SPEAKER_REAR2 "
+ BASS_SPEAKER_FRONTLEFT "
+ BASS_SPEAKER_FRONTRIGHT "
+ BASS_SPEAKER_REARLEFT "
+ BASS_SPEAKER_REARRIGHT "
+ BASS_SPEAKER_CENTER "
+ BASS_SPEAKER_LFE "
+ BASS_SPEAKER_REAR2LEFT "
+ BASS_SPEAKER_REAR2RIGHT "
+ BASS_INFO (speakers member)
+ BASS_DEVICE_SPEAKERS (BASS_Init flag)
+ 4SPEAKER example replaced by SPEAKERS example
+* Recording input type retrieval
+ BASS_INPUT_TYPE_xxx (BASS_RecordGetInput)
+ RECTEST example updated
+* Non-interpolated MOD mixing
+ BASS_MUSIC_NONINTER (BASS_MusicLoad/PlayEx flag)
+* Performance improvements
+ FFT up to 100% faster!
+ MP3(MPEG2/2.5) decoding up to 60% faster
+ MMX mixers 5-10% faster
+ MP3(MPEG1)/MP2/MP1/OGG decoding all ~5% faster
+* Optional disabling of FFT windowing
+ BASS_DATA_FFT_NOWINDOW (BASS_ChannelGetData flag)
+* BASS_ERROR_FILEFORM - error code to distinguish between file and sample format
+ BASS_MusicLoad
+ BASS_SampleLoad
+ BASS_StreamCreate/File/URL
+* BASS_StreamGetFilePosition mode flags added
+ BASS_FILEPOS_DECODE/DOWNLOAD/END
+* DirectSound 9 detection
+ BASS_INFO (dsver member)
+* Initialization flags retrieval
+ BASS_INFO (initflags member)
+* Half-rate MP3 playback option removed
+ BASS_MP3_HALFRATE flag *removed*
+* New internal "plugin" system - BASSWMA is further integrated as a result
+* Improved documentation - integrated with BASSWMA, search option added
+* VB version of DSPTEST example added
+* Delphi RECORDTEST example added
+* Guess what... reduced DLL size again :)
+
+1.7 - 27/10/2002
+----------------
+* New alternative DX8 (DMO) effects implementation
+ BASS_StreamCreate/File/URL
+ BASS_MusicLoad
+ BASS_ChannelSetFX
+ SYNTH example updated
+* User file streaming
+ BASS_STREAM_FILEPROC (BASS_StreamCreate flag)
+ STREAMFILEPROC
+* DSP & FX support for decoding channels
+ BASS_ChannelSetDSP
+ BASS_ChannelSetFX
+* Support for DX8 (DMO) effects in IT/XM/MO3 files
+ BASS_MusicLoad
+* Support for chained OGG streaming (and syncing)
+ BASS_StreamCreateURL
+ BASS_SYNC_META (BASS_ChannelSetSync type)
+* Attribute (volume/frequency/pan) sliding
+ BASS_ChannelSlideAttributes
+ BASS_ChannelIsSliding
+ BASS_SYNC_SLIDE (BASS_ChannelSetSync type)
+* Recording without a callback function
+ BASS_RecordStart
+ LIVEFX example added
+* Query a channel's buffered data
+ BASS_DATA_AVAILABLE (BASS_ChannelGetData flag)
+* Discard data from the recording buffer
+ BASS_ChannelGetData
+* Adjustable internet stream config (timeout/buffer lengths)
+ BASS_SetNetConfig
+* Recommended minimum buffer length
+ BASS_INFO (minbuf member)
+* MOD music flags adjustment without changing playback position
+ BASS_MusicPlayEx
+ PLAYER (MASM) example updated
+* More functions are now useable in MOD music "mixtime" syncs
+ SYNCPROC
+ BASS_ChannelSetPosition
+ BASS_MusicPlayEx
+ BASS_MusicSetAmplify
+ BASS_MusicSetPanSep
+* Maximum buffer length increased to 5 seconds
+ BASS_SetBufferLength
+* Support for extended filter range in IT files
+ BASS_MusicLoad
+* Speedier MOD music file verification
+ BASS_MusicLoad
+* Delphi 3DTEST example fixed
+* Magically reduced DLL size again :)
+
+1.6a - 25/8/2002
+----------------
+* OGG support updated to 1.0
+* Stereo FFT
+ BASS_DATA_FFT512S/1024S/2048S (BASS_ChannelGetData flags)
+* Support for "Invert Loop" (EFx) MOD effect
+* Reduced DLL size
+* New Delphi examples
+ WRITEWAV - WAVE writer example
+ SAMPLEVIS - Visualisation example
+
+1.6 - 13/6/2002
+---------------
+* 64-bit stream lengths and positions
+ BASS_StreamGetLength
+ BASS_ChannelBytes2Seconds
+ BASS_ChannelSeconds2Bytes
+ BASS_ChannelGetPosition
+ BASS_ChannelSetPosition
+ BASS_ChannelSetSync
+* Recording input selection
+ BASS_RECORDINFO (inputs & singlein members)
+ BASS_RecordGetInputName
+ BASS_RecordGetInput
+ BASS_RecordSetInput
+* Adjustable recording update period
+ BASS_RecordStart
+* Load OGG files as samples
+ BASS_SampleLoad
+* CD drive door opening & closing
+ BASS_CDDoor
+* CDDB2 ID retrieval
+ BASS_CDID_CDDB2 (BASS_CDGetID flag)
+* Streaming beyond initial file length
+ BASS_StreamCreateFile
+* Recording position bytes<->seconds translation
+ BASS_ChannelBytes2Seconds
+ BASS_ChannelSeconds2Bytes
+* Improved multi-threaded support (play from any thread)
+ BASS_MusicPlay/Ex
+ BASS_SamplePlay/3D/Ex
+ BASS_StreamPlay
+ BASS_DEVICE_NOSYNC flag *removed*
+* Paused channel status
+ BASS_ACTIVE_PAUSED (BASS_ChannelIsActive)
+* Integrated WMA stream freeing
+ BASS_StreamFree
+ BASS_Free
+* Pin-point accurate OGG seeking without BASS_MP3_SETPOS flag
+* Win2k DS buffer bug fix
+
+1.5a - 14/4/2002
+----------------
+* NT4 fix (also enables "nosound" device without DX installed)
+ BASS_ERROR_DX error code
+* MOD music loading without the samples
+ BASS_MUSIC_NOSAMPLE (BASS_MusicLoad flag)
+* Custom decoding channels
+ BASS_STREAM_DECODE (BASS_StreamCreate flag)
+* 5 second HTTP connection timeout
+ BASS_ERROR_TIMEOUT (BASS_StreamCreateURL error code)
+
+1.5 - 31/3/2002
+---------------
+* Improved performance
+ MMX mixers lot faster (over 50% faster in some cases!)
+ OGG decoding 15-20% faster
+ MP3 decoding 5-10% faster
+* Recording
+ BASS_RecordGetDeviceDescription
+ BASS_RecordInit
+ BASS_RecordFree
+ BASS_RecordGetInfo
+ BASS_RecordStart
+* OGG support built-in (OGG/VORBIS DLLs not required)
+ BASS_DEVICE_OGG flag *removed*
+* MOD music seeking in seconds
+ BASS_MusicPlayEx
+ BASS_ChannelSetPosition
+* Shoutcast metadata retrieval
+ BASS_STREAM_META (BASS_StreamCreateURL flag)
+ BASS_TAG_META (BASS_StreamGetTags type)
+ BASS_SYNC_META (BASS_ChannelSetSync type)
+* 1000 volume levels
+ BASS_DEVICE_VOL1000 (BASS_Init/CDInit flag)
+* CDDB ID retrieval
+ BASS_CDID_CDDB (BASS_CDGetID flag)
+* Leave the CD volume as it is during init/closing
+ BASS_DEVICE_LEAVEVOL (BASS_CDInit flag)
+* FFT enabled on decoding channels
+ BASS_ChannelGetData
+* Left level duplicated on right for mono channels
+ BASS_ChannelGetLevel
+* Improved MPEG length estimation without BASS_MP3_SETPOS flag
+ BASS_StreamGetLength
+* Support for Modplug/ADPCM compressed files
+ BASS_MusicLoad
+* Device description function parameter change
+ BASS_GetDeviceDescription
+* MASM API
+
+1.4 - 30/1/2002
+---------------
+* Channel decoding without playback
+ BASS_MUSIC_DECODE (BASS_MusicLoad flag)
+ BASS_STREAM_DECODE (BASS_StreamCreateFile/URL flag)
+ BASS_ChannelGetData
+* Windows message sync callbacks
+ BASS_SYNC_MESSAGE (BASS_ChannelSetSync flag)
+* Adjustable channel volumes in MOD musics
+ BASS_MusicSetChannelVol
+ BASS_MusicGetChannelVol
+* Customizable DirectSound initialization object
+ BASS_SetCLSID
+* Retrieve HMUSIC/HSTREAM/HCHANNEL IDirectSoundBuffer interfaces
+ BASS_GetDSoundObject
+* A3D functions removed (use BASS_SetCLSID/BASS_GetDSoundObject to access A3D)
+ BASS_DEVICE_A3D (BASS_Init flag)
+ BASS_SetA3DResManager
+ BASS_GetA3DResManager
+ BASS_SetA3DHFAbsorbtion
+ BASS_GetA3DHFAbsorbtion
+* Callback functions now work in VB6
+ DSPPROC
+ STREAMPROC
+ SYNCPROC
+* Improved PCM WAVE streaming performance
+ BASS_StreamCreateFile
+ BASS_StreamCreateURL
+* OGG modules updated to RC3
+* Stereo sample support in MO3 format
+* MO3 encoder now distributed separately from BASS
+
+1.3 - 17/11/2001
+----------------
+* Manual buffer updating
+ BASS_DEVICE_NOTHREAD (BASS_Init flag)
+ BASS_Update
+* Adjustable buffer update period (allows small buffer sizes)
+ BASS_Init
+* Output device latency retrieval
+ BASS_INFO (latency member)
+* MPEG/OGG seeking without BASS_MP3_SETPOS flag
+ BASS_ChannelSetPosition
+* Internet file streaming from offsets
+ BASS_StreamCreateURL
+* File stream tag/comment retrieval (ID3/ID3v2/OGG/HTTP/ICY tags)
+ BASS_StreamGetTags
+* Byte<->time position translation
+ BASS_ChannelBytes2Seconds
+ BASS_ChannelSeconds2Bytes
+* UMX (Unreal/Tournament music package) format support
+ BASS_MusicLoad
+* S3M/IT sync fx changed to S2x (S0x conflicted with S00)
+ BASS_SYNC_MUSICFX
+* Stereo sample support in IT/XM/S3M formats
+* MO3: OGG compression supported
+
+1.2 - 25/9/2001
+---------------
+* OGG (Ogg Vorbis) stream support
+ BASS_DEVICE_OGG (BASS_Init flag)
+ BASS_StreamCreateFile
+ BASS_StreamCreateURL
+* Channel linking (start/stop/pause/resume channels together)
+ BASS_ChannelSetLink
+ BASS_ChannelRemoveLink
+* MOD music playback length calculation
+ BASS_MUSIC_CALCLEN (BASS_MusicLoad flag)
+ BASS_MusicGetLength
+* Pre-buffering
+ BASS_MusicPreBuf
+ BASS_StreamPreBuf
+* Samples with single simultaneous playbacks have same HSAMPLE/HCHANNEL handle
+ BASS_SamplePlay/Ex
+* Stopping a custom stream flushes its buffer contents
+ BASS_ChannelStop
+
+1.1a - 31/8/2001
+----------------
+* NT4 bug fixed
+* XM Wxx effect syncing
+ BASS_SYNC_MUSICFX
+* MP3/2/1 rewinding without BASS_MP3_SETPOS
+ BASS_ChannelSetPosition
+
+1.1 - 11/8/2001
+---------------
+* DX8 (DMO) effects
+ BASS_SAMPLE_FX (BASS_StreamCreate/File/URL flag)
+ BASS_MUSIC_FX (BASS_MusicLoad flag)
+ BASS_ChannelSetFX
+ BASS_ChannelRemoveFX
+ BASS_FXSetParameters
+ BASS_FXGetParameters
+ BASS_FXCHORUS structure
+ BASS_FXCOMPRESSOR structure
+ BASS_FXDISTORTION structure
+ BASS_FXECHO structure
+ BASS_FXFLANGER structure
+ BASS_FXGARGLE structure
+ BASS_FXI3DL2REVERB structure
+ BASS_FXPARAMEQ structure
+ BASS_FXREVERB structure
+* Internet file streaming in blocks (inc. Shoutcast/Icecast stream support)
+ BASS_STREAM_BLOCK (BASS_StreamCreateURL flag)
+* 512/1024/2048 sample FFT
+ BASS_DATA_FFT512/1024/2048 (BASS_ChannelGetData flags)
+* CD identification
+ BASS_CDGetID
+* Improved DX version detection
+ BASS_INFO (dsver member)
+
+1.0 - 20/6/2001
+---------------
+* Load MP3/MP2/MP1 files as samples
+ BASS_SampleLoad
+* Internet file streaming from FTP servers
+ BASS_StreamCreateURL
+* Save a local copy of internet file streams
+ BASS_StreamCreateURL
+* Sample accurate file stream seeking
+ BASS_ChannelSetPosition
+ BASS_StreamGetBlockLength *removed*
+* Stream position synchronizer
+ BASS_SYNC_POS
+* Increased synchronizer precision
+* Improved MPEG file detection and error detection
+* Stop MOD musics on a backwards jump effect
+ BASS_MUSIC_STOPBACK (BASS_MusicLoad/PlayEx flag)
+* Leave the volume as it is during closing (as well as initialization)
+ BASS_DEVICE_LEAVEVOL (BASS_Init flag)
+* Optional automatic use of foreground window handle during initialization
+ BASS_Init
+* Reduced DLL size
+* VB API fixes
+
+0.9 - 18/4/2001
+---------------
+* Internet file streaming
+ BASS_StreamCreateURL
+* MP1 & MP2 (MPEG layer 1 & 2) support
+ BASS_StreamCreateFile/URL
+* MPEG 2.5 support (12000/11025/8000hz sample rates)
+ BASS_StreamCreateFile/URL
+* Decoding/download/end file stream position retrieval
+ BASS_StreamGetFilePosition
+* XMPlay surround sound for MOD musics
+ BASS_MUSIC_SURROUND (BASS_MusicLoad/PlayEx flag)
+ BASS_MUSIC_SURROUND2 (BASS_MusicLoad/PlayEx flag)
+* Restrict the download rate of internet file streams
+ BASS_STREAM_RESTRATE (BASS_StreamCreateURL flag)
+* Check if an internet file stream is stalled
+ BASS_ChannelIsActive
+* Automatically free a stream when it stops or ends
+ BASS_STREAM_AUTOFREE (BASS_StreamCreate/File/URL flag)
+* Leave the volume as it is during initialization
+ BASS_DEVICE_LEAVEVOL (BASS_Init flag)
+* Number of CD tracks retrieval
+ BASS_CDGetTracks
+* CD track length retrieval
+ BASS_CDGetTrackLength
+* Exact stream length set after whole file is streamed
+ BASS_StreamGetLength
+* TMT Pascal API and samples
+* Dynamic-loading Delphi API
+
+0.8a - 28/2/2000
+----------------
+* Updated Delphi API and samples
+
+0.8 - 24/1/2000
+---------------
+* Improved MP3 performance on P2/K6 and above CPUs
+* User DSP functions on streams and MOD musics
+ BASS_ChannelSetDSP
+ BASS_ChannelRemoveDSP
+* DX7 voice allocation & management
+ BASS_SAMPLE_VAM (BASS_SampleLoad/Create flag)
+ BASS_VAM_xxx flags
+ BASS_SAMPLE (vam & priority members)
+* DX7 software 3D algorithm selection
+ BASS_Set3DAlgorithm
+* DirectSound interface retrieval
+ BASS_GetDSoundObject
+* Log/linear volume & panning curves
+ BASS_SetLogCurves
+* User data passed to callback functions
+ STREAMPROC - BASS_StreamCreate
+ SYNCPROC - BASS_ChannelSetSync
+* New synchronizer
+ BASS_SYNC_MUSICFX
+* New synchronizer flag
+ BASS_SYNC_MIXTIME
+* Disable synchronizers option - saves a little CPU time
+ BASS_DEVICE_NOSYNC (BASS_Init flag)
+* Hi-res floating-point CPU usage monitoring
+ BASS_GetCPU
+* Wait for playback to start when playing a CD
+ BASS_CDPlay
+* DirectSound (dsound.dll) version retrieval
+ BASS_INFO (dsver member)
+* Removed volume sliding functions (they were fairly pointless)
+ BASS_SlideVolume
+ BASS_IsSliding
+* MO3: read/write encoder settings
+* MO3: remove inst/samp/message texts now optional
+* MO3: LAME encoder settings
+
+0.7 - 3/10/1999
+---------------
+* MO3 (MP3 compressed MODs)
+* A3D functions
+ BASS_DEVICE_A3D (BASS_Init flag)
+ BASS_INFO (a3d member)
+ BASS_SetA3DResManager
+ BASS_GetA3DResManager
+ BASS_SetA3DHFAbsorbtion
+ BASS_GetA3DHFAbsorbtion
+* Music/stream immediate sample data retrieval
+ BASS_ChannelGetData
+* File stream (WAV/MP3) length retrieval
+ BASS_StreamGetLength
+ BASS_StreamGetBlockLength
+* File stream seeking
+ BASS_ChannelSetPosition
+* Mono MP3 option (lower CPU usage)
+ BASS_StreamCreateFile
+* Music length retrieval
+ BASS_MusicGetLength
+* Music name retrieval
+ BASS_MusicGetName
+* Stop notes when moving MOD music position
+ BASS_MUSIC_POSRESET (BASS_MusicLoad/BASS_MusicPlayEx flag)
+* BASS_ERROR_FREQ - invalid sample rate error code
+ BASS_SampleCreate
+ BASS_SamplePlayEx
+ BASS_SamplePlay3DEx
+ BASS_StreamCreate
+ BASS_ChannelSetAttributes
+* Delphi and VB APIs
+
+0.6a - 26/7/1999
+----------------
+* Half rate MP3 option (lower CPU usage)
+ BASS_MP3_HALFRATE
+* Loading/streaming from file offsets
+ BASS_MusicLoad
+ BASS_SampleLoad
+ BASS_StreamCreateFile
+* Global music/sample/stream volume levels
+ BASS_SetGlobalVolumes
+ BASS_GetGlobalVolumes
+* Other new function
+ BASS_SampleStop
+* New synchronizer
+ BASS_SYNC_END
+* New sample overrider
+ BASS_SAMPLE_OVER_DIST
+* LoadLibrary/GetProcAddress instructions and example
+
+0.5 - 4/7/1999
+--------------
+* Documentation!
+* File streaming (MP3 and WAV)
+ BASS_StreamCreateFile
+* Custom generated samples
+ BASS_SampleCreate
+ BASS_SampleCreateDone
+* Other new function
+ BASS_MusicSetPositionScaler
+* Renamed function
+ BASS_ChannelClearSync -> BASS_ChannelRemoveSync
+* Alterations made to
+ BASS_ChannelGetPosition
+ BASS_SampleLoad
+ BASS_StreamPlay
+
+0.4 - 30/3/1999
+---------------
+* Compressed WAV samples support (using audio CODECs)
+* Updated CD volume handling - now works with SB Live
+* More linear channel volume/pan scales (were slightly off before)
+* "No sound" device option
+* 3D sound functions
+ BASS_Set3DFactors
+ BASS_Get3DFactors
+ BASS_Set3DPosition
+ BASS_Get3DPosition
+ BASS_Apply3D
+ BASS_SamplePlay3D
+ BASS_SamplePlay3DEx
+ BASS_ChannelSet3DAttributes
+ BASS_ChannelGet3DAttributes
+ BASS_ChannelSet3DPosition
+ BASS_ChannelGet3DPosition
+* EAX functions
+ BASS_SetEAXParameters
+ BASS_GetEAXParameters
+ BASS_ChannelSetEAXMix
+ BASS_ChannelGetEAXMix
+* Other new functions
+ BASS_GetDeviceDescription
+ BASS_SetBufferLen
+ BASS_ChannelGetFlags
+ BASS_ChannelPause
+ BASS_ChannelResume
+ BASS_ChannelSetPosition
+* Replaced function
+ BASS_CDResume -> BASS_ChannelResume
+* Alterations made to
+ BASS_Init
+ BASS_CDInit
+ BASS_SampleLoad
+ BASS_StreamPlay
+ BASS_INFO structure
+ BASS_SAMPLE structure
+ BASS_DEVICE_xxx flags
+ BASS_SAMPLE_xxx flags
+
+0.3 - 8/3/1999
+--------------
+* Synchronization functions
+ BASS_ChannelSetSync
+ BASS_ChannelClearSync
+* Other new functions
+ BASS_GetVersion
+ BASS_ChannelGetPosition
+ BASS_ChannelGetLevel
+ BASS_ChannelGetAttributes
+ BASS_ChannelSetAttributes
+* Replaced functions
+ BASS_MusicStop -> BASS_ChannelStop
+ BASS_MusicSetVolume -> BASS_ChannelSetAttributes
+ BASS_CDStop -> BASS_ChannelStop
+ BASS_CDSetVolume -> BASS_ChannelSetAttributes
+ BASS_CDGetVolume -> BASS_ChannelGetAttributes
+ BASS_ChannelUpdate -> BASS_ChannelSetAttributes
+* Alterations made to
+ BASS_MusicPlayEx
+ BASS_StreamPlay
+ BASS_INFO structure
+
+0.2 - 28/2/1999
+---------------
+* First public release
+
+
+Bug reports, Suggestions, Comments, Enquiries, etc
+==================================================
+If you have any of the aforementioned please visit the BASS forum at the
+website. If you can't find an answer there, you can also email:
+
+ bass@un4seen.com
+
diff --git a/bass/bassmidi.dll b/bass/bassmidi.dll
new file mode 100644
index 0000000..6890577
Binary files /dev/null and b/bass/bassmidi.dll differ
diff --git a/bass/bassmidi.txt b/bass/bassmidi.txt
new file mode 100644
index 0000000..ae9909c
--- /dev/null
+++ b/bass/bassmidi.txt
@@ -0,0 +1,734 @@
+BASSMIDI 2.4
+Copyright (c) 2006-2024 Un4seen Developments Ltd. All rights reserved.
+
+Files that you should have found in the BASSMIDI package
+========================================================
+Win32 version
+-------------
+BASSMIDI.TXT This file
+BASSMIDI.DLL BASSMIDI module
+BASSMIDI.CHM BASSMIDI documentation
+X64\
+ BASSMIDI.DLL 64-bit BASSMIDI module
+C\ C/C++ API and examples...
+ BASSMIDI.H BASSMIDI C/C++ header file
+ BASSMIDI.LIB BASSMIDI import library
+ BASSMIDI.SLN Visual Studio solution for examples
+ MAKEFILE Makefile for examples
+ MAKEFILE.IN Makefile helper macros
+ X64\
+ BASSMIDI.LIB 64-bit BASSMIDI import library
+ MIDITEST\ MIDI playback example
+ ...
+ SF2PACK\ Soundfont packer
+ ...
+ SYNTH\ Real-time MIDI example
+ ...
+ BIN\ Precompiled examples
+ MIDITEST.EXE
+ SF2PACK.EXE
+ SYNTH.EXE
+VB\ Visual Basic API and examples...
+ BASSMIDI.BAS BASSMIDI Visual Basic module
+ MIDITEST\ MIDI playback example
+ ...
+DELPHI\ Delphi API and examples...
+ BASSMIDI.PAS BASSMIDI Delphi unit
+ MIDITEST\ MIDI playback example
+ ...
+ SYNTH\ Real-time MIDI example
+ ...
+
+NOTE: You may need to "Unblock" the BASSMIDI.CHM file in its "Properties" to
+ view it on Windows 7. The documentation can also be viewed online at
+ the BASS website.
+
+NOTE: To run the example EXEs, first you will have to copy BASSMIDI.DLL and
+ BASS.DLL into the same directory as them.
+
+NOTE: To build the examples, you will need to copy the BASS API into the same
+ directory as the BASSMIDI API.
+
+NOTE: The Delphi and VB examples may not always be up to date with the C
+ examples, so the latter should be preferred as references if possible.
+
+macOS version
+-------------
+BASSMIDI.TXT This file
+LIBBASSMIDI.DYLIB BASSMIDI module
+BASSMIDI.CHM BASSMIDI documentation
+BASSMIDI.H BASSMIDI C/C++ header file
+BASSMIDI.XCODEPROJ Xcode project for examples
+MIDITEST\ MIDI playback example
+ ...
+SF2PACK\ Soundfont packer
+ ...
+SYNTH\ Real-time MIDI example
+ ...
+
+NOTE: To build the examples, you will need to copy the BASS API into the same
+ directory as the BASSMIDI API.
+
+Linux version
+-------------
+BASSMIDI.TXT This file
+BASSMIDI.CHM BASSMIDI documentation
+BASSMIDI.H BASSMIDI C/C++ header file
+MAKEFILE Makefile for examples
+MAKEFILE.IN Makefile helper macros
+LIBS\ BASSMIDI modules
+ ...
+MIDITEST\ MIDI playback example
+ ...
+SF2PACK\ Soundfont packer
+ ...
+SYNTH\ Real-time MIDI example
+ ...
+
+NOTE: To build the examples, you will need to copy the BASS API into the same
+ directory as the BASSMIDI API.
+
+Android version
+---------------
+BASSMIDI.TXT This file
+BASSMIDI.CHM BASSMIDI documentation
+LIBS\ BASSMIDI modules
+ ...
+C\ C/C++ API...
+ BASSMIDI.H BASSMIDI C/C++ header file
+JAVA\COM\UN4SEEN\BASS\
+ BASSMIDI.JAVA BASSMIDI Java class
+EXAMPLES\ Java examples
+ BUILD.GRADLE Android Studio build script for examples
+ SETTINGS.GRADLE
+ PROGUARD-BASS.PRO
+ MIDITEST\ MIDI playback example
+ ...
+
+NOTE: To build the examples, you will need to copy the BASS API into the same
+ directory as the BASSMIDI API.
+
+iOS version
+-----------
+BASSMIDI.TXT This file
+BASSMIDI.XCFRAMEWORK BASSMIDI framework
+BASSMIDI.CHM BASSMIDI documentation
+BASSMIDI.H BASSMIDI C/C++ header file
+
+
+What's the point?
+=================
+BASSMIDI is an extension to the BASS audio library, enabling the playing of
+MIDI files and custom event sequences, using SF2 (including SF2PACK and SF3)
+and/or SFZ soundfonts to provide the sounds. MIDI input is also supported.
+
+
+Requirements
+============
+BASS 2.4 is required.
+
+
+Using BASSMIDI
+==============
+The MIDI format is used in very much the same way as any of the built-in BASS
+stream formats; simply call the MIDI stream creation function instead of the
+BASS built-in functions. The BASS plugin system (see BASS_PluginLoad) is also
+supported.
+
+SF2 and SFZ soundfonts are used to provide the sounds. There are several
+soundfonts available on the internet, including a couple on the BASS webpage.
+On Windows, the Creative 28MB (28MBGM.SF2), 8MB (CT8MGM.SF2), 4MB (CT4MGM.SF2),
+or 2MB (CT2MGM.SF2) soundfont will be used by default when present in the
+Windows system directory.
+
+The usage information in the BASS.TXT file (from the BASS package) is also
+applicable to BASSMIDI and other add-ons.
+
+TIP: The BASSMIDI.CHM file should be put in the same directory as the BASS.CHM
+ file, so that the BASSMIDI documentation can be accessed from within the
+ BASS documentation.
+
+iOS version
+-----------
+The CoreMIDI framework is required for MIDI input, so that should be added to
+the "Link Binary With Libraries" build phase in Xcode.
+
+
+Latest Version
+==============
+The latest versions of BASSMIDI & BASS can be found at the BASS website:
+
+ www.un4seen.com
+
+
+Licence
+=======
+BASSMIDI is free to use with BASS.
+
+TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, BASSMIDI IS PROVIDED
+"AS IS", WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY
+AND/OR FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS SHALL NOT BE HELD
+LIABLE FOR ANY DAMAGE THAT MAY RESULT FROM THE USE OF BASSMIDI. YOU USE
+BASSMIDI ENTIRELY AT YOUR OWN RISK.
+
+Usage of BASSMIDI indicates that you agree to the above conditions.
+
+All trademarks and other registered names contained in the BASSMIDI
+package are the property of their respective owners.
+
+
+History
+=======
+These are the major (and not so major) changes in each release, along with the
+functions/options that are introduced/affected by them. There are other little
+tweaks and fixes made along the way too.
+
+2.4.15 - 9/10/2024
+------------------
+* Support for Key On Velocity to attackModEnv/decayModEnv/releaseModEnv and
+ Key Number to startAddrsOffset SF2 modulators
+ BASS_MIDI_FontInit/User
+* Support for fileg_vel2attack/fileg_vel2decay/fileg_vel2release/pitcheg_vel2attack/
+ pitcheg_vel2decay/pitcheg_vel2release SFZ opcodes
+ BASS_MIDI_FontInit/User
+* Improved SFZ variable parsing compatibility (uses the shortest match)
+ BASS_MIDI_FontInit/User
+* Support for high-pass filter in fil_type SFZ opcode
+ BASS_MIDI_FontInit/User
+* SoundBlaster hardware limit emulation is disabled by default for modern SF2 soundfonts
+ BASS_MIDI_FONT_SBLIMITS/NOSBLIMITS (BASS_MIDI_FontInit/User flags)
+* Extended filter cutoff range when SB limits are disabled
+ BASS_MIDI_FONT_NOSBLIMITS (BASS_MIDI_FontInit/User flag)
+* Improved single note releasing when there are overlapping instances of the same note
+ BASS_MIDI_NOTEOFF1 (BASS_MIDI_StreamCreateFile/User/URL flag)
+* Ports above 7 are mapped to lower ports (modulo 8)
+ BASS_MIDI_StreamCreateFile
+* Higher ports are shifted to lower channels when lower ports are unused
+ BASS_MIDI_StreamCreateFile
+* Default per-drum USERFX levels to 127 instead of 0 in all modes
+ BASS_MIDI_NODRUMPARAMUSER (BASS_MIDI_StreamCreate/Events/File/User/URL flag)
+* Per-drum key settings may be applied to all keys at once
+ MIDI_EVENT_DRUM_xxx (BASS_MIDI_StreamEvent/s)
+* System mode/reset events are ignored from additional ports
+ BASS_MIDI_StreamCreateFile/User/URL
+ BASS_MIDI_StreamEvents
+* Sequencer specific meta-event retrieval
+ BASS_MIDI_MARK_SEQSPEC (BASS_MIDI_StreamGetMark type)
+* Queued event buffer preallocation
+ BASS_ATTRIB_MIDI_QUEUE_TICK/BYTE/ASYNC (BASS_ChannelSetAttribute options)
+* Faster SFZ info retrieval
+ BASS_MIDI_FontGetInfo
+* Support for SF2 soundfonts embedded in RMID files
+ BASS_MIDI_StreamCreateFile/User/URL
+* RIFF/RMID "INFO" tag support
+ BASS_TAG_RIFF_INFO (BASS_ChannelGetTags type)
+* MIDI filename retrieval
+ BASS_CHANNELINFO (filename member)
+* Approximate support for AWE32 filter NRPN (7f15/7f16)
+ MIDI_EVENT_CUTOFF/RESONANCE
+* Maximum voices is practically unlimited (~14 million)
+ BASS_CONFIG_MIDI_VOICES (BASS_SetConfig option)
+ BASS_ATTRIB_MIDI_VOICES (BASS_ChannelSetAttribute option)
+
+2.4.14 - 3/5/2022
+-----------------
+* Support for Key On Velocity to startAddrsOffset/modEnvToFilterFc and CC21-24 to initialFilterFc/
+ initialAttenuation/attackVolEnv/decayVolEnv/releaseVolEnv/releaseModEnv/modEnvToFilterFc SF2 modulators
+ BASS_MIDI_FontInit/User
+* Support for all Key On Velocity to initialAttenuation SF2 modulator curve types
+ BASS_MIDI_FontInit/User
+* Support for SF3 (compressed SF2) soundfonts
+ BASS_MIDI_FontInit/User
+* Soundfont flag setting/retrieval
+ BASS_MIDI_FontFlags
+* Retrieval of currently loading samples
+ BASS_CONFIG_MIDI_SAMPLELOADING (BASS_GetConfig option)
+* Channel-specific soundfont configuration
+ BASS_MIDI_FONT_EX2 (BASS_MIDI_StreamSetFonts/GetFonts flag)
+ BASS_MIDI_FONTEX2 structure
+* MIDI port meta-event support (for more than 16 channels)
+ BASS_MIDI_StreamCreateFile/User/URL
+ BASS_MIDI_StreamEvents
+ BASS_MIDI_ConvertEvents
+* Asynchronous processing of live events
+ BASS_MIDI_ASYNC (BASS_MIDI_StreamCreate/Events/File/User/URL flag)
+ BASS_MIDI_EVENTS_ASYNC (BASS_MIDI_StreamEvents flag)
+ BASS_MIDI_EVENTS_FLUSH (BASS_MIDI_StreamEvents flag)
+ SYNTH example updated
+* Filtering of live events
+ BASS_MIDI_EVENTS_FILTER (BASS_MIDI_StreamEvents flag)
+* Improved reverb effect
+* Reverb/chorus levels raised (closer to Roland/Yamaha levels)
+* Current reverb/chorus type retrieval
+ MIDI_EVENT_REVERB_MACRO (BASS_MIDI_StreamGetEvent)
+ MIDI_EVENT_CHORUS_MACRO (BASS_MIDI_StreamGetEvent)
+* Treat soundfont reverb/chorus levels as minimums
+ BASS_MIDI_FONT_MINFX (BASS_MIDI_FontInit/User/Flags flag)
+* Default per-drum reverb/chorus levels now apply in all modes and can be disabled
+ BASS_MIDI_NODRUMPARAM (BASS_MIDI_StreamCreate/Events/File/User/URL flag)
+* Default drum channel configuration
+ BASS_EVENT_DEFDRUMS (BASS_MIDI_StreamEvent/s and BASS_MIDI_StreamCreateEvents)
+* Support for master tuning
+ MIDI_EVENT_MASTER_FINETUNE/COARSETUNE (BASS_MIDI_StreamEvent/s)
+* Omni-on/off (CC124/125) are treated as all-notes-off (CC123)
+ BASS_MIDI_StreamCreateFile/User/URL
+ BASS_MIDI_StreamEvents
+ BASS_MIDI_ConvertEvents
+* 16 point sinc interpolation support on ARM platforms with NEON
+ BASS_ATTRIB_MIDI_SRC (BASS_ChannelSetAttribute option)
+* Version number retrieval
+ BASS_MIDI_GetVersion
+* BASS_CONFIG_MIDI_SFZHEAD value changed (was same as BASS_CONFIG_MIDI_SAMPLEREAD)
+ BASS_CONFIG_MIDI_SFZHEAD (BASS_SetConfigPtr option)
+* MIDI implementation chart added to documentation
+
+2.4.13 - 16/9/2020
+------------------
+* Vibrato rate/depth/delay adjustment
+ MIDI_EVENT_VIBRATO_RATE/DEPTH/DELAY (BASS_MIDI_StreamEvent/s)
+* Support for Key Number to initialAttenuation/initialFilterFc/pan and Key On Velocity
+ to decayVolEnv/releaseVolEnv SF2 modulators
+ BASS_MIDI_FontInit/User
+* Support for amp_keycenter/amp_keytrack/ampeg_vel2release/delay_beats/fil_keycenter/
+ fil_keytrack/locc67/hicc67/pan_keycenter/pan_keytrack/sw_default/sw_last/sw_lokey/
+ sw_lolast/sw_hikey/sw_hilast SFZ opcodes
+ BASS_MIDI_FontInit/User
+* Support for global and master headers and #define directive in SFZ files
+ BASS_MIDI_FontInit/User
+* SFZ files share memory for common sample files
+ BASS_MIDI_FontInit/User
+* Partial sample loading and unloading
+ BASS_MIDI_FontLoadEx
+ SYNTH example updated
+* Non-interpolated resampling option
+ BASS_ATTRIB_MIDI_SRC (BASS_ChannelSetAttribute option)
+* Tempo modification attribute
+ BASS_ATTRIB_MIDI_SPEED (BASS_ChannelSetAttribute option)
+ MIDITEST example updated
+* Mix level control
+ BASS_ATTRIB_MIDI_VOL (BASS_ChannelSetAttribute option)
+* Reverb level modification
+ BASS_ATTRIB_MIDI_REVERB (BASS_ChannelSetAttribute option)
+* Global SFZ headers
+ BASS_CONFIG_MIDI_SFZHEAD (BASS_SetConfigPtr option)
+* Linear volume envelopes option
+ BASS_MIDI_FONT_LINDECVOL (BASS_MIDI_FontInit/User flag)
+* Disabling of sample ramping-in
+ BASS_MIDI_FONT_NORAMPIN (BASS_MIDI_FontInit/User flag)
+* Disabling of Creative/SoundBlaster hardware limit emulation
+ BASS_MIDI_FONT_NOLIMITS (BASS_MIDI_FontInit flag)
+* Duplicate soundfonts will be reloaded instead of shared if modified in the meantime
+ BASS_MIDI_FontInit
+* Memory-mapped support for default soundfont option
+ BASS_CONFIG_MIDI_DEFFONT
+* Retrieval of total memory usage for sample data
+ BASS_CONFIG_MIDI_SAMPLEMEM (BASS_GetConfig option)
+* Total sample data size available for SFZ files
+ BASS_MIDI_FontGetInfo
+* Adjustable asynchronous sample loading chunks
+ BASS_CONFIG_MIDI_SAMPLEREAD (BASS_SetConfig option)
+* CPU usage limiting is enabled by default during playback
+ BASS_MIDI_StreamCreate/Events/File/User/URL
+ BASS_ATTRIB_MIDI_CPU (BASS_ChannelSetAttribute option)
+* Option to limit sample loading waiting without killing voices
+ BASS_ATTRIB_MIDI_CPU (BASS_ChannelSetAttribute option)
+* Tick-based timing for realtime event streams
+ BASS_MIDI_StreamCreate
+ BASS_MIDI_StreamEvents
+ BASS_ATTRIB_MIDI_PPQN (BASS_ChannelSetAttribute option)
+* 48000 Hz soundfont data encoding option
+ BASS_MIDI_PACK_48KHZ (BASS_MIDI_FontPack flag)
+* macOS examples rewritten in Objective-C/Cocoa
+
+2.4.12 - 9/11/2018
+------------------
+* Support for more than 16 MIDI channels in custom event sequences
+ BASS_MIDI_StreamCreateEvents
+* Absolute timing option for custom events
+ BASS_MIDI_EVENTS_ABSTIME (BASS_MIDI_StreamEvents flag)
+* Retrieval of note-on events
+ MIDI_EVENT_NOTES (BASS_MIDI_StreamGetEvents/Ex filter)
+* Soundfont config can be modified without stopping currently playing notes
+ BASS_MIDI_StreamSetFonts
+* Memory-mapped soundfonts can be preloaded/mapped
+ BASS_MIDI_FontLoad
+* Support for Key On Velocity to initialAttenuation SF2 modulators
+ BASS_MIDI_FontInit/User
+* Linear attack phase option for SF2 modulation envelopes
+ BASS_MIDI_FONT_LINATTMOD (BASS_MIDI_FontInit/User flag)
+* The attack phase of SFZ pitch/filter envelopes is now linear instead of convex
+* Support for trigger/rt_decay/delay/amplfo_fade/fillfo_fade/pitchlfo_fade/pitch_random/
+ xfin_lokey/xfin_hikey/xfout_lokey/xfout_hikey/xf_keycurve/xfin_lovel/xfin_hivel/
+ xfout_lovel/xfout_hivel/xf_velcurve SFZ opcodes
+ BASS_MIDI_FontInit/User
+* Support for separate amplifier/filter/pitch LFOs in SFZ
+ BASS_MIDI_FontInit/User
+* Support for UTF-8 sample SFZ opcodes on Windows (already on other platforms)
+ BASS_MIDI_FontInit/User
+* Support for #include directive in SFZ files
+ BASS_MIDI_FontInit
+* SFZ files are no longer kept open/locked after being loaded
+ BASS_MIDI_FontInit
+* Samples given more time to load asynchronously when CPU usage is low
+ BASS_ATTRIB_MIDI_CPU (BASS_ChannelSetAttribute option)
+* BASS_MIDI_SINCINTER flag deprecated in favour of BASS_ATTRIB_MIDI_SRC attribute
+ BASS_MIDI_StreamCreate/Events/File/User/URL
+* Smoother low-pass filter activation and deactivation
+* Fix for transpose/tune SFZ opcodes with encoded samples
+
+2.4.11 - 30/3/2017
+------------------
+* Event modification/filtering
+ BASS_MIDI_StreamSetFilter
+ MIDIFILTERPROC
+* Simpler tempo modification
+ MIDI_EVENT_SPEED (BASS_MIDI_StreamEvent)
+ MIDITEST example updated
+* Checking whether individual notes are playing
+ MIDI_EVENT_NOTE (BASS_MIDI_StreamGetEvent)
+* Retrieval of total number of notes playing in a channel
+ MIDI_EVENT_NOTES (BASS_MIDI_StreamGetEvent)
+* Retrieval of currently active voices in a channel
+ MIDI_EVENT_VOICES (BASS_MIDI_StreamGetEvent)
+* Retrieval of currently in use presets
+ BASS_MIDI_StreamGetPreset
+* SFZ filenames are used as preset names
+ BASS_MIDI_FontGetPreset
+* Support for loop info in FLAC samples used with SFZ (requires BASSFLAC 2.4.3)
+* Faster loading of very large MIDI files
+ BASS_MIDI_StreamCreateFile/User/URL
+* Faster unfiltered event counting
+ BASS_MIDI_StreamGetEvents/Ex
+ BASS_MIDI_ConvertEvents
+* 24-bit paramater passed to MIDI_EVENT_TEMPO event sync callbacks
+ BASS_SYNC_MIDI_EVENT (BASS_ChannelSetSync type)
+* When getting the number of events, only those in the specified range are counted
+ BASS_MIDI_StreamGetEventsEx
+* Invalid event types in custom sequences will give an error instead of being ignored
+ BASS_MIDI_StreamCreateEvents
+
+2.4.10 - 8/12/2016
+------------------
+* 16 point sinc interpolation option
+ BASS_ATTRIB_MIDI_SRC (BASS_ChannelSetAttribute option)
+* Support for lorand/hirand/locc1/hicc1/locc64/hicc64/off_mode/default_path SFZ opcodes
+ BASS_MIDI_FontInit/User
+* Support for Key On Velocity to initialFilterFc/attackVolEnv SF2 modulators
+ BASS_MIDI_FontInit/User
+* Conversion of raw MIDI data to BASS_MIDI_EVENT
+ BASS_MIDI_ConvertEvents
+* Modulation (CC1) destination control
+ MIDI_EVENT_MOD_VIBRATO/PITCH/FILTER/VOLUME (BASS_MIDI_StreamEvent/s)
+ MIDI_EVENT_MODRANGE superseded by MIDI_EVENT_MOD_VIBRATO
+* Sostenuto
+ MIDI_EVENT_SOSTENUTO (BASS_MIDI_StreamEvent/s)
+* Legato channel mode
+ MIDI_EVENT_MODE (BASS_MIDI_StreamEvent)
+* Partial retrieval of events
+ BASS_MIDI_StreamGetEventsEx
+* Bulk MIDI state retrieval/setting
+ BASS_ATTRIB_MIDI_STATE (BASS_ChannelGet/SetAttributeEx option)
+* Support for delaying custom events, including delta-time info in raw MIDI data
+ BASS_MIDI_EVENTS_TIME (BASS_MIDI_StreamEvents flag)
+* Cancellation of pending custom events
+ BASS_MIDI_EVENTS_CANCEL (BASS_MIDI_StreamEvents flag)
+* Marker for the start of each track in SMF2 files
+ BASS_MIDI_MARK_TRACKSTART (BASS_MIDI_StreamGetMark type)
+* Ignoring of soundfont effect levels
+ BASS_MIDI_FONT_NOFX (BASS_MIDI_FontInit/Ex flag)
+* Maximum voice limit increased to 100000
+ BASS_CONFIG_MIDI_VOICES (BASS_SetConfig option)
+ BASS_ATTRIB_MIDI_VOICES (BASS_ChannelSetAttribute option)
+* Unicode support for default soundfont option on Windows
+ BASS_CONFIG_MIDI_DEFFONT
+* BASS_CONFIG_UNICODE option support for input device names
+ BASS_MIDI_InGetDeviceInfo
+* Improved seeking with MIDI files that have events for a channel in multiple tracks
+ BASS_ChannelSetPosition
+* Fix for 2GB size limit when unpacking a soundfont on Windows
+ BASS_MIDI_FontUnpack
+
+2.4.9 - 4/12/2014
+-----------------
+* SFZ soundfont support
+ BASS_MIDI_FontInit/User
+* Support for XG drums in bank 127 of SF2 soundfonts
+ BASS_MIDI_FONT_XGDRUMS (BASS_MIDI_FontInit/Ex flag)
+* Key pressure/aftertouch support
+ MIDI_EVENT_KEYPRES (BASS_MIDI_StreamEvent/s)
+ MIDI_EVENT_KEYPRES_VIBRATO/PITCH/FILTER/VOLUME (BASS_MIDI_StreamEvent/s)
+* 3rd effect path for custom processing
+ BASS_MIDI_CHAN_USERFX (BASS_MIDI_StreamGetChannel option)
+ MIDI_EVENT_USERFX (BASS_MIDI_StreamEvent/s)
+ MIDI_EVENT_USERFX_LEVEL (BASS_MIDI_StreamEvent/s)
+ MIDI_EVENT_USERFX_REVERB (BASS_MIDI_StreamEvent/s)
+ MIDI_EVENT_USERFX_CHORUS (BASS_MIDI_StreamEvent/s)
+* Custom reverb/chorus effect processing
+ BASS_MIDI_CHAN_CHORUS/REVERB (BASS_MIDI_StreamGetChannel options)
+* Custom channel processing output routed to reverb/chorus/custom effects
+ BASS_MIDI_StreamGetChannel
+* Default drum reverb/chorus levels set to XG spec in XG mode (GS/GM modes too)
+ MIDI_EVENT_DRUM_REVERB/CHORUS (BASS_MIDI_StreamEvent/s)
+* Decay time event
+ MIDI_EVENT_DECAY (BASS_MIDI_StreamEvent/s)
+* Support for up to 65536 presets per bank
+ BASS_MIDI_StreamSetFonts
+ MIDI_EVENT_PROGRAM (BASS_MIDI_StreamEvent/s)
+* Input ports to receive MIDI data from other software on Linux
+ BASS_MIDI_InInit
+ BASS_CONFIG_MIDI_IN_PORTS (BASS_SetConfig option)
+ SYNTH example updated
+* Single note releasing when there are overlapping instances of the same note
+ BASS_MIDI_NOTEOFF1 (BASS_MIDI_StreamCreateFile/User/URL flag)
+* Ignoring of system resets with unchanged mode
+ BASS_MIDI_NOSYSRESET (BASS_MIDI_StreamCreateFile/User/URL flag)
+ MIDI_EVENT_SYSTEM (BASS_MIDI_StreamEvent/s)
+* Disabling of running status
+ BASS_MIDI_EVENTS_NORSTATUS (BASS_MIDI_StreamEvents flag)
+* Maximum voice limit increased to 1000
+ BASS_CONFIG_MIDI_VOICES (BASS_SetConfig option)
+ BASS_ATTRIB_MIDI_VOICES (BASS_ChannelSetAttribute option)
+* Reduction of 24-bit data to 16-bit when packing soundfont samples
+ BASS_MIDI_PACK_16BIT (BASS_MIDI_FontPack flag)
+* Support for remaining SF2 generators: fixed key, fixed velocity, key to vol/mod envelope hold/decay
+* Fix for multi-track custom event sequence stream creation
+ BASS_MIDI_StreamCreateEvents
+
+2.4.8 - 2/5/2013
+----------------
+* User file soundfont loading
+ BASS_MIDI_FontInitUser
+* Retrieval of all of a soundfont's preset numbers
+ BASS_MIDI_FontGetPresets
+* More flexible soundfont preset mapping
+ BASS_MIDI_FONT_EX (BASS_MIDI_StreamSetFonts/GetFonts flag)
+ BASS_MIDI_FONTEX structure
+* Bank LSB controller support
+ MIDI_EVENT_BANK_LSB (BASS_MIDI_StreamEvent/s)
+ BASS_MIDI_FONTEX structure
+* Modulation depth range control
+ MIDI_EVENT_MODRANGE (BASS_MIDI_StreamEvent/s)
+* Channel pressure destination control
+ MIDI_EVENT_CHANPRES_VIBRATO/PITCH/FILTER/VOLUME (BASS_MIDI_StreamEvent/s)
+* Unhandled controller event
+ MIDI_EVENT_CONTROL (BASS_MIDI_StreamEvent/s)
+* Reverb send level default changed to 40 (was 0)
+ MIDI_EVENT_REVERB (BASS_MIDI_StreamEvent/s)
+* Retrieval of events from all tracks at once
+ BASS_MIDI_StreamGetEvents
+* Copyright/instrument/track name markers
+ BASS_MIDI_MARK_COPY (BASS_MIDI_StreamGetMark type)
+ BASS_MIDI_MARK_INST (BASS_MIDI_StreamGetMark type)
+ BASS_MIDI_MARK_TRACK (BASS_MIDI_StreamGetMark type)
+* Retrieval of all markers at once
+ BASS_MIDI_StreamGetMarks
+* New sync type that supports all marker types
+ BASS_SYNC_MIDI_MARK (BASS_ChannelSetSync type)
+* Non-removal of empty space at the end of a MIDI file
+ BASS_MIDI_NOCROP (BASS_MIDI_StreamCreateFile/User/URL flag)
+* Omission of a WAVE header when packing soundfont samples
+ BASS_MIDI_PACK_NOHEAD (BASS_MIDI_FontPack flag)
+* Streams created via the plugin system use the output device's sample rate
+ BASS_StreamCreateFile/etc
+* Automatic BASS_UNICODE flag use in C++ and Delphi
+ BASS_MIDI_StreamCreateFile/URL
+ BASS_MIDI_FontInit/Pack/Unpack
+
+2.4.7 - 29/6/2012
+-----------------
+* Custom event sequence streams
+ BASS_MIDI_StreamCreateEvents
+* Sinc interpolated sample mixing
+ BASS_MIDI_SINCINTER (BASS_MIDI_StreamCreate/Events/File/User/URL flag)
+* Asynchronous sample loading
+ BASS_ATTRIB_MIDI_CPU (BASS_ChannelSetAttribute option)
+* Preset unloading
+ BASS_MIDI_FontUnload
+* Note stopping without sustain/decay
+ BASS_EVENT_NOTE (BASS_MIDI_StreamEvent/s)
+* Syncing on all event types
+ BASS_SYNC_MIDI_EVENT (BASS_ChannelSetSync type)
+* Marker tick position retrieval
+ BASS_MIDI_MARK_TICK (BASS_MIDI_StreamGetMark flag)
+* Maximum voice limit increased to 500
+ BASS_CONFIG_MIDI_VOICES (BASS_SetConfig option)
+ BASS_ATTRIB_MIDI_VOICES (BASS_ChannelSetAttribute option)
+* Default voice limit raised to 40 on Android/iOS
+ BASS_CONFIG_MIDI_VOICES (BASS_SetConfig option)
+* Active voice count retrieval
+ BASS_ATTRIB_MIDI_VOICES_ACTIVE (BASS_ChannelGetAttribute option)
+* Use of the device's current output rate
+ BASS_MIDI_StreamCreate/Events/File/User/URL
+* Memory-mapped soundfont loading
+ BASS_MIDI_FONT_MMAP (BASS_MIDI_FontInit flag)
+* Fix for applying multiple events in BASS_MIDI_EVENTS_STRUCT mode
+ BASS_MIDI_StreamEvents
+* Marker sync compatibility (with mixer/splitter/tempo/reverse streams) fix
+ BASS_SYNC_MIDI_MARKER/CUE/LYRIC (BASS_ChannelSetSync types)
+* MIDI sysex input compatibility fix for some drivers on Windows
+ MIDIINPROC
+
+2.4.6 - 30/3/2011
+-----------------
+* MIDI input device support
+ BASS_MIDI_InGetDeviceInfo
+ BASS_MIDI_InInit
+ BASS_MIDI_InFree
+ BASS_MIDI_InStart
+ BASS_MIDI_InStop
+ MIDIINPROC
+ SYNTH example updated
+* Multiple event processing including support for raw MIDI data
+ BASS_MIDI_StreamEvents
+* CPU usage limiting
+ BASS_ATTRIB_MIDI_CPU (BASS_ChannelSetAttribute option)
+* Scale/octave tuning
+ MIDI_EVENT_SCALETUNING (BASS_MIDI_StreamEvent/s)
+* Soft pedal event
+ MIDI_EVENT_SOFT (BASS_MIDI_StreamEvent/s)
+* Random panning
+ MIDI_EVENT_PAN (BASS_MIDI_StreamEvent/s)
+* System reset event
+ MIDI_EVENT_SYSTEM/EX (BASS_MIDI_StreamEvent/s)
+* Resetting of overridden drum key pan/reverb/chorus back to normal
+ MIDI_EVENT_DRUM_PAN/REVERB/CHORUS (BASS_MIDI_StreamEvent)
+* Retrieval of drum key event values
+ BASS_MIDI_StreamGetEvent
+* All events initialized to a MIDI file's 1st tick values
+ BASS_MIDI_StreamGetEvent
+* Adjustable MIDI channel count
+ BASS_ATTRIB_MIDI_CHANS (BASS_ChannelSetAttribute option)
+* Adjustable voice limit
+ BASS_ATTRIB_MIDI_VOICES (BASS_ChannelSetAttribute option)
+* Preloaded presets are not automatically compacted
+ BASS_MIDI_FontLoad
+ BASS_CONFIG_MIDI_COMPACT (BASS_SetConfig option)
+* Multiple instances of a soundfont
+ BASS_MIDI_FontInit
+* Xcode examples project added for OSX
+
+2.4.5 - 8/2/2010
+----------------
+* Key signature retrieval
+ BASS_MIDI_MARK_KEYSIG (BASS_MIDI_StreamGetMark type)
+ BASS_SYNC_MIDI_KEYSIG (BASS_ChannelSetSync type)
+* Tempo event initialized to MIDI file's 1st tick value
+ MIDI_EVENT_TEMPO (BASS_MIDI_StreamGetEvent)
+* UTF-16 support on OSX
+ BASS_UNICODE (BASS_MIDI_StreamCreateFile/BASS_MIDI_FontInit/Pack/Unpack flag)
+
+2.4.4 - 24/8/2009
+-----------------
+* Attack & release time events
+ MIDI_EVENT_ATTACK/RELEASE (BASS_MIDI_StreamEvent)
+* Drum key level NRPN event
+ MIDI_EVENT_DRUM_LEVEL (BASS_MIDI_StreamEvent)
+* MIDI file event retrieval
+ BASS_MIDI_StreamGetEvents
+* Time signature retrieval
+ BASS_MIDI_MARK_TIMESIG (BASS_MIDI_StreamGetMark type)
+ BASS_SYNC_MIDI_TIMESIG (BASS_ChannelSetSync type)
+* Default soundfont configuration
+ BASS_CONFIG_MIDI_DEFFONT (BASS_SetConfig option)
+
+2.4.3 - 19/3/2009
+-----------------
+* Possibility of applying DSP/FX to individual MIDI channels
+ BASS_MIDI_StreamGetChannel
+* Per-track volume control
+ BASS_ATTRIB_MIDI_TRACK_VOL (BASS_ChannelSetAttribute option)
+* Support for all tracks in format 2 MIDI files
+ BASS_MIDI_StreamCreateFile/User/URL
+
+2.4.2 - 28/10/2008
+------------------
+* Decaying of old sound when seeking
+ BASS_MIDI_DECAYSEEK (BASS_MIDI_StreamCreateFile/User/URL flag)
+ MIDITEST example updated (C version)
+* End decaying now also applies when looping
+ BASS_MIDI_DECAYEND (BASS_MIDI_StreamCreateFile/User/URL flag)
+* Support for 28MBGM.SF2 and CT8MGM.SF2 as default soundfonts
+
+2.4.1 - 9/7/2008
+----------------
+* Ticks-per-beat retrieval
+ BASS_ATTRIB_MIDI_PPQN (BASS_ChannelGetAttribute option)
+
+2.4 - 2/4/2008
+--------------
+* Tick-based positioning
+ BASS_POS_MIDI_TICK (BASS_ChannelGetLength/GetPosition/SetPosition mode)
+ BASS_SYNC_MIDI_TICK (BASS_ChannelSetSync type)
+* Preset name retrieval
+ BASS_MIDI_FontGetPreset
+* Text markers
+ BASS_MIDI_MARK_TEXT (BASS_MIDI_StreamGetMark type)
+ BASS_SYNC_MIDI_TEXT (BASS_ChannelSetSync type)
+* Individual marker retrieval
+ BASS_MIDI_StreamGetMark
+ BASS_MIDI_StreamGetMarks *removed*
+* Marker index passed to marker sync callbacks
+ BASS_SYNC_MIDI_MARKER/CUE/LYRIC
+* Use of BASS_Init sample rate
+ BASS_MIDI_StreamCreate/File/User/URL
+* Support for updated user file stream system
+ BASS_MIDI_StreamCreateFileUser
+* 64-bit file positioning
+ BASS_MIDI_StreamCreateFile
+* Callback "user" parameters changed to pointers
+ BASS_MIDI_StreamCreateURL
+ BASS_MIDI_StreamCreateFileUser
+
+2.3.0.3 - 10/7/2007
+-------------------
+* Syncing on events
+ BASS_SYNC_MIDI_EVENT (BASS_ChannelSetSync type)
+
+2.3.0.2 - 26/2/2007
+-------------------
+* Reverb and chorus
+ MIDI_EVENT_REVERB/CHORUS (BASS_MIDI_StreamEvent)
+ MIDI_EVENT_REVERB_TIME/DELAY/LOCUTOFF/HICUTOFF/LEVEL (BASS_MIDI_StreamEvent)
+ MIDI_EVENT_CHORUS_DELAY/DEPTH/RATE/FEEDBACK/LEVEL/REVERB (BASS_MIDI_StreamEvent)
+ BASS_MIDI_NOFX (BASS_MIDI_StreamCreate/File/User/URL flag)
+* Resonant low-pass filters
+ MIDI_EVENT_CUTOFF/RESONANCE (BASS_MIDI_StreamEvent)
+* Portamento
+ MIDI_EVENT_PORTAMENTO/TIME/NOTE (BASS_MIDI_StreamEvent)
+* Fine-tuning
+ MIDI_EVENT_FINETUNE/COARSETUNE (BASS_MIDI_StreamEvent)
+* Drum key specific parameters
+ MIDI_EVENT_DRUM_FINETUNE/COARSETUNE/PAN/REVERB/CHORUS/CUTOFF/RESONANCE (BASS_MIDI_StreamEvent)
+* Support for mono channel mode
+ MIDI_EVENT_MODE (BASS_MIDI_StreamEvent)
+* Support for master volume
+ MIDI_EVENT_MASTERVOL (BASS_MIDI_StreamEvent)
+* Channel level control
+ MIDI_EVENT_MIXLEVEL (BASS_MIDI_StreamEvent)
+* Channel transposing
+ MIDI_EVENT_TRANSPOSE (BASS_MIDI_StreamEvent)
+* Retrieval of current event values
+ BASS_MIDI_StreamGetEvent
+* Soundfont volume control
+ BASS_MIDI_FontSetVolume/GetVolume
+* Track number added to markers and syncs
+ BASS_MIDI_MARK (track member)
+ BASS_SYNC_MIDI_MARKER/CUE/LYRIC
+
+2.3.0.1 - 1/12/2006
+-------------------
+* Optionally apply matching soundfonts to all banks
+ BASS_CONFIG_MIDI_AUTOFONT (BASS_SetConfig option)
+* Support for 0 length notes
+
+2.3 - 14/11/2006
+----------------
+* First release
+
+
+Bug reports, Suggestions, Comments, Enquiries, etc
+==================================================
+If you have any of the aforementioned please visit the BASS forum at the
+website.
+
diff --git a/bass/inc/bass.h b/bass/inc/bass.h
new file mode 100644
index 0000000..1e3a86f
--- /dev/null
+++ b/bass/inc/bass.h
@@ -0,0 +1,1149 @@
+/*
+ BASS 2.4 C/C++ header file
+ Copyright (c) 1999-2022 Un4seen Developments Ltd.
+
+ See the BASS.CHM file for more detailed documentation
+*/
+
+#ifndef BASS_H
+#define BASS_H
+
+#ifdef _WIN32
+#ifdef WINAPI_FAMILY
+#include
+#endif
+#include
+typedef unsigned __int64 QWORD;
+#else
+#include
+#define WINAPI
+#define CALLBACK
+typedef uint8_t BYTE;
+typedef uint16_t WORD;
+typedef uint32_t DWORD;
+typedef uint64_t QWORD;
+#ifdef __OBJC__
+typedef int BOOL32;
+#define BOOL BOOL32 // override objc's BOOL
+#else
+typedef int BOOL;
+#endif
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+#define LOBYTE(a) (BYTE)(a)
+#define HIBYTE(a) (BYTE)((a)>>8)
+#define LOWORD(a) (WORD)(a)
+#define HIWORD(a) (WORD)((a)>>16)
+#define MAKEWORD(a,b) (WORD)(((a)&0xff)|((b)<<8))
+#define MAKELONG(a,b) (DWORD)(((a)&0xffff)|((b)<<16))
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define BASSVERSION 0x204 // API version
+#define BASSVERSIONTEXT "2.4"
+
+#ifndef BASSDEF
+#define BASSDEF(f) WINAPI f
+#else
+#define NOBASSOVERLOADS
+#endif
+
+typedef DWORD HMUSIC; // MOD music handle
+typedef DWORD HSAMPLE; // sample handle
+typedef DWORD HCHANNEL; // sample playback handle
+typedef DWORD HSTREAM; // sample stream handle
+typedef DWORD HRECORD; // recording handle
+typedef DWORD HSYNC; // synchronizer handle
+typedef DWORD HDSP; // DSP handle
+typedef DWORD HFX; // effect handle
+typedef DWORD HPLUGIN; // plugin handle
+
+// Error codes returned by BASS_ErrorGetCode
+#define BASS_OK 0 // all is OK
+#define BASS_ERROR_MEM 1 // memory error
+#define BASS_ERROR_FILEOPEN 2 // can't open the file
+#define BASS_ERROR_DRIVER 3 // can't find a free/valid driver
+#define BASS_ERROR_BUFLOST 4 // the sample buffer was lost
+#define BASS_ERROR_HANDLE 5 // invalid handle
+#define BASS_ERROR_FORMAT 6 // unsupported sample format
+#define BASS_ERROR_POSITION 7 // invalid position
+#define BASS_ERROR_INIT 8 // BASS_Init has not been successfully called
+#define BASS_ERROR_START 9 // BASS_Start has not been successfully called
+#define BASS_ERROR_SSL 10 // SSL/HTTPS support isn't available
+#define BASS_ERROR_REINIT 11 // device needs to be reinitialized
+#define BASS_ERROR_ALREADY 14 // already initialized/paused/whatever
+#define BASS_ERROR_NOTAUDIO 17 // file does not contain audio
+#define BASS_ERROR_NOCHAN 18 // can't get a free channel
+#define BASS_ERROR_ILLTYPE 19 // an illegal type was specified
+#define BASS_ERROR_ILLPARAM 20 // an illegal parameter was specified
+#define BASS_ERROR_NO3D 21 // no 3D support
+#define BASS_ERROR_NOEAX 22 // no EAX support
+#define BASS_ERROR_DEVICE 23 // illegal device number
+#define BASS_ERROR_NOPLAY 24 // not playing
+#define BASS_ERROR_FREQ 25 // illegal sample rate
+#define BASS_ERROR_NOTFILE 27 // the stream is not a file stream
+#define BASS_ERROR_NOHW 29 // no hardware voices available
+#define BASS_ERROR_EMPTY 31 // the file has no sample data
+#define BASS_ERROR_NONET 32 // no internet connection could be opened
+#define BASS_ERROR_CREATE 33 // couldn't create the file
+#define BASS_ERROR_NOFX 34 // effects are not available
+#define BASS_ERROR_NOTAVAIL 37 // requested data/action is not available
+#define BASS_ERROR_DECODE 38 // the channel is/isn't a "decoding channel"
+#define BASS_ERROR_DX 39 // a sufficient DirectX version is not installed
+#define BASS_ERROR_TIMEOUT 40 // connection timedout
+#define BASS_ERROR_FILEFORM 41 // unsupported file format
+#define BASS_ERROR_SPEAKER 42 // unavailable speaker
+#define BASS_ERROR_VERSION 43 // invalid BASS version (used by add-ons)
+#define BASS_ERROR_CODEC 44 // codec is not available/supported
+#define BASS_ERROR_ENDED 45 // the channel/file has ended
+#define BASS_ERROR_BUSY 46 // the device is busy
+#define BASS_ERROR_UNSTREAMABLE 47 // unstreamable file
+#define BASS_ERROR_PROTOCOL 48 // unsupported protocol
+#define BASS_ERROR_DENIED 49 // access denied
+#define BASS_ERROR_UNKNOWN -1 // some other mystery problem
+
+// BASS_SetConfig options
+#define BASS_CONFIG_BUFFER 0
+#define BASS_CONFIG_UPDATEPERIOD 1
+#define BASS_CONFIG_GVOL_SAMPLE 4
+#define BASS_CONFIG_GVOL_STREAM 5
+#define BASS_CONFIG_GVOL_MUSIC 6
+#define BASS_CONFIG_CURVE_VOL 7
+#define BASS_CONFIG_CURVE_PAN 8
+#define BASS_CONFIG_FLOATDSP 9
+#define BASS_CONFIG_3DALGORITHM 10
+#define BASS_CONFIG_NET_TIMEOUT 11
+#define BASS_CONFIG_NET_BUFFER 12
+#define BASS_CONFIG_PAUSE_NOPLAY 13
+#define BASS_CONFIG_NET_PREBUF 15
+#define BASS_CONFIG_NET_PASSIVE 18
+#define BASS_CONFIG_REC_BUFFER 19
+#define BASS_CONFIG_NET_PLAYLIST 21
+#define BASS_CONFIG_MUSIC_VIRTUAL 22
+#define BASS_CONFIG_VERIFY 23
+#define BASS_CONFIG_UPDATETHREADS 24
+#define BASS_CONFIG_DEV_BUFFER 27
+#define BASS_CONFIG_REC_LOOPBACK 28
+#define BASS_CONFIG_VISTA_TRUEPOS 30
+#define BASS_CONFIG_IOS_SESSION 34
+#define BASS_CONFIG_IOS_MIXAUDIO 34
+#define BASS_CONFIG_DEV_DEFAULT 36
+#define BASS_CONFIG_NET_READTIMEOUT 37
+#define BASS_CONFIG_VISTA_SPEAKERS 38
+#define BASS_CONFIG_IOS_SPEAKER 39
+#define BASS_CONFIG_MF_DISABLE 40
+#define BASS_CONFIG_HANDLES 41
+#define BASS_CONFIG_UNICODE 42
+#define BASS_CONFIG_SRC 43
+#define BASS_CONFIG_SRC_SAMPLE 44
+#define BASS_CONFIG_ASYNCFILE_BUFFER 45
+#define BASS_CONFIG_OGG_PRESCAN 47
+#define BASS_CONFIG_MF_VIDEO 48
+#define BASS_CONFIG_AIRPLAY 49
+#define BASS_CONFIG_DEV_NONSTOP 50
+#define BASS_CONFIG_IOS_NOCATEGORY 51
+#define BASS_CONFIG_VERIFY_NET 52
+#define BASS_CONFIG_DEV_PERIOD 53
+#define BASS_CONFIG_FLOAT 54
+#define BASS_CONFIG_NET_SEEK 56
+#define BASS_CONFIG_AM_DISABLE 58
+#define BASS_CONFIG_NET_PLAYLIST_DEPTH 59
+#define BASS_CONFIG_NET_PREBUF_WAIT 60
+#define BASS_CONFIG_ANDROID_SESSIONID 62
+#define BASS_CONFIG_WASAPI_PERSIST 65
+#define BASS_CONFIG_REC_WASAPI 66
+#define BASS_CONFIG_ANDROID_AAUDIO 67
+#define BASS_CONFIG_SAMPLE_ONEHANDLE 69
+#define BASS_CONFIG_NET_META 71
+#define BASS_CONFIG_NET_RESTRATE 72
+#define BASS_CONFIG_REC_DEFAULT 73
+#define BASS_CONFIG_NORAMP 74
+
+// BASS_SetConfigPtr options
+#define BASS_CONFIG_NET_AGENT 16
+#define BASS_CONFIG_NET_PROXY 17
+#define BASS_CONFIG_IOS_NOTIFY 46
+#define BASS_CONFIG_ANDROID_JAVAVM 63
+#define BASS_CONFIG_LIBSSL 64
+#define BASS_CONFIG_FILENAME 75
+
+#define BASS_CONFIG_THREAD 0x40000000 // flag: thread-specific setting
+
+// BASS_CONFIG_IOS_SESSION flags
+#define BASS_IOS_SESSION_MIX 1
+#define BASS_IOS_SESSION_DUCK 2
+#define BASS_IOS_SESSION_AMBIENT 4
+#define BASS_IOS_SESSION_SPEAKER 8
+#define BASS_IOS_SESSION_DISABLE 16
+#define BASS_IOS_SESSION_DEACTIVATE 32
+#define BASS_IOS_SESSION_AIRPLAY 64
+#define BASS_IOS_SESSION_BTHFP 128
+#define BASS_IOS_SESSION_BTA2DP 0x100
+
+// BASS_Init flags
+#define BASS_DEVICE_8BITS 1 // unused
+#define BASS_DEVICE_MONO 2 // mono
+#define BASS_DEVICE_3D 4 // unused
+#define BASS_DEVICE_16BITS 8 // limit output to 16-bit
+#define BASS_DEVICE_REINIT 128 // reinitialize
+#define BASS_DEVICE_LATENCY 0x100 // unused
+#define BASS_DEVICE_CPSPEAKERS 0x400 // unused
+#define BASS_DEVICE_SPEAKERS 0x800 // force enabling of speaker assignment
+#define BASS_DEVICE_NOSPEAKER 0x1000 // ignore speaker arrangement
+#define BASS_DEVICE_DMIX 0x2000 // use ALSA "dmix" plugin
+#define BASS_DEVICE_FREQ 0x4000 // set device sample rate
+#define BASS_DEVICE_STEREO 0x8000 // limit output to stereo
+#define BASS_DEVICE_HOG 0x10000 // hog/exclusive mode
+#define BASS_DEVICE_AUDIOTRACK 0x20000 // use AudioTrack output
+#define BASS_DEVICE_DSOUND 0x40000 // use DirectSound output
+#define BASS_DEVICE_SOFTWARE 0x80000 // disable hardware/fastpath output
+
+// DirectSound interfaces (for use with BASS_GetDSoundObject)
+#define BASS_OBJECT_DS 1 // IDirectSound
+#define BASS_OBJECT_DS3DL 2 // IDirectSound3DListener
+
+// Device info structure
+typedef struct {
+#if defined(_WIN32_WCE) || (defined(WINAPI_FAMILY) && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
+ const wchar_t *name; // description
+ const wchar_t *driver; // driver
+#else
+ const char *name; // description
+ const char *driver; // driver
+#endif
+ DWORD flags;
+} BASS_DEVICEINFO;
+
+// BASS_DEVICEINFO flags
+#define BASS_DEVICE_ENABLED 1
+#define BASS_DEVICE_DEFAULT 2
+#define BASS_DEVICE_INIT 4
+#define BASS_DEVICE_LOOPBACK 8
+#define BASS_DEVICE_DEFAULTCOM 128
+
+#define BASS_DEVICE_TYPE_MASK 0xff000000
+#define BASS_DEVICE_TYPE_NETWORK 0x01000000
+#define BASS_DEVICE_TYPE_SPEAKERS 0x02000000
+#define BASS_DEVICE_TYPE_LINE 0x03000000
+#define BASS_DEVICE_TYPE_HEADPHONES 0x04000000
+#define BASS_DEVICE_TYPE_MICROPHONE 0x05000000
+#define BASS_DEVICE_TYPE_HEADSET 0x06000000
+#define BASS_DEVICE_TYPE_HANDSET 0x07000000
+#define BASS_DEVICE_TYPE_DIGITAL 0x08000000
+#define BASS_DEVICE_TYPE_SPDIF 0x09000000
+#define BASS_DEVICE_TYPE_HDMI 0x0a000000
+#define BASS_DEVICE_TYPE_DISPLAYPORT 0x40000000
+
+// BASS_GetDeviceInfo flags
+#define BASS_DEVICES_AIRPLAY 0x1000000
+
+typedef struct {
+ DWORD flags; // device capabilities (DSCAPS_xxx flags)
+ DWORD hwsize; // unused
+ DWORD hwfree; // unused
+ DWORD freesam; // unused
+ DWORD free3d; // unused
+ DWORD minrate; // unused
+ DWORD maxrate; // unused
+ BOOL eax; // unused
+ DWORD minbuf; // recommended minimum buffer length in ms
+ DWORD dsver; // DirectSound version
+ DWORD latency; // average delay (in ms) before start of playback
+ DWORD initflags; // BASS_Init "flags" parameter
+ DWORD speakers; // number of speakers available
+ DWORD freq; // current output rate
+} BASS_INFO;
+
+// BASS_INFO flags (from DSOUND.H)
+#define DSCAPS_EMULDRIVER 0x00000020 // device does not have hardware DirectSound support
+#define DSCAPS_CERTIFIED 0x00000040 // device driver has been certified by Microsoft
+
+#define DSCAPS_HARDWARE 0x80000000 // hardware mixed
+
+// Recording device info structure
+typedef struct {
+ DWORD flags; // device capabilities (DSCCAPS_xxx flags)
+ DWORD formats; // supported standard formats (WAVE_FORMAT_xxx flags)
+ DWORD inputs; // number of inputs
+ BOOL singlein; // TRUE = only 1 input can be set at a time
+ DWORD freq; // current input rate
+} BASS_RECORDINFO;
+
+// BASS_RECORDINFO flags (from DSOUND.H)
+#define DSCCAPS_EMULDRIVER DSCAPS_EMULDRIVER // device does not have hardware DirectSound recording support
+#define DSCCAPS_CERTIFIED DSCAPS_CERTIFIED // device driver has been certified by Microsoft
+
+// defines for formats field of BASS_RECORDINFO (from MMSYSTEM.H)
+#ifndef WAVE_FORMAT_1M08
+#define WAVE_FORMAT_1M08 0x00000001 /* 11.025 kHz, Mono, 8-bit */
+#define WAVE_FORMAT_1S08 0x00000002 /* 11.025 kHz, Stereo, 8-bit */
+#define WAVE_FORMAT_1M16 0x00000004 /* 11.025 kHz, Mono, 16-bit */
+#define WAVE_FORMAT_1S16 0x00000008 /* 11.025 kHz, Stereo, 16-bit */
+#define WAVE_FORMAT_2M08 0x00000010 /* 22.05 kHz, Mono, 8-bit */
+#define WAVE_FORMAT_2S08 0x00000020 /* 22.05 kHz, Stereo, 8-bit */
+#define WAVE_FORMAT_2M16 0x00000040 /* 22.05 kHz, Mono, 16-bit */
+#define WAVE_FORMAT_2S16 0x00000080 /* 22.05 kHz, Stereo, 16-bit */
+#define WAVE_FORMAT_4M08 0x00000100 /* 44.1 kHz, Mono, 8-bit */
+#define WAVE_FORMAT_4S08 0x00000200 /* 44.1 kHz, Stereo, 8-bit */
+#define WAVE_FORMAT_4M16 0x00000400 /* 44.1 kHz, Mono, 16-bit */
+#define WAVE_FORMAT_4S16 0x00000800 /* 44.1 kHz, Stereo, 16-bit */
+#endif
+
+// Sample info structure
+typedef struct {
+ DWORD freq; // default playback rate
+ float volume; // default volume (0-1)
+ float pan; // default pan (-1=left, 0=middle, 1=right)
+ DWORD flags; // BASS_SAMPLE_xxx flags
+ DWORD length; // length (in bytes)
+ DWORD max; // maximum simultaneous playbacks
+ DWORD origres; // original resolution
+ DWORD chans; // number of channels
+ DWORD mingap; // minimum gap (ms) between creating channels
+ DWORD mode3d; // BASS_3DMODE_xxx mode
+ float mindist; // minimum distance
+ float maxdist; // maximum distance
+ DWORD iangle; // angle of inside projection cone
+ DWORD oangle; // angle of outside projection cone
+ float outvol; // delta-volume outside the projection cone
+ DWORD vam; // unused
+ DWORD priority; // unused
+} BASS_SAMPLE;
+
+#define BASS_SAMPLE_8BITS 1 // 8 bit
+#define BASS_SAMPLE_FLOAT 256 // 32 bit floating-point
+#define BASS_SAMPLE_MONO 2 // mono
+#define BASS_SAMPLE_LOOP 4 // looped
+#define BASS_SAMPLE_3D 8 // 3D functionality
+#define BASS_SAMPLE_SOFTWARE 16 // unused
+#define BASS_SAMPLE_MUTEMAX 32 // mute at max distance (3D only)
+#define BASS_SAMPLE_VAM 64 // unused
+#define BASS_SAMPLE_FX 128 // unused
+#define BASS_SAMPLE_OVER_VOL 0x10000 // override lowest volume
+#define BASS_SAMPLE_OVER_POS 0x20000 // override longest playing
+#define BASS_SAMPLE_OVER_DIST 0x30000 // override furthest from listener (3D only)
+
+#define BASS_STREAM_PRESCAN 0x20000 // scan file for accurate seeking and length
+#define BASS_STREAM_AUTOFREE 0x40000 // automatically free the stream when it stops/ends
+#define BASS_STREAM_RESTRATE 0x80000 // restrict the download rate of internet file stream
+#define BASS_STREAM_BLOCK 0x100000 // download internet file stream in small blocks
+#define BASS_STREAM_DECODE 0x200000 // don't play the stream, only decode
+#define BASS_STREAM_STATUS 0x800000 // give server status info (HTTP/ICY tags) in DOWNLOADPROC
+
+#define BASS_MP3_IGNOREDELAY 0x200 // ignore LAME/Xing/VBRI/iTunes delay & padding info
+#define BASS_MP3_SETPOS BASS_STREAM_PRESCAN
+
+#define BASS_MUSIC_FLOAT BASS_SAMPLE_FLOAT
+#define BASS_MUSIC_MONO BASS_SAMPLE_MONO
+#define BASS_MUSIC_LOOP BASS_SAMPLE_LOOP
+#define BASS_MUSIC_3D BASS_SAMPLE_3D
+#define BASS_MUSIC_FX BASS_SAMPLE_FX
+#define BASS_MUSIC_AUTOFREE BASS_STREAM_AUTOFREE
+#define BASS_MUSIC_DECODE BASS_STREAM_DECODE
+#define BASS_MUSIC_PRESCAN BASS_STREAM_PRESCAN // calculate playback length
+#define BASS_MUSIC_CALCLEN BASS_MUSIC_PRESCAN
+#define BASS_MUSIC_RAMP 0x200 // normal ramping
+#define BASS_MUSIC_RAMPS 0x400 // sensitive ramping
+#define BASS_MUSIC_SURROUND 0x800 // surround sound
+#define BASS_MUSIC_SURROUND2 0x1000 // surround sound (mode 2)
+#define BASS_MUSIC_FT2PAN 0x2000 // apply FastTracker 2 panning to XM files
+#define BASS_MUSIC_FT2MOD 0x2000 // play .MOD as FastTracker 2 does
+#define BASS_MUSIC_PT1MOD 0x4000 // play .MOD as ProTracker 1 does
+#define BASS_MUSIC_NONINTER 0x10000 // non-interpolated sample mixing
+#define BASS_MUSIC_SINCINTER 0x800000 // sinc interpolated sample mixing
+#define BASS_MUSIC_POSRESET 0x8000 // stop all notes when moving position
+#define BASS_MUSIC_POSRESETEX 0x400000 // stop all notes and reset bmp/etc when moving position
+#define BASS_MUSIC_STOPBACK 0x80000 // stop the music on a backwards jump effect
+#define BASS_MUSIC_NOSAMPLE 0x100000 // don't load the samples
+
+// Speaker assignment flags
+#define BASS_SPEAKER_FRONT 0x1000000 // front speakers
+#define BASS_SPEAKER_REAR 0x2000000 // rear speakers
+#define BASS_SPEAKER_CENLFE 0x3000000 // center & LFE speakers (5.1)
+#define BASS_SPEAKER_SIDE 0x4000000 // side speakers (7.1)
+#define BASS_SPEAKER_N(n) ((n)<<24) // n'th pair of speakers (max 15)
+#define BASS_SPEAKER_LEFT 0x10000000 // modifier: left
+#define BASS_SPEAKER_RIGHT 0x20000000 // modifier: right
+#define BASS_SPEAKER_FRONTLEFT BASS_SPEAKER_FRONT | BASS_SPEAKER_LEFT
+#define BASS_SPEAKER_FRONTRIGHT BASS_SPEAKER_FRONT | BASS_SPEAKER_RIGHT
+#define BASS_SPEAKER_REARLEFT BASS_SPEAKER_REAR | BASS_SPEAKER_LEFT
+#define BASS_SPEAKER_REARRIGHT BASS_SPEAKER_REAR | BASS_SPEAKER_RIGHT
+#define BASS_SPEAKER_CENTER BASS_SPEAKER_CENLFE | BASS_SPEAKER_LEFT
+#define BASS_SPEAKER_LFE BASS_SPEAKER_CENLFE | BASS_SPEAKER_RIGHT
+#define BASS_SPEAKER_SIDELEFT BASS_SPEAKER_SIDE | BASS_SPEAKER_LEFT
+#define BASS_SPEAKER_SIDERIGHT BASS_SPEAKER_SIDE | BASS_SPEAKER_RIGHT
+#define BASS_SPEAKER_REAR2 BASS_SPEAKER_SIDE
+#define BASS_SPEAKER_REAR2LEFT BASS_SPEAKER_SIDELEFT
+#define BASS_SPEAKER_REAR2RIGHT BASS_SPEAKER_SIDERIGHT
+
+#define BASS_ASYNCFILE 0x40000000 // read file asynchronously
+#define BASS_UNICODE 0x80000000 // UTF-16
+
+#define BASS_RECORD_ECHOCANCEL 0x2000
+#define BASS_RECORD_AGC 0x4000
+#define BASS_RECORD_PAUSE 0x8000 // start recording paused
+
+// DX7 voice allocation & management flags
+#define BASS_VAM_HARDWARE 1
+#define BASS_VAM_SOFTWARE 2
+#define BASS_VAM_TERM_TIME 4
+#define BASS_VAM_TERM_DIST 8
+#define BASS_VAM_TERM_PRIO 16
+
+// Channel info structure
+typedef struct {
+ DWORD freq; // default playback rate
+ DWORD chans; // channels
+ DWORD flags;
+ DWORD ctype; // type of channel
+ DWORD origres; // original resolution
+ HPLUGIN plugin;
+ HSAMPLE sample;
+ const char *filename;
+} BASS_CHANNELINFO;
+
+#define BASS_ORIGRES_FLOAT 0x10000
+
+// BASS_CHANNELINFO types
+#define BASS_CTYPE_SAMPLE 1
+#define BASS_CTYPE_RECORD 2
+#define BASS_CTYPE_STREAM 0x10000
+#define BASS_CTYPE_STREAM_VORBIS 0x10002
+#define BASS_CTYPE_STREAM_OGG 0x10002
+#define BASS_CTYPE_STREAM_MP1 0x10003
+#define BASS_CTYPE_STREAM_MP2 0x10004
+#define BASS_CTYPE_STREAM_MP3 0x10005
+#define BASS_CTYPE_STREAM_AIFF 0x10006
+#define BASS_CTYPE_STREAM_CA 0x10007
+#define BASS_CTYPE_STREAM_MF 0x10008
+#define BASS_CTYPE_STREAM_AM 0x10009
+#define BASS_CTYPE_STREAM_SAMPLE 0x1000a
+#define BASS_CTYPE_STREAM_DUMMY 0x18000
+#define BASS_CTYPE_STREAM_DEVICE 0x18001
+#define BASS_CTYPE_STREAM_WAV 0x40000 // WAVE flag (LOWORD=codec)
+#define BASS_CTYPE_STREAM_WAV_PCM 0x50001
+#define BASS_CTYPE_STREAM_WAV_FLOAT 0x50003
+#define BASS_CTYPE_MUSIC_MOD 0x20000
+#define BASS_CTYPE_MUSIC_MTM 0x20001
+#define BASS_CTYPE_MUSIC_S3M 0x20002
+#define BASS_CTYPE_MUSIC_XM 0x20003
+#define BASS_CTYPE_MUSIC_IT 0x20004
+#define BASS_CTYPE_MUSIC_MO3 0x00100 // MO3 flag
+
+// BASS_PluginLoad flags
+#define BASS_PLUGIN_PROC 1
+
+typedef struct {
+ DWORD ctype; // channel type
+#if defined(_WIN32_WCE) || (defined(WINAPI_FAMILY) && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
+ const wchar_t *name; // format description
+ const wchar_t *exts; // file extension filter (*.ext1;*.ext2;etc...)
+#else
+ const char *name; // format description
+ const char *exts; // file extension filter (*.ext1;*.ext2;etc...)
+#endif
+} BASS_PLUGINFORM;
+
+typedef struct {
+ DWORD version; // version (same form as BASS_GetVersion)
+ DWORD formatc; // number of formats
+ const BASS_PLUGINFORM *formats; // the array of formats
+} BASS_PLUGININFO;
+
+// 3D vector (for 3D positions/velocities/orientations)
+typedef struct BASS_3DVECTOR {
+#ifdef __cplusplus
+ BASS_3DVECTOR() {}
+ BASS_3DVECTOR(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
+#endif
+ float x; // +=right, -=left
+ float y; // +=up, -=down
+ float z; // +=front, -=behind
+} BASS_3DVECTOR;
+
+// 3D channel modes
+#define BASS_3DMODE_NORMAL 0 // normal 3D processing
+#define BASS_3DMODE_RELATIVE 1 // position is relative to the listener
+#define BASS_3DMODE_OFF 2 // no 3D processing
+
+// software 3D mixing algorithms (used with BASS_CONFIG_3DALGORITHM)
+#define BASS_3DALG_DEFAULT 0
+#define BASS_3DALG_OFF 1
+#define BASS_3DALG_FULL 2
+#define BASS_3DALG_LIGHT 3
+
+// BASS_SampleGetChannel flags
+#define BASS_SAMCHAN_NEW 1 // get a new playback channel
+#define BASS_SAMCHAN_STREAM 2 // create a stream
+
+typedef DWORD (CALLBACK STREAMPROC)(HSTREAM handle, void *buffer, DWORD length, void *user);
+/* User stream callback function.
+handle : The stream that needs writing
+buffer : Buffer to write the samples in
+length : Number of bytes to write
+user : The 'user' parameter value given when calling BASS_StreamCreate
+RETURN : Number of bytes written. Set the BASS_STREAMPROC_END flag to end the stream. */
+
+#define BASS_STREAMPROC_END 0x80000000 // end of user stream flag
+
+// Special STREAMPROCs
+#define STREAMPROC_DUMMY (STREAMPROC*)0 // "dummy" stream
+#define STREAMPROC_PUSH (STREAMPROC*)-1 // push stream
+#define STREAMPROC_DEVICE (STREAMPROC*)-2 // device mix stream
+#define STREAMPROC_DEVICE_3D (STREAMPROC*)-3 // device 3D mix stream
+
+// BASS_StreamCreateFileUser file systems
+#define STREAMFILE_NOBUFFER 0
+#define STREAMFILE_BUFFER 1
+#define STREAMFILE_BUFFERPUSH 2
+
+// User file stream callback functions
+typedef void (CALLBACK FILECLOSEPROC)(void *user);
+typedef QWORD (CALLBACK FILELENPROC)(void *user);
+typedef DWORD (CALLBACK FILEREADPROC)(void *buffer, DWORD length, void *user);
+typedef BOOL (CALLBACK FILESEEKPROC)(QWORD offset, void *user);
+
+typedef struct {
+ FILECLOSEPROC *close;
+ FILELENPROC *length;
+ FILEREADPROC *read;
+ FILESEEKPROC *seek;
+} BASS_FILEPROCS;
+
+// BASS_StreamPutFileData options
+#define BASS_FILEDATA_END 0 // end & close the file
+
+// BASS_StreamGetFilePosition modes
+#define BASS_FILEPOS_CURRENT 0
+#define BASS_FILEPOS_DECODE BASS_FILEPOS_CURRENT
+#define BASS_FILEPOS_DOWNLOAD 1
+#define BASS_FILEPOS_END 2
+#define BASS_FILEPOS_START 3
+#define BASS_FILEPOS_CONNECTED 4
+#define BASS_FILEPOS_BUFFER 5
+#define BASS_FILEPOS_SOCKET 6
+#define BASS_FILEPOS_ASYNCBUF 7
+#define BASS_FILEPOS_SIZE 8
+#define BASS_FILEPOS_BUFFERING 9
+#define BASS_FILEPOS_AVAILABLE 10
+
+typedef void (CALLBACK DOWNLOADPROC)(const void *buffer, DWORD length, void *user);
+/* Internet stream download callback function.
+buffer : Buffer containing the downloaded data... NULL=end of download
+length : Number of bytes in the buffer
+user : The 'user' parameter value given when calling BASS_StreamCreateURL */
+
+// BASS_ChannelSetSync types
+#define BASS_SYNC_POS 0
+#define BASS_SYNC_END 2
+#define BASS_SYNC_META 4
+#define BASS_SYNC_SLIDE 5
+#define BASS_SYNC_STALL 6
+#define BASS_SYNC_DOWNLOAD 7
+#define BASS_SYNC_FREE 8
+#define BASS_SYNC_SETPOS 11
+#define BASS_SYNC_MUSICPOS 10
+#define BASS_SYNC_MUSICINST 1
+#define BASS_SYNC_MUSICFX 3
+#define BASS_SYNC_OGG_CHANGE 12
+#define BASS_SYNC_DEV_FAIL 14
+#define BASS_SYNC_DEV_FORMAT 15
+#define BASS_SYNC_THREAD 0x20000000 // flag: call sync in other thread
+#define BASS_SYNC_MIXTIME 0x40000000 // flag: sync at mixtime, else at playtime
+#define BASS_SYNC_ONETIME 0x80000000 // flag: sync only once, else continuously
+
+typedef void (CALLBACK SYNCPROC)(HSYNC handle, DWORD channel, DWORD data, void *user);
+/* Sync callback function.
+handle : The sync that has occured
+channel: Channel that the sync occured in
+data : Additional data associated with the sync's occurance
+user : The 'user' parameter given when calling BASS_ChannelSetSync */
+
+typedef void (CALLBACK DSPPROC)(HDSP handle, DWORD channel, void *buffer, DWORD length, void *user);
+/* DSP callback function.
+handle : The DSP handle
+channel: Channel that the DSP is being applied to
+buffer : Buffer to apply the DSP to
+length : Number of bytes in the buffer
+user : The 'user' parameter given when calling BASS_ChannelSetDSP */
+
+typedef BOOL (CALLBACK RECORDPROC)(HRECORD handle, const void *buffer, DWORD length, void *user);
+/* Recording callback function.
+handle : The recording handle
+buffer : Buffer containing the recorded sample data
+length : Number of bytes
+user : The 'user' parameter value given when calling BASS_RecordStart
+RETURN : TRUE = continue recording, FALSE = stop */
+
+// BASS_ChannelIsActive return values
+#define BASS_ACTIVE_STOPPED 0
+#define BASS_ACTIVE_PLAYING 1
+#define BASS_ACTIVE_STALLED 2
+#define BASS_ACTIVE_PAUSED 3
+#define BASS_ACTIVE_PAUSED_DEVICE 4
+
+// Channel attributes
+#define BASS_ATTRIB_FREQ 1
+#define BASS_ATTRIB_VOL 2
+#define BASS_ATTRIB_PAN 3
+#define BASS_ATTRIB_EAXMIX 4
+#define BASS_ATTRIB_NOBUFFER 5
+#define BASS_ATTRIB_VBR 6
+#define BASS_ATTRIB_CPU 7
+#define BASS_ATTRIB_SRC 8
+#define BASS_ATTRIB_NET_RESUME 9
+#define BASS_ATTRIB_SCANINFO 10
+#define BASS_ATTRIB_NORAMP 11
+#define BASS_ATTRIB_BITRATE 12
+#define BASS_ATTRIB_BUFFER 13
+#define BASS_ATTRIB_GRANULE 14
+#define BASS_ATTRIB_USER 15
+#define BASS_ATTRIB_TAIL 16
+#define BASS_ATTRIB_PUSH_LIMIT 17
+#define BASS_ATTRIB_DOWNLOADPROC 18
+#define BASS_ATTRIB_VOLDSP 19
+#define BASS_ATTRIB_VOLDSP_PRIORITY 20
+#define BASS_ATTRIB_MUSIC_AMPLIFY 0x100
+#define BASS_ATTRIB_MUSIC_PANSEP 0x101
+#define BASS_ATTRIB_MUSIC_PSCALER 0x102
+#define BASS_ATTRIB_MUSIC_BPM 0x103
+#define BASS_ATTRIB_MUSIC_SPEED 0x104
+#define BASS_ATTRIB_MUSIC_VOL_GLOBAL 0x105
+#define BASS_ATTRIB_MUSIC_ACTIVE 0x106
+#define BASS_ATTRIB_MUSIC_VOL_CHAN 0x200 // + channel #
+#define BASS_ATTRIB_MUSIC_VOL_INST 0x300 // + instrument #
+
+// BASS_ChannelSlideAttribute flags
+#define BASS_SLIDE_LOG 0x1000000
+
+// BASS_ChannelGetData flags
+#define BASS_DATA_AVAILABLE 0 // query how much data is buffered
+#define BASS_DATA_NOREMOVE 0x10000000 // flag: don't remove data from recording buffer
+#define BASS_DATA_FIXED 0x20000000 // unused
+#define BASS_DATA_FLOAT 0x40000000 // flag: return floating-point sample data
+#define BASS_DATA_FFT256 0x80000000 // 256 sample FFT
+#define BASS_DATA_FFT512 0x80000001 // 512 FFT
+#define BASS_DATA_FFT1024 0x80000002 // 1024 FFT
+#define BASS_DATA_FFT2048 0x80000003 // 2048 FFT
+#define BASS_DATA_FFT4096 0x80000004 // 4096 FFT
+#define BASS_DATA_FFT8192 0x80000005 // 8192 FFT
+#define BASS_DATA_FFT16384 0x80000006 // 16384 FFT
+#define BASS_DATA_FFT32768 0x80000007 // 32768 FFT
+#define BASS_DATA_FFT_INDIVIDUAL 0x10 // FFT flag: FFT for each channel, else all combined
+#define BASS_DATA_FFT_NOWINDOW 0x20 // FFT flag: no Hanning window
+#define BASS_DATA_FFT_REMOVEDC 0x40 // FFT flag: pre-remove DC bias
+#define BASS_DATA_FFT_COMPLEX 0x80 // FFT flag: return complex data
+#define BASS_DATA_FFT_NYQUIST 0x100 // FFT flag: return extra Nyquist value
+
+// BASS_ChannelGetLevelEx flags
+#define BASS_LEVEL_MONO 1 // get mono level
+#define BASS_LEVEL_STEREO 2 // get stereo level
+#define BASS_LEVEL_RMS 4 // get RMS levels
+#define BASS_LEVEL_VOLPAN 8 // apply VOL/PAN attributes to the levels
+#define BASS_LEVEL_NOREMOVE 16 // don't remove data from recording buffer
+
+// BASS_ChannelGetTags types : what's returned
+#define BASS_TAG_ID3 0 // ID3v1 tags : TAG_ID3 structure
+#define BASS_TAG_ID3V2 1 // ID3v2 tags : variable length block
+#define BASS_TAG_OGG 2 // OGG comments : series of null-terminated UTF-8 strings
+#define BASS_TAG_HTTP 3 // HTTP headers : series of null-terminated ASCII strings
+#define BASS_TAG_ICY 4 // ICY headers : series of null-terminated ANSI strings
+#define BASS_TAG_META 5 // ICY metadata : ANSI string
+#define BASS_TAG_APE 6 // APE tags : series of null-terminated UTF-8 strings
+#define BASS_TAG_MP4 7 // MP4/iTunes metadata : series of null-terminated UTF-8 strings
+#define BASS_TAG_WMA 8 // WMA tags : series of null-terminated UTF-8 strings
+#define BASS_TAG_VENDOR 9 // OGG encoder : UTF-8 string
+#define BASS_TAG_LYRICS3 10 // Lyric3v2 tag : ASCII string
+#define BASS_TAG_CA_CODEC 11 // CoreAudio codec info : TAG_CA_CODEC structure
+#define BASS_TAG_MF 13 // Media Foundation tags : series of null-terminated UTF-8 strings
+#define BASS_TAG_WAVEFORMAT 14 // WAVE format : WAVEFORMATEEX structure
+#define BASS_TAG_AM_NAME 16 // Android Media codec name : ASCII string
+#define BASS_TAG_ID3V2_2 17 // ID3v2 tags (2nd block) : variable length block
+#define BASS_TAG_AM_MIME 18 // Android Media MIME type : ASCII string
+#define BASS_TAG_LOCATION 19 // redirected URL : ASCII string
+#define BASS_TAG_RIFF_INFO 0x100 // RIFF "INFO" tags : series of null-terminated ANSI strings
+#define BASS_TAG_RIFF_BEXT 0x101 // RIFF/BWF "bext" tags : TAG_BEXT structure
+#define BASS_TAG_RIFF_CART 0x102 // RIFF/BWF "cart" tags : TAG_CART structure
+#define BASS_TAG_RIFF_DISP 0x103 // RIFF "DISP" text tag : ANSI string
+#define BASS_TAG_RIFF_CUE 0x104 // RIFF "cue " chunk : TAG_CUE structure
+#define BASS_TAG_RIFF_SMPL 0x105 // RIFF "smpl" chunk : TAG_SMPL structure
+#define BASS_TAG_APE_BINARY 0x1000 // + index #, binary APE tag : TAG_APE_BINARY structure
+#define BASS_TAG_MUSIC_NAME 0x10000 // MOD music name : ANSI string
+#define BASS_TAG_MUSIC_MESSAGE 0x10001 // MOD message : ANSI string
+#define BASS_TAG_MUSIC_ORDERS 0x10002 // MOD order list : BYTE array of pattern numbers
+#define BASS_TAG_MUSIC_AUTH 0x10003 // MOD author : UTF-8 string
+#define BASS_TAG_MUSIC_INST 0x10100 // + instrument #, MOD instrument name : ANSI string
+#define BASS_TAG_MUSIC_CHAN 0x10200 // + channel #, MOD channel name : ANSI string
+#define BASS_TAG_MUSIC_SAMPLE 0x10300 // + sample #, MOD sample name : ANSI string
+
+// ID3v1 tag structure
+typedef struct {
+ char id[3];
+ char title[30];
+ char artist[30];
+ char album[30];
+ char year[4];
+ char comment[30];
+ BYTE genre;
+} TAG_ID3;
+
+// Binary APE tag structure
+typedef struct {
+ const char *key;
+ const void *data;
+ DWORD length;
+} TAG_APE_BINARY;
+
+// BWF "bext" tag structure
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4200)
+#endif
+#pragma pack(push,1)
+typedef struct {
+ char Description[256]; // description
+ char Originator[32]; // name of the originator
+ char OriginatorReference[32]; // reference of the originator
+ char OriginationDate[10]; // date of creation (yyyy-mm-dd)
+ char OriginationTime[8]; // time of creation (hh-mm-ss)
+ QWORD TimeReference; // first sample count since midnight (little-endian)
+ WORD Version; // BWF version (little-endian)
+ BYTE UMID[64]; // SMPTE UMID
+ BYTE Reserved[190];
+#if defined(__GNUC__) && __GNUC__<3
+ char CodingHistory[0]; // history
+#elif 1 // change to 0 if compiler fails the following line
+ char CodingHistory[]; // history
+#else
+ char CodingHistory[1]; // history
+#endif
+} TAG_BEXT;
+#pragma pack(pop)
+
+// BWF "cart" tag structures
+typedef struct
+{
+ DWORD dwUsage; // FOURCC timer usage ID
+ DWORD dwValue; // timer value in samples from head
+} TAG_CART_TIMER;
+
+typedef struct
+{
+ char Version[4]; // version of the data structure
+ char Title[64]; // title of cart audio sequence
+ char Artist[64]; // artist or creator name
+ char CutID[64]; // cut number identification
+ char ClientID[64]; // client identification
+ char Category[64]; // category ID, PSA, NEWS, etc
+ char Classification[64]; // classification or auxiliary key
+ char OutCue[64]; // out cue text
+ char StartDate[10]; // yyyy-mm-dd
+ char StartTime[8]; // hh:mm:ss
+ char EndDate[10]; // yyyy-mm-dd
+ char EndTime[8]; // hh:mm:ss
+ char ProducerAppID[64]; // name of vendor or application
+ char ProducerAppVersion[64]; // version of producer application
+ char UserDef[64]; // user defined text
+ DWORD dwLevelReference; // sample value for 0 dB reference
+ TAG_CART_TIMER PostTimer[8]; // 8 time markers after head
+ char Reserved[276];
+ char URL[1024]; // uniform resource locator
+#if defined(__GNUC__) && __GNUC__<3
+ char TagText[0]; // free form text for scripts or tags
+#elif 1 // change to 0 if compiler fails the following line
+ char TagText[]; // free form text for scripts or tags
+#else
+ char TagText[1]; // free form text for scripts or tags
+#endif
+} TAG_CART;
+
+// RIFF "cue " tag structures
+typedef struct
+{
+ DWORD dwName;
+ DWORD dwPosition;
+ DWORD fccChunk;
+ DWORD dwChunkStart;
+ DWORD dwBlockStart;
+ DWORD dwSampleOffset;
+} TAG_CUE_POINT;
+
+typedef struct
+{
+ DWORD dwCuePoints;
+#if defined(__GNUC__) && __GNUC__<3
+ TAG_CUE_POINT CuePoints[0];
+#elif 1 // change to 0 if compiler fails the following line
+ TAG_CUE_POINT CuePoints[];
+#else
+ TAG_CUE_POINT CuePoints[1];
+#endif
+} TAG_CUE;
+
+// RIFF "smpl" tag structures
+typedef struct
+{
+ DWORD dwIdentifier;
+ DWORD dwType;
+ DWORD dwStart;
+ DWORD dwEnd;
+ DWORD dwFraction;
+ DWORD dwPlayCount;
+} TAG_SMPL_LOOP;
+
+typedef struct
+{
+ DWORD dwManufacturer;
+ DWORD dwProduct;
+ DWORD dwSamplePeriod;
+ DWORD dwMIDIUnityNote;
+ DWORD dwMIDIPitchFraction;
+ DWORD dwSMPTEFormat;
+ DWORD dwSMPTEOffset;
+ DWORD cSampleLoops;
+ DWORD cbSamplerData;
+#if defined(__GNUC__) && __GNUC__<3
+ TAG_SMPL_LOOP SampleLoops[0];
+#elif 1 // change to 0 if compiler fails the following line
+ TAG_SMPL_LOOP SampleLoops[];
+#else
+ TAG_SMPL_LOOP SampleLoops[1];
+#endif
+} TAG_SMPL;
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+// CoreAudio codec info structure
+typedef struct {
+ DWORD ftype; // file format
+ DWORD atype; // audio format
+ const char *name; // description
+} TAG_CA_CODEC;
+
+#ifndef _WAVEFORMATEX_
+#define _WAVEFORMATEX_
+#pragma pack(push,1)
+typedef struct tWAVEFORMATEX
+{
+ WORD wFormatTag;
+ WORD nChannels;
+ DWORD nSamplesPerSec;
+ DWORD nAvgBytesPerSec;
+ WORD nBlockAlign;
+ WORD wBitsPerSample;
+ WORD cbSize;
+} WAVEFORMATEX, *PWAVEFORMATEX, *LPWAVEFORMATEX;
+typedef const WAVEFORMATEX *LPCWAVEFORMATEX;
+#pragma pack(pop)
+#endif
+
+// BASS_ChannelGetLength/GetPosition/SetPosition modes
+#define BASS_POS_BYTE 0 // byte position
+#define BASS_POS_MUSIC_ORDER 1 // order.row position, MAKELONG(order,row)
+#define BASS_POS_OGG 3 // OGG bitstream number
+#define BASS_POS_END 0x10 // trimmed end position
+#define BASS_POS_LOOP 0x11 // loop start positiom
+#define BASS_POS_FLUSH 0x1000000 // flag: flush decoder/FX buffers
+#define BASS_POS_RESET 0x2000000 // flag: reset user file buffers
+#define BASS_POS_RELATIVE 0x4000000 // flag: seek relative to the current position
+#define BASS_POS_INEXACT 0x8000000 // flag: allow seeking to inexact position
+#define BASS_POS_DECODE 0x10000000 // flag: get the decoding (not playing) position
+#define BASS_POS_DECODETO 0x20000000 // flag: decode to the position instead of seeking
+#define BASS_POS_SCAN 0x40000000 // flag: scan to the position
+
+// BASS_ChannelSetDevice/GetDevice option
+#define BASS_NODEVICE 0x20000
+
+// BASS_RecordSetInput flags
+#define BASS_INPUT_OFF 0x10000
+#define BASS_INPUT_ON 0x20000
+
+#define BASS_INPUT_TYPE_MASK 0xff000000
+#define BASS_INPUT_TYPE_UNDEF 0x00000000
+#define BASS_INPUT_TYPE_DIGITAL 0x01000000
+#define BASS_INPUT_TYPE_LINE 0x02000000
+#define BASS_INPUT_TYPE_MIC 0x03000000
+#define BASS_INPUT_TYPE_SYNTH 0x04000000
+#define BASS_INPUT_TYPE_CD 0x05000000
+#define BASS_INPUT_TYPE_PHONE 0x06000000
+#define BASS_INPUT_TYPE_SPEAKER 0x07000000
+#define BASS_INPUT_TYPE_WAVE 0x08000000
+#define BASS_INPUT_TYPE_AUX 0x09000000
+#define BASS_INPUT_TYPE_ANALOG 0x0a000000
+
+// BASS_ChannelSetFX effect types
+#define BASS_FX_DX8_CHORUS 0
+#define BASS_FX_DX8_COMPRESSOR 1
+#define BASS_FX_DX8_DISTORTION 2
+#define BASS_FX_DX8_ECHO 3
+#define BASS_FX_DX8_FLANGER 4
+#define BASS_FX_DX8_GARGLE 5
+#define BASS_FX_DX8_I3DL2REVERB 6
+#define BASS_FX_DX8_PARAMEQ 7
+#define BASS_FX_DX8_REVERB 8
+#define BASS_FX_VOLUME 9
+
+typedef struct {
+ float fWetDryMix;
+ float fDepth;
+ float fFeedback;
+ float fFrequency;
+ DWORD lWaveform; // 0=triangle, 1=sine
+ float fDelay;
+ DWORD lPhase; // BASS_DX8_PHASE_xxx
+} BASS_DX8_CHORUS;
+
+typedef struct {
+ float fGain;
+ float fAttack;
+ float fRelease;
+ float fThreshold;
+ float fRatio;
+ float fPredelay;
+} BASS_DX8_COMPRESSOR;
+
+typedef struct {
+ float fGain;
+ float fEdge;
+ float fPostEQCenterFrequency;
+ float fPostEQBandwidth;
+ float fPreLowpassCutoff;
+} BASS_DX8_DISTORTION;
+
+typedef struct {
+ float fWetDryMix;
+ float fFeedback;
+ float fLeftDelay;
+ float fRightDelay;
+ BOOL lPanDelay;
+} BASS_DX8_ECHO;
+
+typedef struct {
+ float fWetDryMix;
+ float fDepth;
+ float fFeedback;
+ float fFrequency;
+ DWORD lWaveform; // 0=triangle, 1=sine
+ float fDelay;
+ DWORD lPhase; // BASS_DX8_PHASE_xxx
+} BASS_DX8_FLANGER;
+
+typedef struct {
+ DWORD dwRateHz; // Rate of modulation in hz
+ DWORD dwWaveShape; // 0=triangle, 1=square
+} BASS_DX8_GARGLE;
+
+typedef struct {
+ int lRoom; // [-10000, 0] default: -1000 mB
+ int lRoomHF; // [-10000, 0] default: 0 mB
+ float flRoomRolloffFactor; // [0.0, 10.0] default: 0.0
+ float flDecayTime; // [0.1, 20.0] default: 1.49s
+ float flDecayHFRatio; // [0.1, 2.0] default: 0.83
+ int lReflections; // [-10000, 1000] default: -2602 mB
+ float flReflectionsDelay; // [0.0, 0.3] default: 0.007 s
+ int lReverb; // [-10000, 2000] default: 200 mB
+ float flReverbDelay; // [0.0, 0.1] default: 0.011 s
+ float flDiffusion; // [0.0, 100.0] default: 100.0 %
+ float flDensity; // [0.0, 100.0] default: 100.0 %
+ float flHFReference; // [20.0, 20000.0] default: 5000.0 Hz
+} BASS_DX8_I3DL2REVERB;
+
+typedef struct {
+ float fCenter;
+ float fBandwidth;
+ float fGain;
+} BASS_DX8_PARAMEQ;
+
+typedef struct {
+ float fInGain; // [-96.0,0.0] default: 0.0 dB
+ float fReverbMix; // [-96.0,0.0] default: 0.0 db
+ float fReverbTime; // [0.001,3000.0] default: 1000.0 ms
+ float fHighFreqRTRatio; // [0.001,0.999] default: 0.001
+} BASS_DX8_REVERB;
+
+#define BASS_DX8_PHASE_NEG_180 0
+#define BASS_DX8_PHASE_NEG_90 1
+#define BASS_DX8_PHASE_ZERO 2
+#define BASS_DX8_PHASE_90 3
+#define BASS_DX8_PHASE_180 4
+
+typedef struct {
+ float fTarget;
+ float fCurrent;
+ float fTime;
+ DWORD lCurve;
+} BASS_FX_VOLUME_PARAM;
+
+typedef void (CALLBACK IOSNOTIFYPROC)(DWORD status);
+/* iOS notification callback function.
+status : The notification (BASS_IOSNOTIFY_xxx) */
+
+#define BASS_IOSNOTIFY_INTERRUPT 1 // interruption started
+#define BASS_IOSNOTIFY_INTERRUPT_END 2 // interruption ended
+
+BOOL BASSDEF(BASS_SetConfig)(DWORD option, DWORD value);
+DWORD BASSDEF(BASS_GetConfig)(DWORD option);
+BOOL BASSDEF(BASS_SetConfigPtr)(DWORD option, const void *value);
+const void *BASSDEF(BASS_GetConfigPtr)(DWORD option);
+DWORD BASSDEF(BASS_GetVersion)(void);
+int BASSDEF(BASS_ErrorGetCode)(void);
+
+BOOL BASSDEF(BASS_GetDeviceInfo)(DWORD device, BASS_DEVICEINFO *info);
+#if defined(_WIN32) && !defined(_WIN32_WCE) && !(defined(WINAPI_FAMILY) && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
+BOOL BASSDEF(BASS_Init)(int device, DWORD freq, DWORD flags, HWND win, const void *dsguid);
+#else
+BOOL BASSDEF(BASS_Init)(int device, DWORD freq, DWORD flags, void *win, const void *dsguid);
+#endif
+BOOL BASSDEF(BASS_Free)(void);
+BOOL BASSDEF(BASS_SetDevice)(DWORD device);
+DWORD BASSDEF(BASS_GetDevice)(void);
+BOOL BASSDEF(BASS_GetInfo)(BASS_INFO *info);
+BOOL BASSDEF(BASS_Start)(void);
+BOOL BASSDEF(BASS_Stop)(void);
+BOOL BASSDEF(BASS_Pause)(void);
+DWORD BASSDEF(BASS_IsStarted)(void);
+BOOL BASSDEF(BASS_Update)(DWORD length);
+float BASSDEF(BASS_GetCPU)(void);
+BOOL BASSDEF(BASS_SetVolume)(float volume);
+float BASSDEF(BASS_GetVolume)(void);
+#if defined(_WIN32) && !defined(_WIN32_WCE) && !(defined(WINAPI_FAMILY) && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
+void *BASSDEF(BASS_GetDSoundObject)(DWORD object);
+#endif
+
+BOOL BASSDEF(BASS_Set3DFactors)(float distf, float rollf, float doppf);
+BOOL BASSDEF(BASS_Get3DFactors)(float *distf, float *rollf, float *doppf);
+BOOL BASSDEF(BASS_Set3DPosition)(const BASS_3DVECTOR *pos, const BASS_3DVECTOR *vel, const BASS_3DVECTOR *front, const BASS_3DVECTOR *top);
+BOOL BASSDEF(BASS_Get3DPosition)(BASS_3DVECTOR *pos, BASS_3DVECTOR *vel, BASS_3DVECTOR *front, BASS_3DVECTOR *top);
+void BASSDEF(BASS_Apply3D)(void);
+
+HPLUGIN BASSDEF(BASS_PluginLoad)(const char *file, DWORD flags);
+BOOL BASSDEF(BASS_PluginFree)(HPLUGIN handle);
+BOOL BASSDEF(BASS_PluginEnable)(HPLUGIN handle, BOOL enable);
+const BASS_PLUGININFO *BASSDEF(BASS_PluginGetInfo)(HPLUGIN handle);
+
+HSAMPLE BASSDEF(BASS_SampleLoad)(BOOL mem, const void *file, QWORD offset, DWORD length, DWORD max, DWORD flags);
+HSAMPLE BASSDEF(BASS_SampleCreate)(DWORD length, DWORD freq, DWORD chans, DWORD max, DWORD flags);
+BOOL BASSDEF(BASS_SampleFree)(HSAMPLE handle);
+BOOL BASSDEF(BASS_SampleSetData)(HSAMPLE handle, const void *buffer);
+BOOL BASSDEF(BASS_SampleGetData)(HSAMPLE handle, void *buffer);
+BOOL BASSDEF(BASS_SampleGetInfo)(HSAMPLE handle, BASS_SAMPLE *info);
+BOOL BASSDEF(BASS_SampleSetInfo)(HSAMPLE handle, const BASS_SAMPLE *info);
+DWORD BASSDEF(BASS_SampleGetChannel)(HSAMPLE handle, DWORD flags);
+DWORD BASSDEF(BASS_SampleGetChannels)(HSAMPLE handle, HCHANNEL *channels);
+BOOL BASSDEF(BASS_SampleStop)(HSAMPLE handle);
+
+HSTREAM BASSDEF(BASS_StreamCreate)(DWORD freq, DWORD chans, DWORD flags, STREAMPROC *proc, void *user);
+HSTREAM BASSDEF(BASS_StreamCreateFile)(BOOL mem, const void *file, QWORD offset, QWORD length, DWORD flags);
+HSTREAM BASSDEF(BASS_StreamCreateURL)(const char *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user);
+HSTREAM BASSDEF(BASS_StreamCreateFileUser)(DWORD system, DWORD flags, const BASS_FILEPROCS *proc, void *user);
+BOOL BASSDEF(BASS_StreamFree)(HSTREAM handle);
+QWORD BASSDEF(BASS_StreamGetFilePosition)(HSTREAM handle, DWORD mode);
+DWORD BASSDEF(BASS_StreamPutData)(HSTREAM handle, const void *buffer, DWORD length);
+DWORD BASSDEF(BASS_StreamPutFileData)(HSTREAM handle, const void *buffer, DWORD length);
+
+HMUSIC BASSDEF(BASS_MusicLoad)(BOOL mem, const void *file, QWORD offset, DWORD length, DWORD flags, DWORD freq);
+BOOL BASSDEF(BASS_MusicFree)(HMUSIC handle);
+
+BOOL BASSDEF(BASS_RecordGetDeviceInfo)(DWORD device, BASS_DEVICEINFO *info);
+BOOL BASSDEF(BASS_RecordInit)(int device);
+BOOL BASSDEF(BASS_RecordFree)(void);
+BOOL BASSDEF(BASS_RecordSetDevice)(DWORD device);
+DWORD BASSDEF(BASS_RecordGetDevice)(void);
+BOOL BASSDEF(BASS_RecordGetInfo)(BASS_RECORDINFO *info);
+const char *BASSDEF(BASS_RecordGetInputName)(int input);
+BOOL BASSDEF(BASS_RecordSetInput)(int input, DWORD flags, float volume);
+DWORD BASSDEF(BASS_RecordGetInput)(int input, float *volume);
+HRECORD BASSDEF(BASS_RecordStart)(DWORD freq, DWORD chans, DWORD flags, RECORDPROC *proc, void *user);
+
+double BASSDEF(BASS_ChannelBytes2Seconds)(DWORD handle, QWORD pos);
+QWORD BASSDEF(BASS_ChannelSeconds2Bytes)(DWORD handle, double pos);
+DWORD BASSDEF(BASS_ChannelGetDevice)(DWORD handle);
+BOOL BASSDEF(BASS_ChannelSetDevice)(DWORD handle, DWORD device);
+DWORD BASSDEF(BASS_ChannelIsActive)(DWORD handle);
+BOOL BASSDEF(BASS_ChannelGetInfo)(DWORD handle, BASS_CHANNELINFO *info);
+const char *BASSDEF(BASS_ChannelGetTags)(DWORD handle, DWORD tags);
+DWORD BASSDEF(BASS_ChannelFlags)(DWORD handle, DWORD flags, DWORD mask);
+BOOL BASSDEF(BASS_ChannelLock)(DWORD handle, BOOL lock);
+BOOL BASSDEF(BASS_ChannelFree)(DWORD handle);
+BOOL BASSDEF(BASS_ChannelPlay)(DWORD handle, BOOL restart);
+BOOL BASSDEF(BASS_ChannelStart)(DWORD handle);
+BOOL BASSDEF(BASS_ChannelStop)(DWORD handle);
+BOOL BASSDEF(BASS_ChannelPause)(DWORD handle);
+BOOL BASSDEF(BASS_ChannelUpdate)(DWORD handle, DWORD length);
+BOOL BASSDEF(BASS_ChannelSetAttribute)(DWORD handle, DWORD attrib, float value);
+BOOL BASSDEF(BASS_ChannelGetAttribute)(DWORD handle, DWORD attrib, float *value);
+BOOL BASSDEF(BASS_ChannelSlideAttribute)(DWORD handle, DWORD attrib, float value, DWORD time);
+BOOL BASSDEF(BASS_ChannelIsSliding)(DWORD handle, DWORD attrib);
+BOOL BASSDEF(BASS_ChannelSetAttributeEx)(DWORD handle, DWORD attrib, void *value, DWORD size);
+DWORD BASSDEF(BASS_ChannelGetAttributeEx)(DWORD handle, DWORD attrib, void *value, DWORD size);
+BOOL BASSDEF(BASS_ChannelSet3DAttributes)(DWORD handle, int mode, float min, float max, int iangle, int oangle, float outvol);
+BOOL BASSDEF(BASS_ChannelGet3DAttributes)(DWORD handle, DWORD *mode, float *min, float *max, DWORD *iangle, DWORD *oangle, float *outvol);
+BOOL BASSDEF(BASS_ChannelSet3DPosition)(DWORD handle, const BASS_3DVECTOR *pos, const BASS_3DVECTOR *orient, const BASS_3DVECTOR *vel);
+BOOL BASSDEF(BASS_ChannelGet3DPosition)(DWORD handle, BASS_3DVECTOR *pos, BASS_3DVECTOR *orient, BASS_3DVECTOR *vel);
+QWORD BASSDEF(BASS_ChannelGetLength)(DWORD handle, DWORD mode);
+BOOL BASSDEF(BASS_ChannelSetPosition)(DWORD handle, QWORD pos, DWORD mode);
+QWORD BASSDEF(BASS_ChannelGetPosition)(DWORD handle, DWORD mode);
+DWORD BASSDEF(BASS_ChannelGetLevel)(DWORD handle);
+BOOL BASSDEF(BASS_ChannelGetLevelEx)(DWORD handle, float *levels, float length, DWORD flags);
+DWORD BASSDEF(BASS_ChannelGetData)(DWORD handle, void *buffer, DWORD length);
+HSYNC BASSDEF(BASS_ChannelSetSync)(DWORD handle, DWORD type, QWORD param, SYNCPROC *proc, void *user);
+BOOL BASSDEF(BASS_ChannelRemoveSync)(DWORD handle, HSYNC sync);
+BOOL BASSDEF(BASS_ChannelSetLink)(DWORD handle, DWORD chan);
+BOOL BASSDEF(BASS_ChannelRemoveLink)(DWORD handle, DWORD chan);
+HDSP BASSDEF(BASS_ChannelSetDSP)(DWORD handle, DSPPROC *proc, void *user, int priority);
+BOOL BASSDEF(BASS_ChannelRemoveDSP)(DWORD handle, HDSP dsp);
+HFX BASSDEF(BASS_ChannelSetFX)(DWORD handle, DWORD type, int priority);
+BOOL BASSDEF(BASS_ChannelRemoveFX)(DWORD handle, HFX fx);
+
+BOOL BASSDEF(BASS_FXSetParameters)(HFX handle, const void *params);
+BOOL BASSDEF(BASS_FXGetParameters)(HFX handle, void *params);
+BOOL BASSDEF(BASS_FXSetPriority)(HFX handle, int priority);
+BOOL BASSDEF(BASS_FXReset)(DWORD handle);
+
+#ifdef __cplusplus
+}
+
+#if defined(_WIN32) && !defined(NOBASSOVERLOADS)
+static inline HPLUGIN BASS_PluginLoad(const WCHAR *file, DWORD flags)
+{
+ return BASS_PluginLoad((const char*)file, flags | BASS_UNICODE);
+}
+
+static inline HMUSIC BASS_MusicLoad(BOOL mem, const WCHAR *file, QWORD offset, DWORD length, DWORD flags, DWORD freq)
+{
+ return BASS_MusicLoad(mem, (const void*)file, offset, length, flags | BASS_UNICODE, freq);
+}
+
+static inline HSAMPLE BASS_SampleLoad(BOOL mem, const WCHAR *file, QWORD offset, DWORD length, DWORD max, DWORD flags)
+{
+ return BASS_SampleLoad(mem, (const void*)file, offset, length, max, flags | BASS_UNICODE);
+}
+
+static inline HSTREAM BASS_StreamCreateFile(BOOL mem, const WCHAR *file, QWORD offset, QWORD length, DWORD flags)
+{
+ return BASS_StreamCreateFile(mem, (const void*)file, offset, length, flags | BASS_UNICODE);
+}
+
+static inline HSTREAM BASS_StreamCreateURL(const WCHAR *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user)
+{
+ return BASS_StreamCreateURL((const char*)url, offset, flags | BASS_UNICODE, proc, user);
+}
+
+static inline BOOL BASS_SetConfigPtr(DWORD option, const WCHAR *value)
+{
+ return BASS_SetConfigPtr(option | BASS_UNICODE, (const void*)value);
+}
+#endif
+#endif
+
+#ifdef __OBJC__
+#undef BOOL
+#endif
+
+#endif
diff --git a/bass/inc/bassmidi.h b/bass/inc/bassmidi.h
new file mode 100644
index 0000000..30e5447
--- /dev/null
+++ b/bass/inc/bassmidi.h
@@ -0,0 +1,442 @@
+/*
+ BASSMIDI 2.4 C/C++ header file
+ Copyright (c) 2006-2024 Un4seen Developments Ltd.
+
+ See the BASSMIDI.CHM file for more detailed documentation
+*/
+
+#ifndef BASSMIDI_H
+#define BASSMIDI_H
+
+#include "bass.h"
+
+#if BASSVERSION!=0x204
+#error conflicting BASS and BASSMIDI versions
+#endif
+
+#ifdef __OBJC__
+typedef int BOOL32;
+#define BOOL BOOL32 // override objc's BOOL
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef BASSMIDIDEF
+#define BASSMIDIDEF(f) WINAPI f
+#else
+#define NOBASSMIDIOVERLOADS
+#endif
+
+typedef DWORD HSOUNDFONT; // soundfont handle
+
+// Additional error codes returned by BASS_ErrorGetCode
+#define BASS_ERROR_MIDI_INCLUDE 7000 // SFZ include file could not be opened
+
+// Additional BASS_SetConfig options
+#define BASS_CONFIG_MIDI_COMPACT 0x10400
+#define BASS_CONFIG_MIDI_VOICES 0x10401
+#define BASS_CONFIG_MIDI_AUTOFONT 0x10402
+#define BASS_CONFIG_MIDI_IN_PORTS 0x10404
+#define BASS_CONFIG_MIDI_SAMPLETHREADS 0x10406
+#define BASS_CONFIG_MIDI_SAMPLEMEM 0x10407
+#define BASS_CONFIG_MIDI_SAMPLEREAD 0x10408
+#define BASS_CONFIG_MIDI_SAMPLELOADING 0x1040a
+
+// Additional BASS_SetConfigPtr options
+#define BASS_CONFIG_MIDI_DEFFONT 0x10403
+#define BASS_CONFIG_MIDI_SFZHEAD 0x10409
+
+// Additional sync types
+#define BASS_SYNC_MIDI_MARK 0x10000
+#define BASS_SYNC_MIDI_MARKER 0x10000
+#define BASS_SYNC_MIDI_CUE 0x10001
+#define BASS_SYNC_MIDI_LYRIC 0x10002
+#define BASS_SYNC_MIDI_TEXT 0x10003
+#define BASS_SYNC_MIDI_EVENT 0x10004
+#define BASS_SYNC_MIDI_TICK 0x10005
+#define BASS_SYNC_MIDI_TIMESIG 0x10006
+#define BASS_SYNC_MIDI_KEYSIG 0x10007
+
+// Additional BASS_MIDI_StreamCreateFile/etc flags
+#define BASS_MIDI_NODRUMPARAMUSER 0x200
+#define BASS_MIDI_NODRUMPARAM 0x400
+#define BASS_MIDI_NOSYSRESET 0x800
+#define BASS_MIDI_DECAYEND 0x1000
+#define BASS_MIDI_NOFX 0x2000
+#define BASS_MIDI_DECAYSEEK 0x4000
+#define BASS_MIDI_NOCROP 0x8000
+#define BASS_MIDI_NOTEOFF1 0x10000
+#define BASS_MIDI_ASYNC 0x400000
+#define BASS_MIDI_SINCINTER 0x800000
+
+// BASS_MIDI_FontInit flags
+#define BASS_MIDI_FONT_MEM 0x10000
+#define BASS_MIDI_FONT_MMAP 0x20000
+#define BASS_MIDI_FONT_XGDRUMS 0x40000
+#define BASS_MIDI_FONT_NOFX 0x80000
+#define BASS_MIDI_FONT_LINATTMOD 0x100000
+#define BASS_MIDI_FONT_LINDECVOL 0x200000
+#define BASS_MIDI_FONT_NORAMPIN 0x400000
+#define BASS_MIDI_FONT_NOSBLIMITS 0x800000
+#define BASS_MIDI_FONT_NOLIMITS BASS_MIDI_FONT_NOSBLIMITS
+#define BASS_MIDI_FONT_MINFX 0x1000000
+#define BASS_MIDI_FONT_SBLIMITS 0x2000000
+
+typedef struct {
+ HSOUNDFONT font; // soundfont
+ int preset; // preset number (-1=all)
+ int bank;
+} BASS_MIDI_FONT;
+
+typedef struct {
+ HSOUNDFONT font; // soundfont
+ int spreset; // source preset number
+ int sbank; // source bank number
+ int dpreset; // destination preset/program number
+ int dbank; // destination bank number
+ int dbanklsb; // destination bank number LSB
+} BASS_MIDI_FONTEX;
+
+typedef struct {
+ HSOUNDFONT font; // soundfont
+ int spreset; // source preset number
+ int sbank; // source bank number
+ int dpreset; // destination preset/program number
+ int dbank; // destination bank number
+ int dbanklsb; // destination bank number LSB
+ DWORD minchan; // minimum channel number
+ DWORD numchan; // number of channels from minchan
+} BASS_MIDI_FONTEX2;
+
+// BASS_MIDI_StreamSet/GetFonts flag
+#define BASS_MIDI_FONT_EX 0x1000000 // BASS_MIDI_FONTEX
+#define BASS_MIDI_FONT_EX2 0x2000000 // BASS_MIDI_FONTEX2
+
+typedef struct {
+ const char *name;
+ const char *copyright;
+ const char *comment;
+ DWORD presets; // number of presets/instruments
+ DWORD samsize; // total size (in bytes) of the sample data
+ DWORD samload; // amount of sample data currently loaded
+ DWORD samtype; // sample format (CTYPE) if packed
+} BASS_MIDI_FONTINFO;
+
+typedef struct {
+ DWORD track; // track containing marker
+ DWORD pos; // marker position
+ const char *text; // marker text
+} BASS_MIDI_MARK;
+
+// Marker types
+#define BASS_MIDI_MARK_MARKER 0 // marker
+#define BASS_MIDI_MARK_CUE 1 // cue point
+#define BASS_MIDI_MARK_LYRIC 2 // lyric
+#define BASS_MIDI_MARK_TEXT 3 // text
+#define BASS_MIDI_MARK_TIMESIG 4 // time signature
+#define BASS_MIDI_MARK_KEYSIG 5 // key signature
+#define BASS_MIDI_MARK_COPY 6 // copyright notice
+#define BASS_MIDI_MARK_TRACK 7 // track name
+#define BASS_MIDI_MARK_INST 8 // instrument name
+#define BASS_MIDI_MARK_TRACKSTART 9 // track start (SMF2)
+#define BASS_MIDI_MARK_SEQSPEC 10 // sequencer-specific
+#define BASS_MIDI_MARK_TICK 0x10000 // flag: get position in ticks (otherwise bytes)
+
+// MIDI events
+#define MIDI_EVENT_NOTE 1
+#define MIDI_EVENT_PROGRAM 2
+#define MIDI_EVENT_CHANPRES 3
+#define MIDI_EVENT_PITCH 4
+#define MIDI_EVENT_PITCHRANGE 5
+#define MIDI_EVENT_DRUMS 6
+#define MIDI_EVENT_FINETUNE 7
+#define MIDI_EVENT_COARSETUNE 8
+#define MIDI_EVENT_MASTERVOL 9
+#define MIDI_EVENT_BANK 10
+#define MIDI_EVENT_MODULATION 11
+#define MIDI_EVENT_VOLUME 12
+#define MIDI_EVENT_PAN 13
+#define MIDI_EVENT_EXPRESSION 14
+#define MIDI_EVENT_SUSTAIN 15
+#define MIDI_EVENT_SOUNDOFF 16
+#define MIDI_EVENT_RESET 17
+#define MIDI_EVENT_NOTESOFF 18
+#define MIDI_EVENT_PORTAMENTO 19
+#define MIDI_EVENT_PORTATIME 20
+#define MIDI_EVENT_PORTANOTE 21
+#define MIDI_EVENT_MODE 22
+#define MIDI_EVENT_REVERB 23
+#define MIDI_EVENT_CHORUS 24
+#define MIDI_EVENT_CUTOFF 25
+#define MIDI_EVENT_RESONANCE 26
+#define MIDI_EVENT_RELEASE 27
+#define MIDI_EVENT_ATTACK 28
+#define MIDI_EVENT_DECAY 29
+#define MIDI_EVENT_REVERB_MACRO 30
+#define MIDI_EVENT_CHORUS_MACRO 31
+#define MIDI_EVENT_REVERB_TIME 32
+#define MIDI_EVENT_REVERB_DELAY 33
+#define MIDI_EVENT_REVERB_LOCUTOFF 34
+#define MIDI_EVENT_REVERB_HICUTOFF 35
+#define MIDI_EVENT_REVERB_LEVEL 36
+#define MIDI_EVENT_CHORUS_DELAY 37
+#define MIDI_EVENT_CHORUS_DEPTH 38
+#define MIDI_EVENT_CHORUS_RATE 39
+#define MIDI_EVENT_CHORUS_FEEDBACK 40
+#define MIDI_EVENT_CHORUS_LEVEL 41
+#define MIDI_EVENT_CHORUS_REVERB 42
+#define MIDI_EVENT_USERFX 43
+#define MIDI_EVENT_USERFX_LEVEL 44
+#define MIDI_EVENT_USERFX_REVERB 45
+#define MIDI_EVENT_USERFX_CHORUS 46
+#define MIDI_EVENT_DRUM_FINETUNE 50
+#define MIDI_EVENT_DRUM_COARSETUNE 51
+#define MIDI_EVENT_DRUM_PAN 52
+#define MIDI_EVENT_DRUM_REVERB 53
+#define MIDI_EVENT_DRUM_CHORUS 54
+#define MIDI_EVENT_DRUM_CUTOFF 55
+#define MIDI_EVENT_DRUM_RESONANCE 56
+#define MIDI_EVENT_DRUM_LEVEL 57
+#define MIDI_EVENT_DRUM_USERFX 58
+#define MIDI_EVENT_SOFT 60
+#define MIDI_EVENT_SYSTEM 61
+#define MIDI_EVENT_TEMPO 62
+#define MIDI_EVENT_SCALETUNING 63
+#define MIDI_EVENT_CONTROL 64
+#define MIDI_EVENT_CHANPRES_VIBRATO 65
+#define MIDI_EVENT_CHANPRES_PITCH 66
+#define MIDI_EVENT_CHANPRES_FILTER 67
+#define MIDI_EVENT_CHANPRES_VOLUME 68
+#define MIDI_EVENT_MOD_VIBRATO 69
+#define MIDI_EVENT_MODRANGE 69
+#define MIDI_EVENT_BANK_LSB 70
+#define MIDI_EVENT_KEYPRES 71
+#define MIDI_EVENT_KEYPRES_VIBRATO 72
+#define MIDI_EVENT_KEYPRES_PITCH 73
+#define MIDI_EVENT_KEYPRES_FILTER 74
+#define MIDI_EVENT_KEYPRES_VOLUME 75
+#define MIDI_EVENT_SOSTENUTO 76
+#define MIDI_EVENT_MOD_PITCH 77
+#define MIDI_EVENT_MOD_FILTER 78
+#define MIDI_EVENT_MOD_VOLUME 79
+#define MIDI_EVENT_VIBRATO_RATE 80
+#define MIDI_EVENT_VIBRATO_DEPTH 81
+#define MIDI_EVENT_VIBRATO_DELAY 82
+#define MIDI_EVENT_MASTER_FINETUNE 83
+#define MIDI_EVENT_MASTER_COARSETUNE 84
+#define MIDI_EVENT_MIXLEVEL 0x10000
+#define MIDI_EVENT_TRANSPOSE 0x10001
+#define MIDI_EVENT_SYSTEMEX 0x10002
+#define MIDI_EVENT_SPEED 0x10004
+#define MIDI_EVENT_DEFDRUMS 0x10006
+
+#define MIDI_EVENT_END 0
+#define MIDI_EVENT_END_TRACK 0x10003
+
+#define MIDI_EVENT_NOTES 0x20000
+#define MIDI_EVENT_VOICES 0x20001
+
+#define MIDI_SYSTEM_DEFAULT 0
+#define MIDI_SYSTEM_GM1 1
+#define MIDI_SYSTEM_GM2 2
+#define MIDI_SYSTEM_XG 3
+#define MIDI_SYSTEM_GS 4
+
+typedef struct {
+ DWORD event; // MIDI_EVENT_xxx
+ DWORD param;
+ DWORD chan;
+ DWORD tick; // event position (ticks)
+ DWORD pos; // event position (bytes)
+} BASS_MIDI_EVENT;
+
+// BASS_MIDI_StreamEvents modes
+#define BASS_MIDI_EVENTS_STRUCT 0 // BASS_MIDI_EVENT structures
+#define BASS_MIDI_EVENTS_RAW 0x10000 // raw MIDI event data
+#define BASS_MIDI_EVENTS_SYNC 0x1000000 // flag: trigger event syncs
+#define BASS_MIDI_EVENTS_NORSTATUS 0x2000000 // flag: no running status
+#define BASS_MIDI_EVENTS_CANCEL 0x4000000 // flag: cancel pending events
+#define BASS_MIDI_EVENTS_TIME 0x8000000 // flag: delta-time info is present
+#define BASS_MIDI_EVENTS_ABSTIME 0x10000000 // flag: absolute time info is present
+#define BASS_MIDI_EVENTS_ASYNC 0x20000000 // flag: process asynchronously
+#define BASS_MIDI_EVENTS_FILTER 0x40000000 // flag: apply filtering
+#define BASS_MIDI_EVENTS_FLUSH 0x80000000 // flag: flush async events
+
+// BASS_MIDI_StreamGetChannel special channels
+#define BASS_MIDI_CHAN_CHORUS (DWORD)-1
+#define BASS_MIDI_CHAN_REVERB (DWORD)-2
+#define BASS_MIDI_CHAN_USERFX (DWORD)-3
+
+// BASS_CHANNELINFO type
+#define BASS_CTYPE_STREAM_MIDI 0x10d00
+
+// Additional attributes
+#define BASS_ATTRIB_MIDI_PPQN 0x12000
+#define BASS_ATTRIB_MIDI_CPU 0x12001
+#define BASS_ATTRIB_MIDI_CHANS 0x12002
+#define BASS_ATTRIB_MIDI_VOICES 0x12003
+#define BASS_ATTRIB_MIDI_VOICES_ACTIVE 0x12004
+#define BASS_ATTRIB_MIDI_STATE 0x12005
+#define BASS_ATTRIB_MIDI_SRC 0x12006
+#define BASS_ATTRIB_MIDI_KILL 0x12007
+#define BASS_ATTRIB_MIDI_SPEED 0x12008
+#define BASS_ATTRIB_MIDI_REVERB 0x12009
+#define BASS_ATTRIB_MIDI_VOL 0x1200a
+#define BASS_ATTRIB_MIDI_QUEUE_TICK 0x1200b
+#define BASS_ATTRIB_MIDI_QUEUE_BYTE 0x1200c
+#define BASS_ATTRIB_MIDI_QUEUE_ASYNC 0x1200d
+#define BASS_ATTRIB_MIDI_TRACK_VOL 0x12100 // + track #
+
+// Additional tag type
+#define BASS_TAG_MIDI_TRACK 0x11000 // + track #, track text : array of null-terminated ANSI strings
+
+// BASS_ChannelGetLength/GetPosition/SetPosition mode
+#define BASS_POS_MIDI_TICK 2 // tick position
+
+typedef BOOL (CALLBACK MIDIFILTERPROC)(HSTREAM handle, int track, BASS_MIDI_EVENT *event, BOOL seeking, void *user);
+/* Event filtering callback function.
+handle : MIDI stream handle
+track : Track containing the event
+event : The event
+seeking: TRUE = the event is being processed while seeking, FALSE = it is being played
+user : The 'user' parameter value given when calling BASS_MIDI_StreamSetFilter
+RETURN : TRUE = process the event, FALSE = drop the event */
+
+// BASS_MIDI_FontLoadEx flags
+#define BASS_MIDI_FONTLOAD_NOWAIT 1 // don't want for the samples to load
+#define BASS_MIDI_FONTLOAD_COMPACT 2 // compact samples
+#define BASS_MIDI_FONTLOAD_NOLOAD 4 // don't load (only compact)
+#define BASS_MIDI_FONTLOAD_TIME 8 // length is in milliseconds
+#define BASS_MIDI_FONTLOAD_KEEPDEC 16 // keep decoders
+
+// BASS_MIDI_FontPack flags
+#define BASS_MIDI_PACK_NOHEAD 1 // don't send a WAV header to the encoder
+#define BASS_MIDI_PACK_16BIT 2 // discard low 8 bits of 24-bit sample data
+#define BASS_MIDI_PACK_48KHZ 4 // set encoding rate to 48000 Hz (else 44100 Hz)
+
+typedef struct {
+ const char *name; // description
+ DWORD id;
+ DWORD flags;
+} BASS_MIDI_DEVICEINFO;
+
+typedef void (CALLBACK MIDIINPROC)(DWORD device, double time, const BYTE *buffer, DWORD length, void *user);
+/* MIDI input callback function.
+device : MIDI input device
+time : Timestamp
+buffer : Buffer containing MIDI data
+length : Number of bytes of data
+user : The 'user' parameter value given when calling BASS_MIDI_InInit */
+
+DWORD BASSMIDIDEF(BASS_MIDI_GetVersion)(void);
+
+HSTREAM BASSMIDIDEF(BASS_MIDI_StreamCreate)(DWORD channels, DWORD flags, DWORD freq);
+HSTREAM BASSMIDIDEF(BASS_MIDI_StreamCreateFile)(BOOL mem, const void *file, QWORD offset, QWORD length, DWORD flags, DWORD freq);
+HSTREAM BASSMIDIDEF(BASS_MIDI_StreamCreateURL)(const char *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user, DWORD freq);
+HSTREAM BASSMIDIDEF(BASS_MIDI_StreamCreateFileUser)(DWORD system, DWORD flags, const BASS_FILEPROCS *procs, void *user, DWORD freq);
+HSTREAM BASSMIDIDEF(BASS_MIDI_StreamCreateEvents)(const BASS_MIDI_EVENT *events, DWORD ppqn, DWORD flags, DWORD freq);
+BOOL BASSMIDIDEF(BASS_MIDI_StreamGetMark)(HSTREAM handle, DWORD type, DWORD index, BASS_MIDI_MARK *mark);
+DWORD BASSMIDIDEF(BASS_MIDI_StreamGetMarks)(HSTREAM handle, int track, DWORD type, BASS_MIDI_MARK *marks);
+BOOL BASSMIDIDEF(BASS_MIDI_StreamSetFonts)(HSTREAM handle, const void *fonts, DWORD count);
+DWORD BASSMIDIDEF(BASS_MIDI_StreamGetFonts)(HSTREAM handle, void *fonts, DWORD count);
+BOOL BASSMIDIDEF(BASS_MIDI_StreamLoadSamples)(HSTREAM handle);
+BOOL BASSMIDIDEF(BASS_MIDI_StreamEvent)(HSTREAM handle, DWORD chan, DWORD event, DWORD param);
+DWORD BASSMIDIDEF(BASS_MIDI_StreamEvents)(HSTREAM handle, DWORD mode, const void *events, DWORD length);
+DWORD BASSMIDIDEF(BASS_MIDI_StreamGetEvent)(HSTREAM handle, DWORD chan, DWORD event);
+DWORD BASSMIDIDEF(BASS_MIDI_StreamGetEvents)(HSTREAM handle, int track, DWORD filter, BASS_MIDI_EVENT *events);
+DWORD BASSMIDIDEF(BASS_MIDI_StreamGetEventsEx)(HSTREAM handle, int track, DWORD filter, BASS_MIDI_EVENT *events, DWORD start, DWORD count);
+BOOL BASSMIDIDEF(BASS_MIDI_StreamGetPreset)(HSTREAM handle, DWORD chan, BASS_MIDI_FONT *font);
+HSTREAM BASSMIDIDEF(BASS_MIDI_StreamGetChannel)(HSTREAM handle, DWORD chan);
+BOOL BASSMIDIDEF(BASS_MIDI_StreamSetFilter)(HSTREAM handle, BOOL seeking, MIDIFILTERPROC *proc, void *user);
+
+HSOUNDFONT BASSMIDIDEF(BASS_MIDI_FontInit)(const void *file, DWORD flags);
+HSOUNDFONT BASSMIDIDEF(BASS_MIDI_FontInitUser)(const BASS_FILEPROCS *procs, void *user, DWORD flags);
+BOOL BASSMIDIDEF(BASS_MIDI_FontFree)(HSOUNDFONT handle);
+BOOL BASSMIDIDEF(BASS_MIDI_FontGetInfo)(HSOUNDFONT handle, BASS_MIDI_FONTINFO *info);
+BOOL BASSMIDIDEF(BASS_MIDI_FontGetPresets)(HSOUNDFONT handle, DWORD *presets);
+const char *BASSMIDIDEF(BASS_MIDI_FontGetPreset)(HSOUNDFONT handle, int preset, int bank);
+BOOL BASSMIDIDEF(BASS_MIDI_FontLoad)(HSOUNDFONT handle, int preset, int bank);
+BOOL BASSMIDIDEF(BASS_MIDI_FontLoadEx)(HSOUNDFONT handle, int preset, int bank, DWORD length, DWORD flags);
+BOOL BASSMIDIDEF(BASS_MIDI_FontUnload)(HSOUNDFONT handle, int preset, int bank);
+BOOL BASSMIDIDEF(BASS_MIDI_FontCompact)(HSOUNDFONT handle);
+BOOL BASSMIDIDEF(BASS_MIDI_FontPack)(HSOUNDFONT handle, const void *outfile, const void *encoder, DWORD flags);
+BOOL BASSMIDIDEF(BASS_MIDI_FontUnpack)(HSOUNDFONT handle, const void *outfile, DWORD flags);
+DWORD BASSMIDIDEF(BASS_MIDI_FontFlags)(HSOUNDFONT handle, DWORD flags, DWORD mask);
+BOOL BASSMIDIDEF(BASS_MIDI_FontSetVolume)(HSOUNDFONT handle, float volume);
+float BASSMIDIDEF(BASS_MIDI_FontGetVolume)(HSOUNDFONT handle);
+
+DWORD BASSMIDIDEF(BASS_MIDI_ConvertEvents)(const BYTE *data, DWORD length, BASS_MIDI_EVENT *events, DWORD count, DWORD flags);
+
+BOOL BASSMIDIDEF(BASS_MIDI_InGetDeviceInfo)(DWORD device, BASS_MIDI_DEVICEINFO *info);
+BOOL BASSMIDIDEF(BASS_MIDI_InInit)(DWORD device, MIDIINPROC *proc, void *user);
+BOOL BASSMIDIDEF(BASS_MIDI_InFree)(DWORD device);
+BOOL BASSMIDIDEF(BASS_MIDI_InStart)(DWORD device);
+BOOL BASSMIDIDEF(BASS_MIDI_InStop)(DWORD device);
+
+#ifdef __cplusplus
+}
+
+#ifndef NOBASSMIDIOVERLOADS
+static inline BOOL BASS_MIDI_StreamSetFonts(HSTREAM handle, const BASS_MIDI_FONTEX *fonts, DWORD count)
+{
+ return BASS_MIDI_StreamSetFonts(handle, (const void*)fonts, count | BASS_MIDI_FONT_EX);
+}
+
+static inline BOOL BASS_MIDI_StreamSetFonts(HSTREAM handle, const BASS_MIDI_FONTEX2 *fonts, DWORD count)
+{
+ return BASS_MIDI_StreamSetFonts(handle, (const void*)fonts, count | BASS_MIDI_FONT_EX2);
+}
+
+static inline DWORD BASS_MIDI_StreamGetFonts(HSTREAM handle, BASS_MIDI_FONTEX *fonts, DWORD count)
+{
+ return BASS_MIDI_StreamGetFonts(handle, (void*)fonts, count | BASS_MIDI_FONT_EX);
+}
+
+static inline DWORD BASS_MIDI_StreamGetFonts(HSTREAM handle, BASS_MIDI_FONTEX2 *fonts, DWORD count)
+{
+ return BASS_MIDI_StreamGetFonts(handle, (void*)fonts, count | BASS_MIDI_FONT_EX2);
+}
+
+#if __cplusplus >= 200707 || _MSC_VER >= 1600
+static inline DWORD BASS_MIDI_StreamGetFonts(HSTREAM handle, decltype(nullptr) fonts, DWORD count)
+{
+ return BASS_MIDI_StreamGetFonts(handle, (void*)fonts, count);
+}
+#endif
+
+#ifdef _WIN32
+static inline HSTREAM BASS_MIDI_StreamCreateFile(BOOL mem, const WCHAR *file, QWORD offset, QWORD length, DWORD flags, DWORD freq)
+{
+ return BASS_MIDI_StreamCreateFile(mem, (const void*)file, offset, length, flags | BASS_UNICODE, freq);
+}
+
+static inline HSTREAM BASS_MIDI_StreamCreateURL(const WCHAR *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user, DWORD freq)
+{
+ return BASS_MIDI_StreamCreateURL((const char*)url, offset, flags | BASS_UNICODE, proc, user, freq);
+}
+
+static inline HSOUNDFONT BASS_MIDI_FontInit(const WCHAR *file, DWORD flags)
+{
+ return BASS_MIDI_FontInit((const void*)file, flags|BASS_UNICODE);
+}
+
+static inline BOOL BASS_MIDI_FontPack(HSOUNDFONT handle, const WCHAR *outfile, const WCHAR *encoder, DWORD flags)
+{
+ return BASS_MIDI_FontPack(handle, (const void*)outfile, (const void*)encoder, flags | BASS_UNICODE);
+}
+
+static inline BOOL BASS_MIDI_FontUnpack(HSOUNDFONT handle, const WCHAR *outfile, DWORD flags)
+{
+ return BASS_MIDI_FontUnpack(handle, (const void*)outfile, flags | BASS_UNICODE);
+}
+#endif
+#endif
+#endif
+
+#ifdef __OBJC__
+#undef BOOL
+#endif
+
+#endif
diff --git a/bass/lib/bass.lib b/bass/lib/bass.lib
new file mode 100644
index 0000000..c69024a
Binary files /dev/null and b/bass/lib/bass.lib differ
diff --git a/bass/lib/bassmidi.lib b/bass/lib/bassmidi.lib
new file mode 100644
index 0000000..9e4947c
Binary files /dev/null and b/bass/lib/bassmidi.lib differ
diff --git a/bass/x64/bass.lib b/bass/x64/bass.lib
new file mode 100644
index 0000000..4e11da3
Binary files /dev/null and b/bass/x64/bass.lib differ
diff --git a/bass/x64/bassmidi.lib b/bass/x64/bassmidi.lib
new file mode 100644
index 0000000..acc16a1
Binary files /dev/null and b/bass/x64/bassmidi.lib differ
diff --git a/dxsdk3 b/dxsdk3
new file mode 160000
index 0000000..71f5b1c
--- /dev/null
+++ b/dxsdk3
@@ -0,0 +1 @@
+Subproject commit 71f5b1cb34ae2a215190b3aec87c3fc9646eb1d3
diff --git a/msvc5/msvc5.dsw b/msvc5/msvc5.dsw
new file mode 100644
index 0000000..d06524d
--- /dev/null
+++ b/msvc5/msvc5.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 5.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "sb2decomp"=".\sb2decomp\sb2decomp.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/msvc5/sb2decomp/sb2decomp.dsp b/msvc5/sb2decomp/sb2decomp.dsp
new file mode 100644
index 0000000..270ace2
--- /dev/null
+++ b/msvc5/sb2decomp/sb2decomp.dsp
@@ -0,0 +1,252 @@
+# Microsoft Developer Studio Project File - Name="sb2decomp" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=sb2decomp - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "sb2decomp.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "sb2decomp.mak" CFG="sb2decomp - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "sb2decomp - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "sb2decomp - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "sb2decomp - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /W3 /Gi /GX /O2 /I "..\..\dxsdk3\sdk\inc" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_X86_" /D WINVER=0x0400 /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ddraw.lib dsound.lib dplayx.lib dxguid.lib /nologo /subsystem:windows /machine:I386 /libpath:"..\..\dxsdk3\sdk\lib" /FORCE:MULTIPLE
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "sb2decomp - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /W3 /Gm /Gi /GX /Zi /Od /I "..\..\dxsdk3\sdk\inc" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_X86_" /D WINVER=0x0400 /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ddraw.lib dsound.lib dplayx.lib dxguid.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /libpath:"..\..\dxsdk3\sdk\lib" /FORCE:MULTIPLE
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "sb2decomp - Win32 Release"
+# Name "sb2decomp - Win32 Debug"
+# Begin Source File
+
+SOURCE=..\..\src\blupi.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\button.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\button.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\ddutil.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\ddutil.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\decblock.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\decblupi.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\decdesign.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\decio.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\decmove.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\decnet.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\decor.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\decor.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\dectables.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\def.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\event.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\event.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\jauge.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\jauge.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\menu.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\menu.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\misc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\misc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\movie.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\movie.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\network.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\network.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\obstacle.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\pixmap.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\pixmap.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\pixtables.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\resource1.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\sound.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\sound.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\text.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\text.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\texttables.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\wave.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\src\wave.h
+# End Source File
+# End Target
+# End Project
diff --git a/resource/Eggbert2.aps b/resource/Eggbert2.aps
new file mode 100644
index 0000000..0a412f3
Binary files /dev/null and b/resource/Eggbert2.aps differ
diff --git a/resource/Eggbert2.rc b/resource/Eggbert2.rc
new file mode 100644
index 0000000..1ad7d3c
Binary files /dev/null and b/resource/Eggbert2.rc differ
diff --git a/resource/IDC_ARROW.cur b/resource/IDC_ARROW.cur
new file mode 100644
index 0000000..d8d49b4
Binary files /dev/null and b/resource/IDC_ARROW.cur differ
diff --git a/resource/IDC_ARROWD.cur b/resource/IDC_ARROWD.cur
new file mode 100644
index 0000000..cb5c925
Binary files /dev/null and b/resource/IDC_ARROWD.cur differ
diff --git a/resource/IDC_ARROWDL.cur b/resource/IDC_ARROWDL.cur
new file mode 100644
index 0000000..80962d4
Binary files /dev/null and b/resource/IDC_ARROWDL.cur differ
diff --git a/resource/IDC_ARROWDR.cur b/resource/IDC_ARROWDR.cur
new file mode 100644
index 0000000..58ac867
Binary files /dev/null and b/resource/IDC_ARROWDR.cur differ
diff --git a/resource/IDC_ARROWL.cur b/resource/IDC_ARROWL.cur
new file mode 100644
index 0000000..c40f781
Binary files /dev/null and b/resource/IDC_ARROWL.cur differ
diff --git a/resource/IDC_ARROWR.cur b/resource/IDC_ARROWR.cur
new file mode 100644
index 0000000..ca8e1aa
Binary files /dev/null and b/resource/IDC_ARROWR.cur differ
diff --git a/resource/IDC_ARROWU.cur b/resource/IDC_ARROWU.cur
new file mode 100644
index 0000000..7390bf5
Binary files /dev/null and b/resource/IDC_ARROWU.cur differ
diff --git a/resource/IDC_ARROWUL.cur b/resource/IDC_ARROWUL.cur
new file mode 100644
index 0000000..f2356d4
Binary files /dev/null and b/resource/IDC_ARROWUL.cur differ
diff --git a/resource/IDC_ARROWUR.cur b/resource/IDC_ARROWUR.cur
new file mode 100644
index 0000000..bd28c66
Binary files /dev/null and b/resource/IDC_ARROWUR.cur differ
diff --git a/resource/IDC_EMPTY.cur b/resource/IDC_EMPTY.cur
new file mode 100644
index 0000000..0ac9262
Binary files /dev/null and b/resource/IDC_EMPTY.cur differ
diff --git a/resource/IDC_FILL.cur b/resource/IDC_FILL.cur
new file mode 100644
index 0000000..1c1b24b
Binary files /dev/null and b/resource/IDC_FILL.cur differ
diff --git a/resource/IDC_MAP.cur b/resource/IDC_MAP.cur
new file mode 100644
index 0000000..e270c4d
Binary files /dev/null and b/resource/IDC_MAP.cur differ
diff --git a/resource/IDC_POINTER.cur b/resource/IDC_POINTER.cur
new file mode 100644
index 0000000..aa9f335
Binary files /dev/null and b/resource/IDC_POINTER.cur differ
diff --git a/resource/IDC_WAIT.cur b/resource/IDC_WAIT.cur
new file mode 100644
index 0000000..55f7588
Binary files /dev/null and b/resource/IDC_WAIT.cur differ
diff --git a/resource/IDR_MAINFRAME.ico b/resource/IDR_MAINFRAME.ico
new file mode 100644
index 0000000..37360ff
Binary files /dev/null and b/resource/IDR_MAINFRAME.ico differ
diff --git a/resource/RCa07276 b/resource/RCa07276
new file mode 100644
index 0000000..3cba63e
Binary files /dev/null and b/resource/RCa07276 differ
diff --git a/resource/RCa07552 b/resource/RCa07552
new file mode 100644
index 0000000..ca64fbb
Binary files /dev/null and b/resource/RCa07552 differ
diff --git a/resource/RCa19860 b/resource/RCa19860
new file mode 100644
index 0000000..88a61d5
Binary files /dev/null and b/resource/RCa19860 differ
diff --git a/resource/RCb07276 b/resource/RCb07276
new file mode 100644
index 0000000..3cba63e
Binary files /dev/null and b/resource/RCb07276 differ
diff --git a/resource/RCb19860 b/resource/RCb19860
new file mode 100644
index 0000000..820cdfb
Binary files /dev/null and b/resource/RCb19860 differ
diff --git a/resource/RCc07276 b/resource/RCc07276
new file mode 100644
index 0000000..3cba63e
Binary files /dev/null and b/resource/RCc07276 differ
diff --git a/resource/RCc19860 b/resource/RCc19860
new file mode 100644
index 0000000..820cdfb
Binary files /dev/null and b/resource/RCc19860 differ
diff --git a/resource/RCd19860 b/resource/RCd19860
new file mode 100644
index 0000000..ec7aa27
Binary files /dev/null and b/resource/RCd19860 differ
diff --git a/resource/Resource.aps b/resource/Resource.aps
new file mode 100644
index 0000000..95a8f38
Binary files /dev/null and b/resource/Resource.aps differ
diff --git a/resource/arrow.cur b/resource/arrow.cur
new file mode 100644
index 0000000..d8d49b4
Binary files /dev/null and b/resource/arrow.cur differ
diff --git a/resource/arrowdl.cur b/resource/arrowdl.cur
new file mode 100644
index 0000000..80962d4
Binary files /dev/null and b/resource/arrowdl.cur differ
diff --git a/resource/arrowdow.cur b/resource/arrowdow.cur
new file mode 100644
index 0000000..cb5c925
Binary files /dev/null and b/resource/arrowdow.cur differ
diff --git a/resource/arrowdr.cur b/resource/arrowdr.cur
new file mode 100644
index 0000000..58ac867
Binary files /dev/null and b/resource/arrowdr.cur differ
diff --git a/resource/arrowlef.cur b/resource/arrowlef.cur
new file mode 100644
index 0000000..c40f781
Binary files /dev/null and b/resource/arrowlef.cur differ
diff --git a/resource/arrowrig.cur b/resource/arrowrig.cur
new file mode 100644
index 0000000..ca8e1aa
Binary files /dev/null and b/resource/arrowrig.cur differ
diff --git a/resource/arrowul.cur b/resource/arrowul.cur
new file mode 100644
index 0000000..f2356d4
Binary files /dev/null and b/resource/arrowul.cur differ
diff --git a/resource/arrowup.cur b/resource/arrowup.cur
new file mode 100644
index 0000000..7390bf5
Binary files /dev/null and b/resource/arrowup.cur differ
diff --git a/resource/arrowur.cur b/resource/arrowur.cur
new file mode 100644
index 0000000..bd28c66
Binary files /dev/null and b/resource/arrowur.cur differ
diff --git a/resource/blupi-d.aps b/resource/blupi-d.aps
new file mode 100644
index 0000000..6c9aa4a
Binary files /dev/null and b/resource/blupi-d.aps differ
diff --git a/resource/blupi-d.rc b/resource/blupi-d.rc
new file mode 100644
index 0000000..250bef8
--- /dev/null
+++ b/resource/blupi-d.rc
@@ -0,0 +1,489 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// French (Switzerland) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRS)
+#ifdef _WIN32
+LANGUAGE LANG_FRENCH, SUBLANG_FRENCH_SWISS
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDR_MAINFRAME ICON DISCARDABLE "blupi.ico"
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 0,4,0,0
+ PRODUCTVERSION 0,4,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "100c04b0"
+ BEGIN
+ VALUE "CompanyName", "EPSITEC\0"
+ VALUE "FileDescription", "Blupi\0"
+ VALUE "FileVersion", "0, 4, 0, 0\0"
+ VALUE "InternalName", "Planet Blupi\0"
+ VALUE "LegalCopyright", "Copyright 1997\0"
+ VALUE "OriginalFilename", "Blupi.exe\0"
+ VALUE "ProductName", "EPSITEC Planet Blupi\0"
+ VALUE "ProductVersion", "0, 4, 0, 0\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x100c, 1200
+ END
+END
+
+#endif // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Cursor
+//
+
+IDC_POINTER CURSOR DISCARDABLE "cursor1.cur"
+IDC_MAP CURSOR DISCARDABLE "map.cur"
+IDC_ARROWU CURSOR DISCARDABLE "arrowup.cur"
+IDC_ARROWD CURSOR DISCARDABLE "arrowdow.cur"
+IDC_ARROWL CURSOR DISCARDABLE "arrowlef.cur"
+IDC_ARROWR CURSOR DISCARDABLE "arrowrig.cur"
+IDC_ARROWUL CURSOR DISCARDABLE "arrowul.cur"
+IDC_ARROWUR CURSOR DISCARDABLE "arrowur.cur"
+IDC_ARROWDR CURSOR DISCARDABLE "arrowdr.cur"
+IDC_ARROWDL CURSOR DISCARDABLE "arrowdl.cur"
+IDC_WAIT CURSOR DISCARDABLE "wait.cur"
+IDC_EMPTY CURSOR DISCARDABLE "empty.cur"
+IDC_FILL CURSOR DISCARDABLE "fill.cur"
+IDC_ARROW CURSOR DISCARDABLE "arrow.cur"
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_ACTION_GO "Gehen"
+ TX_ACTION_STOP "Halt"
+ TX_ACTION_MANGE "Essen"
+ TX_ACTION_CARRY "Nehmen"
+ TX_ACTION_DEPOSE "Hinlegen"
+ TX_ACTION_ABAT "Baum fllen"
+ TX_ACTION_ROC "Stein bearbeiten"
+ TX_ACTION_CULTIVE "Garten anlegen"
+ TX_ACTION_BUILD1 "Gartenhuschen"
+ TX_ACTION_BUILD2 "Brutplatz"
+ TX_ACTION_BUILD3 "Labor"
+ TX_ACTION_BUILD4 "Bergwerk"
+ TX_ACTION_BUILD5 "Werkstatt"
+ TX_ACTION_BUILD6 "Beamgert"
+ TX_ACTION_MUR "Mauer"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_ACTION_PALIS "Palisade"
+ TX_ACTION_ABATn "Bume fllen"
+ TX_ACTION_ROCn "Steine bearbeiten"
+ TX_ACTION_PONT "Brcke"
+ TX_ACTION_TOUR "Wachturm"
+ TX_ACTION_BOIT "Trinken"
+ TX_ACTION_LABO "Verarbeiten"
+ TX_ACTION_FLEUR "Blumenstrauss machen"
+ TX_ACTION_FLEURn "Blumenstrusse machen"
+ TX_ACTION_DYNAMITE "Znden"
+ TX_ACTION_BATEAU "Boot"
+ TX_ACTION_DJEEP "Aussteigen"
+ TX_ACTION_DRAPEAU "Eisen suchen"
+ TX_ACTION_EXTRAIT "Eisen abbauen"
+ TX_ACTION_FABJEEP "Jeep bauen"
+ TX_ACTION_FABMINE "Zeitbombe bauen"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_ERROR_MISC "Hier nicht mglich"
+ TX_ERROR_GROUND "Untergrund nicht geeignet"
+ TX_ERROR_FREE "Untergrund schon besetzt"
+ TX_ERROR_PONTOP "Anderes Ufer nicht OK"
+ TX_ERROR_PONTTERM "Brcke schon fertig"
+ TX_ERROR_TOURISOL "(Alleinstehender Wachturm)"
+ TX_ERROR_TOUREAU "Zu nahe am Wasser"
+ TX_ERROR_TELE2 "Es gibt schon 2 Beammaschinen"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_IONAMEEX "Training %d, Zeit %d"
+ TX_IOFREE "frei"
+ TX_TERMMIN "Verloren sobald weniger als %d Blupis"
+ TX_TERMMAX "Gewinnen unmglich wenn weniger als %d Blupis"
+ TX_BUTTON_JOUER "Missionen"
+ TX_BUTTON_APPRENDRE "Training"
+ TX_BUTTON_QUITTER "BLUPI beenden"
+ TX_BUTTON_PREVP "Vorhergehende Mission"
+ TX_BUTTON_NEXTP "Nchste Mission"
+ TX_BUTTON_PLAYP "Diese Mission spielen"
+ TX_BUTTON_BUILDP "Diese Mission konstruieren"
+ TX_BUTTON_TERM "Beenden"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_BUTTON_READP "Gespeicherte Mission ffnen"
+ TX_BUTTON_WRITEP "Mission speichern"
+ TX_BUTTON_CANCELP "Mission aufgeben"
+ TX_BUTTON_CONTP "Mission weiterspielen"
+ TX_BUTTON_REPEAT "Neu Anfangen"
+ TX_BUTTON_BUTTON "Zur Verfgung stehende Knpfe"
+ TX_BUTTON_CTERM "Bedingungen fr Ende der Mission"
+ TX_BUTTON_TERMC "Konstruktion beenden"
+ TX_BUTTON_TERMHBLUPI "Blupi auf gestreiften Quadraten"
+ TX_BUTTON_TERMHPLANCHE "Bretter auf gestreiften Quadraten"
+ TX_BUTTON_TERMFIRE "Feuer ausgegangen"
+ TX_BUTTON_TERMDEC "(-)"
+ TX_BUTTON_TERMINC "(+)"
+ TX_PAUSE "Pause"
+ TX_JAUGE1 "Blupis Energie"
+ TX_JAUGE2 "Arbeitsfortschritt"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_BUTTON_SETUP "Einstellungen"
+ TX_BUTTON_MUSIC "Auswahl der Musik"
+ TX_BUTTON_SETUP1 "Langsamer"
+ TX_BUTTON_SETUP2 "Schneller"
+ TX_BUTTON_SETUP3 "Leiser"
+ TX_BUTTON_SETUP4 "Lauter"
+ TX_BUTTON_MUSIC1 "Keine Musik"
+ TX_BUTTON_MUSIC2 "Musik Nummer 1"
+ TX_BUTTON_MUSIC3 "Musik Nummer 2"
+ TX_BUTTON_MUSIC4 "Musik Nummer 3"
+ TX_BUTTON_MUSIC5 "Musik Nummer 4"
+ TX_BUTTON_MUSIC6 "Musik Nummer 5"
+ TX_BUTTON_MUSIC7 "Musik Nummer 6"
+ TX_BUTTON_MUSIC8 "Musik Nummer 7"
+ TX_BUTTON_MUSIC9 "Musik Nummer 8"
+ TX_BUTTON_MUSIC10 "Musik Nummer 9"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_BUTTON_REGION "Auswahl der Umgebung"
+ TX_BUTTON_TERMMBLUPI "Blupi im Haus"
+ TX_BUTTON_TERMKILL "Keine Feinde mehr"
+ TX_TERM "Bedingungen fr\ndas Ende der Mission"
+ TX_BUTTON "Zur Verfgung\nstehende Knpfe"
+ TX_MUSIC "Auswahl der Musik"
+ TX_SCHOOL "Training Nummer"
+ TX_MISSION "Mission Nummer"
+ TX_IONAMEMI "Mission %d, Zeit %d"
+ TX_BUTTON_TERMHTOMATE "Tomaten auf gestreiften Quadraten"
+ TX_BUTTON_SETUP5 "Leiser"
+ TX_BUTTON_SETUP6 "Lauter"
+ TX_BUTTON_SETUP7 "Keine Videosequenzen"
+ TX_BUTTON_SETUP8 "Zeigt die Videosequenzen"
+ TX_OUI "Ja"
+ TX_NON "Nein"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_OBJ_BLUPIm "Kranker Blupi"
+ TX_OBJ_BLUPIf "Erschpfter Blupi"
+ TX_OBJ_BLUPI "Blupi"
+ TX_OBJ_BATEAU "Boot"
+ TX_OBJ_JEEP "Jeep"
+ TX_OBJ_PIEGE "Klebefalle"
+ TX_OBJ_POISON "Gift"
+ TX_OBJ_DYNAMITE "Dynamitstangen"
+ TX_OBJ_MINE "Zeitbombe"
+ TX_OBJ_TOMATE "Tomaten"
+ TX_OBJ_POTION "Medikament"
+ TX_OBJ_PLANCHE "Bretter"
+ TX_OBJ_PIERRE "Steine"
+ TX_OBJ_DRAPEAU "Wimpel"
+ TX_OBJ_FER "Eisenerz"
+ TX_OBJ_FLEUR1 "Blumen"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_OBJ_FLEUR2 "Blumen"
+ TX_OBJ_FLEUR3 "Blumen"
+ TX_OBJ_CABANE "Gartenhuschen"
+ TX_OBJ_LABO "Labor"
+ TX_OBJ_MINEFER "Bergwerk"
+ TX_OBJ_USINE "Werkstatt"
+ TX_OBJ_TOUR "Wachturm"
+ TX_OBJ_FEU "Feuer"
+ TX_OBJ_ROBOT "Roboterchef"
+ TX_OBJ_TRACKS "Planierraupe"
+ TX_OBJ_BOMBE "Springende Bombe"
+ TX_OBJ_ARAIGNEE "Spinne"
+ TX_OBJ_VIRUS "Virus"
+ TX_OBJ_ELECTRO "Elektrisiermaschine"
+ TX_OBJ_ARBRE "Bume"
+ TX_OBJ_MUR "Mauer"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_OBJ_ARBREb "Baumstmme"
+ TX_OBJ_ROC "Felsen"
+ TX_OBJ_OEUF "Eier"
+ TX_OBJ_PALISSADE "Palisade"
+ TX_OBJ_ENNEMIp "Verklebter Feind"
+ TX_OBJ_ENNEMI "Feindliche Einrichtung"
+ TX_OBJ_HERBE "Normaler Untergrund"
+ TX_OBJ_MOUSSE "Brennbarer Untergrund"
+ TX_OBJ_TERRE "Karger Untergrund"
+ TX_OBJ_EAU "Wasser"
+ TX_OBJ_RIVE "Ufer"
+ TX_OBJ_MIXTE "Gemischter Untergrund"
+ TX_OBJ_PONT "Brcke"
+ TX_OBJ_COUVEUSE "Brutplatz"
+ TX_OBJ_GLACE "Eis"
+ TX_OBJ_MAISON "Blupis Haus"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_OBJ_HACHURE "Gestreifte Quadrate"
+ TX_OBJ_MOUSSEb "Verbrannter Untergrund"
+ TX_OBJ_BOUQUET1 "Blumenstrauss"
+ TX_OBJ_BOUQUET2 "Blumenstrauss"
+ TX_OBJ_BOUQUET3 "Blumenstrauss"
+ TX_OBJ_DALLE "Platten"
+ TX_OBJ_ENNEMIs "Feindesgrund"
+ TX_OBJ_DISCIPLE "Hilfsroboter"
+ TX_OBJ_METAL "Platinium"
+ TX_OBJ_FUSEE "Feindliche Rakete"
+ TX_OBJ_TELEPORTE "Beammaschine"
+ TX_OBJ_ARMURE "Rstung"
+ TX_OBJ_DALLESPEC "Spezialplatten"
+ TX_OBJ_COUVTELE "Brutplatz oder Beammaschine"
+ TX_OBJ_BATIMENT "Gebude"
+ TX_OBJ_BATENNEMIS "Feindliches Gebude"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_WIN1 "Toll, Du hast es geschafft"
+ TX_WIN2 "Ja, super"
+ TX_WIN3 "Sehr gut"
+ TX_WIN4 "Ausgezeichnet"
+ TX_WIN5 "Auftrag erfllt"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_LOST1 "Das war nichts, probier es noch einmal !"
+ TX_LOST2 "Nein, so geht das leider nicht !"
+ TX_LOST3 "Das war mal wieder nichts !"
+ TX_LOST4 "Das war leider nicht die richtige Lsung !"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_LOST5 "Aber nein, doch nicht so..."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_LASTWIN1 "Du kannst jetzt mit den Missionen beginnen."
+ TX_LASTWIN2 "Bravo, das Spiel ist beendet !"
+ TX_LASTWIN3 "Letzte konstruierte Mission beendet."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_BUTTON_SETUP9 "Langsamer"
+ TX_BUTTON_SETUP10 "Schneller"
+ TX_INFO_SETUP1 "Globale\nGeschwindigkeit\ndes Spiels"
+ TX_INFO_SETUP2 "Lautstrke der\nGeruscheffekte"
+ TX_INFO_SETUP3 "Lautstrke\nder Musik"
+ TX_INFO_SETUP4 "Videosequenzen"
+ TX_INFO_SETUP5 "Geschwindigkeit\nder Bildschirm-\nverschiebungen\nmit der Maus"
+ TX_INFO_NOSCROLL "Keine"
+ TX_BUTTON_REGION1 "Wiese"
+ TX_BUTTON_REGION2 "Wste"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_BUTTON_REGION3 "Verschneiter Wald"
+ TX_BUTTON_REGION4 "Wald"
+ TX_REGION "Auswahl\nder Umgebung"
+ TX_BUTTON_PLAY_STOP "Halt"
+ TX_BUTTON_PLAY_SETUP "Einstellungen"
+ TX_BUTTON_PLAY_WRITE "Speichern"
+ TX_INSERT "Fge die Planet Blupi CD-Rom in das Laufwerk ein und warte einige Sekunden ..."
+ TX_BUTTON_PREVH "Vorhergehende Seite"
+ TX_BUTTON_NEXTH "Nchste Seite"
+ TX_BUTTON_TERMHMETAL "Platinium auf gestreiften Quadraten"
+ TX_BUTTON_HELP "Hilfe"
+ TX_HELP "Hilfe Nummer"
+ TX_BUTTON_PRIVE "Konstruktion"
+ TX_PRIVATE "Konstruktion Nummer"
+ TX_IONAMEPR "Konstruktion %d, Zeit %d"
+ TX_PRIVATE_HACHBLUPI "1|Auf die gestreiften Quadrate gehen."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_ACTION_FABDISC "Roboter bauen"
+ TX_ACTION_REPEAT "Wiederholen"
+ TX_ACTION_QARMURE "Aussteigen"
+ TX_ACTION_FABARMURE "Rstung bauen"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_PRIVATE_HACHPLANCHE "1|Bretter auf die\n1|gestreiften Quadrate legen."
+ TX_PRIVATE_HACHTOMATE "1|Tomaten auf die\n1|gestreiften Quadrate legen."
+ TX_PRIVATE_HACHMETAL "1|Platinium auf die\n1|gestreiften Quadrate legen."
+ TX_PRIVATE_STOPFIRE "1|Solange berleben bis\n1|das Feuer ausgegangen ist."
+ TX_PRIVATE_HOMEBLUPI "1|Jeder Blupi\n1|in seinem Haus."
+ TX_PRIVATE_KILLROBOTS "1|Alle Feinde\n1|zerstren !"
+ TX_BUTTON_UNDO "Letzten Befehl rckgngig machen"
+ TX_DEMO_END1 "Sie haben soeben mit der DEMO Version von Planet Blupi gespielt."
+ TX_DEMO_END2 "Hoffentlich hatten Sie genau soviel Spass beim Spielen wie wir beim herstellen des Spiels !"
+ TX_DEMO_END3 "Dieses Spiel wurde entwickelt von Epsitec SA, CH-1092 Belmont"
+ TX_DEMO_END4 "http://www.blupi.com blupi@epsitec.ch"
+ TX_FULL_END1 "Sie haben soeben mit PLANET BLUPI gespielt."
+ TX_FULL_END2 "Hoffentlich hatten Sie genau soviel Spass beim Spielen wie wir beim herstellen des Spiels !"
+ TX_FULL_END3 "Herausgegeben von WG Verlag & Lizenzen AG"
+ TX_FULL_END4 "Entwickelt von EPSITEC SA"
+ TX_PRIVATE_OBJECTIF "1|Ziel :"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_PRIVATE_NBBLUPI "1|Die Blupibevlkerung muss mindestens %d Blupi(s) betragen."
+ TX_BUTTON_SKILL "Schwierigkeitsgrad"
+ TX_SKILL1 "Leicht"
+ TX_SKILL2 "Schwer"
+ TX_BUTTON_DEMO "Demo"
+ TX_DEMOREC "REC"
+ TX_DEMOPLAY "Demo"
+ TX_BUTTON_TERMHROBOT "Roboter auf gestreiften Quadraten"
+ TX_PRIVATE_HACHROBOT "1|Der Roboter muss die\n1|gestreiften Quadrate erreichen."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_REPEAT_CULTIVE "1: Tomaten anbauen...\n2: Essen"
+ TX_REPEAT_FLEUR "1: Blumenstrauss binden\n2: Verarbeiten"
+ TX_REPEAT_FLEURQ "1: Nehmen\n2: Verarbeiten"
+ TX_REPEAT_FABMINE "1: Eisen abbauen\n2: Zeitbombe bauen"
+ TX_REPEAT_FABJEEP "1: Eisen abbauen\n2: Jeep bauen"
+ TX_REPEAT_PALIS "1: Baum fllen\n2: Palissade bauen"
+ TX_REPEAT_PALISQ "1: Nehmen\n2: Palissade bauen"
+ TX_REPEAT_PONT "1: Baum fllen\n2: Brcke bauen"
+ TX_REPEAT_PONTQ "1: Nehmen\n2: Brcke bauen"
+ TX_REPEAT_BATEAU "1: Baum fllen\n2: Boot bauen"
+ TX_REPEAT_BATEAUQ "1: Bretter nehmen\n2: Boot bauen"
+ TX_REPEAT_FABARMURE "1: Eisen abbauen\n2: Rstung bauen"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_OBJ_MURPAL "Mauer oder Palissade"
+ TX_OBJ_OBJET "Gegenstnde"
+ TX_OBJ_ARME "Waffen"
+ TX_OBJ_VEHICULE "Transportmittel"
+ TX_OBJ_STARTFEU "Feuer"
+ TX_OBJ_DELOBJ "Gegenstand lschen"
+ TX_OBJ_DELPERSO "Figur lschen"
+ TX_OBJ_DELFEU "Feuer lschen"
+ TX_OBJ_PLANTE "Pflanzen"
+ TX_OBJ_BARENNEMIS "Feindlicher Zaun"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_DIRECT_N "N"
+ TX_DIRECT_S "S"
+ TX_DIRECT_E "O"
+ TX_DIRECT_O "W"
+END
+
+#endif // French (Switzerland) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/resource/blupi-e.aps b/resource/blupi-e.aps
new file mode 100644
index 0000000..f864504
Binary files /dev/null and b/resource/blupi-e.aps differ
diff --git a/resource/blupi-e.rc b/resource/blupi-e.rc
new file mode 100644
index 0000000..5b608b6
--- /dev/null
+++ b/resource/blupi-e.rc
@@ -0,0 +1,489 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// French (Switzerland) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRS)
+#ifdef _WIN32
+LANGUAGE LANG_FRENCH, SUBLANG_FRENCH_SWISS
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDR_MAINFRAME ICON DISCARDABLE "blupi.ico"
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 0,4,0,0
+ PRODUCTVERSION 0,4,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "100c04b0"
+ BEGIN
+ VALUE "CompanyName", "EPSITEC\0"
+ VALUE "FileDescription", "Blupi\0"
+ VALUE "FileVersion", "0, 4, 0, 0\0"
+ VALUE "InternalName", "Planet Blupi\0"
+ VALUE "LegalCopyright", "Copyright 1997\0"
+ VALUE "OriginalFilename", "Blupi.exe\0"
+ VALUE "ProductName", "EPSITEC Planet Blupi\0"
+ VALUE "ProductVersion", "0, 4, 0, 0\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x100c, 1200
+ END
+END
+
+#endif // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Cursor
+//
+
+IDC_POINTER CURSOR DISCARDABLE "cursor1.cur"
+IDC_MAP CURSOR DISCARDABLE "map.cur"
+IDC_ARROWU CURSOR DISCARDABLE "arrowup.cur"
+IDC_ARROWD CURSOR DISCARDABLE "arrowdow.cur"
+IDC_ARROWL CURSOR DISCARDABLE "arrowlef.cur"
+IDC_ARROWR CURSOR DISCARDABLE "arrowrig.cur"
+IDC_ARROWUL CURSOR DISCARDABLE "arrowul.cur"
+IDC_ARROWUR CURSOR DISCARDABLE "arrowur.cur"
+IDC_ARROWDR CURSOR DISCARDABLE "arrowdr.cur"
+IDC_ARROWDL CURSOR DISCARDABLE "arrowdl.cur"
+IDC_WAIT CURSOR DISCARDABLE "wait.cur"
+IDC_EMPTY CURSOR DISCARDABLE "empty.cur"
+IDC_FILL CURSOR DISCARDABLE "fill.cur"
+IDC_ARROW CURSOR DISCARDABLE "arrow.cur"
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_ACTION_GO "Go"
+ TX_ACTION_STOP "Stop"
+ TX_ACTION_MANGE "Eat"
+ TX_ACTION_CARRY "Take"
+ TX_ACTION_DEPOSE "Drop"
+ TX_ACTION_ABAT "Cut down a tree"
+ TX_ACTION_ROC "Carve a rock"
+ TX_ACTION_CULTIVE "Grow tomatoes"
+ TX_ACTION_BUILD1 "Garden shed"
+ TX_ACTION_BUILD2 "Incubator"
+ TX_ACTION_BUILD3 "Laboratory"
+ TX_ACTION_BUILD4 "Mine"
+ TX_ACTION_BUILD5 "Workshop"
+ TX_ACTION_BUILD6 "Teleporter"
+ TX_ACTION_MUR "Wall"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_ACTION_PALIS "Palisade"
+ TX_ACTION_ABATn "Cut down trees"
+ TX_ACTION_ROCn "Carve rocks"
+ TX_ACTION_PONT "Bridge"
+ TX_ACTION_TOUR "Protection tower"
+ TX_ACTION_BOIT "Drink"
+ TX_ACTION_LABO "Transform"
+ TX_ACTION_FLEUR "Make bunch of flowers"
+ TX_ACTION_FLEURn "Make bunches of flowers"
+ TX_ACTION_DYNAMITE "Blow up"
+ TX_ACTION_BATEAU "Boat"
+ TX_ACTION_DJEEP "Leave Jeep"
+ TX_ACTION_DRAPEAU "Prospect for iron"
+ TX_ACTION_EXTRAIT "Extract iron"
+ TX_ACTION_FABJEEP "Make a Jeep"
+ TX_ACTION_FABMINE "Make a time bomb"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_ERROR_MISC "Impossible"
+ TX_ERROR_GROUND "Inadequate ground"
+ TX_ERROR_FREE "Occupied ground"
+ TX_ERROR_PONTOP "Opposite bank no good"
+ TX_ERROR_PONTTERM "Bridge finished"
+ TX_ERROR_TOURISOL "(isolated tower)"
+ TX_ERROR_TOUREAU "Too close to water"
+ TX_ERROR_TELE2 "Already two teleporters"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_IONAMEEX "training %d, time %d"
+ TX_IOFREE "free slot"
+ TX_TERMMIN "Lost if less than %d Blupis"
+ TX_TERMMAX "Impossible to win if less than %d Blupis"
+ TX_BUTTON_JOUER "Missions"
+ TX_BUTTON_APPRENDRE "Training"
+ TX_BUTTON_QUITTER "Quit BLUPI"
+ TX_BUTTON_PREVP "Previous game"
+ TX_BUTTON_NEXTP "Next game"
+ TX_BUTTON_PLAYP "Play this game"
+ TX_BUTTON_BUILDP "Construct this game"
+ TX_BUTTON_TERM "Finish"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_BUTTON_READP "Open another game "
+ TX_BUTTON_WRITEP "Save this game"
+ TX_BUTTON_CANCELP "Quit this game"
+ TX_BUTTON_CONTP "Continue this game"
+ TX_BUTTON_REPEAT "Restart this game"
+ TX_BUTTON_BUTTON "Available buttons"
+ TX_BUTTON_CTERM "Ending conditions"
+ TX_BUTTON_TERMC "Quit construction"
+ TX_BUTTON_TERMHBLUPI "Blupi on striped paving stones"
+ TX_BUTTON_TERMHPLANCHE "Planks on striped paving stones"
+ TX_BUTTON_TERMFIRE "Fire out"
+ TX_BUTTON_TERMDEC "(-)"
+ TX_BUTTON_TERMINC "(+)"
+ TX_PAUSE "Game paused"
+ TX_JAUGE1 "Blupi's energy"
+ TX_JAUGE2 "Work done"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_BUTTON_SETUP "Settings"
+ TX_BUTTON_MUSIC "Music choice"
+ TX_BUTTON_SETUP1 "Slower"
+ TX_BUTTON_SETUP2 "Faster"
+ TX_BUTTON_SETUP3 "Reduce volume"
+ TX_BUTTON_SETUP4 "Increase volume"
+ TX_BUTTON_MUSIC1 "No music"
+ TX_BUTTON_MUSIC2 "Music number 1"
+ TX_BUTTON_MUSIC3 "Music number 2"
+ TX_BUTTON_MUSIC4 "Music number 3"
+ TX_BUTTON_MUSIC5 "Music number 4"
+ TX_BUTTON_MUSIC6 "Music number 5"
+ TX_BUTTON_MUSIC7 "Music number 6"
+ TX_BUTTON_MUSIC8 "Music number 7"
+ TX_BUTTON_MUSIC9 "Music number 8"
+ TX_BUTTON_MUSIC10 "Music number 9"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_BUTTON_REGION "Scenery choice"
+ TX_BUTTON_TERMMBLUPI "Blupi in house"
+ TX_BUTTON_TERMKILL "No more enemies"
+ TX_TERM "Ending conditions"
+ TX_BUTTON "Available buttons"
+ TX_MUSIC "Music choice"
+ TX_SCHOOL "Training number"
+ TX_MISSION "Mission number"
+ TX_IONAMEMI "mission %d, time %d"
+ TX_BUTTON_TERMHTOMATE "Tomatoes on striped paving stones"
+ TX_BUTTON_SETUP5 "Reduce volume"
+ TX_BUTTON_SETUP6 "Increase volume"
+ TX_BUTTON_SETUP7 "No video"
+ TX_BUTTON_SETUP8 "Show videos"
+ TX_OUI "Yes"
+ TX_NON "No"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_OBJ_BLUPIm "Sick Blupi"
+ TX_OBJ_BLUPIf "Tired Blupi"
+ TX_OBJ_BLUPI "Blupi"
+ TX_OBJ_BATEAU "Boat"
+ TX_OBJ_JEEP "Jeep"
+ TX_OBJ_PIEGE "Sticky trap"
+ TX_OBJ_POISON "Poison"
+ TX_OBJ_DYNAMITE "Dynamite"
+ TX_OBJ_MINE "Time bomb"
+ TX_OBJ_TOMATE "Tomatoes"
+ TX_OBJ_POTION "Medical potion"
+ TX_OBJ_PLANCHE "Planks"
+ TX_OBJ_PIERRE "Stones"
+ TX_OBJ_DRAPEAU "Flag"
+ TX_OBJ_FER "Iron"
+ TX_OBJ_FLEUR1 "Flowers"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_OBJ_FLEUR2 "Flowers"
+ TX_OBJ_FLEUR3 "Flowers"
+ TX_OBJ_CABANE "Garden shed"
+ TX_OBJ_LABO "Laboratory"
+ TX_OBJ_MINEFER "Mine"
+ TX_OBJ_USINE "Workshop"
+ TX_OBJ_TOUR "Protection tower"
+ TX_OBJ_FEU "Fire"
+ TX_OBJ_ROBOT "Master robot"
+ TX_OBJ_TRACKS "Bulldozer"
+ TX_OBJ_BOMBE "Bouncing bomb"
+ TX_OBJ_ARAIGNEE "Spider"
+ TX_OBJ_VIRUS "Virus"
+ TX_OBJ_ELECTRO "Electrocutor"
+ TX_OBJ_ARBRE "Tree"
+ TX_OBJ_MUR "Wall"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_OBJ_ARBREb "Tree trunks"
+ TX_OBJ_ROC "Rocks"
+ TX_OBJ_OEUF "Eggs"
+ TX_OBJ_PALISSADE "Palisade"
+ TX_OBJ_ENNEMIp "Trapped enemy"
+ TX_OBJ_ENNEMI "Enemy construction"
+ TX_OBJ_HERBE "Normal ground"
+ TX_OBJ_MOUSSE "Inflammable ground"
+ TX_OBJ_TERRE "Sterile ground"
+ TX_OBJ_EAU "Water"
+ TX_OBJ_RIVE "Bank"
+ TX_OBJ_MIXTE "Miscellaneous ground"
+ TX_OBJ_PONT "Bridge"
+ TX_OBJ_COUVEUSE "Incubator"
+ TX_OBJ_GLACE "Ice"
+ TX_OBJ_MAISON "Blupi's house"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_OBJ_HACHURE "Striped paving stones"
+ TX_OBJ_MOUSSEb "Burnt ground"
+ TX_OBJ_BOUQUET1 "Bunch of flowers"
+ TX_OBJ_BOUQUET2 "Bunch of flowers"
+ TX_OBJ_BOUQUET3 "Bunch of flowers"
+ TX_OBJ_DALLE "Paving stones"
+ TX_OBJ_ENNEMIs "Enemy ground "
+ TX_OBJ_DISCIPLE "Helper robot"
+ TX_OBJ_METAL "Platinium"
+ TX_OBJ_FUSEE "Enemy rocket"
+ TX_OBJ_TELEPORTE "Teleporter"
+ TX_OBJ_ARMURE "Armour"
+ TX_OBJ_DALLESPEC "Special pavings"
+ TX_OBJ_COUVTELE "Incubator or teleporter"
+ TX_OBJ_BATIMENT "Buildings"
+ TX_OBJ_BATENNEMIS "Enemy buildings"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_WIN1 "Well done !"
+ TX_WIN2 "Yes, great ..."
+ TX_WIN3 "Very good."
+ TX_WIN4 "Excellent..."
+ TX_WIN5 "Mission over..."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_LOST1 "You have failed, try again..."
+ TX_LOST2 "No, wrong way ..."
+ TX_LOST3 "Bang, failed again !"
+ TX_LOST4 "Another mistake..."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_LOST5 "No, not that way !"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_LASTWIN1 "Now go on mission."
+ TX_LASTWIN2 "Very good, success on all missions !"
+ TX_LASTWIN3 "Last construction resolved !"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_BUTTON_SETUP9 "Slower"
+ TX_BUTTON_SETUP10 "Faster"
+ TX_INFO_SETUP1 "Global game\nspeed"
+ TX_INFO_SETUP2 "Sound effect\nvolume"
+ TX_INFO_SETUP3 "Music\nvolume"
+ TX_INFO_SETUP4 "Video\nsequences"
+ TX_INFO_SETUP5 "Scroll speed\nwith mouse"
+ TX_INFO_NOSCROLL "None"
+ TX_BUTTON_REGION1 "Prairie"
+ TX_BUTTON_REGION2 "Desert"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_BUTTON_REGION3 "Forest under snow"
+ TX_BUTTON_REGION4 "Forest"
+ TX_REGION "Scenery choice"
+ TX_BUTTON_PLAY_STOP "Interrupt"
+ TX_BUTTON_PLAY_SETUP "Settings"
+ TX_BUTTON_PLAY_WRITE "Save"
+ TX_INSERT "Insert CD-Rom Planet Blupi and wait a few seconds..."
+ TX_BUTTON_PREVH "Previous page"
+ TX_BUTTON_NEXTH "Next page"
+ TX_BUTTON_TERMHMETAL "Platinium on striped paving stones"
+ TX_BUTTON_HELP "Help"
+ TX_HELP "Help number"
+ TX_BUTTON_PRIVE "Construction"
+ TX_PRIVATE "Construction number"
+ TX_IONAMEPR "Construction %d, time %d"
+ TX_PRIVATE_HACHBLUPI "1|Go on striped\n1| paving stones."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_ACTION_FABDISC "Make a helper robot"
+ TX_ACTION_REPEAT "Repeat"
+ TX_ACTION_QARMURE "Quit"
+ TX_ACTION_FABARMURE "Make armour"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_PRIVATE_HACHPLANCHE "1|Drop planks on striped \n1|paving stones."
+ TX_PRIVATE_HACHTOMATE "1|Drop tomatoes on striped \n1|paving stones."
+ TX_PRIVATE_HACHMETAL "1|Drop platinium on striped \n1|paving stones."
+ TX_PRIVATE_STOPFIRE "1|Resist until\n1|fire extinction ..."
+ TX_PRIVATE_HOMEBLUPI "1|Each Blupi in\n1|his house."
+ TX_PRIVATE_KILLROBOTS "1|Kill all\n1|enemies !"
+ TX_BUTTON_UNDO "Cancel last operation"
+ TX_DEMO_END1 "You have played the DEMO version of Planet Blupi."
+ TX_DEMO_END2 "We hope you have had as much fun playing the game as we had making it !"
+ TX_DEMO_END3 "This game is an original creation of EPSITEC SA, CH-1092 Belmont"
+ TX_DEMO_END4 "http://www.blupi.com blupi@epsitec.ch"
+ TX_FULL_END1 "You have played Planet Blupi."
+ TX_FULL_END2 "We hope you have had as much fun playing the game as we had making it !"
+ TX_FULL_END3 "This game is an original creation of EPSITEC SA, CH-1092 Belmont"
+ TX_FULL_END4 "http://www.blupi.com blupi@epsitec.ch"
+ TX_PRIVATE_OBJECTIF "1|Goal :"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_PRIVATE_NBBLUPI "1|The Blupi population must \n1|be of at least %d Blupis."
+ TX_BUTTON_SKILL "Skill level"
+ TX_SKILL1 "Easy"
+ TX_SKILL2 "Difficult"
+ TX_BUTTON_DEMO "Demo"
+ TX_DEMOREC "REC"
+ TX_DEMOPLAY "Demo"
+ TX_BUTTON_TERMHROBOT "Robot on striped paving stones"
+ TX_PRIVATE_HACHROBOT "1|The robot must reach\n1|the striped paving stones."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_REPEAT_CULTIVE "1: Grow tomatoes\n2: Eat"
+ TX_REPEAT_FLEUR "1: Make a bunch\n2: Transform"
+ TX_REPEAT_FLEURQ "1: Take\n2: Transform"
+ TX_REPEAT_FABMINE "1: Extract iron\n2: Make a bomb"
+ TX_REPEAT_FABJEEP "1: Extract iron\n2: Make a Jeep"
+ TX_REPEAT_PALIS "1: Cut down a tree \n2: Make a palisade"
+ TX_REPEAT_PALISQ "1: Take\n2: Build palisade"
+ TX_REPEAT_PONT "1: Cut down a tree \n2: Build a bridge"
+ TX_REPEAT_PONTQ "1: Take\n2: Build a bridge"
+ TX_REPEAT_BATEAU "1: Cut down a tree \n2: Make a boat"
+ TX_REPEAT_BATEAUQ "1: Take\n2: Make a boat"
+ TX_REPEAT_FABARMURE "1: Extract iron\n2: Make an armour"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_OBJ_MURPAL "Wall or palisade"
+ TX_OBJ_OBJET "Items"
+ TX_OBJ_ARME "Weapons"
+ TX_OBJ_VEHICULE "Transport"
+ TX_OBJ_STARTFEU "Starting fire"
+ TX_OBJ_DELOBJ "Delete item"
+ TX_OBJ_DELPERSO "Delete figure"
+ TX_OBJ_DELFEU "Delete fire"
+ TX_OBJ_PLANTE "Decorative plants"
+ TX_OBJ_BARENNEMIS "Enemy barrier"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_DIRECT_N "N"
+ TX_DIRECT_S "S"
+ TX_DIRECT_E "E"
+ TX_DIRECT_O "W"
+END
+
+#endif // French (Switzerland) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/resource/blupi-f.aps b/resource/blupi-f.aps
new file mode 100644
index 0000000..e29e922
Binary files /dev/null and b/resource/blupi-f.aps differ
diff --git a/resource/blupi-f.rc b/resource/blupi-f.rc
new file mode 100644
index 0000000..d35e46e
--- /dev/null
+++ b/resource/blupi-f.rc
@@ -0,0 +1,489 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// French (Switzerland) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRS)
+#ifdef _WIN32
+LANGUAGE LANG_FRENCH, SUBLANG_FRENCH_SWISS
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDR_MAINFRAME ICON DISCARDABLE "blupi.ico"
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 0,4,0,0
+ PRODUCTVERSION 0,4,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "100c04b0"
+ BEGIN
+ VALUE "CompanyName", "EPSITEC\0"
+ VALUE "FileDescription", "Blupi\0"
+ VALUE "FileVersion", "0, 4, 0, 0\0"
+ VALUE "InternalName", "Planet Blupi\0"
+ VALUE "LegalCopyright", "Copyright 1997\0"
+ VALUE "OriginalFilename", "Blupi.exe\0"
+ VALUE "ProductName", "EPSITEC Planet Blupi\0"
+ VALUE "ProductVersion", "0, 4, 0, 0\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x100c, 1200
+ END
+END
+
+#endif // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Cursor
+//
+
+IDC_POINTER CURSOR DISCARDABLE "cursor1.cur"
+IDC_MAP CURSOR DISCARDABLE "map.cur"
+IDC_ARROWU CURSOR DISCARDABLE "arrowup.cur"
+IDC_ARROWD CURSOR DISCARDABLE "arrowdow.cur"
+IDC_ARROWL CURSOR DISCARDABLE "arrowlef.cur"
+IDC_ARROWR CURSOR DISCARDABLE "arrowrig.cur"
+IDC_ARROWUL CURSOR DISCARDABLE "arrowul.cur"
+IDC_ARROWUR CURSOR DISCARDABLE "arrowur.cur"
+IDC_ARROWDR CURSOR DISCARDABLE "arrowdr.cur"
+IDC_ARROWDL CURSOR DISCARDABLE "arrowdl.cur"
+IDC_WAIT CURSOR DISCARDABLE "wait.cur"
+IDC_EMPTY CURSOR DISCARDABLE "empty.cur"
+IDC_FILL CURSOR DISCARDABLE "fill.cur"
+IDC_ARROW CURSOR DISCARDABLE "arrow.cur"
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_ACTION_GO "Va"
+ TX_ACTION_STOP "Stoppe"
+ TX_ACTION_MANGE "Mange"
+ TX_ACTION_CARRY "Prend"
+ TX_ACTION_DEPOSE "Dpose"
+ TX_ACTION_ABAT "Abat un arbre"
+ TX_ACTION_ROC "Taille un rocher"
+ TX_ACTION_CULTIVE "Cultive un jardin"
+ TX_ACTION_BUILD1 "Cabane de jardin"
+ TX_ACTION_BUILD2 "Couveuse"
+ TX_ACTION_BUILD3 "Laboratoire"
+ TX_ACTION_BUILD4 "Mine de fer"
+ TX_ACTION_BUILD5 "Usine"
+ TX_ACTION_BUILD6 "Tlporteur"
+ TX_ACTION_MUR "Mur anti-feu"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_ACTION_PALIS "Palissade"
+ TX_ACTION_ABATn "Abat des arbres"
+ TX_ACTION_ROCn "Taille des rochers"
+ TX_ACTION_PONT "Pont"
+ TX_ACTION_TOUR "Tour de protection"
+ TX_ACTION_BOIT "Boit"
+ TX_ACTION_LABO "Transforme"
+ TX_ACTION_FLEUR "Fait un bouquet"
+ TX_ACTION_FLEURn "Fait des bouquets"
+ TX_ACTION_DYNAMITE "Explose"
+ TX_ACTION_BATEAU "Bateau"
+ TX_ACTION_DJEEP "Descend"
+ TX_ACTION_DRAPEAU "Cherche du fer"
+ TX_ACTION_EXTRAIT "Extrait du fer"
+ TX_ACTION_FABJEEP "Farbique une jeep"
+ TX_ACTION_FABMINE "Fabrique une bombe"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_ERROR_MISC "Impossible ici"
+ TX_ERROR_GROUND "Terrain pas adapt"
+ TX_ERROR_FREE "Terrain occup"
+ TX_ERROR_PONTOP "Autre rive pas ok"
+ TX_ERROR_PONTTERM "Pont termin"
+ TX_ERROR_TOURISOL "(tour isole)"
+ TX_ERROR_TOUREAU "Trop prs de l'eau"
+ TX_ERROR_TELE2 "Dj 2 tlporteurs"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_IONAMEEX "entranement %d, temps %d"
+ TX_IOFREE "libre"
+ TX_TERMMIN "Perdu si moins de %d blupi"
+ TX_TERMMAX "Impossible de gagner si moins de %d blupi"
+ TX_BUTTON_JOUER "Missions"
+ TX_BUTTON_APPRENDRE "Entranement"
+ TX_BUTTON_QUITTER "Quitter BLUPI"
+ TX_BUTTON_PREVP "Partie prcdente"
+ TX_BUTTON_NEXTP "Partie suivante"
+ TX_BUTTON_PLAYP "Jouer cette partie"
+ TX_BUTTON_BUILDP "Construire cette partie"
+ TX_BUTTON_TERM "Terminer"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_BUTTON_READP "Ouvrir une autre partie"
+ TX_BUTTON_WRITEP "Enregistrer la partie en cours"
+ TX_BUTTON_CANCELP "Abandonner la partie"
+ TX_BUTTON_CONTP "Continuer la partie"
+ TX_BUTTON_REPEAT "Recommencer"
+ TX_BUTTON_BUTTON "Boutons disponibles"
+ TX_BUTTON_CTERM "Conditions de fin"
+ TX_BUTTON_TERMC "Terminer la construction"
+ TX_BUTTON_TERMHBLUPI "Blupi sur dalles hachures"
+ TX_BUTTON_TERMHPLANCHE "Planches sur dalles hachures"
+ TX_BUTTON_TERMFIRE "Feu stopp"
+ TX_BUTTON_TERMDEC "(-)"
+ TX_BUTTON_TERMINC "(+)"
+ TX_PAUSE "Partie interrompue"
+ TX_JAUGE1 "Energie de Blupi"
+ TX_JAUGE2 "Travail en cours"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_BUTTON_SETUP "Rglages"
+ TX_BUTTON_MUSIC "Choix de la musique"
+ TX_BUTTON_SETUP1 "Diminue la vitesse"
+ TX_BUTTON_SETUP2 "Augmente la vitesse"
+ TX_BUTTON_SETUP3 "Diminue le volume"
+ TX_BUTTON_SETUP4 "Augmente le volume"
+ TX_BUTTON_MUSIC1 "Pas de musique"
+ TX_BUTTON_MUSIC2 "Musique numro 1"
+ TX_BUTTON_MUSIC3 "Musique numro 2"
+ TX_BUTTON_MUSIC4 "Musique numro 3"
+ TX_BUTTON_MUSIC5 "Musique numro 4"
+ TX_BUTTON_MUSIC6 "Musique numro 5"
+ TX_BUTTON_MUSIC7 "Musique numro 6"
+ TX_BUTTON_MUSIC8 "Musique numro 7"
+ TX_BUTTON_MUSIC9 "Musique numro 8"
+ TX_BUTTON_MUSIC10 "Musique numro 9"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_BUTTON_REGION "Choix des dcors"
+ TX_BUTTON_TERMMBLUPI "Blupi dans sa maison"
+ TX_BUTTON_TERMKILL "Plus d'ennemis"
+ TX_TERM "Conditions de fin"
+ TX_BUTTON "Boutons disponibles"
+ TX_MUSIC "Choix des musiques"
+ TX_SCHOOL "Entranement numro"
+ TX_MISSION "Mission numro"
+ TX_IONAMEMI "mission %d, temps %d"
+ TX_BUTTON_TERMHTOMATE "Tomates sur dalles hachures"
+ TX_BUTTON_SETUP5 "Diminue le volume"
+ TX_BUTTON_SETUP6 "Augmente le volume"
+ TX_BUTTON_SETUP7 "Pas de vido"
+ TX_BUTTON_SETUP8 "Montre les vidos"
+ TX_OUI "Oui"
+ TX_NON "Non"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_OBJ_BLUPIm "Blupi malade"
+ TX_OBJ_BLUPIf "Blupi fatigu"
+ TX_OBJ_BLUPI "Blupi"
+ TX_OBJ_BATEAU "Bateau"
+ TX_OBJ_JEEP "Jeep"
+ TX_OBJ_PIEGE "Pige glu"
+ TX_OBJ_POISON "Poison"
+ TX_OBJ_DYNAMITE "Dynamite"
+ TX_OBJ_MINE "Bombe retardement"
+ TX_OBJ_TOMATE "Tomates"
+ TX_OBJ_POTION "Potion"
+ TX_OBJ_PLANCHE "Planches"
+ TX_OBJ_PIERRE "Pierres"
+ TX_OBJ_DRAPEAU "Drapeau"
+ TX_OBJ_FER "Minerai de fer"
+ TX_OBJ_FLEUR1 "Fleurs"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_OBJ_FLEUR2 "Fleurs"
+ TX_OBJ_FLEUR3 "Fleurs"
+ TX_OBJ_CABANE "Cabane de jardin"
+ TX_OBJ_LABO "Laboratoire"
+ TX_OBJ_MINEFER "Mine de fer"
+ TX_OBJ_USINE "Usine"
+ TX_OBJ_TOUR "Tour de protection"
+ TX_OBJ_FEU "Feu"
+ TX_OBJ_ROBOT "Robot-matre"
+ TX_OBJ_TRACKS "Bulldozer"
+ TX_OBJ_BOMBE "Bombe sauteuse"
+ TX_OBJ_ARAIGNEE "Araigne"
+ TX_OBJ_VIRUS "Virus"
+ TX_OBJ_ELECTRO "Electrocuteur"
+ TX_OBJ_ARBRE "Arbres"
+ TX_OBJ_MUR "Mur anti-feu"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_OBJ_ARBREb "Troncs"
+ TX_OBJ_ROC "Rochers"
+ TX_OBJ_OEUF "Oeufs"
+ TX_OBJ_PALISSADE "Palissade"
+ TX_OBJ_ENNEMIp "Ennemi pig"
+ TX_OBJ_ENNEMI "Construction ennemie"
+ TX_OBJ_HERBE "Sol normal"
+ TX_OBJ_MOUSSE "Sol inflammable"
+ TX_OBJ_TERRE "Sol improductif"
+ TX_OBJ_EAU "Eau"
+ TX_OBJ_RIVE "Rive"
+ TX_OBJ_MIXTE "Sol mixte"
+ TX_OBJ_PONT "Pont"
+ TX_OBJ_COUVEUSE "Couveuse"
+ TX_OBJ_GLACE "Glace"
+ TX_OBJ_MAISON "Maison de blupi"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_OBJ_HACHURE "Dalles hachures"
+ TX_OBJ_MOUSSEb "Mousse brle"
+ TX_OBJ_BOUQUET1 "Bouquet de fleurs"
+ TX_OBJ_BOUQUET2 "Bouquet de fleurs"
+ TX_OBJ_BOUQUET3 "Bouquet de fleurs"
+ TX_OBJ_DALLE "Dalles"
+ TX_OBJ_ENNEMIs "Sol ennemi"
+ TX_OBJ_DISCIPLE "Robot-aide"
+ TX_OBJ_METAL "Platinium"
+ TX_OBJ_FUSEE "Fuse ennemie"
+ TX_OBJ_TELEPORTE "Tlporteur"
+ TX_OBJ_ARMURE "Armure"
+ TX_OBJ_DALLESPEC "Dalles spciales"
+ TX_OBJ_COUVTELE "Couveuse ou tlporteur"
+ TX_OBJ_BATIMENT "Btiments"
+ TX_OBJ_BATENNEMIS "Btiments ennemis"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_WIN1 "Bravo, c'est russi !"
+ TX_WIN2 "Oui, super ..."
+ TX_WIN3 "Trs bien."
+ TX_WIN4 "Magnifique, excellent ..."
+ TX_WIN5 "Mission accomplie."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_LOST1 "C'est rat, essaie encore une fois"
+ TX_LOST2 "Et non, ce n'est pas a ..."
+ TX_LOST3 "Paf, c'est rat !"
+ TX_LOST4 "Caramba, encore rat ..."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_LOST5 "Mais non, pas comme a !"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_LASTWIN1 "Passe maintenant aux missions."
+ TX_LASTWIN2 "Magnifique, le jeu est termin !"
+ TX_LASTWIN3 "Dernire construction rsolue !"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_BUTTON_SETUP9 "Diminue la vitesse"
+ TX_BUTTON_SETUP10 "Augmente la vitesse"
+ TX_INFO_SETUP1 "Vitesse globale\ndu jeu"
+ TX_INFO_SETUP2 "Volume\ndes bruitages"
+ TX_INFO_SETUP3 "Volume\ndes musiques"
+ TX_INFO_SETUP4 "Squences\nvido"
+ TX_INFO_SETUP5 "Vitesse\ndes dcalages\navec la souris"
+ TX_INFO_NOSCROLL "Aucun"
+ TX_BUTTON_REGION1 "Prairie"
+ TX_BUTTON_REGION2 "Dsert"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_BUTTON_REGION3 "Fort enneige"
+ TX_BUTTON_REGION4 "Fort"
+ TX_REGION "Choix de la rgion"
+ TX_BUTTON_PLAY_STOP "Interrompre"
+ TX_BUTTON_PLAY_SETUP "Rglages"
+ TX_BUTTON_PLAY_WRITE "Enregistrer"
+ TX_INSERT "Veuillez insrer le CD-Rom Plante Blupi, puis attendre quelques secondes ..."
+ TX_BUTTON_PREVH "Page prcdente"
+ TX_BUTTON_NEXTH "Page suivante"
+ TX_BUTTON_TERMHMETAL "Platinium sur dalles hachures"
+ TX_BUTTON_HELP "Aide"
+ TX_HELP "Aide numro"
+ TX_BUTTON_PRIVE "Construction"
+ TX_PRIVATE "Construction numro"
+ TX_IONAMEPR "construction %d, temps %d"
+ TX_PRIVATE_HACHBLUPI "1|Aller sur les dalles\n1|hachures."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_ACTION_FABDISC "Fabrique un robot"
+ TX_ACTION_REPEAT "Rpte"
+ TX_ACTION_QARMURE "Quitte"
+ TX_ACTION_FABARMURE "Fabrique une armure"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_PRIVATE_HACHPLANCHE "1|Dposer des planches\n1|sur les dalles hachures."
+ TX_PRIVATE_HACHTOMATE "1|Dposer des tomates\n1|sur les dalles hachures."
+ TX_PRIVATE_HACHMETAL "1|Dposer du platinium\n1|sur les dalles hachures."
+ TX_PRIVATE_STOPFIRE "1|Rsister jusqu'\n1|l'extinction du feu ..."
+ TX_PRIVATE_HOMEBLUPI "1|Chaque Blupi dans\n1|sa maison."
+ TX_PRIVATE_KILLROBOTS "1|Supprimer tous les\n1|ennemis !"
+ TX_BUTTON_UNDO "Annuler la dernire opration"
+ TX_DEMO_END1 "Vous avez jou la version DEMO de Plante Blupi."
+ TX_DEMO_END2 "Nous esprons que vous avez eu autant de plaisir y jouer que nous le raliser !"
+ TX_DEMO_END3 "Ce jeu est une cration originale d'EPSITEC SA, CH-1092 Belmont"
+ TX_DEMO_END4 "http://www.blupi.com blupi@epsitec.ch"
+ TX_FULL_END1 "Vous avez jou Plante Blupi."
+ TX_FULL_END2 "Nous esprons que vous avez eu autant de plaisir y jouer que nous le raliser !"
+ TX_FULL_END3 "Ce jeu est une cration originale d'EPSITEC SA, CH-1092 Belmont"
+ TX_FULL_END4 "http://www.blupi.com blupi@epsitec.ch"
+ TX_PRIVATE_OBJECTIF "1|Objectif :"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_PRIVATE_NBBLUPI "1|La population doit tre\n1|d'au moins %d Blupi."
+ TX_BUTTON_SKILL "Niveau de difficult"
+ TX_SKILL1 "Facile"
+ TX_SKILL2 "Difficile"
+ TX_BUTTON_DEMO "Dmo"
+ TX_DEMOREC "REC"
+ TX_DEMOPLAY "Dmo"
+ TX_BUTTON_TERMHROBOT "Robot sur dalles hachures"
+ TX_PRIVATE_HACHROBOT "1|Le robot doit atteindre\n1|les dalles hachures."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_REPEAT_CULTIVE "1: Cultive ...\n2: Mange"
+ TX_REPEAT_FLEUR "1: Fait un bouquet\n2: Transforme"
+ TX_REPEAT_FLEURQ "1: Prend\n2: Transforme"
+ TX_REPEAT_FABMINE "1: Extrait du fer\n2: Fabrique bombe"
+ TX_REPEAT_FABJEEP "1: Extrait du fer\n2: Fabrique jeep"
+ TX_REPEAT_PALIS "1: Abat un arbre\n2: Construit palissade"
+ TX_REPEAT_PALISQ "1: Prend\n2: Construit palissade"
+ TX_REPEAT_PONT "1: Abat un arbre\n2: Construit pont"
+ TX_REPEAT_PONTQ "1: Prend\n2: Construit pont"
+ TX_REPEAT_BATEAU "1: Abat un arbre\n2: Construit bateau"
+ TX_REPEAT_BATEAUQ "1: Prend\n2: Construit bateau"
+ TX_REPEAT_FABARMURE "1: Extrait du fer\n2: Fabrique armure"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_OBJ_MURPAL "Mur ou palissade"
+ TX_OBJ_OBJET "Objets"
+ TX_OBJ_ARME "Armes"
+ TX_OBJ_VEHICULE "Moyens de transport"
+ TX_OBJ_STARTFEU "Dbut d'incendie"
+ TX_OBJ_DELOBJ "Supprime objet"
+ TX_OBJ_DELPERSO "Supprime personnage"
+ TX_OBJ_DELFEU "Supprime feu"
+ TX_OBJ_PLANTE "Plantes ornementales"
+ TX_OBJ_BARENNEMIS "Barrire ennemie"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ TX_DIRECT_N "N"
+ TX_DIRECT_S "S"
+ TX_DIRECT_E "E"
+ TX_DIRECT_O "O"
+END
+
+#endif // French (Switzerland) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/resource/blupi.ico b/resource/blupi.ico
new file mode 100644
index 0000000..c825fe0
Binary files /dev/null and b/resource/blupi.ico differ
diff --git a/resource/blupi.rct b/resource/blupi.rct
new file mode 100644
index 0000000..7400333
Binary files /dev/null and b/resource/blupi.rct differ
diff --git a/resource/cursor1.cur b/resource/cursor1.cur
new file mode 100644
index 0000000..aa9f335
Binary files /dev/null and b/resource/cursor1.cur differ
diff --git a/resource/empty.cur b/resource/empty.cur
new file mode 100644
index 0000000..0ac9262
Binary files /dev/null and b/resource/empty.cur differ
diff --git a/resource/fill.cur b/resource/fill.cur
new file mode 100644
index 0000000..1c1b24b
Binary files /dev/null and b/resource/fill.cur differ
diff --git a/resource/map.cur b/resource/map.cur
new file mode 100644
index 0000000..e270c4d
Binary files /dev/null and b/resource/map.cur differ
diff --git a/resource/resource.h b/resource/resource.h
new file mode 100644
index 0000000..52fc058
--- /dev/null
+++ b/resource/resource.h
@@ -0,0 +1,561 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Eggbert2.rc
+//
+#define TX_IONAMEEX 100
+#define TX_IOFREE 101
+#define TX_OWNMISSION 102
+#define TX_TESTMISSION 103
+#define TX_BUTTON_JOUER 104
+#define TX_BUTTON_APPRENDRE 105
+#define TX_BUTTON_QUITTER 106
+#define TX_BUTTON_PREVP 107
+#define TX_BUTTON_NEXTP 108
+#define TX_BUTTON_PLAYP 109
+#define TX_BUTTON_BUILDP 110
+#define TX_BUTTON_TERM 111
+#define TX_BUTTON_READP 112
+#define TX_BUTTON_WRITEP 113
+#define TX_BUTTON_CANCELP 114
+#define TX_BUTTON_CONTP 115
+#define TX_BUTTON_REPEAT 116
+#define TX_CHOOSEPLAYER 117
+#define TX_PLAYERSNAME 118
+#define TX_BUTTON_TERMC 119
+#define TX_CHOOSESIZE 120
+#define TX_BUTTON_HVSCROLL 121
+#define TX_BUTTON_ONLYHSCROLL 122
+#define TX_BUTTON_ONLYVSCROLL 123
+#define TX_BUTTON_TESTMISSION 124
+#define TX_PAUSE 125
+#define TX_TINY 126
+#define TX_CLEARPLAYER 127
+#define TX_SETTINGS 128
+#define TX_CHOOSEMUSIC 129
+#define TX_BUTTON_SETUP1 130
+#define TX_BUTTON_SETUP2 131
+#define TX_BUTTON_SETUP3 132
+#define TX_BUTTON_SETUP4 133
+#define TX_NOMUSIC 134
+#define TX_MUSIC1 135
+#define TX_MUSIC2 136
+#define TX_MUSIC3 137
+#define TX_MUSIC4 138
+#define TX_MUSIC5 139
+#define TX_MUSIC6 140
+#define TX_MUSIC7 141
+#define TX_MUSIC8 142
+#define TX_MUSIC9 143
+#define TX_BUTTON_REGION 144
+#define TX_CHOOSEBACK 144
+#define TX_DISCARDGAME 145
+#define TX_CONFIRMCLEARGAME 145
+#define TX_EGGBERT 146
+#define TX_BLUPI 146
+#define TX_DESIGNMISSION 147
+#define TX_DESIGNMISSIONS 147
+#define TX_CHOOSEGAMER 148
+#define TX_CHOOSEPLAYER2 148
+#define TX_MUSIC 149
+#define TX_CHOOSEMUSIC2 149
+#define TX_TRAININGNUM 150
+#define TX_MISSIONNUM 151
+#define TX_MISSIONTIME 152
+#define IDS_STRING152 152
+#define TX_SIZE 153
+#define IDS_STRING153 153
+#define TX_BUTTON_SETUP5 154
+#define IDS_STRING154 154
+#define TX_BUTTON_SETUP6 155
+#define IDS_STRING155 155
+#define TX_BUTTON_SETUP7 156
+#define IDS_STRING156 156
+#define TX_BUTTON_SETUP8 157
+#define IDS_STRING157 157
+#define TX_CONFYES 158
+#define IDS_STRING158 158
+#define TX_CONFNO 159
+#define IDS_STRING159 159
+#define TX_SETTING 160
+#define IDS_STRING160 160
+#define TX_SAVECURRENTMISS 161
+#define IDS_STRING161 161
+#define TX_SOUNDVOL 162
+#define IDS_STRING162 162
+#define TX_MUSICVOL 163
+#define IDS_STRING163 163
+#define TX_COLORDEP 164
+#define IDS_STRING164 164
+#define TX_INPUT 165
+#define IDS_STRING165 165
+#define TX_OPENMISS 166
+#define IDS_STRING166 166
+#define TX_READINFO 167
+#define IDS_STRING167 167
+#define TX_PLAYERFREE 168
+#define IDS_STRING168 168
+#define TX_NUMDOOROPEN 169
+#define IDS_STRING169 169
+#define TX_NUMDOORSOPEN 170
+#define IDS_STRING170 170
+#define TX_MUSIC10 171
+#define IDS_STRING171 171
+#define TX_WRITENAME 172
+#define IDS_STRING172 172
+#define TX_NONE 173
+#define IDS_STRING173 173
+#define TX_CONFIRM 174
+#define IDS_STRING174 174
+#define TX_CANCEL 175
+#define IDS_STRING175 175
+#define TX_YES 176
+#define IDS_STRING176 176
+#define TX_NO 177
+#define IDS_STRING177 177
+#define TX_REGION 178
+#define IDS_STRING178 178
+#define TX_SUS 179
+#define IDS_STRING179 179
+#define TX_BUTTON_SETUP 180
+#define IDS_STRING180 180
+#define TX_SAVES 181
+#define IDS_STRING181 181
+#define TX_INSERT 182
+#define IDS_STRING182 182
+#define TX_DELETEMISS 183
+#define IDS_STRING183 183
+#define TX_DELETEMISSION 184
+#define IDS_STRING184 184
+#define TX_NAMEOFMISS 185
+#define IDS_STRING185 185
+#define TX_NAMEOFMISSION 186
+#define IDS_STRING186 186
+#define TX_NONAME 187
+#define IDS_STRING187 187
+#define TX_DESIGN 188
+#define IDS_STRING188 188
+#define TX_MISSNUM 189
+#define IDS_STRING189 189
+#define TX_MISSTIME 190
+#define IDS_STRING190 190
+#define TX_MISSION2D 191
+#define IDS_STRING191 191
+#define TX_SHOWNEXT 192
+#define IDS_STRING192 192
+#define TX_SHOWPREV 193
+#define IDS_STRING193 193
+#define TX_CONTENT 194
+#define IDS_STRING194 194
+#define TX_SINGLEPLAYER 195
+#define IDS_STRING195 195
+#define TX_MUTLIPLAYER 196
+#define TX_MULTIPLAYER 196
+#define IDS_STRING196 196
+#define TX_GAMEPAUSE 197
+#define TX_CANCELLAST 198
+#define TX_PLAYDEMO 199
+#define IDS_STRING199 199
+#define TX_HADFUN 200
+#define IDS_STRING200 200
+#define TX_OGCREATION 201
+#define IDS_STRING201 201
+#define TX_WEBSITE 202
+#define IDS_STRING202 202
+#define TX_FULL_END1 203
+#define IDS_STRING203 203
+#define TX_FULL_END2 204
+#define IDS_STRING204 204
+#define TX_FULL_END3 205
+#define IDS_STRING205 205
+#define TX_FULL_END4 206
+#define IDS_STRING206 206
+#define TX_CHOOSECOLOR 207
+#define IDS_STRING207 207
+#define TX_CLICKREADY 208
+#define IDS_STRING208 208
+#define TX_BUTTON_SKILL 209
+#define IDS_STRING209 209
+#define TX_EASY 210
+#define IDS_STRING210 210
+#define TX_HARD 211
+#define IDS_STRING211 211
+#define TX_BUTTON_DEMO 212
+#define IDS_STRING212 212
+#define TX_DEMOREC 213
+#define TX_DEMOPLAY 214
+#define IDS_STRING215 215
+#define IDS_STRING216 216
+#define IDS_STRING217 217
+#define IDS_STRING218 218
+#define IDS_STRING219 219
+#define IDS_STRING220 220
+#define IDS_STRING221 221
+#define IDS_STRING222 222
+#define IDS_STRING223 223
+#define IDS_STRING224 224
+#define IDS_STRING225 225
+#define IDS_STRING226 226
+#define IDS_STRING227 227
+#define IDS_STRING228 228
+#define IDS_STRING229 229
+#define IDS_STRING230 230
+#define IDS_STRING231 231
+#define IDS_STRING232 232
+#define IDS_STRING233 233
+#define IDS_STRING234 234
+#define IDS_STRING235 235
+#define IDS_STRING236 236
+#define IDS_STRING237 237
+#define IDS_STRING238 238
+#define IDS_STRING239 239
+#define IDS_STRING240 240
+#define IDS_STRING241 241
+#define TX_SHOWCONNECTION 242
+#define IDS_STRING242 242
+#define IDS_STRING243 243
+#define IDS_STRING244 244
+#define IDS_STRING245 245
+#define IDS_STRING246 246
+#define TX_GAMEJOIN 247
+#define IDS_STRING247 247
+#define TX_CREATE_MULTIGAME 248
+#define IDS_STRING248 248
+#define TX_UPDATELIST 249
+#define IDS_STRING249 249
+#define TX_MULTI_CREATE 250
+#define TX_MULTI_GNAME 251
+#define IDS_STRING251 251
+#define IDS_STRING252 252
+#define IDS_STRING253 253
+#define IDS_STRING254 254
+#define IDS_STRING255 255
+#define IDS_STRING256 256
+#define IDS_STRING257 257
+#define IDS_STRING258 258
+#define IDS_STRING259 259
+#define IDS_STRING260 260
+#define IDS_STRING261 261
+#define IDS_STRING262 262
+#define IDS_STRING263 263
+#define TX_OPEN 264
+#define IDS_STRING264 264
+#define IDS_STRING265 265
+#define IDS_STRING266 266
+#define IDS_STRING267 267
+#define TX_HELP 268
+#define IDS_STRING268 268
+#define TX_LOAD_CGAME 269
+#define TX_SAVE_CGAME 270
+#define IDS_STRING271 271
+#define TX_MISSIONFREE 272
+#define IDS_STRING272 272
+#define IDS_STRING273 273
+#define IDS_STRING274 274
+#define IDS_STRING275 275
+#define IDS_STRING276 276
+#define IDS_STRING277 277
+#define IDS_STRING278 278
+#define IDS_STRING279 279
+#define IDS_STRING280 280
+#define IDS_STRING281 281
+#define IDS_STRING282 282
+#define IDS_STRING283 283
+#define IDS_STRING284 284
+#define IDS_STRING285 285
+#define IDS_STRING286 286
+#define IDS_STRING287 287
+#define TX_GAMESAVED 288
+#define IDS_STRING288 288
+#define TX_NOTINDEMO 289
+#define IDS_STRING289 289
+#define IDS_STRING290 290
+#define IDS_STRING291 291
+#define IDS_STRING292 292
+#define IDS_STRING293 293
+#define IDS_STRING294 294
+#define IDS_STRING295 295
+#define IDS_STRING296 296
+#define IDS_STRING297 297
+#define IDS_STRING298 298
+#define IDS_STRING299 299
+#define IDS_STRING300 300
+#define IDS_STRING301 301
+#define IDS_STRING302 302
+#define IDS_STRING303 303
+#define IDS_STRING304 304
+#define IDS_STRING305 305
+#define IDS_STRING306 306
+#define IDS_STRING400 400
+#define IDS_STRING401 401
+#define IDS_STRING402 402
+#define IDS_STRING403 403
+#define IDS_STRING404 404
+#define IDS_STRING405 405
+#define IDS_STRING406 406
+#define IDS_STRING407 407
+#define IDS_STRING408 408
+#define IDS_STRING409 409
+#define IDS_STRING410 410
+#define IDS_STRING411 411
+#define IDS_STRING412 412
+#define TX_REPEAT_CULTIVE 500
+#define IDS_STRING500 500
+#define TX_REPEAT_FLEUR 501
+#define IDS_STRING501 501
+#define TX_REPEAT_FLEURQ 502
+#define IDS_STRING502 502
+#define TX_REPEAT_FABMINE 503
+#define IDS_STRING503 503
+#define TX_REPEAT_FABJEEP 504
+#define IDS_STRING504 504
+#define TX_REPEAT_PALIS 505
+#define IDS_STRING505 505
+#define TX_REPEAT_PALISQ 506
+#define IDS_STRING506 506
+#define TX_REPEAT_PONT 507
+#define IDS_STRING507 507
+#define TX_REPEAT_PONTQ 508
+#define IDS_STRING508 508
+#define TX_REPEAT_BATEAU 509
+#define IDS_STRING509 509
+#define TX_REPEAT_BATEAUQ 510
+#define IDS_STRING510 510
+#define TX_REPEAT_FABARMURE 511
+#define IDS_STRING511 511
+#define TX_DIRECT_N 512
+#define IDS_STRING512 512
+#define TX_DIRECT_S 513
+#define TX_DIRECT_E 514
+#define TX_DIRECT_O 515
+#define IDS_STRING600 600
+#define IDS_STRING601 601
+#define IDS_STRING602 602
+#define IDS_STRING603 603
+#define IDS_STRING604 604
+#define IDS_STRING605 605
+#define IDS_STRING606 606
+#define IDS_STRING607 607
+#define IDS_STRING608 608
+#define IDS_STRING609 609
+#define IDS_STRING610 610
+#define IDS_STRING611 611
+#define IDS_STRING612 612
+#define IDS_STRING613 613
+#define IDS_STRING614 614
+#define IDS_STRING615 615
+#define IDS_STRING616 616
+#define IDS_STRING617 617
+#define IDS_STRING618 618
+#define IDS_STRING619 619
+#define IDS_STRING620 620
+#define IDS_STRING621 621
+#define IDS_STRING622 622
+#define IDS_STRING623 623
+#define IDR_WAVE_BOING 1000
+#define TX_ERROR_MISC 1000
+#define IDS_STRING1000 1000
+#define IDR_WAVE_BLOW 1001
+#define TX_ERROR_GROUND 1001
+#define IDS_STRING1001 1001
+#define TX_ERROR_FREE 1002
+#define IDS_STRING1002 1002
+#define TX_ERROR_PONTOP 1003
+#define IDS_STRING1003 1003
+#define TX_ERROR_PONTTERM 1004
+#define IDS_STRING1004 1004
+#define TX_ERROR_TOURISOL 1005
+#define IDS_STRING1005 1005
+#define TX_ERROR_TOUREAU 1006
+#define IDS_STRING1006 1006
+#define TX_ERROR_TELE2 1007
+#define IDS_STRING1007 1007
+#define IDS_STRING1008 1008
+#define IDS_STRING1009 1009
+#define IDS_STRING1010 1010
+#define IDS_STRING1011 1011
+#define IDS_STRING1012 1012
+#define IDS_STRING1013 1013
+#define IDS_STRING1014 1014
+#define IDS_STRING1015 1015
+#define IDS_STRING1016 1016
+#define IDS_STRING1017 1017
+#define IDS_STRING1018 1018
+#define IDS_STRING1019 1019
+#define IDS_STRING1020 1020
+#define IDS_STRING1021 1021
+#define IDS_STRING1022 1022
+#define IDS_STRING1023 1023
+#define IDS_STRING1024 1024
+#define IDS_STRING1025 1025
+#define IDS_STRING1026 1026
+#define IDS_STRING1027 1027
+#define IDS_STRING1028 1028
+#define IDS_STRING1029 1029
+#define IDS_STRING1030 1030
+#define IDS_STRING1031 1031
+#define IDS_STRING1032 1032
+#define IDS_STRING1033 1033
+#define IDS_STRING1034 1034
+#define IDS_STRING1035 1035
+#define IDS_STRING1036 1036
+#define IDS_STRING1037 1037
+#define IDS_STRING1038 1038
+#define IDS_STRING1039 1039
+#define IDS_STRING1040 1040
+#define IDS_STRING1041 1041
+#define IDS_STRING1042 1042
+#define IDS_STRING1043 1043
+#define IDS_STRING1044 1044
+#define IDS_STRING1045 1045
+#define IDS_STRING1046 1046
+#define IDS_STRING1047 1047
+#define IDS_STRING1048 1048
+#define IDS_STRING1049 1049
+#define IDS_STRING1050 1050
+#define IDS_STRING1051 1051
+#define IDS_STRING1052 1052
+#define IDS_STRING1053 1053
+#define IDS_STRING1054 1054
+#define IDS_STRING1055 1055
+#define IDS_STRING1056 1056
+#define IDS_STRING1057 1057
+#define IDS_STRING1058 1058
+#define IDS_STRING1059 1059
+#define IDS_STRING1060 1060
+#define IDS_STRING1061 1061
+#define IDS_STRING1062 1062
+#define IDS_STRING1063 1063
+#define IDS_STRING1064 1064
+#define IDS_STRING1065 1065
+#define IDS_STRING1066 1066
+#define IDS_STRING1067 1067
+#define IDS_STRING1068 1068
+#define IDS_STRING1069 1069
+#define IDS_STRING1070 1070
+#define IDS_STRING1071 1071
+#define IDS_STRING1072 1072
+#define IDS_STRING1073 1073
+#define IDS_STRING1074 1074
+#define IDS_STRING1075 1075
+#define IDS_STRING1076 1076
+#define IDS_STRING1077 1077
+#define IDS_STRING1078 1078
+#define IDS_STRING1079 1079
+#define IDS_STRING1080 1080
+#define IDS_STRING1081 1081
+#define IDS_STRING1082 1082
+#define IDS_STRING1083 1083
+#define IDS_STRING1084 1084
+#define TX_OBJ_BLUPIm 2000
+#define TX_OBJ_BLUPIf 2001
+#define TX_OBJ_BLUPI 2002
+#define TX_OBJ_BATEAU 2003
+#define TX_OBJ_JEEP 2004
+#define IDS_STRING2004 2004
+#define TX_OBJ_PIEGE 2005
+#define TX_OBJ_POISON 2006
+#define TX_OBJ_DYNAMITE 2007
+#define IDS_STRING2007 2007
+#define TX_OBJ_MINE 2008
+#define TX_OBJ_TOMATE 2009
+#define IDS_STRING2009 2009
+#define TX_OBJ_POTION 2010
+#define TX_OBJ_PLANCHE 2011
+#define TX_OBJ_PIERRE 2012
+#define TX_OBJ_DRAPEAU 2013
+#define TX_OBJ_FER 2014
+#define TX_OBJ_FLEUR1 2015
+#define TX_OBJ_FLEUR2 2016
+#define TX_OBJ_FLEUR3 2017
+#define TX_OBJ_CABANE 2018
+#define TX_OBJ_LABO 2019
+#define TX_OBJ_MINEFER 2020
+#define TX_OBJ_USINE 2021
+#define TX_OBJ_TOUR 2022
+#define TX_OBJ_FEU 2023
+#define TX_OBJ_ROBOT 2024
+#define TX_OBJ_TRACKS 2025
+#define TX_OBJ_BOMBE 2026
+#define TX_OBJ_ARAIGNEE 2027
+#define TX_OBJ_VIRUS 2028
+#define TX_OBJ_ELECTRO 2029
+#define TX_OBJ_ARBRE 2030
+#define IDS_STRING2030 2030
+#define TX_OBJ_MUR 2031
+#define TX_OBJ_ARBREb 2032
+#define TX_OBJ_ROC 2033
+#define IDS_STRING2033 2033
+#define TX_OBJ_OEUF 2034
+#define TX_OBJ_PALISSADE 2035
+#define TX_OBJ_ENNEMIp 2036
+#define TX_OBJ_ENNEMI 2037
+#define TX_OBJ_HERBE 2038
+#define IDS_STRING2038 2038
+#define TX_OBJ_MOUSSE 2039
+#define TX_OBJ_TERRE 2040
+#define TX_OBJ_EAU 2041
+#define IDS_STRING2041 2041
+#define TX_OBJ_RIVE 2042
+#define TX_OBJ_MIXTE 2043
+#define TX_OBJ_PONT 2044
+#define IDS_STRING2044 2044
+#define TX_OBJ_COUVEUSE 2045
+#define TX_OBJ_GLACE 2046
+#define TX_OBJ_MAISON 2047
+#define IDS_STRING2047 2047
+#define TX_OBJ_HACHURE 2048
+#define TX_OBJ_MOUSSEb 2049
+#define TX_OBJ_BOUQUET1 2050
+#define TX_OBJ_BOUQUET2 2051
+#define TX_OBJ_BOUQUET3 2052
+#define TX_OBJ_DALLE 2053
+#define TX_OBJ_ENNEMIs 2054
+#define TX_OBJ_DISCIPLE 2055
+#define TX_OBJ_METAL 2056
+#define TX_OBJ_FUSEE 2057
+#define TX_OBJ_TELEPORTE 2058
+#define TX_OBJ_ARMURE 2059
+#define TX_OBJ_DALLESPEC 2060
+#define TX_OBJ_COUVTELE 2061
+#define TX_OBJ_BATIMENT 2062
+#define TX_OBJ_BATENNEMIS 2063
+#define TX_OBJ_MURPAL 2064
+#define TX_OBJ_OBJET 2065
+#define TX_OBJ_ARME 2066
+#define TX_OBJ_VEHICULE 2067
+#define TX_OBJ_STARTFEU 2068
+#define TX_OBJ_DELOBJ 2069
+#define TX_OBJ_DELPERSO 2070
+#define TX_OBJ_DELFEU 2071
+#define TX_OBJ_PLANTE 2072
+#define IDS_STRING2072 2072
+#define TX_OBJ_BARENNEMIS 2073
+#define TX_WIN1 3000
+#define TX_WIN2 3001
+#define TX_WIN3 3002
+#define TX_WIN4 3003
+#define TX_WIN5 3004
+#define TX_LOST1 3100
+#define TX_LOST2 3101
+#define TX_LOST3 3102
+#define TX_LOST4 3103
+#define TX_LOST5 3104
+#define TX_LASTWIN1 3200
+#define IDS_STRING3200 3200
+#define TX_LASTWIN2 3201
+#define IDS_STRING3201 3201
+#define TX_LASTWIN3 3202
+#define IDS_STRING3202 3202
+#define TX_BUTTON_CREATE 6900
+#define IDM_EXIT 40001
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 195
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/resource/resource1.h b/resource/resource1.h
new file mode 100644
index 0000000..514be47
--- /dev/null
+++ b/resource/resource1.h
@@ -0,0 +1,88 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Eggbert2.rc
+//
+#pragma once
+#define IDS_STRING101 101
+#define IDS_STRING102 102
+#define IDC_CURSOR1 102
+#define IDS_STRING103 103
+#define IDC_CURSOR2 103
+#define IDS_STRING104 104
+#define IDC_CURSOR3 104
+#define IDS_STRING105 105
+#define IDC_CURSOR4 105
+#define IDS_STRING106 106
+#define IDC_CURSOR5 106
+#define IDS_STRING107 107
+#define IDC_CURSOR6 107
+#define IDS_STRING108 108
+#define IDC_CURSOR7 108
+#define IDS_STRING109 109
+#define IDC_CURSOR8 109
+#define IDS_STRING110 110
+#define IDC_CURSOR9 110
+#define IDS_STRING111 111
+#define IDC_CURSOR10 111
+#define IDS_STRING112 112
+#define IDC_CURSOR11 112
+#define IDS_STRING113 113
+#define IDC_CURSOR12 113
+#define IDS_STRING114 114
+#define IDC_CURSOR13 114
+#define IDS_STRING115 115
+#define IDC_CURSOR14 115
+#define IDS_STRING116 116
+#define IDC_CURSOR15 116
+#define IDS_STRING117 117
+#define IDI_ICON1 117
+#define IDS_STRING118 118
+#define IDD_DIALOG1 118
+#define IDS_STRING119 119
+#define IDS_STRING120 120
+#define IDS_STRING121 121
+#define IDS_STRING122 122
+#define IDS_STRING123 123
+#define IDS_STRING124 124
+#define IDS_STRING125 125
+#define IDS_STRING126 126
+#define IDS_STRING127 127
+#define IDS_STRING128 128
+#define IDS_STRING129 129
+#define IDS_STRING130 130
+#define IDS_STRING131 131
+#define IDS_STRING132 132
+#define IDS_STRING133 133
+#define IDS_STRING134 134
+#define IDS_STRING135 135
+#define IDS_STRING136 136
+#define IDS_STRING137 137
+#define IDS_STRING198 149
+#define IDS_STRING150 178
+#define IDS_STRING197 197
+#define IDS_STRING213 213
+#define IDS_STRING214 214
+#define IDS_STRING250 250
+#define IDS_STRING3005 269
+#define IDS_STRING270 270
+#define IDS_STRING3105 3000
+#define IDS_STRING3001 3001
+#define IDS_STRING3002 3002
+#define IDS_STRING3003 3003
+#define IDS_STRING3004 3004
+#define IDS_STRING138 3100
+#define IDS_STRING3101 3101
+#define IDS_STRING3102 3102
+#define IDS_STRING3103 3103
+#define IDS_STRING3104 3104
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 120
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/resource/resource2.h b/resource/resource2.h
new file mode 100644
index 0000000..7c27dc8
--- /dev/null
+++ b/resource/resource2.h
@@ -0,0 +1,108 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Resource.rc
+//
+#define TX_IONAMEEX 100
+#define TX_IOFREE 101
+#define TX_OWNMISSION 102
+#define TX_TESTMISSION 103
+#define TX_BUTTON_JOUER 104
+#define TX_BUTTON_APPRENDRE 105
+#define TX_BUTTON_QUITTER 106
+#define TX_BUTTON_PREVP 107
+#define TX_BUTTON_NEXTP 108
+#define TX_BUTTON_PLAYP 109
+#define TX_BUTTON_BUILDP 110
+#define TX_BUTTON_TERM 111
+#define TX_BUTTON_READP 112
+#define TX_BUTTON_WRITEP 113
+#define TX_BUTTON_CANCELP 114
+#define TX_BUTTON_CONTP 115
+#define TX_BUTTON_REPEAT 116
+#define TX_CHOOSEPLAYER 117
+#define TX_PLAYERSNAME 118
+#define TX_BUTTON_TERMC 119
+#define TX_CHOOSESIZE 120
+#define TX_BUTTON_HVSCROLL 121
+#define TX_BUTTON_ONLYHSSCROLL 122
+#define TX_BUTTON_ONLYVSCROLL 123
+#define TX_BUTTON_TESTMISSION 124
+#define TX_PAUSE 125
+#define TX_TINY 126
+#define TX_CLEARPLAYER 127
+#define TX_SETTINGS 128
+#define TX_CHOOSEMUSIC 129
+#define TX_BUTTON_SETUP1 130
+#define TX_BUTTON_SETUP2 131
+#define TX_BUTTON_SETUP3 132
+#define TX_BUTTON_SETUP4 133
+#define TX_NOMUSIC 134
+#define TX_MUSIC1 135
+#define TX_MUSIC2 136
+#define TX_MUSIC3 137
+#define TX_MUSIC4 138
+#define TX_MUSIC5 139
+#define TX_MUSIC6 140
+#define TX_MUSIC7 141
+#define TX_MUSIC8 142
+#define TX_MUSIC9 143
+#define TX_BUTTON_REGION 144
+#define TX_DISCARDGAME 145
+#define TX_EGGBERT 146
+#define TX_DESIGNMISSION 147
+#define TX_CHOOSEGAMER 148
+#define TX_MUSIC 149
+#define TX_TRAININGNUM 150
+#define TX_MISSIONNUM 151
+#define TX_MISSIONTIME 152
+#define TX_SIZE 153
+#define TX_BUTTON_SETUP5 154
+#define TX_BUTTON_SETUP6 155
+#define TX_BUTTON_SETUP7 156
+#define TX_BUTTON_SETUP8 157
+#define TX_CONFYES 158
+#define TX_CONFNO 159
+#define TX_SETTING 160
+#define TX_SAVECURRENTMISS 161
+#define TX_SOUNDVOL 162
+#define TX_MUSICVOL 163
+#define TX_COLORDEP 164
+#define TX_INPUT 165
+#define TX_OPENMISS 166
+#define TX_READINFO 167
+#define TX_PLAYERFREE 168
+#define TX_NUMDOOROPEN 169
+#define TX_NUMDOORSOPEN 170
+#define TX_MUSIC10 171
+#define TX_WRITENAME 172
+#define TX_NONE 173
+#define TX_CONFIRM 174
+#define TX_CANCEL 175
+#define TX_YES 176
+#define TX_NO 177
+#define TX_REGION 178
+#define TX_SUS 179
+#define TX_BUTTON_SETUP 180
+#define TX_SAVES 181
+#define TX_INSERT 182
+#define TX_DELETEMISS 183
+#define TX_DELETEMISSION 184
+#define TX_NAMEOFMISS 185
+#define TX_NAMEOFMISSION 186
+#define TX_NONAME 187
+#define TX_DESIGN 188
+#define TX_MISSNUM 189
+#define TX_MISSTIME 190
+#define IDI_ICON1 190
+#define TX_MISSION2D 191
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 191
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/resource/rstemp.rct b/resource/rstemp.rct
new file mode 100644
index 0000000..1e8b3a8
Binary files /dev/null and b/resource/rstemp.rct differ
diff --git a/resource/speedy.aps b/resource/speedy.aps
new file mode 100644
index 0000000..e006d59
Binary files /dev/null and b/resource/speedy.aps differ
diff --git a/resource/speedy.rc b/resource/speedy.rc
new file mode 100644
index 0000000..4409ebb
--- /dev/null
+++ b/resource/speedy.rc
@@ -0,0 +1,63 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/resource/speedyblupi.aps b/resource/speedyblupi.aps
new file mode 100644
index 0000000..cbb5729
Binary files /dev/null and b/resource/speedyblupi.aps differ
diff --git a/resource/speedyblupi.rc b/resource/speedyblupi.rc
new file mode 100644
index 0000000..a12cd11
Binary files /dev/null and b/resource/speedyblupi.rc differ
diff --git a/resource/wait.cur b/resource/wait.cur
new file mode 100644
index 0000000..55f7588
Binary files /dev/null and b/resource/wait.cur differ
diff --git a/screenshot.png b/screenshot.png
new file mode 100644
index 0000000..333d1ec
Binary files /dev/null and b/screenshot.png differ
diff --git a/src/blupi.cpp b/src/blupi.cpp
new file mode 100644
index 0000000..e9a507d
--- /dev/null
+++ b/src/blupi.cpp
@@ -0,0 +1,897 @@
+// blupi.cpp
+//
+
+#define WIN32_LEAN_AND_MEAN
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "def.h"
+#include "resource.h"
+#include "ddutil.h"
+#include "pixmap.h"
+#include "sound.h"
+#include "decor.h"
+#include "movie.h"
+#include "button.h"
+#include "menu.h"
+#include "event.h"
+#include "network.h"
+#include "misc.h"
+
+// Define Globals
+
+#define NAME "Blupi"
+#ifdef _EGAMES
+#define TITLE "Eggbert"
+#else
+#define TITLE "Blupi"
+#endif
+
+#define MMTIMER TRUE
+#define THREAD FALSE
+
+// Variables Globals
+
+HWND g_hWnd; // handle à la fenètre
+CEvent* g_pEvent = NULL;
+CPixmap* g_pPixmap = NULL; // pixmap principal
+CSound* g_pSound = NULL; // sound principal
+CMovie* g_pMovie = NULL; // movie principal
+CDecor* g_pDecor = NULL;
+CNetwork* g_pNetwork = NULL;
+char g_CDPath[MAX_PATH]; // chemin d'accès au CD-Rom
+BOOL g_bFullScreen = FALSE; // FALSE si mode de test
+int g_speedRate = 1;
+int g_timerInterval = 50; // inverval = 50ms
+int g_mouseType = MOUSETYPEGRA;
+int g_benchmark;
+BOOL g_bBenchmarkSuccess;
+BOOL g_bTrueColorBack;
+BOOL g_bTrueColorDecor;
+BOOL g_bCDAudio = FALSE;
+int g_something;
+MMRESULT g_updateTimer; // timer général
+BOOL g_bActive = TRUE; // is application active ?
+BOOL g_bTermInit = FALSE; // initialisation en cours
+int g_timer;
+
+UINT g_lastPhase = 999;
+
+// Lit un numéro décimal.
+
+int GetNum(char *p)
+{
+ int n = 0;
+
+ while ( *p >= '0' && *p <= '9' )
+ {
+ n *= 10;
+ n += (*p++)-'0';
+ }
+
+ return n;
+}
+
+BOOL ReadConfig(LPSTR lpCmdLine)
+{
+ FILE* file = NULL;
+ char buffer[200];
+ char* pText;
+ int nb;
+ int i;
+ MEMORYSTATUS mem;
+
+ file = fopen("data\\config.def", "rb");
+ if (file == NULL) return FALSE;
+ nb = fread(buffer, sizeof(char), 200 - 1, file);
+ buffer[nb] = 0;
+ fclose(file);
+
+
+#if _CD
+ pText = strstr(buffer, "CD-Rom=");
+ if (pText == NULL)
+ {
+#if _DEMO
+ GetCurrentDirectory(MAX_PATH, g_CDPath);
+ i = strlen(g_CDPath);
+ if (i > 0 && g_CDPath[i - 1] != '\\')
+ {
+ g_CDPath[i++] = '\\';
+ g_CDPath[i] = 0;
+ }
+#else
+ return FALSE;
+#endif // _DEMO
+ }
+ else
+ {
+ pText += 7;
+ i = 0;
+ while (pText[i] != 0 && pText[i] != '\n' && pText[i] != '\r')
+ {
+ g_CDPath[i] = pText[i];
+ i++;
+ }
+ if (i > 0 && g_CDPath[i - 1] != '\\')
+ {
+ g_CDPath[i++] = '\\';
+ }
+ g_CDPath[i] = 0; // met le terminateur
+ }
+
+#if !_DEMO && !_EGAMES
+ if (strstr(lpCmdLine, "-nocd") == NULL)
+ {
+ char drive[10];
+
+ drive[0] = g_CDPath[0];
+ drive[1] = ':';
+ drive[2] = '\\';
+ drive[3] = 0;
+ nb = GetDriveType(drive);
+ if (nb != DRIVE_CDROM) return FALSE;
+ }
+#endif // !_DEMO && !_EGAMES
+#endif // _CD
+
+ pText = strstr(buffer, "SpeedRate=");
+ if (pText != NULL)
+ {
+ g_speedRate = GetNum(pText + 10);
+ if (g_speedRate < 1) g_speedRate = 1;
+ if (g_speedRate > 2) g_speedRate = 2;
+ }
+
+ pText = strstr(buffer, "Timer=");
+ if (pText != NULL)
+ {
+ g_timerInterval = GetNum(pText + 6);
+ if (g_timerInterval < 10) g_timerInterval = 10;
+ if (g_timerInterval > 1000) g_timerInterval = 1000;
+ }
+
+ pText = strstr(buffer, "FullScreen=");
+ if (pText != NULL)
+ {
+ g_bFullScreen = GetNum(pText + 11);
+ if (g_bFullScreen != 0) g_bFullScreen = 1;
+ }
+
+ pText = strstr(buffer, "MouseType=");
+ if (pText != NULL)
+ {
+ g_mouseType = GetNum(pText + 10);
+ if (g_mouseType < 1) g_mouseType = 1;
+ if (g_mouseType > 9) g_mouseType = 9;
+ }
+
+ pText = strstr(buffer, "Benchmark=");
+ if (pText != NULL)
+ {
+ g_benchmark = GetNum(pText + 10);
+ if (g_benchmark < 0) g_benchmark = 0;
+ if (g_benchmark > 100000) g_benchmark = 100000;
+ if (g_benchmark > 3099)
+ {
+ g_bBenchmarkSuccess = TRUE;
+ g_bTrueColorBack = TRUE;
+ g_bTrueColorDecor = TRUE;
+ }
+ }
+
+ pText = strstr(buffer, "TrueColor=");
+ if (pText != NULL)
+ {
+ i = GetNum(pText + 10);
+ if (i == 8) g_bTrueColorBack = FALSE;
+ if (i == 16) g_bTrueColorBack = TRUE;
+ g_bTrueColorDecor = g_bTrueColorBack;
+ }
+
+ pText = strstr(buffer, "TrueColorBack=");
+ if (pText != NULL)
+ {
+ i = GetNum(pText + 14);
+ if (i == 8) g_bTrueColorBack = FALSE;
+ if (i == 16) g_bTrueColorBack = TRUE;
+ }
+
+ pText = strstr(buffer, "TrueColorDecor=");
+ if (pText != NULL)
+ {
+ i = GetNum(pText + 15);
+ if (i == 8) g_bTrueColorDecor = FALSE;
+ if (i == 16) g_bTrueColorDecor = TRUE;
+ }
+
+ pText = strstr(buffer, "CDAudio=");
+ if (pText != NULL)
+ {
+ i = GetNum(pText + 8);
+ g_bCDAudio = (i == TRUE);
+ }
+
+ mem.dwLength = sizeof(MEMORYSTATUS);
+ GlobalMemoryStatus(&mem);
+
+ if (mem.dwTotalPhys < 32000000) g_bBenchmarkSuccess = FALSE;
+
+ if (!g_bBenchmarkSuccess)
+ {
+ g_bTrueColorBack = FALSE;
+ g_bTrueColorDecor = FALSE;
+ }
+
+ return TRUE;
+}
+
+// Mise à jour principale.
+
+void UpdateFrame(void)
+{
+ int phase, term, speed;
+
+ g_pEvent->ReadInput();
+ phase = g_pEvent->GetPhase();
+
+ if (phase == WM_PHASE_INTRO1 ||
+ phase == WM_PHASE_INTRO2)
+ {
+ g_pEvent->IntroStep();
+ }
+
+ if (phase == WM_PHASE_PLAY || phase == WM_PHASE_PLAYTEST || phase == WM_PHASE_BUILD)
+ {
+ if (!g_pDecor->GetPause())
+ {
+ speed = g_pEvent->GetSpeed() * g_speedRate;
+ for (int i = 0; i < speed; i++)
+ {
+ g_pDecor->MoveStep();
+ g_pEvent->DemoStep();
+ }
+ }
+ }
+
+ if (phase == WM_PHASE_INIT)
+ {
+ g_pEvent->DemoStep(); // d?marre ?v. d?mo automatique
+ }
+
+ if (phase == WM_PHASE_PLAYMOVIE ||
+ phase == WM_PHASE_WINMOVIE ||
+ phase == WM_PHASE_WINMOVIEDESIGN ||
+ phase == WM_PHASE_WINMOVIEMULTI)
+ {
+ g_pEvent->MovieToStart();
+ }
+
+ if (phase == WM_PHASE_INSERT)
+ {
+ g_pEvent->TryInsert();
+ }
+
+ if (phase == WM_PHASE_PLAY)
+ {
+ term = g_pDecor->IsTerminated();
+
+ if (g_pEvent->IsPrivate())
+ {
+ if (term == -1)
+ {
+ g_pEvent->ChangePhase(WM_PHASE_LOSTDESIGN);
+ return;
+ }
+ if (term != 0)
+ {
+ g_pEvent->ChangePhase(WM_PHASE_WINMOVIEDESIGN);
+ return;
+ }
+ }
+ else
+ {
+ if (g_pEvent->IsMulti())
+ {
+ if (term == -1)
+ {
+ g_pEvent->ChangePhase(WM_PHASE_WINMULTI);
+ return;
+ }
+ if (term != 0)
+ {
+ g_pEvent->ChangePhase(WM_PHASE_WINMOVIEMULTI);
+ return;
+ }
+ }
+ else
+ {
+ if (term == -1)
+ {
+ g_pEvent->GetWorldGroup();
+ g_pEvent->SetNbVies(g_pDecor->GetNbVies());
+ g_pEvent->ChangePhase(WM_PHASE_LOST);
+ }
+ if (term == -2)
+ {
+ g_pEvent->SetNbVies(g_pDecor->GetNbVies());
+ g_pEvent->ChangePhase(WM_PHASE_WINMOVIE);
+ }
+ if (term > 0)
+ {
+ g_pEvent->SetNbVies(g_pDecor->GetNbVies());
+ g_pEvent->SetMission(term);
+ g_pEvent->ChangePhase(WM_PHASE_PLAY);
+ }
+ }
+ }
+ }
+}
+
+
+void SetDecor()
+{
+ RECT rect;
+ UINT phase;
+ POINT posMouse;
+ char test[12];
+
+ g_pPixmap->MouseBackClear();
+ posMouse = g_pEvent->GetLastMousePos();
+
+ phase = g_pEvent->GetPhase();
+
+ rect = RECT( 0, 0, LXIMAGE, LYIMAGE );
+
+ if (phase == WM_PHASE_PLAY || phase == WM_PHASE_PLAYTEST || phase == WM_PHASE_BUILD)
+ {
+ g_pDecor->Build(rect);
+ }
+ else {
+ g_pPixmap->DrawImage(-1, 0, rect, 1);
+ }
+
+ g_pEvent->DrawButtons();
+ g_lastPhase = phase;
+ g_pPixmap->MouseBackDraw();
+}
+
+// Restitue le jeu après une activation en mode fullScreen.
+
+BOOL RestoreGame()
+{
+ if (g_pPixmap == NULL) return FALSE;
+
+ g_pEvent->RestoreGame();
+ return g_pPixmap->Restore();
+}
+
+// Libère le jeu avant une désactivation en mode fullScreen.
+
+BOOL FlushGame()
+{
+ if (g_pPixmap == NULL) return FALSE;
+
+ return g_pPixmap->Flush();
+}
+
+// Finished with all objects we use; release them.
+
+static void FinishObjects(void)
+{
+ if ( g_pMovie != NULL )
+ {
+ g_pEvent->StopMovie();
+
+ delete g_pMovie;
+ g_pMovie = NULL;
+ }
+
+ if ( g_pEvent != NULL )
+ {
+ delete g_pEvent;
+ g_pEvent = NULL;
+ }
+
+ if ( g_pDecor != NULL )
+ {
+ delete g_pDecor;
+ g_pDecor = NULL;
+ }
+
+ if (g_pSound != NULL )
+ {
+ g_pSound->StopMusic();
+
+ delete g_pSound;
+ g_pSound = NULL;
+ }
+
+ if (g_pNetwork != NULL )
+ {
+ delete g_pNetwork;
+ g_pNetwork = NULL;
+ }
+
+ if ( g_pPixmap != NULL )
+ {
+ delete g_pPixmap;
+ g_pPixmap = NULL;
+ }
+}
+
+LRESULT CALLBACK WindowProc(HWND hWnd, UINT message,
+ WPARAM wParam, LPARAM lParam)
+{
+ static HINSTANCE hInstance;
+ POINT mousePos, totalDim, iconDim;
+
+#if 0
+ if (message != WM_TIMER)
+ {
+ char s[100];
+ sprintf(s, "message=%d,%d\n", message, wParam);
+ OutputDebug(s);
+ }
+#endif
+
+ // La touche F10 envoie un autre message pour activer
+ // le menu dans les applications Windows standard !
+ if (message == WM_SYSKEYDOWN && wParam == VK_F10)
+ {
+ message = WM_KEYDOWN;
+ }
+ if (message == WM_SYSKEYUP && wParam == VK_F10)
+ {
+ message = WM_KEYUP;
+ }
+
+ if (g_pEvent != NULL &&
+ g_pEvent->TreatEvent(message, wParam, lParam)) return 0;
+
+ switch (message)
+ {
+ case WM_TIMER:
+ case WM_UPDATE:
+ if (g_pEvent != NULL && !g_pEvent->IsMovie() && !g_pEvent->IsMouseRelease()) // pas de film en cours ?
+ {
+ g_pEvent->GetPhase(); // ?
+ if (g_bActive)
+ {
+ UpdateFrame();
+ SetDecor();
+ }
+ g_pPixmap->Display();
+ }
+ if (g_timer > 0) g_timer--;
+ break;
+ case WM_CREATE:
+ hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
+ return 0;
+ break;
+ case WM_ACTIVATEAPP:
+ g_bActive = (wParam != 0);
+ if (g_pEvent != NULL)
+ {
+ g_pEvent->FlushInput();
+ }
+ if (g_bActive)
+ {
+ if (g_bFullScreen)
+ {
+ RestoreGame();
+ g_lastPhase = 999;
+ }
+ if (!g_bFullScreen && g_bTermInit)
+ {
+ g_pPixmap->BackgroundCache(CHLITTLE, "little.blp", POINT( 256, 96 ), POINT( DIMLITTLEX , DIMLITTLEY ), TRUE);
+ g_pPixmap->SetTransparent(CHLITTLE, RGB(0, 0, 255)); // bleu
+
+ g_pPixmap->SavePalette();
+ g_pPixmap->InitSysPalette();
+ }
+ SetWindowText(hWnd, "Blupi");
+ if (g_pSound != NULL) g_pSound->RestartMusic();
+ }
+ else // désactive ?
+ {
+ if (g_bFullScreen)
+ {
+ FlushGame();
+ }
+ SetWindowText(hWnd, "Blupi -- stop");
+ if (g_pSound != NULL) g_pSound->SuspendMusic();
+ }
+ return 0;
+
+ case WM_SYSCOLORCHANGE:
+ OutputDebug("Event WM_SYSCOLORCHANGE\n");
+ break;
+
+ case WM_QUERYNEWPALETTE:
+ OutputDebug("Event WM_QUERYNEWPALETTE\n");
+ break;
+
+ case WM_PALETTECHANGED:
+ OutputDebug("Event WM_PALLETECHANGED\n");
+ break;
+
+ case WM_DISPLAYCHANGE:
+ OutputDebug("Event WM_DISPLAYCHANGE\n");
+ break;
+
+ case MM_MCINOTIFY:
+ OutputDebug("Event MM_MCINOTIFY\n");
+ if (g_pEvent->IsMovie()) // film en cours ?
+ {
+ if (wParam == MCI_NOTIFY_SUCCESSFUL)
+ {
+ g_pEvent->StopMovie();
+ }
+ }
+ else
+ {
+ // music over, play it again
+ g_pSound->SuspendMusic();
+ // if music finished, play it again. Otherwise assume that
+ // it was aborted by the user or otherwise
+ if (wParam == MCI_NOTIFY_SUCCESSFUL)
+ {
+ OutputDebug("Event MCI_NOTIFY_SUCCESSFUL\n");
+ g_pSound->RestartMusic();
+ }
+ else
+ {
+ char s[50];
+ sprintf(s, "wParam=%d\n", wParam);
+ OutputDebug(s);
+ }
+ }
+ break;
+
+ case WM_SETCURSOR:
+ // ChangeSprite();
+ // SetCursor(NULL); // pas de souris visible !
+ return TRUE;
+
+ case WM_LBUTTONDOWN:
+ //? Benchmark();
+ GetCursorPos(&mousePos);
+ ScreenToClient(hWnd, &mousePos);
+ break;
+
+ case WM_RBUTTONDOWN:
+ break;
+
+ case WM_MOUSEMOVE:
+ break;
+
+ case WM_KEYDOWN:
+ switch (wParam)
+ {
+ case VK_F5:
+ g_pEvent->SetSpeed(1);
+ break;
+ case VK_F6:
+ g_pEvent->SetSpeed(2);
+ break;
+ case VK_F7:
+ g_pEvent->SetSpeed(4);
+ break;
+ case VK_F8:
+ g_pEvent->SetSpeed(8);
+ break;
+ }
+ break;
+
+ case WM_DESTROY:
+#if MMTIMER
+ timeKillEvent((UINT)g_updateTimer);
+#else
+ KillTimer(g_hWnd, 1);
+#endif
+ FinishObjects();
+ PostQuitMessage(0);
+ break;
+
+ }
+
+ return DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+void CALLBACK TimerStep(UINT wTimerID, UINT msg,
+ DWORD dwUser, DWORD dw1, DWORD dw2)
+{
+ if (g_bActive && g_timer == 0)
+ {
+ g_timer = 1;
+ PostMessage(g_hWnd, WM_UPDATE, 0, 0);
+ }
+}
+
+// Erreur dans DoInit.
+
+BOOL InitFail(const char *msg, BOOL bDirectX)
+{
+ char buffer[100];
+
+ if ( bDirectX ) strcpy(buffer, "DirectX Init FAILED\n(while ");
+ else strcpy(buffer, "Error (");
+ strcat(buffer, msg);
+ strcat(buffer, ")");
+ MessageBoxA(g_hWnd, buffer, TITLE, MB_OK);
+
+ FinishObjects();
+ DestroyWindow(g_hWnd);
+ return FALSE;
+}
+
+int Benchmark()
+{
+ struct timeb tstruct;
+ int i, j, t1, t2, time;
+ RECT rect;
+ POINT dest;
+ _MEMORYSTATUS mem;
+
+ ftime(&tstruct);
+ t1 = tstruct.millitm;
+
+ for (j = 0; j < 10; j++)
+ {
+ UpdateFrame();
+ SetDecor();
+ g_pPixmap->Display();
+ }
+
+ ftime(&tstruct);
+ t2 = tstruct.millitm;
+
+ if (t1 > t2) t2 += 1000;
+ time = t2 - t1;
+
+ mem.dwLength = 32;
+ GlobalMemoryStatus(&mem);
+ FILE* file = NULL;
+ char string[100];
+ sprintf(string, "CheckTime = %d Memory = %d\r\n", time, mem.dwTotalPhys);
+ file = fopen("data\\time.blp", "wb");
+ if (file == NULL) return time;
+ fwrite(string, strlen(string), 1, file);
+ fclose(file);
+
+ return time;
+}
+
+static BOOL DoInit(HINSTANCE hInstance, LPSTR lpCmdLine, int nCmdShow)
+{
+ WNDCLASSA wc;
+ POINT totalDim, iconDim;
+ RECT rcRect;
+ BOOL bOK;
+
+ bOK = ReadConfig(lpCmdLine); // lit le fichier config.def
+
+ InitHInstance(hInstance);
+
+ // Set up and register window class.
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc = WindowProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hInstance;
+ //? wc.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
+ wc.hIcon = LoadIcon(hInstance, "IDR_MAINFRAME");
+ wc.hCursor = LoadCursor(hInstance, "IDC_POINTER");
+ wc.hbrBackground = GetStockBrush(BLACK_BRUSH);
+ wc.lpszMenuName = NAME;
+ wc.lpszClassName = NAME;
+ RegisterClass(&wc);
+
+ // Create a window.
+ if (g_bFullScreen)
+ {
+ g_hWnd = CreateWindowEx
+ (
+ WS_EX_TOPMOST,
+ NAME,
+ TITLE,
+ WS_POPUP,
+ 0, 0,
+ GetSystemMetrics(SM_CXSCREEN),
+ GetSystemMetrics(SM_CYSCREEN),
+ NULL,
+ NULL,
+ hInstance,
+ NULL
+ );
+ }
+ else
+ {
+ int sx, sy;
+ RECT WindowRect;
+
+ sx = GetSystemMetrics(SM_CXSCREEN);
+ sy = GetSystemMetrics(SM_CYSCREEN);
+
+ SetRect(&WindowRect, (sx - LXIMAGE) / 2, (sy - LYIMAGE) / 2,
+ (sx + LXIMAGE) / 2, (sy + LYIMAGE) / 2);
+
+#if _LEGACY
+ // Old behavior is semantically incorrect.
+ // The game window becomes too short on modern versions of Windows.
+ AdjustWindowRect(&WindowRect, WS_POPUPWINDOW | WS_CAPTION, TRUE);
+ WindowRect.top += GetSystemMetrics(SM_CYCAPTION);
+#else
+ AdjustWindowRect(&WindowRect, WS_POPUPWINDOW | WS_CAPTION, FALSE);
+#endif
+
+ g_hWnd = CreateWindow
+ (
+ NAME,
+ TITLE,
+ WS_POPUPWINDOW | WS_CAPTION | WS_VISIBLE,
+ (sx - LXIMAGE) / 2, (sy - LYIMAGE) / 2,
+ WindowRect.right - WindowRect.left,
+ WindowRect.bottom - WindowRect.top,
+ HWND_DESKTOP,
+ NULL,
+ hInstance,
+ NULL
+ );
+ }
+ if (!g_hWnd) return FALSE;
+
+ ShowWindow(g_hWnd, nCmdShow);
+ UpdateWindow(g_hWnd);
+ SetFocus(g_hWnd);
+
+ ChangeSprite(SPRITE_WAIT); // met le sablier maison
+
+ if (!bOK) // config.def pas correct ?
+ {
+ return InitFail("Game not correctly installed", FALSE);
+ }
+
+ // Crée le pixmap principal.
+ g_pPixmap = new CPixmap;
+ if (g_pPixmap == NULL) return InitFail("New pixmap", TRUE);
+
+ totalDim.x = LXIMAGE;
+ totalDim.y = LYIMAGE;
+ if (!g_pPixmap->Create(g_hWnd, totalDim, g_bFullScreen, g_mouseType, g_bTrueColorBack, g_bTrueColorDecor))
+ return InitFail("Create pixmap", TRUE);
+
+ OutputDebug("Image: init\n");
+ totalDim.x = LXIMAGE;
+ totalDim.y = LYIMAGE;
+ iconDim.x = 0;
+ iconDim.y = 0;
+
+ if (!g_pPixmap->CacheAll(TRUE, g_hWnd, g_bFullScreen, g_bTrueColorBack, g_bTrueColorDecor, g_mouseType, "init.blp", 0))
+ return FALSE;
+ OutputDebug("SavePalette\n");
+ g_pPixmap->SavePalette();
+ OutputDebug("InitSysPalette\n");
+ g_pPixmap->InitSysPalette();
+
+ g_pSound = new CSound;
+ if (g_pSound == NULL) return InitFail("New sound", TRUE);
+
+ g_pSound->Create(g_hWnd);
+ g_pSound->CacheAll();
+ g_pSound->SetState(TRUE);
+ g_pSound->SetCDAudio(g_bCDAudio);
+
+ g_pNetwork = new CNetwork;
+ if (g_pNetwork == NULL) return InitFail("New network", TRUE);
+
+ g_pNetwork->CreateProvider(0);
+
+ g_pMovie = new CMovie;
+ if (g_pMovie == NULL) return InitFail("New movie", FALSE);
+
+ g_pMovie->Create();
+
+ g_pDecor = new CDecor;
+ if (g_pDecor == NULL) return InitFail("New decor", FALSE);
+
+ g_pDecor->Create(g_hWnd, g_pSound, g_pPixmap, g_pNetwork);
+
+ g_pEvent = new CEvent;
+ if (g_pEvent == NULL) return InitFail("New event", FALSE);
+
+ g_pEvent->Create(hInstance, g_hWnd, g_pPixmap, g_pDecor, g_pSound, g_pNetwork, g_pMovie);
+ g_pEvent->SetFullScreen(g_bFullScreen);
+ g_pEvent->SetMouseType(g_mouseType);
+
+#if _INTRO
+ g_pEvent->ChangePhase(WM_PHASE_INTRO1);
+#else
+ g_pEvent->ChangePhase(WM_PHASE_INIT);
+#endif
+
+ g_bTermInit = TRUE;
+ return TRUE;
+}
+
+int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
+ LPSTR lpCmdLine, int nCmdShow)
+{
+ MSG msg;
+ LPTIMECALLBACK timeStep;
+
+ if ( !DoInit(hInstance, lpCmdLine, nCmdShow) )
+ {
+ return FALSE;
+ }
+
+ Benchmark();
+
+#if MMTIMER
+ g_updateTimer = timeSetEvent(g_timerInterval, g_timerInterval / 4, TimerStep, NULL, TIME_PERIODIC);
+#else
+ SetTimer(g_hWnd, 1, g_timerInterval, NULL);
+#endif
+
+#if THREAD
+ g_hScreenMutex = CreateMutex(NULL, FALSE, NULL);
+ g_hRunMutex = CreateMutex(NULL, TRUE, NULL);
+ g_threadNr = 0;
+
+ g_hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadDisplay, 0, DETACHED_PROCESS, &g_threadID);
+#endif
+
+ while ( TRUE )
+ {
+ if ( PeekMessage(&msg, NULL, 0,0, PM_NOREMOVE) )
+ {
+ if ( !GetMessage(&msg, NULL, 0, 0) )
+ {
+ return msg.wParam;
+ }
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ else
+ {
+ // make sure we go to sleep if we have nothing else to do
+ if ( !g_bActive ) WaitMessage();
+ }
+ }
+
+ return msg.wParam;
+}
+
+#if THREAD
+// Thread d'affichage.
+
+static void ThreadDisplay(char* MyID)
+{
+ UINT phase;
+
+ do
+ {
+ phase = g_pEvent->GetPhase();
+ if (phase == WM_PHASE_PLAY)
+ {
+ // Wait for display to be available, then lock it.
+ WaitForSingleObject(g_hScreenMutex, INFINITE);
+
+ SetDecor();
+ g_pPixmap->Display();
+
+ // Clear screen lock.
+ ReleaseMutex(g_hScreenMutex);
+ }
+ }
+ // Repeat while RunMutex is still taken.
+ while (WaitForSingleObject(g_hRunMutex, 10L) == WAIT_TIMEOUT);
+}
+#endif
\ No newline at end of file
diff --git a/src/button.cpp b/src/button.cpp
new file mode 100644
index 0000000..d46828e
--- /dev/null
+++ b/src/button.cpp
@@ -0,0 +1,392 @@
+// Button.cpp
+//
+
+//#include
+//#include
+//#include
+//#include
+
+#ifndef POINT
+#include
+#endif
+
+#include "button.h"
+#include "misc.h"
+#include "def.h"
+#include "pixmap.h"
+#include "sound.h"
+
+//////////////////////////////////////////////////////////
+
+// Constructor
+
+CButton::CButton()
+{
+ m_type = 0;
+ m_bEnable = TRUE;
+ m_bHide = FALSE;
+ m_bLocked = FALSE;
+ m_state = 0;
+ m_mouseState = 0;
+ m_nbMenu = 0;
+ m_nbToolTips = 0;
+ m_selMenu = 0;
+ m_bMouseDown = FALSE;
+ m_bMinimizeRedraw = FALSE;
+ m_bRedraw = FALSE;
+}
+
+// Destructor
+
+CButton::~CButton()
+{
+}
+
+
+// Create a new Button
+
+BOOL CButton::Create(HWND hWnd, CPixmap *pPixmap, CSound *pSound,
+ POINT pos, int type, BOOL bMinimizeRedraw, UINT message)
+{
+ POINT iconDim;
+ int i, icon;
+
+ static int ttypes[] =
+ {
+ DIMBUTTONX,DIMBUTTONY,
+ };
+
+ if (type < 0 || type > 0) return FALSE;
+
+
+ iconDim.x = ttypes[type * 2 + 0];
+ iconDim.y = ttypes[type * 2 + 1];
+
+ m_hWnd = hWnd;
+ m_pPixmap = pPixmap;
+ m_pSound = pSound;
+ m_type = type;
+ m_bMinimizeRedraw = bMinimizeRedraw;
+ m_bEnable = TRUE;
+ m_bHide = FALSE;
+ m_bLocked = FALSE;
+ m_message = message;
+ m_pos.x = pos.x;
+ m_pos.y = pos.y;
+ m_dim.x = iconDim.x;
+ m_dim.y = iconDim.y;
+ m_nbMenu = 0;
+ m_nbToolTips = 0;
+ m_selMenu = 0;
+ m_state = 0;
+ m_mouseState = 0;
+ m_bMouseDown = FALSE;
+ m_bRedraw = TRUE;
+ return TRUE;
+}
+
+void CButton::SetIconMenu(int* pIcons, int nbMenu)
+{
+ for (int i = 0; i < nbMenu; i++)
+ {
+ m_iconMenu[i] = pIcons[i];
+ }
+ m_nbMenu = nbMenu;
+}
+
+void CButton::SetToolTips(int* pToolTips, int nbToolTips)
+{
+ for (int i = 0; i < nbToolTips; i++)
+ {
+ m_toolTips[i] = pToolTips[i];
+ }
+ m_nbToolTips = nbToolTips;
+}
+
+// Draw a button in its state
+
+void CButton::Draw()
+{
+ int i;
+ POINT pos;
+ RECT rect;
+
+ if (m_bMinimizeRedraw && !m_bRedraw) return;
+ m_bRedraw = FALSE;
+
+ if (m_bHide) // Hidden button
+ {
+ pos = m_pos;
+ return;
+ }
+
+ if (m_bEnable)
+ {
+ m_pPixmap->DrawIcon(-1, CHBUTTON + m_type, m_mouseState, m_pos);
+ }
+ else
+ {
+ m_pPixmap->DrawIcon(-1, CHBUTTON + m_type, m_bLocked ? 5 : 4, m_pos);
+ }
+
+ if (m_nbMenu == 0) return;
+
+ pos = m_pos;
+ if (m_nbMenu > 0)
+ {
+ m_pPixmap->DrawIcon(-1, CHBUTTON + m_type,
+ m_iconMenu[m_selMenu] + 6, pos);
+ }
+
+ if (m_nbMenu == 1 || !m_bEnable || !m_bMouseDown) return;
+
+ pos = m_pos;
+ pos.x += m_dim.x + 2;
+ for (i = 0; iDrawIcon(-1, CHBUTTON + m_type, i == m_selMenu ? 1 : 0, pos);
+ m_pPixmap->DrawIcon(-1, CHBUTTON + m_type, m_iconMenu[i] + 6, pos);
+ pos.x += m_dim.x - 1;
+ }
+}
+
+/*
+/Needed Yet?
+//////////////////////////////////////////////
+void CButton::Redraw()
+{
+m_bRedraw = TRUE;
+}
+//////////////////////////////////////////////
+*/
+
+int CButton::GetState()
+{
+ return m_state;
+}
+
+void CButton::SetState(int state)
+{
+ if (m_state != state ||
+ m_mouseState != state)
+ {
+ m_bRedraw = TRUE;
+ }
+
+ m_state = state;
+ m_mouseState = state;
+}
+
+int CButton::GetMenu()
+{
+ return m_selMenu;
+}
+
+void CButton::SetMenu(int menu)
+{
+ if (m_selMenu != menu)
+ {
+ m_bRedraw = TRUE;
+ }
+
+ m_selMenu = menu;
+}
+
+void CButton::SetEnable(BOOL bEnable)
+{
+ if (m_bEnable != bEnable)
+ {
+ m_bRedraw = TRUE;
+ }
+
+ m_bEnable = bEnable;
+}
+
+
+/*
+// Needed Yet?
+/////////////////////////////////////////
+BOOL CButton::GetHide()
+{
+return m_bHide;
+}
+/////////////////////////////////////////
+*/
+
+
+void CButton::SetHide(BOOL bHide)
+{
+ if (m_bHide != bHide)
+ {
+ m_bRedraw = TRUE;
+ }
+
+ m_bHide = bHide;
+}
+
+BOOL CButton::TreatEvent(UINT message, WPARAM wParam, LPARAM lParam)
+{
+ POINT pos;
+
+ if (m_bHide || !m_bEnable) return FALSE;
+
+ pos = ConvLongToPos(lParam);
+
+ switch (message)
+ {
+ case WM_LBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ if (MouseDown(pos)) return TRUE;
+ break;
+
+ case WM_MOUSEMOVE:
+ if (MouseMove(pos)) return TRUE;
+ break;
+
+ case WM_LBUTTONUP:
+ case WM_RBUTTONUP:
+ if (MouseUp(pos)) return FALSE;
+ break;
+ }
+
+ return FALSE;
+}
+
+// All buttons must receive the BUTTONUP event!
+
+// Indicates whether the mouse is over this button.
+
+BOOL CButton::MouseOnButton(POINT pos)
+{
+ return Detect(pos);
+}
+
+// Return the tooltips for a button, depending
+// on mouse position.
+
+int CButton::GetToolTips(POINT pos)
+{
+ int width = m_dim.x;
+ int rank;
+
+ if (m_bHide || !m_bEnable) return -1;
+
+ if (m_nbMenu > 1 && m_bMouseDown) // Drop-down submenu?
+ {
+ width += 2 + (m_dim.x - 1)*m_nbMenu;
+ }
+
+ if (pos.x < m_pos.x ||
+ pos.x > m_pos.x + width ||
+ pos.y < m_pos.y ||
+ pos.y > m_pos.y + m_dim.y) return -1;
+
+ rank = (pos.x = -(m_pos.x + 2 + 1)) / (m_dim.x - 1);
+ if (rank < 0) rank = 0;
+ if (rank > m_nbToolTips) return -1;
+
+ if (m_nbMenu > 1)
+ {
+ if (m_bMouseDown && rank > 0)
+ {
+ rank--;
+ }
+ else
+ {
+ rank = m_selMenu;
+ }
+ }
+
+ return m_toolTips[rank];
+}
+
+BOOL CButton::Detect(POINT pos)
+{
+ int width = m_dim.x;
+
+ if (m_bHide || !m_bEnable) return FALSE;
+
+ if (m_nbMenu > 1 && m_bMouseDown)
+ {
+ width += 2 + (m_dim.x - 1)*m_nbMenu;
+ }
+
+ if (pos.x < m_pos.x ||
+ pos.x > m_pos.x + width ||
+ pos.y < m_pos.y ||
+ pos.y > m_pos.y + m_dim.y) return FALSE;
+
+ return TRUE;
+}
+
+BOOL CButton::MouseMove(POINT pos)
+{
+ int selMenu = m_selMenu;
+ int mouseState;
+ BOOL BVar3;
+ int iVar4;
+ int iVar5;
+ BOOL BVar6;
+ int iVar7;
+
+ mouseState = m_mouseState;
+ BVar6 = Detect(pos);
+ BVar3 = m_bMouseDown;
+ if (!m_bMouseDown) {
+ if (!Detect(pos)) {
+ m_mouseState = m_state;
+ }
+ else {
+ m_mouseState = m_state + 2;
+ }
+ }
+ else if (Detect(pos)) {
+ m_mouseState = 1;
+ }
+ else {
+ m_mouseState = m_state;
+ }
+ if (m_nbMenu > 1 && m_bMouseDown) {
+ if ((m_pos.x + m_dim.x + 2 < pos.x))
+ {
+ m_selMenu = (pos.x - m_pos.x - m_dim.x - 2) / (m_dim.x - 1);
+ if (m_selMenu >= m_nbMenu) m_selMenu = m_nbMenu - 1;
+ }
+ }
+ if (mouseState != m_mouseState || selMenu != m_selMenu) m_bRedraw = TRUE;
+ return BVar3;
+}
+
+
+BOOL CButton::MouseDown(POINT pos)
+{
+ if (!Detect(pos)) return FALSE;
+
+ m_mouseState = 1;
+ m_bMouseDown = TRUE;
+ m_bRedraw = TRUE;
+ // PostMessage(m_hWnd, WM_UPDATE, 0, 0);
+
+ m_pSound->PlayImage(SOUND_CLICK, pos);
+ return TRUE;
+}
+
+BOOL CButton::MouseUp(POINT pos)
+{
+ BOOL bDetect;
+
+ bDetect = Detect(pos);
+
+ m_mouseState = m_state;
+ m_bMouseDown = FALSE;
+ m_bRedraw = TRUE;
+
+ if (!bDetect) return FALSE;
+
+ if (m_message != -1)
+ {
+ PostMessage(m_hWnd, m_message, 0, 0);
+ }
+
+ return TRUE;
+}
\ No newline at end of file
diff --git a/src/button.h b/src/button.h
new file mode 100644
index 0000000..a896b82
--- /dev/null
+++ b/src/button.h
@@ -0,0 +1,70 @@
+#ifndef BUTTON_H
+#define BUTTON_H
+
+#include
+
+#include "decor.h"
+#include "pixmap.h"
+#include "sound.h"
+
+class CButton
+{
+public:
+ CButton();
+ ~CButton();
+
+ BOOL Create(HWND hWnd, CPixmap *pPixmap, CSound *pSound,
+ POINT pos, int type, BOOL bMinimizeRedraw, UINT message);
+ void SetIconMenu(int* pIcons, int nbIcons);
+ void SetToolTips(int* pToolTips, int nbTooltips);
+ void Draw();
+ void Redraw();
+
+ int GetState();
+ void SetState(int state);
+
+ int GetMenu();
+ void SetMenu(int menu);
+
+ BOOL GetEnable();
+ void SetEnable(BOOL bEnable);
+
+ BOOL GetHide();
+ void SetHide(BOOL bHide);
+
+ BOOL TreatEvent(UINT message, WPARAM wParam, LPARAM lParam);
+ BOOL MouseOnButton(POINT pos);
+ int GetToolTips(POINT pos);
+
+
+protected:
+ BOOL Detect(POINT pos);
+ BOOL MouseDown(POINT pos);
+ BOOL MouseMove(POINT pos);
+ BOOL MouseUp(POINT pos);
+
+protected:
+ HWND m_hWnd;
+ CPixmap* m_pPixmap;
+ CDecor* m_pDecor;
+ CSound* m_pSound;
+ int m_type; // type de bouton
+ BOOL m_bEnable; // TRUE si bouton actif
+ int m_bLocked;
+ BOOL m_bHide; // TRUE si bouton caché
+ UINT m_message; // message envoyé si bouton actionné
+ POINT m_pos; // coin sup/gauche
+ POINT m_dim; // dimensions
+ int m_state;
+ int m_mouseState;
+ int m_iconMenu[20]; // icônes du sous-menu
+ int m_toolTips[20]; // info-bulles
+ int m_nbMenu; // nb de case du sous-menu
+ int m_nbToolTips; // nb d'info-bulles
+ int m_selMenu;
+ BOOL m_bMouseDown; // TRUE -> bouton souris pressé
+ BOOL m_bMinimizeRedraw;
+ BOOL m_bRedraw;
+};
+
+#endif
\ No newline at end of file
diff --git a/src/ddutil.cpp b/src/ddutil.cpp
new file mode 100644
index 0000000..1cb9610
--- /dev/null
+++ b/src/ddutil.cpp
@@ -0,0 +1,342 @@
+/*==========================================================================
+ *
+ * Copyright (C) 1995-1997 Microsoft Corporation. All Rights Reserved.
+ *
+ * File: ddutil.cpp
+ * Content: Routines for loading bitmap and palettes from resources
+ *
+ ***************************************************************************/
+#undef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#include
+#include
+#include
+#include
+#include
+#include "ddutil.h"
+#include "misc.h"
+
+BOOL g_bDebug = TRUE;
+
+void DDSetDebug(BOOL bDebug)
+{
+ g_bDebug = bDebug;
+}
+
+
+/*
+ * DDLoadBitmap
+ *
+ * create a DirectDrawSurface from a bitmap resource.
+ *
+ */
+extern "C" IDirectDrawSurface * DDLoadBitmap(IDirectDraw *pdd, LPCSTR szBitmap, int dx, int dy)
+{
+ HBITMAP hbm;
+ BITMAP bm;
+ DDSURFACEDESC ddsd;
+ IDirectDrawSurface *pdds;
+
+ //
+ // try to load the bitmap as a resource, if that fails, try it as a file
+ //
+ hbm = (HBITMAP)LoadImageA(GetModuleHandle(NULL), szBitmap, IMAGE_BITMAP, dx, dy, LR_CREATEDIBSECTION);
+
+ if (hbm == NULL)
+ hbm = (HBITMAP)LoadImageA(NULL, szBitmap, IMAGE_BITMAP, dx, dy, LR_LOADFROMFILE|LR_CREATEDIBSECTION);
+
+ if (hbm == NULL)
+ return NULL;
+
+ //
+ // get size of the bitmap
+ //
+ GetObject(hbm, sizeof(bm), &bm); // get size of bitmap
+
+ //
+ // create a DirectDrawSurface for this bitmap
+ //
+ ZeroMemory(&ddsd, sizeof(ddsd));
+ ddsd.dwSize = sizeof(ddsd);
+ ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+ ddsd.dwWidth = bm.bmWidth;
+ ddsd.dwHeight = bm.bmHeight;
+
+ if (pdd->CreateSurface(&ddsd, &pdds, NULL) != DD_OK)
+ return NULL;
+
+ DDCopyBitmap(pdds, hbm, 0, 0, 0, 0);
+
+ DeleteObject(hbm);
+
+ return pdds;
+}
+
+/*
+ * DDReLoadBitmap
+ *
+ * load a bitmap from a file or resource into a directdraw surface.
+ * normaly used to re-load a surface after a restore.
+ *
+ */
+HRESULT DDReLoadBitmap(IDirectDrawSurface *pdds, LPCSTR szBitmap)
+{
+ HBITMAP hbm;
+ HRESULT hr;
+
+ //
+ // try to load the bitmap as a resource, if that fails, try it as a file
+ //
+ hbm = (HBITMAP)LoadImageA(GetModuleHandle(NULL), szBitmap, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
+
+ if (hbm == NULL)
+ hbm = (HBITMAP)LoadImageA(NULL, szBitmap, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION);
+
+ if (hbm == NULL)
+ {
+ OutputDebugStringA("handle is null\n");
+ return E_FAIL;
+ }
+
+ hr = DDCopyBitmap(pdds, hbm, 0, 0, 0, 0);
+ if (hr != DD_OK)
+ {
+ OutputDebugStringA("ddcopybitmap failed\n");
+ }
+
+
+ DeleteObject(hbm);
+ return hr;
+}
+
+/*
+ * DDCopyBitmap
+ *
+ * draw a bitmap into a DirectDrawSurface
+ *
+ */
+extern "C" HRESULT DDCopyBitmap(IDirectDrawSurface *pdds, HBITMAP hbm, int x, int y, int dx, int dy)
+{
+ HDC hdcImage;
+ HDC hdc;
+ BITMAP bm;
+ DDSURFACEDESC ddsd;
+ HRESULT hr;
+
+ if (hbm == NULL || pdds == NULL)
+ return E_FAIL;
+
+ //
+ // make sure this surface is restored.
+ //
+ pdds->Restore();
+
+ //
+ // select bitmap into a memoryDC so we can use it.
+ //
+ hdcImage = CreateCompatibleDC(NULL);
+ if (!hdcImage)
+ OutputDebugStringA("createcompatible dc failed\n");
+ SelectObject(hdcImage, hbm);
+
+ //
+ // get size of the bitmap
+ //
+ GetObject(hbm, sizeof(bm), &bm); // get size of bitmap
+ dx = dx == 0 ? bm.bmWidth : dx; // use the passed size, unless zero
+ dy = dy == 0 ? bm.bmHeight : dy;
+
+ //
+ // get size of surface.
+ //
+ ddsd.dwSize = sizeof(ddsd);
+ ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH;
+ pdds->GetSurfaceDesc(&ddsd);
+
+ if ((hr = pdds->GetDC(&hdc)) == DD_OK)
+ {
+ StretchBlt(hdc, 0, 0, ddsd.dwWidth, ddsd.dwHeight, hdcImage, x, y, dx, dy, SRCCOPY);
+ pdds->ReleaseDC(hdc);
+ }
+
+ DeleteDC(hdcImage);
+
+ return hr;
+}
+
+//
+// DDLoadPalette
+//
+// Create a DirectDraw palette object from a bitmap resoure
+//
+// if the resource does not exist or NULL is passed create a
+// default 332 palette.
+//
+extern "C" IDirectDrawPalette * DDLoadPalette(IDirectDraw *pdd, LPCSTR szBitmap)
+{
+ IDirectDrawPalette* ddpal;
+ int i;
+ int n;
+ int fh;
+ HRSRC h;
+ LPBITMAPINFOHEADER lpbi;
+ PALETTEENTRY ape[256];
+ RGBQUAD * prgb;
+
+ //
+ // build a 332 palette as the default.
+ //
+ for (i=0; i<256; i++)
+ {
+ ape[i].peRed = (BYTE)(((i >> 5) & 0x07) * 255 / 7);
+ ape[i].peGreen = (BYTE)(((i >> 2) & 0x07) * 255 / 7);
+ ape[i].peBlue = (BYTE)(((i >> 0) & 0x03) * 255 / 3);
+ ape[i].peFlags = (BYTE)0;
+ }
+
+ //
+ // get a pointer to the bitmap resource.
+ //
+ if (szBitmap && (h = FindResourceA(NULL, szBitmap, (LPCSTR)RT_BITMAP)))
+ {
+ lpbi = (LPBITMAPINFOHEADER)LockResource(LoadResource(NULL, h));
+ if (!lpbi)
+ OutputDebugStringA("lock resource failed\n");
+ prgb = (RGBQUAD*)((BYTE*)lpbi + lpbi->biSize);
+
+ if (lpbi == NULL || lpbi->biSize < sizeof(BITMAPINFOHEADER))
+ n = 0;
+ else if (lpbi->biBitCount > 8)
+ n = 0;
+ else if (lpbi->biClrUsed == 0)
+ n = 1 << lpbi->biBitCount;
+ else
+ n = lpbi->biClrUsed;
+
+ //
+ // a DIB color table has its colors stored BGR not RGB
+ // so flip them around.
+ //
+ for(i=0; i 8)
+ n = 0;
+ else if (bi.biClrUsed == 0)
+ n = 1 << bi.biBitCount;
+ else
+ n = bi.biClrUsed;
+
+ //
+ // a DIB color table has its colors stored BGR not RGB
+ // so flip them around.
+ //
+ for(i=0; iCreatePalette(DDPCAPS_8BIT, ape, &ddpal, NULL);
+
+ return ddpal;
+}
+
+/*
+ * DDColorMatch
+ *
+ * convert a RGB color to a pysical color.
+ *
+ * we do this by leting GDI SetPixel() do the color matching
+ * then we lock the memory and see what it got mapped to.
+ */
+extern "C" DWORD DDColorMatch(IDirectDrawSurface *pdds, COLORREF rgb)
+{
+ COLORREF rgbT;
+ HDC hdc;
+ DWORD dw = CLR_INVALID;
+ DDSURFACEDESC ddsd;
+ HRESULT hres;
+
+ //
+ // use GDI SetPixel to color match for us
+ //
+ if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
+ {
+ rgbT = GetPixel(hdc, 0, 0); // save current pixel value
+ SetPixel(hdc, 0, 0, rgb); // set our value
+ pdds->ReleaseDC(hdc);
+ }
+
+ //
+ // now lock the surface so we can read back the converted color
+ //
+ ddsd.dwSize = sizeof(ddsd);
+ while ((hres = pdds->Lock(NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING)
+ ;
+
+ if (hres == DD_OK)
+ {
+ dw = *(DWORD *)ddsd.lpSurface; // get DWORD
+ if(ddsd.ddpfPixelFormat.dwRGBBitCount < 32)
+ dw &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount)-1; // mask it to bpp
+ pdds->Unlock(NULL);
+ }
+
+ //
+ // now put the color that was there back.
+ //
+ if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
+ {
+ SetPixel(hdc, 0, 0, rgbT);
+ pdds->ReleaseDC(hdc);
+ }
+
+ return dw;
+}
+
+/*
+ * DDSetColorKey
+ *
+ * set a color key for a surface, given a RGB.
+ * if you pass CLR_INVALID as the color key, the pixel
+ * in the upper-left corner will be used.
+ */
+extern "C" HRESULT DDSetColorKey(IDirectDrawSurface *pdds, COLORREF rgb)
+{
+ DDCOLORKEY ddck;
+
+ ddck.dwColorSpaceLowValue = DDColorMatch(pdds, rgb);
+ ddck.dwColorSpaceHighValue = ddck.dwColorSpaceLowValue;
+ return pdds->SetColorKey(DDCKEY_SRCBLT, &ddck);
+}
+
+extern "C" HRESULT DDSetColorKey2(IDirectDrawSurface* pdds, COLORREF rgb1,
+ COLORREF rgb2)
+{
+ DDCOLORKEY ddck;
+
+ ddck.dwColorSpaceLowValue = DDColorMatch(pdds, rgb1);
+ ddck.dwColorSpaceHighValue = DDColorMatch(pdds, rgb2);
+ return pdds->SetColorKey(DDCKEY_SRCBLT, &ddck);
+}
\ No newline at end of file
diff --git a/src/ddutil.h b/src/ddutil.h
new file mode 100644
index 0000000..1490d25
--- /dev/null
+++ b/src/ddutil.h
@@ -0,0 +1,33 @@
+#ifndef DDUTIL_H
+#define DDUTIL_H
+/*==========================================================================
+ *
+ * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
+ *
+ * File: ddutil.cpp
+ * Content: Routines for loading bitmap and palettes from resources
+ *
+ ***************************************************************************/
+
+#define DIRECTDRAW_VERSION 0x0500
+
+#include
+
+#ifdef __cplusplus
+extern "C" { /* Assume C declarations for C++ */
+#endif /* __cplusplus */
+
+extern void DDSetDebug(BOOL bDebug);
+extern IDirectDrawPalette * DDLoadPalette(IDirectDraw *pdd, LPCSTR szBitmap);
+extern IDirectDrawSurface * DDLoadBitmap(IDirectDraw *pdd, LPCSTR szBitmap, int dx, int dy);
+extern HRESULT DDReLoadBitmap(IDirectDrawSurface *pdds, LPCSTR szBitmap);
+extern HRESULT DDCopyBitmap(IDirectDrawSurface *pdds, HBITMAP hbm, int x, int y, int dx, int dy);
+extern DWORD DDColorMatch(IDirectDrawSurface *pdds, COLORREF rgb);
+extern HRESULT DDSetColorKey(IDirectDrawSurface *pdds, COLORREF rgb);
+extern HRESULT DDSetColorKey2(IDirectDrawSurface* pdds, COLORREF rgb1, COLORREF rgb2);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
\ No newline at end of file
diff --git a/src/decblock.cpp b/src/decblock.cpp
new file mode 100644
index 0000000..b4600e8
--- /dev/null
+++ b/src/decblock.cpp
@@ -0,0 +1,802 @@
+// DecBlock.cpp
+//
+
+#include "def.h"
+#include "decor.h"
+#include "misc.h"
+#include "obstacle.h"
+#include "dectables.h"
+
+BOOL CDecor::BlitzActif(POINT cel)
+{
+ if (m_phase == WM_PHASE_BUILD) {
+ //TODO: rewrite this like a human
+ int foo = m_time >> 31;
+ return 1 - (((m_time ^ foo) - foo & 1 ^ foo) == foo);
+ }
+
+ POINT pos = { cel.x * DIMOBJX, cel.y * DIMOBJY };
+
+ int num = m_time % 100;
+
+ if (m_blupiPos.x >= pos.x - 80 && m_blupiPos.x <= pos.x + 80 &&
+ m_blupiPos.y >= pos.y - 500 && m_blupiPos.y <= pos.y + 500)
+ {
+ if (m_time % 100 < 70 && cel.y > 0 && m_decor[cel.x][cel.y - 1].icon == 0x130)
+ {
+ PlaySound(SOUND_BLITZ, pos, 0);
+ }
+
+ for (int i = 0; table_blitz[i] != -1; i++)
+ {
+ if (m_time % 100 == i) return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+int CDecor::SoundEnviron(int sound, int obstacle)
+{
+ if ((obstacle >= 32 && obstacle <= 34) || (obstacle >= 41 && obstacle <= 47) || (obstacle >= 139 && obstacle <= 143))
+ {
+ if (sound == SOUND_JUMPTOC)
+ {
+ return 79;
+ }
+ if (sound == SOUND_JUMPEND)
+ {
+ return 78;
+ }
+ }
+ if ((obstacle >= 1 && obstacle <= 28) || (obstacle >= 78 && obstacle <= 90) || (obstacle >= 250 && obstacle <= 260) || (obstacle >= 311 && obstacle <= 316) || (obstacle >= 324 && obstacle <= 329))
+ {
+ if (sound == SOUND_JUMPTOC)
+ {
+ return 81;
+ }
+ if (sound == SOUND_JUMPEND)
+ {
+ return 80;
+ }
+ }
+ if ((obstacle >= 284 && obstacle <= 303) || obstacle == 338)
+ {
+ if (sound == SOUND_JUMPTOC)
+ {
+ return 83;
+ }
+ if (sound == SOUND_JUMPEND)
+ {
+ return 82;
+ }
+ }
+ if (obstacle >= 341 && obstacle <= 363)
+ {
+ if (sound == SOUND_JUMPTOC)
+ {
+ return 85;
+ }
+ if (sound == SOUND_JUMPEND)
+ {
+ return 84;
+ }
+ }
+ if (obstacle >= 215 && obstacle <= 234)
+ {
+ if (sound == SOUND_JUMPTOC)
+ {
+ return 87;
+ }
+ if (sound == SOUND_JUMPEND)
+ {
+ return 86;
+ }
+ }
+ if (obstacle >= 246 && obstacle <= 249)
+ {
+ if (sound == SOUND_JUMPTOC)
+ {
+ return 89;
+ }
+ if (sound == SOUND_JUMPEND)
+ {
+ return 88;
+ }
+ }
+ if (obstacle >= 107 && obstacle <= 109)
+ {
+ if (sound == SOUND_JUMPTOC)
+ {
+ return 91;
+ }
+ if (sound == SOUND_JUMPEND)
+ {
+ return 90;
+ }
+ }
+ return sound;
+}
+
+
+int CDecor::IsWorld(POINT pos)
+{
+ pos.x += 30;
+ pos.y += 30;
+ if (pos.x < 0 || pos.x >= DIMOBJX * MAXCELX || pos.y < 0 || pos.y >= DIMOBJY * MAXCELY)
+ {
+ return -1;
+ }
+ int icon = m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY].icon;
+ if (icon >= Object::World_1 && icon <= Object::World_8)
+ {
+ return icon - Object::World_1 + 1;
+ }
+ if (icon >= Object::WorldDone_1 && icon <= Object::WorldDone_8)
+ {
+ return icon - Object::WorldDone_1 + 1;
+ }
+ if (icon == Object::World_9 || icon == Object::WorldDone_9)
+ {
+ return 9;
+ }
+ if (icon >= Object::World_10 && icon <= Object::World_14)
+ {
+ return icon - Object::World_10 + 10;
+ }
+ if (icon >= Object::WorldDone_10 && icon <= Object::WorldDone_14)
+ {
+ return icon - Object::WorldDone_10 + 10;
+ }
+ if (icon >= Object::Level_1 && icon <= Object::Level_8)
+ {
+ return icon - Object::Level_1 + 1;
+ }
+ if (icon == Object::WorldBack)
+ {
+ return 199;
+ }
+ return -1;
+}
+
+void CDecor::ActiveSwitch(BOOL bState, POINT cel)
+{
+ POINT pos;
+ pos.x = cel.x * DIMOBJX;
+ pos.y = cel.y * DIMOBJY;
+ ModifDecor(pos, bState ? 384 : 385);
+ PlaySound(bState ? 77 : 76, pos);
+ cel.x -= 20;
+ for (int i = 0; i < 41; i++)
+ {
+ if (cel.x >= 0 && cel.x < 100 && m_decor[cel.x][cel.y].icon == (bState ? 379 : 378))
+ {
+ pos.x = cel.x * DIMOBJX;
+ pos.y = cel.y * DIMOBJY;
+ ModifDecor(pos, bState ? 378 : 379);
+ }
+ cel.x++;
+ }
+}
+
+int CDecor::GetTypeBarre(POINT pos)
+{
+ POINT pos2 = pos;
+ pos.x += 30;
+ pos.y += 22;
+ if (pos.y % 64 > 44)
+ {
+ return 0;
+ }
+ if (pos.x < 0 || pos.x >= 6400 || pos.y < 0 || pos.y >= 6400)
+ {
+ return 0;
+ }
+ int icon = m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY].icon;
+ if (icon != 138 && icon != 202)
+ {
+ return 0;
+ }
+ if (pos.y >= 6336)
+ {
+ return 1;
+ }
+ icon = m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY + 1].icon;
+ if (IsPassIcon(icon))
+ {
+ return 2;
+ }
+ RECT rect = BlupiRect(pos2);
+ rect.top = pos2.y + 60 - 2;
+ rect.bottom = pos2.y + 60 - 1;
+ if (DecorDetect(rect, TRUE))
+ {
+ return 2;
+ }
+ return 1;
+}
+
+BOOL CDecor::IsLave(POINT pos)
+{
+ pos.x += DIMBLUPIX / 2;
+ return pos.x >= 0 && pos.x < 6400 && pos.y >= 0 && pos.y < 6400 && m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY].icon == 68;
+}
+
+BOOL CDecor::IsPiege(POINT pos)
+{
+ pos.x += DIMBLUPIX / 2;
+ pos.y += DIMBLUPIY;
+ return pos.x % 64 >= 15 && pos.x % 64 <= 49 && pos.x >= 0 && pos.x < 6400 && pos.y >= 0 && pos.y < 6400 && m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY].icon == 373;
+}
+
+BOOL CDecor::IsGoutte(POINT pos, BOOL bAlways)
+{
+ pos.x += DIMBLUPIX / 2;
+ if (pos.x % 64 < 15 || pos.x % 64 > 49)
+ {
+ return FALSE;
+ }
+ if (pos.x < 0 || pos.x >= 6400 || pos.y < 0 || pos.y >= 6400)
+ {
+ return FALSE;
+ }
+ int icon = m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY].icon;
+ if (bAlways)
+ {
+ return icon == 404 || icon == 410;
+ }
+ return icon == 404;
+}
+
+BOOL CDecor::IsScie(POINT pos)
+{
+ pos.x += DIMBLUPIX / 2;
+ return pos.x % 64 >= 4 && pos.x % 64 <= 60 && pos.x >= 0 && pos.x < 6400 && pos.y >= 0 && pos.y < 6400 && m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY].icon == 378;
+}
+
+BOOL CDecor::IsSwitch(POINT pos, POINT *outCelSwitch)
+{
+ pos.x += DIMBLUPIX / 2;
+ if (pos.x % DIMOBJX < 4 || pos.x % DIMOBJX > DIMOBJX - 4)
+ {
+ return FALSE;
+ }
+ if (pos.x < 0 || pos.x >= DIMOBJX * MAXCELX || pos.y < 0 || pos.y >= DIMOBJY * MAXCELY)
+ {
+ return FALSE;
+ }
+ outCelSwitch->x = pos.x / DIMOBJX;
+ outCelSwitch->y = pos.y / DIMOBJY;
+ return m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY].icon == 384 || m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY].icon == 385;
+}
+
+BOOL CDecor::IsEcraseur(POINT pos)
+{
+ if (m_time / 3 % 10 > 2)
+ {
+ return FALSE;
+ }
+ pos.x += 30;
+ return pos.x >= 0 && pos.x < 6400 && pos.y >= 0 && pos.y < 6400 && m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY].icon == 317;
+}
+
+BOOL CDecor::IsBlitz(POINT pos, BOOL bAlways)
+{
+ pos.x += 30;
+ if (pos.x < 0 || pos.x >= 6400 || pos.y < 0 || pos.y >= 6400)
+ {
+ return FALSE;
+ }
+ POINT tinyPoint;
+ tinyPoint.x = pos.x / DIMOBJX;
+ tinyPoint.y = pos.y / DIMOBJY;
+ return m_decor[tinyPoint.x][tinyPoint.y].icon == 305 && (bAlways || BlitzActif(tinyPoint));
+}
+
+BOOL CDecor::IsRessort(POINT pos)
+{
+ pos.x += 30;
+ pos.y += 60;
+ return pos.x >= 0 && pos.x < 6400 && pos.y >= 0 && pos.y < 6400 && m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY].icon == 211;
+}
+
+BOOL CDecor::IsTemp(POINT pos)
+{
+ pos.x += 30;
+ pos.y += 60;
+ return pos.x >= 0 && pos.x < 6400 && pos.y >= 0 && pos.y < 6400 && m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY].icon == 324;
+}
+
+BOOL CDecor::IsBridge(POINT pos, POINT *outCelBridge)
+{
+ pos.x += 30;
+ pos.y += 60;
+ if (pos.x >= 0 && pos.x < 6400 && pos.y >= 0 && pos.y < 6400 && m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY].icon == 364)
+ {
+ outCelBridge->x = pos.x / DIMOBJX;
+ outCelBridge->y = pos.y / DIMOBJY;
+ return TRUE;
+ }
+ pos.y -= 60;
+ if (pos.x >= 0 && pos.x < 6400 && pos.y >= 0 && pos.y < 6400 && m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY].icon == 364)
+ {
+ outCelBridge->x = pos.x / DIMOBJX;
+ outCelBridge->y = pos.y / DIMOBJY;
+ return TRUE;
+ }
+ return FALSE;
+
+}
+
+int CDecor::IsDoor(POINT pos, POINT *outCelPorte)
+{
+ int num;
+ if (m_blupiDir == 1)
+ {
+ num = -60;
+ }
+ else
+ {
+ num = 60;
+ }
+ pos.x += 30;
+ for (int i = 0; i < 2; i++)
+ {
+ if (pos.x >= 0 && pos.x < DIMOBJX * MAXCELX && pos.y >= 0 && pos.y < DIMOBJY * MAXCELY && m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY].icon >= 334 && m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY].icon <= 336)
+ {
+ outCelPorte->x = pos.x / DIMOBJX;
+ outCelPorte->y = pos.y / DIMOBJY;
+ return m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY].icon;
+ }
+ pos.x += num;
+ }
+ return -1;
+}
+
+int CDecor::IsTeleporte(POINT pos)
+{
+ if (pos.x % DIMOBJX > 6)
+ {
+ return -1;
+ }
+ pos.x += 30;
+ pos.y -= 60;
+ if (pos.x < 0 || pos.x >= DIMOBJX * MAXCELX || pos.y < 0 || pos.y >= DIMOBJY * MAXCELY)
+ {
+ return -1;
+ }
+ if (m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY].icon >= 330 && m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY].icon <= 333)
+ {
+ return m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY].icon;
+ }
+ return -1;
+}
+
+BOOL CDecor::SearchTeleporte(POINT pos, POINT *newpos)
+{
+ int num = IsTeleporte(pos);
+ if (num == -1)
+ {
+ return FALSE;
+ }
+ for (int i = 0; i < 100; i++)
+ {
+ for (int j = 0; j < 100; j++)
+ {
+ if (num == m_decor[i][j].icon)
+ {
+ newpos->x = i * 64;
+ newpos->y = j * 64 + 60;
+ if (newpos->x < pos.x - 40 || newpos->x > pos.x + 40 || newpos->y < pos.y - 40 || newpos->y > pos.y + 40)
+ {
+ return TRUE;
+ }
+ }
+ }
+ }
+ return FALSE;
+}
+
+BOOL CDecor::IsSurfWater(POINT pos)
+{
+ if (pos.y % 64 < 64 - BLUPISURF)
+ {
+ return FALSE;
+ }
+ int icon = m_decor[(pos.x + 30) / 64][pos.y / DIMOBJY].icon;
+ int icon2 = m_decor[(pos.x + 30) / 64][(pos.y + BLUPISURF) / 64].icon;
+ return icon != 92 && icon2 == 92;
+}
+
+BOOL CDecor::IsDeepWater(POINT pos)
+{
+ int num = (pos.x + 30) / 64;
+ int num2 = pos.y / DIMOBJY;
+ if (num < 0 || num >= 100 || num2 < 0 || num2 >= 100)
+ {
+ return FALSE;
+ }
+ int icon = m_decor[num][num2].icon;
+ return icon == 91 || icon == 92;
+}
+
+BOOL CDecor::IsOutWater(POINT pos)
+{
+ int icon = m_decor[(pos.x + 30) / 64][(pos.y + 30) / 64].icon;
+ return icon != 91 && icon != 92 && IsPassIcon(icon);
+}
+
+BOOL CDecor::IsPassIcon(int icon)
+{
+ if (icon == 324 && m_time / 4 % 20 >= 18)
+ {
+ return TRUE;
+ }
+ if (icon >= 0 && icon < MAXQUART)
+ {
+ for (int i = 0; i < 16; i++)
+ {
+ if (table_decor_quart[icon * 16 + i] != 0)
+ {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+BOOL CDecor::IsBlocIcon(int icon)
+{
+ if (icon < 0 || icon >= MAXQUART)
+ {
+ return FALSE;
+ }
+ if (icon == 324 && m_time / 4 % 20 < 18)
+ {
+ return FALSE;
+ }
+ for (int i = 0; i < 16; i++)
+ {
+ if (table_decor_quart[icon * 16 + i] == 0)
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+BOOL CDecor::IsVentillo(POINT pos)
+{
+ int num = 0;
+ BOOL flag = FALSE;
+ POINT tinyPoint;
+ pos.x += 30;
+ pos.y += 30;
+ if (pos.x < 0 || pos.x >= 6400 || pos.y < 0 || pos.y >= 6400)
+ {
+ return FALSE;
+ }
+ int icon = m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY].icon;
+ if (icon < 126 || icon > 137)
+ {
+ return FALSE;
+ }
+ if (icon == 126)
+ {
+ if (pos.x % 64 <= 16)
+ {
+ flag = TRUE;
+ }
+ tinyPoint.x = -64;
+ tinyPoint.y = 0;
+ num = 110;
+ }
+ if (icon == 129)
+ {
+ if (pos.x % 64 >= 48)
+ {
+ flag = TRUE;
+ }
+ tinyPoint.x = 64;
+ tinyPoint.y = 0;
+ num = 114;
+ }
+ if (icon == 132)
+ {
+ if (pos.y % 64 <= 32)
+ {
+ flag = TRUE;;
+ }
+ tinyPoint.x = 0;
+ tinyPoint.y = -64;
+ num = 118;
+ }
+ if (icon == 135)
+ {
+ if (pos.y % 64 >= 48)
+ {
+ flag = TRUE;
+ }
+ tinyPoint.x = 0;
+ tinyPoint.y = 64;
+ num = 122;
+ }
+ if (!flag)
+ {
+ return FALSE;
+ }
+ ModifDecor(pos, -1);
+ do
+ {
+ pos.x += tinyPoint.x;
+ pos.y += tinyPoint.y;
+ if (num != m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY].icon)
+ {
+ break;
+ }
+ ModifDecor(pos, -1);
+ } while (pos.x >= 0 && pos.x < 6400 && pos.y >= 0 && pos.y < 6400);
+ return TRUE;
+}
+
+void CDecor::ModifDecor(POINT pos, int icon, BOOL bMulti)
+{// TODO: this
+ int icon2 = m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY].icon;
+ if (icon == -1 && icon >= 126 && icon2 <= 137)
+ {
+
+ }
+ m_decor[pos.x / DIMOBJX][pos.y / DIMOBJY].icon = icon;
+}
+
+BOOL CDecor::IsRightBorder(POINT pos, POINT offset)
+{
+ int icon;
+
+ if (pos.x >= 0
+ && pos.x < (m_dimDecor.x != 0 ? 100 : 10)
+ && pos.y >= 0
+ && pos.y < (m_dimDecor.y != 0 ? 100 : 8))
+ {
+ icon = m_decor[offset.x][100 * pos.x + pos.y + offset.y].icon;
+ if (icon >= 386 && icon <= 397 || icon == 400)
+ {
+ int icon2 = m_decor[pos.x][pos.y].icon;
+ return icon2 >= 386 && icon2 <= 397 || icon2 == 400;
+ }
+ if (icon >= 250 && icon <= 260)
+ {
+ int icon3 = m_decor[pos.x][pos.y].icon;
+ return icon3 >= 250 && icon <= 260;
+ }
+ int num = m_decor[pos.x][pos.y].icon;
+
+ switch (num)
+ {
+
+ }
+ }
+
+ return FALSE; // temp.
+}
+
+
+BOOL CDecor::IsFromage(POINT cel)
+{
+ if (!IsValidCel(cel)) return FALSE;
+
+ int icon = m_decor[cel.x][cel.y].icon;
+ return (icon >= 246 && icon <= 249) || icon == 339;
+}
+
+BOOL CDecor::IsGrotte(POINT cel)
+{
+ if (!IsValidCel(cel)) return FALSE;
+
+ int icon = m_decor[cel.x][cel.y].icon;
+ return icon = 284 || icon == 301 || icon == 337;
+}
+
+void CDecor::AdaptMidBorder(POINT cel)
+{
+ if (!IsValidCel(cel)) return;
+
+ int num = 15;
+ if (!IsRightBorder(POINT( cel.x, cel.y + 1 ), POINT( 0, -1 )))
+ {
+ num &= -2;
+ }
+ if (!IsRightBorder(POINT( cel.x, cel.y + 1 ), POINT( 0, 1 )))
+ {
+ num &= -3;
+ }
+ if (!IsRightBorder(POINT( cel.x + 1, cel.y ), POINT( -1, 0 )))
+ {
+ num &= -5;
+ }
+ if (!IsRightBorder(POINT( cel.x - 1, cel.y ), POINT( 1, 0 )))
+ {
+ num &= -9;
+ }
+ int num2 = m_decor[cel.x][cel.y].icon;
+ if (num2 == 156)
+ {
+ num2 = 35;
+ }
+ if (num2 == 252 || num2 == 253)
+ {
+ num2 = 251;
+ }
+ if (num2 == 255)
+ {
+ num2 = 254;
+ }
+ if (num2 == 362)
+ {
+ num2 = 347;
+ }
+ if (num2 == 363)
+ {
+ num2 = 348;
+ }
+ if (num2 >= 341 && num2 <= 346)
+ {
+ num2 = 341;
+ }
+ for (int i = 0; i < 144; i++)
+ {
+ if (num2 == table_adapt_decor[i])
+ {
+ num2 = table_adapt_decor[i / 16 * 16 + num];
+ if (num2 == 35 && rand() % 2 == 0)
+ {
+ num2 = 156;
+ }
+ if (num2 == 251)
+ {
+ num2 = Random(251, 253);
+ }
+ if (num2 == 254 && rand() % 2 == 0)
+ {
+ num2 = 255;
+ }
+ if (num2 == 347 && rand() % 2 == 0)
+ {
+ num2 = 362;
+ }
+ if (num2 == 348 && rand() % 2 == 0)
+ {
+ num2 = 363;
+ }
+ if (num2 == 341)
+ {
+ num2 = Random(341, 346);
+ }
+ m_decor[cel.x][cel.y].icon = num2;
+ return;
+ }
+ }
+ num2 = m_decor[cel.x][cel.y].icon;
+ if (num2 == -1 || (num2 >= 264 && num2 <= 282))
+ {
+ num = 15;
+ if (!IsFromage(POINT(cel.x, cel.y + 1)))
+ {
+ num &= -2;
+ }
+ if (!IsFromage(POINT(cel.x, cel.y - 1)))
+ {
+ num &= -3;
+ }
+ if (!IsFromage(POINT(cel.x + 1, cel.y)))
+ {
+ num &= -5;
+ }
+ if (!IsFromage(POINT(cel.x - 1, cel.y)))
+ {
+ num &= -9;
+ }
+ num2 = table_adapt_fromage[num];
+ if (num2 == 268 && rand() % 2 == 0)
+ {
+ num2 = 279;
+ }
+ if (num2 == 269 && rand() % 2 == 0)
+ {
+ num2 = 280;
+ }
+ if (num2 == 264 && rand() % 2 == 0)
+ {
+ num2 = 281;
+ }
+ if (num2 == 265 && rand() % 2 == 0)
+ {
+ num2 = 282;
+ }
+ m_decor[cel.x][cel.y].icon = num2;
+ }
+ num2 = m_decor[cel.x][cel.y].icon;
+ if (num2 == -1 || (num2 >= 285 && num2 <= 303 && num2 != 301))
+ {
+ num = 15;
+ if (!IsGrotte(POINT(cel.x, cel.y + 1)))
+ {
+ num &= -2;
+ }
+ if (!IsGrotte(POINT(cel.x, cel.y - 1)))
+ {
+ num &= -3;
+ }
+ if (!IsGrotte(POINT(cel.x + 1, cel.y)))
+ {
+ num &= -5;
+ }
+ if (!IsGrotte(POINT(cel.x - 1, cel.y)))
+ {
+ num &= -9;
+ }
+ num2 = table_adapt_fromage[num + 16];
+ if (num2 == 289 && rand() % 2 == 0)
+ {
+ num2 = 300;
+ }
+ if (num2 == 285 && rand() % 2 == 0)
+ {
+ num2 = 302;
+ }
+ if (num2 == 286 && rand() % 2 == 0)
+ {
+ num2 = 303;
+ }
+ m_decor[cel.x][cel.y].icon = num2;
+ }
+}
+
+void CDecor::AdaptBorder(POINT cel)
+{
+ AdaptMidBorder(cel);
+ AdaptMidBorder(POINT(cel.x + 1, cel.y));
+ AdaptMidBorder(POINT(cel.x - 1, cel.y));
+ AdaptMidBorder(POINT(cel.x, cel.y + 1));
+ AdaptMidBorder(POINT(cel.x, cel.y - 1));
+ int icon = m_decor[cel.x][cel.y].icon;
+ if (icon != -1 && !IsPassIcon(icon))
+ {
+ MoveObjectDelete(cel);
+ }
+ icon = m_decor[cel.x][cel.y].icon;
+ if (icon == 304)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ cel.y++;
+ if (cel.y >= 100)
+ {
+ break;
+ }
+ icon = m_decor[cel.x][cel.y].icon;
+ if (icon != -1)
+ {
+ break;
+ }
+ m_decor[cel.x][cel.y].icon = 305;
+ }
+ }
+ if (icon == -1)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ cel.y++;
+ if (cel.y >= 100)
+ {
+ return;
+ }
+ icon = m_decor[cel.x][cel.y].icon;
+ if (icon != 305)
+ {
+ return;
+ }
+ m_decor[cel.x][cel.y].icon = -1;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/decblupi.cpp b/src/decblupi.cpp
new file mode 100644
index 0000000..6367b4b
--- /dev/null
+++ b/src/decblupi.cpp
@@ -0,0 +1,4392 @@
+// DecBlupi.cpp
+//
+
+#include "misc.h"
+#include "decor.h"
+#include "text.h" // debug
+//#include "resource.h"
+#include "dectables.h"
+
+// get the graphics channel corresponding to Blupi's team
+// (for Personal bomb, etc)
+int CDecor::GetBlupiChannelStandard()
+{
+ if (m_bMulti && m_blupiChannel == CHBLUPI && m_team > 0) {
+ return m_team + CHBLUPI1 - 1;
+ }
+ else return m_blupiChannel;
+}
+
+// get Blupi's current graphics channel
+// (changes for certain effects such as burned or glued)
+int CDecor::GetBlupiChannelActual()
+{
+ if (m_bMulti && m_team > 0) {
+ return m_team + CHBLUPI1 - 1;
+ }
+ else return CHBLUPI;
+}
+
+// get various flags relating to Blupi's current state
+void CDecor::GetBlupiInfo(BOOL* bHelico, BOOL* bJeep, BOOL* bSkate, BOOL* bNage)
+{
+ *bHelico = m_blupiHelico;
+ *bJeep = m_blupiJeep | m_blupiTank;
+ *bSkate = m_blupiSkate;
+ *bNage = m_blupiNage | m_blupiSurf;
+}
+
+// set blupi's current graphics icon according to his state
+// from ghidra
+void CDecor::BlupiSearchIcon()
+
+{
+ int phase;
+ int action = m_blupiAction;
+ int icon = 2;
+
+ if (m_blupiVent && !m_blupiHelico && !m_blupiOver)
+ {
+ if (action == ACTION_STOP) action = ACTION_VERTIGO;
+ if (action == ACTION_MARCH) action = ACTION_PUSH;
+ }
+
+ if (m_blupiHelico)
+ {
+ if (action == ACTION_STOP) action = ACTION_STOPHELICO;
+ if (action == ACTION_MARCH) action = ACTION_MARCHHELICO;
+ if (action == ACTION_TURN) action = ACTION_TURNHELICO;
+ if (action == ACTION_ADVANCE) action = ACTION_STOPHELICO;
+ if (action == ACTION_RECEDE) action = ACTION_STOPHELICO;
+ }
+
+ if (m_blupiOver)
+ {
+ if (action == ACTION_STOP) action = ACTION_STOPOVER;
+ if (action == ACTION_MARCH) action = ACTION_MARCHOVER;
+ if (action == ACTION_TURN) action = ACTION_TURNOVER;
+ if (action == ACTION_ADVANCE) action = ACTION_STOPOVER;
+ if (action == ACTION_RECEDE) action = ACTION_STOPOVER;
+ }
+
+ if (m_blupiJeep)
+ {
+ if (action == ACTION_STOP) action = ACTION_STOPJEEP;
+ if (action == ACTION_MARCH) action = ACTION_MARCHJEEP;
+ if (action == ACTION_ADVANCE) action = ACTION_MARCHJEEP;
+ if (action == ACTION_TURN) action = ACTION_TURNJEEP;
+ }
+
+ if (m_blupiTank)
+ {
+ if (action == ACTION_STOP) action = ACTION_STOPTANK;
+ if (action == ACTION_MARCH) action = ACTION_MARCHTANK;
+ if (action == ACTION_ADVANCE) action = ACTION_MARCHTANK;
+ if (action == ACTION_TURN) action = ACTION_TURNTANK;
+ }
+
+ if (m_blupiSkate)
+ {
+ if (action == ACTION_STOP) action = ACTION_STOPSKATE;
+ if (action == ACTION_MARCH) action = ACTION_MARCHSKATE;
+ if (action == ACTION_ADVANCE) action = ACTION_MARCHSKATE;
+ if (action == ACTION_TURN) action = ACTION_TURNSKATE;
+ if (action == ACTION_TURNAIR) action = ACTION_TURNSKATE;
+ if (action == ACTION_JUMP) action = ACTION_JUMPSKATE;
+ if (action == ACTION_AIR) action = ACTION_AIRSKATE;
+ }
+
+ if (m_blupiNage)
+ {
+ if (action == ACTION_STOP) action = ACTION_STOPNAGE;
+ if (action == ACTION_MARCH) action = ACTION_MARCHNAGE;
+ if (action == ACTION_TURN) action = ACTION_TURNNAGE;
+ if (m_blupiVitesse.x == 0)
+ {
+ if (action == ACTION_STOPNAGE) action = ACTION_STOPSURF;
+ if (action == ACTION_MARCHNAGE) action = ACTION_MARCHSURF;
+ }
+ }
+
+ if (m_blupiSurf)
+ {
+ if (action == ACTION_STOP) action = ACTION_STOPSURF;
+ if (action == ACTION_MARCH) action = ACTION_MARCHSURF;
+ if (action == ACTION_TURN) action = ACTION_TURNSURF;
+ }
+
+ if (m_blupiSuspend)
+ {
+ if (action == ACTION_STOP) action = ACTION_STOPSUSPEND;
+ if (action == ACTION_MARCH) action = ACTION_MARCHSUSPEND;
+ if (action == ACTION_TURN) action = ACTION_TURNSUSPEND;
+ if (action == ACTION_JUMP) action = ACTION_JUMPSUSPEND;
+ }
+
+ if (m_blupiBalloon) action = ACTION_BALLOON;
+
+ if (m_blupiEcrase)
+ {
+ if (action == ACTION_STOP) action = ACTION_STOPECRASE;
+ if (action == ACTION_MARCH) action = ACTION_MARCHECRASE;
+ if (action == ACTION_TURN) action = ACTION_MARCHECRASE;
+ }
+
+ if (action == ACTION_STOP)
+ {
+ phase = m_blupiPhase % 330;
+ if (phase == 125 ||
+ phase == 129 ||
+ phase == 135 ||
+ phase == 139 ||
+ phase == 215 ||
+ phase == 219 ||
+ phase == 225 ||
+ phase == 229 ||
+ phase == 235 ||
+ phase == 239 ||
+ phase == 245 ||
+ phase == 249 ||
+ phase == 255 ||
+ phase == 259 ||
+ phase == 265 ||
+ phase == 269)
+ {
+ PlaySound(SOUND_PATIENT, m_blupiPos, FALSE);
+ }
+ }
+ if (action == ACTION_STOPSUSPEND && (((phase = m_blupiPhase % 328, phase == 0x76 || (phase == 0xe6)) || (phase == 0x116))))
+ {
+ PlaySound(SOUND_SINGE, m_blupiPos, FALSE);
+ }
+ if ((action == ACTION_STOPSURF || action == ACTION_MARCHSURF) && m_blupiPhase % 12 == 0 && m_blupiSurf)
+ {
+ MoveObjectTiplouf(m_blupiPos);
+ }
+ for (int i = 0; table_blupi[i] != 0; i += table_blupi[i + 1] + 3)
+ {
+ if (action == table_blupi[i])
+ {
+ phase = table_blupi[i + 2];
+ if (phase == 0 || m_blupiPhase <= phase)
+ {
+ phase = m_blupiPhase % table_blupi[i + 1];
+ }
+ icon = table_blupi[i + 3 + phase];
+ break;
+ }
+ }
+ if ((action == ACTION_CLEAR1 ||
+ action == ACTION_CLEAR2 ||
+ action == ACTION_CLEAR3 ||
+ action == ACTION_GLU ||
+ action == ACTION_ELECTRO) && icon < 0x10a)
+ {
+ m_blupiChannel = CHELEMENT;
+ }
+ else
+ {
+ m_blupiChannel = CHBLUPI;
+ }
+ if (m_blupiDir == DIR_LEFT || (m_blupiDir == DIR_RIGHT && m_blupiInvert))
+ {
+ if (m_blupiChannel == CHBLUPI)
+ {
+ if (action == ACTION_STOPSUSPEND)
+ {
+ if (icon == 0x90) icon = 0x9e;
+ if (icon == 0x8f) icon = 0x91;
+ if (icon == 0x97) icon = 0x92;
+ }
+ if (icon > -1 && icon < 0x14f)
+ {
+ icon = table_mirror[icon];
+ }
+ }
+ if (true && m_blupiChannel == CHELEMENT && icon > 0xa7 && icon < 0xac)
+ {
+ icon = (icon + 4);
+ }
+ }
+ m_blupiIcon = icon;
+ m_blupiPhase++;
+}
+
+BOOL CDecor::BlupiIsGround()
+{
+ if (m_blupiTransport == -1)
+ {
+ RECT rect = BlupiRect(m_blupiPos);
+ rect.top = m_blupiPos.y + DIMBLUPIY - 2;
+ rect.bottom = m_blupiPos.y + DIMBLUPIY - 1;
+ return DecorDetect(rect, TRUE);
+ }
+ else {
+ return FALSE;
+ }
+}
+
+// get Blupi's hitbox according to his state
+RECT CDecor::BlupiRect(POINT pos)
+{
+ RECT result;
+ if (m_blupiNage || m_blupiSurf)
+ {
+ result.left = pos.x + 12;
+ result.right = pos.x + DIMBLUPIX - 12;
+ if (m_blupiAction == ACTION_STOP)
+ {
+ result.top = pos.y + 5;
+ result.bottom = pos.y + DIMBLUPIY - 10;
+ }
+ else
+ {
+ result.top = pos.y + 15;
+ result.bottom = pos.y + DIMBLUPIY - 10;
+ }
+ }
+ else if (m_blupiJeep)
+ {
+ result.left = pos.x + 2;
+ result.right = pos.x + DIMBLUPIX - 2;
+ result.top = pos.y + 10;
+ result.bottom = pos.y + DIMBLUPIY - 2;
+ }
+ else if (m_blupiTank)
+ {
+ result.left = pos.x + 2;
+ result.right = pos.x + DIMBLUPIX - 2;
+ result.top = pos.y + 10;
+ result.bottom = pos.y + DIMBLUPIY - 2;
+ }
+ else if (m_blupiOver)
+ {
+ result.left = pos.x + 2;
+ result.right = pos.x + DIMBLUPIX - 2;
+ result.top = pos.y + 2;
+ result.bottom = pos.y + DIMBLUPIY - 2;
+ }
+ else if (m_blupiBalloon)
+ {
+ result.left = pos.x + 10;
+ result.right = pos.x + DIMBLUPIX - 10;
+ result.top = pos.y + 5;
+ result.bottom = pos.y + DIMBLUPIY - 2;
+ }
+ else if (m_blupiEcrase)
+ {
+ result.left = pos.x + 5;
+ result.right = pos.x + DIMBLUPIX - 5;
+ result.top = pos.y + 39;
+ result.bottom = pos.y + DIMBLUPIY - 2;
+ }
+ else
+ {
+ result.left = pos.x + 12;
+ result.right = pos.x + DIMBLUPIX - 12;
+ result.top = pos.y + 11;
+ result.bottom = pos.y + DIMBLUPIY - 2;
+ }
+ return result;
+}
+
+// prevent blupi from getting stuck in blocks
+void CDecor::BlupiAdjust()
+{
+ int i;
+ RECT tinyRect = BlupiRect(m_blupiPos);
+
+ if (!DecorDetect(tinyRect))
+ {
+ return;
+ }
+ for (i = 0; i < 50; i++)
+ {
+ RECT rect = tinyRect;
+ rect.bottom = rect.top + 2;
+ rect.left = m_blupiPos.x + 12;
+ rect.right = m_blupiPos.x + 60 - 12;
+ if (!DecorDetect(rect))
+ {
+ break;
+ }
+ tinyRect.top += 2;
+ tinyRect.bottom += 2;
+ m_blupiPos.y = m_blupiPos.y + 2;
+ }
+ for (i = 0; i < 50; i++)
+ {
+ RECT rect = tinyRect;
+ rect.right = rect.left + 2;
+ rect.top = m_blupiPos.y + 11;
+ rect.bottom = m_blupiPos.y + 60 - 2;
+ if (!DecorDetect(rect))
+ {
+ break;
+ }
+ tinyRect.left += 2;
+ tinyRect.right += 2;
+ m_blupiPos.x = m_blupiPos.x + 2;
+ }
+ for (i = 0; i < 50; i++)
+ {
+ RECT rect = tinyRect;
+ rect.left = rect.right - 2;
+ rect.top = m_blupiPos.y + 11;
+ rect.bottom = m_blupiPos.y + 60 - 2;
+ if (!DecorDetect(rect))
+ {
+ break;
+ }
+ tinyRect.left -= 2;
+ tinyRect.right -= 2;
+ m_blupiPos.x = m_blupiPos.x - 2;
+ }
+ for (i = 0; i < 50; i++)
+ {
+ RECT rect = tinyRect;
+ rect.right = rect.left + 2;
+ if (!DecorDetect(rect))
+ {
+ break;
+ }
+ tinyRect.left += 2;
+ tinyRect.right += 2;
+ m_blupiPos.x = m_blupiPos.x + 2;
+ }
+ for (i = 0; i < 50; i++)
+ {
+ RECT rect = tinyRect;
+ rect.left = rect.right - 2;
+ if (!DecorDetect(rect))
+ {
+ return;
+ }
+ tinyRect.left -= 2;
+ tinyRect.right -= 2;
+ m_blupiPos.x = m_blupiPos.x - 2;
+ }
+}
+
+BOOL CDecor::BlupiBloque(POINT pos, int dir)
+{
+ RECT rect = BlupiRect(pos);
+ rect.top = rect.bottom - 20;
+ rect.bottom -= 2;
+ if (dir > 0)
+ {
+ rect.left = rect.right - 2;
+ }
+ if (dir < 0)
+ {
+ rect.right = rect.left + 2;
+ }
+ return DecorDetect(rect);
+}
+
+// handle Blupi's movement and current state.
+void CDecor::BlupiStep()
+{
+ BOOL bNear;
+ int icon;
+ POINT tinyPoint;
+ POINT tinyPoint2 = m_blupiPos; // = m_blupiPos ?
+ BlupiAdjust();
+ //m_blupiLastPos = m_blupiPos;
+ POINT end = m_blupiPos;
+ int lastBlupiAction = m_blupiAction;
+ BOOL bLastBlupiAir = m_blupiAir;
+ BOOL bAirStart = FALSE;
+ BOOL bIsOpen = FALSE;
+ BOOL bIsOpen2 = FALSE;
+ int num;
+ end.x += m_blupiVector.x;
+ end.y += m_blupiVector.y;
+ RECT rect;
+ if (m_blupiVector.x != 0 || m_blupiVector.y != 0)
+ {
+ rect = BlupiRect(m_blupiPos);
+ rect.top = m_blupiPos.y + 11;
+ rect.bottom = m_blupiPos.y + DIMBLUPIY - 2;
+ TestPath(rect, m_blupiPos, &end);
+ }
+ m_blupiVent = FALSE;
+ if (m_blupiTransport == -1 && !m_blupiJeep && !m_blupiTank && !m_blupiSkate
+ && m_blupiFocus)
+ {
+ num = m_decor[(end.x + DIMBLUPIX / 2) / DIMOBJX][(end.y + DIMBLUPIY / 2) / DIMOBJY].icon;
+ if (num == 110)
+ {
+ end.x -= 9;
+ }
+ if (num == 114)
+ {
+ end.x += 9;
+ }
+ if (num == 118)
+ {
+ end.y -= 20;
+ }
+ if (num == 122)
+ {
+ end.y += 20;
+ }
+ if (num >= 110 && num <= 125)
+ {
+ m_blupiVent = TRUE;
+ rect.left = m_blupiPos.x + 12;
+ rect.right = m_blupiPos.x + DIMBLUPIX - 12;
+ rect.top = m_blupiPos.y + 11;
+ rect.bottom = m_blupiPos.y + DIMBLUPIY - 2;
+ TestPath(rect, m_blupiPos, &end);
+ }
+ }
+ m_blupiVent = FALSE;
+ if (m_blupiTransport == -1)
+ {
+ rect = BlupiRect(end);
+ rect.top = end.y + DIMBLUPIY - 2;
+ rect.bottom = end.y + DIMBLUPIY - 1;
+ bAirStart = !DecorDetect(rect);
+ }
+ else
+ {
+ bAirStart = FALSE;
+ }
+ rect = BlupiRect(end);
+ rect.top = end.y + 10;
+ rect.bottom = end.y + 20;
+ int detectIcon = m_detectIcon;
+ if (!m_blupiAir &&
+ !IsBlupiMotorVehicle() &&
+ !m_blupiBalloon &&
+ !m_blupiEcrase &&
+ !m_blupiNage &&
+ !m_blupiSurf &&
+ !m_blupiSuspend &&
+ m_blupiFocus &&
+ bAirStart)
+ {
+ if (m_blupiFocus)
+ {
+ m_blupiAction = ACTION_AIR;
+ m_blupiPhase = 0;
+ }
+ m_blupiVitesse.y = 1;
+ m_blupiAir = TRUE;
+ bLastBlupiAir = TRUE;
+ }
+ if (!m_blupiNage &&
+ !m_blupiSurf &&
+ !m_blupiSuspend &&
+ !m_blupiAir &&
+ IsRessort(end))
+ {
+ if (IsBlupiVehicle() &&
+ !m_blupiShield &&
+ !m_blupiHide &&
+ !m_bSuperBlupi)
+ {
+ m_blupiHelico = FALSE;
+ m_blupiOver = FALSE;
+ m_blupiJeep = FALSE;
+ m_blupiTank = FALSE;
+ m_blupiSkate = FALSE;
+ tinyPoint.x = end.x - 34;
+ tinyPoint.y = end.y - 34;
+ ObjectStart(tinyPoint, TYPE_EXPLO2, 0);
+ m_decorAction = 1;
+ m_decorPhase = 0;
+ StopVehicleSound();
+ PlaySound(SOUND_BOUM, m_blupiPos);
+ }
+ if (m_blupiFocus && !IsDeadAction(m_blupiAction))
+ {
+ m_blupiAction = ACTION_AIR;
+ m_blupiPhase = 0;
+ }
+ if (m_keyPress & KEY_JUMP && m_blupiFocus)
+ {
+ if (m_keyPress & KEY_UP)
+ {
+ m_blupiVitesse.y = (m_blupiPower ? -29 : -25);
+ }
+ else if (m_keyPress & KEY_DOWN)
+ {
+ m_blupiVitesse.y = (m_blupiPower ? -19 : -16);
+ }
+ else
+ {
+ m_blupiVitesse.y = (m_blupiPower ? -25 : -19);
+ }
+ }
+ else
+ {
+ m_blupiVitesse.y = (m_blupiPower ? -16 : -10);
+ }
+ m_blupiAir = TRUE;
+ bLastBlupiAir = TRUE;
+ PlaySound(SOUND_RESSORT, end);
+ }
+ if (m_keyPress & KEY_JUMP &&
+ !IsBlupiMotorVehicle() &&
+ !m_blupiBalloon &&
+ !m_blupiEcrase &&
+ !m_blupiNage &&
+ !m_blupiSurf &&
+ !m_blupiSuspend
+ && m_blupiFocus)
+ {
+ if (m_blupiAction != ACTION_JUMP &&
+ m_blupiAction != ACTION_TURN &&
+ !m_blupiAir)
+ {
+ m_blupiAction = ACTION_JUMP;
+ m_blupiPhase = 0;
+ }
+ if (m_blupiAction == ACTION_JUMP && m_blupiPhase == 3)
+ {
+ m_blupiAction = ACTION_AIR;
+ m_blupiPhase = 0;
+ if (m_blupiSkate)
+ {
+ PlaySound(SOUND_JUMP1, end);
+ m_blupiVitesse.y = (m_blupiPower ? -22 : -16);
+ }
+ else
+ {
+ if (m_keyPress & KEY_UP)
+ {
+ PlaySound(SOUND_JUMP2, end);
+ m_blupiVitesse.y = (m_blupiPower ? -26 : -22);
+ }
+ else if (m_keyPress & KEY_DOWN)
+ {
+ PlaySound(SOUND_JUMP0, end);
+ m_blupiVitesse.y = (m_blupiPower ? -16 : -12);
+ }
+ else
+ {
+ PlaySound(SOUND_JUMP1, end);
+ m_blupiVitesse.y = (m_blupiPower ? -22 : -16);
+ }
+ }
+ m_blupiAir = TRUE;
+ bLastBlupiAir = TRUE;
+ }
+ }
+ if (m_blupiAir)
+ {
+ if (DecorDetect(rect) && m_blupiVitesse.y < 0)
+ {
+ if (m_blupiVitesse.y < -14 && !IsDeadAction(m_blupiAction) && !m_blupiSkate)
+ {
+ m_blupiJumpAie = TRUE;
+ PlaySound(SOUND_JUMPAIE, end);
+ }
+ else
+ {
+ PlaySound(SoundEnviron(SOUND_JUMPTOC, detectIcon), end);
+ }
+ m_blupiVitesse.y = 1;
+ }
+ end.y += m_blupiVitesse.y * 2;
+ if (m_blupiVitesse.y < 20)
+ {
+ m_blupiVitesse.y += 2;
+ }
+ rect = BlupiRect(end);
+ rect.top = end.y + DIMBLUPIY - 30;
+ rect.bottom = end.y + DIMBLUPIY - 1;
+ if (m_blupiVitesse.y >= 0 && DecorDetect(rect))
+ {
+ end.y = end.y / 32 * 32 + BLUPIOFFY;
+ if (!IsRessort(end))
+ {
+ PlaySound(SoundEnviron(SOUND_JUMPEND, m_detectIcon), end);
+ }
+ if (m_blupiFocus)
+ {
+ if (m_blupiVitesse.y > 20)
+ {
+ m_blupiAction = ACTION_STOPJUMP; // ??
+ }
+ else
+ {
+ m_blupiAction = ACTION_STOPJUMP;
+ }
+ m_blupiPhase = 0;
+ }
+ m_blupiAir = FALSE;
+ if (m_blupiJumpAie)
+ {
+ m_blupiJumpAie = FALSE;
+ m_blupiAction = ACTION_JUMPAIE;
+ m_blupiPhase = 0;
+ }
+ }
+ rect.left = end.x + 20;
+ rect.right = end.x + DIMBLUPIX - 20;
+ rect.top = end.y + DIMBLUPIY - 33;
+ rect.bottom = end.y + DIMBLUPIY - 1;
+ icon = AscenseurDetect(rect, m_blupiPos, end);
+ if (m_blupiVitesse.y >= 0 && icon != -1)
+ {
+ m_blupiTransport = icon;
+ bAirStart = FALSE;
+ PlaySound(SOUND_JUMPEND, end, FALSE);
+ end.y = m_moveObject[icon].posCurrent.y - DIMOBJY + BLUPIOFFY;
+ if (m_blupiFocus)
+ {
+ if (m_blupiVitesse.y > 20)
+ {
+ m_blupiAction = ACTION_STOPJUMP; // ???
+ }
+ else
+ {
+ m_blupiAction = ACTION_STOPJUMP;
+ }
+ m_blupiPhase = 0;
+ }
+ m_blupiAir = FALSE;
+ if (m_blupiJumpAie)
+ {
+ m_blupiJumpAie = FALSE;
+ m_blupiAction = ACTION_JUMPAIE;
+ m_blupiPhase = 0;
+ }
+ }
+ } // if (m_blupiAir)
+
+ switch (m_blupiAction)
+ {
+ case ACTION_JUMPAIE:
+ if (m_blupiPhase == 30) StopBlupi(TRUE);
+ break;
+ case ACTION_CHARGE:
+ if (m_blupiPhase == 64)
+ {
+ StopBlupi(TRUE);
+ m_blupiCloud = TRUE;
+ m_blupiTimeShield = 100;
+ m_jauges[JAUGE_POWER].SetHide(FALSE);
+ PlaySound(ACTION_DRINK, end);
+ }
+ break;
+ case ACTION_HELICOGLU:
+ if (m_blupiPhase == 8)
+ {
+ tinyPoint.x = m_blupiPos.x;
+ tinyPoint.y = m_blupiPos.y + 40;
+ if (m_blupiVitesse.y > 0)
+ {
+ tinyPoint.y += m_blupiVitesse.y * 4;
+ }
+ m_blupiVitesse.y -= 10;
+ if (ObjectStart(tinyPoint, TYPE_BALLE, 55) != -1)
+ {
+ PlaySound(SOUND_FIREOK, m_blupiPos);
+ m_blupiTimeFire = 10;
+ m_blupiBullet--;
+ }
+ }
+ if (m_blupiPhase == 14) StopBlupi(TRUE);
+ break;
+ case ACTION_OUF1a:
+ case ACTION_OUF1b:
+ if (m_blupiPhase == 29) StopBlupi(TRUE);
+ break;
+ case ACTION_OUF2:
+ if (m_blupiPhase == 32) StopBlupi(TRUE);
+ break;
+ case ACTION_OUF3:
+ if (m_blupiPhase == 34) StopBlupi(TRUE);
+ break;
+ case ACTION_OUF4:
+ if (m_blupiPhase == 40)
+ {
+ StopBlupi(TRUE);
+ icon = MoveObjectDetect(end, &bNear);
+ if (icon != -1 && !bNear && end.y - BLUPIFLOOR == m_moveObject[num].posCurrent.y)
+ {
+ if (m_blupiDir == DIR_RIGHT && end.x < m_moveObject[num].posCurrent.x)
+ {
+ tinyPoint.x = end.x - 16;
+ tinyPoint.y = end.y;
+ int num2 = MoveObjectDetect(tinyPoint, &bNear);
+ if (num2 == -1)
+ {
+ m_blupiAction = ACTION_RECEDE;
+ m_blupiPhase = 0;
+ }
+ }
+ if (m_blupiDir == DIR_LEFT && end.x > m_moveObject[num].posCurrent.x)
+ {
+ tinyPoint.x = end.x + 16;
+ tinyPoint.y = end.y;
+ int num2 = MoveObjectDetect(tinyPoint, &bNear);
+ if (num2 == -1)
+ {
+ m_blupiAction = ACTION_RECEDE;
+ m_blupiPhase = 0;
+ }
+ }
+ }
+ }
+ break;
+ case ACTION_OUF5:
+ if (m_blupiPhase == 4) PlaySound(SOUND_OUF2, m_blupiPos);
+ if (m_blupiPhase == 44) StopBlupi(TRUE);
+ break;
+ case ACTION_MOCKERY:
+ if (m_blupiPhase == 1)
+ {
+ PlaySound(SOUND_MOCKERY, m_blupiPos);
+ m_blupiTimeMockery = 300;
+ }
+ if (m_blupiPhase == 92) StopBlupi(TRUE);
+ break;
+ case ACTION_MOCKERYi:
+ if (m_blupiPhase == 6)
+ {
+ PlaySound(SOUND_MOCKERY, m_blupiPos);
+ m_blupiTimeMockery = 300;
+ }
+ if (m_blupiPhase == 104) StopBlupi(TRUE);
+ break;
+ case ACTION_MOCKERYp:
+ if (m_blupiPhase == 4) PlaySound(SOUND_OUF2, m_blupiPos);
+ if (m_blupiPhase == 60) StopBlupi(TRUE);
+ break;
+ case ACTION_NON:
+ if (m_blupiPhase == 18) StopBlupi(TRUE);
+ break;
+ case ACTION_STOPMARCH:
+ if (m_blupiPhase == 3) StopBlupi();
+ break;
+ case ACTION_STOPJUMP:
+ if (m_blupiPhase == 5) StopBlupi();
+ break;
+ case ACTION_STOPJUMPh:
+ if (m_blupiPhase == 2)
+ {
+ m_blupiAction = ACTION_AIR;
+ m_blupiPhase = 0;
+ m_blupiVitesse.y = -12;
+ m_blupiAir = TRUE;
+ bLastBlupiAir = TRUE;
+ }
+ case ACTION_SUCETTE:
+ if (m_blupiPhase == 32)
+ {
+ //ObjectStart(m_sucettePos, m_sucetteType, 0); // respawn item (winphone behavior)
+ StopBlupi(TRUE);
+ m_blupiPower = TRUE;
+ m_blupiTimeShield = 100;
+ m_blupiPosMagic = m_blupiPos;
+ m_jauges[JAUGE_POWER].SetHide(FALSE);
+ PlaySound(SOUND_STARTPOWER, end);
+ }
+ case ACTION_DRINK:
+ if (m_blupiPhase == 36)
+ {
+ //ObjectStart(m_sucettePos, m_sucetteType, 0); // respawn item (winphone behavior)
+ StopBlupi(TRUE);
+ m_blupiHide = TRUE;
+ m_blupiTimeShield = 100;
+ m_blupiPosMagic = m_blupiPos;
+ m_jauges[JAUGE_POWER].SetHide(FALSE);
+ PlaySound(SOUND_STARTHIDE, end);
+ }
+ }
+
+ if (m_keyPress & KEY_UP &&
+ !(m_lastKeyPress & KEY_UP) &&
+ IsBlupiStanding() &&
+ m_blupiAction != ACTION_UP &&
+ m_blupiFocus)
+ {
+ m_blupiAction = ACTION_UP;
+ m_blupiPhase = 0;
+ }
+
+ if (!(m_keyPress & (KEY_UP | KEY_DOWN)) &&
+ m_lastKeyPress & KEY_UP &&
+ IsBlupiStanding() &&
+ m_blupiFocus)
+ {
+ StopBlupi();
+ }
+
+ if (m_keyPress & KEY_DOWN &&
+ !(m_lastKeyPress & KEY_DOWN) &&
+ IsBlupiStanding() &&
+ m_blupiAction != ACTION_DOWN &&
+ m_blupiAction != ACTION_STOPPOP &&
+ m_blupiFocus)
+ {
+ m_blupiAction = ACTION_DOWN;
+ m_blupiPhase = 0;
+ }
+
+ if (m_keyPress & KEY_DOWN &&
+ !(m_keyPress & (KEY_JUMP | KEY_LEFT | KEY_RIGHT)) &&
+ IsBlupiStanding() &&
+ m_blupiAction != ACTION_DOWN &&
+ m_blupiAction != ACTION_STOPPOP &&
+ m_blupiFocus)
+ {
+ m_blupiAction = ACTION_DOWN;
+ m_blupiPhase = 0;
+ }
+ if (!(m_keyPress & KEY_DOWN) &&
+ m_lastKeyPress & KEY_DOWN &&
+ IsBlupiStanding() &&
+ m_blupiFocus)
+ {
+ StopBlupi();
+ }
+ if (m_blupiAction == ACTION_UP && m_blupiPhase == 4)
+ {
+ m_scrollAdd.y = -150;
+ PlaySound(SOUND_LOOKUP, end);
+ }
+ if (m_blupiAction == ACTION_DOWN && m_blupiPhase == 4)
+ {
+ m_scrollAdd.y = 150;
+ PlaySound(SOUND_DOWN, end);
+ }
+ if (!IsBlupiVehicle() &&
+ !m_blupiBalloon &&
+ !m_blupiEcrase &&
+ !m_blupiNage &&
+ !m_blupiSurf &&
+ !m_blupiSuspend
+ && m_blupiFocus)
+ {
+ if (m_keyPress & KEY_DOWN &&
+ !(m_keyPress & (KEY_JUMP | KEY_LEFT | KEY_RIGHT)) &&
+ m_blupiAction != ACTION_STOPPOP &&
+ m_blupiDir == DIR_LEFT &&
+ (num = CaisseInFront()) != -1)
+ {
+ end.x = m_moveObject[num].posCurrent.x + 64 - 5;
+ m_blupiAction = ACTION_STOPPOP;
+ m_blupiPhase = 0;
+ m_scrollAdd.y = 0;
+ PlaySound(SOUND_POP, end);
+ }
+ if (m_keyPress & (KEY_DOWN | KEY_RIGHT) &&
+ !(m_keyPress & KEY_JUMP) &&
+ m_blupiAction != ACTION_POP &&
+ m_blupiDir == DIR_LEFT &&
+ CaisseInFront() != -1)
+ {
+ m_blupiAction = ACTION_POP;
+ m_blupiPhase = 0;
+ m_scrollAdd.y = 0;
+ PlaySound(SOUND_POP, end);
+ }
+ if (m_keyPress & KEY_DOWN &&
+ !(m_keyPress & (KEY_JUMP | KEY_LEFT | KEY_RIGHT)) &&
+ m_blupiAction != ACTION_STOPPOP &&
+ m_blupiDir == DIR_RIGHT &&
+ (num = CaisseInFront()) != -1)
+ {
+ end.x = m_moveObject[num].posCurrent.x - DIMBLUPIX + 5;
+ m_blupiAction = ACTION_STOPPOP;
+ m_blupiPhase = 0;
+ m_scrollAdd.y = 0;
+ PlaySound(SOUND_POP, end);
+ }
+ if (m_keyPress & (KEY_DOWN | KEY_LEFT) &&
+ !(m_keyPress & KEY_JUMP) &&
+ m_blupiAction != ACTION_POP &&
+ m_blupiDir == DIR_RIGHT &&
+ CaisseInFront() != -1)
+ {
+ m_blupiAction = ACTION_POP;
+ m_blupiPhase = 0;
+ m_scrollAdd.y = 0;
+ PlaySound(SOUND_POP, end);
+ }
+ if (m_blupiAction == ACTION_POP && m_blupiActionOuf != ACTION_OUF3)
+ {
+ m_blupiActionOuf = ACTION_OUF3;
+ m_blupiTimeOuf = 0;
+ }
+ }
+ if (m_blupiAction != ACTION_STOPPOP &&
+ m_blupiAction != ACTION_POP &&
+ m_blupiFocus)
+ {
+ if (m_keyPress & KEY_LEFT && !(m_lastKeyPress & (KEY_LEFT | KEY_RIGHT)) && !m_blupiAir && m_keyPress & (KEY_UP | KEY_DOWN))
+ {
+ m_blupiAction = 1;
+ m_blupiPhase = 0;
+ }
+ if (!(m_keyPress & (KEY_LEFT | KEY_RIGHT)) && m_lastKeyPress & KEY_LEFT && m_keyPress & (KEY_UP | KEY_DOWN))
+ {
+ m_blupiAction = 1;
+ m_blupiPhase = 0;
+ }
+ if (m_keyPress & KEY_RIGHT && !(m_lastKeyPress & (KEY_LEFT | KEY_RIGHT)) && !m_blupiAir && m_keyPress & (KEY_UP | KEY_DOWN))
+ {
+ m_blupiAction = 1;
+ m_blupiPhase = 0;
+ }
+ if (!(m_keyPress & (KEY_LEFT | KEY_RIGHT)) && m_lastKeyPress & KEY_RIGHT && m_keyPress & (KEY_UP | KEY_DOWN))
+ {
+ m_blupiAction = 1;
+ m_blupiPhase = 0;
+ }
+ }
+ int num3;
+ int num4;
+ if (m_keyPress & KEY_LEFT && m_blupiFocus)
+ {
+ if (m_blupiDir == DIR_RIGHT &&
+ m_blupiAction != ACTION_TURN &&
+ m_blupiAction != ACTION_TURNAIR &&
+ m_blupiAction != ACTION_UP &&
+ m_blupiAction != ACTION_DOWN &&
+ m_blupiAction != ACTION_POP &&
+ ((!m_blupiJeep && !m_blupiTank && !m_blupiSkate) || abs(m_blupiVitesse.x) <= 8))
+ {
+ if (m_blupiAir)
+ {
+ PlaySound(SOUND_TURN, end);
+ m_blupiAction = ACTION_TURNAIR;
+ m_blupiPhase = 0;
+ m_blupiDir = DIR_LEFT;
+ }
+ else
+ {
+ PlaySound(SOUND_TURN, end);
+ m_blupiAction = ACTION_TURN;
+ m_blupiPhase = 0;
+ }
+ }
+ if (m_blupiDir == DIR_LEFT &&
+ m_blupiAction != ACTION_MARCH &&
+ m_blupiAction != ACTION_PUSH &&
+ m_blupiAction != ACTION_JUMP &&
+ m_blupiAction != ACTION_UP &&
+ m_blupiAction != ACTION_DOWN &&
+ m_blupiAction != ACTION_POP &&
+ !m_blupiAir)
+ {
+ m_blupiAction = ACTION_MARCH;
+ m_blupiPhase = 0;
+ }
+ if (m_blupiDir == DIR_LEFT &&
+ m_blupiAction != ACTION_TURN &&
+ m_blupiAction != ACTION_JUMP &&
+ m_blupiAction != ACTION_UP &&
+ m_blupiAction != ACTION_DOWN &&
+ m_blupiAction != ACTION_POP &&
+ !IsBlupiVehicle() &&
+ !m_blupiBalloon &&
+ !m_blupiEcrase &&
+ !m_blupiNage &&
+ !m_blupiSurf &&
+ !m_blupiSuspend)
+ {
+ if (m_blupiAction == ACTION_PUSH)
+ {
+ end.x -= CaisseGetMove(5);
+ }
+ else
+ {
+ num3 = m_blupiPhase;
+ if (num3 > 3 || m_blupiAir)
+ {
+ num3 = 3;
+ }
+ num4 = table_vitesse_march[num3];
+ if (m_blupiPower)
+ {
+ num4 *= 3;
+ num4 /= 2;
+ }
+ end.x -= num4;
+ }
+ }
+ if (m_blupiDir == DIR_RIGHT && m_blupiAction == ACTION_POP)
+ {
+ end.x -= CaisseGetMove(3);
+ }
+ } // if (m_keyPress & KEY_LEFT && m_blupiFocus)
+
+ if (m_keyPress & KEY_RIGHT && m_blupiFocus)
+ {
+ if (m_blupiDir == DIR_LEFT &&
+ m_blupiAction != ACTION_TURN &&
+ m_blupiAction != ACTION_TURNAIR &&
+ m_blupiAction != ACTION_UP &&
+ m_blupiAction != ACTION_DOWN &&
+ m_blupiAction != ACTION_POP &&
+ ((!m_blupiJeep && !m_blupiTank && !m_blupiSkate) || abs(m_blupiVitesse.x) <= 8))
+ {
+ if (m_blupiAir)
+ {
+ PlaySound(SOUND_TURN, end);
+ m_blupiAction = ACTION_TURNAIR;
+ m_blupiPhase = 0;
+ m_blupiDir = DIR_RIGHT;
+ }
+ else
+ {
+ PlaySound(SOUND_TURN, end);
+ m_blupiAction = ACTION_TURN;
+ m_blupiPhase = 0;
+ }
+ }
+ if (m_blupiDir == DIR_RIGHT &&
+ m_blupiAction != ACTION_MARCH &&
+ m_blupiAction != ACTION_PUSH &&
+ m_blupiAction != ACTION_JUMP &&
+ m_blupiAction != ACTION_UP &&
+ m_blupiAction != ACTION_DOWN &&
+ m_blupiAction != ACTION_POP &&
+ !m_blupiAir)
+ {
+ m_blupiAction = ACTION_MARCH;
+ m_blupiPhase = 0;
+ }
+ if (m_blupiDir == DIR_RIGHT &&
+ m_blupiAction != ACTION_TURN &&
+ m_blupiAction != ACTION_JUMP &&
+ m_blupiAction != ACTION_UP &&
+ m_blupiAction != ACTION_DOWN &&
+ m_blupiAction != ACTION_POP &&
+ !IsBlupiVehicle() &&
+ !m_blupiBalloon &&
+ !m_blupiEcrase &&
+ !m_blupiNage &&
+ !m_blupiSurf &&
+ !m_blupiSuspend)
+ {
+ if (m_blupiAction == ACTION_PUSH)
+ {
+ end.x += CaisseGetMove(5);
+ }
+ else
+ {
+ num3 = m_blupiPhase;
+ if (num3 > 3 || m_blupiAir)
+ {
+ num3 = 3;
+ }
+ num4 = table_vitesse_march[num3];
+ if (m_blupiPower)
+ {
+ num4 *= 3;
+ num4 /= 2;
+ }
+ end.x += num4;
+ }
+ }
+ if (m_blupiDir == DIR_LEFT && m_blupiAction == ACTION_POP)
+ {
+ end.x += CaisseGetMove(3);
+ }
+ } // if (m_keyPress & KEY_RIGHT && m_blupiFocus)
+
+ if (m_blupiHelico)
+ {
+ if (m_blupiAction == ACTION_TURN && m_blupiPhase == 10)
+ {
+ m_blupiAction = ACTION_MARCH;
+ if (m_blupiDir == DIR_LEFT) m_blupiDir = DIR_RIGHT;
+ else m_blupiDir = DIR_LEFT;
+ }
+ }
+ else if (m_blupiOver)
+ {
+ if (m_blupiAction == ACTION_TURN && m_blupiPhase == 7)
+ {
+ m_blupiAction = ACTION_MARCH;
+ if (m_blupiDir == DIR_LEFT) m_blupiDir = DIR_RIGHT;
+ else m_blupiDir = DIR_LEFT;
+ }
+ }
+ else if (m_blupiJeep)
+ {
+ if (m_blupiAction == ACTION_TURN && m_blupiPhase == 7)
+ {
+ StopBlupi();
+ if (m_blupiDir == DIR_LEFT) m_blupiDir = DIR_RIGHT;
+ else m_blupiDir = DIR_LEFT;
+ }
+ }
+ else if (m_blupiTank)
+ {
+ if (m_blupiAction == ACTION_TURN && m_blupiPhase == 12)
+ {
+ StopBlupi();
+ if (m_blupiDir == DIR_LEFT) m_blupiDir = DIR_RIGHT;
+ else m_blupiDir = DIR_LEFT;
+ }
+ }
+ else if (m_blupiSkate)
+ {
+ if (m_blupiAction == ACTION_TURN && m_blupiPhase == 14)
+ {
+ StopBlupi();
+ if (m_blupiDir == DIR_LEFT) m_blupiDir = DIR_RIGHT;
+ else m_blupiDir = DIR_LEFT;
+ }
+ }
+ else if (m_blupiNage || m_blupiSurf)
+ {
+ if (m_blupiAction == ACTION_TURN && m_blupiPhase == 10)
+ {
+ m_blupiAction = ACTION_MARCH;
+ if (m_blupiDir == DIR_LEFT) m_blupiDir = DIR_RIGHT;
+ else m_blupiDir = DIR_LEFT;
+ }
+ }
+ else if (m_blupiSuspend)
+ {
+ if (m_blupiAction == ACTION_TURN && m_blupiPhase == 10)
+ {
+ StopBlupi();
+ if (m_blupiDir == DIR_LEFT) m_blupiDir = DIR_RIGHT;
+ else m_blupiDir = DIR_LEFT;
+ }
+ }
+ else
+ {
+ if (m_blupiAction == ACTION_TURN && m_blupiPhase == 6)
+ {
+ StopBlupi();
+ if (m_blupiDir == DIR_LEFT) m_blupiDir = DIR_RIGHT;
+ else m_blupiDir = DIR_LEFT;
+ }
+ if (m_blupiAction == ACTION_TURNAIR && m_blupiPhase == 6)
+ {
+ m_blupiAction = ACTION_AIR;
+ m_blupiPhase = 0;
+ }
+ }
+
+ if (!m_blupiSuspend && m_blupiAction == ACTION_JUMP && m_blupiPhase == 3)
+ {
+ StopBlupi();
+ }
+
+ if (!(m_keyPress & (KEY_LEFT | KEY_RIGHT | KEY_UP | KEY_DOWN)) &&
+ !IsBlupiVehicle() &&
+ !m_blupiBalloon &&
+ !m_blupiEcrase &&
+ !m_blupiNage &&
+ !m_blupiSurf &&
+ m_blupiFocus)
+ {
+ if (m_blupiAction == ACTION_PUSH || m_blupiAction == ACTION_UP)
+ {
+ StopBlupi();
+ }
+ if (m_blupiAction == ACTION_MARCH)
+ {
+ if (m_blupiSuspend || m_blupiPhase < 10)
+ {
+ StopBlupi();
+ }
+ else
+ {
+ m_blupiAction = ACTION_STOPMARCH;
+ m_blupiPhase = 0;
+ }
+ }
+ if (m_blupiAction == ACTION_DOWN)
+ {
+ StopBlupi();
+ PlaySound(ACTION_UP, end);
+ }
+ m_scrollAdd.y = 0;
+ if (lastBlupiAction == ACTION_PUSH)
+ {
+ StopSound(SOUND_PUSH);
+ }
+ if (lastBlupiAction == ACTION_POP || lastBlupiAction == ACTION_STOPPOP)
+ {
+ StopSound(SOUND_POP);
+ }
+ }
+ if (!m_blupiBalloon &&
+ !m_blupiEcrase &&
+ !m_blupiJeep &&
+ !m_blupiTank &&
+ !m_blupiSkate &&
+ !m_blupiNage &&
+ !m_blupiSurf &&
+ m_blupiFocus)
+ {
+ if (m_blupiAction == ACTION_RECEDE && m_blupiDir == DIR_LEFT)
+ {
+ end.x += 4;
+ }
+ if (m_blupiAction == ACTION_RECEDE && m_blupiDir == DIR_RIGHT)
+ {
+ end.x -= 4;
+ }
+ if (m_blupiAction == ACTION_ADVANCE && m_blupiDir == DIR_LEFT)
+ {
+ end.x -= 4;
+ }
+ if (m_blupiAction == ACTION_ADVANCE && m_blupiDir == DIR_RIGHT)
+ {
+ end.x += 4;
+ }
+ }
+
+ if (!(m_keyPress & (KEY_LEFT | KEY_RIGHT | KEY_UP | KEY_DOWN | KEY_JUMP)))
+ {
+ if ((m_blupiJeep || m_blupiTank || m_blupiSkate) && m_blupiFocus)
+ {
+ if (m_blupiAction == ACTION_ADVANCE && m_blupiDir == DIR_LEFT)
+ {
+ end.x -= 5;
+ }
+ if (m_blupiAction == ACTION_ADVANCE && m_blupiDir == DIR_RIGHT)
+ {
+ end.x += 5;
+ }
+ }
+ if ((m_blupiNage || m_blupiSurf) &&
+ m_blupiFocus &&
+ m_blupiAction == ACTION_MARCH)
+ {
+ StopBlupi();
+ }
+ }
+ if (m_blupiHelico && (m_blupiFocus || m_blupiAction == ACTION_HELICOGLU))
+ {
+ if (m_keyPress & KEY_FIRE &&
+ m_blupiTimeFire == 0 &&
+ m_blupiAction != ACTION_TURN &&
+ m_blupiAction != ACTION_HELICOGLU &&
+ bAirStart)
+ {
+ if (m_blupiBullet == 0)
+ {
+ PlaySound(SOUND_FIREKO, m_blupiPos);
+ }
+ else
+ {
+ m_blupiAction = ACTION_HELICOGLU;
+ m_blupiPhase = 0;
+ m_blupiFocus = FALSE;
+ }
+ }
+ ////m_blupiMotorHigh = bCanUseLift;
+ if (m_blupiAction != ACTION_TURN && m_blupiAction != ACTION_HELICOGLU)
+ {
+ if (bAirStart)
+ {
+ m_blupiAction = ACTION_MARCH;
+ }
+ else
+ {
+ StopBlupi();
+ m_blupiVitesse.y = 0;
+ }
+ }
+
+ if (m_keyPress & (KEY_UP | KEY_JUMP))
+ {
+ if (m_blupiVitesse.y > -10) m_blupiVitesse.y -= 2;
+ }
+ else if (m_keyPress & KEY_DOWN)
+ {
+ if (m_blupiVitesse.y < 12) m_blupiVitesse.y += 2;
+ }
+ else
+ {
+ if (m_blupiVitesse.y > 1) m_blupiVitesse.y -= 1;
+ if (m_blupiVitesse.y < 1) m_blupiVitesse.y += 1;
+ }
+ end.y += m_blupiVitesse.y;
+
+ if (m_keyPress & KEY_LEFT)
+ {
+ if (m_blupiVitesse.x > -16)
+ {
+ m_blupiVitesse.x -= 2;
+ }
+ if (BlupiBloque(POINT( end.x + m_blupiVitesse.x, end.y ), -1))
+ {
+ m_blupiVitesse.x = 0;
+ }
+ }
+ else if (m_keyPress & KEY_RIGHT)
+ {
+ if (m_blupiVitesse.x < 16)
+ {
+ m_blupiVitesse.x += 2;
+ }
+ if (BlupiBloque(POINT( end.x + m_blupiVitesse.x, end.y ), -1))
+ {
+ m_blupiVitesse.x = 0;
+ }
+ }
+ else
+ {
+ if (m_blupiVitesse.x > 0)
+ {
+ m_blupiVitesse.x -= 2;
+ if (m_blupiVitesse.x < 0) m_blupiVitesse.x = 0;
+ }
+ if (m_blupiVitesse.x < 0)
+ {
+ m_blupiVitesse.x += 2;
+ if (m_blupiVitesse.x > 0) m_blupiVitesse.x = 0;
+ }
+ }
+ end.x += m_blupiVitesse.x;
+
+ MoveObjectPollution();
+
+ if ( m_keyPress & KEY_DOWN && !bAirStart && m_blupiTransport == -1)
+ {
+
+ rect.left = m_blupiPos.x + 20;
+ rect.right = m_blupiPos.x + 22;
+ rect.top = m_blupiPos.y + 60 - 2;
+ rect.bottom = m_blupiPos.y + 60;
+ bIsOpen = !DecorDetect(rect);
+ rect.left = m_blupiPos.x + 60 - 22;
+ rect.right = m_blupiPos.x + 60 - 20;
+ rect.top = m_blupiPos.y + 60 - 2;
+ rect.bottom = m_blupiPos.y + 60;
+ bIsOpen2 = !DecorDetect(rect);
+ if (!bIsOpen && !bIsOpen2)
+ {
+ tinyPoint.x = m_blupiPos.x;
+ tinyPoint.y = m_blupiPos.y - BLUPIFLOOR;
+ ObjectStart(tinyPoint, TYPE_HELICO, 0);
+ m_blupiHelico = FALSE;
+ StopBlupi(TRUE);
+ m_blupiPosHelico = m_blupiPos;
+ StopSound(SOUND_HELICOHIGH);
+ StopSound(SOUND_HELICOLOW);
+ PlaySound(SOUND_HELICOSTOP, m_blupiPos);
+ }
+ }
+ }
+ if (m_blupiOver && (m_blupiFocus || m_blupiAction == ACTION_HELICOGLU))
+ {
+ ////m_blupiMotorHigh = bCanUseLift;
+ if (m_blupiAction != ACTION_TURN)
+ {
+ if (bAirStart)
+ {
+ m_blupiAction = ACTION_MARCH;
+ }
+ else
+ {
+ if (m_blupiAction != 1)
+ {
+ StopBlupi();
+ }
+ m_blupiVitesse.y = 0;
+ }
+ }
+ rect = BlupiRect(end);
+ rect.top = end.y + 60 - 2;
+ rect.bottom = end.y + 60 + OVERHEIGHT - 1;
+ bIsOpen = !DecorDetect(rect);
+ num = MoveAscenseurDetect(m_blupiPos, OVERHEIGHT);
+ if (num != -1)
+ {
+ bIsOpen = FALSE;
+ }
+ if (m_keyPress & (KEY_JUMP | KEY_UP) && !bIsOpen)
+ {
+ if (m_blupiVitesse.y == 0 && num != -1)
+ {
+ m_blupiVitesse.y = -5;
+ }
+ else if (m_blupiVitesse.y > -5)
+ {
+ m_blupiVitesse.y -= 1;
+ }
+ }
+ else if (m_keyPress & KEY_DOWN)
+ {
+ if (m_blupiVitesse.y < 12)
+ {
+ m_blupiVitesse.y += 5;
+ }
+ }
+ else if (m_blupiVitesse.y < 12 && m_time % 2 == 0)
+ {
+ m_blupiVitesse.y += 1;
+ }
+ end.y += m_blupiVitesse.y;
+ if (m_keyPress & KEY_LEFT && bAirStart)
+ {
+ if (m_blupiVitesse.x > -12)
+ {
+ m_blupiVitesse.x -= 1;
+ }
+ tinyPoint.x = end.x + m_blupiVitesse.x;
+ tinyPoint.y = end.y;
+ if (BlupiBloque(tinyPoint, -1))
+ {
+ m_blupiVitesse.x = 0;
+ }
+ }
+ else if (m_keyPress & KEY_RIGHT && bAirStart)
+ {
+ if (m_blupiVitesse.x < 12)
+ {
+ m_blupiVitesse.x += 1;
+ }
+ tinyPoint.x = end.x + m_blupiVitesse.x;
+ tinyPoint.y = end.y;
+ if (BlupiBloque(tinyPoint, 1))
+ {
+ m_blupiVitesse.x = 0;
+ }
+ }
+ else
+ {
+ if (m_blupiVitesse.x > 0)
+ {
+ m_blupiVitesse.x -= 1;
+ }
+ if (m_blupiVitesse.x < 0)
+ {
+ m_blupiVitesse.x += 1;
+ }
+ }
+ end.x += m_blupiVitesse.x;
+
+ MoveObjectPollution();
+
+ if ( !bAirStart && m_blupiTransport == -1)
+ {
+
+ rect.left = m_blupiPos.x + 20;
+ rect.right = m_blupiPos.x + 22;
+ rect.top = m_blupiPos.y + 60 - 2;
+ rect.bottom = m_blupiPos.y + 60;
+ bIsOpen = !DecorDetect(rect);
+ rect.left = m_blupiPos.x + 60 - 22;
+ rect.right = m_blupiPos.x + 60 - 20;
+ rect.top = m_blupiPos.y + 60 - 2;
+ rect.bottom = m_blupiPos.y + 60;
+ bIsOpen2 = !DecorDetect(rect);
+ if (!bIsOpen && !bIsOpen2)
+ {
+ tinyPoint.x = m_blupiPos.x;
+ tinyPoint.y = m_blupiPos.y - BLUPIFLOOR;
+ ObjectStart(tinyPoint, TYPE_OVER, 0);
+ m_blupiOver = FALSE;
+ StopBlupi(TRUE);
+ m_blupiPosHelico = m_blupiPos;
+ StopSound(SOUND_HELICOHIGH);
+ StopSound(SOUND_HELICOLOW);
+ PlaySound(SOUND_HELICOSTOP, m_blupiPos);
+ }
+ }
+ }
+ if (m_blupiBalloon && m_blupiFocus)
+ {
+ if (m_keyPress & (KEY_JUMP | KEY_UP))
+ {
+ if (m_blupiVitesse.y > -5 && m_time % 6 == 0)
+ {
+ m_blupiVitesse.y -= 1;
+ }
+ }
+ else if (m_keyPress & KEY_DOWN)
+ {
+ if (m_blupiVitesse.y < 0 && m_time % 6 == 0)
+ {
+ m_blupiVitesse.y += 1;
+ }
+ }
+ else if (m_blupiVitesse.y > -3 && m_time % 6 == 0)
+ {
+ m_blupiVitesse.y -= 1;
+ }
+ end.y += (int)m_blupiVitesse.y;
+ if (m_keyPress & KEY_LEFT)
+ {
+ if (m_blupiVitesse.x > -10)
+ {
+ m_blupiVitesse.x -= 1;
+ }
+ tinyPoint.x = end.x + m_blupiVitesse.x;
+ tinyPoint.y = end.y;
+ if (BlupiBloque(tinyPoint, -1))
+ {
+ m_blupiVitesse.x = 0;
+ }
+ }
+ else if (m_keyPress & KEY_RIGHT)
+ {
+ if (m_blupiVitesse.x < 10)
+ {
+ m_blupiVitesse.x += 1;
+ }
+ tinyPoint.x = end.x + m_blupiVitesse.x;
+ tinyPoint.y = end.y;
+ if (BlupiBloque(tinyPoint, 1))
+ {
+ m_blupiVitesse.x = 0;
+ }
+ }
+ else
+ {
+ if (m_blupiVitesse.x > 0)
+ {
+ m_blupiVitesse.x -= 2;
+ if (m_blupiVitesse.x < 0)
+ {
+ m_blupiVitesse.x = 0;
+ }
+ }
+ if (m_blupiVitesse.x < 0)
+ {
+ m_blupiVitesse.x += 2;
+ if (m_blupiVitesse.x > 0)
+ {
+ m_blupiVitesse.x = 0;
+ }
+ }
+ }
+ end.x += (int)m_blupiVitesse.x;
+ }
+ if (m_blupiEcrase && m_blupiFocus)
+ {
+ if (bAirStart)
+ {
+ if (m_blupiVitesse.y < 2)
+ {
+ m_blupiVitesse.y += 1;
+ }
+ }
+ else
+ {
+ m_blupiVitesse.y = 0;
+ }
+ end.y += (int)m_blupiVitesse.y;
+ if (bAirStart)
+ {
+ num3 = 7;
+ }
+ else
+ {
+ num3 = 4;
+ }
+ if (m_keyPress & KEY_LEFT) num3 = -num3;
+ if (m_keyPress & KEY_LEFT)
+ {
+ if (m_blupiVitesse.x > num3)
+ {
+ m_blupiVitesse.x -= 1;
+ }
+ tinyPoint.x = end.x + (int)m_blupiVitesse.x;
+ tinyPoint.y = end.y;
+ if (BlupiBloque(tinyPoint, -1))
+ {
+ m_blupiVitesse.x = 0;
+ }
+ }
+ else if (m_keyPress & KEY_RIGHT)
+ {
+ if (m_blupiVitesse.x < num3)
+ {
+ m_blupiVitesse.x += 1;
+ }
+ tinyPoint.x = end.x + (int)m_blupiVitesse.x;
+ tinyPoint.y = end.y;
+ if (BlupiBloque(tinyPoint, 1))
+ {
+ m_blupiVitesse.x = 0;
+ }
+ }
+ else
+ {
+ if (m_blupiVitesse.x > 0)
+ {
+ m_blupiVitesse.x -= 2;
+ if (m_blupiVitesse.x < 0)
+ {
+ m_blupiVitesse.x = 0;
+ }
+ }
+ if (m_blupiVitesse.x < 0)
+ {
+ m_blupiVitesse.x += 2;
+ if (m_blupiVitesse.x > 0)
+ {
+ m_blupiVitesse.x = 0;
+ }
+ }
+ }
+ if (m_blupiVitesse.x == 0 && !bAirStart)
+ {
+ StopBlupi();
+ }
+ end.x += (int)m_blupiVitesse.x;
+ }
+ if (m_blupiJeep && m_blupiFocus)
+ {
+ if (m_blupiVitesse.x == 0 && m_blupiAction == 2)
+ {
+ StopBlupi();
+ }
+ //m_blupiMotorHigh = (m_blupiAction != 1);
+ rect = BlupiRect(end);
+ rect.right -= 40;
+ rect.top = end.y + 60 - 2;
+ rect.bottom = end.y + 60 - 1;
+ bIsOpen = !DecorDetect(rect);
+ rect.left += 40;
+ rect.right += 40;
+ bIsOpen2 = !DecorDetect(rect);
+ if (bAirStart)
+ {
+ if (m_blupiVitesse.y < 50)
+ {
+ m_blupiVitesse.y += 5;
+ }
+ }
+ else
+ {
+ if (m_blupiVitesse.y != 0)
+ {
+ PlaySound(SOUND_JUMPEND, m_blupiPos);
+ }
+ m_blupiVitesse.y = 0;
+ }
+ end.y += (int)m_blupiVitesse.y;
+ if (m_blupiTransport == -1)
+ {
+ rect.left = end.x + 20;
+ rect.right = end.x + 60 - 20;
+ rect.top = end.y + 60 - 35;
+ rect.bottom = end.y + 60 - 1;
+ num = AscenseurDetect(rect, m_blupiPos, end);
+ if (m_blupiVitesse.y >= 0 && num != -1)
+ {
+ m_blupiTransport = num;
+ bAirStart = FALSE;
+ PlaySound(SOUND_JUMPEND, end);
+ end.y = m_moveObject[num].posCurrent.y - 64 + BLUPIOFFY;
+ }
+ }
+ if (bIsOpen && !bIsOpen2)
+ {
+ int num13 = -20;
+ if (m_blupiVitesse.x > num13)
+ {
+ m_blupiVitesse.x -= 1;
+ }
+ }
+ else if (!bIsOpen && bIsOpen2)
+ {
+ int num14 = 20;
+ if (m_blupiVitesse.x < num14)
+ {
+ m_blupiVitesse.x += 1;
+ }
+ }
+ else if (m_keyPress & KEY_LEFT)
+ {
+ if (m_blupiVitesse.x > -20)
+ {
+ m_blupiVitesse.x -= 1;
+ }
+ }
+ else if (m_keyPress & KEY_RIGHT)
+ {
+ if (m_blupiVitesse.x < 20)
+ {
+ m_blupiVitesse.x += 1;
+ }
+ }
+ else
+ {
+ if (m_blupiVitesse.x > 0)
+ {
+ m_blupiVitesse.x -= 2;
+ if (m_blupiVitesse.x < 0)
+ {
+ m_blupiVitesse.x = 0;
+ }
+ }
+ if (m_blupiVitesse.x < 0)
+ {
+ m_blupiVitesse.x += 2;
+ if (m_blupiVitesse.x > 0)
+ {
+ m_blupiVitesse.x = 0;
+ }
+ }
+ }
+ if (m_blupiAction == 3)
+ {
+ m_blupiVitesse.x = 0;
+ }
+ end.x += (int)m_blupiVitesse.x;
+ MoveObjectPollution();
+ if ( !bLastBlupiAir && m_blupiTransport == -1)
+ {
+ tinyPoint.x = m_blupiPos.x;
+ tinyPoint.y = m_blupiPos.y - BLUPIFLOOR;
+ ObjectStart(tinyPoint, TYPE_JEEP, 0);
+ m_blupiJeep = FALSE;
+ StopBlupi();
+ m_blupiPosHelico = m_blupiPos;
+ StopSound(SOUND_JEEPHIGH);
+ StopSound(SOUND_JEEPLOW);
+ PlaySound(SOUND_JEEPSTOP, m_blupiPos);
+ }
+ }
+ if (m_blupiTank && m_blupiFocus)
+ {
+ if (m_blupiAction == 53 && m_blupiPhase == 6)
+ {
+ StopBlupi();
+ }
+ if (m_keyPress & KEY_FIRE && m_blupiTimeFire == 0 && m_blupiAction != ACTION_TURN)
+ {
+ if (m_blupiBullet == 0)
+ {
+ PlaySound(SOUND_FIREKO, m_blupiPos);
+ }
+ else
+ {
+ if (m_blupiDir == DIR_LEFT)
+ {
+ tinyPoint.x = m_blupiPos.x - 35;
+ tinyPoint.y = m_blupiPos.y;
+ num4 = -5;
+ m_blupiVitesse.x += 12;
+ }
+ else
+ {
+ tinyPoint.x = m_blupiPos.x + 35;
+ tinyPoint.y = m_blupiPos.y;
+ num4 = 5;
+ m_blupiVitesse.x -= 12;
+ }
+ if (ObjectStart(tinyPoint, TYPE_BALLE, num4) != -1)
+ {
+ m_blupiAction = 53;
+ m_blupiPhase = 0;
+ PlaySound(SOUND_FIREOK, m_blupiPos);
+ m_blupiTimeFire = 10;
+ m_blupiBullet--;
+ }
+ }
+ }
+ if (m_blupiVitesse.x == 0 && m_blupiAction == 2)
+ {
+ StopBlupi();
+ }
+ //m_blupiMotorHigh = (m_blupiAction != 1);
+ if (bAirStart)
+ {
+ if (m_blupiVitesse.y < 50)
+ {
+ m_blupiVitesse.y += 5;
+ }
+ }
+ else
+ {
+ if (m_blupiVitesse.y != 0)
+ {
+ PlaySound(SOUND_JUMPEND, m_blupiPos);
+ }
+ m_blupiVitesse.y = 0;
+ }
+ end.y += (int)m_blupiVitesse.y;
+ if (m_blupiTransport == -1)
+ {
+ rect.left = end.x + 20;
+ rect.right = end.x + 60 - 20;
+ rect.top = end.y + 60 - 35;
+ rect.bottom = end.y + 60 - 1;
+ num = AscenseurDetect(rect, m_blupiPos, end);
+ if (m_blupiVitesse.y >= 0 && num != -1)
+ {
+ m_blupiTransport = num;
+ bAirStart = FALSE;
+ PlaySound(SOUND_JUMPEND, end);
+ end.y = m_moveObject[num].posCurrent.y - 64 + BLUPIOFFY;
+ }
+ }
+ if (m_keyPress & KEY_LEFT)
+ {
+ if (m_blupiVitesse.x > -12)
+ {
+ m_blupiVitesse.x -= 1;
+ }
+ }
+ else if (m_keyPress & KEY_RIGHT)
+ {
+ if (m_blupiVitesse.x < 12)
+ {
+ m_blupiVitesse.x += 1;
+ }
+ }
+ else
+ {
+ if (m_blupiVitesse.x > 0)
+ {
+ m_blupiVitesse.x -= 3;
+ if (m_blupiVitesse.x < 0)
+ {
+ m_blupiVitesse.x = 0;
+ }
+ }
+ if (m_blupiVitesse.x < 0)
+ {
+ m_blupiVitesse.x += 3;
+ if (m_blupiVitesse.x > 0)
+ {
+ m_blupiVitesse.x = 0;
+ }
+ }
+ }
+ if (m_blupiAction == 3)
+ {
+ m_blupiVitesse.x = 0;
+ }
+ end.x += (int)m_blupiVitesse.x;
+ MoveObjectPollution();
+ if ( m_keyPress & KEY_DOWN && !bAirStart && m_blupiTransport == -1)
+ {
+
+ tinyPoint.x = m_blupiPos.x;
+ tinyPoint.y = m_blupiPos.y;
+ ObjectStart(tinyPoint, TYPE_TANK, 0);
+ m_blupiTank = FALSE;
+ StopBlupi();
+ m_blupiPosHelico = m_blupiPos;
+ StopSound(SOUND_JEEPHIGH);
+ StopSound(SOUND_JEEPLOW);
+ PlaySound(SOUND_JEEPSTOP, m_blupiPos);
+ }
+ }
+ if (m_blupiSkate && m_blupiFocus)
+ {
+ if (m_blupiVitesse.x == 0 && m_blupiAction == 2)
+ {
+ StopBlupi();
+ }
+ if (m_keyPress & KEY_LEFT)
+ {
+ if (m_blupiVitesse.x > -15)
+ {
+ m_blupiVitesse.x -= 1;
+ }
+ }
+ else if (m_keyPress & KEY_RIGHT)
+ {
+ if (m_blupiVitesse.x < 15)
+ {
+ m_blupiVitesse.x += 1;
+ }
+ }
+ else
+ {
+ if (m_blupiVitesse.x > 0)
+ {
+ m_blupiVitesse.x -= 1;
+ if (m_blupiVitesse.x < 0)
+ {
+ m_blupiVitesse.x = 0;
+ }
+ }
+ if (m_blupiVitesse.x < 0)
+ {
+ m_blupiVitesse.x += 1;
+ if (m_blupiVitesse.x > 0)
+ {
+ m_blupiVitesse.x = 0;
+ }
+ }
+ }
+ if (m_blupiAction == 3)
+ {
+ m_blupiVitesse.x = 0;
+ }
+ end.x += (int)m_blupiVitesse.x;
+ if ( m_keyPress & KEY_DOWN && !bAirStart && !m_blupiAir && m_blupiTransport == -1 && m_blupiVitesse.x < 8)
+ {
+
+ m_blupiSkate = FALSE;
+ m_blupiAction = 43;
+ m_blupiPhase = 0;
+ m_blupiFocus = FALSE;
+ m_blupiPosHelico = m_blupiPos;
+ }
+ }
+ if (m_blupiAction == 42)
+ {
+ if (m_blupiPhase == 8)
+ {
+ num = MoveObjectDetect(m_blupiPos, &bNear);
+ if (num != -1)
+ {
+ ObjectDelete(m_moveObject[num].posCurrent, m_moveObject[num].type);
+ }
+ }
+ if (m_blupiPhase == 20)
+ {
+ StopBlupi(TRUE);
+ }
+ }
+ if (m_blupiAction == 43)
+ {
+ if (m_blupiPhase == 12)
+ {
+ tinyPoint.x = m_blupiPos.x;
+ tinyPoint.y = m_blupiPos.y - BLUPIFLOOR + 1;
+ ObjectStart(tinyPoint, TYPE_SKATE, 0);
+ }
+ if (m_blupiPhase == 20)
+ {
+ StopBlupi(TRUE);
+ }
+ }
+ if (m_blupiNage && m_blupiFocus)
+ {
+ if (m_blupiTransport == -1)
+ {
+ if (m_keyPress & (KEY_JUMP | KEY_UP))
+ {
+ if (m_blupiVitesse.y > -5)
+ {
+ m_blupiVitesse.y -= 1;
+ }
+ }
+ else if (m_keyPress & KEY_DOWN)
+ {
+ if (m_blupiVitesse.y < 5)
+ {
+ m_blupiVitesse.y += 1;
+ }
+ }
+ else
+ {
+ if (m_blupiAction == 1)
+ {
+ num3 = -1;
+ }
+ else
+ {
+ num3 = 0;
+ }
+ if (m_blupiVitesse.y > num3)
+ {
+ m_blupiVitesse.y -= 1;
+ }
+ if (m_blupiVitesse.y < num3)
+ {
+ m_blupiVitesse.y += 1;
+ }
+ }
+ end.y += (int)m_blupiVitesse.y;
+ }
+ if (m_keyPress & KEY_LEFT)
+ {
+ if (m_blupiVitesse.x > -8)
+ {
+ m_blupiVitesse.x -= 1;
+ }
+ }
+ else if (m_keyPress & KEY_RIGHT)
+ {
+ if (m_blupiVitesse.x < 8)
+ {
+ m_blupiVitesse.x += 1;
+ }
+ }
+ else
+ {
+ if (m_blupiVitesse.x > 0)
+ {
+ m_blupiVitesse.x -= 2;
+ if (m_blupiVitesse.x < 0)
+ {
+ m_blupiVitesse.x = 0;
+ }
+ }
+ if (m_blupiVitesse.x < 0)
+ {
+ m_blupiVitesse.x += 2;
+ if (m_blupiVitesse.x > 0)
+ {
+ m_blupiVitesse.x = 0;
+ }
+ }
+ }
+ num = table_vitesse_nage[m_blupiPhase % 14 / 2];
+ end.x += (int)(m_blupiVitesse.x * num / 7);
+ if (m_time % 70 == 0 || m_time % 70 == 28)
+ {
+ MoveObjectBlup(end);
+ }
+ if (m_time % 5 == 0)
+ {
+ if (!m_blupiShield && !m_blupiHide && !m_bSuperBlupi)
+ {
+ m_blupiLevel--;
+ }
+ if (m_blupiLevel == 25)
+ {
+ m_jauges[JAUGE_AIR].SetType(1);
+ }
+ m_jauges[JAUGE_AIR].SetLevel(m_blupiLevel);
+ if (m_blupiLevel == 0)
+ {
+ m_blupiAction = ACTION_DROWN;
+ m_blupiPhase = 0;
+ m_blupiFocus = FALSE;
+ m_blupiHelico = FALSE;
+ m_blupiOver = FALSE;
+ m_blupiJeep = FALSE;
+ m_blupiTank = FALSE;
+ m_blupiSkate = FALSE;
+ m_blupiNage = FALSE;
+ m_blupiSurf = FALSE;
+ m_blupiSuspend = FALSE;
+ m_blupiJumpAie = FALSE;
+ m_blupiShield = FALSE;
+ m_blupiPower = FALSE;
+ m_blupiCloud = FALSE;
+ m_blupiHide = FALSE;
+ m_blupiInvert = FALSE;
+ m_blupiBalloon = FALSE;
+ m_blupiEcrase = FALSE;
+ m_blupiAir = FALSE;
+ m_blupiRestart = TRUE;
+ m_blupiActionOuf = 0;
+ m_jauges[JAUGE_AIR].SetHide(TRUE);
+ m_jauges[JAUGE_POWER].SetHide(TRUE);
+ PlaySound(SOUND_DROWN, end);
+ }
+ }
+ }
+ if (m_blupiSurf && m_blupiFocus)
+ {
+ if (m_blupiTransport == -1)
+ {
+ if (m_keyPress & (KEY_JUMP | KEY_UP))
+ {
+ if (m_blupiVitesse.y > -5)
+ {
+ m_blupiVitesse.y -= 1;
+ }
+ }
+ else if (m_keyPress & KEY_DOWN)
+ {
+ if (m_blupiVitesse.y < 5)
+ {
+ m_blupiVitesse.y += 1;
+ }
+ }
+ else
+ {
+ if (m_blupiVitesse.y > -2)
+ {
+ m_blupiVitesse.y -= 1;
+ }
+ if (m_blupiVitesse.y < -2)
+ {
+ m_blupiVitesse.y += 1;
+ }
+ }
+ end.y += (int)m_blupiVitesse.y;
+ end.y += BLUPISURF;
+ if (end.y % 64 > 30)
+ {
+ end.y += 64 - end.y % 64;
+ }
+ end.y -= BLUPISURF;
+ }
+ if (m_keyPress & KEY_LEFT)
+ {
+ if (m_blupiVitesse.x > -8)
+ {
+ m_blupiVitesse.x -= 1;
+ }
+ }
+ else if (m_keyPress & KEY_RIGHT)
+ {
+ if (m_blupiVitesse.x < 8)
+ {
+ m_blupiVitesse.x += 1;
+ }
+ }
+ else
+ {
+ if (m_blupiVitesse.x > 0)
+ {
+ m_blupiVitesse.x -= 2;
+ if (m_blupiVitesse.x < 0)
+ {
+ m_blupiVitesse.x = 0;
+ }
+ }
+ if (m_blupiVitesse.x < 0)
+ {
+ m_blupiVitesse.x += 2;
+ if (m_blupiVitesse.x > 0)
+ {
+ m_blupiVitesse.x = 0;
+ }
+ }
+ }
+ num = table_vitesse_surf[m_blupiPhase % 12 / 2];
+ end.x += (int)(m_blupiVitesse.x * num / 10);
+ }
+ POINT tinyPoint4;
+ if (m_blupiSuspend && m_blupiFocus)
+ {
+ if (m_keyPress & KEY_LEFT && m_blupiAction == 2)
+ {
+ end.x -= 5;
+ }
+ if (m_keyPress & KEY_RIGHT && m_blupiAction == 2)
+ {
+ end.x += 5;
+ }
+ num = GetTypeBarre(end);
+ if (num == 2)
+ {
+ tinyPoint4.x = end.x;
+ tinyPoint4.y = end.y / 64 * 64 + BLUPIOFFY;
+ rect = BlupiRect(tinyPoint4);
+ if (!DecorDetect(rect, TRUE))
+ {
+ m_blupiSuspend = FALSE;
+ StopBlupi();
+ end = tinyPoint4;
+ m_blupiPos = end;
+ }
+ }
+ if ((m_keyPress & KEY_DOWN && m_blupiPhase > 5) || num == 0)
+ {
+ m_blupiSuspend = FALSE;
+ m_blupiAir = TRUE;
+ m_blupiAction = 5;
+ end.y = end.y;
+ m_blupiVitesse.y = 0;
+ m_blupiNoBarre = 5;
+ m_blupiActionOuf = 65;
+ m_blupiTimeOuf = 0;
+ }
+ if ((m_keyPress & KEY_JUMP || m_keyPress & KEY_UP) && m_blupiAction != ACTION_JUMP && m_blupiAction != ACTION_TURN)
+ {
+ m_blupiAction = 4;
+ m_blupiPhase = 0;
+ }
+ if (!(m_keyPress & KEY_JUMP) && !(m_keyPress & (KEY_UP | KEY_DOWN)) && m_blupiAction == 4)
+ {
+ StopBlupi();
+ }
+ if (m_blupiAction == 4 && m_blupiPhase == 10)
+ {
+ m_blupiSuspend = FALSE;
+ m_blupiAir = TRUE;
+ m_blupiAction = ACTION_AIR;
+ m_blupiPhase = 0;
+ end.y -= 2;
+ m_blupiVitesse.y = -11;
+ m_blupiNoBarre = 5;
+ PlaySound(SOUND_SUSPENDJUMP, end);
+ }
+ }
+ if (m_keyPress & KEY_FIRE &&
+ !m_blupiHelico &&
+ !m_blupiOver &&
+ !m_blupiBalloon &&
+ !m_blupiEcrase &&
+ !m_blupiTank &&
+ !m_blupiJeep &&
+ !m_blupiSkate &&
+ !bAirStart &&
+ m_blupiTransport == -1 &&
+ m_blupiFocus)
+ {
+ if (m_blupiDynamite > 0)
+ {
+
+ rect.left = end.x + 18;
+ rect.right = end.x + 20;
+ rect.top = end.y + 60 - 2;
+ rect.bottom = end.y + 60;
+ bIsOpen = !DecorDetect(rect);
+ rect.left = end.x + 60 - 20;
+ rect.right = end.x + 60 - 18;
+ rect.top = end.y + 60 - 2;
+ rect.bottom = end.y + 60;
+ bIsOpen2 = !DecorDetect(rect);
+ if (!bIsOpen && !bIsOpen2 && ObjectStart(end, TYPE_DYNAMITEf, 0) != -1)
+ {
+ m_blupiAction = ACTION_PUTDYNAMITE;
+ m_blupiPhase = 0;
+ m_blupiFocus = FALSE;
+ PlaySound(SOUND_PERSOPOSE, end);
+ m_blupiDynamite--;
+ }
+ }
+ else if (m_blupiPerso > 0)
+ {
+ num = MoveObjectDetect(end, &bNear);
+ if (num == -1 || m_moveObject[num].type != TYPE_BOMBEPERSO1)
+ {
+ rect.left = end.x + 18;
+ rect.right = end.x + 20;
+ rect.top = end.y + DIMBLUPIY - 2;
+ rect.bottom = end.y + DIMBLUPIY;
+ bIsOpen = !DecorDetect(rect);
+ rect.left = end.x + DIMBLUPIX - 20;
+ rect.right = end.x + DIMBLUPIX - 18;
+ rect.top = end.y + DIMBLUPIY - 2;
+ rect.bottom = end.y + DIMBLUPIY;
+ bIsOpen2 = !DecorDetect(rect);
+ num = MoveChargeDetect(end);
+ if (num == -1 && !bIsOpen && !bIsOpen2 && ObjectStart(end, TYPE_BOMBEPERSO1, 0) != -1)
+ {
+ m_blupiAction = ACTION_OUF2;
+ m_blupiPhase = 0;
+ m_blupiFocus = FALSE;
+ PlaySound(SOUND_PERSOPOSE, end);
+ m_blupiPerso--;
+ }
+ }
+ if (m_blupiFocus)
+ {
+ m_blupiAction = ACTION_OUF3;
+ m_blupiPhase = 0;
+ PlaySound(SOUND_ERROR, end);
+ }
+ }
+ }
+ rect = BlupiRect(m_blupiPos);
+ tinyPoint4 = end;
+ TestPath(rect, m_blupiPos, &end);
+ if (bLastBlupiAir && m_blupiPos.x == end.x && m_blupiPos.x != tinyPoint4.x)
+ {
+ end.y = tinyPoint4.y;
+ TestPath(rect, m_blupiPos, &end);
+ }
+ if (m_blupiVent && m_blupiPos.y == end.y && m_blupiPos.y != tinyPoint4.y)
+ {
+ end.x = tinyPoint4.x;
+ TestPath(rect, m_blupiPos, &end);
+ }
+ if (m_blupiTransport != -1 && m_blupiPos.x == end.x && m_blupiPos.x != tinyPoint4.x)
+ {
+ end.y = tinyPoint4.y;
+ TestPath(rect, m_blupiPos, &end);
+ }
+ if (m_blupiHelico || m_blupiOver || m_blupiBalloon || m_blupiEcrase || m_blupiJeep || m_blupiTank || m_blupiSkate || m_blupiNage)
+ {
+ if (m_blupiPos.x == end.x && m_blupiPos.x != tinyPoint4.x)
+ {
+ end.y = tinyPoint4.y;
+ TestPath(rect, m_blupiPos, &end);
+ }
+ else if (m_blupiPos.y == end.y && m_blupiPos.y != tinyPoint4.y)
+ {
+ end.x = tinyPoint4.x;
+ TestPath(rect, m_blupiPos, &end);
+ }
+ }
+ POINT blupiPos = m_blupiPos;
+ m_blupiPos = end;
+ if ((m_blupiAction == ACTION_STOP ||
+ m_blupiAction == ACTION_STOPMARCH ||
+ m_blupiAction == ACTION_UP ||
+ m_blupiAction == ACTION_DOWN) &&
+ !m_blupiAir &&
+ !m_blupiBalloon &&
+ !m_blupiEcrase &&
+ !m_blupiJeep &&
+ !m_blupiTank &&
+ !m_blupiSkate &&
+ !m_blupiNage &&
+ !m_blupiSurf &&
+ !m_blupiSuspend &&
+ m_blupiFocus)
+ {
+ if (m_blupiTransport != -1)
+ {
+ AscenseurVertigo(m_blupiTransport, &bIsOpen, &bIsOpen2);
+ }
+ else
+ {
+ rect.left = end.x + 24;
+ rect.right = end.x + 26;
+ rect.top = end.y + DIMBLUPIY - 2;
+ rect.bottom = end.y + DIMBLUPIY;
+ bIsOpen = !DecorDetect(rect);
+ rect.left = end.x + DIMBLUPIX - 26;
+ rect.right = end.x + DIMBLUPIX - 24;
+ rect.top = end.y + DIMBLUPIY - 2;
+ rect.bottom = end.y + DIMBLUPIY;
+ bIsOpen2 = !DecorDetect(rect);
+ }
+ if (m_blupiDir == DIR_LEFT && bIsOpen && !bIsOpen2)
+ {
+ if (m_blupiHelico || m_blupiOver || AscenseurShift(m_blupiTransport))
+ {
+ m_blupiAction = ACTION_RECEDE;
+ m_blupiPhase = 0;
+ }
+ else
+ {
+ PlaySound(SOUND_VERTIGO, end);
+ m_blupiAction = ACTION_VERTIGO;
+ m_blupiPhase = 0;
+ }
+ }
+ if (m_blupiDir == DIR_RIGHT && !bIsOpen && bIsOpen2)
+ {
+ if (m_blupiHelico || m_blupiOver || AscenseurShift(m_blupiTransport))
+ {
+ m_blupiAction = ACTION_RECEDE;
+ m_blupiPhase = 0;
+ }
+ else
+ {
+ PlaySound(SOUND_VERTIGO, end);
+ m_blupiAction = ACTION_VERTIGO;
+ m_blupiPhase = 0;
+ }
+ }
+ if (m_blupiAction != ACTION_VERTIGO &&
+ m_blupiAction != ACTION_ADVANCE &&
+ m_blupiAction != ACTION_RECEDE &&
+ (bIsOpen || bIsOpen2))
+ {
+ if (!m_blupiHelico && !m_blupiOver)
+ {
+ PlaySound(SOUND_VERTIGO, end);
+ }
+ m_blupiAction = ACTION_ADVANCE;
+ m_blupiPhase = 0;
+ }
+ }
+ if (m_blupiAction == ACTION_STOP &&
+ m_blupiJeep &&
+ !m_blupiHelico &&
+ !m_blupiOver &&
+ !m_blupiBalloon &&
+ !m_blupiEcrase &&
+ !m_blupiNage &&
+ !m_blupiSurf &&
+ !m_blupiSuspend &&
+ m_blupiFocus)
+ {
+ if (m_blupiTransport != -1)
+ {
+ AscenseurVertigo(m_blupiTransport, &bIsOpen, &bIsOpen2);
+ }
+ else
+ {
+ rect.left = end.x + 2;
+ rect.right = end.x + 18;
+ rect.top = end.y + DIMBLUPIY - 2;
+ rect.bottom = end.y + DIMBLUPIY;
+ bIsOpen = !DecorDetect(rect);
+ rect.left = end.x + DIMBLUPIX - 18;
+ rect.right = end.x + DIMBLUPIX - 2;
+ rect.top = end.y + DIMBLUPIY - 2;
+ rect.bottom = end.y + DIMBLUPIY;
+ bIsOpen2 = !DecorDetect(rect);
+ }
+ if (bIsOpen && !bIsOpen2)
+ {
+ m_blupiAction = ACTION_ADVANCE;
+ m_blupiPhase = 0;
+ }
+ if (!bIsOpen && bIsOpen2)
+ {
+ m_blupiAction = ACTION_ADVANCE;
+ m_blupiPhase = 0;
+ }
+ }
+ if (m_blupiAction == ACTION_STOP &&
+ m_blupiTank &&
+ !m_blupiHelico &&
+ !m_blupiOver &&
+ !m_blupiBalloon &&
+ !m_blupiEcrase &&
+ !m_blupiNage &&
+ !m_blupiSurf &&
+ !m_blupiSuspend &&
+ m_blupiFocus)
+ {
+ if (m_blupiTransport != -1)
+ {
+ AscenseurVertigo(m_blupiTransport, &bIsOpen, &bIsOpen2);
+ }
+ else
+ {
+ rect.left = end.x + 2;
+ rect.right = end.x + 18;
+ rect.top = end.y + DIMBLUPIY - 2;
+ rect.bottom = end.y + DIMBLUPIY;
+ bIsOpen = !DecorDetect(rect);
+ rect.left = end.x + DIMBLUPIX - 18;
+ rect.right = end.x + DIMBLUPIX - 2;
+ rect.top = end.y + DIMBLUPIY - 2;
+ rect.bottom = end.y + DIMBLUPIY;
+ bIsOpen2 = !DecorDetect(rect);
+ }
+ if (bIsOpen && !bIsOpen2)
+ {
+ m_blupiAction = ACTION_ADVANCE;
+ m_blupiPhase = 0;
+ }
+ if (!bIsOpen && bIsOpen2)
+ {
+ m_blupiAction = ACTION_ADVANCE;
+ m_blupiPhase = 0;
+ }
+ }
+ if (m_blupiAction == ACTION_STOP &&
+ m_blupiSkate &&
+ !m_blupiHelico &&
+ !m_blupiOver &&
+ !m_blupiBalloon &&
+ !m_blupiEcrase &&
+ !m_blupiNage &&
+ !m_blupiSurf &&
+ !m_blupiSuspend &&
+ m_blupiFocus)
+ {
+ if (m_blupiTransport != -1)
+ {
+ AscenseurVertigo(m_blupiTransport, &bIsOpen, &bIsOpen2);
+ }
+ else
+ {
+ rect.left = end.x + 12;
+ rect.right = end.x + 19;
+ rect.top = end.y + DIMBLUPIY - 2;
+ rect.bottom = end.y + DIMBLUPIY;
+ bIsOpen = !DecorDetect(rect);
+ rect.left = end.x + DIMBLUPIX - 19;
+ rect.right = end.x + DIMBLUPIX - 12;
+ rect.top = end.y + DIMBLUPIY - 2;
+ rect.bottom = end.y + DIMBLUPIY;
+ bIsOpen2 = !DecorDetect(rect);
+ }
+ if (bIsOpen && !bIsOpen2)
+ {
+ m_blupiAction = ACTION_ADVANCE;
+ m_blupiPhase = 0;
+ }
+ if (!bIsOpen && bIsOpen2)
+ {
+ m_blupiAction = ACTION_ADVANCE;
+ m_blupiPhase = 0;
+ }
+ }
+ if (m_blupiFocus)
+ {
+ if (m_blupiAction == ACTION_VERTIGO && m_blupiPhase == 16)
+ {
+ m_blupiAction = ACTION_RECEDE;
+ m_blupiPhase = 0;
+ }
+ if (m_blupiAction == ACTION_RECEDE && m_blupiPhase == 3)
+ {
+ StopBlupi();
+ m_blupiActionOuf = 0;
+ }
+ num3 = 5;
+ if (m_blupiJeep)
+ {
+ num3 = 10;
+ }
+ if (m_blupiTank)
+ {
+ num3 = 10;
+ }
+ if (m_blupiSkate)
+ {
+ num3 = 10;
+ }
+ if (m_blupiAction == ACTION_ADVANCE && m_blupiPhase == num3)
+ {
+ StopBlupi();
+ }
+ }
+ BlupiSearchIcon();
+ if (m_blupiShield)
+ {
+ if (m_blupiTimeShield == 10)
+ {
+ PlaySound(SOUND_STOPSHIELD, m_blupiPos);
+ }
+ if (m_blupiTimeShield == 0)
+ {
+ m_blupiShield = FALSE;
+ m_jauges[JAUGE_POWER].SetHide(TRUE);
+ }
+ else if (m_time % 5 == 0)
+ {
+ m_blupiTimeShield--;
+ m_jauges[JAUGE_POWER].SetLevel(m_blupiTimeShield);
+ }
+ }
+ if (m_blupiPower)
+ {
+ if (m_blupiTimeShield == 20)
+ {
+ PlaySound(SOUND_STOPPOWER, m_blupiPos);
+ }
+ if (m_blupiTimeShield == 0)
+ {
+ m_blupiPower = FALSE;
+ m_jauges[JAUGE_POWER].SetHide(TRUE);
+ }
+ else if (m_time % 3 == 0)
+ {
+ m_blupiTimeShield--;
+ m_jauges[JAUGE_POWER].SetLevel(m_blupiTimeShield);
+ }
+ }
+ if (m_blupiCloud)
+ {
+ if (m_blupiTimeShield == 25)
+ {
+ PlaySound(SOUND_STOPCLOUD, m_blupiPos);
+ }
+ if (m_blupiTimeShield == 0)
+ {
+ m_blupiCloud = FALSE;
+ m_jauges[JAUGE_POWER].SetHide(TRUE);
+ }
+ else if (m_time % 4 == 0)
+ {
+ m_blupiTimeShield--;
+ m_jauges[JAUGE_POWER].SetLevel(m_blupiTimeShield);
+ }
+ }
+ if (m_blupiHide)
+ {
+ if (m_blupiTimeShield == 20)
+ {
+ PlaySound(SOUND_STOPHIDE, m_blupiPos);
+ }
+ if (m_blupiTimeShield == 0)
+ {
+ m_blupiHide = FALSE;
+ m_jauges[JAUGE_POWER].SetHide(TRUE);
+ }
+ else if (m_time % 4 == 0)
+ {
+ m_blupiTimeShield--;
+ m_jauges[JAUGE_POWER].SetLevel(m_blupiTimeShield);
+ }
+ }
+ if (m_blupiInvert)
+ {
+ if (m_blupiTimeShield == 0)
+ {
+ m_blupiInvert = FALSE;
+ m_jauges[JAUGE_POWER].SetHide(TRUE);
+ tinyPoint.x = m_blupiPos.x;
+ tinyPoint.y = m_blupiPos.y + 100;
+ ObjectStart(tinyPoint, TYPE_INVERTSTOP, -60);
+ tinyPoint.x = m_blupiPos.x;
+ tinyPoint.y = m_blupiPos.y - 100;
+ ObjectStart(tinyPoint, TYPE_INVERTSTOP, 60);
+ tinyPoint.x = m_blupiPos.x - 100;
+ tinyPoint.y = m_blupiPos.y;
+ ObjectStart(tinyPoint, TYPE_INVERTSTOP, 10);
+ tinyPoint.x = m_blupiPos.x + 100;
+ tinyPoint.y = m_blupiPos.y;
+ ObjectStart(tinyPoint, TYPE_INVERTSTOP, -10);
+ PlaySound(SOUND_INVERTSTOP, end);
+ }
+ else if (m_time % 3 == 0)
+ {
+ m_blupiTimeShield--;
+ m_jauges[JAUGE_POWER].SetLevel(m_blupiTimeShield);
+ }
+ }
+ if (m_blupiBalloon)
+ {
+ if (m_blupiTimeShield == 0)
+ {
+ m_blupiBalloon = FALSE;
+ m_jauges[JAUGE_POWER].SetHide(TRUE);
+ tinyPoint.x = m_blupiPos.x - 34;
+ tinyPoint.y = m_blupiPos.y - 34;
+ ObjectStart(tinyPoint, TYPE_EXPLO6, 0);
+ PlaySound(SOUND_RESSORT, m_blupiPos);
+ }
+ else if (m_time % 2 == 0)
+ {
+ m_blupiTimeShield--;
+ m_jauges[JAUGE_POWER].SetLevel(m_blupiTimeShield);
+ }
+ }
+ if (m_blupiEcrase)
+ {
+ if (m_blupiTimeShield == 0)
+ {
+ m_blupiEcrase = FALSE;
+ m_blupiAir = TRUE;
+ m_jauges[JAUGE_POWER].SetHide(TRUE);
+ ObjectStart(m_blupiPos, TYPE_INVERTSTART, -60);
+ ObjectStart(m_blupiPos, TYPE_INVERTSTART, 60);
+ ObjectStart(m_blupiPos, TYPE_INVERTSTART, 10);
+ ObjectStart(m_blupiPos, TYPE_INVERTSTART, -10);
+ tinyPoint.x = m_blupiPos.x - 34;
+ tinyPoint.y = m_blupiPos.y - 34;
+ ObjectStart(tinyPoint, TYPE_EXPLO5, 0);
+ PlaySound(SOUND_RESSORT, m_blupiPos);
+ }
+ else if (m_time % 2 == 0)
+ {
+ m_blupiTimeShield--;
+ m_jauges[JAUGE_POWER].SetLevel(m_blupiTimeShield);
+ }
+ }
+ if (m_blupiPower && abs(m_blupiPos.x - m_blupiPosMagic.x) + abs(m_blupiPos.y - m_blupiPosMagic.y) >= 40)
+ {
+ num = MoveObjectFree();
+ if (num != -1)
+ {
+ m_moveObject[num].type = TYPE_MAGICTRACK;
+ m_moveObject[num].phase = 0;
+ m_moveObject[num].posCurrent = m_blupiPos;
+ m_moveObject[num].posStart = m_moveObject[num].posCurrent;
+ m_moveObject[num].posEnd = m_moveObject[num].posCurrent;
+ m_moveObject[num].step = STEP_STOPSTART;
+ m_moveObject[num].time = 0;
+ MoveObjectStepIcon(num);
+ m_blupiPosMagic = m_blupiPos;
+ }
+ }
+ if (m_blupiShield && abs(m_blupiPos.x - m_blupiPosMagic.x) + abs(m_blupiPos.y - m_blupiPosMagic.y) >= 40)
+ {
+ num = MoveObjectFree();
+ if (num != -1)
+ {
+ m_moveObject[num].type = TYPE_SHIELDTRACK;
+ m_moveObject[num].phase = 0;
+ m_moveObject[num].posCurrent = m_blupiPos;
+ m_moveObject[num].posStart = m_moveObject[num].posCurrent;
+ m_moveObject[num].posEnd = m_moveObject[num].posCurrent;
+ m_moveObject[num].step = STEP_STOPSTART;
+ m_moveObject[num].time = 0;
+ MoveObjectStepIcon(num);
+ m_blupiPosMagic = m_blupiPos;
+ }
+ }
+ /* // winphone
+ if (m_blupiHide && abs(m_blupiPos.x - m_blupiPosMagic.x) + abs(m_blupiPos.y - m_blupiPosMagic.y) >= 10)
+ {
+ num = MoveObjectFree();
+ if (num != -1)
+ {
+ m_moveObject[num].type = TYPE_HIDETRACK;
+ m_moveObject[num].icon = m_blupiIcon;
+ m_moveObject[num].channel = CHBLUPI;
+ m_moveObject[num].phase = 0;
+ m_moveObject[num].posCurrent = m_blupiPos;
+ m_moveObject[num].posStart = m_moveObject[num].posCurrent;
+ m_moveObject[num].posEnd = m_moveObject[num].posCurrent;
+ m_moveObject[num].step = STEP_STOPSTART;
+ m_moveObject[num].time = 0;
+ MoveObjectStepIcon(num);
+ m_blupiPosMagic = m_blupiPos;
+ }
+ }
+ */
+ if (m_blupiTimeNoAsc > 0)
+ {
+ m_blupiTimeNoAsc--;
+ }
+ if (m_blupiHelico && m_blupiPos.y > 2 && m_blupiFocus && !m_blupiShield && !m_blupiHide && !m_bSuperBlupi)
+ {
+ rect = BlupiRect(end);
+ rect.top = end.y + 4;
+ rect.bottom = end.y + 20;
+ if (DecorDetect(rect))
+ {
+ StopBlupi();
+ m_blupiHelico = FALSE;
+ tinyPoint.x = m_blupiPos.x - 34;
+ tinyPoint.y = m_blupiPos.y - 34;
+ ObjectStart(tinyPoint, TYPE_EXPLO2, 0);
+ m_decorAction = 1;
+ m_decorPhase = 0;
+ StopVehicleSound();
+ PlaySound(SOUND_BOUM, m_blupiPos);
+ }
+ }
+ if (!m_blupiHelico && !m_blupiOver && !m_blupiBalloon && !m_blupiEcrase && !m_blupiJeep && !m_blupiTank && !m_blupiSkate && m_blupiFocus)
+ {
+ if (!m_blupiNage && !m_blupiSurf && IsSurfWater(m_blupiPos))
+ {
+ m_scrollAdd.x = 0;
+ m_scrollAdd.y = 0;
+ m_blupiAir = FALSE;
+ m_blupiNage = FALSE;
+ m_blupiSurf = TRUE;
+ StopBlupi();
+ m_blupiVitesse.x = 0;
+ m_blupiVitesse.y = 0;
+ MoveObjectPlouf(m_blupiPos);
+ if (m_blupiTransport != -1)
+ {
+ m_blupiPos.y = m_blupiPos.y - 10;
+ m_blupiTransport = -1;
+ }
+ if (m_blupiCloud)
+ {
+ m_blupiCloud = FALSE;
+ m_jauges[JAUGE_POWER].SetHide(TRUE);
+ }
+ }
+ if (!m_blupiNage && !IsSurfWater(m_blupiPos) && IsDeepWater(m_blupiPos))
+ {
+ if (!m_blupiSurf)
+ {
+ StopBlupi();
+ m_blupiVitesse.x = 0;
+ m_blupiVitesse.y = 0;
+ MoveObjectPlouf(m_blupiPos);
+ }
+ m_blupiAir = FALSE;
+ m_blupiSurf = FALSE;
+ m_blupiNage = TRUE;
+ m_blupiLevel = 100;
+ m_jauges[JAUGE_AIR].SetLevel(m_blupiLevel);
+ m_jauges[JAUGE_AIR].SetType(2);
+ m_jauges[JAUGE_AIR].SetHide(FALSE);
+ }
+ if (m_blupiNage && IsSurfWater(m_blupiPos))
+ {
+ m_blupiAir = FALSE;
+ m_blupiNage = FALSE;
+ m_blupiSurf = TRUE;
+ PlaySound(SOUND_DROWN, m_blupiPos);
+ m_jauges[JAUGE_AIR].SetHide(TRUE);
+ }
+ tinyPoint4.x = m_blupiPos.x;
+ tinyPoint4.y = m_blupiPos.y - DIMOBJY;
+ if ((m_blupiSurf || m_blupiNage) && (m_blupiPos.y % DIMOBJY == DIMOBJY - BLUPISURF || m_blupiPos.y % DIMOBJY == DIMOBJY / 2) && IsOutWater(tinyPoint4) && m_keyPress & KEY_JUMP)
+ {
+ m_blupiNage = FALSE;
+ m_blupiSurf = FALSE;
+ m_blupiAir = TRUE;
+ m_blupiAction = ACTION_AIR;
+ m_blupiPhase = 0;
+ m_blupiVitesse.x = 0;
+ if (m_blupiPower)
+ {
+ m_blupiVitesse.y = -16;
+ }
+ else
+ {
+ m_blupiVitesse.y = -12;
+ }
+ MoveObjectTiplouf(m_blupiPos);
+ PlaySound(SOUND_JUMP0, m_blupiPos);
+ m_jauges[JAUGE_AIR].SetHide(TRUE);
+ }
+ if ((m_blupiSurf || m_blupiNage) && IsOutWater(m_blupiPos))
+ {
+ if (m_blupiVitesse.y < 0)
+ {
+ if (m_blupiTransport == -1)
+ {
+ m_blupiPos = blupiPos;
+ }
+ else
+ {
+ m_blupiTransport = -1;
+ m_blupiNage = FALSE;
+ m_blupiSurf = FALSE;
+ m_blupiAir = TRUE;
+ m_blupiAction = ACTION_AIR;
+ m_blupiPhase = 0;
+ m_blupiPos.y = m_blupiPos.y - 10;
+ m_blupiVitesse.x = 0;
+ m_blupiVitesse.y = -10;
+ PlaySound(SOUND_JUMP0, m_blupiPos);
+ m_jauges[JAUGE_AIR].SetHide(TRUE);
+ }
+ }
+ else if (m_blupiVitesse.y > 0)
+ {
+ m_blupiNage = FALSE;
+ m_blupiSurf = FALSE;
+ m_blupiAir = FALSE;
+ m_blupiAction = ACTION_AIR;
+ m_blupiPhase = 0;
+ m_blupiPos.y = m_blupiPos.y + 30;
+ m_blupiVitesse.x = 0;
+ m_blupiVitesse.y = 0;
+ PlaySound(SOUND_JUMP0, m_blupiPos);
+ m_jauges[JAUGE_AIR].SetHide(TRUE);
+ }
+ else
+ {
+ m_blupiNage = FALSE;
+ m_blupiSurf = FALSE;
+ m_blupiAir = FALSE;
+ StopBlupi();
+ m_blupiPos.y = m_blupiPos.y - 10;
+ m_blupiVitesse.x = 0;
+ m_blupiVitesse.y = 0;
+ PlaySound(SOUND_JUMP0, m_blupiPos);
+ m_jauges[JAUGE_AIR].SetHide(TRUE);
+ }
+ }
+ if ((m_blupiSurf || m_blupiNage) && m_blupiActionOuf != ACTION_OUF1a)
+ {
+ m_blupiActionOuf = ACTION_OUF1a;
+ m_blupiTimeOuf = 0;
+ }
+ }
+ if ((m_blupiHelico || m_blupiOver || m_blupiJeep || m_blupiTank || m_blupiSkate) && m_blupiFocus && (IsSurfWater(m_blupiPos) || IsDeepWater(m_blupiPos)))
+ {
+
+ StopBlupi();
+ m_blupiHelico = FALSE;
+ m_blupiOver = FALSE;
+ m_blupiJeep = FALSE;
+ m_blupiTank = FALSE;
+ m_blupiSkate = FALSE;
+ tinyPoint.x = m_blupiPos.x - 34;
+ tinyPoint.y = m_blupiPos.y - 34;
+ ObjectStart(tinyPoint, TYPE_EXPLO2, 0);
+ m_decorAction = 1;
+ m_decorPhase = 0;
+ StopVehicleSound();
+ PlaySound(SOUND_BOUM, m_blupiPos);
+ }
+ if (m_blupiFocus && !m_blupiSuspend && !m_blupiHelico && !m_blupiOver && !m_blupiBalloon && !m_blupiEcrase && !m_blupiJeep && !m_blupiTank && !m_blupiSkate && !m_blupiNage && !m_blupiSurf && m_blupiNoBarre == 0 && GetTypeBarre(m_blupiPos) == 1)
+ {
+ tinyPoint4.x = m_blupiPos.x;
+ tinyPoint4.y = (m_blupiPos.y + 22) / DIMOBJY * DIMOBJY + BLUPISUSPEND;
+ rect = BlupiRect(tinyPoint4);
+ if (!DecorDetect(rect, TRUE))
+ {
+ m_blupiPos = tinyPoint4;
+ m_blupiSuspend = TRUE;
+ m_blupiAir = FALSE;
+ StopBlupi();
+ m_blupiActionOuf = 0;
+ PlaySound(SOUND_SUSPENDTOC, m_blupiPos);
+ }
+ }
+ if (m_blupiNoBarre > 0)
+ {
+ m_blupiNoBarre--;
+ }
+ if (IsVentillo(m_blupiPos))
+ {
+ if (m_blupiFocus && !m_blupiShield && !m_blupiHide && !m_bSuperBlupi)
+ {
+ BlupiDead(ACTION_CLEAR1, ACTION_CLEAR2);
+ }
+ tinyPoint.x = m_blupiPos.x - 34;
+ tinyPoint.y = m_blupiPos.y - 34;
+ ObjectStart(tinyPoint, TYPE_EXPLO4, 0);
+ m_decorAction = 2;
+ m_decorPhase = 0;
+ StopVehicleSound();
+ PlaySound(SOUND_BOUM, m_blupiPos);
+ }
+ if (m_blupiAction != ACTION_STOPTANK && m_blupiFocus)
+ {
+ num = IsWorld(m_blupiPos);
+ if (num != -1)
+ {
+ StopVehicleSound();
+ PlaySound(SOUND_BYE, m_blupiPos);
+ m_blupiAction = ACTION_BYE;
+ m_blupiPhase = 0;
+ m_blupiFocus = FALSE;
+ m_blupiFront = TRUE;
+ }
+ }
+ int num27 = MoveObjectDetect(m_blupiPos, &bNear);
+ POINT tinyPoint5;
+ if (m_blupiAction != ACTION_CLEAR1 &&
+ m_blupiAction != ACTION_CLEAR2 &&
+ m_blupiAction != ACTION_CLEAR3 &&
+ m_blupiAction != ACTION_CLEAR4 &&
+ m_blupiAction != ACTION_CLEAR5 &&
+ m_blupiAction != ACTION_CLEAR6 &&
+ m_blupiAction != ACTION_CLEAR7 &&
+ m_blupiAction != ACTION_CLEAR8)
+ {
+ if (IsLave(m_blupiPos) && !m_blupiShield && !m_blupiHide && !m_bSuperBlupi)
+ {
+ BlupiDead(ACTION_CLEAR3, -1);
+ m_blupiRestart = TRUE;
+ m_blupiPos.y = m_blupiPos.y / DIMOBJY * DIMOBJY + BLUPIOFFY;
+ PlaySound(SOUND_FALL, m_blupiPos);
+ }
+ if (IsPiege(m_blupiPos) && !m_blupiOver && !m_blupiJeep && !m_blupiTank && !m_blupiShield && !m_blupiHide && !m_bSuperBlupi && m_blupiFocus)
+ {
+ BlupiDead(ACTION_GLU, -1);
+ m_blupiRestart = TRUE;
+ m_blupiAir = TRUE;
+ ObjectStart(m_blupiPos, TYPE_TENTACULE, 0);
+ PlaySound(SOUND_GLU, m_blupiPos);
+ }
+ if (IsGoutte(m_blupiPos, FALSE) && !m_blupiOver && !m_blupiJeep && !m_blupiTank && !m_blupiShield && !m_blupiHide && !m_bSuperBlupi && m_blupiFocus)
+ {
+ BlupiDead(ACTION_GLU, -1);
+ m_blupiRestart = TRUE;
+ m_blupiAir = TRUE;
+ PlaySound(SOUND_GLU, m_blupiPos);
+ }
+ if (IsScie(m_blupiPos) && !m_blupiOver && !m_blupiJeep && !m_blupiTank && !m_blupiShield && !m_blupiHide && !m_bSuperBlupi && m_blupiFocus)
+ {
+ BlupiDead(ACTION_CLEAR4, -1);
+ m_blupiFront = TRUE;
+ m_blupiRestart = TRUE;
+ m_blupiAir = TRUE;
+ }
+ if ( (num27 == -1 || !bNear) && IsSwitch(m_blupiPos, &tinyPoint) && !m_blupiOver && !m_blupiBalloon && !m_blupiJeep && !m_blupiTank && !m_blupiSkate && !m_blupiShield && !m_blupiHide && !m_bSuperBlupi && m_blupiFocus)
+ {
+
+ ActiveSwitch(m_decor[tinyPoint.x][tinyPoint.y].icon == 385, tinyPoint);
+ m_blupiAction = ACTION_SWITCH;
+ m_blupiPhase = 0;
+ m_blupiFocus = FALSE;
+ m_blupiVitesse.x = 0;
+ m_blupiVitesse.y = 0;
+ }
+ if (IsBlitz(m_blupiPos, FALSE) && !m_blupiShield && !m_blupiHide && !m_bSuperBlupi)
+ {
+ BlupiDead(ACTION_CLEAR1, -1);
+ m_blupiRestart = TRUE;
+ m_blupiAir = TRUE;
+ m_blupiPos.y = m_blupiPos.y / DIMOBJY * DIMOBJY + BLUPIOFFY;
+ PlaySound(SOUND_FALL, m_blupiPos);
+ }
+ if (IsEcraseur(m_blupiPos) && !m_blupiEcrase && !m_blupiShield && !m_blupiHide && !m_bSuperBlupi && m_blupiFocus)
+ {
+ StopBlupi();
+ m_blupiVitesse.x = 0;
+ m_blupiVitesse.y = 0;
+ m_blupiEcrase = TRUE;
+ m_blupiBalloon = FALSE;
+ m_blupiAir = FALSE;
+ m_blupiHelico = FALSE;
+ m_blupiOver = FALSE;
+ m_blupiJeep = FALSE;
+ m_blupiTank = FALSE;
+ m_blupiSkate = FALSE;
+ m_blupiNage = FALSE;
+ m_blupiSurf = FALSE;
+ m_blupiSuspend = FALSE;
+ m_blupiJumpAie = FALSE;
+ m_blupiShield = FALSE;
+ m_blupiPower = FALSE;
+ m_blupiCloud = FALSE;
+ m_blupiHide = FALSE;
+ m_blupiTimeShield = 100;
+ m_blupiPosMagic = m_blupiPos;
+ m_jauges[JAUGE_POWER].SetHide(FALSE);
+ if (!m_blupiJeep && !m_blupiTank)
+ {
+ StopVehicleSound();
+ }
+ PlaySound(SOUND_ECRASE, m_blupiPos);
+ ObjectStart(m_blupiPos, TYPE_INVERTSTART, -60);
+ ObjectStart(m_blupiPos, TYPE_INVERTSTART, 60);
+ ObjectStart(m_blupiPos, TYPE_INVERTSTART, 10);
+ ObjectStart(m_blupiPos, TYPE_INVERTSTART, -10);
+ tinyPoint.x = m_blupiPos.x - 34;
+ tinyPoint.y = m_blupiPos.y - 34;
+ ObjectStart(tinyPoint, TYPE_EXPLO5, 0);
+ m_decorAction = 2;
+ m_decorPhase = 0;
+ }
+ if (IsTeleporte(m_blupiPos) != -1 && !m_blupiHelico && !m_blupiOver && !m_blupiBalloon && !m_blupiEcrase && !m_blupiJeep && !m_blupiTank && !m_blupiSkate && !m_blupiAir && m_blupiFocus && m_blupiPosHelico.x == -1)
+ {
+ m_blupiAction = ACTION_TELEPORTE;
+ m_blupiPhase = 0;
+ m_blupiVitesse.x = 0;
+ m_blupiVitesse.y = 0;
+ m_blupiFocus = FALSE;
+ m_blupiPos.x = m_blupiPos.x / DIMOBJX * DIMOBJX;
+ PlaySound(SOUND_TELEPORTE, m_blupiPos);
+ tinyPoint.x = m_blupiPos.x;
+ tinyPoint.y = m_blupiPos.y - 5;
+ ObjectStart(tinyPoint, TYPE_EXPLO7, 0);
+ }
+ if (IsBridge(m_blupiPos, &tinyPoint2) && m_blupiFocus)
+ {
+ tinyPoint2.x *= DIMOBJX;
+ tinyPoint2.y *= DIMOBJY;
+ ObjectStart(tinyPoint2, TYPE_BRIDGE, 0);
+ }
+ int num2 = IsDoor(m_blupiPos, &tinyPoint2);
+ if (num2 != -1 && (m_blupiCle & (1 << num2) - 334) != 0)
+ {
+ OpenDoor(tinyPoint2);
+ m_blupiCle &= ~((1 << num2) - 334);
+ tinyPoint.x = 520;
+ tinyPoint.y = 418;
+ tinyPoint5.x = tinyPoint2.x * 64 - m_posDecor.x;
+ tinyPoint5.y = tinyPoint2.y * 64 - m_posDecor.y;
+ VoyageInit(tinyPoint, tinyPoint5, 214 + (num2 - 334) * 7, 10);
+ }
+ }
+ if (!m_blupiHelico && !m_blupiSuspend && !m_blupiOver && !m_blupiBalloon && !m_blupiEcrase && !m_blupiSkate && !m_blupiJeep && !m_blupiTank && !m_blupiJeep && m_blupiFocus)
+ {
+ num = MockeryDetect(m_blupiPos);
+ if (num != 0)
+ {
+ m_blupiActionOuf = num;
+ m_blupiTimeOuf = 0;
+ }
+ }
+ MoveObjectFollow(m_blupiPos);
+ num = num27;
+ if (num != -1 && !bNear && m_moveObject[num].type == TYPE_BOMBEDOWN && !m_blupiHelico && !m_blupiOver && !m_blupiBalloon && !m_blupiEcrase && !m_blupiJeep && !m_blupiTank && !m_blupiSkate && !m_blupiNage && !m_blupiSurf && !m_blupiSuspend && !m_blupiShield && !m_bSuperBlupi && m_blupiFocus)
+ {
+ m_blupiActionOuf = 48;
+ m_blupiTimeOuf = 0;
+ }
+ if (num != -1 && bNear)
+ {
+ if (m_moveObject[num].type == TYPE_HELICO &&
+ !IsBlupiVehicle() &&
+ !m_blupiBalloon &&
+ !m_blupiEcrase &&
+ !m_blupiNage &&
+ !m_blupiSurf &&
+ !m_blupiSuspend &&
+ m_blupiFocus)
+ {
+ ObjectDelete(m_moveObject[num].posCurrent, m_moveObject[num].type);
+ m_scrollAdd.x = 0;
+ m_scrollAdd.y = 0;
+ m_blupiAir = FALSE;
+ m_blupiHelico = TRUE;
+ m_blupiVitesse.x = 0;
+ if (m_blupiCloud || m_blupiHide)
+ {
+ m_blupiCloud = FALSE;
+ m_blupiHide = FALSE;
+ m_jauges[JAUGE_POWER].SetHide(TRUE);
+ }
+ }
+ if (m_moveObject[num].type == TYPE_OVER &&
+ !IsBlupiVehicle() &&
+ !m_blupiBalloon &&
+ !m_blupiEcrase &&
+ !m_blupiNage &&
+ !m_blupiSurf &&
+ !m_blupiSuspend &&
+ m_blupiFocus)
+ {
+ ObjectDelete(m_moveObject[num].posCurrent, m_moveObject[num].type);
+ m_scrollAdd.x = 0;
+ m_scrollAdd.y = 0;
+ m_blupiAir = FALSE;
+ m_blupiOver = TRUE;
+ m_blupiVitesse.x = 0;
+ if (m_blupiCloud || m_blupiHide)
+ {
+ m_blupiCloud = FALSE;
+ m_blupiHide = FALSE;
+ m_jauges[JAUGE_POWER].SetHide(TRUE);
+ }
+ }
+ if (m_moveObject[num].type == TYPE_JEEP &&
+ !IsBlupiVehicle() &&
+ !m_blupiBalloon &&
+ !m_blupiEcrase &&
+ !m_blupiNage &&
+ !m_blupiSurf &&
+ !m_blupiSuspend &&
+ m_blupiFocus)
+ {
+ ObjectDelete(m_moveObject[num].posCurrent, m_moveObject[num].type);
+ m_scrollAdd.x = 0;
+ m_scrollAdd.y = 0;
+ StopBlupi();
+ m_blupiAir = FALSE;
+ m_blupiJeep = TRUE;
+ m_blupiVitesse.x = 0;
+ if (m_blupiCloud || m_blupiHide)
+ {
+ m_blupiCloud = FALSE;
+ m_blupiHide = FALSE;
+ m_jauges[JAUGE_POWER].SetHide(TRUE);
+ }
+ }
+ if ( m_moveObject[num].type == TYPE_TANK &&
+ !IsBlupiVehicle() &&
+ !m_blupiBalloon &&
+ !m_blupiEcrase &&
+ !m_blupiNage &&
+ !m_blupiSurf &&
+ !m_blupiSuspend &&
+ m_blupiFocus)
+ {
+
+ ObjectDelete(m_moveObject[num].posCurrent, m_moveObject[num].type);
+ m_scrollAdd.x = 0;
+ m_scrollAdd.y = 0;
+ StopBlupi();
+ m_blupiAir = FALSE;
+ m_blupiTank = TRUE;
+ m_blupiVitesse.x = 0;
+ if (m_blupiCloud || m_blupiHide)
+ {
+ m_blupiCloud = FALSE;
+ m_blupiHide = FALSE;
+ m_jauges[JAUGE_POWER].SetHide(TRUE);
+ }
+ }
+ if (m_moveObject[num].type == TYPE_BULLET && m_blupiFocus && m_blupiBullet < 10)
+ {
+ ObjectDelete(m_moveObject[num].posCurrent, m_moveObject[num].type);
+ tinyPoint.x = m_moveObject[num].posCurrent.x - m_posDecor.x;
+ tinyPoint.y = m_moveObject[num].posCurrent.y - m_posDecor.y;
+ tinyPoint5.x = 570;
+ tinyPoint5.y = 430;
+ VoyageInit(tinyPoint, tinyPoint5, 177, 10);
+ m_blupiBullet += 10;
+ if (m_blupiBullet > 10)
+ {
+ m_blupiBullet = 10;
+ }
+ }
+ if ( m_moveObject[num].type == TYPE_SKATE &&
+ !IsBlupiVehicle() &&
+ !m_blupiBalloon &&
+ !m_blupiEcrase &&
+ !m_blupiNage &&
+ !m_blupiSurf &&
+ !m_blupiSuspend &&
+ m_blupiFocus)
+ {
+ m_scrollAdd.x = 0;
+ m_scrollAdd.y = 0;
+ m_blupiAction = ACTION_TAKESKATE;
+ m_blupiPhase = 0;
+ m_blupiPos.y = m_moveObject[num].posCurrent.y / DIMOBJY * DIMOBJY + BLUPIOFFY;
+ m_blupiFocus = FALSE;
+ m_blupiAir = FALSE;
+ m_blupiSkate = TRUE;
+ m_blupiVitesse.x = 0;
+ if (m_blupiCloud || m_blupiHide)
+ {
+ m_blupiCloud = FALSE;
+ m_blupiHide = FALSE;
+ m_jauges[JAUGE_POWER].SetHide(TRUE);
+ }
+ }
+ if ((m_moveObject[num].type == TYPE_BOMBEUP ||
+ m_moveObject[num].type == TYPE_BOMBEMOVE ||
+ m_moveObject[num].type == TYPE_BOMBEFOLLOW1 ||
+ m_moveObject[num].type == TYPE_BOMBEFOLLOW2) &&
+ m_blupiBalloon &&
+ m_blupiPosHelico.x == -1)
+ {
+ m_blupiBalloon = FALSE;
+ m_blupiAir = TRUE;
+ m_blupiTimeShield = 0;
+ m_jauges[JAUGE_POWER].SetHide(TRUE);
+ m_decorAction = 0;
+ tinyPoint.x = m_blupiPos.x - 34;
+ tinyPoint.y = m_blupiPos.y - 34;
+ ObjectStart(tinyPoint, TYPE_EXPLO6, 0);
+ PlaySound(SOUND_RESSORT, m_blupiPos);
+ m_blupiPos.y = m_blupiPos.y + 4;
+ m_blupiVitesse.y = 0;
+ m_blupiPosHelico = m_blupiPos;
+ }
+ else if ((m_moveObject[num].type == TYPE_BOMBEDOWN ||
+ m_moveObject[num].type == TYPE_BOMBEUP ||
+ m_moveObject[num].type == TYPE_BOMBEFOLLOW1 ||
+ m_moveObject[num].type == TYPE_BOMBEFOLLOW2 ||
+ m_moveObject[num].type == TYPE_BOMBEMOVE ||
+ m_moveObject[num].type == TYPE_BULLDOZER ||
+ m_moveObject[num].type == TYPE_POISSON ||
+ m_moveObject[num].type == TYPE_OISEAU) &&
+ !m_blupiShield &&
+ !m_bSuperBlupi &&
+ m_blupiPosHelico.x == -1)
+ {
+ if (!m_blupiJeep &&
+ !m_blupiTank &&
+ !m_blupiSkate &&
+ (m_blupiFocus || m_blupiAction == ACTION_AIR || m_blupiAction == ACTION_JUMPAIE))
+ {
+ if (m_blupiHelico || m_blupiOver || m_blupiBalloon || m_blupiEcrase)
+ {
+ m_blupiAir = TRUE;
+ }
+ BlupiDead(ACTION_CLEAR1, ACTION_CLEAR2);
+ }
+ if (m_moveObject[num].type == TYPE_POISSON || m_moveObject[num].type == TYPE_OISEAU)
+ {
+ tinyPoint = m_moveObject[num].posCurrent;
+ ObjectDelete(tinyPoint, m_moveObject[num].type);
+ tinyPoint.x -= 34;
+ tinyPoint.y -= 34;
+ ObjectStart(tinyPoint, TYPE_EXPLO3, 0);
+ m_decorAction = 2;
+ m_decorPhase = 0;
+ }
+ else
+ {
+ tinyPoint = m_moveObject[num].posCurrent;
+ ObjectDelete(tinyPoint, m_moveObject[num].type);
+ tinyPoint.x -= 34;
+ tinyPoint.y -= 34;
+ ObjectStart(tinyPoint, TYPE_EXPLO1, 0);
+ m_decorAction = 1;
+ m_decorPhase = 0;
+ }
+ if (!m_blupiJeep && !m_blupiTank)
+ {
+ StopVehicleSound();
+ }
+ PlaySound(SOUND_BOUM, m_moveObject[num].posCurrent);
+ }
+ if (m_moveObject[num].type == TYPE_GUEPE &&
+ m_blupiFocus &&
+ !m_blupiBalloon &&
+ !m_blupiShield &&
+ !m_bSuperBlupi)
+ {
+ StopBlupi();
+ m_blupiVitesse.x = 0;
+ m_blupiVitesse.y = 0;
+ m_blupiBalloon = TRUE;
+ m_blupiEcrase = FALSE;
+ m_blupiAir = FALSE;
+ m_blupiHelico = FALSE;
+ m_blupiOver = FALSE;
+ m_blupiJeep = FALSE;
+ m_blupiTank = FALSE;
+ m_blupiSkate = FALSE;
+ m_blupiNage = FALSE;
+ m_blupiSurf = FALSE;
+ m_blupiSuspend = FALSE;
+ m_blupiJumpAie = FALSE;
+ m_blupiShield = FALSE;
+ m_blupiPower = FALSE;
+ m_blupiCloud = FALSE;
+ m_blupiHide = FALSE;
+ m_blupiTimeShield = 100;
+ m_blupiPosMagic = m_blupiPos;
+ m_jauges[JAUGE_POWER].SetHide(FALSE);
+ if (!m_blupiJeep && !m_blupiTank)
+ {
+ StopVehicleSound();
+ }
+ PlaySound(SOUND_JUMPAIE, m_moveObject[num].posCurrent);
+ tinyPoint.x = m_blupiPos.x - 34;
+ tinyPoint.y = m_blupiPos.y - 34;
+ ObjectStart(tinyPoint, TYPE_EXPLO5, 0);
+ m_decorAction = 5;
+ m_decorPhase = 0;
+ }
+ if (m_moveObject[num].type == TYPE_CREATURE &&
+ m_moveObject[num].step != STEP_ADVANCE &&
+ m_moveObject[num].step != STEP_RECEDE &&
+ m_blupiFocus &&
+ !m_blupiBalloon &&
+ !m_blupiShield &&
+ !m_bSuperBlupi)
+ {
+
+ tinyPoint.x = m_blupiPos.x;
+ tinyPoint.y = (m_blupiPos.y + DIMOBJY - 10) / DIMOBJY * DIMOBJY + 4;
+ ObjectStart(tinyPoint, TYPE_TENTACULE, 0);
+ m_blupiAction = ACTION_GLU;
+ m_blupiPhase = 0;
+ m_blupiSuspend = FALSE;
+ m_blupiJumpAie = FALSE;
+ m_blupiFocus = FALSE;
+ m_blupiRestart = TRUE;
+ if (bAirStart)
+ {
+ m_blupiAir = TRUE;
+ }
+ if (IsBlupiVehicle() ||
+ m_blupiBalloon ||
+ m_blupiEcrase)
+ {
+ m_blupiHelico = FALSE;
+ m_blupiOver = FALSE;
+ m_blupiBalloon = FALSE;
+ m_blupiEcrase = FALSE;
+ m_blupiJeep = FALSE;
+ m_blupiTank = FALSE;
+ m_blupiSkate = FALSE;
+ tinyPoint = m_moveObject[num].posCurrent;
+ tinyPoint.x -= 34;
+ tinyPoint.y -= 34;
+ ObjectStart(tinyPoint, TYPE_EXPLO3, 0);
+ StopVehicleSound();
+ PlaySound(SOUND_BOUM, m_moveObject[num].posCurrent);
+ m_decorAction = 1;
+ m_decorPhase = 0;
+ }
+ else
+ {
+ PlaySound(SOUND_GLU, m_moveObject[num].posCurrent);
+ }
+ m_blupiCloud = FALSE;
+ m_blupiHide = FALSE;
+ m_jauges[JAUGE_POWER].SetHide(TRUE);
+ }
+ if (m_moveObject[num].type == TYPE_BALLE &&
+ !m_blupiShield &&
+ !m_bSuperBlupi &&
+ m_blupiAction != ACTION_WIN &&
+ m_blupiAction != ACTION_BYE &&
+ !IsDeadAction(m_blupiAction) &&
+ m_blupiAction != ACTION_GLU &&
+ m_blupiAction != ACTION_ELECTRO &&
+ m_blupiAction != ACTION_HIDE)
+ {
+
+ tinyPoint = m_moveObject[num].posCurrent;
+ ObjectDelete(tinyPoint, m_moveObject[num].type);
+ m_blupiAction = ACTION_GLU;
+ m_blupiPhase = 0;
+ m_blupiSuspend = FALSE;
+ m_blupiJumpAie = FALSE;
+ m_blupiFocus = FALSE;
+ m_blupiRestart = TRUE;
+ if (bAirStart)
+ {
+ m_blupiAir = TRUE;
+ }
+ if (IsBlupiVehicle() ||
+ m_blupiBalloon ||
+ m_blupiEcrase)
+ {
+ m_blupiHelico = FALSE;
+ m_blupiOver = FALSE;
+ m_blupiBalloon = FALSE;
+ m_blupiEcrase = FALSE;
+ m_blupiJeep = FALSE;
+ m_blupiTank = FALSE;
+ m_blupiSkate = FALSE;
+ }
+ StartSploutchGlu(m_moveObject[num].posCurrent);
+ m_blupiCloud = FALSE;
+ m_blupiHide = FALSE;
+ m_jauges[JAUGE_POWER].SetHide(TRUE);
+ }
+ if (m_moveObject[num].type == TYPE_TRESOR)
+ {
+ ObjectDelete(m_moveObject[num].posCurrent, m_moveObject[num].type);
+ tinyPoint.x = m_moveObject[num].posCurrent.x - m_posDecor.x;
+ tinyPoint.y = m_moveObject[num].posCurrent.y - m_posDecor.y;
+ POINT end;
+ end.x = 430;
+ end.y = 430;
+ VoyageInit(tinyPoint, end, 6, CHELEMENT);
+ ObjectStart(m_moveObject[num].posCurrent, TYPE_TRESORTRACK, -60);
+ ObjectStart(m_moveObject[num].posCurrent, TYPE_TRESORTRACK, 60);
+ ObjectStart(m_moveObject[num].posCurrent, TYPE_TRESORTRACK, 10);
+ ObjectStart(m_moveObject[num].posCurrent, TYPE_TRESORTRACK, -10);
+ }
+ if (m_moveObject[num].type == TYPE_CLE1 &&
+ (m_voyageIcon != 215 || m_voyageChannel != CHELEMENT) &&
+ !(m_blupiCle & CLE_RED))
+ {
+ ObjectDelete(m_moveObject[num].posCurrent, m_moveObject[num].type);
+ tinyPoint.x = m_moveObject[num].posCurrent.x - m_posDecor.x;
+ tinyPoint.y = m_moveObject[num].posCurrent.y - m_posDecor.y;
+ POINT end2;
+ end2.x = 520;
+ end2.y = 418;
+ VoyageInit(tinyPoint, end2, 215, CHELEMENT);
+ ObjectStart(m_moveObject[num].posCurrent, TYPE_TRESORTRACK, -60);
+ ObjectStart(m_moveObject[num].posCurrent, TYPE_TRESORTRACK, 60);
+ ObjectStart(m_moveObject[num].posCurrent, TYPE_TRESORTRACK, 10);
+ ObjectStart(m_moveObject[num].posCurrent, TYPE_TRESORTRACK, -10);
+ }
+ if (m_moveObject[num].type == TYPE_CLE2 &&
+ (m_voyageIcon != 222 || m_voyageChannel != CHELEMENT) &&
+ !(m_blupiCle & CLE_GREEN))
+ {
+ ObjectDelete(m_moveObject[num].posCurrent, m_moveObject[num].type);
+ tinyPoint.x = m_moveObject[num].posCurrent.x - m_posDecor.x;
+ tinyPoint.y = m_moveObject[num].posCurrent.y - m_posDecor.y;
+ POINT end3;
+ end3.x = 530;
+ end3.y = 418;
+ VoyageInit(tinyPoint, end3, 222, CHELEMENT);
+ ObjectStart(m_moveObject[num].posCurrent, TYPE_TRESORTRACK, -60);
+ ObjectStart(m_moveObject[num].posCurrent, TYPE_TRESORTRACK, 60);
+ ObjectStart(m_moveObject[num].posCurrent, TYPE_TRESORTRACK, 10);
+ ObjectStart(m_moveObject[num].posCurrent, TYPE_TRESORTRACK, -10);
+ }
+ if (m_moveObject[num].type == TYPE_CLE3 &&
+ (m_voyageIcon != 229 || m_voyageChannel != CHELEMENT) &&
+ !(m_blupiCle & CLE_BLUE))
+ {
+ ObjectDelete(m_moveObject[num].posCurrent, m_moveObject[num].type);
+ tinyPoint.x = m_moveObject[num].posCurrent.x - m_posDecor.x;
+ tinyPoint.y = m_moveObject[num].posCurrent.y - m_posDecor.y;
+ POINT end4;
+ end4.x = 540;
+ end4.y = 418;
+ VoyageInit(tinyPoint, end4, 229, CHELEMENT);
+ ObjectStart(m_moveObject[num].posCurrent, TYPE_TRESORTRACK, -60);
+ ObjectStart(m_moveObject[num].posCurrent, TYPE_TRESORTRACK, 60);
+ ObjectStart(m_moveObject[num].posCurrent, TYPE_TRESORTRACK, 10);
+ ObjectStart(m_moveObject[num].posCurrent, TYPE_TRESORTRACK, -10);
+ }
+ if (m_moveObject[num].type == TYPE_EGG && m_nbVies < 10 && m_blupiFocus)
+ {
+ ObjectDelete(m_moveObject[num].posCurrent, m_moveObject[num].type);
+ tinyPoint.x = m_moveObject[num].posCurrent.x - m_posDecor.x;
+ tinyPoint.y = m_moveObject[num].posCurrent.y - m_posDecor.y;
+ VoyageInit(tinyPoint, VoyageGetPosVie(m_nbVies + 1), 21, CHELEMENT);
+ }
+ if (m_moveObject[num].type == TYPE_SHIELD && !m_blupiShield && !m_blupiHide && !m_blupiPower && m_blupiFocus)
+ {
+ PlaySound(SOUND_STARTSHIELD, m_moveObject[num].posCurrent);
+ m_blupiShield = TRUE;
+ m_blupiPower = FALSE;
+ m_blupiCloud = FALSE;
+ m_blupiHide = FALSE;
+ m_blupiTimeShield = 100;
+ m_blupiPosMagic = m_blupiPos;
+ m_jauges[JAUGE_POWER].SetHide(FALSE);
+ }
+ if ( m_moveObject[num].type == TYPE_POWER &&
+ !m_blupiShield &&
+ !IsBlupiVehicle() &&
+ !m_blupiBalloon &&
+ !m_blupiEcrase &&
+ m_blupiFocus)
+ {
+ ObjectDelete(m_moveObject[num].posCurrent, m_moveObject[num].type);
+ m_blupiAction = ACTION_SUCETTE;
+ m_blupiPhase = 0;
+ m_blupiCloud = FALSE;
+ m_blupiHide = FALSE;
+ m_blupiFocus = FALSE;
+ PlaySound(SOUND_SUCETTE, end);
+ }
+ if (m_moveObject[num].type == TYPE_INVERT && !m_blupiHide && m_blupiFocus)
+ {
+ ObjectDelete(m_moveObject[num].posCurrent, m_moveObject[num].type);
+ m_blupiInvert = TRUE;
+ m_blupiTimeShield = 100;
+ m_blupiPosMagic = m_blupiPos;
+ m_jauges[JAUGE_POWER].SetHide(FALSE);
+ PlaySound(SOUND_INVERTSTART, end);
+ ObjectStart(m_blupiPos, TYPE_INVERTSTART, -60);
+ ObjectStart(m_blupiPos, TYPE_INVERTSTART, 60);
+ ObjectStart(m_blupiPos, TYPE_INVERTSTART, 10);
+ ObjectStart(m_blupiPos, TYPE_INVERTSTART, -10);
+ }
+ if ( m_moveObject[num].type == TYPE_DRINK &&
+ !m_blupiShield &&
+ !m_blupiCloud &&
+ !IsBlupiVehicle() &&
+ !m_blupiBalloon &&
+ !m_blupiEcrase &&
+ m_blupiFocus)
+ {
+ ObjectDelete(m_moveObject[num].posCurrent, m_moveObject[num].type);
+ m_blupiAction = ACTION_DRINK;
+ m_blupiPhase = 0;
+ m_blupiShield = FALSE;
+ m_blupiPower = FALSE;
+ m_blupiJumpAie = FALSE;
+ m_blupiFocus = FALSE;
+ PlaySound(SOUND_DRINK, end);
+ }
+ if (m_moveObject[num].type == TYPE_CHARGE &&
+ !m_blupiShield &&
+ !m_blupiHide &&
+ !m_blupiPower &&
+ !m_blupiCloud &&
+ !IsBlupiVehicle() &&
+ !m_blupiBalloon &&
+ !m_blupiEcrase &&
+ m_blupiFocus)
+ {
+ m_blupiAction = ACTION_CHARGE;
+ m_blupiPhase = 0;
+ m_blupiShield = FALSE;
+ m_blupiPower = FALSE;
+ m_blupiJumpAie = FALSE;
+ m_blupiFocus = FALSE;
+ m_blupiCloud = TRUE;
+ m_blupiTimeShield = 100;
+ PlaySound(SOUND_CHARGE, end);
+ if (m_blupiHide)
+ {
+ m_blupiHide = FALSE;
+ m_jauges[JAUGE_POWER].SetHide(TRUE);
+ }
+ }
+ if (m_moveObject[num].type >= TYPE_BOMBEPERSO1 &&
+ m_moveObject[num].type <= TYPE_BOMBEPERSO4 &&
+ m_blupiFocus)
+ {
+ if (m_moveObject[num].type == TYPE_BOMBEPERSO1)
+ {
+ if (m_blupiPerso < 5 )
+ {
+
+ ObjectDelete(m_moveObject[num].posCurrent, m_moveObject[num].type);
+ tinyPoint.x = m_moveObject[num].posCurrent.x - m_posDecor.x;
+ tinyPoint.y = m_moveObject[num].posCurrent.y - m_posDecor.y;
+ tinyPoint5.x = 0;
+ tinyPoint5.y = 438;
+ VoyageInit(tinyPoint, tinyPoint5, 108, CHBUTTON);
+ }
+ }
+ else if (!m_blupiShield && !m_bSuperBlupi)
+ {
+ ObjectDelete(m_moveObject[num].posCurrent, m_moveObject[num].type);
+ BlupiDead(ACTION_CLEAR1, ACTION_CLEAR2);
+ tinyPoint = m_moveObject[num].posCurrent;
+ tinyPoint.x -= 34;
+ tinyPoint.y -= 34;
+ ObjectStart(tinyPoint, TYPE_EXPLO3, 0);
+ PlaySound(SOUND_BOUM, m_moveObject[num].posCurrent);
+ m_decorAction = 1;
+ m_decorPhase = 0;
+ }
+ }
+ if (m_moveObject[num].type == TYPE_DYNAMITE &&
+ m_blupiFocus &&
+ m_blupiDynamite == 0 &&
+ (m_voyageIcon != 252 || m_voyageChannel != CHELEMENT) )
+ {
+
+ ObjectDelete(m_moveObject[num].posCurrent, m_moveObject[num].type);
+ tinyPoint.x = m_moveObject[num].posCurrent.x - m_posDecor.x;
+ tinyPoint.y = m_moveObject[num].posCurrent.y - m_posDecor.y;
+ tinyPoint5.x = 505;
+ tinyPoint5.y = 414;
+ VoyageInit(tinyPoint, tinyPoint5, 252, CHELEMENT);
+ m_blupiAction = ACTION_TAKEDYNAMITE;
+ m_blupiPhase = 0;
+ m_blupiFocus = FALSE;
+ }
+ if (m_moveObject[num].type == 12 &&
+ !IsBlupiVehicle() &&
+ !m_blupiBalloon &&
+ !m_blupiEcrase &&
+ !m_blupiNage &&
+ !m_blupiSurf &&
+ !m_blupiSuspend &&
+ m_blupiFocus &&
+ m_blupiAction == ACTION_MARCH)
+ {
+ end = m_moveObject[num].posCurrent;
+ if (m_blupiDir == DIR_LEFT && m_blupiPos.x > end.x)
+ {
+ end.x = m_blupiPos.x - 59;
+ PlaySound(SOUND_PUSH, end);
+ m_blupiActionOuf = ACTION_OUF1b;
+ m_blupiTimeOuf = 0;
+ m_blupiAction = ACTION_PUSH;
+ m_blupiPhase = 0;
+ }
+ if (m_blupiDir == DIR_RIGHT && m_blupiPos.x < end.x)
+ {
+ end.x = m_blupiPos.x + 55;
+ PlaySound(SOUND_PUSH, end);
+ m_blupiActionOuf = ACTION_OUF1b;
+ m_blupiTimeOuf = 0;
+ m_blupiAction = ACTION_PUSH;
+ m_blupiPhase = 0;
+ }
+ if (!TestPushCaisse(num, end, FALSE))
+ {
+ m_blupiPos.x = blupiPos.x;
+ }
+ }
+ if ((m_moveObject[num].type == TYPE_GOAL || m_moveObject[num].type == TYPE_CLE) && m_blupiFocus)
+ {
+ if (m_goalPhase == 0)
+ {
+ if (m_nbTresor >= m_totalTresor)
+ {
+ if (m_moveObject[num].type == TYPE_CLE)
+ {
+ m_bFoundCle = TRUE;
+ }
+ StopVehicleSound();
+ PlaySound(SOUND_ENDOK, m_moveObject[num].posCurrent);
+ m_blupiAction = ACTION_WIN;
+ m_blupiPhase = 0;
+ m_blupiFocus = FALSE;
+ m_blupiFront = TRUE;
+ m_blupiPos.y = m_moveObject[num].posCurrent.y;
+ }
+ else
+ {
+ PlaySound(SOUND_ENDKO, m_moveObject[num].posCurrent);
+ }
+ m_goalPhase = 50;
+ }
+ else
+ {
+ m_goalPhase--;
+ }
+ }
+ else
+ {
+ m_goalPhase = 0;
+ }
+ }
+ else
+ {
+ m_goalPhase = 0;
+ }
+ if (m_blupiAction == ACTION_PUSH && m_blupiFocus)
+ {
+ num = CaisseInFront();
+ if (num != -1)
+ {
+ end = m_moveObject[num].posCurrent;
+ if (m_blupiDir == DIR_LEFT)
+ {
+ end.x = m_blupiPos.x - 59;
+ }
+ else
+ {
+ end.x = m_blupiPos.x + 55;
+ }
+ if (!TestPushCaisse(num, end, FALSE))
+ {
+ m_blupiPos.x = blupiPos.x;
+ }
+ }
+ else
+ {
+ StopBlupi();
+ }
+ }
+ if (m_blupiAction == ACTION_POP && m_blupiFocus)
+ {
+ num = CaisseInFront();
+ if (num != -1)
+ {
+ end = m_moveObject[num].posCurrent;
+ if (m_blupiDir == DIR_LEFT)
+ {
+ end.x = m_blupiPos.x - 59;
+ }
+ else
+ {
+ end.x = m_blupiPos.x + 55;
+ }
+ if (!TestPushCaisse(num, end, TRUE))
+ {
+ StopBlupi();
+ }
+ }
+ else
+ {
+ StopBlupi();
+ }
+ }
+ if (!IsBlupiVehicle() &&
+ !m_blupiBalloon &&
+ !m_blupiEcrase &&
+ !m_blupiNage &&
+ !m_blupiSurf &&
+ m_blupiFocus)
+ {
+ if (m_blupiActionOuf == ACTION_OUF1a && m_blupiAction == ACTION_STOP)
+ {
+ if (m_blupiTimeOuf > 50)
+ {
+ m_blupiAction = m_blupiActionOuf;
+ m_blupiPhase = 0;
+ PlaySound(SOUND_OUF1, m_blupiPos);
+ }
+ m_blupiActionOuf = 0;
+ }
+ if (m_blupiActionOuf == ACTION_OUF1b && m_blupiAction == ACTION_STOP)
+ {
+ if (m_blupiTimeOuf > 50)
+ {
+ m_blupiAction = m_blupiActionOuf;
+ m_blupiPhase = 0;
+ }
+ m_blupiActionOuf = 0;
+ }
+ if (m_blupiAction == ACTION_OUF1b && m_blupiPhase == ACTION_JUMP)
+ {
+ PlaySound(SOUND_OUF1, m_blupiPos);
+ }
+ if (m_blupiActionOuf == ACTION_OUF5 && m_blupiAction == ACTION_STOP)
+ {
+ if (m_blupiTimeOuf > 10 && m_blupiTimeOuf < 50)
+ {
+ m_blupiAction = m_blupiActionOuf;
+ m_blupiPhase = 0;
+ }
+ m_blupiActionOuf = 0;
+ }
+ if (m_blupiActionOuf == ACTION_OUF3 && m_blupiAction == ACTION_STOP)
+ {
+ if (m_blupiTimeOuf > 60)
+ {
+ m_blupiAction = m_blupiActionOuf;
+ m_blupiPhase = 0;
+ PlaySound(SOUND_OUF3, m_blupiPos);
+ }
+ m_blupiActionOuf = 0;
+ }
+ if (m_blupiActionOuf == ACTION_OUF4 && m_blupiAction == ACTION_STOP)
+ {
+ if (m_blupiTimeOuf < 10)
+ {
+ m_blupiAction = m_blupiActionOuf;
+ m_blupiPhase = 0;
+ PlaySound(SOUND_OUF4, m_blupiPos);
+ }
+ m_blupiActionOuf = 0;
+ }
+ if ((m_blupiActionOuf == ACTION_MOCKERY ||
+ m_blupiActionOuf == ACTION_MOCKERYi ||
+ m_blupiActionOuf == ACTION_MOCKERYp)
+ && m_blupiAction == ACTION_STOP)
+ {
+ if (m_blupiTimeOuf < 20)
+ {
+ m_blupiAction = m_blupiActionOuf;
+ m_blupiPhase = 0;
+ }
+ m_blupiActionOuf = 0;
+ }
+ }
+ if (m_blupiAction == ACTION_MARCH &&
+ m_blupiActionOuf != ACTION_MOCKERY &&
+ m_blupiActionOuf != ACTION_MOCKERYi &&
+ m_blupiActionOuf != ACTION_MOCKERYp &&
+ !m_blupiSurf &&
+ !m_blupiNage)
+ {
+ m_blupiActionOuf = 0;
+ }
+ if (m_blupiActionOuf != 0)
+ {
+ m_blupiTimeOuf++;
+ }
+ if (m_blupiTimeMockery > 0)
+ {
+ m_blupiTimeMockery--;
+ }
+ if (m_blupiAction == ACTION_TAKEDYNAMITE && m_blupiPhase == 18)
+ {
+ StopBlupi(TRUE);
+ }
+ if (m_blupiAction == ACTION_PUTDYNAMITE && m_blupiPhase == 26)
+ {
+ StopBlupi(TRUE);
+ }
+ if (m_blupiPos.x - 30 > m_blupiPosHelico.x || m_blupiPos.x + 30 < m_blupiPosHelico.x || m_blupiPos.y - 30 > m_blupiPosHelico.y || m_blupiPos.y + 30 < m_blupiPosHelico.y)
+ {
+ m_blupiPosHelico.x = -1;
+ }
+ if (m_blupiTimeFire > 0)
+ {
+ m_blupiTimeFire--;
+ }
+ if (m_blupiAction == ACTION_TELEPORTE && m_blupiPhase == 128)
+ {
+ POINT blupiPos2;
+ if (SearchTeleporte(m_blupiPos, &blupiPos2))
+ {
+ m_blupiPos = blupiPos2;
+ ObjectStart(m_blupiPos, TYPE_MAGICTRACK, 20);
+ ObjectStart(m_blupiPos, TYPE_MAGICTRACK, -20);
+ }
+ m_blupiFocus = TRUE;
+ m_blupiPosHelico = m_blupiPos;
+ }
+ if (m_blupiAction == ACTION_SWITCH && m_blupiPhase == 10)
+ {
+ StopBlupi(TRUE);
+ }
+ //// winphone ?
+ //if (m_keyPress & KEY_FIRE && m_blupiAction == ACTION_STOP)
+ //{
+ // m_blupiAction = ACTION_NON;
+ // m_blupiPhase = 0;
+ // PlaySound(SOUND_ERROR, m_blupiPos);
+ //}
+ if ((m_blupiAction == ACTION_CLEAR1 && m_blupiPhase == 70) ||
+ (m_blupiAction == ACTION_CLEAR2 && m_blupiPhase == 100) ||
+ (m_blupiAction == ACTION_CLEAR3 && m_blupiPhase == 70) ||
+ (m_blupiAction == ACTION_CLEAR4 && m_blupiPhase == 110) ||
+ (m_blupiAction == ACTION_CLEAR5 && m_blupiPhase == 90) ||
+ (m_blupiAction == ACTION_CLEAR6 && m_blupiPhase == 90) ||
+ (m_blupiAction == ACTION_CLEAR7 && m_blupiPhase == 90) ||
+ (m_blupiAction == ACTION_CLEAR8 && m_blupiPhase == 90) ||
+ (m_blupiAction == ACTION_DROWN && m_blupiPhase == 90) ||
+ (m_blupiAction == ACTION_GLU && m_blupiPhase == 100) ||
+ (m_blupiAction == ACTION_ELECTRO && m_blupiPhase == 90))
+ {
+ if (m_nbVies > 0)
+ {
+ m_blupiAction = ACTION_HIDE;
+ m_blupiIcon = -1;
+ m_blupiPhase = 0;
+ if (m_blupiRestart || m_bMulti)
+ {
+ m_blupiPos = m_blupiValidPos;
+ }
+ POINT posDecor = GetPosDecor(m_blupiPos);
+ tinyPoint.x = m_blupiPos.x - posDecor.x - 30;
+ tinyPoint.y = m_blupiPos.y - posDecor.y;
+ VoyageInit(VoyageGetPosVie(m_nbVies), tinyPoint, 48, GetBlupiChannelActual());
+ NetSendBarePacket(PK_DIE, m_nbVies);
+ }
+ else
+ {
+ m_nbVies = -1;
+ m_term = -1;
+ DoorsLost();
+ NetSendBarePacket(PK_LOST, 0);
+ }
+ m_blupiFront = FALSE;
+ }
+ if (m_bMulti && m_blupiAction != ACTION_WIN)
+ {
+ int num = 0;
+ for (int i = 0; i < MAXNETPLAYER; i++)
+ {
+ if (m_pNetwork->m_players[i].bIsPresent) num++;
+ }
+ if (num < 2)
+ {
+ char str[100];
+ StopVehicleSound();
+ PlaySound(14, m_blupiPos, FALSE);
+ m_blupiAction = ACTION_WIN;
+ m_blupiPhase = 0;
+ m_blupiFocus = FALSE;
+ m_blupiFront = TRUE;
+ m_blupiAir = FALSE;
+ m_blupiHelico = FALSE;
+ m_blupiOver = FALSE;
+ m_blupiJeep = FALSE;
+ m_blupiTank = FALSE;
+ m_blupiSkate = FALSE;
+ m_blupiNage = FALSE;
+ m_blupiSurf = FALSE;
+ m_blupiVent = FALSE;
+ m_blupiSuspend = FALSE;
+ m_blupiShield = FALSE;
+ m_blupiPower = FALSE;
+ m_blupiCloud = FALSE;
+ m_blupiHide = FALSE;
+ m_blupiInvert = FALSE;
+ m_blupiBalloon = FALSE;
+ m_blupiEcrase = FALSE;
+ LoadString(287, str, 100);
+ NotifPush(str);
+ }
+ }
+ if (m_dimDecor.y == 0)
+ {
+ num3 = LYIMAGE;
+ }
+ else
+ {
+ num3 = DIMOBJY * MAXCELY;
+ }
+ if (m_blupiPos.y >= num3 + 1 && m_blupiPos.y <= num3 + 40)
+ {
+ PlaySound(SOUND_FALL, m_blupiPos);
+ }
+ if (m_blupiPos.y > num3 + 1000)
+ {
+ m_term = -1;
+ DoorsLost();
+ }
+ if (m_blupiAction == ACTION_WIN && m_blupiPhase == 70)
+ {
+ if (m_bPrivate)
+ {
+ m_term = 1;
+ }
+ else if (m_mission == 1)
+ {
+ m_term = 199;
+ }
+ else if (m_mission == 199)
+ {
+ m_term = -2;
+ }
+ else if (m_bFoundCle)
+ {
+ OpenGoldsWin();
+ m_term = 1;
+ }
+ else
+ {
+ OpenDoorsWin();
+ m_term = m_mission / 10 * 10;
+ }
+ }
+ if (m_blupiAction == ACTION_BYE && m_blupiPhase == 50)
+ {
+ num = IsWorld(m_blupiPos);
+ if (num != -1)
+ {
+ if (m_mission == 1)
+ {
+ m_term = num * 10;
+ }
+ else if (num == 199)
+ {
+ m_term = 1;
+ }
+ else
+ {
+ m_term = m_mission / 10 * 10 + num;
+ }
+ }
+ }
+ if (lastBlupiAction == ACTION_MOCKERY && m_blupiAction != ACTION_MOCKERY)
+ {
+ StopSound(SOUND_MOCKERY);
+ NetStopSound(SOUND_MOCKERY);
+ }
+ if (lastBlupiAction == ACTION_MOCKERYi && m_blupiAction != ACTION_MOCKERYi)
+ {
+ StopSound(SOUND_MOCKERY);
+ NetStopSound(SOUND_MOCKERY);
+ }
+ if (lastBlupiAction == ACTION_MOCKERYp && m_blupiAction != ACTION_MOCKERYp)
+ {
+ StopSound(SOUND_OUF2);
+ NetStopSound(SOUND_OUF2);
+ }
+ if (m_blupiFocus &&
+ !m_blupiAir &&
+ (!m_blupiHelico || BlupiIsGround()) &&
+ (!m_blupiOver || BlupiIsGround()) &&
+ !m_blupiBalloon &&
+ !m_blupiEcrase &&
+ !m_blupiShield &&
+ !m_blupiHide &&
+ !bIsOpen &&
+ !bIsOpen2 &&
+ m_blupiTransport == -1 &&
+ !IsLave(m_blupiPos) &&
+ !IsPiege(m_blupiPos) &&
+ !IsGoutte(m_blupiPos, TRUE) &&
+ !IsScie(m_blupiPos) &&
+ !IsBridge(m_blupiPos, &tinyPoint) &&
+ IsTeleporte(m_blupiPos) == -1 &&
+ !IsBlitz(m_blupiPos, TRUE) &&
+ !IsTemp(m_blupiPos) &&
+ !IsBalleTraj(m_blupiPos) &&
+ !IsMoveTraj(m_blupiPos))
+ {
+ if (m_blupiFifoNb > 0)
+ {
+ m_blupiValidPos = m_blupiFifoPos[0];
+ }
+ BlupiAddFifo(m_blupiPos);
+ }
+ end.x = m_blupiPos.x + DIMBLUPIX / 2 + m_scrollAdd.x;
+ end.y = m_blupiPos.y + DIMBLUPIY / 2 + m_scrollAdd.y;
+ int num28 = abs(m_scrollPoint.x - end.x);
+ int num29 = abs(m_scrollPoint.y - end.y);
+ num4 = SCROLL_SPEED;
+ if (num28 > SCROLL_MARGX * 2)
+ {
+ num4 += (num28 - SCROLL_MARGX * 2) / 4;
+ }
+ if (num29 > SCROLL_MARGY * 2)
+ {
+ num4 += (num29 - SCROLL_MARGY * 2) / 4;
+ }
+ if (m_scrollPoint.x < end.x)
+ {
+ m_scrollPoint.x = m_scrollPoint.x + num4;
+ if (m_scrollPoint.x >= end.x)
+ {
+ m_scrollPoint.x = end.x;
+ }
+ }
+ if (m_scrollPoint.x > end.x)
+ {
+ m_scrollPoint.x = m_scrollPoint.x - num4;
+ if (m_scrollPoint.x <= end.x)
+ {
+ m_scrollPoint.x = end.x;
+ }
+ }
+ if (m_scrollPoint.y < end.y)
+ {
+ m_scrollPoint.y = m_scrollPoint.y + num4;
+ if (m_scrollPoint.y >= end.y)
+ {
+ m_scrollPoint.y = end.y;
+ }
+ }
+ if (m_scrollPoint.y > end.y)
+ {
+ m_scrollPoint.y = m_scrollPoint.y - num4;
+ if (m_scrollPoint.y <= end.y)
+ {
+ m_scrollPoint.y = end.y;
+ }
+ }
+ if ((m_phase == WM_PHASE_PLAY || m_phase == WM_PHASE_PLAYTEST) &&
+ m_blupiAction != ACTION_CLEAR2 &&
+ m_blupiAction != ACTION_CLEAR3)
+ {
+ m_posDecor = GetPosDecor(m_scrollPoint);
+ }
+ if (m_time % 4 == 0)
+ {
+ AdaptMotorVehicleSound(m_blupiPos);
+ }
+ VoyageStep();
+
+ m_lastKeyPress = m_keyPress;
+
+ // DEBUG v
+ sprintf(m_notifText[0], "time %d", m_time);
+ m_notifTime = 200;
+ // DEBUG ^
+}
+
+
+
+void CDecor::BlupiDead(int action1, int action2)
+{
+ if (action2 == -1)
+ {
+ m_blupiAction = action1;
+ }
+ else
+ {
+ m_blupiAction = ((rand() % 2 == 0) ? action1 : action2);
+ }
+ m_blupiPhase = 0;
+ m_blupiFocus = FALSE;
+ m_blupiHelico = FALSE;
+ m_blupiOver = FALSE;
+ m_blupiJeep = FALSE;
+ m_blupiTank = FALSE;
+ m_blupiSkate = FALSE;
+ m_blupiNage = FALSE;
+ m_blupiSurf = FALSE;
+ m_blupiVent = FALSE;
+ m_blupiSuspend = FALSE;
+ m_blupiJumpAie = FALSE;
+ m_blupiShield = FALSE;
+ m_blupiPower = FALSE;
+ m_blupiCloud = FALSE;
+ m_blupiHide = FALSE;
+ m_blupiInvert = FALSE;
+ m_blupiBalloon = FALSE;
+ m_blupiEcrase = FALSE;
+ m_blupiRestart = FALSE;
+ m_blupiActionOuf = 0;
+ m_jauges[JAUGE_AIR].SetHide(TRUE);
+ m_jauges[JAUGE_POWER].SetHide(TRUE);
+ StopSound(SOUND_HELICOHIGH);
+ StopSound(SOUND_HELICOLOW);
+ StopSound(SOUND_JEEPHIGH);
+ StopSound(SOUND_JEEPLOW);
+
+ POINT pos;
+ POINT pos2;
+ if (m_blupiAction == ACTION_CLEAR2)
+ {
+ pos.x = m_blupiPos.x - m_posDecor.x;
+ pos.y = m_blupiPos.y - m_posDecor.y;
+ pos2.x = m_blupiPos.x - m_posDecor.x;
+ pos2.y = m_blupiPos.y - m_posDecor.y - 300;
+ VoyageInit(pos, pos2, 230, CHELEMENT);
+ PlaySound(SOUND_ANGEL, m_blupiPos);
+ }
+ if (m_blupiAction == ACTION_CLEAR3)
+ {
+ pos.x = m_blupiPos.x - m_posDecor.x;
+ pos.y = m_blupiPos.y - m_posDecor.y;
+ pos2.x = m_blupiPos.x - m_posDecor.x;
+ pos2.y = m_blupiPos.y - m_posDecor.y - 2000;
+ VoyageInit(pos, pos2, 40, CHELEMENT);
+ PlaySound(SOUND_ANGEL, m_blupiPos);
+ }
+ if (m_blupiAction == ACTION_CLEAR4)
+ {
+ ObjectStart(m_blupiPos, TYPE_INVERTSTART, -70);
+ ObjectStart(m_blupiPos, TYPE_INVERTSTART, 20);
+ ObjectStart(m_blupiPos, TYPE_INVERTSTART, -20);
+ PlaySound(SOUND_SCIE, m_blupiPos);
+ }
+}
+
+POINT CDecor::GetPosDecor(POINT pos)
+{
+ POINT result;
+
+ if (this->m_dimDecor.x)
+ {
+ result.x = pos.x - LXIMAGE / 2;
+ if (result.x < 0) result.x = 0;
+ if (result.x > MAXCELX * DIMOBJX - LXIMAGE) result.x = MAXCELX * DIMOBJX - LXIMAGE;
+ }
+ else result.x = 0;
+
+ if (this->m_dimDecor.y)
+ {
+ result.y = pos.y - LYIMAGE / 2;
+ if (result.y < 0) result.y = 0;
+ if (result.y > MAXCELY * DIMOBJY - LYIMAGE) result.y = MAXCELY * DIMOBJY - LYIMAGE;
+ }
+ else result.y = 0;
+
+ return result;
+}
+
+void CDecor::BlupiAddFifo(POINT pos)
+{
+ if (m_blupiFifoNb < 10)
+ {
+ if (m_blupiFifoNb > 0 && pos.x == m_blupiFifoPos[m_blupiFifoNb - 1].x && pos.y == m_blupiFifoPos[m_blupiFifoNb - 1].y)
+ {
+ return;
+ }
+ m_blupiFifoPos[m_blupiFifoNb] = pos;
+ m_blupiFifoNb++;
+ return;
+ }
+ else
+ {
+ if (pos.x == m_blupiFifoPos[9].x && pos.y == m_blupiFifoPos[9].y)
+ {
+ return;
+ }
+ for (int i = 0; i < 9; i++)
+ {
+ m_blupiFifoPos[i] = m_blupiFifoPos[i + 1];
+ }
+ m_blupiFifoPos[9] = pos;
+ return;
+ }
+}
+
+BOOL CDecor::DecorDetect(RECT rect, BOOL bCaisse)
+{
+ m_detectIcon = -1;
+ if (rect.left < 0 || rect.top < 0)
+ {
+ return TRUE;
+ }
+ int num;
+ if (m_dimDecor.x == 0)
+ {
+ num = 640;
+ }
+ else
+ {
+ num = 6400;
+ }
+ if (rect.right > num)
+ {
+ return TRUE;
+ }
+ if (m_blupiHelico ||
+ m_blupiOver ||
+ m_blupiBalloon ||
+ m_blupiEcrase ||
+ m_blupiNage ||
+ m_blupiSurf)
+ {
+ if (m_dimDecor.y == 0)
+ {
+ num = 480;
+ }
+ else
+ {
+ num = 6400;
+ }
+ if (rect.bottom > num)
+ {
+ return TRUE;
+ }
+ }
+ int num2 = rect.left / 16;
+ int num3 = (rect.right + 16 - 1) / 16;
+ int num4 = rect.top / 16;
+ int num5 = (rect.bottom + 16 - 1) / 16;
+ RECT src;
+ for (int i = num4; i <= num5; i++)
+ {
+ for (int j = num2; j <= num3; j++)
+ {
+ int num6 = j / 4;
+ int num7 = i / 4;
+ if (num6 >= 0 && num6 < 100 && num7 >= 0 && num7 < 100)
+ {
+ int icon = m_decor[num6][num7].icon;
+ if (icon >= 0 && icon < MAXQUART && (!m_blupiHelico || icon != 214) && (m_blupiOver || icon != 214) && (icon != 324 || m_time / 4 % 20 < 18))
+ {
+ num6 = j % 4;
+ num7 = i % 4;
+ if (table_decor_quart[icon * 16 + num7 * 4 + num6] != 0)
+ {
+ src.left = j * 16;
+ src.right = src.left + 16;
+ src.top = i * 16;
+ src.bottom = src.top + 16;
+ RECT tinyRect;
+ if (IntersectRect(&tinyRect, &src, &rect))
+ {
+ m_detectIcon = icon;
+ return TRUE;
+ }
+ }
+
+ }
+ }
+ }
+ }
+ if (!bCaisse)
+ {
+ return FALSE;
+ }
+ for (int k = 0; k < m_nbRankCaisse; k++)
+ {
+ int num8 = m_rankCaisse[k];
+ src.left = m_moveObject[num8].posCurrent.x;
+ src.right = m_moveObject[num8].posCurrent.x + 64;
+ src.top = m_moveObject[num8].posCurrent.y;
+ src.bottom = m_moveObject[num8].posCurrent.y + 64;
+ RECT tinyRect;
+ if (IntersectRect(&tinyRect, &src, &rect))
+ {
+ m_detectIcon = m_moveObject[num8].icon;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+BOOL CDecor::TestPath(RECT rect, POINT start, POINT *end)
+{
+ int num = abs(end->x - start.x);
+ int num2 = abs(end->y - start.y);
+
+ POINT tinyPoint = start;
+ if (num > num2)
+ {
+ RECT rect2;
+ if (end->x > start.x)
+ {
+ for (int i = 0; i <= num; i++)
+ {
+ int j = i * (end->y - start.y) / num;
+ rect2.left = rect.left + i;
+ rect2.right = rect.right + i;
+ rect2.top = rect.top + j;
+ rect2.bottom = rect.bottom + j;
+ if (DecorDetect(rect2))
+ {
+ *end = tinyPoint;
+ return FALSE;
+ }
+ tinyPoint.x = start.x + i;
+ tinyPoint.y = start.y + j;
+ }
+ }
+ if (end->x < start.x)
+ {
+ for (int i = 0; i >= -num; i--)
+ {
+ int j = i * (start.y - end->y) / num;
+ rect2.left = rect.left + i;
+ rect2.right = rect.right + i;
+ rect2.top = rect.top + j;
+ rect2.bottom = rect.bottom + j;
+ if (DecorDetect(rect2))
+ {
+ *end = tinyPoint;
+ return FALSE;
+ }
+ tinyPoint.x = start.x + i;
+ tinyPoint.y = start.y + j;
+ }
+ }
+ }
+ else
+ {
+ RECT rect2;
+ if (end->y > start.y)
+ {
+ for (int j = 0; j <= num2; j++)
+ {
+ int i = j * (end->x - start.x) / num2;
+ rect2.left = rect.left + i;
+ rect2.right = rect.right + i;
+ rect2.top = rect.top + j;
+ rect2.bottom = rect.bottom + j;
+ if (DecorDetect(rect2))
+ {
+ *end = tinyPoint;
+ return FALSE;
+ }
+ tinyPoint.x = start.x + i;
+ tinyPoint.y = start.y + j;
+ }
+ }
+ if (end->y < start.y)
+ {
+ for (int j = 0; j >= -num2; j--)
+ {
+ int i = j * (start.x - end->x) / num2;
+ rect2.left = rect.left + i;
+ rect2.right = rect.right + i;
+ rect2.top = rect.top + j;
+ rect2.bottom = rect.bottom + j;
+ if (DecorDetect(rect2))
+ {
+ *end = tinyPoint;
+ return FALSE;
+ }
+ tinyPoint.x = start.x + i;
+ tinyPoint.y = start.y + j;
+ }
+ }
+ }
+ return TRUE;
+}
\ No newline at end of file
diff --git a/src/decdesign.cpp b/src/decdesign.cpp
new file mode 100644
index 0000000..52395f1
--- /dev/null
+++ b/src/decdesign.cpp
@@ -0,0 +1,659 @@
+// DecDesign.cpp
+//
+
+#include "def.h"
+#include "decor.h"
+#include "misc.h"
+#include "dectables.h"
+
+POINT CDecor::ScreenPosToCelPos(POINT pos)
+{
+ if (pos.x >= 0 && pos.x < LXIMAGE && pos.y >= 0 && pos.y < LYIMAGE) {
+ return POINT(
+ (m_posDecor.x + m_dimCelHili.x * -32 + 32 + pos.x) / DIMOBJX,
+ (m_posDecor.y + m_dimCelHili.y * -32 + 32 + pos.y) / DIMOBJY
+ );
+ }
+ else return POINT( -1, -1 );
+}
+
+void CDecor::SetCelPosFromScreenPos(POINT pos)
+{
+ m_posCelHili = ScreenPosToCelPos(pos);
+}
+
+void CDecor::SetFieldCC38AndStuff(int _foo, int _bar)
+{
+ m_dimCelHili = POINT( 1, 1 );
+ if (_foo == 2 && _bar != 3 && _bar != 9 && _bar != 10) m_dimCelHili = POINT( 2, 2 );
+ if (_foo == 3) m_iconLift = _bar;
+ if (_foo == 4) m_iconLift = _bar + 20;
+ if (_foo == 5) m_iconLift = _bar + 40;
+ m_2ndPositionCalculationSlot = -1;
+}
+
+void CDecor::DeleteCel(POINT cel)
+{
+ m_2ndPositionCalculationSlot = -1;
+
+ if (!IsValidCel(cel)) return;
+
+ m_decor[cel.x][cel.y].icon = -1;
+ AdaptBorder(cel);
+ m_bigDecor[cel.x][cel.y].icon = -1;
+ MoveObjectDelete(cel);
+}
+
+void CDecor::PlaceMenuItem(short *pCel, int *pTable, int lastIndex, BYTE flags, int currentIcon, BOOL bRand)
+{
+ if (bRand) {
+ *pCel = pTable[rand() % (pTable[0] + 1)];
+ }
+ else if (!(flags & 8)) {
+ if (flags & 1) {
+ lastIndex++;
+ if (*pCel == pTable[lastIndex] && currentIcon != 0 && pTable[0] <= lastIndex) {
+ lastIndex = 0;
+ }
+ *pCel = pTable[lastIndex + 1];
+ }
+ }
+ else {
+ *pCel = pTable[lastIndex + 1];
+ }
+}
+
+void CDecor::PlaceItemFromMenu1(POINT cel, int index, BYTE flags, int currentIcon)
+{
+ m_2ndPositionCalculationSlot = -1;
+
+ short *pIcon = &m_decor[cel.x][cel.y].icon;
+ short *pIconBig = &m_bigDecor[cel.x][cel.y].icon;
+
+ if (!IsValidCel(cel)) return;
+
+ switch (index) {
+ case 0: // Tree
+ PlaceMenuItem(pIconBig, table_366b0, m_lastDecorIndexes[0], flags, *pIconBig, TRUE);
+ break;
+ case 1: // Palmtree
+ PlaceMenuItem(pIconBig, table_366c0, m_lastDecorIndexes[1], flags, *pIconBig, TRUE);
+ break;
+ case 2: // Decorative plant
+ PlaceMenuItem(pIconBig, table_366d8, m_lastDecorIndexes[2], flags, *pIconBig, TRUE);
+ break;
+ case 3: // Marine plant
+ *pIcon = Object::Marine_1;
+ break;
+ case 4: // House
+ PlaceMenuItem(pIconBig, table_366e8, m_lastDecorIndexes[3], flags, *pIconBig, TRUE);
+ break;
+ case 5: // Mechanical background
+ PlaceMenuItem(pIconBig, table_366f8, m_lastDecorIndexes[4], flags, *pIconBig, TRUE);
+ break;
+ case 6: // Kid's stuff background
+ PlaceMenuItem(pIconBig, table_36710, m_lastDecorIndexes[5], flags, *pIconBig, TRUE);
+ break;
+ case 7: // Green slime 2
+ PlaceMenuItem(pIconBig, table_36748, m_lastDecorIndexes[6], flags, *pIconBig, TRUE);
+ break;
+ case 8: // Element for Palace
+ PlaceMenuItem(pIconBig, table_36520, m_lastDecorIndexes[7], flags, *pIconBig, TRUE);
+ break;
+ case 9: // Support
+ PlaceMenuItem(pIcon, table_36670, m_lastDecorIndexes[8], flags, *pIcon, TRUE);
+ break;
+ case 10: // Spider's web
+ PlaceMenuItem(pIcon, table_366a0, m_lastDecorIndexes[9], flags, *pIcon, TRUE);
+ break;
+ }
+}
+
+void CDecor::PlaceItemFromMenu2(POINT cel, int index, BYTE flags, int currentIcon)
+{
+ m_2ndPositionCalculationSlot = -1;
+
+ short *pIcon = &m_decor[cel.x][cel.y].icon;
+
+ if (!IsValidCel(cel)) return;
+
+ m_iconLift = index;
+
+ switch (index) {
+ case 0: // Square tech-blocks
+ PlaceMenuItem(pIcon, table_36418, m_lastDecorIndexes[10], flags, *pIcon, TRUE);
+ break;
+ case 1: // Special tech-blocks
+ PlaceMenuItem(pIcon, table_36458, m_lastDecorIndexes[11], flags, *pIcon, TRUE);
+ break;
+ case 2: // Triangular tech-blocks
+ PlaceMenuItem(pIcon, table_36488, m_lastDecorIndexes[12], flags, *pIcon, FALSE);
+ break;
+ case 3: // Secret tech-block
+ PlaceMenuItem(pIcon, table_364a0, m_lastDecorIndexes[13], flags, *pIcon, FALSE);
+ break;
+ case 4: // Mechanical square
+ PlaceMenuItem(pIcon, table_364b0, m_lastDecorIndexes[14], flags, *pIcon, TRUE);
+ break;
+ case 5: // Special mechanical
+ PlaceMenuItem(pIcon, table_364d0, m_lastDecorIndexes[15], flags, *pIcon, FALSE);
+ break;
+ case 6: // Secret mechanical
+ PlaceMenuItem(pIcon, table_364e8, m_lastDecorIndexes[16], flags, *pIcon, FALSE);
+ break;
+ case 7: // Pipes
+ *pIcon = Object::Pipes_1;
+ break;
+ }
+ AdaptBorder(cel);
+}
+
+void CDecor::PlaceItemFromMenu3(POINT cel, int index, BYTE flags, int currentIcon)
+{
+ m_2ndPositionCalculationSlot = -1;
+
+ short *pIcon = &m_decor[cel.x][cel.y].icon;
+
+ if (!IsValidCel(cel)) return;
+
+ m_iconLift = index + 20;
+
+ switch (index) {
+ case 0: // Square rock
+ PlaceMenuItem(pIcon, table_36530, m_lastDecorIndexes[20], flags, *pIcon, FALSE);
+ break;
+ case 1: // Triangular rock
+ PlaceMenuItem(pIcon, table_36538, m_lastDecorIndexes[21], flags, *pIcon, FALSE);
+ break;
+ case 2: // Secret rock
+ PlaceMenuItem(pIcon, table_36548, m_lastDecorIndexes[22], flags, *pIcon, FALSE);
+ break;
+ case 3: // Cave
+ // todo
+ break;
+ case 4: // Secret cave
+ *pIcon = Object::CaveSecret;
+ break;
+ case 5: // Cheese
+ *pIcon = Random(Object::CheeseSquare_1, Object::CheeseSquare_4);
+ break;
+ case 6: // Secret cheese
+ *pIcon = Object::CheeseSecret;
+ break;
+ case 7: // Green slime 2
+ *pIcon = Object::Slime_1;
+ break;
+ case 8: // Grass
+ PlaceMenuItem(pIcon, table_365d0, m_lastDecorIndexes[23], flags, *pIcon, FALSE);
+ break;
+ case 9: // Water
+ PlaceMenuItem(pIcon, table_36630, m_lastDecorIndexes[24], flags, *pIcon, FALSE);
+ break;
+ }
+ AdaptBorder(cel);
+}
+
+void CDecor::PlaceItemFromMenu4(POINT cel, int index, BYTE flags, int currentIcon)
+{
+ m_2ndPositionCalculationSlot = -1;
+
+ short *pIcon = &m_decor[cel.x][cel.y].icon;
+
+ if (!IsValidCel(cel)) return;
+
+ m_iconLift = index + 40;
+
+ switch (index) {
+ case 0: // Palace
+ break;
+ case 1: // Element for Palace
+ break;
+ case 2: // Building facade
+ break;
+ case 3: // Roof
+ break;
+ case 4: // Bricks
+ break;
+ case 5: // Furniture
+ break;
+ case 6: // Wooden wall
+ break;
+ case 7: // Kid's stuff square
+ break;
+ case 8: // Special Kid's stuff
+ break;
+ case 9: // Invisible block
+ break;
+ }
+ AdaptBorder(cel);
+}
+
+void CDecor::PlaceItemFromMenu5(POINT cel, int index, BYTE flags, int currentIcon)
+{
+ m_2ndPositionCalculationSlot = -1;
+
+ int mobId;
+ MoveObject* pMob;
+
+ short *pIcon = &m_decor[cel.x][cel.y].icon;
+
+ if (!IsValidCel(cel)) return;
+
+ switch (index) {
+ case 0: // Bomb
+ MoveObjectDelete(cel);
+ mobId = MoveObjectFree();
+ if (mobId == -1) return;
+ pMob = &m_moveObject[mobId];
+ pMob->type = TYPE_BOMBEDOWN;
+ pMob->stepAdvance = 1;
+ pMob->stepRecede = 1;
+ pMob->timeStopStart = 0;
+ pMob->timeStopEnd = 0;
+ pMob->posStart = POINT( cel.x * DIMOBJX + 2, cel.y * DIMOBJY + 4 );
+ pMob->posEnd = pMob->posStart;
+ pMob->posCurrent = pMob->posStart;
+ pMob->step = STEP_STOPSTART;
+ pMob->time = 0;
+ pMob->phase = 0;
+ pMob->channel = CHELEMENT;
+ pMob->icon = 0x0c;
+ break;
+ case 1: // Hanging bomb
+ MoveObjectDelete(cel);
+ mobId = MoveObjectFree();
+ if (mobId == -1) return;
+ pMob = &m_moveObject[mobId];
+ pMob->type = TYPE_BOMBEUP;
+ pMob->stepAdvance = 1;
+ pMob->stepRecede = 1;
+ pMob->timeStopStart = 0;
+ pMob->timeStopEnd = 0;
+ pMob->posStart = POINT( cel.x * DIMOBJX + 2, cel.y * DIMOBJY );
+ pMob->posEnd = pMob->posStart;
+ pMob->posCurrent = pMob->posStart;
+ pMob->step = STEP_STOPSTART;
+ pMob->time = 0;
+ pMob->phase = 0;
+ pMob->channel = CHELEMENT;
+ pMob->icon = 0x30;
+ break;
+ case 2: // Homing bomb
+ MoveObjectDelete(cel);
+ mobId = MoveObjectFree();
+ if (mobId == -1) return;
+ pMob = &m_moveObject[mobId];
+ pMob->type = TYPE_BOMBEFOLLOW1;
+ pMob->stepAdvance = 1;
+ pMob->stepRecede = 1;
+ pMob->timeStopStart = 0;
+ pMob->timeStopEnd = 0;
+ pMob->posStart = POINT( cel.x * DIMOBJX, cel.y * DIMOBJY );
+ pMob->posEnd = pMob->posStart;
+ pMob->posCurrent = pMob->posStart;
+ pMob->step = STEP_STOPSTART;
+ pMob->time = 0;
+ pMob->phase = 0;
+ pMob->channel = CHELEMENT;
+ pMob->icon = 0x100;
+ break;
+ case 3: // Lava
+ PlaceMenuItem(pIcon, table_decor_lave, m_lastDecorIndexes[40], flags, *pIcon, FALSE);
+ break;
+ case 4: // Fan
+ PlaceMenuItem(pIcon, table_decor_ventillog, m_lastDecorIndexes[41], flags, *pIcon, FALSE);
+ break;
+ case 5: // Wind
+ PlaceMenuItem(pIcon, table_decor_ventg, m_lastDecorIndexes[42], flags, *pIcon, FALSE);
+ break;
+ case 6: // Slime trap (floor)
+ *pIcon = Object::SlimeTrapFloor_1;
+ break;
+ case 7: // Slime trap (ceiling)
+ *pIcon = Object::SlimeTrapCeiling_1;
+ break;
+ case 8: // Circular saw
+ PlaceMenuItem(pIcon, table_decor_scie, m_lastDecorIndexes[43], flags, *pIcon, FALSE);
+ break;
+ case 9: // Inverter
+ MoveObjectDelete(cel);
+ mobId = MoveObjectFree();
+ if (mobId == -1) return;
+ pMob = &m_moveObject[mobId];
+ pMob->type = TYPE_INVERT;
+ pMob->stepAdvance = 1;
+ pMob->stepRecede = 1;
+ pMob->timeStopStart = 0;
+ pMob->timeStopEnd = 0;
+ pMob->posStart = POINT( cel.x * DIMOBJX + 2, cel.y * DIMOBJY + 8 );
+ pMob->posEnd = pMob->posStart;
+ pMob->posCurrent = pMob->posStart;
+ pMob->step = STEP_STOPSTART;
+ pMob->time = 0;
+ pMob->phase = 0;
+ pMob->channel = CHELEMENT;
+ pMob->icon = 0xBB;
+ break;
+ case 10: // Lightning
+ *pIcon = Object::LightningMachine;
+ break;
+ case 11: // Crusher
+ *pIcon = Object::Crusher_1;
+ break;
+ }
+ AdaptBorder(cel);
+}
+
+void CDecor::PlaceItemFromMenu6(POINT cel, int index, BYTE flags, int currentIcon)
+{
+ m_2ndPositionCalculationSlot = -1;
+
+ short *pIcon = &m_decor[cel.x][cel.y].icon;
+
+ if (!IsValidCel(cel) || currentIcon == 0) return;
+
+ switch (m_iconLift) {
+
+ }
+
+ switch (index) {
+ case 0: // Slow lift
+ case 1: // Normal lift
+ case 2: // Fast lift
+ case 3: // Fast/Slow lift
+ case 4: // Lift with conveyor belt
+ case 5: // Bulldozer
+ case 6: // Fish
+ case 7: // Bird
+ case 8: // Wasp
+ case 9: // Slime creature
+ case 10: // Moving bomb
+ case 11: // Heliported ennemy
+ case 12: // Motorized ennemy
+ break;
+ }
+}
+
+void CDecor::PlaceItemFromMenu7(POINT cel, int index, BYTE flags, int currentIcon)
+{
+ m_2ndPositionCalculationSlot = -1;
+
+ MoveObject* pMob;
+ int mobId;
+
+ short *pIcon = &m_decor[cel.x][cel.y].icon;
+
+ if (!IsValidCel(cel)) return;
+
+ switch (index) {
+ case 0: // Chest
+ MoveObjectDelete(cel);
+ mobId = MoveObjectFree();
+ if (mobId == -1) return;
+ pMob = &m_moveObject[mobId];
+ pMob->type = TYPE_TRESOR;
+ pMob->stepAdvance = 1;
+ pMob->stepRecede = 1;
+ pMob->timeStopStart = 0;
+ pMob->timeStopEnd = 0;
+ pMob->posStart = POINT( cel.x * DIMOBJX + 2, cel.y * DIMOBJY + 4 );
+ pMob->posEnd = pMob->posStart;
+ pMob->posCurrent = pMob->posStart;
+ pMob->step = STEP_STOPSTART;
+ pMob->time = 0;
+ pMob->phase = 0;
+ pMob->channel = CHELEMENT;
+ pMob->icon = 0x00;
+ break;
+ case 1: // Egg
+ MoveObjectDelete(cel);
+ mobId = MoveObjectFree();
+ if (mobId == -1) return;
+ pMob = &m_moveObject[mobId];
+ pMob->type = TYPE_EGG;
+ pMob->stepAdvance = 1;
+ pMob->stepRecede = 1;
+ pMob->timeStopStart = 0;
+ pMob->timeStopEnd = 0;
+ pMob->posStart = POINT( cel.x * DIMOBJX + 2, cel.y * DIMOBJY + 8 );
+ pMob->posEnd = pMob->posStart;
+ pMob->posCurrent = pMob->posStart;
+ pMob->step = STEP_STOPSTART;
+ pMob->time = 0;
+ pMob->phase = 0;
+ pMob->channel = CHELEMENT;
+ pMob->icon = 0x15;
+ break;
+ case 2: // Lollipop
+ MoveObjectDelete(cel);
+ mobId = MoveObjectFree();
+ if (mobId == -1) return;
+ pMob = &m_moveObject[mobId];
+ pMob->type = TYPE_POWER;
+ pMob->stepAdvance = 1;
+ pMob->stepRecede = 1;
+ pMob->timeStopStart = 0;
+ pMob->timeStopEnd = 0;
+ pMob->posStart = POINT( cel.x * DIMOBJX + 2, cel.y * DIMOBJY + 8 );
+ pMob->posEnd = pMob->posStart;
+ pMob->posCurrent = pMob->posStart;
+ pMob->step = STEP_STOPSTART;
+ pMob->time = 0;
+ pMob->phase = 0;
+ pMob->channel = CHELEMENT;
+ pMob->icon = 0x88;
+ break;
+ case 3: // Shield
+ MoveObjectDelete(cel);
+ mobId = MoveObjectFree();
+ if (mobId == -1) return;
+ pMob = &m_moveObject[mobId];
+ pMob->type = TYPE_SHIELD;
+ pMob->stepAdvance = 1;
+ pMob->stepRecede = 1;
+ pMob->timeStopStart = 0;
+ pMob->timeStopEnd = 0;
+ pMob->posStart = POINT( cel.x * DIMOBJX + 2, cel.y * DIMOBJY + 8 );
+ pMob->posEnd = pMob->posStart;
+ pMob->posCurrent = pMob->posStart;
+ pMob->step = STEP_STOPSTART;
+ pMob->time = 0;
+ pMob->phase = 0;
+ pMob->channel = CHELEMENT;
+ pMob->icon = 0x90;
+ break;
+ case 4: // Invisibility potion
+ MoveObjectDelete(cel);
+ mobId = MoveObjectFree();
+ if (mobId == -1) return;
+ pMob = &m_moveObject[mobId];
+ pMob->type = TYPE_DRINK;
+ pMob->stepAdvance = 1;
+ pMob->stepRecede = 1;
+ pMob->timeStopStart = 0;
+ pMob->timeStopEnd = 0;
+ pMob->posStart = POINT( cel.x * DIMOBJX + 2, cel.y * DIMOBJY + 6 );
+ pMob->posEnd = pMob->posStart;
+ pMob->posCurrent = pMob->posStart;
+ pMob->step = STEP_STOPSTART;
+ pMob->time = 0;
+ pMob->phase = 0;
+ pMob->channel = CHELEMENT;
+ pMob->icon = 0xB2;
+ break;
+ case 5: // Glue supply
+ MoveObjectDelete(cel);
+ mobId = MoveObjectFree();
+ if (mobId == -1) return;
+ pMob = &m_moveObject[mobId];
+ pMob->type = TYPE_BULLET;
+ pMob->stepAdvance = 1;
+ pMob->stepRecede = 1;
+ pMob->timeStopStart = 0;
+ pMob->timeStopEnd = 0;
+ pMob->posStart = POINT( cel.x * DIMOBJX + 2, cel.y * DIMOBJY + 4 );
+ pMob->posEnd = pMob->posStart;
+ pMob->posCurrent = pMob->posStart;
+ pMob->step = STEP_STOPSTART;
+ pMob->time = 0;
+ pMob->phase = 0;
+ pMob->channel = CHELEMENT;
+ pMob->icon = 0xB1;
+ break;
+ case 6: // Recharging device
+ MoveObjectDelete(cel);
+ mobId = MoveObjectFree();
+ if (mobId == -1) return;
+ pMob = &m_moveObject[mobId];
+ pMob->type = TYPE_CHARGE;
+ pMob->stepAdvance = 1;
+ pMob->stepRecede = 1;
+ pMob->timeStopStart = 0;
+ pMob->timeStopEnd = 0;
+ pMob->posStart = POINT( cel.x * DIMOBJX + 2, cel.y * DIMOBJY + 4 );
+ pMob->posEnd = pMob->posStart;
+ pMob->posCurrent = pMob->posStart;
+ pMob->step = STEP_STOPSTART;
+ pMob->time = 0;
+ pMob->phase = 0;
+ pMob->channel = CHELEMENT;
+ pMob->icon = 0xEE;
+ break;
+ case 7: // Personal bomb
+ int type;
+ mobId = MoveObjectSearch(cel, -1);
+ if (mobId != -1 && currentIcon != 0) {
+ if (mobId >= TYPE_BOMBEPERSO4) {
+ m_lastDecorIndexes[60] = 0;
+ }
+ else {
+ m_lastDecorIndexes[60] = m_moveObject[mobId].type - TYPE_BOMBEPERSO1;
+ }
+ }
+ type = m_lastDecorIndexes[60] + TYPE_BOMBEPERSO1;
+ MoveObjectDelete(cel);
+ mobId = MoveObjectFree();
+ if (mobId == -1) return;
+ pMob = &m_moveObject[mobId];
+ pMob->type = type;
+ pMob->stepAdvance = 1;
+ pMob->stepRecede = 1;
+ pMob->timeStopStart = 0;
+ pMob->timeStopEnd = 0;
+ pMob->posStart = POINT( cel.x * DIMOBJX + 2, cel.y * DIMOBJY + 6 );
+ pMob->posEnd = pMob->posStart;
+ pMob->posCurrent = pMob->posStart;
+ pMob->step = STEP_STOPSTART;
+ pMob->time = 0;
+ pMob->phase = 0;
+ switch (type) {
+ default:
+ case TYPE_BOMBEPERSO1:
+ pMob->channel = CHBLUPI;
+ break;
+ case TYPE_BOMBEPERSO2:
+ pMob->channel = CHBLUPI1;
+ break;
+ case TYPE_BOMBEPERSO3:
+ pMob->channel = CHBLUPI2;
+ break;
+ case TYPE_BOMBEPERSO4:
+ pMob->channel = CHBLUPI3;
+ break;
+ }
+ pMob->icon = 0x101;
+ break;
+ case 8: // Dynamite
+ MoveObjectDelete(cel);
+ mobId = MoveObjectFree();
+ if (mobId == -1) return;
+ pMob = &m_moveObject[mobId];
+ pMob->type = TYPE_DYNAMITE;
+ pMob->stepAdvance = 1;
+ pMob->stepRecede = 1;
+ pMob->timeStopStart = 0;
+ pMob->timeStopEnd = 0;
+ pMob->posStart = POINT( cel.x * DIMOBJX + 2, cel.y * DIMOBJY + 6 );
+ pMob->posEnd = pMob->posStart;
+ pMob->posCurrent = pMob->posStart;
+ pMob->step = STEP_STOPSTART;
+ pMob->time = 0;
+ pMob->phase = 0;
+ pMob->channel = CHELEMENT;
+ pMob->icon = 0xFC;
+ break;
+ }
+ AdaptBorder(cel);
+}
+
+void CDecor::PlaceItemFromMenu8(POINT cel, int index, BYTE flags, int currentIcon)
+{
+ m_2ndPositionCalculationSlot = -1;
+
+ short *pIcon = &m_decor[cel.x][cel.y].icon;
+
+ if (!IsValidCel(cel)) return;
+
+ switch (index) {
+ case 0: // Key
+ case 1: // Door
+ case 2: // Closed while not all chests have been found
+ case 3: // Teleporter
+ case 4: // Bar to hang from
+ case 5: // Spring
+ case 6: // Vanishing bloc
+ case 7: // Fragile bridge
+ case 8: // Wooden case
+ case 9: // Secret wooden case
+ break;
+ }
+}
+
+void CDecor::PlaceItemFromMenu9(POINT cel, int index, BYTE flags, int currentIcon)
+{
+ m_2ndPositionCalculationSlot = -1;
+
+ short *pIcon = &m_decor[cel.x][cel.y].icon;
+
+ if (!IsValidCel(cel)) return;
+
+ switch (index) {
+ case 0: // Hovercraft
+ case 1: // Helicopter
+ case 2: // Skateboard
+ case 3: // Jeep
+ case 4: // Glue tank
+ break;
+ }
+}
+
+void CDecor::PlaceItemFromMenu10(POINT cel, int index, BYTE flags, int currentIcon)
+{
+ m_2ndPositionCalculationSlot = -1;
+
+ short *pIcon = &m_decor[cel.x][cel.y].icon;
+
+ if (!IsValidCel(cel)) return;
+
+ switch (index) {
+ case 0: // Goal
+ case 1: // Yellow Blupi
+ case 2: // Orange Blupi
+ case 3: // Blue Blupi
+ case 4: // Green Blupi
+ case 5: // Door
+ case 6: // Level start
+ case 7: // Key
+ break;
+ }
+}
+
+char* CDecor::GetMissionTitle()
+{
+ return m_missionTitle;
+}
+
+void CDecor::SetMissionTitle(char *str)
+{
+ strcpy(m_missionTitle, str);
+}
diff --git a/src/decio.cpp b/src/decio.cpp
new file mode 100644
index 0000000..d0bb59e
--- /dev/null
+++ b/src/decio.cpp
@@ -0,0 +1,388 @@
+// DecIO.cpp
+//
+
+#include "def.h"
+#include "decor.h"
+#include "misc.h"
+
+void CDecor::GetMissionPath(char* str, int user, int mission, BOOL bUser)
+{
+ if (bUser != 0)
+ {
+ sprintf(str, "data\\%.3d-%.3d.blp", user, mission);
+ AddUserPath(str);
+ return;
+ }
+ sprintf(str, "data\\world%.3d.blp", mission);
+ AddUserPath(str);
+ return;
+}
+
+BOOL CDecor::DeleteMission(int user, int mission, BOOL bUser)
+{
+ char filename[FILENAME_MAX];
+
+ GetMissionPath(filename, user, mission, bUser);
+ remove(filename);
+ return TRUE;
+}
+
+BOOL CDecor::Write(int gamer, int mission, BOOL bUser)
+{
+ char filename[FILENAME_MAX];
+ DescFile* pBuffer = NULL;
+ FILE* file;
+ int* blupiDir;
+ POINT* blupiPos;
+ int nb;
+ int i;
+
+
+ GetMissionPath(filename, gamer, mission, bUser);
+
+
+ file = fopen(filename, "wb");
+ if (file == NULL) goto error;
+
+ pBuffer = (DescFile*)malloc(sizeof(DescFile));
+ if (pBuffer == NULL) goto error;
+ memset(pBuffer, 0, sizeof(DescFile));
+
+ i = 4;
+ pBuffer->majRev = 1;
+ pBuffer->minRev = 3;
+ *pBuffer->reserve1 = 0;
+ pBuffer->posDecor = m_posDecor;
+ pBuffer->dimDecor = m_dimDecor;
+ pBuffer->music = m_music;
+ pBuffer->region = m_region;
+ blupiDir = m_blupiStartDir;
+ strcpy(pBuffer->name, m_missionTitle);
+ blupiPos = m_blupiStartPos;
+
+ for (i = 0; i < 4; i++)
+ {
+ pBuffer->blupiPos[i] = m_blupiStartPos[i];
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ pBuffer->blupiDir[i] = m_blupiStartDir[i];
+ }
+
+ nb = fwrite(pBuffer, sizeof(DescFile), 1, file);
+ if (nb < 1) goto error;
+
+ nb = fwrite(m_decor, sizeof(Cellule), MAXCELX * MAXCELY / 4, file);
+ if (nb < MAXCELX * MAXCELY / 4) goto error;
+
+ nb = fwrite(m_bigDecor, sizeof(Cellule), MAXCELX * MAXCELY / 4, file);
+ if (nb < MAXCELX * MAXCELY / 4) goto error;
+
+ nb = fwrite(m_moveObject, sizeof(MoveObject), MAXMOVEOBJECT, file);
+ if (nb < MAXMOVEOBJECT) goto error;
+
+ free(pBuffer);
+ fclose(file);
+ return TRUE;
+
+error:
+ if (pBuffer != NULL) free(pBuffer);
+ if (file != NULL) fclose(file);
+ return FALSE;
+}
+
+BOOL CDecor::Read(int gamer, int mission, BOOL bUser)
+{
+ char filename[FILENAME_MAX];
+ FILE* file;
+ DescFile* pBuffer;
+ short majRev, minRev;
+ short obj;
+ Cellule(*objects)[100];
+ POINT* startPos;
+ POINT* blupiPos;
+ int nb;
+ int i = 4;
+ int x, y;
+ int* startDir;
+ int* blupiDir;
+
+ pBuffer = 0;
+ InitDecor();
+ GetMissionPath(filename, gamer, mission, bUser);
+
+ file = fopen(filename, "rb");
+ if (file == NULL) goto error;
+
+ pBuffer = (DescFile*)malloc(sizeof(DescFile));
+ if (pBuffer == NULL) goto error;
+
+ nb = fread(pBuffer, sizeof(DescFile), 1, file);
+ if (nb < 1) goto error;
+
+ majRev = pBuffer->majRev;
+ minRev = pBuffer->minRev;
+ m_posDecor = pBuffer->posDecor;
+ m_dimDecor = pBuffer->dimDecor;
+ m_music = pBuffer->music;
+ m_region = pBuffer->region;
+ if (majRev >= 1 && minRev >= 3)
+ {
+ strcpy(m_missionTitle,pBuffer->name);
+ }
+ startDir = m_blupiStartDir;
+ blupiDir = pBuffer->blupiDir;
+ startPos = m_blupiStartPos;
+ blupiPos = pBuffer->blupiPos;
+
+ for (i = 0; i < MAXNETPLAYER; i++)
+ {
+ m_blupiStartPos[i] = pBuffer->blupiPos[i];
+ m_blupiStartDir[i] = pBuffer->blupiDir[i];
+ }
+
+ nb = fread(m_decor, sizeof(Cellule), MAXCELX * MAXCELY, file);
+ if (nb < MAXCELX * MAXCELY) goto error;
+
+#if !_DREAM
+ for (x = 0; x < MAXCELX; x++)
+ {
+ for (y = 0; y < MAXCELY; y++)
+ {
+ if (m_decor[x][y].icon >= Object::Dream_1 &&
+ m_decor[x][y].icon <= Object::Dream_20)
+ {
+ m_decor[x][y].icon = Object::KidsSquare_10;
+ }
+ }
+ }
+#endif
+
+ if (majRev == 1 && minRev >= 1)
+ {
+ nb = fread(m_bigDecor, sizeof(Cellule), MAXCELX * MAXCELY, file);
+ if (nb < MAXCELX * MAXCELY) goto error;
+ }
+
+ memset(m_moveObject, 0, sizeof(MoveObject) * MAXMOVEOBJECT);
+ if (majRev == 1 && minRev >= 2)
+ {
+ nb = fread(m_moveObject, sizeof(MoveObject), MAXMOVEOBJECT, file);
+ if (nb < MAXMOVEOBJECT) goto error;
+ }
+ else
+ {
+ nb = fread(m_moveObject, sizeof(MoveObject), MAXMOVEOBJECT / 2, file);
+ if (nb < MAXMOVEOBJECT / 2) goto error;
+ }
+
+ free(pBuffer);
+ fclose(file);
+ return TRUE;
+error:
+ if (pBuffer != NULL) free(pBuffer);
+ if (file != NULL) fclose(file);
+
+ InitDecor();
+ return FALSE;
+}
+
+BOOL CDecor::SomethingMissionPath(int gamer, int mission, BOOL bUser)
+{
+ return FALSE;
+}
+
+BOOL CDecor::CurrentWrite(int gamer, int mission, BOOL bUser)
+{
+ char filename[MAX_PATH];
+ FILE* file = NULL;
+ DescSave* pBuffer = NULL;
+ int nb, i, x, y;
+ int majRev, minRev;
+
+ sprintf(filename, "data\\s%.3d-%.3d.blp", gamer, mission);
+ AddUserPath(filename);
+
+ file = fopen(filename, "wb");
+ if (file == NULL) goto error;
+
+ pBuffer = (DescSave*)malloc(sizeof(DescSave));
+ if (pBuffer == NULL) goto error;
+
+ memset(pBuffer, 0, sizeof(DescSave));
+ pBuffer->lg = sizeof(DescSave);
+ pBuffer->majRev = 1;
+ pBuffer->minRev = 4;
+ pBuffer->reserve1[0] = 0;
+ memcpy(pBuffer->decor, m_decor, sizeof(pBuffer->decor));
+ memcpy(pBuffer->bigDecor, m_bigDecor, sizeof(pBuffer->bigDecor));
+ memcpy(pBuffer->balleTraj, m_balleTraj, sizeof(pBuffer->balleTraj));
+ memcpy(pBuffer->moveTraj, m_moveTraj, sizeof(pBuffer->moveTraj));
+ memcpy(pBuffer->moveObject, m_moveObject, sizeof(pBuffer->moveObject));
+ pBuffer->posDecor = m_posDecor;
+ pBuffer->dimDecor = m_dimDecor;
+ pBuffer->phase = m_phase;
+ pBuffer->term = m_term;
+ pBuffer->music = m_music;
+ pBuffer->region = m_region;
+ pBuffer->time = m_time;
+ memcpy(pBuffer->missionTitle, m_missionTitle, sizeof(pBuffer->missionTitle));
+ pBuffer->nbRankCaisse = m_nbRankCaisse;
+ memcpy(pBuffer->rankCaisse, m_rankCaisse, sizeof(pBuffer->rankCaisse));
+ pBuffer->nbLinkCaisse = m_nbLinkCaisse;
+ memcpy(pBuffer->linkCaisse, m_linkCaisse, sizeof(pBuffer->linkCaisse));
+ pBuffer->blupiPos = m_blupiPos;
+ pBuffer->blupiValidPos = m_blupiValidPos;
+ pBuffer->blupiAction = m_blupiAction;
+ pBuffer->blupiDir = m_blupiDir;
+ pBuffer->blupiPhase = m_blupiPhase;
+ pBuffer->blupiVitesse = m_blupiVitesse;
+ pBuffer->blupiIcon = m_blupiIcon;
+ pBuffer->blupiSec = m_blupiSec;
+ pBuffer->blupiChannel = m_blupiChannel;
+ pBuffer->blupiVector = m_blupiVector;
+ pBuffer->blupiTransport = m_blupiTransport;
+ pBuffer->blupiFocus = m_blupiFocus;
+ pBuffer->blupiAir = m_blupiAir;
+ pBuffer->blupiHelico = m_blupiHelico;
+ pBuffer->blupiOver = m_blupiOver;
+ pBuffer->blupiJeep = m_blupiJeep;
+ pBuffer->blupiTank = m_blupiTank;
+ pBuffer->blupiSkate = m_blupiSkate;
+ pBuffer->blupiNage = m_blupiNage;
+ pBuffer->blupiSurf = m_blupiSurf;
+ pBuffer->blupiVent = m_blupiVent;
+ pBuffer->blupiSuspend = m_blupiSuspend;
+ pBuffer->blupiJumpAie = m_blupiJumpAie;
+ pBuffer->blupiShield = m_blupiShield;
+ pBuffer->blupiPower = m_blupiPower;
+ pBuffer->blupiCloud = m_blupiCloud;
+ pBuffer->blupiHide = m_blupiHide;
+ pBuffer->blupiInvert = m_blupiInvert;
+ pBuffer->blupiBalloon = m_blupiBalloon;
+ pBuffer->blupiEcrase = m_blupiEcrase;
+ pBuffer->blupiPosHelico = m_blupiPosHelico;
+ pBuffer->blupiPosMagic = m_blupiPosMagic;
+ pBuffer->blupiRestart = m_blupiRestart;
+ pBuffer->blupiFront = m_blupiFront;
+ pBuffer->blupiBullet = m_blupiBullet;
+ pBuffer->blupiCle = m_blupiCle;
+ pBuffer->blupiPerso = m_blupiPerso;
+ pBuffer->blupiDynamite = m_blupiDynamite;
+ pBuffer->blupiNoBarre = m_blupiNoBarre;
+ pBuffer->blupiTimeShield = m_blupiTimeShield;
+ pBuffer->blupiTimeFire = m_blupiTimeFire;
+ pBuffer->blupiTimeNoAsc = m_blupiTimeNoAsc;
+ pBuffer->blupiTimeOuf = m_blupiTimeOuf;
+ pBuffer->blupiActionOuf = m_blupiActionOuf;
+ pBuffer->blupiFifoNb = m_blupiFifoNb;
+ memcpy(pBuffer->blupiFifoPos, m_blupiFifoPos, sizeof(pBuffer->blupiFifoPos));
+ memcpy(pBuffer->blupiStartPos, m_blupiStartPos, sizeof(pBuffer->blupiStartPos));
+ pBuffer->blupiStartDir[0] = m_blupiStartDir[0];
+ pBuffer->blupiStartDir[1] = m_blupiStartDir[1];
+ pBuffer->blupiStartDir[2] = m_blupiStartDir[2];
+ pBuffer->blupiStartDir[3] = m_blupiStartDir[3];
+ pBuffer->jaugeHide[0] = m_jauges[0].GetHide();
+ pBuffer->jaugeHide[1] = m_jauges[1].GetHide();
+ pBuffer->jaugeType[0] = m_jauges[0].GetType();
+ pBuffer->jaugeType[1] = m_jauges[1].GetType();
+ pBuffer->jaugeLevel[0] = m_jauges[0].GetLevel();
+ pBuffer->jaugeLevel[1] = m_jauges[1].GetLevel();
+ pBuffer->blupiLevel = m_blupiLevel;
+ pBuffer->energyUnused = m_blupiEnergyUnused;
+ pBuffer->bHelicoMarch = m_bHelicoMarch;
+ pBuffer->bHelicoStop = m_bHelicoStop;
+ pBuffer->bJeepMarch = m_bJeepMarch;
+ pBuffer->bJeepStop = m_bJeepStop;
+ pBuffer->bFoundCle = m_bFoundCle;
+ pBuffer->bPrivate = m_bPrivate;
+ pBuffer->bCheatDoors = m_bCheatDoors;
+ pBuffer->bSuperBlupi = m_bSuperBlupi;
+ pBuffer->bDrawSecret = m_bDrawSecret;
+ pBuffer->bJoystick = m_bJoystick;
+ pBuffer->mission = m_mission;
+ memcpy(pBuffer->doors, m_doors, sizeof(pBuffer->doors));
+ pBuffer->nbVies = m_nbVies;
+ pBuffer->nbTresor = m_nbTresor;
+ pBuffer->totalTresor = m_totalTresor;
+ pBuffer->goalPhase = m_goalPhase;
+ pBuffer->d8f8 = m_D8F8;
+ pBuffer->scrollPoint = m_scrollPoint;
+ pBuffer->scrollAdd = m_scrollAdd;
+ pBuffer->voyageIcon = m_voyageIcon;
+ pBuffer->voyageChannel = m_voyageChannel;
+ pBuffer->voyagePhase = m_voyagePhase;
+ pBuffer->voyageTotal = m_voyageTotal;
+ pBuffer->voyageStart = m_voyageStart;
+ pBuffer->voyageEnd = m_voyageEnd;
+ pBuffer->decorAction = m_decorAction;
+ pBuffer->decorPhase = m_decorPhase;
+
+ if (fwrite(pBuffer, sizeof(DescSave), 1, file) >= 1)
+ {
+ free(pBuffer);
+ fclose(file);
+ return TRUE;
+ }
+
+error:
+ if (pBuffer != NULL) free(pBuffer);
+ if (file != NULL) fclose(file);
+ return FALSE;
+
+}
+
+BOOL CDecor::CurrentRead(int gamer, int mission, BOOL *pbMission, BOOL *pbPrivate)
+{
+ char filename[MAX_PATH];
+ FILE* file = NULL;
+ DescFile* pBuffer = NULL;
+ int majRev, minRev;
+ int nb, i, x, y;
+
+ sprintf(filename, "data\\s%.3d-%.3d.blp", gamer, mission);
+ AddUserPath(filename);
+
+ file = fopen(filename, "rb");
+ if (file == NULL) goto error;
+
+ pBuffer = (DescFile*)malloc(sizeof(DescFile));
+ if (pBuffer == NULL) goto error;
+
+ nb = fread(pBuffer, sizeof(DescFile), 1, file);
+ if (nb < 1) goto error;
+
+ majRev = pBuffer->majRev;
+
+ return TRUE;
+
+error:
+ if (pBuffer != NULL) free(pBuffer);
+ if (file != NULL) fclose(file);
+ return FALSE;
+}
+
+BOOL CDecor::MissionStart(int gamer, int mission, char* param3)
+{
+ char filename[MAX_PATH];
+ FILE* file = NULL;
+ DescFile* pBuffer = NULL;
+ int majRev, minRev;
+ int nb, i, x, y;
+
+ sprintf(filename, "data\\s%.3d-%.3d.blp", gamer, mission);
+ AddUserPath(filename);
+ file = fopen(filename, "wb");
+ if (file == NULL) goto error;
+
+ pBuffer = (DescFile*)malloc(sizeof(DescFile));
+ if (pBuffer == NULL) goto error;
+
+ return TRUE;
+
+error:
+ if (pBuffer != NULL) free(pBuffer);
+ if (file != NULL) fclose(file);
+ return FALSE;
+}
diff --git a/src/decmove.cpp b/src/decmove.cpp
new file mode 100644
index 0000000..0c4592f
--- /dev/null
+++ b/src/decmove.cpp
@@ -0,0 +1,2308 @@
+// DecMove.cpp
+//
+
+#include "def.h"
+#include "decor.h"
+#include "misc.h"
+#include "dectables.h"
+
+void CDecor::MoveObjectPollution()
+{
+ POINT blupiPos = m_blupiPos;
+ POINT pos = { 0, 0 };
+ BOOL bPollution;
+ int num = 20;
+ bPollution = FALSE;
+ if (m_blupiAction == ACTION_TURN)
+ {
+ return;
+ }
+ if (m_blupiHelico)
+ {
+ if (m_blupiVitesse.y < -5)
+ {
+ if (m_time % 20 != 0 &&
+ m_time % 20 != 2 &&
+ m_time % 20 != 5 &&
+ m_time % 20 != 8 &&
+ m_time % 20 != 10 &&
+ m_time % 20 != 11 &&
+ m_time % 20 != 16 &&
+ m_time % 20 != 18)
+ {
+ return;
+ }
+ }
+ else if (m_blupiVitesse.x == 0)
+ {
+ if (m_time % 50 != 0 &&
+ m_time % 50 != 12 &&
+ m_time % 50 != 30)
+ {
+ return;
+ }
+ }
+ else if (m_time % 20 != 0 &&
+ m_time % 20 != 3 &&
+ m_time % 20 != 5 &&
+ m_time % 20 != 11 &&
+ m_time % 20 != 15)
+ {
+ return;
+ }
+ pos.x = 22;
+ bPollution = TRUE;
+ }
+ if (m_blupiOver)
+ {
+ // more
+ }
+}
+
+void CDecor::MoveObjectPlouf(POINT pos)
+{
+ for (int i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ if (m_moveObject[i].type == TYPE_PLOUF)
+ {
+ return;
+ }
+ }
+ pos.y -= 45;
+ PlaySound(SOUND_PLOUF, pos);
+ ObjectStart(pos, TYPE_PLOUF, 0);
+}
+
+void CDecor::MoveObjectTiplouf(POINT pos)
+{
+ for (int i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ if (m_moveObject[i].type == TYPE_TIPLOUF)
+ {
+ return;
+ }
+ }
+ if (m_blupiDir == DIR_RIGHT)
+ {
+ pos.x += 5;
+ }
+ else
+ {
+ pos.x -= 5;
+ }
+ pos.y -= 45;
+ PlaySound(SOUND_TIPLOUF, pos);
+ ObjectStart(pos, TYPE_TIPLOUF, 0);
+}
+
+void CDecor::MoveObjectBlup(POINT pos)
+{
+ PlaySound(SOUND_BLUP, pos);
+ pos.y -= 20;
+ int num = 0;
+ POINT tinyPoint = pos;
+ while (tinyPoint.y > 0)
+ {
+ int icon = m_decor[(tinyPoint.x + 16) / DIMOBJX][tinyPoint.y / DIMOBJY].icon;
+ if (icon != 91 && icon != 92)
+ {
+ break;
+ }
+ num++;
+ tinyPoint.y -= DIMOBJY;
+ }
+ num--;
+ if (num <= 0)
+ {
+ return;
+ }
+ int num2 = MoveObjectFree();
+ if (num2 == -1)
+ {
+ return;
+ }
+ m_moveObject[num2].type = TYPE_BLUP;
+ m_moveObject[num2].phase = 0;
+ m_moveObject[num2].posCurrent.x = pos.x;
+ m_moveObject[num2].posCurrent.y = pos.y;
+ m_moveObject[num2].posStart = m_moveObject[num2].posCurrent;
+ m_moveObject[num2].posEnd.x = pos.x;
+ m_moveObject[num2].posEnd.y = pos.y - num * DIMOBJY;
+ m_moveObject[num2].timeStopStart = 0;
+ m_moveObject[num2].stepAdvance = num * 10;
+ m_moveObject[num2].step = STEP_ADVANCE;
+ m_moveObject[num2].time = 0;
+ MoveObjectStepIcon(num2);
+}
+
+
+void CDecor::FlushBalleTraj()
+{
+ ZeroMemory(m_balleTraj, sizeof(m_balleTraj));
+}
+
+void CDecor::SetBalleTraj(POINT cel)
+{
+ if (!IsValidCel(cel)) return;
+ int num = cel.y * TRAJBYTEX;
+ num += cel.x / 8;
+ int num2 = cel.x & 7;
+ m_balleTraj[num] |= 1 << num2;
+}
+
+BOOL CDecor::IsBalleTraj(POINT pos)
+{
+ POINT cel;
+ pos.x = (pos.x + DIMOBJX / 2) / DIMOBJX;
+ pos.y = (pos.y + DIMOBJY / 2) / DIMOBJY;
+ cel.x = pos.x / DIMOBJX;
+ cel.y = pos.y / DIMOBJY;
+ if (!IsValidCel(cel)) return FALSE;
+ int num = cel.y * TRAJBYTEX;
+ num += cel.x / 8;
+ int num2 = cel.x & 7;
+ return (m_balleTraj[num] & 1 << num2) != 0;
+}
+
+void CDecor::FlushMoveTraj()
+{
+ memset(m_moveTraj, 0, sizeof(m_moveTraj));
+}
+
+void CDecor::SetMoveTraj(POINT cel)
+{
+
+ if (!IsValidCel(cel)) return;
+ int num = cel.y * TRAJBYTEX;
+ num += cel.x / 8;
+ int num2 = cel.x & 7;
+ m_moveTraj[num] |= 1 << num2;
+}
+
+BOOL CDecor::IsMoveTraj(POINT pos)
+{
+ POINT cel;
+ pos.x = (pos.x + DIMOBJX / 2) / DIMOBJX;
+ pos.y = (pos.y + DIMOBJY / 2) / DIMOBJY;
+ cel.x = pos.x / DIMOBJX;
+ cel.y = pos.y / DIMOBJY;
+ if (!IsValidCel(cel)) return FALSE;
+ int num = cel.y * TRAJBYTEX;
+ num += cel.x / 8;
+ int num2 = cel.x & 7;
+ return (m_moveTraj[num] & 1 << num2) != 0;
+}
+
+int CDecor::SearchDistRight(POINT pos, POINT dir, int type)
+{
+ POINT cel;
+ int num = 0;
+ if (type == TYPE_POLLUTION ||
+ type == TYPE_TRESORTRACK ||
+ type == TYPE_INVERTSTART ||
+ type == TYPE_INVERTSTOP ||
+ type == TYPE_INVERTSPIN ||
+ type == TYPE_EXPLO8)
+ {
+ return 500;
+ }
+ cel.x = (pos.x + DIMOBJX / 2) / DIMOBJX;
+ cel.y = (pos.y + DIMOBJY / 2) / DIMOBJY;
+ while (IsValidCel(cel) && !IsBlocIcon(m_decor[cel.x][cel.y].icon))
+ {
+ if (type == TYPE_BALLE)
+ {
+ SetBalleTraj(cel);
+ }
+ num += DIMOBJX;
+ cel += dir;
+ }
+ if ((type == TYPE_GLU || type == TYPE_ELECTRO) && num >= DIMOBJX)
+ {
+ num -= DIMOBJX;
+ }
+ if (type == TYPE_BALLE && num >= 10)
+ {
+ num -= 10;
+ }
+ return num;
+}
+
+
+void CDecor::StartSploutchGlu(POINT pos)
+{
+ POINT pos2;
+ pos2.x = pos.x;
+ pos2.y = pos.y;
+ ObjectStart(pos2, TYPE_SPLOUTCH1, 0);
+ pos2.x = pos.x + 15;
+ pos2.y = pos.y + 20;
+ ObjectStart(pos2, TYPE_SPLOUTCH2, 0);
+ pos2.x = pos.x - 20;
+ pos2.y = pos.y + 18;
+ ObjectStart(pos2, TYPE_SPLOUTCH2, 0);
+ pos2.x = pos.x + 23;
+ pos2.y = pos.y - 18;
+ ObjectStart(pos2, TYPE_SPLOUTCH2, 0);
+ pos2.x = pos.x - 15;
+ pos2.y = pos.y - 18;
+ ObjectStart(pos2, TYPE_SPLOUTCH2, 0);
+ pos2.x = pos.x + 32;
+ pos2.y = pos.y + 10;
+ ObjectStart(pos2, TYPE_SPLOUTCH3, 0);
+ pos2.x = pos.x - 28;
+ pos2.y = pos.y + 15;
+ ObjectStart(pos2, TYPE_SPLOUTCH3, 0);
+ StopVehicleSound();
+ PlaySound(SOUND_GLU, pos);
+}
+
+BOOL CDecor::ObjectStart(POINT pos, int type, int speed)
+{
+ return ObjectStart(pos, type, speed, FALSE);
+}
+
+BOOL CDecor::ObjectStart(POINT pos, int type, int speed, BOOL bMulti)
+{
+ int num = MoveObjectFree();
+ if (num == -1)
+ {
+ return FALSE;
+ }
+ m_moveObject[num].type = type;
+ m_moveObject[num].phase = 0;
+ m_moveObject[num].posCurrent = pos;
+ m_moveObject[num].posStart = pos;
+ m_moveObject[num].posEnd = pos;
+ MoveObjectStepIcon(num);
+ if (speed != 0)
+ {
+ POINT tinyPoint = pos;
+ int num2 = speed;
+ int dist = 0;
+ if (num2 > 50)
+ {
+ num2 -= 50;
+ POINT dir;
+ dir.x = 0;
+ dir.y = 1;
+ dist = SearchDistRight(tinyPoint, dir, type);
+ tinyPoint.y += dist;
+ }
+ else if (num < -50)
+ {
+ num2 += 50;
+ POINT dir;
+ dir.x = 0;
+ dir.y = -1;
+ dist = SearchDistRight(tinyPoint, dir, type);
+ tinyPoint.y -= dist;
+ }
+ else if (num2 > 0)
+ {
+ POINT dir;
+ dir.x = 1;
+ dir.y = 0;
+ dist = SearchDistRight(tinyPoint, dir, type);
+ tinyPoint.x += dist;
+ }
+ else if (num2 < 0)
+ {
+ POINT dir;
+ dir.x = -1;
+ dir.y = 0;
+ dist = SearchDistRight(tinyPoint, dir, type);
+ tinyPoint.x -= dist;
+ }
+ if (dist == 0)
+ {
+ if (type == TYPE_BALLE)
+ {
+ m_moveObject[num].type = 0;
+ return TRUE;
+ }
+ }
+ else
+ {
+ m_moveObject[num].posEnd = tinyPoint;
+ m_moveObject[num].timeStopStart = 0;
+ m_moveObject[num].stepAdvance = abs(dist * num2 / DIMOBJX);
+ m_moveObject[num].step = STEP_ADVANCE;
+ m_moveObject[num].time = 0;
+ }
+ }
+ MoveObjectPriority(num);
+ if (bMulti)
+ {
+ NetMessage msg;
+ msg.type = MESS_OBJECTSTART;
+ msg.data1 = speed;
+ msg.data2 = pos.x;
+ msg.data3 = pos.y;
+ msg.data4 = type;
+ NetMessagePush(&msg);
+ }
+ return TRUE;
+}
+
+BOOL CDecor::ObjectDelete(POINT pos, int type, BOOL bMulti)
+{
+ NetMessage msg;
+
+ int num = MoveObjectSearch(pos, type);
+ if (num == -1)
+ {
+ return FALSE;
+ }
+ m_moveObject[num].type = 0;
+ if (bMulti)
+ {
+ msg.type = MESS_OBJECTDELETE;
+ msg.data1 = 0;
+ msg.data2 = pos.x;
+ msg.data3 = pos.y;
+ msg.data4 = type;
+
+ NetMessagePush(&msg);
+ }
+ return TRUE;
+}
+
+void CDecor::MoveObjectStep()
+{
+ m_blupiVector = POINT( 0, 0 );
+ m_blupiTransport = -1;
+ for (int i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ if (m_moveObject[i].type != 0)
+ {
+ MoveObjectStepLine(i);
+ MoveObjectStepIcon(i);
+ if (m_moveObject[i].type == TYPE_BULLDOZER ||
+ m_moveObject[i].type == TYPE_BLUPITANK ||
+ m_moveObject[i].type == TYPE_BLUPIHELICO)
+ {
+ int num = MovePersoDetect(m_moveObject[i].posCurrent);
+ if (num != -1)
+ {
+ POINT posCurrent = m_moveObject[i].posCurrent;
+ posCurrent.x -= 34;
+ posCurrent.y -= 34;
+ ObjectStart(posCurrent, TYPE_EXPLO1, 0, TRUE);
+ PlaySound(SOUND_BOUM, m_moveObject[i].posCurrent);
+ m_decorAction = 1;
+ m_decorPhase = 0;
+ posCurrent = m_moveObject[i].posCurrent;
+ posCurrent.x += 2;
+ posCurrent.y += BLUPIOFFY;
+ ObjectDelete(m_moveObject[i].posCurrent, m_moveObject[i].type);
+ ObjectStart(posCurrent, TYPE_CLEAR, 0);
+ ObjectDelete(m_moveObject[num].posCurrent, m_moveObject[num].type);
+ }
+ if (BlupiElectro(m_moveObject[i].posCurrent))
+ {
+ POINT posCurrent = m_moveObject[i].posCurrent;
+ posCurrent.x += 2;
+ posCurrent.y += BLUPIOFFY;
+ ObjectDelete(m_moveObject[i].posCurrent, m_moveObject[i].type);
+ ObjectStart(posCurrent, TYPE_ELECTRO, 55);
+ PlaySound(SOUND_ELECTRO, posCurrent);
+ }
+ }
+ }
+ }
+}
+
+void CDecor::MoveObjectStepLine(int i)
+{
+ MoveObject moveObject;
+ POINT tinyPoint;
+ BOOL flag = FALSE;
+ RECT tinyRect = { 0, 0, 0, 0 };
+ if (m_moveObject[i].type == TYPE_ASCENSEUR ||
+ m_moveObject[i].type == TYPE_ASCENSEURs ||
+ m_moveObject[i].type == TYPE_ASCENSEURsi &&
+ !m_blupiSuspend)
+ {
+ RECT src;
+ src.left = m_blupiPos.x + 20;
+ src.right = m_blupiPos.x + DIMBLUPIX - 20;
+ src.top = m_blupiPos.y + DIMBLUPIY - 2;
+ src.bottom = m_blupiPos.y + DIMBLUPIY - 1;
+ tinyRect.left = m_moveObject[i].posCurrent.x;
+ tinyRect.right = m_moveObject[i].posCurrent.x + DIMOBJX;
+ tinyRect.top = m_moveObject[i].posCurrent.y;
+ tinyRect.bottom = m_moveObject[i].posCurrent.y + 16;
+ RECT tinyRect2;
+ flag = IntersectRect(&tinyRect2, &tinyRect, &src);
+ tinyPoint = m_moveObject[i].posCurrent;
+ }
+ POINT posCurrent;
+ if (m_blupiFocus && !m_blupiHide && m_moveObject[i].type == TYPE_BOMBEFOLLOW2)
+ {
+ posCurrent = m_moveObject[i].posCurrent;
+ if (posCurrent.x < m_blupiPos.x)
+ {
+ posCurrent.x++;
+ }
+ if (posCurrent.x > m_blupiPos.x)
+ {
+ posCurrent.x--;
+ }
+ if (posCurrent.y < m_blupiPos.y)
+ {
+ posCurrent.y++;
+ }
+ if (posCurrent.y > m_blupiPos.y)
+ {
+ posCurrent.y--;
+ }
+ tinyRect.left = posCurrent.x + 10;
+ tinyRect.right = posCurrent.x + DIMBLUPIX - 10;
+ tinyRect.top = posCurrent.y + 10;
+ tinyRect.bottom = posCurrent.y + DIMBLUPIX - 10;
+ if (TestPath(tinyRect, m_moveObject[i].posCurrent, &posCurrent))
+ {
+ m_moveObject[i].posCurrent = posCurrent;
+ m_moveObject[i].posStart = posCurrent;
+ m_moveObject[i].posEnd = posCurrent;
+ }
+ else
+ {
+ ObjectDelete(m_moveObject[i].posCurrent, m_moveObject[i].type);
+ posCurrent.x -= DIMOBJX / 2 + 2;
+ posCurrent.y -= DIMOBJY / 2 + 2;
+ ObjectStart(posCurrent, TYPE_EXPLO2, 0);
+ PlaySound(SOUND_BOUM, posCurrent);
+ m_decorAction = 1;
+ m_decorPhase = 0;
+ }
+ }
+ if (m_moveObject[i].posStart.x != m_moveObject[i].posEnd.x || m_moveObject[i].posStart.y != m_moveObject[i].posEnd.y)
+ {
+ if (m_moveObject[i].step == STEP_STOPSTART)
+ {
+ if (m_moveObject[i].time < m_moveObject[i].timeStopStart)
+ {
+ m_moveObject[i].time ++;
+ }
+ else
+ {
+ m_moveObject[i].step = STEP_ADVANCE;
+ m_moveObject[i].time = 0;
+ }
+ }
+ else if (m_moveObject[i].step == STEP_ADVANCE)
+ {
+ if (m_moveObject[i].posCurrent.x != m_moveObject[i].posEnd.x || m_moveObject[i].posCurrent.y != m_moveObject[i].posEnd.y)
+ {
+ m_moveObject[i].time ++;
+ if (m_moveObject[i].stepAdvance != 0)
+ {
+ m_moveObject[i].posCurrent = (m_moveObject[i].posEnd - m_moveObject[i].posStart) * m_moveObject[i].time / m_moveObject[i].stepAdvance + m_moveObject[i].posStart;
+ }
+
+ }
+ else if (m_moveObject[i].type == TYPE_BLUP || m_moveObject[i].type == TYPE_BALLE)
+ {
+ m_moveObject[i].type = 0;
+ }
+ else if (m_moveObject[i].type == TYPE_GLU)
+ {
+ m_moveObject[i].posStart = m_moveObject[i].posCurrent;
+ m_moveObject[i].posEnd = m_moveObject[i].posCurrent;
+ m_moveObject[i].step = STEP_STOPEND;
+ m_moveObject[i].time = 0;
+ }
+ else
+ {
+ m_moveObject[i].step = STEP_STOPEND;
+ m_moveObject[i].time = 0;
+ }
+ }
+ else if (m_moveObject[i].step == STEP_STOPEND)
+ {
+ if (m_moveObject[i].time < m_moveObject[i].timeStopEnd)
+ {
+ m_moveObject[i].time ++;
+ }
+ else
+ {
+ m_moveObject[i].step = STEP_RECEDE;
+ m_moveObject[i].time = 0;
+ }
+ }
+ else if (m_moveObject[i].step == STEP_RECEDE)
+ {
+ if (m_moveObject[i].posCurrent.x != m_moveObject[i].posStart.x || m_moveObject[i].posCurrent.y != m_moveObject[i].posStart.y)
+ {
+ m_moveObject[i].time ++;
+ if (m_moveObject[i].stepRecede != 0)
+ {
+ m_moveObject[i].posCurrent = (m_moveObject[i].posStart - m_moveObject[i].posEnd) * m_moveObject[i].time / m_moveObject[i].stepRecede + m_moveObject[i].posEnd;
+ }
+ }
+ else
+ {
+ m_moveObject[i].step = STEP_STOPSTART;
+ m_moveObject[i].time = 0;
+ }
+ }
+ }
+ if (m_moveObject[i].type == TYPE_DOOR && m_moveObject[i].step == STEP_STOPEND)
+ {
+ m_moveObject[i].type = 0;
+ }
+ posCurrent = m_moveObject[i].posCurrent;
+ if (m_moveObject[i].type == TYPE_ASCENSEUR ||
+ m_moveObject[i].type == TYPE_ASCENSEURs ||
+ m_moveObject[i].type == TYPE_ASCENSEURsi)
+ {
+ posCurrent.y -= DIMOBJY;
+ }
+ posCurrent.x = (posCurrent.x + DIMOBJX / 2) / DIMOBJX;
+ posCurrent.y = (posCurrent.y + DIMOBJY / 2) / DIMOBJY;
+ SetMoveTraj(posCurrent);
+ if (flag)
+ {
+ m_blupiVector.x = m_moveObject[i].posCurrent.x - tinyPoint.x;
+ m_blupiVector.y = m_moveObject[i].posCurrent.y - (m_blupiPos.y + DIMBLUPIY - BLUPIFLOOR);
+ if (m_moveObject[i].type == TYPE_ASCENSEURs)
+ {
+ m_blupiVector.x += 2;
+ }
+ if (m_moveObject[i].type == TYPE_ASCENSEURsi)
+ {
+ m_blupiVector.x -= 2;
+ }
+ if (m_blupiTimeNoAsc == 0)
+ {
+ m_blupiTransport = i;
+ }
+ }
+}
+
+void CDecor::MoveObjectStepIcon(int i)
+{
+ POINT pos;
+ if (m_moveObject[i].type == TYPE_ASCENSEURs)
+ {
+ m_moveObject[i].icon = table_chenille[m_moveObject[i].phase / 1 % 6];
+ }
+ if (m_moveObject[i].type == TYPE_ASCENSEURsi)
+ {
+ m_moveObject[i].icon = table_chenillei[m_moveObject[i].phase / 1 % 6];
+ }
+ if (m_moveObject[i].type == TYPE_BOMBEDOWN)
+ {
+ m_moveObject[i].icon = 12 + m_moveObject[i].phase / 2 % 9;
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_BOMBEUP)
+ {
+ m_moveObject[i].icon = 48 + m_moveObject[i].phase / 2 % 9;
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_BOMBEMOVE)
+ {
+ m_moveObject[i].icon = 69 + m_moveObject[i].phase / 1 % 9;
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_BOMBEFOLLOW1)
+ {
+ m_moveObject[i].icon = table_follow1[m_moveObject[i].phase / 1 % 26];
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_BOMBEFOLLOW2)
+ {
+ m_moveObject[i].icon = table_follow2[m_moveObject[i].phase / 1 % 5];
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_BOMBEPERSO1)
+ {
+ m_moveObject[i].icon = 257 + m_moveObject[i].phase / 1 % 6;
+ m_moveObject[i].channel = CHBLUPI;
+ }
+ if (m_moveObject[i].type == TYPE_BOMBEPERSO2)
+ {
+ m_moveObject[i].icon = 257 + m_moveObject[i].phase / 1 % 6;
+ m_moveObject[i].channel = CHBLUPI1;
+ }
+ if (m_moveObject[i].type == TYPE_BOMBEPERSO3)
+ {
+ m_moveObject[i].icon = 257 + m_moveObject[i].phase / 1 % 6;
+ m_moveObject[i].channel = CHBLUPI2;
+ }
+ if (m_moveObject[i].type == TYPE_BOMBEPERSO4)
+ {
+ m_moveObject[i].icon = 257 + m_moveObject[i].phase / 1 % 6;
+ m_moveObject[i].channel = CHBLUPI3;
+ }
+ if (m_moveObject[i].type == TYPE_DYNAMITE)
+ {
+ m_moveObject[i].icon = 252;
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_DYNAMITEf)
+ {
+ m_moveObject[i].icon = table_dynamitef[m_moveObject[i].phase / 1 % 100];
+ m_moveObject[i].channel = CHELEMENT;
+ if (m_moveObject[i].phase == 50)
+ {
+ DynamiteStart(i, 0, 0);
+ }
+ if (m_moveObject[i].phase == 53)
+ {
+ DynamiteStart(i, -100, 8);
+ }
+ if (m_moveObject[i].phase == 55)
+ {
+ DynamiteStart(i, 80, 10);
+ }
+ if (m_moveObject[i].phase == 56)
+ {
+ DynamiteStart(i, -15, -100);
+ }
+ if (m_moveObject[i].phase == 59)
+ {
+ DynamiteStart(i, 20, 70);
+ }
+ if (m_moveObject[i].phase == 62)
+ {
+ DynamiteStart(i, 30, -50);
+ }
+ if (m_moveObject[i].phase == 64)
+ {
+ DynamiteStart(i, -40, 30);
+ }
+ if (m_moveObject[i].phase == 67)
+ {
+ DynamiteStart(i, -180, 10);
+ }
+ if (m_moveObject[i].phase == 69)
+ {
+ DynamiteStart(i, 200, -10);
+ }
+ if (m_moveObject[i].phase >= 70)
+ {
+ m_moveObject[i].type = 0;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_TRESOR)
+ {
+ if (m_moveObject[i].phase / 3 % 22 < 11)
+ {
+ m_moveObject[i].icon = m_moveObject[i].phase / 3 % 11;
+ }
+ else
+ {
+ m_moveObject[i].icon = 11 - m_moveObject[i].phase / 3 % 11;
+ }
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_EGG)
+ {
+ m_moveObject[i].icon = 21 + m_moveObject[i].phase / 4 % 8;
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_GOAL)
+ {
+ m_moveObject[i].icon = 29 + m_moveObject[i].phase / 3 % 8;
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_CLE)
+ {
+ m_moveObject[i].icon = table_cle[m_moveObject[i].phase / 3 % 12];
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_CLE1)
+ {
+ m_moveObject[i].icon = table_cle1[m_moveObject[i].phase / 3 % 12];
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_CLE2)
+ {
+ m_moveObject[i].icon = table_cle2[m_moveObject[i].phase / 3 % 12];
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_CLE3)
+ {
+ m_moveObject[i].icon = table_cle3[m_moveObject[i].phase / 3 % 12];
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_SKATE)
+ {
+ m_moveObject[i].icon = table_skate[m_moveObject[i].phase / 1 % 34];
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_SHIELD)
+ {
+ m_moveObject[i].icon = table_shield[m_moveObject[i].phase / 2 % 16];
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_POWER)
+ {
+ m_moveObject[i].icon = table_power[m_moveObject[i].phase / 2 % 8];
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_INVERT)
+ {
+ m_moveObject[i].icon = table_invert[m_moveObject[i].phase / 2 % 20];
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_CHARGE)
+ {
+ m_moveObject[i].icon = table_charge[m_moveObject[i].phase / 2 % 6];
+ m_moveObject[i].channel = CHOBJECT;
+ }
+ if (m_moveObject[i].type == TYPE_MAGICTRACK)
+ {
+ m_moveObject[i].icon = table_magictrack[m_moveObject[i].phase / 1 % 24];
+ m_moveObject[i].channel = CHELEMENT;
+ if (m_moveObject[i].phase >= 24)
+ {
+ m_moveObject[i].type = 0;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_SHIELDTRACK)
+ {
+ m_moveObject[i].icon = table_shieldtrack[m_moveObject[i].phase / 1 % 20];
+ m_moveObject[i].channel = CHELEMENT;
+ if (m_moveObject[i].phase >= 20)
+ {
+ m_moveObject[i].type = 0;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_TRESORTRACK)
+ {
+ m_moveObject[i].icon = table_tresortrack[m_moveObject[i].phase / 1 % 11];
+ m_moveObject[i].channel = CHELEMENT;
+ if (m_moveObject[i].phase >= 11)
+ {
+ m_moveObject[i].type = 0;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_HIDETRACK && m_moveObject[i].phase >= 20)
+ {
+ m_moveObject[i].type = 0;
+ }
+ if (m_moveObject[i].type == TYPE_EXPLO1)
+ {
+ if (m_moveObject[i].phase >= 36)
+ {
+ m_moveObject[i].type = 0;
+ }
+ else
+ {
+ m_moveObject[i].icon = table_explo1[m_moveObject[i].phase];
+ m_moveObject[i].channel = CHEXPLO;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_EXPLO2)
+ {
+ if (m_moveObject[i].phase >= 20)
+ {
+ m_moveObject[i].type = 0;
+ }
+ else
+ {
+ m_moveObject[i].icon = table_explo2[m_moveObject[i].phase % 20];
+ m_moveObject[i].channel = CHEXPLO;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_EXPLO3)
+ {
+ if (m_moveObject[i].phase >= 20)
+ {
+ m_moveObject[i].type = 0;
+ }
+ else
+ {
+ m_moveObject[i].icon = table_explo3[m_moveObject[i].phase / 1 % 20];
+ m_moveObject[i].channel = CHEXPLO;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_EXPLO4)
+ {
+ if (m_moveObject[i].phase >= 9)
+ {
+ m_moveObject[i].type = 0;
+ }
+ else
+ {
+ m_moveObject[i].icon = table_explo4[m_moveObject[i].phase / 1 % 9];
+ m_moveObject[i].channel = CHEXPLO;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_EXPLO5)
+ {
+ if (m_moveObject[i].phase >= 12)
+ {
+ m_moveObject[i].type = 0;
+ }
+ else
+ {
+ m_moveObject[i].icon = table_explo5[m_moveObject[i].phase / 1 % 12];
+ m_moveObject[i].channel = CHEXPLO;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_EXPLO6)
+ {
+ if (m_moveObject[i].phase >= 6)
+ {
+ m_moveObject[i].type = 0;
+ }
+ else
+ {
+ m_moveObject[i].icon = table_explo6[m_moveObject[i].phase / 1 % 6];
+ m_moveObject[i].channel = CHEXPLO;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_EXPLO7)
+ {
+ if (m_moveObject[i].phase >= 128)
+ {
+ m_moveObject[i].type = 0;
+ }
+ else
+ {
+ m_moveObject[i].icon = table_explo7[m_moveObject[i].phase / 1 % 128];
+ m_moveObject[i].channel = CHEXPLO;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_EXPLO8)
+ {
+ if (m_moveObject[i].phase >= 5)
+ {
+ m_moveObject[i].type = 0;
+ }
+ else
+ {
+ m_moveObject[i].icon = table_explo8[m_moveObject[i].phase / 1 % 5];
+ m_moveObject[i].channel = CHEXPLO;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_SPLOUTCH1)
+ {
+ if (m_moveObject[i].phase >= 10)
+ {
+ m_moveObject[i].type = 0;
+ }
+ else
+ {
+ m_moveObject[i].icon = table_sploutch1[m_moveObject[i].phase / 1 % 10];
+ m_moveObject[i].channel = CHEXPLO;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_SPLOUTCH2)
+ {
+ if (m_moveObject[i].phase >= 13)
+ {
+ m_moveObject[i].type = 0;
+ }
+ else
+ {
+ m_moveObject[i].icon = table_sploutch2[m_moveObject[i].phase / 1 % 13];
+ m_moveObject[i].channel = CHEXPLO;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_SPLOUTCH3)
+ {
+ if (m_moveObject[i].phase >= 18)
+ {
+ m_moveObject[i].type = 0;
+ }
+ else
+ {
+ m_moveObject[i].icon = table_sploutch3[m_moveObject[i].phase / 1 % 18];
+ m_moveObject[i].channel = CHEXPLO;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_TENTACULE)
+ {
+ if (m_moveObject[i].phase >= 90)
+ {
+ m_moveObject[i].type = 0;
+ }
+ else
+ {
+ m_moveObject[i].icon = table_tentacule[m_moveObject[i].phase / 2 % 45];
+ m_moveObject[i].channel = CHEXPLO;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_BRIDGE)
+ {
+ if (m_moveObject[i].phase == 0)
+ {
+ PlaySound(SOUND_BRIDGE1, m_moveObject[i].posStart);
+ }
+ if (m_moveObject[i].phase == 137)
+ {
+ PlaySound(SOUND_BRIDGE2, m_moveObject[i].posStart);
+ }
+ if (m_moveObject[i].phase >= 157)
+ {
+ m_moveObject[i].type = 0;
+ }
+ else
+ {
+ m_moveObject[i].icon = table_bridge[m_moveObject[i].phase / 1 % 157];
+ m_moveObject[i].channel = CHOBJECT;
+ pos.x = m_moveObject[i].posStart.x / DIMOBJX;
+ pos.y = m_moveObject[i].posStart.y / DIMOBJY;
+ m_decor[pos.x][pos.y].icon = m_moveObject[i].icon;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_POLLUTION)
+ {
+ if (m_moveObject[i].phase >= 16)
+ {
+ m_moveObject[i].type = 0;
+ }
+ else
+ {
+ m_moveObject[i].icon = table_pollution[m_moveObject[i].phase / 2 % 8];
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_INVERTSTART)
+ {
+ if (m_moveObject[i].phase >= 16)
+ {
+ m_moveObject[i].type = 0;
+ }
+ else
+ {
+ m_moveObject[i].icon = table_invertstart[m_moveObject[i].phase / 2 % 8];
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_INVERTSTOP)
+ {
+ if (m_moveObject[i].phase >= 16)
+ {
+ m_moveObject[i].type = 0;
+ }
+ else
+ {
+ m_moveObject[i].icon = table_invertstop[m_moveObject[i].phase / 2 % 8];
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_PLOUF)
+ {
+ if (m_moveObject[i].phase >= 14)
+ {
+ m_moveObject[i].type = 0;
+ }
+ else
+ {
+ m_moveObject[i].icon = table_plouf[m_moveObject[i].phase / 2 % 7];
+ m_moveObject[i].channel = CHOBJECT;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_TIPLOUF)
+ {
+ if (m_moveObject[i].phase >= 6)
+ {
+ m_moveObject[i].type = 0;
+ }
+ else
+ {
+ m_moveObject[i].icon = table_tiplouf[m_moveObject[i].phase / 2 % 7];
+ m_moveObject[i].channel = CHOBJECT;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_BLUP)
+ {
+ m_moveObject[i].icon = table_blup[m_moveObject[i].phase / 2 % 20];
+ m_moveObject[i].channel = CHOBJECT;
+ }
+ if (m_moveObject[i].type == TYPE_BULLDOZER)
+ {
+ if (m_moveObject[i].posStart.x > m_moveObject[i].posEnd.x)
+ {
+ if (m_moveObject[i].step == STEP_STOPSTART)
+ {
+ m_moveObject[i].icon = table_bulldozer_turn2l[m_moveObject[i].time % 22];
+ }
+ if (m_moveObject[i].step == STEP_STOPEND)
+ {
+ m_moveObject[i].icon = table_bulldozer_turn2r[m_moveObject[i].time % 22];
+ }
+ if (m_moveObject[i].step == STEP_ADVANCE)
+ {
+ m_moveObject[i].icon = table_bulldozer_left[m_moveObject[i].time % 8];
+ }
+ if (m_moveObject[i].step == STEP_RECEDE)
+ {
+ m_moveObject[i].icon = table_bulldozer_right[m_moveObject[i].time % 8];
+ }
+ }
+ else
+ {
+ if (m_moveObject[i].step == STEP_STOPSTART)
+ {
+ m_moveObject[i].icon = table_bulldozer_turn2r[m_moveObject[i].time % 22];
+ }
+ if (m_moveObject[i].step == STEP_STOPEND)
+ {
+ m_moveObject[i].icon = table_bulldozer_turn2l[m_moveObject[i].time % 22];
+ }
+ if (m_moveObject[i].step == STEP_ADVANCE)
+ {
+ m_moveObject[i].icon = table_bulldozer_right[m_moveObject[i].time % 8];
+ }
+ if (m_moveObject[i].step == STEP_RECEDE)
+ {
+ m_moveObject[i].icon = table_bulldozer_left[m_moveObject[i].time % 8];
+ }
+ }
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_POISSON)
+ {
+ if (m_moveObject[i].posStart.x > m_moveObject[i].posEnd.x)
+ {
+ if (m_moveObject[i].step == STEP_STOPSTART)
+ {
+ m_moveObject[i].icon = table_poisson_turn2l[m_moveObject[i].time % 48];
+ }
+ if (m_moveObject[i].step == STEP_STOPEND)
+ {
+ m_moveObject[i].icon = table_poisson_turn2r[m_moveObject[i].time % 48];
+ }
+ if (m_moveObject[i].step == STEP_ADVANCE)
+ {
+ m_moveObject[i].icon = table_poisson_left[m_moveObject[i].time % 8];
+ }
+ if (m_moveObject[i].step == STEP_RECEDE)
+ {
+ m_moveObject[i].icon = table_poisson_right[m_moveObject[i].time % 8];
+ }
+ }
+ else
+ {
+ if (m_moveObject[i].step == STEP_STOPSTART)
+ {
+ m_moveObject[i].icon = table_poisson_turn2r[m_moveObject[i].time % 48];
+ }
+ if (m_moveObject[i].step == STEP_STOPEND)
+ {
+ m_moveObject[i].icon = table_poisson_turn2l[m_moveObject[i].time % 48];
+ }
+ if (m_moveObject[i].step == STEP_ADVANCE)
+ {
+ m_moveObject[i].icon = table_poisson_right[m_moveObject[i].time % 8];
+ }
+ if (m_moveObject[i].step == STEP_RECEDE)
+ {
+ m_moveObject[i].icon = table_poisson_left[m_moveObject[i].time % 8];
+ }
+ }
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_OISEAU)
+ {
+ if (m_moveObject[i].posStart.x > m_moveObject[i].posEnd.x)
+ {
+ if (m_moveObject[i].step == STEP_STOPSTART)
+ {
+ m_moveObject[i].icon = table_oiseau_turn2l[m_moveObject[i].time % 10];
+ }
+ if (m_moveObject[i].step == STEP_STOPEND)
+ {
+ m_moveObject[i].icon = table_oiseau_turn2r[m_moveObject[i].time % 10];
+ }
+ if (m_moveObject[i].step == STEP_ADVANCE)
+ {
+ m_moveObject[i].icon = table_oiseau_left[m_moveObject[i].time % 8];
+ }
+ if (m_moveObject[i].step == STEP_RECEDE)
+ {
+ m_moveObject[i].icon = table_oiseau_right[m_moveObject[i].time % 8];
+ }
+ }
+ else
+ {
+ if (m_moveObject[i].step == STEP_STOPSTART)
+ {
+ m_moveObject[i].icon = table_oiseau_turn2r[m_moveObject[i].time % 10];
+ }
+ if (m_moveObject[i].step == STEP_STOPEND)
+ {
+ m_moveObject[i].icon = table_oiseau_turn2l[m_moveObject[i].time % 10];
+ }
+ if (m_moveObject[i].step == STEP_ADVANCE)
+ {
+ m_moveObject[i].icon = table_oiseau_right[m_moveObject[i].time % 8];
+ }
+ if (m_moveObject[i].step == STEP_RECEDE)
+ {
+ m_moveObject[i].icon = table_oiseau_left[m_moveObject[i].time % 8];
+ }
+ }
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_GUEPE)
+ {
+ if (m_moveObject[i].posStart.x > m_moveObject[i].posEnd.x)
+ {
+ if (m_moveObject[i].step == STEP_STOPSTART)
+ {
+ m_moveObject[i].icon = table_guepe_turn2l[m_moveObject[i].time % 5];
+ }
+ if (m_moveObject[i].step == STEP_STOPEND)
+ {
+ m_moveObject[i].icon = table_guepe_turn2r[m_moveObject[i].time % 5];
+ }
+ if (m_moveObject[i].step == STEP_ADVANCE)
+ {
+ m_moveObject[i].icon = table_guepe_left[m_moveObject[i].time % 6];
+ }
+ if (m_moveObject[i].step == STEP_RECEDE)
+ {
+ m_moveObject[i].icon = table_guepe_right[m_moveObject[i].time % 6];
+ }
+ }
+ else
+ {
+ if (m_moveObject[i].step == STEP_STOPSTART)
+ {
+ m_moveObject[i].icon = table_guepe_turn2r[m_moveObject[i].time % 5];
+ }
+ if (m_moveObject[i].step == STEP_STOPEND)
+ {
+ m_moveObject[i].icon = table_guepe_turn2l[m_moveObject[i].time % 5];
+ }
+ if (m_moveObject[i].step == STEP_ADVANCE)
+ {
+ m_moveObject[i].icon = table_guepe_right[m_moveObject[i].time % 6];
+ }
+ if (m_moveObject[i].step == STEP_RECEDE)
+ {
+ m_moveObject[i].icon = table_guepe_left[m_moveObject[i].time % 6];
+ }
+ }
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_CREATURE)
+ {
+ if (m_moveObject[i].posStart.x > m_moveObject[i].posEnd.x)
+ {
+ if (m_moveObject[i].step == STEP_STOPSTART)
+ {
+ m_moveObject[i].icon = table_creature_turn2[m_moveObject[i].time % 200];
+ }
+ if (m_moveObject[i].step == STEP_STOPEND)
+ {
+ m_moveObject[i].icon = table_creature_turn2[m_moveObject[i].time % 200];
+ }
+ if (m_moveObject[i].step == STEP_ADVANCE)
+ {
+ m_moveObject[i].icon = table_creature_left[m_moveObject[i].time % 8];
+ }
+ if (m_moveObject[i].step == STEP_RECEDE)
+ {
+ m_moveObject[i].icon = table_creature_right[m_moveObject[i].time % 8];
+ }
+ }
+ else
+ {
+ if (m_moveObject[i].step == STEP_STOPSTART)
+ {
+ m_moveObject[i].icon = table_creature_turn2[m_moveObject[i].time % 200];
+ }
+ if (m_moveObject[i].step == STEP_STOPEND)
+ {
+ m_moveObject[i].icon = table_creature_turn2[m_moveObject[i].time % 200];
+ }
+ if (m_moveObject[i].step == STEP_ADVANCE)
+ {
+ m_moveObject[i].icon = table_creature_right[m_moveObject[i].time % 8];
+ }
+ if (m_moveObject[i].step == STEP_RECEDE)
+ {
+ m_moveObject[i].icon = table_creature_left[m_moveObject[i].time % 8];
+ }
+ }
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_BLUPIHELICO)
+ {
+ if (m_moveObject[i].posStart.x > m_moveObject[i].posEnd.x)
+ {
+ if (m_moveObject[i].step == STEP_STOPSTART)
+ {
+ m_moveObject[i].icon = table_blupih_turn2l[m_moveObject[i].time % 26];
+ }
+ if (m_moveObject[i].step == STEP_STOPEND)
+ {
+ m_moveObject[i].icon = table_blupih_turn2r[m_moveObject[i].time % 26];
+ }
+ if (m_moveObject[i].step == STEP_ADVANCE)
+ {
+ m_moveObject[i].icon = table_blupih_left[m_moveObject[i].time % 8];
+ }
+ if (m_moveObject[i].step == STEP_RECEDE)
+ {
+ m_moveObject[i].icon = table_blupih_right[m_moveObject[i].time % 8];
+ }
+ }
+ else
+ {
+ if (m_moveObject[i].step == STEP_STOPSTART)
+ {
+ m_moveObject[i].icon = table_blupih_turn2r[m_moveObject[i].time % 26];
+ }
+ if (m_moveObject[i].step == STEP_STOPEND)
+ {
+ m_moveObject[i].icon = table_blupih_turn2l[m_moveObject[i].time % 26];
+ }
+ if (m_moveObject[i].step == STEP_ADVANCE)
+ {
+ m_moveObject[i].icon = table_blupih_right[m_moveObject[i].time % 8];
+ }
+ if (m_moveObject[i].step == STEP_RECEDE)
+ {
+ m_moveObject[i].icon = table_blupih_left[m_moveObject[i].time % 8];
+ }
+ }
+ if ((m_moveObject[i].step == STEP_STOPSTART || m_moveObject[i].step == STEP_STOPEND) && m_moveObject[i].time == 21)
+ {
+ pos.x = m_moveObject[i].posCurrent.x;
+ pos.y = m_moveObject[i].posCurrent.y + 40;
+ if (ObjectStart(pos, TYPE_BALLE, 55) != -1)
+ {
+ PlaySound(SOUND_FIREOK, pos);
+ }
+ }
+ }
+ if (m_moveObject[i].type == TYPE_BLUPITANK)
+ {
+ if (m_moveObject[i].posStart.x > m_moveObject[i].posEnd.x)
+ {
+ if (m_moveObject[i].step == STEP_STOPSTART)
+ {
+ m_moveObject[i].icon = table_blupit_turn2l[m_moveObject[i].time % 24];
+ }
+ if (m_moveObject[i].step == STEP_STOPEND)
+ {
+ m_moveObject[i].icon = table_blupit_turn2r[m_moveObject[i].time % 24];
+ }
+ if (m_moveObject[i].step == STEP_ADVANCE)
+ {
+ m_moveObject[i].icon = table_blupit_left[m_moveObject[i].time % 8];
+ }
+ if (m_moveObject[i].step == STEP_RECEDE)
+ {
+ m_moveObject[i].icon = table_blupit_right[m_moveObject[i].time % 8];
+ }
+ }
+ else
+ {
+ if (m_moveObject[i].step == STEP_STOPSTART)
+ {
+ m_moveObject[i].icon = table_blupit_turn2r[m_moveObject[i].time % 24];
+ }
+ if (m_moveObject[i].step == STEP_STOPEND)
+ {
+ m_moveObject[i].icon = table_blupit_turn2l[m_moveObject[i].time % 24];
+ }
+ if (m_moveObject[i].step == STEP_ADVANCE)
+ {
+ m_moveObject[i].icon = table_blupit_right[m_moveObject[i].time % 8];
+ }
+ if (m_moveObject[i].step == STEP_RECEDE)
+ {
+ m_moveObject[i].icon = table_blupit_left[m_moveObject[i].time % 8];
+ }
+ }
+ if ((m_moveObject[i].step == STEP_STOPSTART || m_moveObject[i].step == STEP_STOPEND) && m_moveObject[i].time == 3)
+ {
+ int speed;
+ if ((m_moveObject[i].posStart.x < m_moveObject[i].posEnd.x && m_moveObject[i].step == STEP_STOPSTART) || (m_moveObject[i].posStart.x > m_moveObject[i].posEnd.x && m_moveObject[i].step == STEP_STOPEND))
+ {
+ pos.x = m_moveObject[i].posCurrent.x - 30;
+ pos.y = m_moveObject[i].posCurrent.y + BLUPIOFFY;
+ speed = -5;
+ }
+ else
+ {
+ pos.x = m_moveObject[i].posCurrent.x + 30;
+ pos.y = m_moveObject[i].posCurrent.y + BLUPIOFFY;
+ speed = 5;
+ }
+ if (ObjectStart(pos, TYPE_BALLE, speed) != -1)
+ {
+ PlaySound(SOUND_FIREOK, pos);
+ }
+ }
+ if ((m_moveObject[i].step == STEP_STOPSTART || m_moveObject[i].step == STEP_STOPEND) && m_moveObject[i].time == 21)
+ {
+ int speed;
+ if ((m_moveObject[i].posStart.x < m_moveObject[i].posEnd.x && m_moveObject[i].step == STEP_STOPSTART) || (m_moveObject[i].posStart.x > m_moveObject[i].posEnd.x && m_moveObject[i].step == STEP_STOPEND))
+ {
+ pos.x = m_moveObject[i].posCurrent.x + 30;
+ pos.y = m_moveObject[i].posCurrent.y + BLUPIOFFY;
+ speed = 5;
+ }
+ else
+ {
+ pos.x = m_moveObject[i].posCurrent.x - 30;
+ pos.y = m_moveObject[i].posCurrent.y + BLUPIOFFY;
+ speed = -5;
+ }
+ if (ObjectStart(pos, TYPE_BALLE, speed) != -1)
+ {
+ PlaySound(SOUND_FIREOK, pos);
+ }
+ }
+ }
+ if (m_moveObject[i].type == TYPE_GLU)
+ {
+ m_moveObject[i].icon = table_glu[m_moveObject[i].phase / 1 % 25];
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_CLEAR)
+ {
+ if (m_moveObject[i].phase >= 70)
+ {
+ m_moveObject[i].type = 0;
+ }
+ else
+ {
+ m_moveObject[i].icon = table_clear[m_moveObject[i].phase / 1 % 70];
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_ELECTRO)
+ {
+ if (m_moveObject[i].phase >= 90)
+ {
+ m_moveObject[i].type = 0;
+ }
+ else
+ {
+ m_moveObject[i].icon = table_electro[m_moveObject[i].phase / 1 % 90];
+ if (m_moveObject[i].phase < 30)
+ {
+ m_moveObject[i].channel = CHBLUPI2;
+ }
+ else
+ {
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ }
+ }
+ if (m_moveObject[i].type == TYPE_HELICO)
+ {
+ m_moveObject[i].icon = 68;
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_OVER)
+ {
+ m_moveObject[i].icon = 208;
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_JEEP)
+ {
+ m_moveObject[i].icon = 89;
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_TANK)
+ {
+ m_moveObject[i].icon = 167;
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_BALLE)
+ {
+ m_moveObject[i].icon = 176;
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_BULLET)
+ {
+ m_moveObject[i].icon = 177;
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ if (m_moveObject[i].type == TYPE_DRINK)
+ {
+ m_moveObject[i].icon = 178;
+ m_moveObject[i].channel = CHELEMENT;
+ }
+ m_moveObject[i].phase ++;
+ if (m_moveObject[i].phase > 32700)
+ {
+ m_moveObject[i].phase = 0;
+ }
+}
+
+void CDecor::DynamiteStart(int i, int dx, int dy)
+{
+ POINT posStart = m_moveObject[i].posStart;
+ posStart.x -= 34;
+ posStart.y -= 34;
+ posStart.x += dx;
+ posStart.y -= dy;
+ ObjectStart(posStart, TYPE_EXPLO1, 0);
+ if (dx == 0 && dy == 0)
+ {
+ PlaySound(SOUND_BOUM, posStart);
+ m_decorAction = 1;
+ m_decorPhase = 0;
+ }
+ RECT src;
+ src.left = posStart.x;
+ src.right = posStart.x + DIMOBJX * 2;
+ src.top = posStart.y;
+ src.bottom = posStart.y + DIMOBJY * 2;
+ POINT tinyPoint;
+ tinyPoint.y = posStart.y / DIMOBJY;
+ for (int j = 0; j < 2; j++)
+ {
+ tinyPoint.x = posStart.x / DIMOBJX;
+ for (int k = 0; k < 2; j++)
+ {
+ if (tinyPoint.x >= 0 && tinyPoint.x < MAXCELX && tinyPoint.y >= 0 && tinyPoint.y < MAXCELY)
+ {
+ int icon = m_decor[tinyPoint.x][tinyPoint.y].icon;
+ if (icon == 378 || icon == 379 || icon == 404 || icon == 410)
+ {
+ POINT pos;
+ pos.x = tinyPoint.x * DIMOBJX;
+ pos.y = tinyPoint.y * DIMOBJY;
+ ModifDecor(pos, -1);
+ }
+ }
+ tinyPoint.x++;
+ }
+ tinyPoint.y++;
+ }
+ for (i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ if (m_moveObject[i].type == TYPE_BOMBEDOWN ||
+ m_moveObject[i].type == TYPE_BOMBEUP ||
+ m_moveObject[i].type == TYPE_BOMBEFOLLOW1 ||
+ m_moveObject[i].type == TYPE_BOMBEFOLLOW2 ||
+ m_moveObject[i].type == TYPE_BULLDOZER ||
+ m_moveObject[i].type == TYPE_EGG ||
+ m_moveObject[i].type == TYPE_CAISSE ||
+ m_moveObject[i].type == TYPE_HELICO ||
+ m_moveObject[i].type == TYPE_BOMBEMOVE ||
+ m_moveObject[i].type == TYPE_POISSON ||
+ m_moveObject[i].type == TYPE_TOMATES ||
+ m_moveObject[i].type == TYPE_JEEP ||
+ m_moveObject[i].type == TYPE_OISEAU ||
+ m_moveObject[i].type == TYPE_SKATE ||
+ m_moveObject[i].type == TYPE_SHIELD ||
+ m_moveObject[i].type == TYPE_POWER ||
+ m_moveObject[i].type == TYPE_TANK ||
+ m_moveObject[i].type == TYPE_DRINK ||
+ m_moveObject[i].type == TYPE_BLUPIHELICO ||
+ m_moveObject[i].type == TYPE_BLUPITANK ||
+ m_moveObject[i].type == TYPE_GLU ||
+ m_moveObject[i].type == TYPE_INVERT ||
+ m_moveObject[i].type == TYPE_GUEPE ||
+ m_moveObject[i].type == TYPE_OVER ||
+ m_moveObject[i].type == TYPE_BRIDGE ||
+ m_moveObject[i].type == TYPE_CREATURE ||
+ m_moveObject[i].type == TYPE_BOMBEPERSO1 ||
+ m_moveObject[i].type == TYPE_BOMBEPERSO2 ||
+ m_moveObject[i].type == TYPE_BOMBEPERSO3 ||
+ m_moveObject[i].type == TYPE_BOMBEPERSO4)
+ {
+ RECT src2;
+ src2.left = m_moveObject[i].posCurrent.x;
+ src2.right = m_moveObject[i].posCurrent.x + 60;
+ src2.top = m_moveObject[i].posCurrent.y;
+ src2.bottom = m_moveObject[i].posCurrent.y + 20;
+ RECT tinyRect = { 0, 0, 0, 0 };
+ if (IntersectRect(&tinyRect, &src2, &src))
+ {
+ if (m_moveObject[i].type == TYPE_CAISSE)
+ {
+ SearchLinkCaisse(i, TRUE);
+ for (int L = 0; L < m_nbLinkCaisse; L++)
+ {
+ int channel = m_moveObject[m_linkCaisse[L]].channel;
+ int icon2 = m_moveObject[m_linkCaisse[L]].icon;
+ POINT posCurrent = m_moveObject[m_linkCaisse[L]].posCurrent;
+ m_moveObject[m_linkCaisse[L]].type = 0;
+ }
+ ObjectDelete(m_moveObject[i].posCurrent, m_moveObject[i].type);
+ UpdateCaisse();
+ }
+ else
+ {
+ ObjectDelete(m_moveObject[i].posCurrent, m_moveObject[i].type);
+ }
+ }
+ }
+ }
+ if (m_blupiFocus && !m_blupiShield && !m_blupiHide && !m_bSuperBlupi && m_blupiPos.x > posStart.x - 30 && m_blupiPos.x < posStart.x + 30 + DIMOBJX && m_blupiPos.y > posStart.y - 30 && m_blupiPos.y < posStart.y + 30 + DIMOBJY)
+ {
+ BlupiDead(ACTION_CLEAR1, -1);
+ m_blupiAir = TRUE;
+ }
+
+}
+
+int CDecor::AscenseurDetect(RECT rect, POINT oldpos, POINT newpos)
+{
+ if (m_blupiTimeNoAsc != 0)
+ {
+ return -1;
+ }
+ int dy = abs(newpos.y - oldpos.y);
+ int dirY = newpos.y < oldpos.y ? -1 : 1;
+
+ for (int i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ if (m_moveObject[i].type == TYPE_ASCENSEUR ||
+ m_moveObject[i].type == TYPE_ASCENSEURs ||
+ m_moveObject[i].type == TYPE_ASCENSEURsi)
+ {
+ RECT src;
+ src.left = m_moveObject[i].posCurrent.x;
+ src.right = m_moveObject[i].posCurrent.x + DIMOBJX;
+ src.top = m_moveObject[i].posCurrent.y;
+ src.bottom = m_moveObject[i].posCurrent.y + 16;
+ if (dy < (DIMBLUPIY / 2))
+ {
+ RECT dest = { 0, 0, 0, 0 };
+ if (IntersectRect(&dest, &src, &rect))
+ {
+ return i;
+ }
+ }
+ else
+ {
+ RECT src2 = rect;
+ src2.top -= dy / (DIMBLUPIY / 2) * (DIMBLUPIY / 2) * dirY;
+ src2.bottom -= dy / (DIMBLUPIY / 2) * (DIMBLUPIY / 2) * dirY;
+ for (int j = 0; j <= dy / (DIMBLUPIY / 2); j++)
+ {
+ RECT dest = { 0, 0, 0, 0 };
+ if (IntersectRect(&dest, &src, &src2))
+ {
+ return i;
+ }
+ src2.top += dirY * (DIMBLUPIY / 2);
+ src2.bottom += dy;
+ }
+ }
+
+ }
+ }
+ return -1;
+}
+
+void CDecor::AscenseurVertigo(int i, BOOL* pbVertigoLeft, BOOL* pbVertigoRight)
+{
+ *pbVertigoLeft = FALSE;
+
+ *pbVertigoRight = FALSE;
+ if (m_blupiPos.x + 20 + 4 < m_moveObject[i].posCurrent.x)
+ {
+ *pbVertigoLeft = TRUE;
+ }
+ if (m_blupiPos.x + DIMBLUPIX - 20 - 4 > m_moveObject[i].posCurrent.x + DIMOBJX)
+ {
+ *pbVertigoRight = TRUE;
+ }
+ if (AscenseurShift(i))
+ {
+ if (*pbVertigoLeft)
+ {
+ *pbVertigoLeft = FALSE;
+ *pbVertigoRight = TRUE;
+ m_blupiTimeNoAsc = 10;
+ return;
+ }
+ if (*pbVertigoRight)
+ {
+ *pbVertigoRight = FALSE;
+ *pbVertigoLeft = TRUE;
+ m_blupiTimeNoAsc = 10;
+ }
+ }
+}
+
+BOOL CDecor::AscenseurShift(int i)
+{
+ return i != -1 && m_moveObject[i].icon >= 311 && m_moveObject[i].icon <= 316;
+}
+
+void CDecor::AscenseurSynchro(int i)
+{
+ for (i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ m_moveObject[i].posCurrent = m_moveObject[i].posStart;
+ m_moveObject[i].step = STEP_STOPSTART;
+ m_moveObject[i].time = 0;
+ m_moveObject[i].phase = 0;
+ }
+}
+
+void CDecor::UpdateCaisse()
+{
+ m_nbRankCaisse = 0;
+ for (int i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ if (m_moveObject[i].type == TYPE_CAISSE)
+ {
+ m_rankCaisse[m_nbRankCaisse++] = i;
+ }
+ }
+}
+
+BOOL CDecor::TestPushCaisse(int i, POINT pos, BOOL bPop)
+{
+ POINT move;
+ int j;
+
+ move.x = pos.x - m_moveObject[i].posCurrent.x;
+ move.y = 0;
+ SearchLinkCaisse(i, bPop);
+ int y = m_moveObject[i].posCurrent.y;
+ for (j = 0; j < m_nbLinkCaisse; j++)
+ {
+ i = m_linkCaisse[j];
+ if (!TestPushOneCaisse(i, move, y))
+ {
+ return FALSE;
+ }
+ }
+ for (j = 0; j < m_nbLinkCaisse; j++)
+ {
+ i = m_linkCaisse[j];
+ int num = i;
+ m_moveObject[num].posCurrent.x = m_moveObject[num].posCurrent.x + move.x;
+ m_moveObject[num].posStart.x = m_moveObject[num].posStart.x + move.x;
+ int num2 = i;
+ m_moveObject[num].posEnd.x = m_moveObject[num].posEnd.x + move.x;
+ }
+ return TRUE;
+}
+
+BOOL CDecor::TestPushOneCaisse(int i, POINT move, int b)
+{
+ int num;
+ RECT rect;
+ num = m_moveObject[i].posCurrent.x + move.x;
+ rect.left = num;
+ rect.right = num + DIMOBJX;
+ rect.top = m_moveObject[i].posCurrent.y;
+ rect.bottom = m_moveObject[i].posCurrent.y + DIMOBJY;
+ if (DecorDetect(rect, FALSE))
+ {
+ return FALSE;
+ }
+ if (m_moveObject[i].posCurrent.y != b)
+ {
+ return TRUE;
+ }
+ rect.left = num;
+ rect.right = num + 20;
+ rect.top = m_moveObject[i].posCurrent.y + DIMOBJY;
+ rect.bottom = m_moveObject[i].posCurrent.y + DIMOBJY + 2;
+ if (!DecorDetect(rect))
+ {
+ return FALSE;
+ }
+ rect.left = num + DIMOBJX - 20;
+ rect.right = num + DIMOBJX;
+ rect.top = m_moveObject[i].posCurrent.y + DIMOBJY;
+ rect.bottom = m_moveObject[i].posCurrent.y + DIMOBJY + 2;
+ return DecorDetect(rect);
+}
+
+void CDecor::SearchLinkCaisse(int rank, BOOL bPop)
+{
+ m_nbLinkCaisse = 0;
+ AddLinkCaisse(rank);
+ POINT posCurrent = m_moveObject[rank].posCurrent;
+
+ BOOL flag;
+ do
+ {
+ flag = FALSE;
+ for (int i = 0; i < m_nbLinkCaisse; i++)
+ {
+ int num = m_linkCaisse[i];
+ if (m_moveObject[num].posCurrent.y <=
+ posCurrent.y && (!bPop || (m_moveObject
+ [num].posCurrent.x >= posCurrent.x - DIMOBJX / 2 &&
+ m_moveObject[num].posCurrent.x <=
+ posCurrent.x + DIMOBJX / 2)))
+ {
+ RECT src;
+ src.left = m_moveObject[num].posCurrent.x - 1;
+ src.top = m_moveObject[num].posCurrent.y - 1;
+ src.right = src.left + DIMOBJX + 1;
+ src.bottom = src.top + DIMOBJY + 1;
+ for (int j = 0; j < m_nbRankCaisse; j++)
+ {
+ int num2 = m_rankCaisse[j];
+ if (num2 != num && m_moveObject[num2].posCurrent.y <= posCurrent.y && (!bPop || (m_moveObject[num2].posCurrent.x >= posCurrent.x - 32 && m_moveObject[num2].posCurrent.x <= posCurrent.x + 32)))
+ {
+ RECT src2;
+ src2.left = m_moveObject[num2].posCurrent.x - 1;
+ src2.top = m_moveObject[num2].posCurrent.y - 1;
+ src2.right = src2.left + DIMOBJX + 1;
+ src2.bottom = src2.top + DIMOBJY + 1;
+ RECT tinyRect = { 0,0,0,0 };
+ if (IntersectRect(&tinyRect, &src2, &src) && AddLinkCaisse(num2))
+ {
+ flag = TRUE;
+ }
+ }
+ }
+ }
+ }
+ } while (flag);
+}
+
+BOOL CDecor::AddLinkCaisse(int rank)
+{
+ for (int i = 0; i < m_nbLinkCaisse; i++)
+ {
+ if (m_linkCaisse[i] == rank)
+ {
+ return FALSE;
+ }
+ }
+ m_linkCaisse[m_nbLinkCaisse] = rank;
+ m_nbLinkCaisse++;
+ return TRUE;
+}
+
+int CDecor::CaisseInFront()
+{
+ POINT tinyPoint;
+ if (m_blupiDir == DIR_LEFT)
+ {
+ tinyPoint.x = m_blupiPos.x + 16 - DIMOBJX / 2;
+ tinyPoint.y = m_blupiPos.y;
+ }
+ else
+ {
+ tinyPoint.x = m_blupiPos.x + DIMBLUPIX - 16 + DIMOBJX / 2;
+ tinyPoint.y = m_blupiPos.y;
+ }
+ for (int i = 0; i < m_nbRankCaisse; i++)
+ {
+ int num = m_rankCaisse[i];
+ if (tinyPoint.x > m_moveObject[num].posCurrent.x &&
+ tinyPoint.x < m_moveObject[num].posCurrent.x + DIMOBJX &&
+ tinyPoint.y > m_moveObject[num].posCurrent.y &&
+ tinyPoint.y < m_moveObject[num].posCurrent.y + DIMOBJY)
+ {
+ return num;
+ }
+ }
+ return -1;
+}
+
+int CDecor::CaisseGetMove(int max)
+{
+ max -= (m_nbLinkCaisse - 1) / 2;
+ if (max < 1)
+ {
+ max = 1;
+ }
+ if (m_blupiPower)
+ {
+ max *= 2;
+ }
+ if (m_blupiPhase < 20)
+ {
+ max = max * m_blupiPhase / 20;
+ if (max == 0)
+ {
+ max++;
+ }
+ }
+ return max;
+}
+
+int CDecor::MockeryDetect(POINT pos)
+{
+ if (m_blupiTimeMockery > 0)
+ {
+ return 0;
+ }
+ if (m_blupiAir)
+ {
+ POINT tinyPoint;
+ tinyPoint.x = pos.x + 30;
+ tinyPoint.y = pos.y + 30 + DIMOBJY;
+ if (tinyPoint.x >= 0 && tinyPoint.x < DIMOBJX*MAXCELX && tinyPoint.y >= 0 && tinyPoint.y < DIMOBJY*MAXCELY)
+ {
+ int icon = m_decor[tinyPoint.x / DIMOBJX][tinyPoint.y / DIMOBJY].icon;
+ if (icon == 68 || icon == 317)
+ {
+ return ACTION_MOCKERYi;
+ }
+ }
+ }
+ RECT src;
+ src.left = pos.x;
+ src.right = pos.x + DIMBLUPIX;
+ src.top = pos.y + 11;
+ src.bottom = pos.y + DIMBLUPIY;
+ if (m_blupiAir)
+ {
+ src.bottom += 90;
+ }
+ for (int i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ if (m_moveObject[i].type == TYPE_BOMBEDOWN ||
+ m_moveObject[i].type == TYPE_BOMBEMOVE ||
+ m_moveObject[i].type == TYPE_BOMBEFOLLOW1 ||
+ m_moveObject[i].type == TYPE_BOMBEFOLLOW2 ||
+ m_moveObject[i].type == TYPE_BULLDOZER ||
+ m_moveObject[i].type == TYPE_OISEAU ||
+ m_moveObject[i].type == TYPE_GUEPE ||
+ m_moveObject[i].type == TYPE_CREATURE ||
+ m_moveObject[i].type == TYPE_BALLE ||
+ m_moveObject[i].type == TYPE_BLUPIHELICO ||
+ m_moveObject[i].type == TYPE_BLUPITANK)
+ {
+ RECT src2;
+ src2.left = m_moveObject[i].posCurrent.x;
+ src2.right = m_moveObject[i].posCurrent.x + DIMBLUPIX;
+ src2.top = m_moveObject[i].posCurrent.y + 36;
+ src2.bottom = m_moveObject[i].posCurrent.y + DIMBLUPIY;
+ RECT tinyRect = { 0,0,0,0 };
+ if (IntersectRect(&tinyRect, &src2, &src))
+ {
+ if (m_moveObject[i].type == TYPE_CREATURE)
+ {
+ return ACTION_MOCKERYp;
+ }
+ if (m_blupiDir == DIR_RIGHT)
+ {
+ if (pos.x >= src2.left)
+ {
+ return ACTION_MOCKERYi;
+ }
+ if (m_moveObject[i].type == TYPE_BOMBEDOWN)
+ {
+ return 0;
+ }
+ return ACTION_MOCKERY;
+ }
+ else
+ {
+ if (pos.x < src2.left)
+ {
+ return ACTION_MOCKERYi;
+ }
+ if (m_moveObject[i].type == TYPE_BOMBEDOWN)
+ {
+ return 0;
+ }
+ return ACTION_MOCKERY;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+BOOL CDecor::BlupiElectro(POINT pos)
+{
+ if (m_phase == WM_PHASE_BUILD) return FALSE;
+ if (!m_blupiCloud) return FALSE;
+
+ RECT src;
+ src.left = pos.x + 16;
+ src.right = pos.x + DIMBLUPIX - 16;
+ src.top = pos.y + 11;
+ src.bottom = pos.y + DIMBLUPIY - 2;
+ RECT src2;
+ src2.left = m_blupiPos.x - 16 - 40;
+ src2.right = m_blupiPos.x + DIMBLUPIX + 16 + 40;
+ src2.top = m_blupiPos.y + 11 - 40;
+ src2.bottom = m_blupiPos.y + DIMBLUPIY - 2 + 40;
+ RECT tinyRect = { 0,0,0,0 };
+ return IntersectRect(&tinyRect, &src, &src2);
+}
+
+void CDecor::MoveObjectFollow(POINT pos)
+{
+ if (m_blupiHide) return;
+
+ RECT src = BlupiRect(pos);
+ src.left = pos.x + 16;
+ src.right = pos.x + DIMBLUPIX - 16;
+ for (int i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ if (m_moveObject[i].type == TYPE_BOMBEFOLLOW1)
+ {
+ RECT src2;
+ src2.left = m_moveObject[i].posCurrent.x - 100;
+ src2.right = m_moveObject[i].posCurrent.x + DIMBLUPIX + 100;
+ src2.top = m_moveObject[i].posCurrent.y - 100;
+ src2.bottom = m_moveObject[i].posCurrent.y + DIMBLUPIY + 100;
+ RECT tinyRect = { 0, 0, 0, 0 };
+ if (IntersectRect(&tinyRect, &src2, &src))
+ {
+ m_moveObject[i].type = TYPE_BOMBEFOLLOW2;
+ PlaySound(SOUND_FOLLOW, m_moveObject[i].posCurrent);
+ }
+ }
+ }
+}
+
+int CDecor::MoveObjectDetect(POINT pos, BOOL* pbNear)
+{
+ RECT src = BlupiRect(pos);
+ src.left = pos.x + 16;
+ src.right = pos.x + DIMBLUPIX - 16;
+ RECT src2;
+ src2.left = src.left - 20;
+ src2.right = src.right + 20;
+ src2.top = src.top - 40;
+ src2.bottom = src.bottom + 30;
+
+ for (int i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ if (m_moveObject[i].type != 0 &&
+ m_moveObject[i].type != TYPE_MAGICTRACK &&
+ m_moveObject[i].type != TYPE_SHIELDTRACK &&
+ m_moveObject[i].type != TYPE_TRESORTRACK &&
+ m_moveObject[i].type != TYPE_HIDETRACK &&
+ m_moveObject[i].type != TYPE_GLU &&
+ m_moveObject[i].type != TYPE_CLEAR &&
+ m_moveObject[i].type != TYPE_ELECTRO &&
+ (m_blupiAction != ACTION_PUSH && m_blupiAction != ACTION_POP) ||
+ m_moveObject[i].type != TYPE_HELICO)
+ {
+ RECT src3;
+ src3.left = m_moveObject[i].posCurrent.x + 16;
+ src3.right = m_moveObject[i].posCurrent.x + DIMBLUPIX - 16;
+ src3.top = m_moveObject[i].posCurrent.y + 36;
+ src3.bottom = m_moveObject[i].posCurrent.y + DIMBLUPIY;
+ if (m_moveObject[i].type == TYPE_BOMBEUP)
+ {
+ if (m_blupiAction == ACTION_DOWN)
+ {
+ continue;
+ }
+ src3.top = m_moveObject[i].posCurrent.y;
+ src3.bottom = m_moveObject[i].posCurrent.y + 69 - 36;
+ }
+ if (m_moveObject[i].type == TYPE_CAISSE)
+ {
+ src3.left = m_moveObject[i].posCurrent.x - 16;
+ src3.right = m_moveObject[i].posCurrent.x + DIMOBJX + 16;
+ src3.top = m_moveObject[i].posCurrent.y;
+ src3.bottom = m_moveObject[i].posCurrent.y + DIMOBJY;
+ if (m_blupiDir == DIR_LEFT)
+ {
+ src3.left += 20;
+ }
+ else
+ {
+ src3.right -= 20;
+ }
+ }
+ if (m_moveObject[i].type == TYPE_POISSON ||
+ m_moveObject[i].type == TYPE_OISEAU ||
+ m_moveObject[i].type == TYPE_GUEPE ||
+ m_moveObject[i].type == TYPE_CREATURE)
+ {
+ src3.top = m_moveObject[i].posCurrent.y + 16;
+ src3.bottom = m_moveObject[i].posCurrent.y + DIMBLUPIY - 16;
+ }
+ if (m_moveObject[i].type == TYPE_BALLE)
+ {
+ src3.left = m_moveObject[i].posCurrent.x + 24;
+ src3.right = m_moveObject[i].posCurrent.x + DIMBLUPIX - 24;
+ src3.top = m_moveObject[i].posCurrent.y + 10;
+ src3.bottom = m_moveObject[i].posCurrent.y + DIMBLUPIY - 32;
+ }
+ RECT rect = { 0, 0, 0, 0 };
+ if (IntersectRect(&rect, &src3, &src))
+ {
+ *pbNear = TRUE;
+ return i;
+ }
+ if (m_moveObject[i].type == TYPE_BOMBEDOWN && IntersectRect(&rect, &src3, &src2))
+ {
+ *pbNear = FALSE;
+ return i;
+ }
+ }
+ }
+ *pbNear = FALSE;
+ return -1;
+}
+
+int CDecor::MoveAscenseurDetect(POINT pos, int height)
+{
+ if (m_blupiTimeNoAsc != 0)
+ {
+ return -1;
+ }
+ RECT src;
+ src.left = pos.x + 12;
+ src.right = pos.x + DIMBLUPIX - 12;
+ src.top = pos.y + DIMBLUPIY - 2;
+ src.bottom = pos.y + DIMBLUPIY + height - 1;
+ for (int i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ if (m_moveObject[i].type == TYPE_ASCENSEUR || m_moveObject[i].type == TYPE_ASCENSEURs || m_moveObject[i].type == TYPE_ASCENSEURsi)
+ {
+ RECT src2;
+ src2.left = m_moveObject[i].posCurrent.x;
+ src2.right = m_moveObject[i].posCurrent.x + DIMOBJX;
+ src2.top = m_moveObject[i].posCurrent.y;
+ src2.bottom = m_moveObject[i].posCurrent.y + 16;
+ RECT tinyRect = { 0, 0, 0, 0 };
+ if (IntersectRect(&tinyRect, &src2, &src))
+ {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+int CDecor::MoveChargeDetect(POINT pos)
+{
+ RECT src;
+ src.left = pos.x + 16;
+ src.right = pos.x + DIMBLUPIX - 16;
+ src.top = pos.y + 11;
+ src.bottom = pos.y + DIMBLUPIY - 2;
+ for (int i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ if (m_moveObject[i].type == TYPE_CHARGE)
+ {
+ RECT src2;
+ src2.left = m_moveObject[i].posCurrent.x - 10;
+ src2.right = m_moveObject[i].posCurrent.x + DIMBLUPIX + 10;
+ src2.top = m_moveObject[i].posCurrent.y + 36;
+ src2.bottom = m_moveObject[i].posCurrent.y + DIMBLUPIY;
+ RECT tinyRect = { 0, 0, 0, 0 };
+ if (IntersectRect(&tinyRect, &src2, &src))
+ {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+int CDecor::MovePersoDetect(POINT pos)
+{
+ RECT src;
+ if (m_phase == WM_PHASE_BUILD) return -1;
+ src.left = pos.x + 16;
+ src.right = pos.x + DIMBLUPIX - 16;
+ src.top = pos.y + 11;
+ src.bottom = pos.y + DIMBLUPIY - 2;
+ for (int i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ if (m_moveObject[i].type >= TYPE_BOMBEPERSO1 && m_moveObject[i].type <= TYPE_BOMBEPERSO4)
+ {
+ RECT src2;
+ src2.left = m_moveObject[i].posCurrent.x - 16;
+ src2.right = m_moveObject[i].posCurrent.x + DIMBLUPIX + 16;
+ src2.top = m_moveObject[i].posCurrent.y + 36;
+ src2.bottom = m_moveObject[i].posCurrent.y + DIMBLUPIY;
+ RECT tinyRect = { 0, 0, 0, 0 };
+ if (IntersectRect(&tinyRect, &src2, &src))
+ {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+int CDecor::MoveBalleDetect(POINT pos)
+{
+ RECT rcSrc1, rcSrc2;
+ tagRECT rcDst;
+ int i;
+ if (m_phase == WM_PHASE_BUILD)
+ return -1;
+ rcSrc2.right = pos.x + DIMBLUPIX - 16;
+ rcSrc2.left = pos.x + 20;
+ rcSrc2.top = pos.y + 10;
+ rcSrc2.bottom = pos.y + 28;
+ for (i = 0; i < MAXMOVEOBJECT - 1; i++)
+ {
+ if (m_moveObject->type == TYPE_BULLDOZER ||
+ m_moveObject->type == TYPE_POISSON ||
+ m_moveObject->type == TYPE_OISEAU ||
+ m_moveObject->type == TYPE_GUEPE ||
+ m_moveObject->type == TYPE_BLUPIHELICO ||
+ m_moveObject->type == TYPE_BLUPITANK)
+ {
+ rcSrc1.right = m_moveObject->posCurrent.x + DIMBLUPIX - 16;
+ rcSrc1.left = m_moveObject->posCurrent.x + 16;
+ rcSrc1.bottom = m_moveObject->posCurrent.y + DIMBLUPIY - 10;
+ rcSrc1.top = m_moveObject->posCurrent.y + 16;
+ rcDst = RECT( 0, 0, 0, 0 );
+ if (IntersectRect(&rcDst, &rcSrc1, &rcSrc2))
+ return i;
+ }
+ }
+ return -1;
+}
+
+int CDecor::MoveObjectDelete(POINT cel)
+{
+ int result = -1;
+ for (int i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ if (m_moveObject[i].type != 0)
+ {
+ if (cel.x == m_moveObject[i].posStart.x / DIMOBJX && cel.y == m_moveObject[i].posStart.y / DIMOBJY)
+ {
+ result = m_moveObject[i].type;
+ m_moveObject[i].type = 0;
+ }
+ else if (cel.x == m_moveObject[i].posEnd.x / DIMOBJX && cel.y == m_moveObject[i].posEnd.y / DIMOBJY)
+ {
+ result = m_moveObject[i].type;
+ m_moveObject[i].type = 0;
+ }
+ }
+ }
+ return result;
+}
+
+int CDecor::MoveObjectFree()
+{
+ for (int i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ if (m_moveObject[i].type == 0)
+ {
+ ZeroMemory(&m_moveObject[i], sizeof(MoveObject));
+ return i;
+ }
+ }
+ return -1;
+}
+
+int CDecor::SortGetType(int type)
+{
+ if (type == TYPE_BOMBEDOWN ||
+ type == TYPE_BOMBEUP ||
+ type == TYPE_BOMBEFOLLOW1 ||
+ type == TYPE_BOMBEFOLLOW2)
+ {
+ return 1;
+ }
+ if (type == TYPE_CAISSE)
+ {
+ return 2;
+ }
+ return 3;
+}
+
+void CDecor::MoveObjectSort()
+{
+ MoveObject dst;
+ int i;
+ int num = 0;
+
+ for (i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ if (m_moveObject[i].type != 0)
+ {
+ MoveObjectCopy(&m_moveObject[num++], &m_moveObject[i]);
+ }
+ }
+ for (i = num; i < MAXMOVEOBJECT; i++)
+ {
+ m_moveObject[i].type = 0;
+ }
+ if (num <= 1)
+ {
+ return;
+ }
+ BOOL flag;
+ do
+ {
+ flag = FALSE;
+ for (i = 0; i < num - 1; i++)
+ {
+ if (SortGetType(m_moveObject[i].type) > SortGetType(m_moveObject[i + 1].type))
+ {
+ MoveObjectCopy(&dst, &m_moveObject[i]);
+ MoveObjectCopy(&m_moveObject[i], &m_moveObject[i + 1]);
+ MoveObjectCopy(&m_moveObject[i + 1], &dst);
+ flag = TRUE;
+ }
+ }
+ } while (flag);
+ UpdateCaisse();
+ m_nbLinkCaisse = 0;
+}
+
+void CDecor::MoveObjectPriority(int rank)
+{
+ MoveObject tempMob;
+ int i;
+ if (rank)
+ {
+ for (i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ if (m_moveObject[i].type == TYPE_BALLE) return;
+ }
+ if (i <= rank)
+ {
+ MoveObjectCopy(&tempMob, &m_moveObject[rank]);
+ MoveObjectCopy(&m_moveObject[rank], &m_moveObject[i]);
+ MoveObjectCopy(&m_moveObject[i], &tempMob);
+ if (m_moveObject[rank].type == TYPE_CAISSE || m_moveObject[i].type == TYPE_CAISSE)
+ {
+ UpdateCaisse();
+ }
+ }
+ }
+}
+
+int CDecor::MoveObjectSearch(POINT pos, int type)
+{
+ for (int i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ if (m_moveObject[i].type != 0 && (type == -1 ||
+ m_moveObject[i].type == type))
+ {
+ if (m_moveObject[i].type == TYPE_BALLE &&
+ m_moveObject[i].posStart.x != m_moveObject[i].posEnd.x)
+ {
+ if (m_moveObject[i].posCurrent.x >= pos.x - 100 &&
+ m_moveObject[i].posCurrent.x <= pos.x + 100 &&
+ m_moveObject[i].posCurrent.y == pos.y)
+ {
+ return i;
+ }
+ }
+ else if (m_moveObject[i].type == TYPE_BALLE &&
+ m_moveObject[i].posStart.y != m_moveObject[i].posEnd.y)
+ {
+ if (m_moveObject[i].posCurrent.y >= pos.y - 100 &&
+ m_moveObject[i].posCurrent.y <= pos.y + 100 &&
+ m_moveObject[i].posCurrent.x == pos.x)
+ {
+ return i;
+ }
+ }
+ else if (m_moveObject[i].posCurrent.x == pos.x &&
+ m_moveObject[i].posCurrent.y == pos.y)
+ {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
diff --git a/src/decnet.cpp b/src/decnet.cpp
new file mode 100644
index 0000000..6dfb509
--- /dev/null
+++ b/src/decnet.cpp
@@ -0,0 +1,464 @@
+// DecNet.cpp
+//
+
+#include "def.h"
+#include "decor.h"
+#include "misc.h"
+#include "network.h"
+
+void CDecor::NetStopCloud(int rank)
+{
+ NetMessage msg;
+
+ msg.type = MESS_STOPCLOUD;
+ msg.data1 = 0;
+ msg.data2 = 0;
+ msg.data3 = 0;
+ msg.data4 = rank;
+ NetMessagePush(&msg);
+ return;
+}
+
+void CDecor::NetPlaySound(short channel, POINT pos)
+{
+ NetMessage msg;
+
+ msg.type = MESS_PLAYSOUND;
+ msg.data1 = 0;
+ msg.data2 = pos.x;
+ msg.data3 = pos.y;
+ msg.data4 = channel;
+ NetMessagePush(&msg);
+ return;
+}
+
+void CDecor::NetStopSound(short channel)
+{
+ NetMessage msg;
+
+ msg.type = MESS_STOPSOUND;
+ msg.data1 = 0;
+ msg.data2 = 0;
+ msg.data3 = 0;
+ msg.data4 = channel;
+ NetMessagePush(&msg);
+}
+
+void CDecor::NetDataFlush()
+{
+ for (int i = 0; i < MAXNETPLAYER; i++)
+ {
+ m_netBlupiPos[i].x = 0;
+ m_netBlupiPos[i].y = 0;
+ m_netBlupiIcon[i] = -1;
+ m_netBlupiSec[i] = 0;
+ m_netBlupiTransport[i] = 0;
+ m_netTransports[i] = 0;
+ m_netTimes[i] = 0;
+ m_netPrevTimes[i] = 0;
+ m_netTimeSincePacket[i] = 0;
+ m_netVitesses[i].x = 0;
+ m_netVitesses[i].y = 0;
+ m_netBlupiPrevPos[i].x = 0;
+ m_netBlupiPrevPos[i].y = 0;
+ }
+ m_netPacketsSent = 0;
+ m_netPacketsSent2 = 0;
+ m_netPacketsReceived = 0;
+ m_netPacketsReceived2 = 0;
+ m_netPacketIcon = -1;
+ NetMessageIndexFlush();
+}
+
+void CDecor::NetSendBarePacket(BYTE type, short num)
+{
+ char data[4];
+ data[0] = 4;
+ data[1] = type;
+ data[2] = num & 0xff;
+ data[3] = num >> 8;
+ m_pNetwork->Send(&data, 4, DPSEND_GUARANTEED);
+ return;
+}
+
+void CDecor::TreatNetData()
+{
+ NetPacket pack;
+ NetMessage* pMsg;
+ int i, j, dt;
+ int flag = 0;
+ int player;
+ int foo;
+ char res[100];
+ char text[100];
+
+ BOOL recentSenders[MAXNETPLAYER];
+
+ if ((m_netMessageIndex1 != 0 ||
+ m_blupiIcon != m_netPacketIcon ||
+ m_blupiPos != m_netPacketPos) &&
+ !m_bNetPacked || m_time % 2 == 0)
+ {
+ m_netPacketPos = m_blupiPos;
+ m_netPacketIcon = m_blupiIcon;
+ pack.time = m_time;
+ pack.keyPress = m_keyPress;
+ pack.blupiPosX = m_blupiPos.x;
+ pack.blupiPosY = m_blupiPos.y;
+ pack.blupiIcon = m_blupiIcon;
+ pack.size = sizeof(pack);
+ pack.type = 1;
+ pack.blupiSec = m_blupiSec;
+ pack.blupiChannel = m_blupiChannel;
+ pack.blupiTransport = m_blupiTransport;
+ pack.nbMessages = 0;
+ for (i = 0; i < MAXMESSAGEPERPACKET; i++)
+ {
+ if (!NetMessagePop(&pack.messages[i]))
+ {
+ break;
+ }
+ pack.nbMessages++;
+ if (pack.messages[i].type == MESS_OBJECTSTART ||
+ pack.messages[i].type == MESS_OBJECTDELETE)
+ {
+ if (pack.messages[i].data4 != TYPE_EXPLO1 &&
+ pack.messages[i].data4 != TYPE_EXPLO2 &&
+ pack.messages[i].data4 != TYPE_EXPLO3 &&
+ pack.messages[i].data4 != TYPE_EXPLO4 &&
+ pack.messages[i].data4 != TYPE_EXPLO5 &&
+ pack.messages[i].data4 != TYPE_EXPLO6 &&
+ pack.messages[i].data4 != TYPE_EXPLO7 &&
+ pack.messages[i].data4 != TYPE_EXPLO8 &&
+ pack.messages[i].data4 != TYPE_EXPLO9 &&
+ pack.messages[i].data4 != TYPE_EXPLO10 &&
+ pack.messages[i].data4 != TYPE_SPLOUTCH1 &&
+ pack.messages[i].data4 != TYPE_SPLOUTCH2 &&
+ pack.messages[i].data4 != TYPE_SPLOUTCH3 &&
+ pack.messages[i].data4 != TYPE_TENTACULE &&
+ pack.messages[i].data4 != TYPE_PLOUF &&
+ pack.messages[i].data4 != TYPE_BLUP &&
+ pack.messages[i].data4 != TYPE_MAGICTRACK &&
+ pack.messages[i].data4 != TYPE_SHIELDTRACK &&
+ pack.messages[i].data4 != TYPE_TRESORTRACK &&
+ pack.messages[i].data4 != TYPE_TIPLOUF &&
+ pack.messages[i].data4 != TYPE_INVERTSTART &&
+ pack.messages[i].data4 != TYPE_INVERTSTOP &&
+ pack.messages[i].data4 != TYPE_POLLUTION)
+ {
+ flag = 1;
+ }
+ }
+ }
+ pack.unk12 = flag;
+ m_pNetwork->Send(&pack, sizeof(NetMessage) * pack.nbMessages + 20, flag);
+ m_netPacketsSent++;
+ if (flag) m_netPacketsSent2++;
+ }
+
+ ZeroMemory(&recentSenders, sizeof(recentSenders));
+
+ for (i = 0; i < 10; i++)
+ {
+ if (!m_pNetwork->Receive(&pack, sizeof(pack), (LPDWORD)&player))
+ {
+ break;
+ }
+
+ if (pack.type == 1)
+ {
+ m_netPacketsReceived++;
+ if (pack.unk12) m_netPacketsReceived2++;
+
+ if (player < MAXNETPLAYER)
+ {
+ if (pack.time > m_netTimes[player])
+ {
+ m_netPrevTimes[player] = m_netTimes[player];
+ recentSenders[player] = TRUE;
+ m_netTimes[player] = pack.time;
+ m_netBlupiPos[player].x = pack.blupiPosX;
+ m_netBlupiPos[player].y = pack.blupiPosY;
+ m_netBlupiIcon[player] = pack.blupiIcon;
+ m_netBlupiSec[player] = pack.blupiSec;
+ m_netBlupiTransport[player] = pack.blupiTransport;
+ dt = pack.time - m_netPrevTimes[player];
+ if (dt <= 0)
+ {
+ m_netVitesses[player] = POINT(0, 0);
+ }
+ else
+ {
+ m_netVitesses[player] = (m_netBlupiPos[player] - m_netBlupiPrevPos[player]) / dt;
+ }
+ m_netBlupiPrevPos[player] = m_netBlupiPos[player];
+ m_netTimeSincePacket[player] = 0;
+ }
+ }
+ for (j = 0; j < pack.nbMessages; j++)
+ {
+ pMsg = &pack.messages[j];
+ switch (pMsg->type)
+ {
+ case MESS_OBJECTSTART:
+ ObjectStart(POINT(pMsg->data2, pMsg->data3), pMsg->data4, pMsg->data1, FALSE);
+ break;
+ case MESS_OBJECTDELETE:
+ ObjectDelete(POINT(pMsg->data2, pMsg->data3), pMsg->data4, FALSE);
+ break;
+ case MESS_MODIFDECOR:
+ ModifDecor(POINT(pMsg->data2, pMsg->data3), pMsg->data4, FALSE);
+ break;
+ case MESS_PLAYSOUND:
+ m_pSound->PlayImage(pMsg->data4, POINT(pMsg->data2, pMsg->data3) - m_posDecor, -1);
+ break;
+ case MESS_STOPSOUND:
+ m_pSound->StopSound(pMsg->data4);
+ break;
+ case MESS_ASCENSEURSTART:
+ NetAscenseurSynchro(pMsg->data4, STEP_STOPSTART);
+ break;
+ case MESS_ASCENSEUREND:
+ NetAscenseurSynchro(pMsg->data4, STEP_STOPEND);
+ break;
+ case MESS_STOPCLOUD:
+ if (pMsg->data4 == m_team)
+ {
+ m_blupiCloud = FALSE;
+ m_jauges[JAUGE_POWER].SetHide(TRUE);
+ }
+ break;
+ }
+ }
+ }
+ if (pack.type == PK_LEAVE)
+ {
+ LoadString(257, res, 100);
+ sprintf(text, res, m_pNetwork->m_players[player].name);
+ NotifPush(text);
+ m_pNetwork->m_players[player].bIsPresent = 0;
+ m_netBlupiIcon[player] = -1;
+ }
+ if (pack.type == PK_LOST)
+ {
+ LoadString(258, res, 100);
+ sprintf(text, res, m_pNetwork->m_players[player].name);
+ NotifPush(text);
+ m_pNetwork->m_players[player].bIsPresent = 0;
+ m_netBlupiIcon[player] = -1;
+ }
+ if (pack.type == PK_DIE)
+ {
+ if (pack.keyPress == 0)
+ {
+ LoadString(261, res, 100);
+ }
+ else if (pack.keyPress == 1)
+ {
+ LoadString(260, res, 100);
+ }
+ else
+ {
+ LoadString(259, res, 100);
+ }
+ sprintf(text, res, m_pNetwork->m_players[player].name, pack.keyPress);
+ NotifPush(text);
+ }
+ if (pack.type == PK_PAUSE)
+ {
+ m_bPause = pack.keyPress;
+ }
+ }
+
+ for (i = 0; i < MAXNETPLAYER; i++)
+ {
+ if (!recentSenders[i])
+ {
+ DoNetSmooth(i);
+ }
+ }
+}
+
+void CDecor::DoNetSmooth(int player)
+{
+ POINT start, end;
+ RECT rect;
+
+ if (m_bNetMovePredict && m_netBlupiIcon[player] != -1)
+ {
+ if (m_netTimeSincePacket[player] < 5)
+ {
+ start = m_netBlupiPos[player];
+ end = start + m_netVitesses[player];
+ rect = RECT(start.x + 12, start.y + 11, start.x + DIMBLUPIX - 12, start.y + DIMBLUPIY - 2);
+ TestPath(rect, start, &end);
+ m_netBlupiPos[player] = end;
+ }
+ m_netTimeSincePacket[player]++;
+ }
+}
+
+void CDecor::NetAdjustToLift()
+{
+ for (int i = 0; i < MAXNETPLAYER; i++)
+ {
+ if (m_netBlupiPos[i].x != -1 && m_netTransports[i] >= 0 && m_netTransports[i] < MAXMOVEOBJECT)
+ {
+ m_netBlupiPos[i].y = m_moveObject[m_netTransports[i]].posCurrent.y - (DIMBLUPIY - 2);
+ }
+ }
+}
+
+void CDecor::NetAscenseurSynchro(int index, short step)
+{
+ int i;
+ POINT delta;
+ MoveObject* otherMob;
+ MoveObject* mob = &m_moveObject[index];
+
+ mob->step = step;
+ mob->time = 0;
+ delta.x = abs(mob->posEnd.x - mob->posStart.x);
+ delta.y = abs(mob->posEnd.y - mob->posStart.y);
+
+ for (i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ otherMob = &m_moveObject[i];
+ if (i != index && otherMob->type == mob->type)
+ {
+ if (otherMob->stepAdvance == mob->stepAdvance &&
+ otherMob->stepRecede == mob->stepRecede &&
+ otherMob->timeStopStart == mob->timeStopStart &&
+ otherMob->timeStopEnd == mob->timeStopEnd)
+ {
+ otherMob->step = step;
+ otherMob->time = 0;
+ }
+ }
+ }
+}
+
+
+void CDecor::NetPlayerCollide(POINT pos, int* out)
+{
+ int i;
+ RECT rect1;
+ RECT rect2;
+ RECT rect3;
+
+ rect2.left = pos.x + 16;
+ rect2.top = pos.y + 11;
+ rect2.right = pos.x + DIMBLUPIX - 16;
+ rect2.bottom = pos.y + DIMBLUPIY - 2;
+
+ for (i = 0; i < MAXNETPLAYER; i++)
+ {
+ if (m_netBlupiIcon[i] != -1)
+ {
+ if (m_netBlupiSec[i] != SEC_HIDE)
+ {
+ rect1.left = m_netBlupiPos[i].x + 16;
+ rect1.top = m_netBlupiPos[i].y + 11;
+ rect1.right = m_netBlupiPos[i].x + DIMBLUPIX - 16;
+ rect1.bottom = m_netBlupiPos[i].y + DIMBLUPIY - 2;
+ }
+ if (IntersectRect(&rect3, &rect1, &rect2))
+ {
+ *out = i;
+ }
+ }
+ }
+ *out = -1;
+}
+
+void CDecor::NetMessageIndexFlush()
+{
+ m_netMessageIndex1 = 0;
+ m_netMessageIndex2 = 0;
+ m_netMessageIndex3 = 0;
+ return;
+}
+
+BOOL CDecor::NetMessagePush(NetMessage* message)
+{
+ NetMessage* messages;
+ BYTE data;
+ short pos;
+ int i;
+
+ if (m_netMessageIndex1 == MAXNETMESSAGE) return FALSE;
+
+ CopyMemory(&m_netMessages[m_netMessageIndex2], message, sizeof(NetMessage));
+ m_netMessageIndex1++;
+ m_netMessageIndex2++;
+ if (m_netMessageIndex2 == MAXNETMESSAGE)
+ {
+ m_netMessageIndex2 = 0;
+ }
+ return TRUE;
+}
+
+BOOL CDecor::NetMessagePop(NetMessage* out_msg)
+{
+ int i;
+
+ if (m_netMessageIndex1 == 0) return FALSE;
+
+ CopyMemory(out_msg, &m_netMessages[m_netMessageIndex3], sizeof(NetMessage));
+ m_netMessageIndex1--;
+ m_netMessageIndex3++;
+ if (m_netMessageIndex3 == MAXNETMESSAGE)
+ {
+ m_netMessageIndex3 = 0;
+ }
+ return TRUE;
+}
+
+void CDecor::NotifFlush()
+{
+ for (int i = 0; i < MAXNOTIF; i++)
+ {
+ m_notifText[i][0] = '\0';
+ }
+
+ m_notifTime = 0;
+}
+
+void CDecor::NotifPop()
+{
+ for (int i = MAXNOTIF; i > 0; --i)
+ {
+ //strcpy()
+ m_notifText[MAXNOTIF - 1][0] = '\0';
+ m_notifTime = NOTIFDELAY; // idk
+ }
+}
+
+void CDecor::NotifPush(char *str)
+{
+ int i;
+ for (i = 0; i < MAXNOTIF; i++)
+ {
+ if (m_notifText[i][0] != '\0') break;
+ }
+ if (i >= MAXNOTIF)
+ {
+ NotifPop();
+ i = MAXNOTIF - 1;
+ }
+ strcpy(m_notifText[i], str);
+ m_notifTime = NOTIFDELAY;
+ m_pSound->PlayImage(SOUND_TRESOR, POINT( LXIMAGE / 2, LYIMAGE / 2 ), -1);
+}
+
+void CDecor::NotifStep()
+{
+ if (m_notifTime == 0)
+ {
+ NotifPop();
+ }
+ else {
+ m_notifTime--;
+ }
+}
+
diff --git a/src/decor.cpp b/src/decor.cpp
new file mode 100644
index 0000000..9d32896
--- /dev/null
+++ b/src/decor.cpp
@@ -0,0 +1,2042 @@
+// Decor.cpp
+//
+
+//#include
+//#include
+//#include
+//#include
+#include
+#include "def.h"
+//#include "resource.h"
+#include "pixmap.h"
+#include "sound.h"
+#include "decor.h"
+#include "text.h"
+#include "misc.h"
+#include "event.h"
+#include "dectables.h"
+#include "jauge.h"
+//#include "network.h"
+
+///////////////////////////////////////////////////////////////////////////////
+
+// Constructor
+
+CDecor::CDecor()
+{
+ int i;
+
+ // FUN_2bd90(m_jauges, sizeof(CJauge), 2, CJauge::CJauge);
+ m_hWnd = NULL;
+ m_pSound = NULL;
+ m_pPixmap = NULL;
+
+ for (i = 0; i < 200; i++)
+ {
+ m_lastDecorIndexes[i] = 0;
+ }
+ m_lastRegion = -1;
+ m_iconLift = 0;
+ m_time = 0;
+ m_bCheatDoors = FALSE;
+ m_bSuperBlupi = FALSE;
+ m_bDrawSecret = FALSE;
+ m_bBuildOfficialMissions = FALSE;
+ m_bNetPacked = FALSE;
+ m_bNetMovePredict = TRUE;
+ m_bNetDebug = FALSE;
+ m_bMulti = FALSE;
+ m_team = 0;
+ m_netPacketsSent = 0;
+ m_netPacketsSent2 = 0;
+ m_netPacketsReceived = 0;
+ m_netPacketsReceived2 = 0;
+}
+
+CDecor::~CDecor()
+{
+ // FUN_2be30(m_jauges, sizeof(CJauge), 2, OutputDebug);
+}
+
+void CDecor::Create(HWND hWnd, CSound* pSound, CPixmap* pPixmap, CNetwork* pNetwork)
+{
+ POINT pos;
+
+ m_hWnd = hWnd;
+ m_pSound = pSound;
+ m_pPixmap = pPixmap;
+ m_pNetwork = pNetwork;
+ m_keyPress = 0;
+ m_lastKeyPress = 0;
+ m_bJoystick = FALSE;
+ m_bHelicoMarch = FALSE;
+ m_bHelicoStop = FALSE;
+ m_bJeepMarch = FALSE;
+ m_bJeepStop = FALSE;
+ InitDecor();
+
+ m_jauges[JAUGE_AIR].Create(m_hWnd, m_pPixmap, m_pSound, POINT( 169, 450 ), 1, FALSE);
+ m_jauges[JAUGE_AIR].SetHide(TRUE);
+ m_jauges[JAUGE_POWER].Create(m_hWnd, m_pPixmap, m_pSound, POINT( 171, 450 ), 3, FALSE);
+ m_jauges[JAUGE_POWER].SetHide(TRUE);
+ NetMessageIndexFlush();
+ NotifFlush();
+}
+
+BOOL CDecor::LoadImages()
+{
+ POINT totalDim = { LXIMAGE, LYIMAGE };
+ POINT iconDim = { 0, 0 };
+ char filename[52];
+
+ if (m_lastRegion == m_region) return TRUE;
+ m_lastRegion = m_region;
+
+ sprintf(filename, "decor%.3d.blp", m_region);
+
+ return m_pPixmap->BackgroundCache(CHDECOR, filename, totalDim, iconDim, FALSE);
+}
+
+void CDecor::InitGamer()
+{
+ m_nbVies = 3;
+ FillMemory(m_doors, sizeof(m_doors), 1);
+}
+
+void CDecor::InitDecor()
+{
+ int i;
+ m_posDecor = POINT( 0, 0 );
+ m_dimDecor = POINT( 100, 100 );
+ m_music = 1;
+ m_region = 2;
+ m_missionTitle[0] = '\0';
+ m_decorAction = 0;
+ for (int x = 0; x < MAXCELX; x++)
+ {
+ for (int y = 0; y < MAXCELY; y++)
+ {
+ m_decor[x][y].icon = -1;
+ m_bigDecor[x][y].icon = -1;
+ }
+ }
+ m_decor[3][4].icon = 40;
+ m_decor[4][4].icon = 38;
+ m_decor[5][4].icon = 39;
+ for (int k = MAXMOVEOBJECT; k != 0; k--)
+ {
+ m_moveObject[k].type = 0;
+ }
+ FlushBalleTraj();
+ FlushMoveTraj();
+ m_moveObject[0].type = TYPE_TRESOR;
+ m_moveObject[0].stepAdvance = 1;
+ m_moveObject[0].stepRecede = 1;
+ m_moveObject[0].timeStopStart = 0;
+ m_moveObject[0].timeStopEnd = 0;
+ m_moveObject[0].posStart = POINT( 258, 196 );
+ m_moveObject[0].posEnd = m_moveObject[0].posStart;
+ m_moveObject[0].posCurrent = m_moveObject[0].posStart;
+ m_moveObject[0].phase = 0;
+ m_moveObject[0].step = STEP_STOPSTART;
+ m_moveObject[0].time = 0;
+ m_moveObject[0].channel = CHELEMENT;
+ m_moveObject[0].icon = 0;
+
+ m_moveObject[1].type = TYPE_GOAL;
+ m_moveObject[1].stepAdvance = 1;
+ m_moveObject[1].timeStopStart = 0;
+ m_moveObject[1].timeStopEnd = 0;
+ m_moveObject[1].posStart = POINT( 322, 196 );
+ m_moveObject[1].posEnd = m_moveObject[1].posStart;
+ m_moveObject[1].posCurrent = m_moveObject[1].posStart;
+ m_moveObject[1].phase = 0;
+ m_moveObject[1].step = STEP_STOPSTART;
+ m_moveObject[1].time = 0;
+ m_moveObject[1].channel = CHELEMENT;
+ m_moveObject[1].icon = 29;
+ for (i = 0; i < MAXFIFOPOS; i++)
+ {
+ m_blupiFifoPos[i] = POINT( 0, 0 );
+ }
+ for (i = 0; i < MAXNETPLAYER; i++)
+ {
+ m_blupiStartPos[i] = POINT( 194, 192 + BLUPIOFFY );
+ m_blupiStartDir[i] = DIR_RIGHT;
+ }
+ m_blupiAction = ACTION_STOP;
+ m_blupiPhase = 0;
+ m_blupiIcon = 0;
+ m_blupiChannel = CHBLUPI;
+ m_blupiFocus = TRUE;
+ m_blupiAir = FALSE;
+ m_blupiHelico = FALSE;
+ m_blupiOver = FALSE;
+ m_blupiJeep = FALSE;
+ m_blupiTank = FALSE;
+ m_blupiSkate = FALSE;
+ m_blupiNage = FALSE;
+ m_blupiSurf = FALSE;
+ m_blupiSuspend = FALSE;
+ m_blupiJumpAie = FALSE;
+ m_blupiShield = FALSE;
+ m_blupiPower = FALSE;
+ m_blupiCloud = FALSE;
+ m_blupiHide = FALSE;
+ m_blupiInvert = FALSE;
+ m_blupiBalloon = FALSE;
+ m_blupiEcrase = FALSE;
+ m_blupiPosHelico.x = -1;
+ m_blupiActionOuf = 0;
+ m_blupiTimeNoAsc = 0;
+ m_blupiTimeMockery = 0;
+ m_blupiVitesse = POINT( 0, 0 );
+ m_blupiValidPos = m_blupiStartPos[0];
+ m_blupiEnergyUnused = 100;
+ m_blupiFront = FALSE;
+ m_blupiBullet = 0;
+ m_blupiCle = 0;
+ m_blupiPerso = 0;
+ m_blupiDynamite = 0;
+ m_nbTresor = 0;
+ m_totalTresor = 1;
+ m_goalPhase = 0;
+ m_scrollPoint = m_blupiStartPos[0];
+ m_scrollAdd.x = 0;
+ m_scrollAdd.y = 0;
+ m_term = 0;
+ m_2ndPositionCalculationSlot = -1;
+}
+
+void CDecor::SetTime(int time)
+{
+ m_time = time;
+}
+
+int CDecor::GetTime()
+{
+ return m_time;
+}
+
+void CDecor::PlayPrepare(BOOL bTest)
+{
+ if (bTest) m_nbVies = 3;
+
+ if (m_bMulti)
+ {
+ m_nbVies = 10;
+ m_blupiPos = m_blupiStartPos[m_team];
+ m_blupiDir = m_blupiStartDir[m_team];
+ }
+ else
+ {
+ m_blupiPos = m_blupiStartPos[0];
+ m_blupiDir = m_blupiStartDir[0];
+ }
+
+ if (m_blupiDir == DIR_LEFT)
+ {
+ m_blupiIcon = 4;
+ }
+ else
+ {
+ m_blupiIcon = 0;
+ }
+
+ m_blupiAction = ACTION_STOP;
+ m_blupiPhase = 0;
+ m_blupiFocus = TRUE;
+ m_blupiAir = FALSE;
+ m_blupiHelico = FALSE;
+ m_blupiOver = FALSE;
+ m_blupiJeep = FALSE;
+ m_blupiTank = FALSE;
+ m_blupiSkate = FALSE;
+ m_blupiNage = FALSE;
+ m_blupiSurf = FALSE;
+ m_blupiSuspend = FALSE;
+ m_blupiJumpAie = FALSE;
+ m_blupiShield = FALSE;
+ m_blupiPower = FALSE;
+ m_blupiCloud = FALSE;
+ m_blupiHide = FALSE;
+ m_blupiInvert = FALSE;
+ m_blupiBalloon = FALSE;
+ m_blupiEcrase = FALSE;
+ m_blupiActionOuf = 0;
+ m_blupiTimeNoAsc = 0;
+ m_blupiTimeMockery = 0;
+ m_blupiValidPos = m_blupiPos;
+ m_blupiEnergyUnused = 100;
+ m_blupiBullet = 0;
+ m_blupiCle = 0;
+ m_blupiPerso = 0;
+ m_blupiDynamite = 0;
+ m_nbTresor = 0;
+ m_totalTresor = 0;
+ for (int i = MAXMOVEOBJECT; i != 0; i--)
+ {
+ if (m_moveObject[i].type == TYPE_TRESOR)
+ {
+ m_totalTresor++;
+ }
+ m_moveObject[i].posCurrent = m_moveObject[i].posStart;
+ m_moveObject[i].step = STEP_STOPSTART;
+ m_moveObject[i].phase = 0;
+ m_moveObject[i].time = 0;
+
+ if (m_moveObject[i].type == TYPE_TRESOR ||
+ m_moveObject[i].type == TYPE_EGG ||
+ m_moveObject[i].type == TYPE_SHIELD ||
+ m_moveObject[i].type == TYPE_POWER ||
+ m_moveObject[i].type == TYPE_INVERT ||
+ m_moveObject[i].type == TYPE_BOMBEDOWN ||
+ m_moveObject[i].type == TYPE_BOMBEUP ||
+ m_moveObject[i].type == TYPE_BOMBEFOLLOW1 ||
+ m_moveObject[i].type == TYPE_BOMBEFOLLOW2)
+ {
+ m_moveObject[i].phase = rand() % 23;
+ }
+
+ if (m_moveObject[i].type == TYPE_BALLE)
+ {
+ m_moveObject[i].type = 0;
+ }
+
+ if (m_bMulti &&
+ (m_moveObject[i].type == TYPE_CAISSE ||
+ m_moveObject[i].type == TYPE_GOAL ||
+ m_moveObject[i].type == TYPE_CLE ||
+ m_moveObject[i].type == TYPE_BLUPIHELICO ||
+ m_moveObject[i].type == TYPE_BLUPITANK))
+ {
+ m_moveObject[i].type = 0;
+ }
+ }
+ m_goalPhase = 0;
+ MoveObjectSort();
+ UpdateCaisse();
+ m_scrollPoint = m_blupiPos;
+ m_scrollAdd = POINT( 0, 0 );
+ m_blupiPosHelico.x = -1;
+ m_nbLinkCaisse = 0;
+ m_bHelicoMarch = FALSE;
+ m_bHelicoStop = FALSE;
+ m_bJeepMarch = FALSE;
+ m_bJeepStop = FALSE;
+ m_blupiFront = FALSE;
+ m_blupiNoBarre = 0;
+ m_blupiValidPos = m_blupiPos;
+ m_blupiFifoNb = 0;
+ m_blupiTimeFire = 0;
+ NetDataFlush();
+ NotifFlush();
+ m_voyageIcon = -1;
+ m_jauges[JAUGE_AIR].SetHide(TRUE);
+ m_jauges[JAUGE_POWER].SetHide(TRUE);
+ m_bFoundCle = FALSE;
+ m_term = 0;
+ m_time = 0;
+ m_bPause = FALSE;
+}
+
+void CDecor::BuildPrepare()
+{
+ for (int i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ m_moveObject[i].posCurrent = m_moveObject[i].posStart;
+ m_moveObject[i].step = STEP_STOPSTART;
+ m_moveObject[i].time = 0;
+ m_moveObject[i].phase = 0;
+ if (m_moveObject[i].type == TYPE_BALLE)
+ {
+ m_moveObject[i].type = 0;
+ }
+ }
+ m_voyageIcon = -1;
+ m_posCelHili.x = -1;
+ m_2ndPositionCalculationSlot = -1;
+ m_time = 0;
+ m_bPause = FALSE;
+ NetDataFlush();
+}
+
+int CDecor::IsTerminated()
+{
+ return m_term;
+}
+
+void CDecor::MoveStep()
+{
+ MoveObjectStep();
+
+ if (m_phase == WM_PHASE_PLAY || m_phase == WM_PHASE_PLAYTEST) {
+ BlupiStep();
+ NetAdjustToLift();
+ NotifStep();
+ }
+
+ if (m_phase == WM_PHASE_BUILD)
+ {
+ if (m_keyPress & KEY_RIGHT)
+ {
+ m_posDecor.x += 50;
+ int limit = (m_dimDecor.x != 0) ? (MAXCELX * DIMOBJX - LXIMAGE) : 0;
+ if (m_posDecor.x > limit) m_posDecor.x = limit;
+ m_posCelHili.x = -1;
+ }
+ if (m_keyPress & KEY_LEFT)
+ {
+ m_posDecor.x -= 50;
+ if (m_posDecor.x < 0) m_posDecor.x = 0;
+ m_posCelHili.x = -1;
+ }
+ if (m_keyPress & KEY_DOWN)
+ {
+ m_posDecor.y += 50;
+ int limit = (m_dimDecor.y > 0) ? (MAXCELY * DIMOBJY - LYIMAGE) : 0;
+ if (m_posDecor.y > limit) m_posDecor.y = limit;
+ m_posCelHili.x = -1;
+ }
+ if (m_keyPress & KEY_UP)
+ {
+ m_posDecor.y -= 50;
+ if (m_posDecor.y < 0) m_posDecor.y = 0;
+ m_posCelHili.x = -1;
+ }
+ }
+}
+
+int CDecor::GetIconPerso()
+{
+ if (m_bMulti) {
+ return m_team + 108;
+ }
+ else {
+ return 108;
+ }
+}
+
+void CDecor::Build(RECT rect)
+{
+ int num = 1;
+ int i, j;
+ POINT tinyPoint;
+ tinyPoint.x = 0;
+ RECT lastClip;
+
+ lastClip = m_pPixmap->GetClipping();
+ m_pPixmap->SetClipping(rect);
+
+ POINT posDecor = DecorNextAction();
+ POINT pos = { posDecor.x * 2 / 3 % DIMDECORX, posDecor.y * 2 / 3 % DIMDECORY };
+
+ for (i = 0; i < ((DIMDECORX - DIMDECORX / LXIMAGE * LXIMAGE) ? 2 : 1) + LXIMAGE / DIMDECORX; i++)
+ {
+ tinyPoint.y = 0;
+ rect.top = pos.y;
+ for (j = 0; j < ((DIMDECORY - DIMDECORY / LYIMAGE * LYIMAGE) ? 2 : 1) + LYIMAGE / DIMDECORY; j++)
+ {
+ rect.left = i ? 0 : pos.x;
+ rect.right = DIMDECORX;
+ rect.bottom = DIMDECORY;
+ m_pPixmap->DrawPart(-1, CHDECOR, tinyPoint, rect, 1, FALSE);
+ tinyPoint.y = DIMDECORY * (j + 1) - pos.y;
+ rect.top = 0;
+ }
+ tinyPoint.x = DIMDECORX * (i + 1) - pos.x;
+
+ }
+
+ tinyPoint.x = -posDecor.x % DIMOBJX - DIMOBJX;
+ for (i = posDecor.x / DIMOBJX - 1; i < posDecor.x / DIMOBJX + LXIMAGE / DIMOBJX + 3; i++) {
+ tinyPoint.y = -posDecor.y % DIMOBJY + 2 - DIMOBJY;
+ for (j = posDecor.y / DIMOBJY - 1; j < posDecor.y / DIMOBJY + LYIMAGE / DIMOBJY + 2; j++)
+ {
+ if (i >= 0 && i < MAXCELX && j >= 0 && j < MAXCELY)
+ {
+ int num2 = m_bigDecor[i][j].icon;
+ int channel = 9;
+ if (num2 != -1)
+ {
+ pos = tinyPoint;
+ if (num2 == 203)
+ {
+ num2 = table_marine[m_time / 3 % 11];
+ channel = 1;
+ }
+ if (num2 >= 66 && num2 <= 68)
+ {
+ pos.y -= 13;
+ }
+ if (num2 >= 87 && num2 <= 89)
+ {
+ pos.y -= 2;
+ }
+ m_pPixmap->QuickIcon(channel, num2, pos);
+ }
+ }
+ tinyPoint.y += DIMOBJY;
+ }
+ tinyPoint.x += DIMOBJX;
+ }
+
+ tinyPoint.x = -posDecor.x % DIMOBJX;
+ for (i = posDecor.x / DIMOBJX; i < posDecor.x / DIMOBJX + LXIMAGE / DIMOBJX + 2; i++)
+ {
+ tinyPoint.y = -posDecor.y % DIMOBJY;
+ for (j = posDecor.y / DIMOBJY; j < posDecor.y / DIMOBJY + LYIMAGE / DIMOBJY + 2; j++)
+ {
+ if (i >= 0 && i < MAXCELX && j >= 0 && j < MAXCELY && m_decor[i][j].icon != -1)
+ {
+ int num2 = m_decor[i][j].icon;
+ if (num2 == 384 || num2 == 385)
+ {
+ m_pPixmap->QuickIcon(CHOBJECT, num2, tinyPoint);
+ }
+ }
+ tinyPoint.y += DIMOBJY;
+ }
+ tinyPoint.x += DIMOBJX;
+ }
+
+ if (m_phase == WM_PHASE_BUILD)
+ {
+ // draw blupi start positions...
+ }
+
+ if (m_bMulti && m_phase != WM_PHASE_BUILD)
+ {
+ // ...
+ }
+
+ m_blupiSec = 0;
+ if (!m_blupiFront && m_phase != WM_PHASE_BUILD)
+ {
+ tinyPoint.x = m_blupiPos.x - posDecor.x;
+ tinyPoint.y = m_blupiPos.y - posDecor.y;
+ if (m_blupiJeep)
+ {
+ tinyPoint.y += BLUPIOFFY;
+ }
+ if (m_blupiShield)
+ {
+ m_blupiSec = SEC_SHIELD;
+ if (m_blupiTimeShield > 25 || m_time % 4 < 2)
+ {
+ int num2 = table_shield_blupi[m_time / 2 % 16];
+ tinyPoint.y -= 2;
+ m_pPixmap->QuickIcon(CHELEMENT, num2, tinyPoint);
+ tinyPoint.y += 2;
+ num2 = table_shieldloop[m_time / 2 % 5];
+ m_pPixmap->QuickIcon(CHELEMENT, num2, tinyPoint);
+ }
+ }
+ else if (m_blupiPower)
+ {
+ m_blupiSec = SEC_POWER;
+ if (m_blupiTimeShield > 25 || m_time % 4 < 2)
+ {
+ int num2 = table_magicloop[m_time / 2 % 5];
+ m_pPixmap->QuickIcon(CHELEMENT, num2, tinyPoint);
+ }
+ }
+ else if (m_blupiCloud)
+ {
+ m_blupiSec = SEC_CLOUD;
+ if (m_blupiTimeShield > 25 || m_time % 4 < 2)
+ {
+ for (int k = 0; k < 3; k++)
+ {
+ int num2 = 48 + (m_time + k) % 6;
+ pos.x = tinyPoint.x - 34;
+ pos.y = tinyPoint.y - 34;
+ m_pPixmap->QuickIcon(CHEXPLO, num2, pos);
+ }
+ }
+ }
+ else if (m_blupiHide)
+ {
+ m_blupiSec = SEC_HIDE;
+ if (m_blupiTimeShield > 25 || m_time % 4 < 2)
+ {
+ m_pPixmap->DrawIcon(CHTEMP, CHOBJECT, 0xF5, POINT( 0, 0 ), 0, TRUE);
+ }
+ else
+ {
+ m_pPixmap->DrawIcon(CHTEMP, GetBlupiChannelStandard(), m_blupiIcon, pos, 1, FALSE);
+ m_pPixmap->DrawIcon(CHTEMP, CHOBJECT, 0xED, POINT( 0, 0 ), 0, TRUE);
+ }
+ }
+ m_pPixmap->QuickIcon(GetBlupiChannelStandard(), m_blupiIcon, tinyPoint);
+ }
+
+ for (i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ if (m_moveObject[i].type != 0 && m_moveObject[i].posCurrent.x >= posDecor.x - 64 && m_moveObject[i].posCurrent.y >= posDecor.y - 64 && m_moveObject[i].posCurrent.x <= posDecor.x + LXIMAGE && m_moveObject[i].posCurrent.y <= posDecor.y + LYIMAGE && (m_moveObject[i].type < 8 || m_moveObject[i].type > 11) && (m_moveObject[i].type < 90 || m_moveObject[i].type > 95) && (m_moveObject[i].type < 98 || m_moveObject[i].type > 100) && m_moveObject[i].type != 53 && m_moveObject[i].type != 1 && m_moveObject[i].type != 47 && m_moveObject[i].type != 48)
+ {
+ tinyPoint.x = m_moveObject[i].posCurrent.x - posDecor.x;
+ tinyPoint.y = m_moveObject[i].posCurrent.y - posDecor.y;
+ if (m_moveObject[i].type == TYPE_BULLDOZER || m_moveObject[i].type == TYPE_BLUPIHELICO || m_moveObject[i].type == TYPE_BLUPITANK)
+ {
+ tinyPoint.x += 2;
+ tinyPoint.y += BLUPIOFFY;
+ }
+ if (m_moveObject[i].type == TYPE_CREATURE)
+ {
+ tinyPoint.y += BLUPIOFFY;
+ }
+ // get the winphone opacity stuff out of here
+ m_pPixmap->QuickIcon(m_moveObject[i].channel, m_moveObject[i].icon, tinyPoint);
+ if (m_moveObject[i].type == TYPE_DRINK)
+ {
+ for (int L = 0; L < sizeof(table_drinkoffset) / sizeof(int); L++)
+ {
+ int num4 = (m_time + table_drinkoffset[L]) % 50;
+ int rank = table_drinkeffect[num4 % 5];
+ POINT tinyPoint2 = { tinyPoint.x + 2, tinyPoint.y - num4 * 3 };
+ POINT pos2 = tinyPoint2;
+ m_pPixmap->QuickIcon(10, rank, pos2);
+ }
+ }
+ if (m_bDrawSecret && m_moveObject[i].type == TYPE_CAISSE && m_moveObject[i].icon != 32 && m_moveObject[i].icon != 33 && m_moveObject[i].icon != 34)
+ {
+ m_pPixmap->QuickIcon(1, 214, tinyPoint);
+ }
+ }
+ }
+ tinyPoint.x = -posDecor.x % 64;
+ for (i = posDecor.x / 64; i < posDecor.x / 64 + LXIMAGE / 64 + 2; i++)
+ {
+ tinyPoint.y = 0 - posDecor.y % 64;
+ for (j = posDecor.y / 64; j < posDecor.y / 64 + LYIMAGE / 64 + 2; j++)
+ {
+ if (i >= 0 && i < 100 && j >= 0 && j < 100 && m_decor[i][j].icon != -1)
+ {
+ int num2 = m_decor[i][j].icon;
+ pos.x = tinyPoint.x;
+ pos.y = tinyPoint.y;
+ if ((num2 >= 107 && num2 <= 109) || num2 == 157)
+ {
+ pos.y -= 7;
+ }
+ if (num2 == 211)
+ {
+ num2 = table_ressort[(m_time / 2 + i * 7) % 8];
+ }
+ if (num2 == 214 && !m_bDrawSecret)
+ {
+ num2 = -1;
+ }
+ if (num2 == 364)
+ {
+ pos.y -= 2;
+ }
+ switch (num2)
+ {
+ default:
+ m_pPixmap->QuickIcon(1, num2, pos);
+ break;
+ case 68:
+ case 91:
+ case 92:
+ case 110:
+ case 111:
+ case 112:
+ case 113:
+ case 114:
+ case 115:
+ case 116:
+ case 117:
+ case 118:
+ case 119:
+ case 120:
+ case 121:
+ case 122:
+ case 123:
+ case 124:
+ case 125:
+ case 126:
+ case 127:
+ case 128:
+ case 129:
+ case 130:
+ case 131:
+ case 132:
+ case 133:
+ case 134:
+ case 135:
+ case 136:
+ case 137:
+ case 305:
+ case 317:
+ case 324:
+ case 373:
+ case 378:
+ case 384:
+ case 385:
+ case 404:
+ case 410:
+ break;
+ }
+ }
+ tinyPoint.y += DIMOBJY;
+ }
+ tinyPoint.x += DIMOBJX;
+ }
+ for (int num3 = 0; num3 < MAXMOVEOBJECT; num3++)
+ {
+ if ((m_moveObject[num3].type == TYPE_ASCENSEUR ||
+ m_moveObject[num3].type == TYPE_ASCENSEURs ||
+ m_moveObject[num3].type == TYPE_ASCENSEURsi) &&
+ m_moveObject[num3].posCurrent.x >= posDecor.x - DIMOBJX &&
+ m_moveObject[num3].posCurrent.y >= posDecor.y - DIMOBJY &&
+ m_moveObject[num3].posCurrent.x <= posDecor.x + LXIMAGE &&
+ m_moveObject[num3].posCurrent.y <= posDecor.y + LYIMAGE)
+ {
+ tinyPoint.x = 0 + m_moveObject[num3].posCurrent.x - posDecor.x;
+ tinyPoint.y = 0 + m_moveObject[num3].posCurrent.y - posDecor.y;
+ m_pPixmap->QuickIcon(m_moveObject[num3].channel, m_moveObject[num3].icon, tinyPoint);
+ }
+ }
+ tinyPoint.x = 0 - posDecor.x % DIMOBJX;
+ for (i = posDecor.x / DIMOBJX; i < posDecor.x / DIMOBJX + LXIMAGE / DIMOBJX + 2; i++)
+ {
+ tinyPoint.y = 0 - posDecor.y % DIMOBJY;
+ for (j = posDecor.y / DIMOBJY; j < posDecor.y / DIMOBJY + LYIMAGE / DIMOBJY + 2; j++)
+ {
+ if (i >= 0 && i < MAXCELX && j >= 0 && j < MAXCELY && m_decor[i][j].icon != -1)
+ {
+ int num2 = m_decor[i][j].icon;
+ pos = tinyPoint;
+ if (num2 == 68)
+ {
+ num2 = table_decor_lave[(i * 13 + j * 7 + m_time / 2) % 8];
+ m_pPixmap->QuickIcon(1, num2, pos);
+ }
+ if (num2 == 373)
+ {
+ num2 = ((!m_blupiFocus) ? table_decor_piege2[(i * 13 + j * 7 + m_time / 2) % 4] : table_decor_piege1[(i * 13 + j * 7 + m_time / 4) % 16]);
+ m_pPixmap->QuickIcon(1, num2, pos);
+ }
+ if (num2 == 404 || num2 == 410)
+ {
+ num2 = table_decor_goutte[(i * 13 + j * 7 + m_time / 2) % 48];
+ pos.y -= 9;
+ m_pPixmap->QuickIcon(1, num2, pos);
+ if (num2 >= 404 && num2 <= 407)
+ {
+ m_decor[i][j].icon = 404;
+ }
+ else
+ {
+ m_decor[i][j].icon = 410;
+ }
+ }
+ if (num2 == 317)
+ {
+ num2 = table_decor_ecraseur[m_time / 3 % 10];
+ m_pPixmap->QuickIcon(1, num2, pos);
+ }
+ if (num2 == 378)
+ {
+ num2 = table_decor_scie[(i * 13 + j * 7 + m_time / 1) % 6];
+ m_pPixmap->QuickIcon(1, num2, pos);
+ }
+ if (num2 == 324)
+ {
+ num2 = table_decor_temp[m_time / 4 % 20];
+ m_pPixmap->QuickIcon(1, num2, pos);
+ }
+ if (num2 == 92)
+ {
+ num2 = table_decor_eau1[(i * 13 + j * 7 + m_time / 3) % 6];
+ m_pPixmap->QuickIcon(1, num2, pos);
+ }
+ if (num2 == 91)
+ {
+ int num5 = 3 + (i * 17 + j * 13) % 3;
+ num2 = table_decor_eau2[(i * 11 + j * 7 + m_time / num5) % 6];
+ m_pPixmap->QuickIcon(1, num2, pos);
+ }
+ if (num2 == 305 && BlitzActif(POINT( i, j )))
+ {
+ num2 = rand() % 4 + 305;
+ m_pPixmap->QuickIcon(1, num2, pos);
+ }
+ if (num2 == 110)
+ {
+ num2 = table_decor_ventg[m_time / 1 % 4];
+ m_pPixmap->QuickIcon(1, num2, pos);
+ }
+ if (num2 == 114)
+ {
+ num2 = table_decor_ventd[m_time / 1 % 4];
+ m_pPixmap->QuickIcon(1, num2, pos);
+ }
+ if (num2 == 118)
+ {
+ num2 = table_decor_venth[m_time / 1 % 4];
+ m_pPixmap->QuickIcon(1, num2, pos);
+ }
+ if (num2 == 122)
+ {
+ num2 = table_decor_ventb[m_time / 1 % 4];
+ m_pPixmap->QuickIcon(1, num2, pos);
+ }
+ if (num2 == 126)
+ {
+ num2 = table_decor_ventillog[m_time / 2 % 3];
+ m_pPixmap->QuickIcon(1, num2, pos);
+ }
+ if (num2 == 129)
+ {
+ num2 = table_decor_ventillod[m_time / 2 % 3];
+ m_pPixmap->QuickIcon(1, num2, pos);
+ }
+ if (num2 == 132)
+ {
+ num2 = table_decor_ventilloh[m_time / 2 % 3];
+ m_pPixmap->QuickIcon(1, num2, pos);
+ }
+ if (num2 == 135)
+ {
+ num2 = table_decor_ventillob[m_time / 2 % 3];
+ m_pPixmap->QuickIcon(1, num2, pos);
+ }
+ }
+ tinyPoint.y += DIMOBJY;
+ }
+ tinyPoint.x += DIMOBJX;
+ }
+ for (i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ if (m_moveObject[i].type != 0 &&
+ m_moveObject[i].posCurrent.x >= posDecor.x - DIMOBJX &&
+ m_moveObject[i].posCurrent.y >= posDecor.y - DIMOBJY &&
+ m_moveObject[i].posCurrent.x <= posDecor.x + LXIMAGE &&
+ m_moveObject[i].posCurrent.y <= posDecor.y + LYIMAGE &&
+ ((m_moveObject[i].type >= TYPE_EXPLO1 && m_moveObject[i].type <= TYPE_EXPLO3) ||
+ (m_moveObject[i].type >= TYPE_EXPLO5 && m_moveObject[i].type <= TYPE_EXPLO10) ||
+ (m_moveObject[i].type >= TYPE_SPLOUTCH1 && m_moveObject[i].type <= TYPE_SPLOUTCH3) ||
+ m_moveObject[i].type == TYPE_TENTACULE))
+ {
+ tinyPoint = m_moveObject[i].posCurrent - posDecor;
+ m_pPixmap->QuickIcon(m_moveObject[i].channel, m_moveObject[i].icon, tinyPoint);
+ }
+ ////debug
+ if (m_moveObject[i].posCurrent.x >= posDecor.x - 64 && m_moveObject[i].posCurrent.y >= posDecor.y - 64 && m_moveObject[i].posCurrent.x <= posDecor.x + LXIMAGE && m_moveObject[i].posCurrent.y <= posDecor.y + LYIMAGE)
+ {
+ char str[50];
+ sprintf(str, "[%d]: %d", i, m_moveObject[i].type);
+ DrawText(m_pPixmap, m_moveObject[i].posCurrent - posDecor, str, FONTLITTLE);
+ }
+ ////
+ }
+ if (m_blupiFront)
+ {
+ tinyPoint = m_blupiPos - posDecor;
+ m_pPixmap->QuickIcon(m_blupiChannel, m_blupiIcon, tinyPoint);
+ }
+ DrawInfo();
+ VoyageDraw();
+ m_time++;
+}
+
+void CDecor::DrawInfo()
+{
+ POINT pos;
+ char text[100];
+ int i;
+
+ if (m_phase == WM_PHASE_PLAY || m_phase == WM_PHASE_PLAYTEST)
+ {
+ pos = POINT( 10, 10 );
+ for (i = 0; i < MAXNOTIF; i++) {
+ if (m_notifText[i][0] != '\0') {
+ DrawText(m_pPixmap, pos, m_notifText[i], FONTWHITE);
+ }
+ pos.y += DIMTEXTY;
+ }
+
+ if (m_nbVies > 0) {
+ pos = POINT( -15, 417 );
+ for (int i = 0; i < m_nbVies; i++) {
+ m_pPixmap->QuickIcon(GetBlupiChannelActual(), 48, pos);
+ pos.x += 16;
+ }
+ }
+
+ if (m_blupiBullet > 0) {
+ pos = POINT( 398, 442 );
+ for (int i = 0; i < m_blupiBullet; i++) {
+ m_pPixmap->QuickIcon(CHELEMENT, 176, pos);
+ pos.x += 4;
+ }
+ }
+
+ if (m_blupiPerso > 0) {
+ m_pPixmap->QuickIcon(CHBUTTON, GetIconPerso(), POINT( 465, 438 ));
+ sprintf(text, "= %d", m_blupiPerso);
+ DrawText(m_pPixmap, POINT( 497, 452 ), text, FONTWHITE);
+ }
+
+ if (m_blupiDynamite > 0) {
+ m_pPixmap->QuickIcon(CHELEMENT, 252, POINT( 505, 414 ));
+ }
+
+ if (m_blupiCle & CLE_RED) {
+ m_pPixmap->QuickIcon(CHELEMENT, 215, POINT( 520, 418 ));
+ }
+
+ if (m_blupiCle & CLE_GREEN) {
+ m_pPixmap->QuickIcon(CHELEMENT, 222, POINT( 530, 418 ));
+ }
+
+ if (m_blupiCle & CLE_BLUE) {
+ m_pPixmap->QuickIcon(CHELEMENT, 229, POINT( 540, 418 ));
+ }
+
+ if ((m_mission != 1 && m_mission % 10 != 0) || m_bPrivate)
+ {
+ sprintf(text, "%d/%d", m_nbTresor, m_totalTresor);
+ DrawText(m_pPixmap, POINT( 590, 452 ), text, FONTWHITE);
+ }
+
+ for (i = 0; i < 2; i++)
+ {
+ if (!(m_jauges[i].GetHide())) m_jauges[i].Draw();
+ }
+
+ if (m_mission == 10 && m_phase == WM_PHASE_PLAY && !m_bPrivate)
+ {
+ switch (m_nbTresor)
+ {
+ case 0:
+ if (m_blupiPos.x > 212) m_blupiPos.x = 212;
+ break;
+ case 1:
+ if (m_blupiPos.x > 788) m_blupiPos.x = 788;
+ break;
+ }
+
+ POINT cel = { (m_blupiPos.x + DIMBLUPIX / 2) / DIMOBJX, (m_blupiPos.y + DIMBLUPIY / 2) / DIMOBJY };
+ for (i = 0; table_tutorial[i * 6 + 0] != -1; i++)
+ {
+ if (cel.x >= table_tutorial[i * 6 + 0] &&
+ cel.x <= table_tutorial[i * 6 + 1] &&
+ cel.y >= table_tutorial[i * 6 + 2] &&
+ cel.y <= table_tutorial[i * 6 + 3])
+ {
+ if (table_tutorial[i * 6 + 4] == -1 || table_tutorial[i * 6 + 4] == m_nbTresor)
+ {
+ if (m_bJoystick)
+ {
+ LoadString(table_tutorial[i * 6 + 5] + 100, text, 100);
+ }
+ else
+ {
+ LoadString(table_tutorial[i * 6 + 5], text, 100);
+ }
+ DrawTextCenter(m_pPixmap, POINT(360, 460), text);
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (m_phase == WM_PHASE_BUILD)
+ {
+ if (m_posCelHili.x != -1)
+ {
+ int icon = 0;
+ if (m_2ndPositionCalculationSlot != -1)
+ {
+ icon = 31;
+ }
+ if (m_dimCelHili.x > 0)
+ {
+ pos.x = m_posCelHili.x * DIMOBJX - m_posDecor.x;
+
+ int j = 0;
+ for (i = 0; i < m_dimCelHili.x; i++)
+ {
+ pos.y = m_posCelHili.y * DIMOBJY - m_posDecor.y;
+ for (j = 0; j < m_dimCelHili.y; j++)
+ {
+ m_pPixmap->QuickIcon(CHOBJECT, icon, pos);
+ pos.y += DIMOBJY;
+ }
+ pos.x += DIMOBJX;
+ }
+ }
+ }
+ if (m_phase == WM_PHASE_BUILD) // again???
+ {
+ LoadString(0x66, text, 100);
+ DrawText(m_pPixmap, POINT(200, 460), text, FONTGOLD);
+ }
+ }
+ if (m_phase == WM_PHASE_PLAYTEST)
+ {
+ LoadString(0x67, text, 100);
+ DrawText(m_pPixmap, POINT(200, 460), text, FONTGOLD);
+ }
+}
+
+POINT CDecor::DecorNextAction()
+{
+ int num = 0;
+ if (m_decorAction == 0 || m_bPause)
+ {
+ return m_posDecor;
+ }
+ POINT posDecor = m_posDecor;
+ while (table_decor_action[num] != 0)
+ {
+ if (m_decorAction == table_decor_action[num])
+ {
+ if (m_decorPhase < table_decor_action[num + 1])
+ {
+ posDecor.x += 3 * table_decor_action[num + 2 + m_decorPhase * 2];
+ posDecor.y += 3 * table_decor_action[num + 2 + m_decorPhase * 2 + 1];
+ int num2;
+ if (m_dimDecor.x == 0)
+ {
+ num2 = 0;
+ }
+ else
+ {
+ num2 = DIMOBJX * MAXCELX - LXIMAGE;
+ }
+ if (posDecor.x < 0)
+ {
+ posDecor.x = 0;
+ }
+ if (posDecor.x > num2)
+ {
+ posDecor.x = num2;
+ }
+ if (m_dimDecor.y == 0)
+ {
+ num2 = 0;
+ }
+ else
+ {
+ num2 = DIMOBJY * MAXCELY - LYIMAGE;
+ }
+ if (posDecor.y < 0)
+ {
+ posDecor.y = 0;
+ }
+ if (posDecor.y > num2)
+ {
+ posDecor.y = num2;
+ }
+ m_decorPhase++;
+ break;
+ }
+ m_decorAction = 0;
+ break;
+ }
+ else
+ {
+ num += 2 + table_decor_action[num + 1] * 2;
+ }
+ }
+ return posDecor;
+}
+
+void CDecor::SetInput(int keys)
+{
+ m_keyPress = keys;
+ if (m_blupiInvert)
+ {
+ if (keys & KEY_LEFT)
+ {
+ m_keyPress = keys & ~KEY_LEFT | KEY_RIGHT;
+ }
+ if (keys & KEY_RIGHT)
+ {
+ m_keyPress = m_keyPress & ~KEY_RIGHT | KEY_LEFT;
+ }
+ }
+}
+
+void CDecor::SetJoystickEnable(BOOL bJoystick)
+{
+ m_bJoystick = bJoystick;
+}
+
+void CDecor::SetDemoPlay(BOOL param)
+{
+ m_bDemoPlay = param;
+}
+
+void CDecor::PlaySound(int sound, POINT pos, BOOL bLocal)
+{
+ if (!bLocal) NetPlaySound(sound, pos);
+
+ m_pSound->PlayImage(sound, POINT(pos.x - m_posDecor.x, pos.y - m_posDecor.y), -1);
+
+ switch (sound) {
+ case SOUND_HELICOHIGH:
+ m_bHelicoMarch = TRUE;
+ break;
+ case SOUND_HELICOLOW:
+ m_bHelicoStop = TRUE;
+ break;
+ case SOUND_JEEPHIGH:
+ m_bJeepMarch = TRUE;
+ break;
+ case SOUND_JEEPLOW:
+ m_bJeepStop = TRUE;
+ break;
+ }
+}
+
+void CDecor::PlaySound(int sound, POINT pos)
+{
+ PlaySound(sound, pos, FALSE);
+}
+
+void CDecor::StopSound(int sound)
+{
+ m_pSound->StopSound(sound);
+
+ switch (sound) {
+ case SOUND_HELICOHIGH:
+ m_bHelicoMarch = FALSE;
+ break;
+ case SOUND_HELICOLOW:
+ m_bHelicoStop = FALSE;
+ break;
+ case SOUND_JEEPHIGH:
+ m_bJeepMarch = FALSE;
+ break;
+ case SOUND_JEEPLOW:
+ m_bJeepStop = FALSE;
+ break;
+ }
+}
+
+void CDecor::AdaptMotorVehicleSound(POINT pos)
+{
+ POINT blupiPos = POINT(pos.x - m_posDecor.x, pos.y - m_posDecor.y);
+
+ if (m_bHelicoMarch) m_pSound->PlayImage(SOUND_HELICOHIGH, blupiPos);
+ if (m_bHelicoStop) m_pSound->PlayImage(SOUND_HELICOLOW, blupiPos);
+ if (m_bJeepMarch) m_pSound->PlayImage(SOUND_JEEPHIGH, blupiPos);
+ if (m_bJeepStop) m_pSound->PlayImage(SOUND_JEEPLOW, blupiPos);
+}
+
+void CDecor::VehicleSoundsPhase(int phase)
+{
+ m_phase = phase;
+
+ if (phase == WM_PHASE_PLAY || phase == WM_PHASE_PLAYTEST) {
+ int channel = -1;
+ if (m_bHelicoMarch) channel = SOUND_HELICOHIGH;
+ if (m_bHelicoStop) channel = SOUND_HELICOLOW;
+ if (m_bJeepMarch) channel = SOUND_JEEPHIGH;
+ if (m_bJeepStop) channel = SOUND_JEEPLOW;
+ if (channel != -1) m_pSound->PlayImage(channel, POINT( LXIMAGE / 2, LYIMAGE / 2 ), -1);
+ }
+ else {
+ if (m_bHelicoMarch) m_pSound->StopSound(SOUND_HELICOHIGH);
+ if (m_bHelicoStop) m_pSound->StopSound(SOUND_HELICOLOW);
+ if (m_bJeepMarch) m_pSound->StopSound(SOUND_JEEPHIGH);
+ if (m_bJeepStop) m_pSound->StopSound(SOUND_JEEPLOW);
+ }
+}
+
+int CDecor::GetRegion()
+{
+ return m_region;
+}
+
+void CDecor::SetRegion(int region)
+{
+ m_region = region;
+}
+
+int CDecor::GetMusic()
+{
+ return m_music;
+}
+
+void CDecor::SetMusic(int music)
+{
+ m_music = music;
+}
+
+POINT CDecor::GetDim()
+{
+ return m_dimDecor;
+}
+
+void CDecor::SetDim(POINT dim)
+{
+ m_dimDecor = dim;
+}
+
+int CDecor::GetNbVies()
+{
+ return m_nbVies;
+}
+
+void CDecor::SetNbVies(int nbVies)
+{
+ m_nbVies = nbVies;
+}
+
+BOOL CDecor::GetPause()
+{
+ return m_bPause;
+}
+
+void CDecor::SetPause(BOOL bPause)
+{
+ m_bPause = bPause;
+}
+
+void CDecor::InitializeDoors(BYTE* doors)
+{
+ for (int i = 0; i < 200; i++)
+ {
+ doors[i] = m_doors[i];
+ }
+}
+
+void CDecor::MemorizeDoors(BYTE* doors)
+{
+ for (int i = 0; i < 200; i++)
+ {
+ m_doors[i] = doors[i];
+ }
+}
+
+void CDecor::SetAllMissions(BOOL bAllMissions)
+{
+ m_bCheatDoors = bAllMissions;
+ AdaptDoors(m_bPrivate, m_mission);
+ return;
+}
+
+void CDecor::CheatAction(int cheat)
+{
+ MoveObject* mob;
+ int i;
+
+ switch (cheat)
+ {
+ case 2: // cleanall
+ for (i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ mob = &m_moveObject[i];
+ switch (mob->type)
+ {
+ case TYPE_BOMBEDOWN:
+ case TYPE_BOMBEUP:
+ case TYPE_BOMBEFOLLOW1:
+ case TYPE_BOMBEFOLLOW2:
+ case TYPE_BULLDOZER:
+ case TYPE_BOMBEMOVE:
+ case TYPE_POISSON:
+ case TYPE_OISEAU:
+ case TYPE_GUEPE:
+ case TYPE_CREATURE:
+ case TYPE_BLUPIHELICO:
+ case TYPE_BLUPITANK:
+ m_decorAction = 1;
+ m_decorPhase = 0;
+ mob->type = TYPE_EXPLO1;
+ mob->phase = 0;
+ mob->posCurrent.x -= 34;
+ mob->posCurrent.y -= 34;
+ mob->posStart = mob->posCurrent;
+ mob->posEnd = mob->posCurrent;
+ MoveObjectStepIcon(i);
+ PlaySound(SOUND_BOUM, mob->posCurrent, FALSE);
+ }
+ }
+ break;
+ case 6: // funskate
+ m_blupiAir = FALSE;
+ m_blupiHelico = FALSE;
+ m_blupiOver = FALSE;
+ m_blupiJeep = FALSE;
+ m_blupiTank = FALSE;
+ m_blupiSkate = TRUE;
+ m_blupiNage = FALSE;
+ m_blupiSurf = FALSE;
+ m_blupiVent = FALSE;
+ m_blupiSuspend = FALSE;
+ StopVehicleSound();
+ break;
+ case 7: // givecopter
+ m_blupiAir = FALSE;
+ m_blupiHelico = TRUE;
+ m_blupiOver = FALSE;
+ m_blupiJeep = FALSE;
+ m_blupiTank = FALSE;
+ m_blupiSkate = FALSE;
+ m_blupiNage = FALSE;
+ m_blupiSurf = FALSE;
+ m_blupiVent = FALSE;
+ m_blupiSuspend = FALSE;
+ StopVehicleSound();
+ PlaySound(SOUND_HELICOSTART, m_blupiPos, FALSE);
+ PlaySound(SOUND_HELICOLOW, m_blupiPos, TRUE);
+ break;
+ case 8: // jeepdrive
+ m_blupiAir = FALSE;
+ m_blupiHelico = FALSE;
+ m_blupiOver = FALSE;
+ m_blupiJeep = TRUE;
+ m_blupiTank = FALSE;
+ m_blupiSkate = FALSE;
+ m_blupiNage = FALSE;
+ m_blupiSurf = FALSE;
+ m_blupiVent = FALSE;
+ m_blupiSuspend = FALSE;
+ StopVehicleSound();
+ PlaySound(SOUND_JEEPLOW, m_blupiPos, TRUE);
+ break;
+ case 9: // alltreasure
+ for (i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ if (m_moveObject[i].type == TYPE_TRESOR)
+ {
+ m_moveObject[i].type = 0;
+ m_nbTresor++;
+ OpenDoorsTresor();
+ PlaySound(SOUND_TRESOR, m_moveObject[i].posCurrent, FALSE);
+ }
+ }
+ break;
+ case 10: // endgoal
+ for (i = 0; i < MAXMOVEOBJECT; i++)
+ {
+ mob = &m_moveObject[i];
+ if (mob->type == TYPE_GOAL || mob->type == TYPE_CLE)
+ {
+ m_blupiPos = mob->posCurrent;
+ if (m_nbTresor >= m_totalTresor)
+ {
+ if (mob->type == TYPE_CLE)
+ {
+ m_bFoundCle = TRUE;
+ }
+ StopVehicleSound();
+ PlaySound(SOUND_ENDOK, mob->posCurrent, FALSE);
+ m_blupiAction = ACTION_WIN;
+ m_blupiPhase = 0;
+ m_blupiFocus = FALSE;
+ m_blupiFront = TRUE;
+ m_blupiAir = FALSE;
+ m_blupiHelico = FALSE;
+ m_blupiOver = FALSE;
+ m_blupiJeep = TRUE;
+ m_blupiTank = FALSE;
+ m_blupiSkate = FALSE;
+ m_blupiNage = FALSE;
+ m_blupiSurf = FALSE;
+ m_blupiVent = FALSE;
+ m_blupiSuspend = FALSE;
+ m_blupiShield = FALSE;
+ m_blupiPower = FALSE;
+ m_blupiCloud = FALSE;
+ m_blupiHide = FALSE;
+ m_blupiInvert = FALSE;
+ m_blupiBalloon = FALSE;
+ m_blupiEcrase = FALSE;
+ }
+ else
+ {
+ PlaySound(SOUND_ENDKO, mob->posCurrent, FALSE);
+ }
+ m_goalPhase = 50;
+ }
+ }
+ break;
+ case 12: // roundshield
+ PlaySound(SOUND_STARTSHIELD, m_blupiPos, FALSE);
+ m_blupiShield = TRUE;
+ m_blupiPower = FALSE;
+ m_blupiCloud = FALSE;
+ m_blupiHide = FALSE;
+ m_blupiTimeShield = 100;
+ m_blupiPosMagic = m_blupiPos;
+ m_jauges[JAUGE_POWER].SetHide(FALSE);
+ break;
+ case 13: // quicklollipop
+ m_blupiAction = ACTION_SUCETTE;
+ m_blupiPhase = 0;
+ m_blupiHelico = FALSE;
+ m_blupiOver = FALSE;
+ m_blupiJeep = FALSE;
+ m_blupiTank = FALSE;
+ m_blupiSkate = FALSE;
+ m_blupiShield = FALSE;
+ m_blupiPower = FALSE;
+ m_blupiCloud = FALSE;
+ m_blupiHide = FALSE;
+ m_blupiFocus = FALSE;
+ PlaySound(SOUND_SUCETTE, m_blupiPos, FALSE);
+ break;
+ case 14: // tenbombs
+ m_blupiPerso = 10;
+ PlaySound(SOUND_PERSOTAKE, m_blupiPos, FALSE);
+ break;
+ case 15: // birdlime
+ m_blupiBullet = 10;
+ break;
+ case 16: // drivetank
+ m_blupiAir = FALSE;
+ m_blupiHelico = FALSE;
+ m_blupiOver = FALSE;
+ m_blupiJeep = FALSE;
+ m_blupiTank = TRUE;
+ m_blupiSkate = FALSE;
+ m_blupiNage = FALSE;
+ m_blupiSurf = FALSE;
+ m_blupiVent = FALSE;
+ m_blupiSuspend = FALSE;
+ m_blupiCloud = FALSE;
+ m_blupiHide = FALSE;
+ PlaySound(SOUND_JEEPLOW, m_blupiPos, TRUE);
+ break;
+ case 17: // powercharge
+ m_blupiAction = ACTION_CHARGE;
+ m_blupiPhase = 0;
+ m_blupiHelico = FALSE;
+ m_blupiOver = FALSE;
+ m_blupiJeep = FALSE;
+ m_blupiTank = TRUE;
+ m_blupiSkate = FALSE;
+ m_blupiShield = FALSE;
+ m_blupiPower = FALSE;
+ m_blupiCloud = FALSE;
+ m_blupiHide = FALSE;
+ m_blupiJumpAie = FALSE;
+ m_blupiFocus = FALSE;
+ PlaySound(SOUND_CHARGE, m_blupiPos, FALSE);
+ break;
+ case 18: // hidedrink
+ m_blupiAction = ACTION_DRINK;
+ m_blupiPhase = 0;
+ m_blupiHelico = FALSE;
+ m_blupiOver = FALSE;
+ m_blupiJeep = FALSE;
+ m_blupiTank = FALSE;
+ m_blupiSkate = FALSE;
+ m_blupiShield = FALSE;
+ m_blupiPower = FALSE;
+ m_blupiCloud = FALSE;
+ m_blupiHide = FALSE;
+ m_blupiJumpAie = FALSE;
+ m_blupiFocus = FALSE;
+ PlaySound(SOUND_DRINK, m_blupiPos, FALSE);
+ break;
+ case 22: // iovercraft
+ m_blupiAir = FALSE;
+ m_blupiHelico = FALSE;
+ m_blupiOver = TRUE;
+ m_blupiJeep = FALSE;
+ m_blupiTank = FALSE;
+ m_blupiSkate = FALSE;
+ m_blupiNage = FALSE;
+ m_blupiSurf = FALSE;
+ m_blupiVent = FALSE;
+ m_blupiSuspend = FALSE;
+ StopVehicleSound();
+ PlaySound(SOUND_HELICOSTART, m_blupiPos, FALSE);
+ PlaySound(SOUND_HELICOLOW, m_blupiPos, TRUE);
+ break;
+ case 23: // udynamite
+ m_blupiDynamite = 1;
+ PlaySound(SOUND_PERSOTAKE, m_blupiPos, FALSE);
+ break;
+ case 24: // wellkeys
+ m_blupiCle |= CLE_RED | CLE_GREEN | CLE_BLUE;
+ break;
+ }
+ if (!m_blupiShield && !m_blupiHide && !m_blupiCloud && !m_blupiPower)
+ {
+ m_jauges[JAUGE_POWER].SetHide(TRUE);
+ }
+ if (!m_blupiHelico && !m_blupiOver)
+ {
+ StopSound(SOUND_HELICOHIGH);
+ StopSound(SOUND_HELICOLOW);
+ }
+ if (m_blupiJeep && m_blupiTank)
+ {
+ StopSound(SOUND_JEEPHIGH);
+ StopSound(SOUND_JEEPLOW);
+ }
+}
+
+BOOL CDecor::GetSuperBlupi()
+{
+ return m_bSuperBlupi;
+}
+
+void CDecor::SetSuperBlupi(BOOL bSuper)
+{
+ m_bSuperBlupi = bSuper;
+}
+
+BOOL CDecor::GetDrawSecret()
+{
+ return m_bDrawSecret;
+}
+
+void CDecor::SetDrawSecret(BOOL bDrawSecret)
+{
+ m_bDrawSecret = bDrawSecret;
+}
+
+void CDecor::SetBuildOfficialMissions(BOOL bBuild)
+{
+ m_bBuildOfficialMissions = bBuild;
+}
+
+BOOL CDecor::GetNetPacked()
+{
+ return m_bNetPacked;
+}
+
+void CDecor::SetNetPacked(BOOL bNetPacked)
+{
+ m_bNetPacked = bNetPacked;
+}
+
+BOOL CDecor::GetNetMovePredict()
+{
+ return m_bNetMovePredict;
+}
+
+void CDecor::SetNetMovePredict(BOOL bNetMovePredict)
+{
+ m_bNetMovePredict = bNetMovePredict;
+}
+
+BOOL CDecor::GetNetDebug()
+{
+ return m_bNetDebug;
+}
+
+void CDecor::SetNetDebug(BOOL bNetDebug)
+{
+ m_bNetDebug = bNetDebug;
+ //if (bNetDebug) FUN_2bfb0("debug.txt");
+}
+
+void CDecor::OutputNetDebug(char* text)
+{
+ char textbuffer[100];
+
+ if (!m_bNetDebug) return;
+
+ sprintf(textbuffer, "/ snd=%d(%d)_rcv=%d(%d)", m_netPacketsSent, m_netPacketsSent2, m_netPacketsReceived, m_netPacketsReceived2);
+ // ...?
+}
+
+void CDecor::SetMulti(BOOL multi)
+{
+ m_bMulti = multi;
+}
+
+void CDecor::SetTeam(int team)
+{
+ m_team = team;
+}
+
+POINT CDecor::VoyageGetPosVie(int nbVies)
+{
+ return POINT( nbVies * 20 - 5, 417 );
+}
+
+void CDecor::VoyageInit(POINT start, POINT end, int icon, int channel)
+{
+ if (m_voyageIcon != -1)
+ {
+ m_voyagePhase = m_voyageTotal;
+ VoyageStep();
+ }
+ m_voyageStart = start;
+ m_voyageEnd = end;
+ m_voyageIcon = icon;
+ m_voyageChannel = channel;
+ int num = abs(end.x - start.x);
+ int num2 = abs(end.y - start.y);
+ m_voyagePhase = 0;
+ m_voyageTotal = (num + num2) / 10;
+ if (m_voyageIcon == 48 && m_voyageChannel == CHBLUPI)
+ {
+ m_voyageTotal = 40;
+ m_nbVies--;
+ m_pSound->PlayImage(SOUND_NEW, end, -1);
+ }
+ if (m_voyageIcon == 21 && m_voyageChannel == CHELEMENT)
+ {
+ m_pSound->PlayImage(SOUND_EGG, start, -1);
+ }
+ if (m_voyageIcon == 6 && m_voyageChannel == CHELEMENT)
+ {
+ if (m_nbTresor == m_totalTresor - 1)
+ {
+ m_pSound->PlayImage(SOUND_LASTTRESOR, start, -1);
+ }
+ else
+ {
+ m_pSound->PlayImage(SOUND_TRESOR, start, -1);
+ }
+ }
+ if (m_voyageIcon == 215 && m_voyageChannel == CHELEMENT)
+ {
+ m_pSound->PlayImage(SOUND_TRESOR, start, -1);
+ }
+ if (m_voyageIcon == 222 && m_voyageChannel == CHELEMENT)
+ {
+ m_pSound->PlayImage(SOUND_TRESOR, start, -1);
+ }
+ if (m_voyageIcon == 229 && m_voyageChannel == CHELEMENT)
+ {
+ m_pSound->PlayImage(SOUND_TRESOR, start, -1);
+ }
+ if (m_voyageIcon == 108 && m_voyageChannel == CHBUTTON)
+ {
+ m_pSound->PlayImage(SOUND_PERSOTAKE, start, -1);
+ }
+ if (m_voyageIcon == 252 && m_voyageChannel == CHELEMENT)
+ {
+ m_pSound->PlayImage(SOUND_PERSOTAKE, start, -1);
+ }
+ if (m_voyageIcon == 177 && m_voyageChannel == CHELEMENT)
+ {
+ m_pSound->PlayImage(SOUND_TAKEGLU, start, -1);
+ }
+ if (m_voyageIcon == 230 && m_voyageChannel == CHELEMENT)
+ {
+ m_voyageTotal = 100;
+ }
+ if (m_voyageIcon == 40 && m_voyageChannel == CHELEMENT)
+ {
+ m_voyageTotal = 50;
+ }
+}
+
+void CDecor::VoyageStep()
+{
+ int v3; // eax
+ LONG y; // ecx
+ LONG x; // eax
+ LONG v7; // edx
+ LONG v8; // eax
+ LONG v9; // eax
+ LONG v11; // edx
+ POINT v12; // [esp-30h] [ebp-34h]
+ POINT v13; // [esp-2Ch] [ebp-30h]
+ POINT v14; // [esp-28h] [ebp-2Ch]
+ POINT v15; // [esp-24h] [ebp-28h]
+ POINT v16; // [esp-20h] [ebp-24h]
+ POINT v17; // [esp-18h] [ebp-1Ch]
+ if (m_voyageIcon != -1)
+ {
+ if (m_voyagePhase >= m_voyageTotal)
+ {
+ if (m_voyageIcon == 48 && m_voyageChannel == CDecor::GetBlupiChannelActual())
+ {
+ m_blupiAction = ACTION_STOP;
+ m_blupiPhase = 0;
+ m_blupiFocus = 1;
+ m_blupiEnergyUnused = 100;
+ }
+ if (m_voyageIcon == 21 && m_voyageChannel == 10)
+ {
+ y = m_voyageEnd.y;
+ ++m_nbVies;
+ v17.y = y;
+ v17.x = m_voyageEnd.x;
+ m_pSound->PlayImage(SOUND_JUMPEND, v17, -1);
+ }
+ if (m_voyageIcon == 6 && m_voyageChannel == 10)
+ {
+ ++m_nbTresor;
+ CDecor::OpenDoorsTresor();
+ m_pSound->PlayImage(SOUND_JUMPEND, m_voyageEnd, -1);
+ }
+ if (m_voyageIcon == 215 && m_voyageChannel == 10)
+ {
+ x = m_voyageEnd.x;
+ m_pSound = m_pSound;
+ m_blupiCle |= CLE_RED;
+ v16.y = m_voyageEnd.y;
+ v16.x = x;
+ m_pSound->PlayImage(SOUND_JUMPEND, v16, -1);
+ }
+ if (m_voyageIcon == 222 && m_voyageChannel == CHELEMENT)
+ {
+ v7 = m_voyageEnd.x;
+ m_blupiCle |= CLE_GREEN;
+ v15.y = m_voyageEnd.y;
+ v15.x = v7;
+ m_pSound->PlayImage(SOUND_JUMPEND, v15, -1);
+ }
+ if (m_voyageIcon == 229 && m_voyageChannel == CHELEMENT)
+ {
+ v8 = m_voyageEnd.y;
+ m_blupiCle |= CLE_BLUE;
+ v14.y = v8;
+ v14.x = m_voyageEnd.x;
+ m_pSound->PlayImage(SOUND_JUMPEND, v14, -1);
+ }
+ if (m_voyageIcon == GetIconPerso() && m_voyageChannel == CHBUTTON)
+ {
+ v9 = m_voyageEnd.x;
+ ++m_blupiPerso;
+ v13.y = m_voyageEnd.y;
+ v13.x = v9;
+ m_pSound->PlayImage(SOUND_JUMPEND, v13, -1);
+ }
+ if (m_voyageIcon == 252 && m_voyageChannel == CHELEMENT)
+ {
+ v11 = m_voyageEnd.x;
+ ++m_blupiDynamite;
+ v12.y = m_voyageEnd.y;
+ v12.x = v11;
+ m_pSound->PlayImage(SOUND_JUMPEND, v12, -1);
+ }
+ if (m_voyageIcon == 177 && m_voyageChannel == CHELEMENT)
+ {
+ m_pSound->PlayImage(SOUND_JUMPEND, m_voyageEnd, -1);
+ }
+ m_voyageIcon = -1;
+ }
+ else if (!(m_time % 2) && m_voyageIcon >= 230 && m_voyageIcon <= 241 && m_voyageChannel == CHELEMENT)
+ {
+ m_voyageIcon = m_voyageIcon + 1;
+ if (m_voyageIcon + 1 > 241)
+ {
+ v3 = m_voyagePhase + 1;
+ m_voyageIcon = 230;
+ m_voyagePhase = v3;
+ return;
+ }
+ }
+ ++m_voyagePhase;
+ }
+}
+
+void CDecor::VoyageDraw()
+{
+ POINT v5; // ebx
+ int v6; // eax
+ int v8; // edi
+ int v9; // ebx
+ int v10; // ecx
+ POINT v11; // [esp-14h] [ebp-2Ch]
+ LONG pos; // [esp+10h] [ebp-8h]
+ const int speed[9] = {
+ -8, -6, -1, -1, -1, -4, -1, -1, -1
+ };
+
+ if (m_voyageIcon != -1)
+ {
+ m_voyagePhase = m_voyagePhase;
+ if (m_voyageIcon == 40 && m_voyageChannel == 10)
+ {
+ m_voyagePhase -= 30;
+ if (m_voyagePhase < 0)
+ {
+ m_voyagePhase = 0;
+ }
+ }
+ m_voyageTotal = m_voyageTotal;
+ v5.x = m_voyageStart.x + m_voyagePhase * (m_voyageEnd.x - m_voyageStart.x) / m_voyageTotal;
+ v6 = m_voyageIcon;
+ v5.y = m_voyageStart.y + m_voyagePhase * (m_voyageEnd.y - m_voyageStart.y) / m_voyageTotal;
+ if (v6 != 40 || m_voyageChannel != 10 || m_voyagePhase)
+ {
+ m_pPixmap->QuickIcon(m_voyageChannel, v6, v5);
+ }
+ if (m_voyageIcon == 40 && m_voyageChannel == 10)
+ {
+ v8 = m_posDecor.y + v5.y;
+ pos = v5.x + m_posDecor.x - 34;
+ v9 = speed[Random(0, 6)];
+ v10 = Random(-10, 10);
+ if (!m_voyagePhase)
+ {
+ v9 /= 2;
+ v10 *= 4;
+ }
+ v11.y = v10 + v8;
+ v11.x = pos;
+ ObjectStart(v11, TYPE_EXPLO8, v9, TRUE);
+ }
+ }
+}
+
+BOOL CDecor::DrawMap(BOOL bPlay, int team)
+{
+ return FALSE;
+}
+
+BOOL CDecor::SearchWorld(int world, POINT *cel, POINT *newBlupiPos)
+{
+ for (int x = 0; x < MAXCELX; x++)
+ {
+ for (int y = 0; y < MAXCELY; y++)
+ {
+ int icon = m_decor[x][y].icon;
+ if (icon >= Object::Level_1 && icon <= Object::Level_8)
+ {
+ if (world == icon - Object::Level_1 + 1)
+ {
+ if (x > 1 && m_decor[x - 1][y].icon == Object::DoorLevel)
+ {
+ *cel = POINT( x - 1, y );
+ *newBlupiPos = POINT( (x - 2) * DIMOBJX + 2, y * DIMOBJY + 6 );
+ return TRUE;
+ }
+ if (x > 2 && m_decor[x - 2][y].icon == Object::DoorLevel)
+ {
+ *cel = POINT( x - 2, y );
+ *newBlupiPos = POINT( (x - 3) * DIMOBJX + 2, y * DIMOBJY + 6 );
+ return TRUE;
+ }
+ if (x < MAXCELX - 1 && m_decor[x + 1][y].icon == Object::DoorLevel)
+ {
+ *cel = POINT( x + 1, y );
+ *newBlupiPos = POINT( (x + 2) * DIMOBJX + 2, y * DIMOBJY + 6 );
+ return TRUE;
+ }
+ if (x < MAXCELX - 2 && m_decor[x + 2][y].icon == Object::DoorLevel)
+ {
+ *cel = POINT( x + 2, y );
+ *newBlupiPos = POINT( (x + 3) * DIMOBJX + 2, y * DIMOBJY + 6 );
+ return TRUE;
+ }
+ }
+ }
+ }
+ }
+ return FALSE;
+}
+
+BOOL CDecor::SearchDoor(int n, POINT *cel)
+{
+ for (int y = MAXCELY - 1; y > 0; y--)
+ {
+ for (int x = MAXCELX - 1; x > 0; x--)
+ {
+ if (m_decor[x][y].icon == 183)
+ {
+ cel->x = x;
+ cel->y = y;
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+void CDecor::AdaptDoors(BOOL bPrivate, int mission)
+{
+ POINT cel;
+ int index;
+ int icon;
+ POINT newPosBlupi;
+
+ m_bPrivate = bPrivate;
+ m_mission = mission;
+ if (bPrivate == FALSE)
+ {
+ if (mission == 1)
+ {
+ for (int i = 0; i < 20; ++i)
+ {
+ if (SearchDoor(i, &cel))
+ {
+ if (!m_doors[180 + i] || m_bCheatDoors)
+ {
+ m_decor[cel.x][cel.y].icon = -1;
+ index = MoveObjectFree();
+ m_moveObject[index].type = TYPE_DOOR;
+ m_moveObject[index].stepAdvance = 50;
+ m_moveObject[index].stepRecede = 1;
+ m_moveObject[index].timeStopStart = 0;
+ m_moveObject[index].timeStopEnd = 0;
+ m_moveObject[index].posStart.x = cel.x * DIMOBJX;
+ m_moveObject[index].posStart.y = cel.y * DIMOBJY;
+ m_moveObject[index].posEnd.x = cel.x * DIMOBJX;
+ m_moveObject[index].posEnd.y = cel.y * DIMOBJY - DIMOBJY;
+ m_moveObject[index].posCurrent.x = m_moveObject[index].posStart.x;
+ m_moveObject[index].posCurrent.y = m_moveObject[index].posStart.y;
+ m_moveObject[index].step = STEP_STOPSTART;
+ m_moveObject[index].time = 0;
+ m_moveObject[index].phase = 0;
+ m_moveObject[index].channel = CHOBJECT;
+ m_moveObject[index].icon = 0xb7;
+ PlaySound(SOUND_DOOR, m_moveObject[index].posStart, FALSE);
+ }
+ }
+ }
+ for (int x = MAXCELX - 1; x > 0; x--)
+ {
+ for (int y = MAXCELY - 1; y > 0; y--)
+ {
+ int icon = m_decor[x][y].icon;
+ if (icon >= Object::World_1 && icon <= Object::World_8 && (!m_doors[icon - Object::World_1 + 1] || m_bCheatDoors))
+ {
+ m_decor[x][y].icon += 8;
+ }
+ if (icon == Object::World_9 && (!m_doors[189] || m_bCheatDoors))
+ {
+ m_decor[x][y].icon = Object::WorldDone_9;
+ }
+ if (icon >= Object::World_10 && icon <= Object::World_14 && (!m_doors[icon - Object::World_10 + 1] || m_bCheatDoors))
+ {
+ m_decor[x][y].icon += 5;
+ }
+ }
+ }
+ }
+ else if (mission % 10 == 0)
+ {
+ for (int i = 0; i < 10; ++i)
+ {
+ if (SearchWorld(i, &cel, &newPosBlupi))
+ {
+ if (!m_doors[mission + i] || m_bCheatDoors)
+ {
+ OpenDoor(cel);
+ for (int j = 0; j < MAXNETPLAYER; j++)
+ {
+ m_blupiStartPos[j] = newPosBlupi;
+ m_blupiStartDir[j] = (m_blupiStartPos[j].x < cel.x * DIMOBJX) ? DIR_RIGHT : DIR_LEFT;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void CDecor::OpenDoorsTresor()
+{
+ for (int x = 0; x < MAXCELX; x++)
+ {
+ for (int y = 0; y < MAXCELY; y++)
+ {
+ int icon = m_decor[x][y].icon;
+ if (icon >= 0x1a5 && icon <= 0x1a5 + m_nbTresor - 1)
+ {
+ OpenDoor(POINT( x, y ));
+ }
+ }
+ }
+}
+
+void CDecor::OpenDoor(POINT cel)
+{
+ int icon = m_decor[cel.x][cel.y].icon;
+ m_decor[cel.x][cel.y].icon = -1;
+ int num = MoveObjectFree();
+ m_moveObject[num].type = TYPE_DOOR;
+ m_moveObject[num].stepAdvance = 50;
+ m_moveObject[num].stepRecede = 1;
+ m_moveObject[num].timeStopStart = 0;
+ m_moveObject[num].timeStopEnd = 0;
+ m_moveObject[num].posStart.x = DIMOBJX * cel.x;
+ m_moveObject[num].posStart.y = DIMOBJY * cel.y;
+ m_moveObject[num].posEnd.x = DIMOBJX * cel.x;
+ m_moveObject[num].posEnd.y = DIMOBJY * (cel.y - 1);
+ m_moveObject[num].posCurrent = m_moveObject[num].posStart;
+ m_moveObject[num].step = STEP_STOPSTART;
+ m_moveObject[num].time = 0;
+ m_moveObject[num].phase = 0;
+ m_moveObject[num].channel = CHOBJECT;
+ m_moveObject[num].icon = icon;
+ PlaySound(SOUND_DOOR, m_moveObject[num].posStart, FALSE);
+}
+
+void CDecor::OpenDoorsWin()
+{
+ m_doors[m_mission + 1] = 0;
+}
+
+void CDecor::OpenGoldsWin()
+{
+ m_doors[180 + m_mission / 10] = 0;
+}
+
+void CDecor::DoorsLost()
+{
+ m_nbVies = 3;
+ // more...
+}
+
+
+
+// Winphone functions, likely unnecessary
+/*
+BOOL CDecor::SearchGold(int n, POINT cel)
+{
+for (int i = 99; i >= 0; i--)
+{
+for (int j = 99; j >= 0; j--)
+{
+if (m_decor[j][i].icon == 183)
+{
+cel.x = j;
+cel.y = i;
+return TRUE;
+}
+}
+}
+return FALSE;
+}
+
+BOOL CDecor::IsFloatingObject(int i)
+{
+POINT posCurrent = m_moveObject[i]->posCurrent;
+int num = (posCurrent.x + 32) / 64;
+int num2 = posCurrent.y / 64 + 1;
+int icon = m_decor[num, num2]->icon;
+return IsPassIcon(icon);
+}
+
+BOOL CDecor::IsNormalJump(POINT pos)
+{
+pos.x += 32;
+pos.y -= 32;
+if (m_blupiDir == 1)
+{
+pos.x -= 15;
+}
+else
+{
+pos.x += 15;
+}
+for (int i = 0; i < 2; i++)
+{
+int num = pos.x / DIMOBJX;
+int num2 = pos.y / DIMOBJY;
+if (num2 < 0)
+{
+return FALSE;
+}
+int icon = m_decor[num, num2]->icon;
+if (!IsPassIcon(icon))
+{
+return FALSE;
+}
+pos.y -= 64;
+}
+return TRUE;
+}*/
\ No newline at end of file
diff --git a/src/decor.h b/src/decor.h
new file mode 100644
index 0000000..b0b4fe5
--- /dev/null
+++ b/src/decor.h
@@ -0,0 +1,645 @@
+// Decor.h
+#ifndef DECOR_H
+#define DECOR_H
+
+#include "DEF.H"
+#include "jauge.h"
+#include "sound.h"
+#include "pixmap.h"
+#include "network.h"
+
+/////////////////////////////////////////////////////////////////////////////
+
+#define MAXQUART 441
+#define SCROLL_SPEED 8
+#define SCROLL_MARGX 80
+#define SCROLL_MARGY 40
+
+#define BLUPIFLOOR 2
+#define BLUPIOFFY 4 + BLUPIFLOOR
+#define BLUPISURF 12
+#define BLUPISUSPEND 12
+#define OVERHEIGHT 80
+
+#define TEXTDELAY 10 // tooltip popup delay
+#define NOTIFDELAY 200
+
+typedef struct
+{
+ short icon;
+}
+Cellule;
+
+typedef struct
+{
+ short type;
+ short stepAdvance;
+ short stepRecede;
+ short timeStopStart;
+ short timeStopEnd;
+ short unknown1;
+ POINT posStart;
+ POINT posEnd;
+ POINT posCurrent;
+ short step;
+ short time;
+ short phase;
+ short channel;
+ short icon;
+ short unknown2;
+}
+MoveObject;
+
+typedef struct
+{
+ char type;
+ char data1;
+ short data2;
+ short data3;
+ short data4;
+}
+NetMessage;
+
+typedef struct
+{
+ char size;
+ char type;
+ short keyPress;
+ int time;
+ short blupiPosX;
+ short blupiPosY;
+ short blupiIcon;
+ short blupiSec;
+ char blupiChannel;
+ char blupiTransport;
+ char unk12;
+ char nbMessages;
+ NetMessage messages[MAXMESSAGEPERPACKET];
+}
+NetPacket;
+
+typedef struct
+{
+ short majRev;
+ short minRev;
+ short reserve1[100];
+ POINT posDecor;
+ POINT dimDecor;
+ short world;
+ short music;
+ short region;
+ short reserve2[51];
+ POINT blupiPos[4];
+ int blupiDir[4];
+ char name[100];
+ short reserve3[196];
+}
+DescFile;
+
+typedef struct
+{
+ int lg;
+ int majRev;
+ int minRev;
+ int reserve1[50];
+ short decor[100][100];
+ short bigDecor[100][100];
+ char balleTraj[100][13];
+ char moveTraj[100][13];
+ MoveObject moveObject[200];
+ int reserve2[50];
+ POINT posDecor;
+ POINT dimDecor;
+ int phase;
+ int term;
+ int music;
+ int region;
+ int time;
+ char missionTitle[100];
+ int reserve3[50];
+ int nbRankCaisse;
+ int rankCaisse[200];
+ int nbLinkCaisse;
+ int linkCaisse[200];
+ int reserve4[50];
+ POINT blupiPos;
+ POINT blupiValidPos;
+ int blupiAction;
+ int blupiDir;
+ int blupiPhase;
+ POINT blupiVitesse;
+ int blupiIcon;
+ int blupiSec;
+ int blupiChannel;
+ POINT blupiVector;
+ int blupiTransport;
+ BOOL blupiFocus;
+ BOOL blupiAir;
+ BOOL blupiHelico;
+ BOOL blupiJeep;
+ BOOL blupiTank;
+ BOOL blupiSkate;
+ BOOL blupiNage;
+ BOOL blupiSurf;
+ BOOL blupiVent;
+ BOOL blupiSuspend;
+ BOOL blupiJumpAie;
+ BOOL blupiShield;
+ BOOL blupiPower;
+ BOOL blupiCloud;
+ BOOL blupiHide;
+ POINT blupiPosHelico;
+ POINT blupiPosMagic;
+ BOOL blupiRestart;
+ BOOL blupiFront;
+ int blupiBullet;
+ int blupiCle;
+ int blupiPerso;
+ int blupiNoBarre;
+ int blupiTimeShield;
+ int blupiTimeFire;
+ int blupiTimeOuf;
+ int blupiActionOuf;
+ int blupiFifoNb;
+ POINT blupiFifoPos[MAXFIFOPOS];
+ BOOL blupiInvert;
+ BOOL blupiBalloon;
+ BOOL blupiOver;
+ BOOL blupiEcrase;
+ int blupiTimeNoAsc;
+ int blupiDynamite;
+ int reserve5[41];
+ POINT blupiStartPos[4];
+ int blupiStartDir[4];
+ int reserve6[50];
+ BOOL jaugeHide[2];
+ BOOL jaugeType[2];
+ BOOL jaugeLevel[2];
+ int blupiLevel;
+ int energyUnused;
+ int reserve7[50];
+ BOOL bHelicoMarch;
+ BOOL bHelicoStop;
+ BOOL bJeepMarch;
+ BOOL bJeepStop;
+ int reserve8[50];
+ BOOL bFoundCle;
+ BOOL bPrivate;
+ BOOL bCheatDoors;
+ BOOL bSuperBlupi;
+ BOOL bDrawSecret;
+ BOOL bJoystick;
+ int idklol;
+ int mission;
+ char doors[200];
+ int nbVies;
+ int nbTresor;
+ int totalTresor;
+ int goalPhase;
+ int reserve9[50];
+ int d8f8;
+ POINT scrollPoint;
+ POINT scrollAdd;
+ int reserve10[50];
+ int voyageIcon;
+ int voyageChannel;
+ int voyagePhase;
+ int voyageTotal;
+ POINT voyageStart;
+ POINT voyageEnd;
+ int reserve11[50];
+ int decorAction;
+ int decorPhase;
+ int reserve12[50];
+}
+DescSave;
+
+class CDecor
+{
+public:
+ CDecor();
+ ~CDecor();
+
+ // Decor.cpp
+ void Create(HWND hWnd, CSound *pSound, CPixmap *pPixmap,
+ CNetwork *pNetwork);
+ BOOL LoadImages();
+ void InitGamer();
+ void InitDecor();
+ void SetTime(int time);
+ int GetTime();
+ void PlayPrepare(BOOL bTest);
+ void BuildPrepare();
+ int IsTerminated();
+ void MoveStep();
+ int GetBlupiChannelStandard();
+ int GetBlupiChannelActual();
+ int GetIconPerso();
+ void Build(RECT rect);
+ void DrawInfo();
+ POINT DecorNextAction();
+ void SetInput(int keys);
+ void SetJoystickEnable(BOOL bJoystick);
+ void SetDemoPlay(BOOL param_1);
+ void PlaySound(int sound, POINT pos, BOOL bLocal);
+ void PlaySound(int sound, POINT pos); // hack
+ void StopSound(int sound);
+ void AdaptMotorVehicleSound(POINT pos);
+ void VehicleSoundsPhase(int phase);
+
+ int GetRegion();
+ void SetRegion(int region);
+ int GetMusic();
+ void SetMusic(int music);
+ POINT GetDim();
+ void SetDim(POINT dim);
+ int GetNbVies();
+ void SetNbVies(int nbVies);
+ BOOL GetPause();
+ void SetPause(BOOL bPause);
+ void InitializeDoors(BYTE *doors);
+ void MemorizeDoors(BYTE* doors);
+ void SetAllMissions(BOOL bAllMissions);
+ void CheatAction(int cheat);
+ BOOL GetSuperBlupi();
+ void SetSuperBlupi(BOOL bSuperBlupi);
+ BOOL GetDrawSecret();
+ void SetDrawSecret(BOOL bDrawSecret);
+ void SetBuildOfficialMissions(BOOL bBuildOfficialMissions);
+ BOOL GetNetPacked();
+ void SetNetPacked(BOOL bNetPacked);
+ BOOL GetNetMovePredict();
+ void SetNetMovePredict(BOOL bNetMovePredict);
+ BOOL GetNetDebug();
+ void SetNetDebug(BOOL bNetDebug);
+ void OutputNetDebug(char* text);
+ void SetMulti(BOOL bMulti);
+ void SetTeam(int team);
+ POINT VoyageGetPosVie(int nbVies);
+ void VoyageInit(POINT start, POINT end, int icon, int channel);
+ void VoyageStep();
+ void VoyageDraw();
+ BOOL DrawMap(BOOL bPlay, int team);
+
+ // DecBlock.cpp
+ BOOL BlitzActif(POINT cel);
+ int SoundEnviron(int sound, int obstacle);
+ int IsWorld(POINT pos);
+ void ActiveSwitch(BOOL bState, POINT cel);
+ int GetTypeBarre(POINT pos);
+ BOOL IsLave(POINT pos);
+ BOOL IsPiege(POINT pos);
+ BOOL IsGoutte(POINT pos, BOOL bAlways);
+ BOOL IsScie(POINT pos);
+ BOOL IsSwitch(POINT pos, POINT *outCelSwitch);
+ BOOL IsEcraseur(POINT pos);
+ BOOL IsBlitz(POINT pos, BOOL bAlways);
+ BOOL IsRessort(POINT pos);
+ BOOL IsTemp(POINT pos);
+ BOOL IsBridge(POINT pos, POINT *outCelBridge);
+ int IsDoor(POINT pos, POINT *outCelPorte);
+ int IsTeleporte(POINT pos);
+ BOOL SearchTeleporte(POINT pos, POINT *newpos);
+ BOOL IsSurfWater(POINT pos);
+ BOOL IsDeepWater(POINT pos);
+ BOOL IsOutWater(POINT pos);
+ BOOL IsPassIcon(int icon);
+ BOOL IsBlocIcon(int icon);
+ BOOL IsVentillo(POINT pos);
+ void ModifDecor(POINT pos, int icon, BOOL bMulti=TRUE);
+ BOOL IsRightBorder(POINT cel, POINT offset);
+ BOOL IsFromage(POINT cel);
+ BOOL IsGrotte(POINT cel);
+ void AdaptMidBorder(POINT cel);
+ void AdaptBorder(POINT cel);
+
+ // DecDesign.cpp
+ POINT ScreenPosToCelPos(POINT pos);
+ void SetCelPosFromScreenPos(POINT pos);
+ void SetFieldCC38AndStuff(int _foo, int _bar);
+ void DeleteCel(POINT cel);
+ void PlaceMenuItem(short *pCel, int *pTable, int lastIndex, BYTE flags, int currentIcon, BOOL bRand);
+ void PlaceItemFromMenu1(POINT cel, int index, BYTE flags, int currentIcon);
+ void PlaceItemFromMenu2(POINT cel, int index, BYTE flags, int currentIcon);
+ void PlaceItemFromMenu3(POINT cel, int index, BYTE flags, int currentIcon);
+ void PlaceItemFromMenu4(POINT cel, int index, BYTE flags, int currentIcon);
+ void PlaceItemFromMenu5(POINT cel, int index, BYTE flags, int currentIcon);
+ void PlaceItemFromMenu6(POINT cel, int index, BYTE flags, int currentIcon);
+ void PlaceItemFromMenu7(POINT cel, int index, BYTE flags, int currentIcon);
+ void PlaceItemFromMenu8(POINT cel, int index, BYTE flags, int currentIcon);
+ void PlaceItemFromMenu9(POINT cel, int index, BYTE flags, int currentIcon);
+ void PlaceItemFromMenu10(POINT cel, int index, BYTE flags, int currentIcon);
+ char* GetMissionTitle();
+ void SetMissionTitle(char *str);
+
+ // DecBlupi.cpp
+ void BlupiSearchIcon();
+ BOOL BlupiIsGround();
+ RECT BlupiRect(POINT pos);
+ void BlupiAdjust();
+ BOOL BlupiBloque(POINT pos, int dir);
+ void BlupiStep();
+ void BlupiDead(int action, int action2);
+ POINT GetPosDecor(POINT pos);
+ void BlupiAddFifo(POINT pos);
+ BOOL DecorDetect(RECT rect, BOOL bCaisse=TRUE);
+ void GetBlupiInfo(BOOL *pbHelico, BOOL *pbJeep, BOOL *pbSkate,
+ BOOL *pbNage);
+
+ // DecMove.cpp
+ BOOL TestPath(RECT rect, POINT start, POINT *end);
+ void MoveObjectPollution();
+ void MoveObjectPlouf(POINT pos);
+ void MoveObjectTiplouf(POINT pos);
+ void MoveObjectBlup(POINT pos);
+ void FlushBalleTraj();
+ void SetBalleTraj(POINT pos);
+ BOOL IsBalleTraj(POINT pos);
+ void FlushMoveTraj();
+ void SetMoveTraj(POINT pos);
+ BOOL IsMoveTraj(POINT pos);
+ int SearchDistRight(POINT pos, POINT dir, int type);
+ void StartSploutchGlu(POINT pos);
+ BOOL ObjectStart(POINT pos, int type, int speed);
+ BOOL ObjectStart(POINT pos, int type, int speed, BOOL bMulti);
+ BOOL ObjectDelete(POINT pos, int type, BOOL bMulti = TRUE);
+ void MoveObjectStep();
+ void MoveObjectStepLine(int i);
+ void MoveObjectStepIcon(int i);
+ void DynamiteStart(int i, int dx, int dy);
+ int AscenseurDetect(RECT rect, POINT oldpos, POINT newpos);
+ void AscenseurVertigo(int i, BOOL *pbVertigoLeft, BOOL *pbVertigoRight);
+ BOOL AscenseurShift(int i);
+ void AscenseurSynchro(int i);
+ void UpdateCaisse();
+ BOOL TestPushCaisse(int i, POINT pos, BOOL bPop);
+ BOOL TestPushOneCaisse(int i, POINT move, int b);
+ void SearchLinkCaisse(int rank, BOOL bPop);
+ BOOL AddLinkCaisse(int rank);
+ int CaisseInFront();
+ int CaisseGetMove(int max);
+ BOOL MockeryDetect(POINT pos);
+ BOOL BlupiElectro(POINT pos);
+ void MoveObjectFollow(POINT pos);
+ int MoveObjectDetect(POINT pos, BOOL *pbNear);
+ int MoveAscenseurDetect(POINT pos, int height);
+ int MoveChargeDetect(POINT pos);
+ int MovePersoDetect(POINT pos);
+ int MoveBalleDetect(POINT pos);
+ int MoveObjectDelete(POINT pos);
+ int MoveObjectFree();
+ int SortGetType(int type);
+ void MoveObjectSort();
+ void MoveObjectPriority(int i);
+ int MoveObjectSearch(POINT pos, int type);
+
+ // DecNet.cpp
+ void NetStopCloud(int rank);
+ void NetPlaySound(short channel, POINT pos);
+ void NetStopSound(short channel);
+ void NetDataFlush();
+ void NetSendBarePacket(BYTE _foo, short _bar);
+ void TreatNetData();
+ void DoNetSmooth(int player);
+ void NetAdjustToLift();
+ void NetAscenseurSynchro(int rank, short step);
+ void NetPlayerCollide(POINT pos, int *out);
+ void NetMessageIndexFlush();
+ BOOL NetMessagePush(NetMessage *message);
+ BOOL NetMessagePop(NetMessage *message);
+ void NotifFlush();
+ void NotifPop();
+ void NotifPush(char *str);
+ void NotifStep();
+
+ // DecIO.cpp
+ void GetMissionPath(char *out, int gamer, int mission, BOOL bUser);
+ BOOL Write(int gamer, int mission, BOOL bUser);
+ BOOL Read(int gamer, int mission, BOOL bUser);
+ BOOL SomethingMissionPath(int gamer, int mission, BOOL bUser);
+ BOOL CurrentWrite(int gamer, int mission, BOOL bUser=FALSE);
+ BOOL CurrentRead(int gamer, int mission, BOOL *pbMission, BOOL *pbPrivate);
+ BOOL MissionStart(int gamer, int mission, char* param3);
+
+ BOOL SearchWorld(int world, POINT *cel, POINT *newBlupiPos);
+ BOOL SearchDoor(int n, POINT *cel);
+ void AdaptDoors(BOOL bPrivate, int mission);
+ void OpenDoorsTresor();
+ void OpenDoor(POINT cel);
+ void OpenDoorsWin();
+ void OpenGoldsWin();
+ void DoorsLost();
+
+ BOOL DeleteMission(int user, int mission, BOOL bUser);
+
+ inline BOOL IsValidCel(POINT cel);
+ inline void MoveObjectCopy(MoveObject *src, MoveObject *dest);
+ inline void StopVehicleSound();
+ inline BOOL IsDeadAction(int action);
+ inline void StopBlupi(BOOL bFocus = FALSE);
+ inline BOOL IsBlupiVehicle();
+ inline BOOL IsBlupiMotorVehicle();
+ inline BOOL IsBlupiStanding();
+
+protected:
+ HWND m_hWnd;
+ CSound* m_pSound;
+ CPixmap* m_pPixmap;
+ CNetwork* m_pNetwork;
+ Cellule m_decor[MAXCELX][MAXCELY];
+ Cellule m_bigDecor[MAXCELX][MAXCELY];
+ byte m_balleTraj[MAXCELX * MAXCELY / 8 + 1];
+ byte m_moveTraj[MAXCELX * MAXCELY / 8 + 1];
+ MoveObject m_moveObject[MAXMOVEOBJECT];
+ int m_keyPress;
+ int m_lastKeyPress;
+ POINT m_posDecor;
+ POINT m_dimDecor;
+ POINT m_posCelHili;
+ POINT m_dimCelHili;
+ int m_2ndPositionCalculationSlot;
+ int m_phase;
+ int m_term;
+ int m_music;
+ int m_region;
+ int m_lastRegion;
+ int m_iconLift;
+ int m_time;
+ char m_missionTitle[100];
+ BOOL m_bPause;
+ int m_nbRankCaisse;
+ int m_rankCaisse[MAXMOVEOBJECT];
+ int m_nbLinkCaisse;
+ int m_linkCaisse[MAXMOVEOBJECT];
+ POINT m_blupiPos;
+ POINT m_blupiValidPos;
+ int m_blupiAction;
+ int m_blupiDir;
+ int m_blupiPhase;
+ POINT m_blupiVitesse;
+ int m_blupiIcon;
+ int m_blupiSec;
+ int m_blupiChannel;
+ POINT m_blupiVector;
+ int m_blupiTransport;
+ BOOL m_blupiFocus;
+ BOOL m_blupiAir;
+ BOOL m_blupiHelico;
+ BOOL m_blupiOver;
+ BOOL m_blupiJeep;
+ BOOL m_blupiTank;
+ BOOL m_blupiSkate;
+ BOOL m_blupiNage;
+ BOOL m_blupiSurf;
+ BOOL m_blupiVent;
+ BOOL m_blupiSuspend;
+ BOOL m_blupiJumpAie;
+ BOOL m_blupiShield;
+ BOOL m_blupiPower;
+ BOOL m_blupiCloud;
+ BOOL m_blupiHide;
+ BOOL m_blupiInvert;
+ BOOL m_blupiBalloon;
+ BOOL m_blupiEcrase;
+ POINT m_blupiPosHelico;
+ POINT m_blupiPosMagic;
+ BOOL m_blupiRestart;
+ BOOL m_blupiFront;
+ int m_blupiBullet;
+ int m_blupiCle;
+ int m_blupiPerso;
+ int m_blupiDynamite;
+ int m_blupiNoBarre;
+ int m_blupiTimeShield;
+ int m_blupiTimeFire;
+ int m_blupiTimeNoAsc;
+ int m_blupiTimeMockery;
+ int m_blupiTimeOuf;
+ int m_blupiActionOuf;
+ int m_blupiFifoNb;
+ POINT m_blupiFifoPos[10];
+ POINT m_blupiStartPos[4];
+ int m_blupiStartDir[4];
+ BOOL m_bMulti;
+ int m_team;
+ int m_netPacketsSent;
+ int m_netPacketsSent2;
+ int m_netPacketsReceived;
+ int m_netPacketsReceived2;
+ POINT m_netBlupiPos[MAXNETPLAYER];
+ int m_netBlupiIcon[MAXNETPLAYER];
+ int m_netBlupiSec[MAXNETPLAYER];
+ int m_netBlupiTransport[MAXNETPLAYER];
+ int m_netTransports[MAXNETPLAYER]; // index of lift ridden by each player, or -1
+ int m_netTimes[MAXNETPLAYER];
+ int m_netPrevTimes[MAXNETPLAYER];
+ int m_netTimeSincePacket[MAXNETPLAYER];
+ POINT m_netVitesses[MAXNETPLAYER];
+ POINT m_netBlupiPrevPos[MAXNETPLAYER];
+ POINT m_netPacketPos;
+ int m_netPacketIcon;
+ NetMessage m_netMessages[MAXNETMESSAGE];
+ int m_netMessageIndex1;
+ int m_netMessageIndex2;
+ int m_netMessageIndex3;
+ char m_notifText[MAXNOTIF][100];
+ int m_notifTime;
+ CJauge m_jauges[2];
+ int m_blupiLevel;
+ int m_blupiEnergyUnused;
+ BOOL m_bHelicoMarch;
+ BOOL m_bHelicoStop;
+ BOOL m_bJeepMarch;
+ BOOL m_bJeepStop;
+ BOOL m_bFoundCle;
+ BOOL m_bPrivate;
+ BOOL m_bCheatDoors; // opendoors
+ BOOL m_bSuperBlupi; // megablupi
+ BOOL m_bDrawSecret; // showsecret
+ BOOL m_bBuildOfficialMissions; // xmission/xnjttjpo
+ BOOL m_bNetPacked; // netpacked
+ BOOL m_bNetMovePredict; // ynosmooth
+ BOOL m_bNetDebug; // znetdebug
+ BOOL m_bJoystick;
+ int m_bDemoPlay;
+ int m_mission;
+ BYTE m_doors[200];
+ int m_nbVies;
+ int m_nbTresor;
+ int m_totalTresor;
+ int m_goalPhase;
+ int m_detectIcon;
+ int m_D8F8;
+ POINT m_scrollPoint;
+ POINT m_scrollAdd;
+ int m_voyageIcon;
+ int m_voyageChannel;
+ int m_voyagePhase;
+ int m_voyageTotal;
+ POINT m_voyageStart;
+ POINT m_voyageEnd;
+ int m_decorAction;
+ int m_decorPhase;
+ int m_lastDecorIndexes[200];
+ int reserve[11];
+ BYTE dummy[100000];
+};
+
+POINT GetCel(int x, int y);
+POINT GetCel(POINT cel, int x, int y);
+POINT GetVector(int direct);
+
+inline BOOL CDecor::IsValidCel(POINT cel)
+{
+ return cel.x >= 0 && cel.x < MAXCELX && cel.y >= 0 && cel.y < MAXCELY;
+}
+
+inline void CDecor::MoveObjectCopy(MoveObject *dest, MoveObject *src)
+{
+ memcpy(dest, src, sizeof(dest));
+}
+
+inline void CDecor::StopVehicleSound()
+{
+ StopSound(SOUND_HELICOHIGH);
+ StopSound(SOUND_HELICOLOW);
+ StopSound(SOUND_JEEPHIGH);
+ StopSound(SOUND_JEEPLOW);
+}
+
+inline BOOL CDecor::IsDeadAction(int action)
+{
+ return action == ACTION_CLEAR1 || (action >= ACTION_CLEAR2 && action <= ACTION_CLEAR8);
+}
+
+inline void CDecor::StopBlupi(BOOL bSetFocus)
+{
+ m_blupiAction = ACTION_STOP;
+ m_blupiPhase = 0;
+ if (bSetFocus) m_blupiFocus = TRUE;
+}
+
+inline BOOL CDecor::IsBlupiVehicle()
+{
+ return IsBlupiMotorVehicle() || m_blupiSkate;
+}
+
+inline BOOL CDecor::IsBlupiMotorVehicle()
+{
+ return m_blupiHelico || m_blupiOver || m_blupiJeep || m_blupiTank;
+}
+
+inline BOOL CDecor::IsBlupiStanding()
+{
+ return !(m_blupiAction == ACTION_TURN ||
+ m_blupiAction == ACTION_JUMP ||
+ m_blupiAction == ACTION_AIR ||
+ m_blupiAction == ACTION_VERTIGO ||
+ m_blupiAction == ACTION_ADVANCE ||
+ m_blupiAction == ACTION_RECEDE) &&
+ !IsBlupiVehicle() &&
+ !(m_blupiAir || m_blupiBalloon || m_blupiEcrase ||
+ m_blupiNage || m_blupiSurf || m_blupiSuspend);
+}
+
+#endif
diff --git a/src/dectables.h b/src/dectables.h
new file mode 100644
index 0000000..1d17db5
--- /dev/null
+++ b/src/dectables.h
@@ -0,0 +1,695 @@
+#ifndef DECTABLES_H
+#define DECTABLES_H
+
+#include "obstacle.h"
+
+extern int table_blitz[] =
+{
+ 0, 7, 15, 18, 26, 27, 32, 39, 45, 47,
+ 50, 58, 60, 62, 64, 66, 68, 70, 71, 72,
+ -1
+};
+
+extern int table_vitesse_march[] =
+{
+ 2, 4, 6, 8
+};
+
+extern int table_vitesse_nage[] =
+{
+ 2, 1, 5, 10, 8, 6, 4
+};
+
+extern int table_vitesse_surf[] =
+{
+ 0, 2, 5, 8, 3, 0
+};
+
+extern int table_bulldozer_left[] = { 66, 66, 67, 67, 66, 66, 65, 65 };
+
+extern int table_bulldozer_right[] = { 58, 58, 57, 57, 58, 58, 59, 59 };
+
+extern int table_bulldozer_turn2l[] =
+{
+ 58, 59, 59, 59, 60, 60, 60, 61, 61, 62,
+ 62, 63, 63, 64, 64, 64, 65, 65, 65, 66,
+ 66, 66
+};
+
+extern int table_bulldozer_turn2r[] =
+{
+ 66, 65, 65, 65, 64, 64, 64, 63, 63, 62,
+ 62, 61, 61, 60, 60, 60, 59, 59, 59, 58,
+ 58, 58
+};
+
+extern int table_poisson_left[] = { 82, 82, 81, 81, 82, 82, 83, 83 };
+
+extern int table_poisson_right[] = { 79, 79, 78, 78, 79, 79, 80, 80 };
+
+extern int table_poisson_turn2l[] =
+{
+ 79, 79, 80, 80, 84, 84, 85, 85, 86, 86,
+ 87, 87, 88, 88, 83, 83, 82, 82, 83, 83,
+ 88, 88, 87, 87, 86, 86, 85, 85, 84, 84,
+ 79, 79, 79, 79, 80, 80, 84, 84, 85, 85,
+ 86, 86, 87, 87, 88, 88, 83, 83
+};
+
+extern int table_poisson_turn2r[] =
+{
+ 82, 82, 83, 83, 88, 88, 87, 87, 86, 86,
+ 85, 85, 84, 84, 79, 79, 79, 79, 80, 80,
+ 84, 84, 85, 85, 86, 86, 87, 87, 88, 88,
+ 83, 83, 82, 82, 83, 83, 88, 88, 87, 87,
+ 86, 86, 85, 85, 84, 84, 79, 79
+};
+
+extern int table_oiseau_left[] = { 98, 99, 100, 101, 102, 103, 104, 105 };
+
+extern int table_oiseau_right[] = { 90, 91, 92, 93, 94, 95, 96, 97 };
+
+extern int table_oiseau_turn2l[] = { 106, 107, 108, 109, 110, 111, 112, 113, 105, 105 };
+
+extern int table_oiseau_turn2r[] = { 114, 115, 116, 117, 118, 119, 120, 121, 97, 97 };
+
+extern int table_guepe_left[] = { 195, 196, 197, 198, 197, 196 };
+
+extern int table_guepe_right[] = { 199, 200, 201, 202, 201, 200 };
+
+extern int table_guepe_turn2l[] = { 5, 207, 206, 205, 204, 203 };
+
+extern int table_guepe_turn2r[] = { 203, 204, 205, 206, 207 };
+
+extern int table_creature_left[] = { 247, 248, 249, 250, 251, 250, 249, 248 };
+
+extern int table_creature_right[] = { 247, 248, 249, 250, 251, 250, 249, 248 };
+
+extern int table_creature_turn2[] =
+{
+ 0xF4, 0xF4, 0xF4,
+ 0xF4, 0xF4, 0xF4,
+ 0xF4, 0xF4, 0xF3,
+ 0xF3, 0xF2, 0xF2,
+ 0xF2, 0xF2, 0xF2,
+ 0xF2, 0xF2, 0xF2,
+ 0xF3, 0xF3, 0xF4,
+ 0xF4, 0xF5, 0xF5,
+ 0xF6, 0xF6, 0xF6,
+ 0xF6, 0xF6, 0xF6,
+ 0xF6, 0xF6, 0xF5,
+ 0xF5, 0xF4, 0xF4,
+ 0xF3, 0xF3, 0xF2,
+ 0xF2, 0xF2, 0xF2,
+ 0xF2, 0xF2, 0xF3,
+ 0xF3, 0xF4, 0xF4,
+ 0xF5, 0xF5, 0xF6,
+ 0xF6, 0xF6, 0xF6,
+ 0xF6, 0xF6, 0xF5,
+ 0xF5, 0xF4, 0xF4,
+ 0xF3, 0xF3, 0xF2,
+ 0xF2, 0xF2, 0xF2,
+ 0xF3, 0xF3, 0xF4,
+ 0xF4, 0xF5, 0xF5,
+ 0xF6, 0xF6, 0xF6,
+ 0xF6, 0xF5, 0xF5,
+ 0xF4, 0xF4, 0xF3,
+ 0xF3, 0xF2, 0xF2,
+ 0xF3, 0xF3, 0xF4,
+ 0xF4, 0xF5, 0xF5,
+ 0xF6, 0xF6, 0xF5,
+ 0xF5, 0xF4, 0xF4,
+ 0xF3, 0xF3, 0xF2,
+ 0xF2, 0xF3, 0xF3,
+ 0xF4, 0xF4, 0xF5,
+ 0xF5, 0xF6, 0xF6,
+ 0xF5, 0xF5, 0xF4,
+ 0xF4, 0xF4, 0xF4,
+ 0xF7, 0xF7, 0xF8,
+ 0xF8, 0xF9, 0xF9,
+ 0xFA, 0xFA, 0xFB,
+ 0xFB, 0xFA, 0xFA,
+ 0xF9, 0xF9, 0xF8,
+ 0xF8, 0xF2, 0xF2,
+ 0xF3, 0xF3, 0xF4,
+ 0xF4, 0xF5, 0xF5,
+ 0xF6, 0xF6, 0xF5,
+ 0xF5, 0xF4, 0xF4,
+ 0xF3, 0xF3, 0xF2,
+ 0xF2, 0xF2, 0xF2,
+ 0xF3, 0xF3, 0xF4,
+ 0xF4, 0xF5, 0xF5,
+ 0xF6, 0xF6, 0xF6,
+ 0xF6, 0xF5, 0xF5,
+ 0xF4, 0xF4, 0xF3,
+ 0xF3, 0xF2, 0xF2,
+ 0xF2, 0xF2, 0xF2,
+ 0xF2, 0xF3, 0xF3,
+ 0xF4, 0xF4, 0xF5,
+ 0xF5, 0xF6, 0xF6,
+ 0xF6, 0xF6, 0xF6,
+ 0xF6, 0xF5, 0xF5,
+ 0xF4, 0xF4, 0xF4,
+ 0xF4, 0xF4, 0xF4,
+ 0xF4, 0xF4, 0xF4,
+ 0xF4, 0xF4, 0xF4,
+ 0xF4, 0xF4
+};
+
+extern int table_blupih_left[] = { 66, 67, 68, 67, 66, 69, 70, 69 };
+
+extern int table_blupih_right[] = { 61, 62, 63, 62, 61, 64, 65, 64 };
+
+extern int table_blupih_turn2l[] =
+{
+ 71, 71, 72, 72, 73, 73, 74, 74, 75, 75,
+ 68, 68, 275, 275, 271, 271, 271, 271, 272, 272,
+ 273, 273, 273, 273, 275, 275
+};
+
+extern int table_blupih_turn2r[] =
+{
+ 75, 75, 74, 74, 73, 73, 72, 72, 71, 71,
+ 63, 63, 274, 274, 271, 271, 271, 271, 272, 272,
+ 273, 273, 273, 273, 274, 274
+};
+
+extern int table_blupit_left[] = { 249, 249, 250, 250, 249, 249, 248, 248 };
+
+extern int table_blupit_right[] = { 238, 238, 237, 237, 238, 238, 239, 239 };
+
+extern int table_blupit_turn2l[] =
+{
+ 238, 238, 251, 251, 238, 238, 238, 239, 240, 241,
+ 242, 243, 244, 245, 246, 247, 248, 249, 249, 249,
+ 252, 252, 249, 249
+};
+
+extern int table_blupit_turn2r[] =
+{
+ 249, 249, 252, 252, 249, 249, 249, 248, 247, 246,
+ 245, 244, 243, 242, 241, 240, 239, 238, 238, 238,
+ 251, 251, 238, 238
+};
+
+extern int table_explo1[] =
+{
+ 0, 0, 1, 1, 2, 2, 3, 3, 4, 3,
+ 4, 4, 3, 4, 3, 3, 4, 4, 5, 5,
+ 4, 5, 6, 5, 6, 6, 5, 5, 6, 7,
+ 7, 8, 8, 9, 9, 10, 10, 11, 11
+};
+
+extern int table_explo2[] =
+{
+ 12, -1, 13, 14, -1, 15, 13, -1, 14, 15,
+ 12, -1, 13, 15, 14, 14, -1, 14, 15, 13
+};
+
+extern int table_explo3[] =
+{
+ 32, 32, 34, 34, 32, 32, 34, 34, 32, 32,
+ 34, 34, 32, 32, 35, 35, 32, 32, 35, 35
+};
+
+extern int table_explo4[] = { 12, 13, 14, 15, 7, 8, 9, 10, 11 };
+
+extern int table_explo5[] =
+{
+ 54, -1, 55, -1, 56, -1, 57, -1, 58, -1,
+ 59, -1
+};
+
+extern int table_explo6[] = { 54, 55, 56, 57, 58, 59 };
+
+extern int table_explo7[] =
+{
+ 60, 61, -1, 63, 64, 65, 62, 64, 62, 60,
+ 62, -1, 65, -1, 60, 65, 63, 61, 62, -1,
+ 64, 65, -1, 62, 64, 61, 62, 63, -1, 65,
+ 60, -1, 65, -1, 63, 65, -1, 61, 60, 65,
+ 62, 63, 64, -1, 62, 63, -1, 62, 62, 60,
+ 62, -1, 65, -1, 60, 65, 64, 61, 62, 63,
+ -1, 65, 60, -1, 63, 61, 62, -1, 64, 65,
+ -1, 62, 62, 60, 62, -1, 65, -1, 60, 65,
+ 60, 61, -1, 63, 64, 65, 62, 64, 63, 61,
+ 62, -1, 64, 65, -1, 62, 60, 61, -1, 63,
+ 64, 65, 62, 64, -1, 60, -1, -1, 65, -1,
+ 60, -1, 63, -1, 62, -1, -1, 65, -1, -1,
+ -1, 61, -1, -1, -1, 60, -1, -1
+};
+
+extern int table_explo8[] = { 7, 8, 9, 10, 11 };
+
+extern int table_sploutch1[] = { 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 };
+
+extern int table_sploutch2[] =
+{
+ -1, -1, -1, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99
+};
+
+extern int table_sploutch3[] =
+{
+ -1, -1, -1, -1, -1, -1, -1, -1, 90, 91,
+ 92, 93, 94, 95, 96, 97, 98, 99
+};
+
+extern int table_tentacule[] =
+{
+ 86, 85, 84, 83, 84, 85, 86, -1, 86, 85,
+ 84, 83, 82, 81, 80, 79, 78, 77, 76, 75,
+ 74, 73, 72, 71, 70, 70, 70, 70, 71, 72,
+ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
+ 83, 84, 85, 86, -1
+};
+
+extern int table_bridge[] =
+{
+ 365, 366, 365, 366, 365, 366, 365, 366, 365, 366,
+ 365, 366, 365, 366, 365, 366, 367, 367, 368, 368,
+ 369, 369, 370, 370, 371, 371, 372, 372, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 372, 372, 371, 371, 370, 370, 369, 369, 368, 368,
+ 367, 367, 366, 366, 365, 365, 364
+};
+
+extern int table_pollution[] = { 179, 180, 181, 182, 183, 184, 185, 186 };
+
+extern int table_invertstart[] = { 179, 180, 181, 182, 183, 184, 185, 186 };
+
+extern int table_invertstop[] = { 186, 185, 184, 183, 182, 181, 180, 179 };
+
+extern int table_invertpanel[] = { 187, 188, 189, 190, 191, 192, 193, 194 };
+
+extern int table_plouf[] = { 99, 100, 101, 102, 101, 100, 99 };
+
+extern int table_tiplouf[] = { 244, 99, 244 };
+
+extern int table_blup[] =
+{
+ 103, 104, 105, 106, 104, 103, 106, 105, 103, 104,
+ 103, 105, 106, 103, 105, 106, 103, 104, 106, 105
+};
+
+extern int table_follow1[] =
+{
+ 256, 256, 256, 257, 257, 258, 259, 260, 261, 262,
+ 263, 264, 264, 265, 265, 265, 264, 264, 263, 262,
+ 261, 260, 259, 258, 257, 257
+};
+
+extern int table_follow2[] = { 256, 258, 260, 262, 264 };
+
+extern int table_cle[] =
+{
+ 122, 123, 124, 125, 126, 127, 128, 127, 126, 125,
+ 124, 123
+};
+
+extern int table_cle1[] =
+{
+ 209, 210, 211, 212, 213, 214, 215, 214, 213, 212, 211, 210
+};
+
+extern int table_cle2[] =
+{
+ 220, 221, 222, 221, 220, 219, 218, 217, 216, 217, 218, 219
+};
+
+extern int table_cle3[] =
+{
+ 229, 228, 227, 226, 225, 224, 223, 224, 225, 226, 227, 228
+};
+
+extern int table_decor_action[] =
+{
+ 1,32,
+ -4,4, 4,-3, -4,2, 4,5, -4,-1, 4,2, -4,-4, 4,-3, -3,2, 3,2,
+ -3,-5, 3,4, -3,5, 3,-2, -3,5, 3,4, -2,-2, 2,4, -2,-2, 2,-2,
+ -2,-4, 2,2, -2,-2, 2,-3, -1,-3, 1,-2, -1,-1, 1,2, -1,-2, 1,-1,
+ -1,1, 1,2,
+ 2,32,
+ -4,0, 4,0, -4,0, 4,0, -4,0, 4,0, -4,0, 4,0, -3,0, 3,0,
+ -3,0, 3,0, -3,0, 3,0, -3,0, 3,0, -2,0, 2,0, -2,0, 2,0,
+ -2,0, 2,0, -2,0, 2,0, -1,0, 1,0, -1,0, 1,0, -1,0, 1,0,
+ -1,0, 1,0,
+ 5,192,
+ 0,-32, 0,32, 0,-16, 0,6, 0,-8, 0,8, 0,-4, 0,4, 0,-2, 0,2,
+ -7,0, -6,0, -5,0, -4,0, -2,0, 0,0, 2,0, 4,0, 5,0, 6,0,
+ 7,0, 7,0, 6,0, 5,0, 4,0, 2,0, 0,0, -2,0, -4,0, -5,0,
+ -6,0, -7,0, -7,0, -6,0, -5,0, -4,0, -2,0, 0,0, 2,0, 4,0,
+ 5,0, 6,0, 7,0, 7,0, 6,0, 5,0, 4,0, 2,0, 0,0, -2,0, -4,0,
+ -5,0, -6,0, -7,0, -7,0, -6,0, -5,0, -4,0, -2,0, 0,0, 2,0,
+ 4,0, 5,0, 6,0, 7,0, 7,0, 6,0, 5,0, 4,0, 2,0, 0,0,
+ -2,0, -4,0, -5,0, -6,0, -7,0, -7,0, -6,0, -5,0, -4,0, -2,0,
+ 0,0, 2,0, 4,0, 5,0, 6,0, 7,0, 7,0, 6,0, 5,0, 4,0,
+ 2,0, 0,0, -2,0, -4,0, -5,0, -6,0, -7,0, -7,0, -6,0, -5,0,
+ -4,0, -2,0, 0,0, 2,0, 4,0, 5,0, 6,0, 7,0, 7,0, 6,0,
+ 5,0, 4,0, 2,0, 0,0, -2,0, -4,0, -5,0, -6,0, -7,0, -7,0,
+ -6,0, -5,0, -4,0, -2,0, 0,0, 2,0, 4,0, 5,0, 6,0, 7,0,
+ 7,0, 6,0, 5,0, 4,0, 2,0, 0,0, -2,0, -4,0, -5,0, -6,0,
+ -7,0, -7,0, -6,0, -5,0, -4,0, -2,0, 0,0, 2,0, 4,0, 5,0,
+ 6,0, 7,0, 7,0, 6,0, 5,0, 4,0, 2,0, 0,0, -2,0, -4,0,
+ -5,0, -6,0, -7,0, -7,0, -6,0, -5,0, -4,0, -2,0, 0,0, 2,0,
+ 4,0, 5,0, 6,0, 7,0, 7,0, 6,0, 5,0, 4,0, 2,0, 0,0,
+ -2,0, -4,0, -5,0, -6,0, -7,0, -7,0, -6,0, -5,0, -4,0, -2,0,
+ -1,0,
+ 0
+};
+
+extern int table_dynamitef[] =
+{
+ 253, 252, 254, 252, 252, 255, 252, 254, 253, 252,
+ 253, 254, 255, 252, 255, 253, 252, 254, 252, 255,
+ 253, 254, 252, 253, 255, 254, 255, 252, 253, 254,
+ 255, 252, 253, 254, 255, 254, 254, 253, 254, 255,
+ 253, 252, 255, 254, 255, 253, 252, 254, 253, 255,
+ 253, 254, 252, 253, 255, 254, 252, 255, 253, 254,
+ 255, 253, 252, 254, 255, 254, 252, 253, 254, 255,
+ 253, 254, 255, 254, 255, 253, 252, 254, 253, 255,
+ 253, 254, 255, 253, 255, 254, 255, 252, 253, 254,
+ 255, 253, 253, 254, 255, 254, 252, 253, 254, 255
+};
+
+extern int table_skate[] =
+{
+ 129, 129, 129, 129, 130, 130, 130, 131, 131, 132,
+ 132, 133, 133, 134, 134, 134, 135, 135, 135, 135,
+ 134, 134, 134, 133, 133, 132, 132, 131, 131, 131,
+ 130, 130, 130, 130
+};
+
+extern int table_glu[] =
+{
+ 168, 168, 169, 169, 170, 170, 171, 171, 170, 170,
+ 169, 169, 168, 168, 169, 169, 169, 168, 168, 169,
+ 169, 170, 170, 169, 168
+};
+
+extern int table_clear[] =
+{
+ 40, 40, 40, 40, 41, 41, 41, 41, 40, 40,
+ 40, 40, 40, 40, 40, 41, 41, 41, 40, 40,
+ 40, 40, 40, 40, 40, 41, 41, 41, 40, 40,
+ 42, 42, 42, 43, 43, 43, 44, 44, 44, 45,
+ 45, 45, 46, 46, 47, 47, 46, 46, 47, 47,
+ 46, 46, 47, 47, 46, 46, 47, 47, 46, 46,
+ 47, 47, 46, 46, 47, 47, 46, 46, 47, 47
+};
+
+extern int table_electro[] =
+{
+ 266, 267, 266, 267, 266, 267, 266, 267, 266, 267,
+ 266, 267, 266, 267, 266, 267, 266, 267, 266, 267,
+ 266, 267, 266, 267, 266, 267, 266, 267, 266, 267,
+ 40, 40, 40, 40, 41, 41, 41, 41, 40, 40,
+ 40, 40, 40, 40, 40, 41, 41, 41, 40, 40,
+ 40, 40, 40, 40, 40, 41, 41, 41, 40, 40,
+ 42, 42, 42, 43, 43, 43, 44, 44, 44, 45,
+ 45, 45, 46, 46, 47, 47, 46, 46, 47, 47,
+ 46, 46, 47, 47, 46, 46, 47, 47, 46, 46
+};
+
+extern int table_chenille[] = { 311, 312, 313, 314, 315, 316 };
+
+extern int table_chenillei[] = { 316, 315, 314, 313, 312, 311 };
+
+extern int table_adapt_decor[] =
+{
+ 153, 147, 148, 146, 40, 151, 150, 144, 39, 152,
+ 149, 145, 38, 36, 37, 35, 153, 147, 148, 146,
+ 40, 151, 150, 144, 39, 152, 149, 145, 38, 36,
+ 37, 156, 75, 75, 155, 155, 75, 75, 155, 155,
+ 74, 74, 154, 154, 75, 75, 155, 155, 157, 157,
+ 157, 157, 109, 109, 109, 109, 108, 108, 108, 108,
+ 107, 107, 107, 107, 202, 202, 138, 138, 202, 202,
+ 138, 138, 202, 202, 138, 138, 202, 202, 138, 138,
+ 283, 283, 283, 283, 262, 262, 262, 262, 263, 263,
+ 263, 263, 261, 261, 261, 261, 361, 359, 360, 352,
+ 357, 353, 355, 349, 358, 354, 356, 350, 351, 347,
+ 348, 341, 387, 387, 386, 386, 394, 394, 392, 392,
+ 395, 395, 393, 393, 397, 397, 396, 396, 251, 254,
+ 254, 254, 251, 258, 260, 258, 251, 257, 259, 257,
+ 251, 250, 256, 250
+};
+
+extern int table_adapt_fromage[] =
+{
+ -1, 265, 264, 268, 267, 273, 271, 275, 266, 272,
+ 270, 274, 269, 277, 276, 278, -1, 286, 285, 289,
+ 288, 294, 292, 296, 287, 293, 291, 295, 290, 298,
+ 297, 299
+};
+
+extern int table_shield[] =
+{
+ 144, 145, 146, 147, 148, 149, 150, 151, 266, 267,
+ 268, 269, 270, 271, 272, 273
+};
+
+extern int table_shield_blupi[] =
+{
+ 144, 145, 146, 147, 148, 149, 150, 151, 266, 267,
+ 268, 269, 270, 271, 272, 273
+};
+
+extern int table_power[] = { 8, 136, 137, 138, 139, 140, 141, 142, 143 };
+
+extern int table_invert[] =
+{
+ 187, 187, 187, 188, 189, 190, 191, 192, 193, 194,
+ 187, 187, 187, 194, 193, 192, 191, 190, 189, 188
+};
+
+extern int table_charge[] = { 238, 239, 240, 241, 242, 243 };
+
+extern int table_magicloop[] = { 152, 153, 154, 155, 156 };
+
+extern int table_magictrack[] =
+{
+ 152, 153, 154, 155, 156, 152, 153, 154, 155, 156,
+ 157, 158, 159, 160, 157, 158, 159, 160, 161, 162,
+ 163, 164, 165, 166
+};
+
+extern int table_shieldloop[] = { 274, 275, 276, 277, 278 };
+
+extern int table_shieldtrack[] =
+{
+ 274, 275, 276, 277, 278, 274, 275, 276, 277, 278,
+ 279, 280, 281, 282, 283, 284, 285, 286, 287, 288
+};
+
+extern int table_drinkeffect[] = { 274, 275, 276, 277, 278 };
+
+extern int table_drinkoffset[] = { 0, 7, 22 };
+
+extern int table_tresortrack[] =
+{
+ 166, 165, 164, 163, 162, 161, 162, 163, 164, 165,
+ 166
+};
+
+extern int table_decor_piege1[] =
+{
+ 374, 374, 373, 347, 373, 374, 374, 374, 373, 347,
+ 347, 373, 374, 374, 374, 374
+};
+
+extern int table_decor_piege2[] = { 374, 373, 347, 373 };
+
+extern int table_decor_goutte[] =
+{
+ 410, 409, 410, -1, -1, -1, -1, -1, -1, 410,
+ 409, 408, 409, 410, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 410, 409, 408, 407, 406, 405,
+ 404, 405, 406, 407, 408, 409, 410, -1, -1, -1,
+ -1, 410, 409, 410, -1, -1, -1, -1
+};
+
+extern int table_decor_ecraseur[] = { 317, 317, 318, 319, 320, 321, 322, 323, 323, 323 };
+
+extern int table_decor_scie[] = { 378, 379, 380, 381, 382, 383 };
+
+extern int table_decor_temp[] =
+{
+ 328, 328, 327, 327, 326, 326, 325, 325, 324, 324,
+ 325, 325, 326, 326, 327, 329, 328, 328, -1, -1
+};
+
+extern int table_decor_eau1[] = { 92, 93, 94, 95, 94, 93 };
+
+extern int table_decor_eau2[] = { 91, 96, 97, 98, 97, 96 };
+
+
+
+extern int table_decor_ventillod[] = { 129, 130, 131 };
+
+extern int table_decor_ventilloh[] = { 132, 133, 134 };
+
+extern int table_decor_ventillob[] = { 135, 136, 137 };
+
+
+
+extern int table_decor_ventd[] = { 114, 115, 116, 117 };
+
+extern int table_decor_venth[] = { 118, 119, 120, 121 };
+
+extern int table_decor_ventb[] = { 122, 123, 124, 125 };
+
+extern int table_marine[] =
+{
+ 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xcf, 0xce, 0xcd, 0xcc, 0xcb
+};
+
+extern int table_36418[] = { 10, 2, 3, 4, 5, 6, 7, 8, 9, 1, 11, 12, 13, 14 };
+extern int table_36458[] = { 19, 20, 21, 23, 24, 25, 26, 27, 28, 29 };
+extern int table_36488[] = { 15, 16, 17, 18 };
+extern int table_364a0[] = { 73, 22 };
+extern int table_364b0[] = { 78, 79, 80, 81, 82, 83, 84 };
+extern int table_364d0[] = { 87, 88, 89, 90 };
+extern int table_364e8[] = { 85, 86 };
+extern int table_364f8[] = { 396, 388, 389, 390, 391 };
+extern int table_36510[] = { 398, 399, 400 };
+extern int table_36520[] = { 87, 88, 89 };
+extern int table_36530[] = { 0x99 };
+extern int table_36538[] = { 0x9a, 0x9b };
+extern int table_36548[] = { 0xb9 };
+extern int table_36550[] = { 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f };
+extern int table_36570[] = { 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xe6, 0xe7, 0xe9, 0xea };
+extern int table_365a8[] = { 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe8 };
+extern int table_365d0[] = { 0x9d };
+extern int table_365d8[] = { 0x8b, 0x8c, 0x8d, 0x8e, 0x8f };
+extern int table_365f0[] = { 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0 };
+extern int table_36610[] = { 0xc1, 0xc2, 0xc3, 0xc4, 0xc5 };
+extern int table_decor_lave[] = { 68, 69, 70, 71, 72, 71, 70, 69 };
+extern int table_36630[] = { 0x5b, 0x5c };
+extern int table_decor_ventillog[] = { 126, 127, 128 };
+extern int table_decor_ventg[] = { 110, 111, 112, 113 };
+extern int table_36670[] = { 0x4c, 0x4d, 0xc7, 0xc6, 0xc8, 0xc9, 0xeb, 0xec, 0x177, 0x178, 0x179 };
+extern int table_366a0[] = { 0x193, 0x191, 0x192 };
+extern int table_366b0[] = { 20, 21, 22 };
+extern int table_366c0[] = { 16, 17, 18, 19 };
+extern int table_366d8[] = { 23, 24, 25 };
+extern int table_366e8[] = { 0x1a, 0x1b };
+extern int table_366f8[] = { 0x1c, 0x1d, 0x1e, 0x1f };
+extern int table_36710[] = { 0x2d, 0x2e, 0x2f, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c};
+extern int table_36748[] = { 0x42, 0x43, 0x44, 0x45 };
+
+extern int table_mirror[] = {
+ 4, 3, 2, 1, 0, 11, 12, 13, 14, 15, 16, 5, 6, 7, 8, 9, 10, 20, 21, 22, 17, 18, 19, 24, 23, 25, 30, 31, 32, 29, 26, 27, 28, 36, 37, 38, 33, 34, 35, 40, 39, 41, 42, 43, 45, 44, 46, 47, 48, 55, 56, 57, 58, 59, 60, 49, 50, 51, 52, 53, 54, 66, 67, 68, 69, 70, 61, 62, 63, 64, 65, 75, 74, 73, 72, 71, 82, 83, 84, 85, 86, 87, 76, 77, 78, 79, 80, 81, 92, 91, 90, 89, 88, 99, 100, 101, 102, 103, 104, 93, 94, 95, 96, 97, 98, 109, 108, 107, 106, 105, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 127, 128, 129, 130, 131, 132, 121, 122, 123, 124, 125, 126, 134, 133, 139, 140, 141, 142, 135, 136, 137, 138, 147, 148, 149, 150, 143, 144, 145, 146, 155, 154, 153, 152, 151, 159, 160, 161, 156, 157, 158, 162, 163, 164, 167, 168, 165, 166, 173, 174, 175, 176, 169, 170, 171, 172, 181, 180, 179, 178, 177, 188, 189, 190, 191, 192, 193, 182, 183, 184, 185, 186, 187, 201, 202, 203, 204, 205, 206, 207, 194, 195, 196, 197, 198, 199, 200, 209, 208, 216, 217, 218, 219, 220, 221, 210, 211, 212, 213, 214, 215, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 252, 251, 255, 256, 253, 254, 257, 258, 259, 260, 261, 262, 285, 286, 287, 266, 267, 270, 269, 268, 271, 272, 273, 275, 274, 276, 277, 278, 279, 280, 281, 282, 283, 284, 263, 264, 265, 288, 289, 290, 291, 292, 293, 294, 295, 303, 304, 305, 306, 307, 308, 309, 296, 297, 298, 299, 300, 301, 302, 314, 313, 312, 311, 310, 316, 315, 323, 322, 321, 320, 319, 318, 317, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334
+};
+
+extern int table_ressort[] =
+{
+ 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd4, 0xd3, 0xd2
+};
+
+extern int table_blupi[] = {
+ 35, 18, 0, 276, 276, 277, 277, 278, 278, 279, 279, 280, 280, 281, 281, 282, 282, 283, 283, 284, 284, 1, 330, 0, 0, 0, 0, 0, 0, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 23, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 23, 23, 23, 0, 0, 0, 0, 0, 0, 133, 133, 0, 0
+ , 0, 133, 133, 0, 0, 0, 0, 0, 0, 0, 133, 133, 0, 0, 0, 0, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 0, 0, 0, 135, 135, 136,
+ 136, 137, 137, 137, 137, 137, 137, 137, 137, 138, 138, 137, 137, 137, 138, 138, 137, 137, 137, 138, 138, 137, 137, 137, 138, 138, 137, 137, 137, 137, 137, 137, 136,
+ 136, 135, 135, 135, 0, 0, 0, 0, 0, 23, 23, 23, 0, 0, 133, 133, 0, 0, 0, 23, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 133, 133, 0, 0, 0, 0, 0,
+ 23, 23, 23, 23, 0, 0, 0, 135, 135, 136, 136, 137, 137, 137, 137, 137, 137, 137, 137, 138, 138, 137, 137, 137, 138, 138, 137, 137, 137, 138, 138, 137, 137, 137, 138,
+ 138, 137, 137, 137, 138, 138, 137, 137, 137, 138, 138, 137, 137, 137, 138, 138, 137, 137, 137, 138, 138, 137, 137, 137, 138, 138, 137, 137, 137, 138, 138, 137, 137,
+ 137, 138, 138, 137, 137, 137, 138, 138, 137, 137, 137, 137, 137, 137, 136, 136, 135, 135, 135, 0, 0, 0, 0, 0, 23, 23, 23, 0, 0, 133, 133, 0, 0, 0, 23, 23, 23, 23, 0, 0
+ , 0, 0, 0, 0, 0, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 133, 133, 0, 0, 0, 0, 0, 23, 23, 23, 23, 0, 0, 0, 2, 6, 0, 5, 6, 7, 8, 9, 10, 60, 3, 0, 19, 18, 19, 3, 6, 0, 1, 1, 2,
+ 2, 3, 3, 4, 3, 0, 17, 18, 19, 5, 5, 4, 169, 26, 170, 170, 27, 59, 6, 0, 3, 3, 2, 2, 1, 1, 61, 5, 0, 34, 35, 34, 34, 33, 62, 2, 0, 35, 34, 6, 3, 2, 33, 34, 35, 7, 1, 0,
+ 44, 8, 8, 0, 0, 169, 26, 170, 27, 171, 28, 172, 9, 6, 0, 5, 6, 7, 8, 9, 10, 10, 6, 0, 5, 6, 7, 8, 9, 10, 13, 6, 0, 41, 41, 42, 42, 43, 43, 11, 70, 0, 40, 40, 40, 40,
+ 41, 41, 41, 41, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 40, 40, 42, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 45, 46, 46, 47, 47,
+ 46, 46, 47, 47, 46, 46, 47, 47, 46, 46, 47, 47, 46, 46, 47, 47, 46, 46, 47, 47, 46, 46, 47, 47, 75, 1, 0, -1, 76, 70, 0, 40, 40, 40, 40, 41, 41, 41, 41, 40, 40, 40,
+ 40, 40, 40, 40, 41, 41, 41, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 40, 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ , -1, -1, -1, -1, -1, 77, 110, 0, 324, 325, 324, 325, 324, 325, 324, 325, 324, 325, 324, 325, 324, 325, 324, 325, 324, 325, 324, 325, 324, 324, 325, 325, 326, 326, 327
+ , 327, 328, 328, 329, 329, 330, 330, 331, 331, 332, 332, 333, 333, 334, 334, 333, 333, 332, 332, 331, 331, 330, 330, 329, 329, 329, 330, 330, 330, 331, 331, 331, 332,
+ 332, 332, 333, 333, 333, 334, 334, 334, 333, 333, 333, 332, 332, 332, 331, 331, 331, 330, 330, 330, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329,
+ 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 329, 78, 1, 0, -1, 79, 1, 0, -1, 80, 1, 0, -1, 81, 1, 0, -1, 14, 6, 0, 49, 50, 51, 52,
+ 53, 54, 29, 6, 0, 126, 125, 124, 123, 122, 121, 28, 6, 0, 122, 122, 122, 125, 125, 125, 15, 1, 0, 61, 16, 8, 0, 61, 62, 63, 62, 61, 64, 65, 64, 17, 10, 0, 71, 71, 72,
+ 72, 73, 73, 74, 74, 75, 75, 67, 1, 0, 315, 68, 12, 0, 296, 297, 298, 299, 300, 301, 302, 301, 300, 299, 298, 297, 69, 7, 0, 296, 310, 311, 312, 313, 314, 303, 18, 10,
+ 0, 76, 76, 76, 76, 76, 76, 77, 77, 77, 77, 19, 14, 0, 76, 76, 77, 77, 78, 78, 79, 79, 80, 80, 81, 81, 39, 39, 20, 10, 0, 88, 88, 89, 89, 90, 90, 91, 91, 92, 92, 21, 12
+ , 0, 93, 93, 94, 94, 95, 95, 96, 96, 97, 97, 98, 98, 22, 12, 0, 93, 93, 94, 94, 95, 95, 96, 96, 97, 97, 98, 98, 23, 10, 0, 105, 105, 106, 106, 107, 107, 108, 108, 109,
+ 109, 24, 90, 0, 93, 96, 98, 94, 95, 93, 95, 98, 93, 94, 96, 96, 94, 94, 98, 98, 93, 93, 97, 97, 94, 94, 94, 96, 96, 96, 93, 93, 93, 93, 94, 94, 94, 94, 94, 97, 97, 97
+ , 97, 97, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 79, 79, 76, 76, 76, 76, 79, 79, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,
+ 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 25, 8, 0, 111, 111, 110, 110, 111, 111, 112, 112, 26, 8, 0, 111, 111, 110, 110, 111, 111, 112, 112, 27, 7, 0, 112, 113, 114
+ , 115, 116, 117, 118, 30, 12, 0, 25, 25, 29, 29, 46, 46, 47, 47, 46, 46, 29, 29, 31, 328, 0, 156, 156, 156, 156, 157, 157, 157, 157, 158, 158, 158, 158, 157, 157, 157,
+ 157, 156, 156, 156, 156, 157, 157, 157, 157, 158, 158, 158, 158, 157, 157, 157, 157, 156, 156, 156, 156, 157, 157, 157, 157, 158, 158, 158, 158, 157, 157, 157, 157,
+ 156, 156, 156, 156, 157, 157, 157, 157, 158, 158, 158, 158, 157, 157, 157, 157, 156, 156, 156, 156, 157, 157, 157, 157, 158, 158, 158, 158, 157, 157, 157, 157, 156,
+ 156, 156, 156, 157, 157, 157, 157, 158, 158, 158, 158, 157, 157, 157, 157, 156, 156, 156, 156, 157, 157, 157, 157, 158, 158, 158, 158, 157, 157, 157, 157, 144, 144,
+ 143, 143, 151, 151, 162, 162, 163, 163, 164, 164, 163, 163, 162, 162, 163, 163, 164, 164, 163, 163, 162, 162, 163, 163, 164, 164, 163, 163, 162, 162, 163, 163, 164,
+ 164, 163, 163, 162, 162, 151, 151, 143, 143, 144, 144, 157, 157, 156, 156, 156, 156, 157, 157, 157, 157, 158, 158, 158, 158, 157, 157, 157, 157, 156, 156, 156, 156,
+ 157, 157, 157, 157, 158, 158, 158, 158, 157, 157, 157, 157, 156, 156, 156, 156, 157, 157, 157, 157, 158, 158, 158, 158, 157, 157, 157, 157, 156, 156, 156, 156, 157,
+ 157, 157, 157, 158, 158, 158, 158, 157, 157, 157, 157, 144, 144, 143, 143, 151, 151, 162, 162, 163, 163, 164, 164, 163, 163, 162, 162, 163, 163, 164, 164, 163, 163,
+ 162, 162, 163, 163, 164, 164, 163, 163, 162, 162, 163, 163, 164, 164, 163, 163, 162, 162, 151, 151, 143, 143, 151, 151, 162, 162, 163, 163, 164, 164, 163, 163, 162,
+ 162, 163, 163, 164, 164, 163, 163, 162, 162, 163, 163, 164, 164, 163, 163, 162, 162, 163, 163, 164, 164, 163, 163, 162, 162, 163, 163, 164, 164, 163, 163, 162, 162,
+ 163, 163, 164, 164, 163, 163, 162, 162, 151, 151, 143, 143, 144, 144, 157, 157, 32, 12, 0, 144, 144, 145, 145, 146, 146, 145, 145, 144, 144, 143, 143, 33, 10, 0, 151,
+ 151, 152, 152, 153, 153, 154, 154, 155, 155, 34, 10, 0, 157, 157, 165, 165, 165, 165, 166, 166, 166, 166, 36, 32, 0, 135, 177, 177, 178, 178, 179, 179, 180, 180, 179,
+ 179, 178, 178, 179, 179, 180, 180, 179, 179, 178, 178, 179, 179, 180, 180, 179, 179, 178, 178, 177, 177, 135, 37, 140, 0, 182, 182, 182, 182, 208, 208, 208, 208, 208,
+ 182, 182, 182, 182, 182, 182, 208, 208, 208, 208, 208, 194, 194, 194, 182, 182, 182, 182, 208, 208, 208, 208, 208, 182, 182, 182, 182, 182, 182, 208, 208, 208, 208,
+ 182, 182, 182, 182, 182, 182, 182, 182, 194, 195, 196, 197, 198, 198, 197, 197, 196, 196, 197, 197, 198, 198, 197, 197, 196, 195, 194, 182, 182, 182, 208, 208, 208,
+ 208, 208, 208, 182, 182, 182, 182, 182, 208, 208, 208, 208, 208, 182, 182, 194, 195, 196, 197, 198, 198, 197, 197, 196, 196, 197, 197, 198, 198, 197, 197, 196, 196,
+ 197, 197, 198, 198, 197, 197, 196, 195, 194, 182, 182, 182, 182, 182, 182, 182, 208, 208, 208, 208, 208, 208, 210, 210, 211, 211, 211, 211, 211, 211, 210, 210, 38, 96,
+ 0, 182, 183, 184, 185, 186, 187, 182, 183, 184, 185, 186, 187, 182, 183, 184, 185, 186, 187, 182, 182, 182, 182, 182, 182, 182, 183, 184, 185, 186, 187, 182, 182, 182
+ , 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 183, 184, 185, 186, 187, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182,
+ 182, 183, 184, 185, 186, 187, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 39, 7, 0, 194,
+ 195, 196, 197, 198, 199, 200, 40, 3, 0, 210, 211, 212, 41, 8, 0, 213, 213, 214, 214, 215, 215, 214, 214, 42, 20, 0, 17, 17, 18, 18, 19, 19, 1, 1, 215, 215, 214, 214,
+ 213, 213, 212, 212, 211, 211, 210, 210, 43, 20, 0, 210, 210, 211, 211, 212, 212, 213, 213, 214, 214, 215, 215, 1, 1, 19, 19, 18, 18, 17, 17, 44, 29, 0, 1, 1, 222, 222,
+ 222, 222, 223, 223, 224, 224, 225, 225, 225, 225, 225, 224, 223, 222, 222, 222, 223, 223, 224, 224, 225, 225, 225, 1, 1, 45, 29, 0, 1, 1, 222, 222, 222, 222, 223, 223
+ , 224, 224, 225, 225, 225, 225, 225, 224, 223, 222, 222, 222, 223, 223, 224, 224, 225, 225, 225, 1, 1, 46, 32, 0, 1, 1, 227, 227, 228, 228, 229, 229, 228, 228, 227,
+ 227, 226, 226, 227, 227, 228, 228, 229, 229, 228, 228, 227, 227, 226, 226, 227, 227, 228, 228, 1, 1, 47, 34, 0, 135, 135, 136, 136, 137, 137, 231, 231, 231, 231, 230,
+ 230, 231, 231, 231, 231, 230, 230, 231, 231, 231, 231, 230, 230, 231, 231, 231, 231, 137, 137, 136, 136, 135, 135, 48, 40, 0, 0, 0, 135, 135, 136, 136, 137, 137, 232,
+ 233, 232, 233, 232, 233, 232, 233, 232, 233, 232, 233, 232, 233, 232, 233, 232, 233, 232, 233, 232, 233, 232, 233, 137, 137, 136, 136, 135, 135, 0, 0, 65, 44, 0, 1, 1,
+ 288, 288, 289, 289, 290, 290, 290, 289, 288, 288, 289, 289, 290, 290, 290, 289, 288, 288, 289, 289, 290, 290, 290, 289, 288, 288, 289, 289, 290, 290, 290, 289, 288,
+ 288, 289, 289, 290, 290, 290, 289, 1, 1, 49, 36, 0, 1, 1, 234, 234, 235, 235, 236, 236, 235, 235, 234, 234, 235, 235, 236, 236, 235, 235, 234, 234, 235, 235, 236, 236,
+ 235, 235, 234, 234, 235, 235, 236, 236, 235, 235, 1, 1, 50, 64, 0, 238, 238, 239, 239, 240, 240, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 240, 240, 241, 241,
+ 240, 240, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 241, 240, 240, 241, 241, 240, 240, 241, 241, 241, 241, 241, 241, 241, 241, 240, 240, 239, 239, 238,
+ 238, 238, 238, 238, 238, 237, 237, 238, 238, 237, 237, 51, 8, 0, 238, 238, 237, 237, 238, 238, 239, 239, 52, 12, 0, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247,
+ 248, 249, 53, 6, 0, 251, 251, 238, 238, 238, 238, 54, 25, 0, 168, 168, 169, 169, 170, 170, 171, 171, 170, 170, 169, 169, 168, 168, 169, 169, 169, 168, 168, 169, 169,
+ 170, 170, 169, 168, 55, 4, 0, 253, 253, 254, 254, 56, 64, 0, 1, 3, 270, 268, 1, 3, 270, 268, 1, 3, 270, 268, 1, 3, 270, 268, 1, 3, 270, 268, 1, 3, 270, 268, 1, 3, 270,
+ 268, 1, 3, 270, 268, 1, 2, 3, 4, 270, 269, 268, 0, 1, 2, 3, 4, 270, 269, 268, 0, 1, 1, 2, 2, 3, 3, 4, 4, 270, 270, 269, 269, 268, 268, 0, 0, 57, 90, 0, 266, 267, 266,
+ 267, 266, 267, 266, 267, 266, 267, 266, 267, 266, 267, 266, 267, 266, 267, 266, 267, 266, 267, 266, 267, 266, 267, 266, 267, 266, 267, 40, 40, 40, 40, 41, 41, 41, 41,
+ 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 40, 40, 42, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 45, 46, 46, 47, 47, 46, 46, 47, 47
+ , 46, 46, 47, 47, 46, 46, 47, 47, 46, 46, 82, 10, 0, 0, 268, 268, 269, 269, 269, 269, 268, 268, 0, 58, 14, 0, 274, 274, 271, 271, 271, 271, 272, 272, 273, 273, 273,
+ 273, 274, 274, 66, 16, 0, 291, 291, 292, 292, 293, 293, 294, 294, 295, 295, 294, 294, 293, 293, 292, 292, 72, 1, 0, 320, 73, 24, 0, 319, 319, 318, 318, 317, 317, 318,
+ 318, 319, 319, 320, 320, 321, 321, 322, 322, 323, 323, 322, 322, 321, 321, 320, 320, 74, 128, 0, 1, 1, 2, 2, 3, 3, 4, 4, 270, 270, 269, 269, 268, 268, 0, 0, 1, 2, 3, 4
+ , 270, 269, 268, 0, 1, 2, 3, 4, 270, 269, 268, 0, 1, 3, 270, 268, 2, 4, 269, 0, 1, 3, 270, 268, 2, 4, 269, 0, -1, 3, 270, -1, 2, -1, 269, 0, 1, -1, -1, 268, -1, -1,
+ 269, -1, -1, -1, -1, 270, -1, -1, 2, -1, -1, -1, -1, -1, -1, 29, 46, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 63, 92, 0, 263, 264, 265, 264, 263, 264, 265, 264, 263, 264, 265, 264
+ , 263, 264, 265, 264, 263, 264, 265, 264, 263, 264, 265, 264, 263, 264, 265, 264, 263, 264, 265, 264, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 23, 23, 0, 0, 0, 0, 0, 0, 0, 133, 133, 0, 0, 0, 133, 133, 0, 0, 0, 0, 0, 0, 0, 133, 133, 0, 0, 0, 0, 23, 23, 23, 23, 0, 0, 0, 0, 64, 104, 0, 1, 1, 2, 2, 3, 3,
+ 285, 286, 287, 286, 285, 286, 287, 286, 285, 286, 287, 286, 285, 286, 287, 286, 285, 286, 287, 286, 285, 286, 287, 286, 285, 286, 287, 286, 285, 286, 287, 286, 3, 3, 2
+ , 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 0, 0, 0, 0, 0, 0, 0, 133, 133, 0, 0, 0, 133, 133, 0, 0, 0, 0, 0, 0, 0, 133,
+ 133, 0, 0, 0, 0, 23, 23, 23, 23, 0, 0, 0, 0, 83, 60, 0, 1, 1, 288, 288, 289, 289, 290, 290, 290, 289, 288, 288, 289, 289, 290, 290, 290, 289, 288, 288, 289, 289, 290,
+ 290, 290, 289, 288, 288, 289, 289, 290, 290, 290, 289, 288, 288, 289, 289, 290, 290, 290, 289, 288, 288, 289, 289, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290,
+ 290, 290, 1, 1, 0
+};
+
+extern int table_tutorial[] = {
+ 0, 2, 0, 7, -1, 0x190,
+ 3, 3, 0, 7, 0, 0x191,
+ 3, 4, 0, 7, -1, 0x192,
+ 6, 8, 0, 7, -1, 0x193,
+ 12, 12, 0, 7, 1, 0x194,
+ 12, 13, 0, 7, -1, 0x195,
+ 14, 15, 0, 7, -1, 0x196,
+ 16, 17, 0, 1, -1, 0x197,
+ 22, 23, 0, 7, -1, 0x198,
+ 29, 30, 0, 7, -1, 0x199,
+ 41, 44, 0, 7, -1, 0x19a,
+ 54, 63, 0, 7, -1, 0x19b,
+ 69, 70, 0, 7, -1, 0x19c,
+ -1
+};
+
+#endif
\ No newline at end of file
diff --git a/src/def.h b/src/def.h
new file mode 100644
index 0000000..1436084
--- /dev/null
+++ b/src/def.h
@@ -0,0 +1,1404 @@
+// Def.h
+//
+
+#ifndef DEF_H
+#define DEF_H
+
+#include
+#include // ceil
+
+// prevent WinAPI from overriding our functions
+#undef PlaySound
+#undef DrawText
+#undef GetCharWidth
+
+#define _DEMO FALSE // TRUE=demo, FALSE=complet
+#define _EGAMES FALSE // TRUE version pour eGames
+#define _SE FALSE // TRUE eGames Special Edition
+#define _INTRO FALSE // TRUE si images d'introduction
+
+// additional flags
+#define _CD FALSE // if TRUE, require the game CD
+#define _BYE !_EGAMES // if TRUE, show exit image (like _INTRO)
+#define _LEGACY FALSE // if TRUE, keep broken/quirky legacy code
+#define _DREAM TRUE // if TRUE, allow Dream blocks when loading levels
+#define _BASS TRUE // if TRUE, use BASS audio library instead of DirectMusic (wip)
+
+#define MAXGAMER 8
+#define MAXNETPLAYER 4
+#define MAXTEAM 4
+#define MAXNETMESSAGE 20
+#define MAXSESSION 100
+#define MAXMOVEOBJECT 200
+#define MAXNOTIF 5
+#define MAXFIFOPOS 10
+#define MAXCHAT 6
+#define MAXSAVE 6
+#define MAXDEMO 9999
+#define MAXINDEX 20
+#define MAXMESSAGEPERPACKET 5
+
+#define LXIMAGE 640 // dimensions de la fenêtre de jeu
+#define LYIMAGE 480
+
+#define POSDRAWX 0
+#define POSDRAWY 0
+
+#define MAXCELX 100 // nb max de cellules d'un monde
+#define MAXCELY 100
+
+#define DIMOBJX 64 // dimensions d'un objet
+#define DIMOBJY 64
+
+#define DIMEXPLOX 128
+#define DIMEXPLOY 128
+
+#define DIMBLUPIX 60 // dimensions de blupi
+#define DIMBLUPIY 60
+
+#define DIMEXPLOX 128
+#define DIMEXPLOY 128
+
+#define DIMBUTTONX 40 // dimensions d'un button
+#define DIMBUTTONY 40
+
+#define DIMJAUGEX 124 // dimensions de la jauge
+#define DIMJAUGEY 22
+
+#define DIMTEXTX 16 // dimensions max d'un caractère
+#define DIMTEXTY 16
+
+#define DIMLITTLEX 16 // dimensions max d'un petit caractère
+#define DIMLITTLEY 12
+
+#define DIMDECORX 640
+#define DIMDECORY 480
+
+#define TRAJBYTEX ceil(MAXCELX / 8.0) // bytes to store one row of traj data
+
+enum {
+ CHBACK = 0,
+ CHOBJECT,
+ CHBLUPI,
+ CHDECOR,
+ CHBUTTON,
+ CHJAUGE,
+ CHTEXT,
+ CHLITTLE,
+ CHMAP,
+ CHEXPLO,
+ CHELEMENT,
+ CHBLUPI1,
+ CHBLUPI2,
+ CHBLUPI3,
+ CHTEMP,
+ CHMAX = CHTEMP
+};
+
+enum {
+ PK_LEAVE = 8,
+ PK_LOST,
+ PK_DIE,
+
+ PK_PAUSE = 12,
+};
+
+enum {
+ MESS_RESUME = 0,
+ MESS_PAUSE,
+ MESS_2,
+ MESS_3,
+ MESS_LOBBY,
+ MESS_5,
+ MESS_6,
+ MESS_7,
+ MESS_START = 10,
+ MESS_11,
+
+ MESS_OBJECTSTART = 20,
+ MESS_OBJECTDELETE,
+
+ MESS_MODIFDECOR = 30,
+
+ MESS_PLAYSOUND = 40,
+ MESS_STOPSOUND,
+
+ MESS_ASCENSEURSTART = 50,
+ MESS_ASCENSEUREND,
+
+ MESS_STOPCLOUD = 60
+};
+
+#define MAXNETMESSAGE 20
+
+// Directions :
+
+enum {
+ DIR_LEFT = 1,
+ DIR_RIGHT
+};
+
+// Actions :
+
+#define ACTION_STOP 1 // stand still
+#define ACTION_MARCH 2 // walk
+#define ACTION_TURN 3
+#define ACTION_JUMP 4 // beginning to jump
+#define ACTION_AIR 5
+#define ACTION_DOWN 6 // look down
+#define ACTION_UP 7 // look up
+#define ACTION_VERTIGO 8 // "whoops"
+#define ACTION_RECEDE 9 // back away from edge
+#define ACTION_ADVANCE 10 // walk forward away from edge
+#define ACTION_CLEAR1 11
+#define ACTION_SET 12
+#define ACTION_WIN 13
+#define ACTION_PUSH 14 // pushing a case
+#define ACTION_STOPHELICO 15
+#define ACTION_MARCHHELICO 16
+#define ACTION_TURNHELICO 17
+#define ACTION_STOPNAGE 18 // stopped in deep water
+#define ACTION_MARCHNAGE 19 // swimming in deep water
+#define ACTION_TURNNAGE 20 // turning in deep water
+#define ACTION_STOPSURF 21 // stopped on water surface
+#define ACTION_MARCHSURF 22 // swimming at water surface
+#define ACTION_TURNSURF 23 // turning at water surface
+#define ACTION_DROWN 24
+#define ACTION_STOPJEEP 25
+#define ACTION_MARCHJEEP 26
+#define ACTION_TURNJEEP 27
+#define ACTION_STOPPOP 28 // pulling a case, stopped
+#define ACTION_POP 29 // pulling a case
+#define ACTION_BYE 30 // "au au"
+#define ACTION_STOPSUSPEND 31 // stopped on bars
+#define ACTION_MARCHSUSPEND 32 // moving on bars
+#define ACTION_TURNSUSPEND 33 // turning on bars
+#define ACTION_JUMPSUSPEND 34 // pulling up from bars
+#define ACTION_HIDE 35 // invisible
+#define ACTION_JUMPAIE 36 // headache
+#define ACTION_STOPSKATE 37
+#define ACTION_MARCHSKATE 38
+#define ACTION_TURNSKATE 39
+#define ACTION_JUMPSKATE 40
+#define ACTION_AIRSKATE 41
+#define ACTION_TAKESKATE 42
+#define ACTION_DEPOSESKATE 43
+#define ACTION_OUF1a 44
+#define ACTION_OUF1b 45
+#define ACTION_OUF2 46
+#define ACTION_OUF3 47 // stop moving case "gahh...!"
+#define ACTION_OUF4 48
+#define ACTION_SUCETTE 49 // eating lollipop
+#define ACTION_STOPTANK 50
+#define ACTION_MARCHTANK 51
+#define ACTION_TURNTANK 52
+#define ACTION_FIRETANK 53
+#define ACTION_GLU 54 // glued
+#define ACTION_DRINK 55
+#define ACTION_CHARGE 56
+#define ACTION_ELECTRO 57
+#define ACTION_HELICOGLU 58
+#define ACTION_TURNAIR 59
+#define ACTION_STOPMARCH 60
+#define ACTION_STOPJUMP 61
+#define ACTION_STOPJUMPh 62
+#define ACTION_MOCKERY 63
+#define ACTION_MOCKERYi 64
+#define ACTION_OUF5 65
+#define ACTION_BALLOON 66 // stung by wasp
+#define ACTION_STOPOVER 67 // stopped in hovercraft
+#define ACTION_MARCHOVER 68 // moving in hovercraft
+#define ACTION_TURNOVER 69 // turning in hovercraft
+#define ACTION_RECEDEq 70
+#define ACTION_ADVANCEq 71
+#define ACTION_STOPECRASE 72
+#define ACTION_MARCHECRASE 73
+#define ACTION_TELEPORTE 74
+#define ACTION_CLEAR2 75
+#define ACTION_CLEAR3 76
+#define ACTION_CLEAR4 77
+#define ACTION_CLEAR5 78
+#define ACTION_CLEAR6 79
+#define ACTION_CLEAR7 80
+#define ACTION_CLEAR8 81
+#define ACTION_SWITCH 82
+#define ACTION_MOCKERYp 83
+#define ACTION_NON 84 // can't place personal bomb
+#define ACTION_SLOWDOWNSKATE 85
+#define ACTION_TAKEDYNAMITE 86
+#define ACTION_PUTDYNAMITE 87
+
+// Sécurités :
+
+enum {
+ SEC_SHIELD = 1,
+ SEC_POWER,
+ SEC_CLOUD,
+ SEC_HIDE
+};
+
+static char debugMobTypeNames[204][20] =
+{
+ "-",
+ "ascenseur",
+ "bombedown",
+ "bombeup",
+ "bulldozer",
+ "tresor",
+ "egg",
+ "goal",
+ "explo1",
+ "explo2",
+ "explo3",
+ "explo4",
+ "caisse",
+ "helico",
+ "plouf",
+ "blup",
+ "bombemove",
+ "poisson",
+ "tomates",
+ "jeep",
+ "oiseau",
+ "cle",
+ "door",
+ "balle",
+ "skate",
+ "shield",
+ "power",
+ "magictrack",
+ "tank",
+ "bullet",
+ "drink",
+ "charge",
+ "blupihelico",
+ "blupitank",
+ "glu",
+ "tiplouf",
+ "pollution",
+ "clear",
+ "electro",
+ "tresortrack",
+ "invert",
+ "invertstart",
+ "invertstop",
+ "?????? (43)",
+ "guepe",
+ "?????? (45)",
+ "over",
+ "ascenseur s",
+ "ascenseur si",
+ "cle1",
+ "cle2",
+ "cle3",
+ "bridge",
+ "tentacule",
+ "creature",
+ "dynamite",
+ "dynamite f",
+ "shieldtrack",
+ "hidetrack",
+ "","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",
+ "explo5",
+ "explo6",
+ "explo7",
+ "explo8",
+ "explo9",
+ "explo10",
+ "bombefollow1",
+ "bombefollow2",
+ "sploutch1",
+ "sploutch2",
+ "sploutch3",
+ "","","","","","","","","","",
+ "","","","","","","","","","",
+ "","","","","","","","","","",
+ "","","","","","","","","","",
+ "","","","","","","","","","",
+ "","","","","","","","","","",
+ "","","","","","","","","","",
+ "","","","","","","","","","",
+ "","","","","","","","","","",
+ "","","","","","","","","",
+ "bombeperso1",
+ "bombeperso2",
+ "bombeperso3",
+ "bombeperso4"
+};
+
+// Types :
+
+#define TYPE_ASCENSEUR 1 // lift
+#define TYPE_BOMBEDOWN 2 // floor bomb
+#define TYPE_BOMBEUP 3 // hanging bomb
+#define TYPE_BULLDOZER 4
+#define TYPE_TRESOR 5
+#define TYPE_EGG 6
+#define TYPE_GOAL 7
+#define TYPE_EXPLO1 8
+#define TYPE_EXPLO2 9
+#define TYPE_EXPLO3 10
+#define TYPE_EXPLO4 11
+#define TYPE_CAISSE 12
+#define TYPE_HELICO 13
+#define TYPE_PLOUF 14
+#define TYPE_BLUP 15
+#define TYPE_BOMBEMOVE 16
+#define TYPE_POISSON 17 // fish
+#define TYPE_TOMATES 18 // unused
+#define TYPE_JEEP 19
+#define TYPE_OISEAU 20 // bird
+#define TYPE_CLE 21 // gold key
+#define TYPE_DOOR 22
+#define TYPE_BALLE 23 // glue ball
+#define TYPE_SKATE 24
+#define TYPE_SHIELD 25
+#define TYPE_POWER 26 // lollipop
+#define TYPE_MAGICTRACK 27 // sparkles
+#define TYPE_TANK 28
+#define TYPE_BULLET 29
+#define TYPE_DRINK 30
+#define TYPE_CHARGE 31 // charging device
+#define TYPE_BLUPIHELICO 32
+#define TYPE_BLUPITANK 33
+#define TYPE_GLU 34
+#define TYPE_TIPLOUF 35
+#define TYPE_POLLUTION 36
+#define TYPE_CLEAR 37 // burned blupi
+#define TYPE_ELECTRO 38 // shocked blupi
+#define TYPE_TRESORTRACK 39 // sparkles
+#define TYPE_INVERT 40
+#define TYPE_INVERTSTART 41
+#define TYPE_INVERTSTOP 42
+#define TYPE_INVERTSPIN 43
+#define TYPE_GUEPE 44 // wasp
+#define TYPE_OVER 46 // hovercraft
+#define TYPE_ASCENSEURs 47 // conveyor belt right
+#define TYPE_ASCENSEURsi 48 // conveyor belt left
+#define TYPE_CLE1 49 // red key
+#define TYPE_CLE2 50 // green key
+#define TYPE_CLE3 51 // blue key
+#define TYPE_BRIDGE 52 // fragile bridge
+#define TYPE_TENTACULE 53 // slime tentacle effect
+#define TYPE_CREATURE 54 // moving slime creature
+#define TYPE_DYNAMITE 55
+#define TYPE_DYNAMITEf 56 // lit dynamite
+#define TYPE_SHIELDTRACK 57 // particles
+#define TYPE_HIDETRACK 58 // particles
+#define TYPE_EXPLO5 90
+#define TYPE_EXPLO6 91
+#define TYPE_EXPLO7 92
+#define TYPE_EXPLO8 93
+#define TYPE_EXPLO9 94
+#define TYPE_EXPLO10 95
+#define TYPE_BOMBEFOLLOW1 96 // homing bomb, stopped
+#define TYPE_BOMBEFOLLOW2 97 // homing bomb, moving
+#define TYPE_SPLOUTCH1 98 // particles
+#define TYPE_SPLOUTCH2 99 // particles
+#define TYPE_SPLOUTCH3 100 // particles
+#define TYPE_BOMBEPERSO1 200 // player 1 personal bomb (yellow)
+#define TYPE_BOMBEPERSO2 201 // player 2 personal bomb (orange)
+#define TYPE_BOMBEPERSO3 202 // player 3 personal bomb (blue)
+#define TYPE_BOMBEPERSO4 203 // player 4 personal bomb (green)
+
+// Steps :
+
+enum {
+ STEP_STOPSTART = 1,
+ STEP_ADVANCE,
+ STEP_STOPEND,
+ STEP_RECEDE
+};
+
+// Sons :
+
+#define SOUND_CLICK 0
+#define SOUND_JUMP1 1 // medium jump
+#define SOUND_JUMP2 2 // high jump
+#define SOUND_JUMPEND 3 // step on stone
+#define SOUND_JUMPTOC 4 // hit stone
+#define SOUND_TURN 5
+#define SOUND_VERTIGO 6 // "whoops"
+#define SOUND_DOWN 7 // look down
+#define SOUND_FALL 8
+#define SOUND_NEW 9 // respawn
+#define SOUND_BOUM 10
+#define SOUND_TRESOR 11
+#define SOUND_EGG 12
+#define SOUND_ENDKO 13
+#define SOUND_ENDOK 14
+#define SOUND_HELICOSTART 15
+#define SOUND_HELICOHIGH 16
+#define SOUND_HELICOSTOP 17
+#define SOUND_HELICOLOW 18
+#define SOUND_LASTTRESOR 19
+#define SOUND_UP 20 // partially unused sound when pressing left+right+down
+#define SOUND_LOOKUP 21
+#define SOUND_JUMP0 22 // low jump
+#define SOUND_PLOUF 23
+#define SOUND_BLUP 24
+#define SOUND_SURF 25 // inhale
+#define SOUND_DROWN 26
+#define SOUND_ERROR 27
+#define SOUND_JEEPSTART 28
+#define SOUND_JEEPHIGH 29
+#define SOUND_JEEPSTOP 30
+#define SOUND_JEEPLOW 31
+#define SOUND_BYE 32 // "au au"
+#define SOUND_DOOR 33 // door creak
+#define SOUND_SUSPENDTOC 34 // grab bar
+#define SOUND_SUSPENDJUMP 35 // pull up from bar
+#define SOUND_SINGE 36
+#define SOUND_PATIENT 37
+#define SOUND_PUSH 38 // pushing crate
+#define SOUND_POP 39 // pulling crate
+#define SOUND_JUMPAIE 40 // headache "aie"
+#define SOUND_RESSORT 41 // spring
+#define SOUND_STARTSHIELD 42
+#define SOUND_STOPSHIELD 43
+#define SOUND_STARTPOWER 44 // lollipop activate
+#define SOUND_STOPPOWER 45 // lollipop deactivate
+#define SOUND_OUF1 46 // exit water "phew"
+#define SOUND_OUF2 47 // scared "huaaaahhhhh--!"
+#define SOUND_OUF3 48 // stop moving case "gahh...!"
+#define SOUND_OUF4 49 // shriek, heartbeat
+#define SOUND_SUCETTE 50 // lick lollipop
+#define SOUND_GLU 51 // buaaaaaaaaaaaah
+#define SOUND_FIREOK 52
+#define SOUND_FIREKO 53 // ratchet
+#define SOUND_TAKEGLU 54
+#define SOUND_STARTCLOUD 55
+#define SOUND_STOPCLOUD 56
+#define SOUND_DRINK 57
+#define SOUND_CHARGE 58
+#define SOUND_ELECTRO 59
+#define SOUND_PERSOTAKE 60 // "wow!"
+#define SOUND_PERSOPOSE 61 // *evil laugh*
+#define SOUND_STARTHIDE 62
+#define SOUND_STOPHIDE 63
+#define SOUND_TIPLOUF 64 // light splash
+#define SOUND_MOCKERY 65
+#define SOUND_INVERTSTART 66
+#define SOUND_INVERTSTOP 67
+#define SOUND_OVERSTOP 68 // hovercraft stall
+#define SOUND_BLITZ 69 // lightning buzz
+#define SOUND_ECRASE 70
+#define SOUND_TELEPORTE 71
+#define SOUND_BRIDGE1 72 // bridge fall
+#define SOUND_BRIDGE2 73 // bridge appear
+#define SOUND_ANGEL 74 // "uie uie uie, aie aie aie"
+#define SOUND_SCIE 75 // saw
+#define SOUND_SWITCHOFF 76
+#define SOUND_SWITCHON 77
+#define SOUND_JUMPENDb 78 // step on wood
+#define SOUND_JUMPTOCb 79 // hit wood
+#define SOUND_JUMPENDm 80 // step on metal
+#define SOUND_JUMPTOCm 81 // hit metal
+#define SOUND_JUMPENDg 82 // step on cave
+#define SOUND_JUMPTOCg 83 // hit cave
+#define SOUND_JUMPENDo 84 // step on slime
+#define SOUND_JUMPTOCo 85 // hit slime
+#define SOUND_JUMPENDk 86 // step on plastic
+#define SOUND_JUMPTOCk 87 // hit plastic
+#define SOUND_JUMPENDf 88 // step on cheese
+#define SOUND_JUMPTOCf 89 // hit cheese
+#define SOUND_JUMPENDh 90 // step on grass
+#define SOUND_JUMPTOCh 91 // hit grass
+#define SOUND_FOLLOW 92 // homing bomb "be-be-beep"
+#define SOUND_MOVIE 99
+
+//
+
+enum {
+ KEY_NONE = 0,
+ KEY_LEFT = 1,
+ KEY_RIGHT = 2,
+ KEY_UP = 4,
+ KEY_DOWN = 8,
+ KEY_JUMP = 16,
+ KEY_FIRE = 32
+};
+
+// Boutons (play) :
+
+#define MAXBUTTON 40
+
+// Lutins pour la souris
+
+#define SPRITE_ARROW 1
+#define SPRITE_POINTER 2
+#define SPRITE_ARROWU 3
+#define SPRITE_ARROWD 4
+#define SPRITE_ARROWL 5
+#define SPRITE_ARROWR 6
+#define SPRITE_ARROWUL 7
+#define SPRITE_ARROWUR 8
+#define SPRITE_ARROWDL 9
+#define SPRITE_ARROWDR 10
+#define SPRITE_WAIT 11
+#define SPRITE_EMPTY 12
+#define SPRITE_DISABLE 13
+
+
+// User define message
+
+enum {
+ WM_UPDATE = WM_USER + 1,
+
+ WM_DECOR1 = WM_USER + 20,
+ WM_DECOR2,
+ WM_DECOR3,
+ WM_DECOR4,
+ WM_DECOR5,
+ WM_DECOR6,
+ WM_DECOR7,
+ WM_DECOR8,
+ WM_DECOR9,
+ WM_DECOR10,
+ WM_DECOR11,
+
+ WM_BUTTON0 = WM_USER + 200,
+ WM_BUTTON1,
+ WM_BUTTON2,
+ WM_BUTTON3,
+ WM_BUTTON4,
+ WM_BUTTON5,
+ WM_BUTTON6,
+ WM_BUTTON7,
+ WM_BUTTON8,
+ WM_BUTTON9,
+ WM_BUTTON10,
+ WM_BUTTON11,
+ WM_BUTTON12,
+ WM_BUTTON13,
+ WM_BUTTON14,
+ WM_BUTTON15,
+ WM_BUTTON16,
+ WM_BUTTON17,
+ WM_BUTTON18,
+ WM_BUTTON19,
+ WM_BUTTON20,
+ WM_BUTTON21,
+ WM_BUTTON22,
+ WM_BUTTON23,
+ WM_BUTTON24,
+ WM_BUTTON25,
+ WM_BUTTON26,
+ WM_BUTTON27,
+ WM_BUTTON28,
+ WM_BUTTON29,
+ WM_BUTTON30,
+ WM_BUTTON31,
+ WM_BUTTON32,
+ WM_BUTTON33,
+ WM_BUTTON34,
+ WM_BUTTON35,
+ WM_BUTTON36,
+ WM_BUTTON37,
+ WM_BUTTON38,
+ WM_BUTTON39,
+
+ WM_DIMS1 = WM_USER + 241,
+ WM_DIMS2,
+ WM_DIMS3,
+ WM_DIMS4,
+
+ WM_READ0 = WM_USER + 300,
+ WM_READ1,
+ WM_READ2,
+ WM_READ3,
+ WM_READ4,
+ WM_READ5,
+ WM_READ6,
+ WM_READ7,
+ WM_READ8,
+ WM_READ9,
+ WM_WRITE0,
+ WM_WRITE1,
+ WM_WRITE2,
+ WM_WRITE3,
+ WM_WRITE4,
+ WM_WRITE5,
+ WM_WRITE6,
+ WM_WRITE7,
+ WM_WRITE8,
+ WM_WRITE9,
+
+ WM_PHASE_INIT = WM_USER + 500,
+ WM_PHASE_PLAY,
+ WM_PHASE_BUILD,
+ WM_PHASE_NAMEGAMER,
+ WM_PHASE_CLEARGAMER,
+ WM_PHASE_INFO,
+ WM_PHASE_PLAYTEST,
+ WM_PHASE_1531,
+ WM_PHASE_WIN,
+ WM_PHASE_LOST,
+ WM_PHASE_SETUP,
+ WM_PHASE_MUSIC,
+ WM_PHASE_PLAYMOVIE,
+ WM_PHASE_WINMOVIE,
+ WM_PHASE_1539,
+ WM_PHASE_DOPLAY, // do singleplayer
+ WM_PHASE_LASTWIN, // PB vestige
+ WM_PHASE_SETUPp,
+ WM_PHASE_REGION,
+ WM_PHASE_INSERT,
+ WM_PHASE_QUITPLAYTEST,
+ WM_PHASE_GAMER,
+ WM_PHASE_WINDESIGN,
+ WM_PHASE_LOSTDESIGN,
+ WM_PHASE_WINMOVIEDESIGN,
+ WM_PHASE_LOSTMULTI,
+ WM_PHASE_WINMULTI,
+ WM_PHASE_WINMOVIEMULTI,
+ WM_PHASE_TESTCD,
+ WM_PHASE_MANUEL,
+ WM_PHASE_PRIVATE,
+ WM_PHASE_UNDO, // PB vestige
+ WM_PHASE_BYE,
+ WM_PHASE_DEMO,
+ WM_PHASE_NAMEDESIGN,
+ WM_PHASE_WRITEDESIGN, // export design to c:\user
+ WM_PHASE_READDESIGN, // import design from c:\user
+ WM_PHASE_CLEARDESIGN,
+ WM_PHASE_DONAMEGAMER,
+ WM_PHASE_DOCLEARGAMER,
+ WM_PHASE_DONAMEDESIGN,
+ WM_PHASE_DOWRITEDESIGN,
+ WM_PHASE_DOREADDESIGN,
+ WM_PHASE_DOCLEARDESIGN,
+ WM_PHASE_SERVICE,
+ WM_PHASE_DP_DOSERVICE,
+ WM_PHASE_DP_CANCELSERVICE,
+ WM_PHASE_SESSION,
+ WM_PHASE_DP_JOIN,
+ WM_PHASE_DP_CREATELOBBY,
+ WM_PHASE_DP_REFRESH,
+ WM_PHASE_DP_CANCELSESSION,
+ WM_PHASE_MULTI,
+ WM_PHASE_DP_STARTMULTI,
+ WM_PHASE_DP_CANCELMULTI,
+ WM_PHASE_CREATE,
+ WM_PHASE_DP_DOCREATE,
+ WM_PHASE_DP_CANCELCREATE,
+ WM_PHASE_STOP, // escape key pause menu during gameplay
+ WM_PHASE_HELP,
+ WM_PHASE_GWRITE,
+ WM_PHASE_GREADp,
+ WM_PHASE_GREAD,
+ WM_PHASE_QUITPLAY,
+ WM_PHASE_1588,
+ WM_PHASE_INTRO1,
+ WM_PHASE_INTRO2,
+
+ WM_PREV = WM_USER + 600,
+ WM_NEXT,
+ WM_MOVIE
+};
+
+// Types de gestion de la souris.
+
+#define MOUSETYPEGRA 1
+#define MOUSETYPEWIN 2
+#define MOUSETYPEWINPOS 3
+
+// Button icons
+
+enum {
+ IC_BT_TECH = 0, // Item: Square tech-block
+ IC_BT_SPECIALTECH, // Item: Special tech-block
+ IC_BT_TRIANGULARTECH, // Item: Triangular tech-block
+ IC_BT_9, // Item: Special tech-block (T shape)
+ IC_BT_10, // Scrolling: Horizontal and vertical (duplicate?)
+ IC_BT_BLUPI, // Item: Yellow Blupi
+ IC_BT_CANCEL, // UI: Black X (cancel)
+ IC_BT_TREASURE, // Item: Treasure chest
+ IC_BT_BOMB, // Item: Bomb
+ IC_BT_BOMBUP, // Item: Hanging bomb
+ IC_BT_EGG, // Item: Egg
+ IC_BT_GOAL, // Item: Goal
+ IC_BT_CANCEL2, // UI: Yellow X
+ IC_BT_HORIZONTAL, // Scrolling: Horizontal only
+ IC_BT_VERTICAL, // Scrolling: Vertical only
+ IC_BT_HORIZONTALVERTICAL, // Scrolling: Horizontal and vertical
+ IC_BT_BULLDOZER, // Item: Bulldozer
+ IC_BT_CASE, // Item: Wooden case
+ IC_BT_ACCEPT, // UI: Black checkmark
+ IC_BT_LIFTFAST, // Item: Fast lift
+ IC_BT_LIFTNORMAL, // Item: Normal lift
+ IC_BT_LIFTSLOW, // Item: Slow lift
+ IC_BT_ROCK, // Item: Square rock
+ IC_BT_WOODENWALL, // Item: Wooden wall
+ IC_BT_HELICOPTER, // Item: Helicopter
+ IC_BT_DREAM, // Item: Dream
+ IC_BT_LAVA, // Item: Lava
+ IC_BT_SECRETTECH, // Item: Secret tech-block
+ IC_BT_LIFTFASTSLOW, // Item: Fast/slow lift
+ IC_BT_PALMTREE, // Item: Palmtree
+ IC_BT_SUPPORT, // Item: Support
+ IC_BT_TREE, // Item: Tree
+ IC_BT_VEGETATION, // Item: Vegetation
+ IC_BT_HOUSE, // Item: House
+ IC_BT_MECH, // Item: Square mechanical
+ IC_BT_SPECIALMECH, // Item: Special mechanical
+ IC_BT_DELETE, // UI: Red X (delete)
+ IC_BT_BIGMECH, // Item: Mechanical background element
+ IC_BT_WATER, // Item: Water
+ IC_BT_GRASS, // Item: Grass
+ IC_BT_STOP, // UI: STOP sign
+ IC_BT_WIND, // Item: Wind
+ IC_BT_FAN, // Item: Fan
+ IC_BT_CREATE, // UI: Create multiplayer lobby
+ IC_BT_MUSIC, // UI: Music
+ IC_BT_JOIN, // UI: Join multiplayer lobby
+ IC_BT_NAME, // UI: Edit name
+ IC_BT_SETUP, // UI: Setup (analog gauge)
+ IC_BT_PLAY, // UI: Play (dice)
+ IC_BT_DESIGN, // UI: Design (wrench and screwdriver)
+ IC_BT_ARROWLEFT, // UI: Arrow pointing left
+ IC_BT_ARROWRIGHT, // UI: Arrow pointing right
+ IC_BT_READ, // UI: Load game
+ IC_BT_WRITE, // UI: Save game
+ IC_BT_MOVINGBOMB, // Item: Moving bomb
+ IC_BT_FISH, // Item: Fish
+ IC_BT_BAR, // Item: Bar to hang from
+ IC_BT_JEEP, // Item: Jeep
+ IC_BT_FURNITURE, // Item: Furniture
+ IC_BT_TRIANGULARROCK, // Item: Triangular rock
+ IC_BT_BIRD, // Item: Bird
+ IC_BT_TINY, // Scrolling: Tiny (No scrolling)
+ IC_BT_LEVELSTART, // Item: Level start
+ IC_BT_DOOR, // Item: Door (hub)
+ IC_BT_KEY, // Item: Key (goal)
+ IC_BT_FACADE, // Item: Building facade
+ IC_BT_ROOF, // Item: Roof
+ IC_BT_SECRETMECH, // Item: Secret mechanical
+ IC_BT_SECRETROCK, // Item: Secret rock
+ IC_BT_MARINE, // Item: Marine plant
+ IC_BT_SPRING, // Item: Spring
+ IC_BT_SKATEBOARD, // Item: Skateboard
+ IC_BT_ARROWUP, // UI: Arrow pointing up
+ IC_BT_ARROWDOWN, // UI: Arrow pointing down
+ IC_BT_SHIELD, // Item: Shield
+ IC_BT_LOLLIPOP, // Item: Lollipop
+ IC_BT_SECRETCASE, // Item: Secret wooden case
+ IC_BT_CONTINUE, // UI: Continue game
+ IC_BT_HALT, // UI: Halt (hand)
+ IC_BT_INVISIBLEBLOCK, // Item: Invisible block
+ IC_BT_KIDSSTUFF, // Item: Kid's stuff block
+ IC_BT_SPECIALKIDSSTUFF, // Item: Special kid's stuff
+ IC_BT_BIGKIDSSTUFF, // Item: Kid's stuff background element
+ IC_BT_MULTI, // UI: Multiplayer
+ IC_BT_DEMO, // UI: Demo
+ IC_BT_TANK, // Item: Tank
+ IC_BT_HELP, // UI: Help
+ IC_BT_DYNAMITE, // Item: Dynamite
+ IC_BT_GLUE, // Item: Glue supply
+ IC_BT_DRINK, // Item: Invisibility potion
+ IC_BT_NOTREADY, // UI: Not ready (multiplayer lobby)
+ IC_BT_READY, // UI: Ready (multiplayer lobby)
+ IC_BT_PERSO, // Item: Personal bomb
+ IC_BT_CHARGER, // Item: Recharging device
+ IC_BT_SEND, // UI: Send message
+ IC_BT_HELICOENEMY, // Item: Heliported enemy
+ IC_BT_BLUPI1, // Item: Orange Blupi
+ IC_BT_BLUPI2, // Item: Blue Blupi
+ IC_BT_BLUPI3, // Item: Green Blupi
+ IC_BT_TANKENEMY, // Item: Motorized enemy
+ IC_BT_CHEESE, // Item: Cheese
+ IC_BT_INVERTER, // Item: Inverter
+ IC_BT_PERSO0, // Item: Yellow personal bomb
+ IC_BT_PERSO1, // Item: Orange personal bomb
+ IC_BT_PERSO2, // Item: Blue personal bomb
+ IC_BT_PERSO3, // Item: Green personal bomb
+ IC_BT_PIPES, // Item: Pipes
+ IC_BT_HOMINGBOMB, // Item: Homing bomb
+ IC_BT_TEAM1, // UI: Select team 1
+ IC_BT_TEAM2, // UI: Select team 2
+ IC_BT_TEAM3, // UI: Select team 3
+ IC_BT_TEAM4, // UI: Select team 4
+ IC_BT_BRICKS, // Item: Bricks
+ IC_BT_WASP, // Item: Wasp
+ IC_BT_TEAMLITTLE1, // Gameplay: Team 1 player indicator
+ IC_BT_TEAMLITTLE2, // Gameplay: Team 2 player indicator
+ IC_BT_TEAMLITTLE3, // Gameplay: Team 3 player indicator
+ IC_BT_TEAMLITTLE4, // Gameplay: Team 4 player indicator
+ IC_BT_CAVE, // Item: Cave
+ IC_BT_HOVERCRAFT, // Item: Hovercraft
+ IC_BT_LIGHTNING, // Item: Lightning
+ IC_BT_CONVEYOR, // Item: Lift with conveyor
+ IC_BT_CRUSHER, // Item: Crusher
+ IC_BT_VANISH, // Item: Vanishing bloc
+ IC_BT_TELEPORTER, // Item: Teleporter
+ IC_BT_KEYCOLOR, // Item: Key (color)
+ IC_BT_DOORCOLOR, // Item: Door (color)
+ IC_BT_SECRETCAVE, // Item: Secret cave
+ IC_BT_SECRETCHEESE, // Item: Secret cheese
+ IC_BT_SLIME, // Item: Slime block
+ IC_BT_BIGSLIME, // Item: Slime background element
+ IC_BT_SLIMEFLOOR, // Item: Floor slime trap
+ IC_BT_SAW, // Item: Saw
+ IC_BT_LOWCOLORBACK, // UI: 256-color background
+ IC_BT_TRUECOLORBACK, // UI: 65536-color background
+ IC_BT_LOWCOLORDECOR, // UI: 256-color foreground
+ IC_BT_TRUECOLORDECOR, // UI: 65536-color foreground
+ IC_BT_PALACE, // Item: Palace
+ IC_BT_PALACEELEMENT, // Item: Element for palace
+ IC_BT_BIGPALACE, // Item: Palace background element
+ IC_BT_SLIMECREATURE, // Item: Slime creature
+ IC_BT_BRIDGE, // Item: Fragile bridge
+ IC_BT_SPIDERWEB, // Item: Spider's web
+ IC_BT_SLIMECEILING, // Item: Ceiling slime trap
+ IC_BT_TREASUREDOOR // Item: Numbered treasure door
+};
+
+
+namespace Object {
+ enum Object {
+ Empty = -1,
+ Hili,
+ TechSquare_1,
+ TechSquare_2,
+ TechSquare_3,
+ TechSquare_4,
+ TechSquare_5,
+ TechSquare_6,
+ TechSquare_7,
+ TechSquare_8,
+ TechSquare_9,
+ TechSquare_10,
+ TechSquare_11,
+ TechSquare_12,
+ TechSquare_13,
+ TechSquare_14,
+ TechTriRight_1,
+ TechTriRight_2, // 16
+ TechTriLeft_1,
+ TechTriLeft_2,
+ TechSpecial_1,
+ TechSpecial_2,
+ TechSpecial_3,
+ TechSecret_1,
+ TechSpecial_4,
+ TechSpecial_5,
+ TechSpecial_6,
+ TechSpecial_7,
+ TechSpecial_8,
+ TechSpecial_9,
+ TechSpecial_10,
+ LiftPoint_1,
+ LiftPoint_2,
+ Caisse_1, // 32
+ Caisse_2,
+ Caisse_3,
+ RockSquare_1,
+ RockSquare_2,
+ RockSquare_3,
+ RockSquare_4,
+ RockSquare_5,
+ RockSquare_6,
+ WoodWall_1,
+ WoodWall_2,
+ WoodWall_3,
+ WoodWall_4,
+ WoodWall_5,
+ WoodWall_6,
+ WoodWall_7,
+ Dream_1, // 48
+ Dream_2,
+ Dream_3,
+ Dream_4,
+ Dream_5,
+ Dream_6,
+ Dream_7,
+ Dream_8,
+ Dream_9,
+ Dream_10,
+ Dream_11,
+ Dream_12,
+ Dream_13,
+ Dream_14,
+ Dream_15,
+ Dream_16,
+ Dream_17, // 64
+ Dream_18,
+ Dream_19,
+ Dream_20,
+ Lava_1,
+ Lava_2,
+ Lava_3,
+ Lava_4,
+ Lava_5,
+ TechSecret_2,
+ RockTriLeft_1,
+ RockTriRight_1,
+ Support_1,
+ Support_2,
+ MechSquare_1,
+ MechSquare_2,
+ MechSquare_3, // 80
+ MechSquare_4,
+ MechSquare_5,
+ MechSquare_6,
+ MechSquare_7,
+ MechSecret_1,
+ MechSecret_2,
+ MechSpecial_1,
+ MechSpecial_2,
+ MechSpecial_3,
+ MechSpecial_4,
+ WaterSquare_1,
+ WaterSurf_1,
+ WaterSurf_2,
+ WaterSurf_3,
+ WaterSurf_4,
+ WaterSquare_2, // 96
+ WaterSquare_3,
+ WaterSquare_4,
+ Splash_1,
+ Splash_2,
+ Splash_3,
+ Splash_4,
+ Bubble_1,
+ Bubble_2,
+ Bubble_3,
+ Bubble_4,
+ GrassSquare_1,
+ GrassLeft,
+ GrassRight,
+ WindLeft_1,
+ WindLeft_2, // 112
+ WindLeft_3,
+ WindLeft_4,
+ WindRight_1,
+ WindRight_2,
+ WindRight_3,
+ WindRight_4,
+ WindUp_1,
+ WindUp_2,
+ WindUp_3,
+ WindUp_4,
+ WindDown_1,
+ WindDown_2,
+ WindDown_3,
+ WindDown_4,
+ FanLeft_1,
+ FanLeft_2, // 128
+ FanLeft_3,
+ FanRight_1,
+ FanRight_2,
+ FanRight_3,
+ FanUp_1,
+ FanUp_2,
+ FanUp_3,
+ FanDown_1,
+ FanDown_2,
+ FanDown_3,
+ Bar_1,
+ Bookshelf_1,
+ Bookshelf_2,
+ Bookshelf_3,
+ Bookshelf_4,
+ Bookshelf_5,
+ RockSquare_7, // 144
+ RockSquare_8,
+ RockSquare_9,
+ RockSquare_10,
+ RockSquare_11,
+ RockSquare_12,
+ RockSquare_13,
+ RockSquare_14,
+ RockSquare_15,
+ RockSquare_16,
+ RockTriLeft_2,
+ RockTriRight_2,
+ RockSquare_17,
+ GrassSquare_2,
+ World_1,
+ World_2,
+ World_3, // 160
+ World_4,
+ World_5,
+ World_6,
+ World_7,
+ World_8,
+ WorldDone_1,
+ WorldDone_2,
+ WorldDone_3,
+ WorldDone_4,
+ WorldDone_5,
+ WorldDone_6,
+ WorldDone_7,
+ WorldDone_8,
+ Level_1,
+ Level_2,
+ Level_3, // 176
+ Level_4,
+ Level_5,
+ Level_6,
+ Level_7,
+ Level_8,
+ DoorLevel,
+ DoorCourse,
+ WorldBack,
+ RockSecret,
+ Facade_1,
+ Facade_2,
+ Facade_3,
+ Facade_4,
+ Facade_5,
+ Facade_6,
+ Facade_7, // 192
+ Roof_1,
+ Roof_2,
+ Roof_3,
+ Roof_4,
+ Roof_5,
+ Support_3,
+ Support_4,
+ Support_5,
+ Support_6,
+ Bar_2,
+ Marine_1,
+ Marine_2,
+ Marine_3,
+ Marine_4,
+ Marine_5,
+ Marine_6, // 208
+ Spring_1,
+ Spring_2,
+ Spring_3,
+ Spring_4,
+ Spring_5,
+ Invisible,
+ KidsSquare_1,
+ KidsSquare_2,
+ KidsSquare_3,
+ KidsSquare_4,
+ KidsSquare_5,
+ KidsSquare_6,
+ KidsSquare_7,
+ KidsSquare_8,
+ KidsSpecial_1,
+ KidsSpecial_2, // 224
+ KidsSpecial_3,
+ KidsSpecial_4,
+ KidsSpecial_5,
+ KidsSpecial_6,
+ KidsSpecial_7,
+ KidsSquare_9,
+ KidsSquare_10,
+ KidsSpecial_8,
+ KidsSquare_11,
+ KidsSquare_12,
+ Support_7,
+ Support_8,
+ DitherMask,
+ Charger_1,
+ Charger_2,
+ Charger_3, // 240
+ Charger_4,
+ Charger_5,
+ Charger_6,
+ Splash_5,
+ Unk_F5,
+ CheeseSquare_1,
+ CheeseSquare_2,
+ CheeseSquare_3,
+ CheeseSquare_4,
+ Pipes_1,
+ Pipes_2,
+ Pipes_3,
+ Pipes_4,
+ Pipes_5,
+ Pipes_6,
+ Pipes_7, // 256
+ Pipes_8,
+ Pipes_9,
+ Pipes_10,
+ Pipes_11,
+ Bricks_1,
+ Bricks_2,
+ Bricks_3,
+ CheeseSupport_1,
+ CheeseSupport_2,
+ CheeseSupport_3,
+ CheeseSupport_4,
+ CheeseSupport_5,
+ CheeseSupport_6,
+ CheeseSupport_7,
+ CheeseSupport_8,
+ CheeseSupport_9, // 272
+ CheeseSupport_10,
+ CheeseSupport_11,
+ CheeseSupport_12,
+ CheeseSupport_13,
+ CheeseSupport_14,
+ CheeseSupport_15,
+ CheeseSupport_16,
+ CheeseSupport_17,
+ CheeseSupport_18,
+ CheeseSupport_19,
+ Bricks_4,
+ Cave_1,
+ CaveSupport_1,
+ CaveSupport_2,
+ CaveSupport_3,
+ CaveSupport_4, // 288
+ CaveSupport_5,
+ CaveSupport_6,
+ CaveSupport_7,
+ CaveSupport_8,
+ CaveSupport_9,
+ CaveSupport_10,
+ CaveSupport_11,
+ CaveSupport_12,
+ CaveSupport_13,
+ CaveSupport_14,
+ CaveSupport_15,
+ CaveSupport_16,
+ Cave_2,
+ CaveSupport_17,
+ CaveSupport_18,
+ LightningMachine, // 304
+ Lightning_1,
+ Lightning_2,
+ Lightning_3,
+ Lightning_4,
+ World_9,
+ WorldDone_9,
+ Conveyor_1,
+ Conveyor_2,
+ Conveyor_3,
+ Conveyor_4,
+ Conveyor_5,
+ Conveyor_6,
+ Crusher_1,
+ Crusher_2,
+ Crusher_3,
+ Crusher_4, // 320
+ Crusher_5,
+ Crusher_6,
+ Crusher_7,
+ Vanish_1,
+ Vanish_2,
+ Vanish_3,
+ Vanish_4,
+ Vanish_5,
+ Vanish_6,
+ Teleporter_1,
+ Teleporter_2,
+ Teleporter_3,
+ Teleporter_4,
+ DoorRed,
+ DoorGreen,
+ DoorBlue, // 336
+ CaveSecret,
+ Cave_3,
+ CheeseSecret,
+ CheeseSquare_5,
+ Slime_1,
+ Slime_2,
+ Slime_3,
+ Slime_4,
+ Slime_5,
+ Slime_6,
+ Slime_7,
+ Slime_8,
+ Slime_9,
+ Slime_10,
+ Slime_11,
+ Slime_12, // 352
+ Slime_13,
+ Slime_14,
+ Slime_15,
+ Slime_16,
+ Slime_17,
+ Slime_18,
+ Slime_19,
+ Slime_20,
+ Slime_21,
+ Slime_22,
+ Slime_23,
+ FragileBridge_1,
+ FragileBridge_2,
+ FragileBridge_3,
+ FragileBridge_4,
+ FragileBridge_5, // 368
+ FragileBridge_6,
+ FragileBridge_7,
+ FragileBridge_8,
+ FragileBridge_9,
+ SlimeTrapFloor_1,
+ SlimeTrapFloor_2,
+ Support_9,
+ Support_10,
+ Support_11,
+ Saw_1,
+ Saw_2,
+ Saw_3,
+ Saw_4,
+ Saw_5,
+ Saw_6,
+ SawSwitchOn, // 384
+ SawSwitchOff,
+ Palace_1,
+ Palace_2,
+ Palace_3,
+ Palace_4,
+ Palace_5,
+ Palace_6,
+ Palace_7,
+ Palace_8,
+ Palace_9,
+ Palace_10,
+ Palace_11,
+ Palace_12,
+ PalaceElement_1,
+ PalaceElement_2,
+ PalaceElement_3, // 400
+ SpiderWeb_1,
+ SpiderWeb_2,
+ SpiderWeb_3,
+ SlimeTrapCeiling_1,
+ SlimeTrapCeiling_2,
+ SlimeTrapCeiling_3,
+ SlimeTrapCeiling_4,
+ SlimeTrapCeiling_5,
+ SlimeTrapCeiling_6,
+ SlimeTrapCeiling_7,
+ World_10,
+ World_11,
+ World_12,
+ World_13,
+ World_14,
+ WorldDone_10, // 416
+ WorldDone_11,
+ WorldDone_12,
+ WorldDone_13,
+ WorldDone_14,
+ DoorTreasure_1,
+ DoorTreasure_2,
+ DoorTreasure_3,
+ DoorTreasure_4,
+ DoorTreasure_5,
+ DoorTreasure_6,
+ DoorTreasure_7,
+ DoorTreasure_8,
+ DoorTreasure_9,
+ DoorTreasure_10,
+ DoorTreasure_11,
+ DoorTreasure_12, // 432
+ DoorTreasure_13,
+ DoorTreasure_14,
+ DoorTreasure_15,
+ DoorTreasure_16,
+ DoorTreasure_17,
+ DoorTreasure_18,
+ DoorTreasure_19,
+ DoorTreasure_20
+ };
+}
+
+#define CLE_RED (1 << 0)
+#define CLE_GREEN (1 << 1)
+#define CLE_BLUE (1 << 2)
+
+#define JAUGE_AIR 0
+#define JAUGE_POWER 1
+
+// hack to mimic array literals in old c++
+#if __cplusplus < 199711
+#define RECT(A,B,C,D) MAKE_RECT(A,B,C,D)
+#define POINT(X,Y) MAKE_POINT(X,Y)
+
+inline RECT MAKE_RECT (int left, int top, int right, int bottom)
+{
+ RECT r = {left, top, right, bottom};
+ return r;
+};
+
+inline POINT MAKE_POINT (int x, int y)
+{
+ POINT p = {x, y};
+ return p;
+};
+#else
+#define RECT(A,B,C,D) RECT{A,B,C,D}
+#define POINT(X,Y) POINT{X,Y}
+#endif
+
+// helpers for POINT
+
+POINT operator+(POINT p, const POINT& a)
+{
+ return POINT( a.x + p.x, a.y + p.y );
+}
+
+POINT operator-(POINT p, const POINT& a)
+{
+ return POINT( p.x - a.x, p.y - a.y );
+}
+
+POINT operator*(POINT p, const POINT& a)
+{
+ return POINT( a.x * p.x, a.y * p.y );
+}
+
+POINT operator/(POINT p, const POINT& a)
+{
+ return POINT( p.x / a.x, p.y / a.y );
+}
+
+POINT operator*(POINT p, const int& a)
+{
+ return POINT( p.x * a, p.y * a );
+}
+
+POINT operator/(POINT p, const int& a)
+{
+ return POINT( p.x / a, p.y / a );
+}
+
+POINT& operator+=(POINT& p, const POINT& a)
+{
+ return POINT( p.x += a.x, p.y += a.y );
+}
+
+POINT& operator-=(POINT& p, const POINT& a)
+{
+ return POINT( p.x -= a.x, p.y -= a.y );
+}
+
+POINT& operator*=(POINT& p, const POINT& a)
+{
+ return POINT( p.x *= a.x, p.y *= a.y );
+}
+
+POINT& operator/=(POINT& p, const POINT& a)
+{
+ return POINT( p.x /= a.x, p.y /= a.y );
+}
+
+POINT& operator*=(POINT& p, const int& a)
+{
+ return POINT( p.x *= a, p.y *= a );
+}
+
+POINT& operator/=(POINT& p, const int& a)
+{
+ return POINT( p.x /= a, p.y /= a );
+}
+
+bool operator!=(POINT a, const POINT& b)
+{
+ return a.x != b.x || a.y != b.y;
+}
+
+bool operator==(POINT a, const POINT& b)
+{
+ return a.x == b.x && a.y == b.y;
+}
+
+#endif
\ No newline at end of file
diff --git a/src/event.cpp b/src/event.cpp
new file mode 100644
index 0000000..53a76fb
--- /dev/null
+++ b/src/event.cpp
@@ -0,0 +1,5867 @@
+// Event.cpp
+//
+
+#include
+#include
+#include
+//#include
+#include
+#include
+#include "def.h"
+#include "resource.h"
+//#include "pixmap.h"
+//#include "sound.h"
+#include "decor.h"
+#include "movie.h"
+//#include "button.h"
+//#include "menu.h"
+//#include "jauge.h"
+#include "event.h"
+#include "text.h"
+#include "misc.h"
+#include "network.h"
+
+#define DEF_TIME_DEMO 1000
+
+typedef struct
+{
+ short majRev;
+ short minRev;
+ short reserve1[9];
+ char name[100];
+ short mission;
+ short speed;
+ short bMovie;
+ short bHiliInfoButton;
+ short audioVolume;
+ short midiVolume;
+ short bBuildOfficialMissions;
+ short prive;
+ short skillUnused;
+ short multi;
+ short reserve2[92];
+ short nbVies;
+ BYTE doors[200];
+}
+DescInfo;
+
+
+
+// Toutes les premi�res lettres doivent
+// �tre diff�rentes !
+
+static char cheat_code[25][60] =
+{
+ "XMISSION", // 0 (xnjttjpo)
+ "OPENDOORS", // 1
+ "CLEANALL", // 2
+ "MEGABLUPI", // 3
+ "LAYEGG", // 4
+ "KILLEGG", // 5
+ "FUNSKATE", // 6
+ "GIVECOPTER", // 7
+ "JEEPDRIVE", // 8
+ "ALLTREASURE",
+ "ENDGOAL",
+ "SHOWSECRET",
+ "ROUNDSHIELD",
+ "QUICKLOLLIPOP",
+ "TENBOMBS",
+ "BIRDLIME",
+ "DRIVETANK",
+ "POWERCHARGE",
+ "HIDEDRINK",
+ "NETPACKED",
+ "ZNETDEBUG",
+ "YNOSMOOTH",
+ "IOVERCRAFT",
+ "UDYNAMITE",
+ "WELLKEYS",
+};
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+static Phase table[] =
+{
+ {
+ WM_PHASE_TESTCD,
+ "init.blp",
+ FALSE,
+ FALSE,
+ { 0 }
+ },
+ {
+ WM_PHASE_INTRO1,
+ "intro1.blp",
+ FALSE,
+ FALSE,
+ { 0 }
+ },
+ {
+ WM_PHASE_INTRO2,
+ "intro2.blp",
+ FALSE,
+ FALSE,
+ { 0 }
+ },
+ {
+ WM_PHASE_INIT,
+ "init.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_PHASE_GAMER,
+ 0,{ 1, 48 },
+ 86, 410,
+ { 1, 109 }
+ },
+ {
+ WM_PHASE_DEMO,
+ 0,{ 1, 84 },
+ 128, 410,
+ { 1, 212 }
+ },
+ {
+ WM_PHASE_BYE,
+ 0,{ 1, 6 },
+ 540, 410,
+ { 1, 106 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_GAMER,
+ "gamer.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_BUTTON1,
+ 0,{ 0 },
+ 60, 58,
+ { 1, 117 }
+ },
+ {
+ WM_BUTTON2,
+ 0,{ 0 },
+ 60, 98,
+ { 1, 117 }
+ },
+ {
+ WM_BUTTON3,
+ 0,{ 0 },
+ 60, 138,
+ { 1, 117 }
+ },
+ {
+ WM_BUTTON4,
+ 0,{ 0 },
+ 60, 178,
+ { 1, 117 }
+ },
+ {
+ WM_BUTTON5,
+ 0,{ 0 },
+ 60, 218,
+ { 1, 117 }
+ },
+ {
+ WM_BUTTON6,
+ 0,{ 0 },
+ 60, 258,
+ { 1, 117 }
+ },
+ {
+ WM_BUTTON7,
+ 0,{ 0 },
+ 60, 298,
+ { 1, 117 }
+ },
+ {
+ WM_BUTTON8,
+ 0,{ 0 },
+ 60, 338,
+ { 1, 117 }
+ },
+ {
+ WM_PHASE_NAMEGAMER,
+ 0,{ 1, 46 },
+ 546, 178,
+ { 1, 118 }
+ },
+ {
+ WM_PHASE_CLEARGAMER,
+ 0,{ 1, 36 },
+ 546, 220,
+ { 1, 127 }
+ },
+ {
+ WM_PHASE_DOPLAY,
+ 0,{ 1, 48 },
+ 65, 414,
+ { 1, 195 }
+ },
+ {
+ WM_PHASE_SERVICE,
+ 0,{ 1, 83 },
+ 107, 414,
+ { 1, 196 }
+ },
+ {
+ WM_PHASE_PRIVATE,
+ 0,{ 1, 49 },
+ 149, 414,
+ { 1, 188 }
+ },
+ {
+ WM_PHASE_GREAD,
+ 0,{ 1, 52 },
+ 191, 414,
+ { 1, 264 }
+ },
+ {
+ WM_PHASE_SETUP,
+ 0,{ 1, 47 },
+ 330, 414,
+ { 1, 128 }
+ },
+ {
+ WM_PHASE_INIT,
+ 0,{ 1, 40 },
+ 540, 414,
+ { 1, 111 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_NAMEGAMER,
+ "name.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_PHASE_DONAMEGAMER,
+ 0,{ 1, 18 },
+ 222, 326,
+ { 1, 174 }
+ },
+ {
+ WM_PHASE_GAMER,
+ 0,{ 1, 36 },
+ 378, 326,
+ { 1, 175 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_CLEARGAMER,
+ "clear.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_PHASE_DOCLEARGAMER,
+ 0,{ 1, 18 },
+ 222, 326,
+ { 1, 176 }
+ },
+ {
+ WM_PHASE_GAMER,
+ 0,{ 1, 36 },
+ 378, 326,
+ { 1, 177 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_SERVICE,
+ "service.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_BUTTON1,
+ 0,{ 1, 51 },
+ 140, 110,
+ { 0 }
+ },
+ {
+ WM_BUTTON2,
+ 0,{ 1, 51 },
+ 140, 150,
+ { 0 }
+ },
+ {
+ WM_BUTTON3,
+ 0,{ 1, 51 },
+ 140, 190,
+ { 0 }
+ },
+ {
+ WM_BUTTON4,
+ 0,{ 1, 51 },
+ 140, 230,
+ { 0 }
+ },
+ {
+ WM_BUTTON5,
+ 0,{ 1, 51 },
+ 140, 270,
+ { 0 }
+ },
+ {
+ WM_BUTTON6,
+ 0,{ 1, 51 },
+ 140, 310,
+ { 0 }
+ },
+ {
+ WM_BUTTON10,
+ 0,{ 1, 72 },
+ 466, 110,
+ { 1, 242 }
+ },
+ {
+ WM_BUTTON11,
+ 0,{ 1, 73 },
+ 466, 310,
+ { 1, 241 }
+ },
+ {
+ WM_PHASE_DP_DOSERVICE,
+ 0,{ 1, 18 },
+ 222, 389,
+ { 1, 174 }
+ },
+ {
+ WM_PHASE_DP_CANCELSERVICE,
+ 0,{ 1, 36 },
+ 380, 389,
+ { 1, 175 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_SESSION,
+ "session.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_BUTTON1,
+ 0,{ 1, 51 },
+ 120, 110,
+ { 0 }
+ },
+ {
+ WM_BUTTON2,
+ 0,{ 1, 51 },
+ 120, 150,
+ { 0 }
+ },
+ {
+ WM_BUTTON3,
+ 0,{ 1, 51 },
+ 120, 190,
+ { 0 }
+ },
+ {
+ WM_BUTTON4,
+ 0,{ 1, 51 },
+ 120, 230,
+ { 0 }
+ },
+ {
+ WM_BUTTON5,
+ 0,{ 1, 51 },
+ 120, 270,
+ { 0 }
+ },
+ {
+ WM_BUTTON6,
+ 0,{ 1, 51 },
+ 120, 310,
+ { 0 }
+ },
+ {
+ WM_BUTTON10,
+ 0,{ 1, 72 },
+ 490, 110,
+ { 1, 246 }
+ },
+ {
+ WM_BUTTON11,
+ 0,{ 1, 73 },
+ 490, 310,
+ { 1, 245 }
+ },
+ {
+ WM_PHASE_DP_JOIN,
+ 0,{ 1, 45 },
+ 120, 389,
+ { 1, 247 }
+ },
+ {
+ WM_PHASE_DP_CREATELOBBY,
+ 0,{ 1, 43 },
+ 162, 389,
+ { 1, 248 }
+ },
+ {
+ WM_PHASE_DP_REFRESH,
+ 0,{ 1, 72 },
+ 260, 389,
+ { 1, 249 }
+ },
+ {
+ WM_PHASE_DP_CANCELSESSION,
+ 0,{ 1, 36 },
+ 485, 389,
+ { 1, 175 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_CREATE,
+ "create.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_PHASE_DP_DOCREATE,
+ 0,{ 1, 18 },
+ 222, 326,
+ { 1, 174 }
+ },
+ {
+ WM_PHASE_DP_CANCELCREATE,
+ 0,{ 1, 36 },
+ 378, 326,
+ { 1, 175 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_MULTI,
+ "multi.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_BUTTON1,
+ 0,{ 0 },
+ 80, 98,
+ { 1, 207 }
+ },
+ {
+ WM_BUTTON2,
+ 0,{ 0 },
+ 80, 140,
+ { 1, 207 }
+ },
+ {
+ WM_BUTTON3,
+ 0,{ 0 },
+ 80, 182,
+ { 1, 207 }
+ },
+ {
+ WM_BUTTON4,
+ 0,{ 0 },
+ 80, 224,
+ { 1, 207 }
+ },
+ {
+ WM_BUTTON11,
+ 0,{ 1, 36 },
+ 288, 98,
+ { 1, 208 }
+ },
+ {
+ WM_BUTTON12,
+ 0,{ 1, 36 },
+ 288, 140,
+ { 1, 208 }
+ },
+ {
+ WM_BUTTON13,
+ 0,{ 1, 36 },
+ 288, 182,
+ { 1, 208 }
+ },
+ {
+ WM_BUTTON14,
+ 0,{ 1, 36 },
+ 288, 224,
+ { 1, 208 }
+ },
+ {
+ WM_BUTTON20,
+ 0,{ 1, 94 },
+ 404, 388,
+ { 1, 262 }
+ },
+ {
+ WM_PREV,
+ 0,{ 1, 50 },
+ 438, 249,
+ { 1, 107 }
+ },
+ {
+ WM_NEXT,
+ 0,{ 1, 51 },
+ 480, 249,
+ { 1, 108 }
+ },
+ {
+ WM_PHASE_DP_STARTMULTI,
+ 0,{ 1, 48 },
+ 508, 389,
+ { 1, 252 }
+ },
+ {
+ WM_PHASE_DP_CANCELMULTI,
+ 0,{ 1, 36 },
+ 508, 330,
+ { 1, 175 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_INFO,
+ "info.blp",
+ FALSE,
+ TRUE,
+ {
+ {
+ WM_PHASE_WRITEDESIGN,
+ 0,{ 1, 53 },
+ 188, 306,
+ { 1, 113 }
+ },
+ {
+ WM_PHASE_READDESIGN,
+ 0,{ 1, 52 },
+ 232, 306,
+ { 1, 112 }
+ },
+ {
+ WM_PHASE_CLEARDESIGN,
+ 0,{ 1, 36 },
+ 276, 306,
+ { 1, 183 }
+ },
+ {
+ WM_PREV,
+ 0,{ 1, 50 },
+ 188, 398,
+ { 1, 107 }
+ },
+ {
+ WM_PHASE_PLAYMOVIE,
+ 0,{ 1, 48 },
+ 232, 398,
+ { 1, 109 }
+ },
+ {
+ WM_NEXT,
+ 0,{ 1, 51 },
+ 276, 398,
+ { 1, 108 }
+ },
+ {
+ WM_PHASE_BUILD,
+ 0,{ 1, 49 },
+ 422, 98,
+ { 1, 110 }
+ },
+ {
+ WM_PHASE_REGION,
+ 0,{ 1, 22 },
+ 422, 195,
+ { 1, 144 }
+ },
+ {
+ WM_PHASE_NAMEDESIGN,
+ 0,{ 1, 46 },
+ 422, 239,
+ { 1, 185 }
+ },
+ {
+ WM_PHASE_MUSIC,
+ 0,{ 1, 44 },
+ 422, 283,
+ { 1, 129 }
+ },
+ {
+ WM_PHASE_GAMER,
+ 0,{ 1, 40 },
+ 422, 398,
+ { 1, 111 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_PLAY,
+ "",
+ FALSE,
+ FALSE,
+ {
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_PLAYTEST,
+ "",
+ FALSE,
+ FALSE,
+ {
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_STOP,
+ "stop.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_PHASE_GWRITE,
+ 0,{ 1, 53 },
+ 187, 178,
+ { 1, 263 }
+ },
+ {
+ WM_PHASE_GREADp,
+ 0,{ 1, 52 },
+ 187, 296,
+ { 1, 264 }
+ },
+ {
+ WM_PHASE_SETUPp,
+ 0,{ 1, 47 },
+ 350, 156,
+ { 1, 128 }
+ },
+ {
+ WM_PHASE_HELP,
+ 0,{ 1, 86 },
+ 391, 156,
+ { 1, 267 }
+ },
+ {
+ WM_PHASE_QUITPLAY,
+ 0,{ 1, 78 },
+ 413, 262,
+ { 1, 266 }
+ },
+ {
+ WM_PHASE_PLAY,
+ 0,{ 1, 77 },
+ 413, 323,
+ { 1, 265 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_HELP,
+ "help.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_PHASE_PLAY,
+ 0,{ 1, 18 },
+ 442, 358,
+ { 1, 174 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_GREAD,
+ "gread.blp",
+ FALSE,
+ TRUE,
+ {
+ {
+ WM_BUTTON1,
+ 0,{ 0 },
+ 280, 110,
+ { 0 }
+ },
+ {
+ WM_BUTTON2,
+ 0,{ 0 },
+ 280, 150,
+ { 0 }
+ },
+ {
+ WM_BUTTON3,
+ 0,{ 0 },
+ 280, 190,
+ { 0 }
+ },
+ {
+ WM_BUTTON4,
+ 0,{ 0 },
+ 280, 230,
+ { 0 }
+ },
+ {
+ WM_BUTTON5,
+ 0,{ 0 },
+ 280, 270,
+ { 0 }
+ },
+ {
+ WM_BUTTON6,
+ 0,{ 0 },
+ 280, 310,
+ { 0 }
+ },
+ {
+ WM_BUTTON20,
+ 0,{ 1, 18 },
+ 330, 387,
+ { 1, 174 }
+ },
+ {
+ WM_PHASE_GAMER,
+ 0,{ 1, 36 },
+ 458, 387,
+ { 1, 175 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_GREADp,
+ "gread.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_BUTTON1,
+ 0,{ 0 },
+ 280, 110,
+ { 0 }
+ },
+ {
+ WM_BUTTON2,
+ 0,{ 0 },
+ 280, 150,
+ { 0 }
+ },
+ {
+ WM_BUTTON3,
+ 0,{ 0 },
+ 280, 190,
+ { 0 }
+ },
+ {
+ WM_BUTTON4,
+ 0,{ 0 },
+ 280, 230,
+ { 0 }
+ },
+ {
+ WM_BUTTON5,
+ 0,{ 0 },
+ 280, 270,
+ { 0 }
+ },
+ {
+ WM_BUTTON6,
+ 0,{ 0 },
+ 280, 310,
+ { 0 }
+ },
+ {
+ WM_BUTTON20,
+ 0,{ 1, 18 },
+ 330, 387,
+ { 1, 174 }
+ },
+ {
+ WM_PHASE_STOP,
+ 0,{ 1, 36 },
+ 458, 387,
+ { 1, 175 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_GWRITE,
+ "gwrite.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_BUTTON1,
+ 0,{ 0 },
+ 280, 110,
+ { 0 }
+ },
+ {
+ WM_BUTTON2,
+ 0,{ 0 },
+ 280, 150,
+ { 0 }
+ },
+ {
+ WM_BUTTON3,
+ 0,{ 0 },
+ 280, 190,
+ { 0 }
+ },
+ {
+ WM_BUTTON4,
+ 0,{ 0 },
+ 280, 230,
+ { 0 }
+ },
+ {
+ WM_BUTTON5,
+ 0,{ 0 },
+ 280, 270,
+ { 0 }
+ },
+ {
+ WM_BUTTON6,
+ 0,{ 0 },
+ 280, 310,
+ { 0 }
+ },
+ {
+ WM_BUTTON20,
+ 0,{ 1, 18 },
+ 330, 387,
+ { 1, 174 }
+ },
+ {
+ WM_PHASE_STOP,
+ 0,{ 1, 36 },
+ 458, 387,
+ { 1, 175 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_SETUP,
+ "setup.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_BUTTON1,
+ 0,{ 1, 50 },
+ 70, 110,
+ { 1, 130 }
+ },
+ {
+ WM_BUTTON2,
+ 0,{ 1, 51 },
+ 110, 110,
+ { 1, 131 }
+ },
+ {
+ WM_BUTTON3,
+ 0,{ 1, 50 },
+ 70, 220,
+ { 1, 132 }
+ },
+ {
+ WM_BUTTON4,
+ 0,{ 1, 51 },
+ 110, 220,
+ { 1, 133 }
+ },
+ {
+ WM_BUTTON5,
+ 0,{ 1, 133 },
+ 70, 330,
+ { 1, 154 }
+ },
+ {
+ WM_BUTTON6,
+ 0,{ 1, 134 },
+ 110, 330,
+ { 1, 155 }
+ },
+ {
+ WM_BUTTON13,
+ 0,{ 1, 135 },
+ 170, 330,
+ { 1, 305 }
+ },
+ {
+ WM_BUTTON14,
+ 0,{ 1, 136 },
+ 210, 330,
+ { 1, 306 }
+ },
+ {
+ WM_BUTTON7,
+ 0,{ 0 },
+ 370, 110,
+ { 1, 156 }
+ },
+ {
+ WM_BUTTON8,
+ 0,{ 0 },
+ 370, 150,
+ { 1, 157 }
+ },
+ {
+ WM_BUTTON9,
+ 0,{ 0 },
+ 370, 190,
+ { 1, 157 }
+ },
+ {
+ WM_BUTTON10,
+ 0,{ 0 },
+ 370, 230,
+ { 1, 157 }
+ },
+ {
+ WM_BUTTON11,
+ 0,{ 0 },
+ 370, 270,
+ { 1, 157 }
+ },
+ {
+ WM_BUTTON12,
+ 0,{ 0 },
+ 370, 310,
+ { 1, 157 }
+ },
+ {
+ WM_PHASE_GAMER,
+ 0,{ 1, 18 },
+ 541, 411,
+ { 1, 174 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_SETUPp,
+ "setup.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_BUTTON1,
+ 0,{ 1, 50 },
+ 70, 110,
+ { 1, 130 }
+ },
+ {
+ WM_BUTTON2,
+ 0,{ 1, 51 },
+ 110, 110,
+ { 1, 131 }
+ },
+ {
+ WM_BUTTON3,
+ 0,{ 1, 50 },
+ 70, 220,
+ { 1, 132 }
+ },
+ {
+ WM_BUTTON4,
+ 0,{ 1, 51 },
+ 110, 220,
+ { 1, 133 }
+ },
+ {
+ WM_BUTTON5,
+ 0,{ 1, 133 },
+ 70, 330,
+ { 1, 154 }
+ },
+ {
+ WM_BUTTON6,
+ 0,{ 1, 134 },
+ 110, 330,
+ { 1, 155 }
+ },
+ {
+ WM_BUTTON13,
+ 0,{ 1, 135 },
+ 170, 330,
+ { 1, 305 }
+ },
+ {
+ WM_BUTTON14,
+ 0,{ 1, 136 },
+ 210, 330,
+ { 1, 306 }
+ },
+ {
+ WM_BUTTON7,
+ 0,{ 0 },
+ 370, 110,
+ { 1, 156 }
+ },
+ {
+ WM_BUTTON8,
+ 0,{ 0 },
+ 370, 150,
+ { 1, 157 }
+ },
+ {
+ WM_BUTTON9,
+ 0,{ 0 },
+ 370, 190,
+ { 1, 157 }
+ },
+ {
+ WM_BUTTON10,
+ 0,{ 0 },
+ 370, 230,
+ { 1, 157 }
+ },
+ {
+ WM_BUTTON11,
+ 0,{ 0 },
+ 370, 270,
+ { 1, 157 }
+ },
+ {
+ WM_BUTTON12,
+ 0,{ 0 },
+ 370, 310,
+ { 1, 157 }
+ },
+ {
+ WM_PHASE_PLAY,
+ 0,{ 1, 18 },
+ 541, 411,
+ { 1, 174 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_LOST,
+ "lost.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_PHASE_PLAY,
+ 0,{ 1, 18 },
+ 541, 411,
+ { 1, 174 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_LOSTDESIGN,
+ "lost.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_PHASE_INFO,
+ 0,{ 1, 18 },
+ 541, 411,
+ { 1, 174 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_LOSTMULTI,
+ "lost.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_PHASE_GAMER,
+ 0,{ 1, 18 },
+ 541, 411,
+ { 1, 174 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_WIN,
+ "win.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_PHASE_GAMER,
+ 0,{ 1, 18 },
+ 541, 411,
+ { 1, 174 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_WINDESIGN,
+ "win.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_PHASE_INFO,
+ 0,{ 1, 18 },
+ 541, 411,
+ { 1, 174 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_WINMULTI,
+ "win.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_PHASE_GAMER,
+ 0,{ 1, 18 },
+ 541, 411,
+ { 1, 174 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_BUILD,
+ "",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_DECOR1,
+ 0,{ 1, 6 },
+ 11, 11,
+ { 1, 1000 }
+ },
+ {
+ WM_DECOR2,
+ 0,{ 11, 31, 29, 32, 69, 33, 37, 82, 130, 139, 30, 142 },
+ 11, 53,
+ { 11, 2030, 1023, 2072, 1042, 2047, 1026, 1049, 1076, 1080, 1021, 1082 }
+ },
+ {
+ WM_DECOR3,
+ 0,{ 8, 0, 1, 2, 27, 34, 35, 67, 106 },
+ 11, 95,
+ { 8, 1001, 1002, 1003, 1020, 1024, 1025, 1038, 1062 }
+ },
+ {
+ WM_DECOR4,
+ 0,{ 10, 22, 59, 68, 118, 127, 100, 128, 129, 39, 38 },
+ 11, 137,
+ { 10, 2033, 1032, 1037, 1067, 1075, 1061, 1074, 1076, 2038, 2041 }
+ },
+ {
+ WM_DECOR5,
+ 0,{ 10, 137, 138, 65, 66, 112, 58, 23, 80, 81, 79 },
+ 11, 179,
+ { 10, 1079, 1080, 1039, 1040, 1065, 1031, 1015, 1047, 1048, 1022 }
+ },
+ {
+ WM_DECOR6,
+ 0,{ 12, 8, 9, 107, 26, 42, 41, 131, 143, 132, 101, 120, 122 },
+ 11, 221,
+ { 12, 1006, 1007, 1063, 1018, 1028, 1027, 1077, 1083, 1078, 1064, 1069, 1071 }
+ },
+ {
+ WM_DECOR7,
+ 0,{ 13, 21, 20, 19, 28, 121, 16, 55, 60, 113, 140, 54, 95, 99 },
+ 11, 263,
+ { 13, 1009, 1010, 1011, 1019, 1070, 1012, 1030, 1033, 1066, 1081, 1029, 1059, 1060 }
+ },
+ {
+ WM_DECOR8,
+ 0,{ 9, 7, 10, 75, 74, 89, 88, 93, 92, 87 },
+ 11, 305,
+ { 9, 1004, 1005, 1046, 1045, 1052, 1051, 1054, 1053, 2007 }
+ },
+ {
+ WM_DECOR9,
+ 0,{ 10, 125, 126, 144, 124, 56, 70, 123, 141, 17, 76 },
+ 11, 347,
+ { 10, 1036, 1035, 1084, 1073, 1041, 1043, 1072, 2044, 1013, 1014 }
+ },
+ {
+ WM_DECOR10,
+ 0,{ 5, 119, 24, 71, 57, 85 },
+ 11, 389,
+ { 5, 1068, 1016, 1044, 2004, 1050 }
+ },
+ {
+ WM_DECOR11,
+ 0,{ 8, 11, 5, 96, 97, 98, 63, 62, 64 },
+ 11, 431,
+ { 8, 1008, 1055, 1056, 1057, 1058, 1035, 1034, 1036 }
+ },
+ {
+ WM_PHASE_PLAYTEST,
+ 0,{ 1, 48 },
+ 544, 431,
+ { 1, 124 }
+ },
+ {
+ WM_PHASE_INFO,
+ 0,{ 1, 40 },
+ 586, 431,
+ { 1, 119 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_MUSIC,
+ "music.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_BUTTON1,
+ 0,{ 1, 40 },
+ 200, 130,
+ { 1, 134 }
+ },
+ {
+ WM_BUTTON2,
+ 0,{ 1, 44 },
+ 290, 130,
+ { 1, 135 }
+ },
+ {
+ WM_BUTTON3,
+ 0,{ 1, 44 },
+ 290, 170,
+ { 1, 136 }
+ },
+ {
+ WM_BUTTON4,
+ 0,{ 1, 44 },
+ 290, 210,
+ { 1, 137 }
+ },
+ {
+ WM_BUTTON5,
+ 0,{ 1, 44 },
+ 290, 250,
+ { 1, 138 }
+ },
+ {
+ WM_BUTTON6,
+ 0,{ 1, 44 },
+ 290, 290,
+ { 1, 139 }
+ },
+ {
+ WM_BUTTON7,
+ 0,{ 1, 44 },
+ 350, 130,
+ { 1, 140 }
+ },
+ {
+ WM_BUTTON8,
+ 0,{ 1, 44 },
+ 350, 170,
+ { 1, 141 }
+ },
+ {
+ WM_BUTTON9,
+ 0,{ 1, 44 },
+ 350, 210,
+ { 1, 142 }
+ },
+ {
+ WM_BUTTON10,
+ 0,{ 1, 44 },
+ 350, 250,
+ { 1, 143 }
+ },
+ {
+ WM_BUTTON11,
+ 0,{ 1, 44 },
+ 350, 290,
+ { 1, 171 }
+ },
+ {
+ WM_PHASE_INFO,
+ 0,{ 1, 18 },
+ 540, 410,
+ { 1, 174 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_REGION,
+ "region.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_BUTTON3,
+ 0,{ 0 },
+ 48, 58,
+ { 1, 217 }
+ },
+ {
+ WM_BUTTON28,
+ 0,{ 0 },
+ 48, 98,
+ { 1, 300 }
+ },
+ {
+ WM_BUTTON22,
+ 0,{ 0 },
+ 48, 138,
+ { 1, 236 }
+ },
+ {
+ WM_BUTTON19,
+ 0,{ 0 },
+ 48, 178,
+ { 1, 233 }
+ },
+ {
+ WM_BUTTON21,
+ 0,{ 0 },
+ 48, 218,
+ { 1, 235 }
+ },
+ {
+ WM_BUTTON20,
+ 0,{ 0 },
+ 48, 258,
+ { 1, 234 }
+ },
+ {
+ WM_BUTTON7,
+ 0,{ 0 },
+ 48, 298,
+ { 1, 221 }
+ },
+ {
+ WM_BUTTON10,
+ 0,{ 0 },
+ 48, 338,
+ { 1, 224 }
+ },
+ {
+ WM_BUTTON1,
+ 0,{ 0 },
+ 148, 58,
+ { 1, 215 }
+ },
+ {
+ WM_BUTTON15,
+ 0,{ 0 },
+ 148, 98,
+ { 1, 229 }
+ },
+ {
+ WM_BUTTON14,
+ 0,{ 0 },
+ 148, 138,
+ { 1, 228 }
+ },
+ {
+ WM_BUTTON11,
+ 0,{ 0 },
+ 148, 178,
+ { 1, 225 }
+ },
+ {
+ WM_BUTTON8,
+ 0,{ 0 },
+ 148, 218,
+ { 1, 222 }
+ },
+ {
+ WM_BUTTON23,
+ 0,{ 0 },
+ 148, 258,
+ { 1, 237 }
+ },
+ {
+ WM_BUTTON13,
+ 0,{ 0 },
+ 148, 298,
+ { 1, 227 }
+ },
+ {
+ WM_BUTTON6,
+ 0,{ 0 },
+ 148, 338,
+ { 1, 220 }
+ },
+ {
+ WM_BUTTON17,
+ 0,{ 0 },
+ 248, 58,
+ { 1, 231 }
+ },
+ {
+ WM_BUTTON18,
+ 0,{ 0 },
+ 248, 98,
+ { 1, 232 }
+ },
+ {
+ WM_BUTTON12,
+ 0,{ 0 },
+ 248, 138,
+ { 1, 226 }
+ },
+ {
+ WM_BUTTON27,
+ 0,{ 0 },
+ 248, 178,
+ { 1, 299 }
+ },
+ {
+ WM_BUTTON16,
+ 0,{ 0 },
+ 248, 218,
+ { 1, 230 }
+ },
+ {
+ WM_BUTTON2,
+ 0,{ 0 },
+ 248, 258,
+ { 1, 216 }
+ },
+ {
+ WM_BUTTON30,
+ 0,{ 0 },
+ 248, 298,
+ { 1, 302 }
+ },
+ {
+ WM_BUTTON29,
+ 0,{ 0 },
+ 248, 338,
+ { 1, 301 }
+ },
+ {
+ WM_BUTTON32,
+ 0,{ 0 },
+ 348, 58,
+ { 1, 304 }
+ },
+ {
+ WM_BUTTON5,
+ 0,{ 0 },
+ 348, 98,
+ { 1, 219 }
+ },
+ {
+ WM_BUTTON9,
+ 0,{ 0 },
+ 348, 138,
+ { 1, 223 }
+ },
+ {
+ WM_BUTTON31,
+ 0,{ 0 },
+ 348, 178,
+ { 1, 303 }
+ },
+ {
+ WM_BUTTON26,
+ 0,{ 0 },
+ 348, 218,
+ { 1, 298 }
+ },
+ {
+ WM_BUTTON24,
+ 0,{ 0 },
+ 348, 258,
+ { 1, 238 }
+ },
+ {
+ WM_BUTTON4,
+ 0,{ 0 },
+ 348, 298,
+ { 1, 218 }
+ },
+ {
+ WM_BUTTON25,
+ 0,{ 0 },
+ 348, 338,
+ { 1, 297 }
+ },
+ {
+ WM_DIMS1,
+ 0,{ 1, 15 },
+ 521, 135,
+ { 1, 121 }
+ },
+ {
+ WM_DIMS2,
+ 0,{ 1, 13 },
+ 521, 175,
+ { 1, 122 }
+ },
+ {
+ WM_DIMS3,
+ 0,{ 1, 14 },
+ 521, 215,
+ { 1, 123 }
+ },
+ {
+ WM_DIMS4,
+ 0,{ 1, 61 },
+ 521, 255,
+ { 1, 126 }
+ },
+ {
+ WM_PHASE_INFO,
+ 0,{ 1, 18 },
+ 540, 411,
+ { 1, 174 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_NAMEDESIGN,
+ "name.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_PHASE_DONAMEDESIGN,
+ 0,{ 1, 18 },
+ 222, 326,
+ { 1, 174 }
+ },
+ {
+ WM_PHASE_INFO,
+ 0,{ 1, 36 },
+ 378, 326,
+ { 1, 175 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_WRITEDESIGN,
+ "write.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_BUTTON10,
+ 0,{ 1, 72 },
+ 420, 112,
+ { 1, 193 }
+ },
+ {
+ WM_BUTTON11,
+ 0,{ 1, 73 },
+ 420, 252,
+ { 1, 192 }
+ },
+ {
+ WM_PHASE_DOWRITEDESIGN,
+ 0,{ 1, 18 },
+ 222, 387,
+ { 1, 174 }
+ },
+ {
+ WM_PHASE_INFO,
+ 0,{ 1, 36 },
+ 380, 387,
+ { 1, 175 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_READDESIGN,
+ "read.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_BUTTON1,
+ 0,{ 1, 51 },
+ 190, 110,
+ { 0 }
+ },
+ {
+ WM_BUTTON2,
+ 0,{ 1, 51 },
+ 190, 150,
+ { 0 }
+ },
+ {
+ WM_BUTTON3,
+ 0,{ 1, 51 },
+ 190, 190,
+ { 0 }
+ },
+ {
+ WM_BUTTON4,
+ 0,{ 1, 51 },
+ 190, 230,
+ { 0 }
+ },
+ {
+ WM_BUTTON5,
+ 0,{ 1, 51 },
+ 190, 270,
+ { 0 }
+ },
+ {
+ WM_BUTTON6,
+ 0,{ 1, 51 },
+ 190, 310,
+ { 0 }
+ },
+ {
+ WM_BUTTON10,
+ 0,{ 1, 72 },
+ 420, 110,
+ { 1, 193 }
+ },
+ {
+ WM_BUTTON11,
+ 0,{ 1, 73 },
+ 420, 310,
+ { 1, 192 }
+ },
+ {
+ WM_PHASE_DOREADDESIGN,
+ 0,{ 1, 18 },
+ 222, 387,
+ { 1, 174 }
+ },
+ {
+ WM_PHASE_INFO,
+ 0,{ 1, 36 },
+ 380, 387,
+ { 1, 175 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_CLEARDESIGN,
+ "clear.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_PHASE_DOCLEARDESIGN,
+ 0,{ 1, 18 },
+ 222, 326,
+ { 1, 176 }
+ },
+ {
+ WM_PHASE_INFO,
+ 0,{ 1, 36 },
+ 378, 326,
+ { 1, 177 }
+ },
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_PLAYMOVIE,
+ "movie.blp",
+ FALSE,
+ FALSE,
+ {
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_PLAYMOVIE,
+ "movie.blp",
+ FALSE,
+ FALSE,
+ {
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_WINMOVIEDESIGN,
+ "movie.blp",
+ FALSE,
+ FALSE,
+ {
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_WINMOVIEMULTI,
+ "movie.blp",
+ FALSE,
+ FALSE,
+ {
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_BYE,
+ "bye.blp",
+ FALSE,
+ FALSE,
+ {
+ { 0 }
+ },
+ },
+ {
+ WM_PHASE_INSERT,
+ "insert.blp",
+ FALSE,
+ FALSE,
+ {
+ {
+ WM_PHASE_GAMER,
+ 0,{ 1, 40 },
+ 16, 424,
+ { 1, 106 }
+ },
+ { 0 }
+ },
+ },
+ { 0 }
+};
+
+
+// Constructor
+
+CEvent::CEvent()
+{
+ m_somethingJoystick = 0;
+ m_bFullScreen = TRUE;
+ m_mouseType = MOUSETYPEGRA;
+ m_index = -1;
+ m_rankCheat = -1;
+ m_nbVies = 3;
+ m_mission = 1;
+ m_private = 1;
+ m_multi = 1;
+ m_phase = 0;
+ m_bPrivate = FALSE;
+ m_bMulti = FALSE;
+ m_bBuildOfficialMissions = FALSE;
+ m_bRunMovie = FALSE;
+ m_bMouseDown = FALSE;
+ m_bHili = FALSE;
+ m_oldMousePos.x = 0;
+ m_oldMousePos.y = 0;
+ m_mouseSprite = 0;
+ m_bWaitMouse = FALSE;
+ m_bHideMouse = FALSE;
+ m_bShowMouse = FALSE;
+ m_bDisableMouse = FALSE;
+ m_bMouseRelease = FALSE;
+ m_posCheat = 0;
+ m_speed = 1;
+ m_bMovie = TRUE;
+ m_bAllMissions = FALSE;
+ m_bHiliInfoButton = TRUE;
+ m_movieToStart[0] = '\0';
+ m_bDemoRec = FALSE;
+ m_bDemoPlay = FALSE;
+ m_pDemoBuffer = NULL;
+ m_demoTime = 0;
+ m_keyPress = 0;
+
+ ZeroMemory(m_menuDecor, sizeof(m_menuDecor));
+ m_menuDecor[10] = 1;
+}
+
+// Destructor
+
+CEvent::~CEvent()
+{
+ WriteInfo(m_gamer);
+}
+
+void CEvent::Create(HINSTANCE hInstance, HWND hWnd, CPixmap *pPixmap, CDecor *pDecor,
+ CSound *pSound, CNetwork *pNetwork, CMovie *pMovie )
+{
+ m_hInstance = hInstance;
+ m_hWnd = hWnd;
+ m_pPixmap = pPixmap;
+ m_pDecor = pDecor;
+ m_pSound = pSound;
+ m_pMovie = pMovie;
+ m_pNetwork = pNetwork;
+ m_gamer = 1;
+
+ ReadInfo(1);
+ return;
+}
+
+int CEvent::GetButtonIndex(int button)
+{
+ int i=0;
+
+ while ( table[m_index].buttons[i].message != 0 )
+ {
+ if ( (UINT)button == table[m_index].buttons[i].message )
+ {
+ return i;
+ }
+ i ++;
+ }
+
+ return -1;
+}
+
+int CEvent::GetState(int button)
+{
+ int index;
+
+ index = GetButtonIndex(button);
+ if ( index < 0 ) return 0;
+
+ return m_buttons[index].GetState();
+}
+
+// Returns the mouse position
+
+POINT CEvent::GetMousePos()
+{
+ POINT pos;
+
+ GetCursorPos(&pos);
+ ScreenToClient(m_hWnd, &pos);
+
+ return pos;
+}
+
+void CEvent::SetFullScreen(BOOL bFullScreen)
+{
+ m_bFullScreen = bFullScreen;
+}
+
+// Initializes the mouse type.
+
+void CEvent::SetMouseType(int mouseType)
+{
+ m_mouseType = mouseType;
+}
+
+// Creates the event handler.
+
+
+
+// Returns the index of the button.
+
+
+
+void CEvent::SetState(int button, int state)
+{
+ int index;
+
+ index = GetButtonIndex(button);
+ if ( index < 0 ) return;
+
+ m_buttons[index].SetState(state);
+}
+
+BOOL CEvent::GetEnable(int button)
+{
+ int index;
+
+ index = GetButtonIndex(button);
+ if ( index < 0 ) return 0;
+
+ return FALSE;
+}
+
+void CEvent::SetEnable(int button, int bEnable)
+{
+ int index;
+
+ index = GetButtonIndex(button);
+ if ( index < 0 ) return;
+
+ m_buttons[index].SetEnable(bEnable);
+}
+
+/*
+BOOL CEvent::GetHide(int button)
+{
+ int index;
+
+ index = GetButtonIndex(button);
+ if (index < 0) return 0;
+
+ return m_buttons[index].GetHide();
+}
+*/
+
+void CEvent::SetHide(int button, BOOL bHide)
+{
+ int index;
+
+ index = GetButtonIndex(button);
+ if (index < 0) return;
+
+ m_buttons[index].SetHide(bHide);
+}
+
+int CEvent::GetMenu(int button)
+{
+ int index;
+
+ index = GetButtonIndex(button);
+ if ( index < 0 ) return 0;
+
+ return m_buttons[index].GetMenu();
+}
+
+void CEvent::SetMenu(int button, int menu)
+{
+ int index;
+
+ index = GetButtonIndex(button);
+ if ( index < 0 ) return;
+
+ m_buttons[index].SetMenu(menu);
+}
+
+// Restore the game after activation in fullScreen mode.
+
+void CEvent::RestoreGame()
+{
+ if (m_phase == WM_PHASE_PLAY || m_phase == WM_PHASE_PLAYTEST)
+ {
+ HideMouse(TRUE);
+ }
+ else
+ {
+ WaitMouse(FALSE);
+ DisableMouse(TRUE);
+ DisableMouse(FALSE); // force le changement de sprite !
+ }
+}
+
+void CEvent::FlushInput()
+{
+ m_keyPress = 0;
+
+ m_pDecor->SetInput(0);
+ return;
+
+}
+
+BOOL CEvent::CreateButtons()
+{
+ int message;
+ int* iconMenu;
+ POINT pos;
+ BOOL bMinimizeRedraw = FALSE;
+
+
+ for (int i = 0; table[m_index].buttons[i].message != 0; i++)
+ {
+ pos.x = table[m_index].buttons[i].x;
+ pos.y = table[m_index].buttons[i].y;
+ message = table[m_index].buttons[i].message;
+
+ m_buttons[i].Create(m_hWnd, m_pPixmap, m_pSound, pos,
+ table[m_index].buttons[i].type,
+ bMinimizeRedraw, message);
+
+ iconMenu = table[m_index].buttons[i].iconMenu;
+ if (!m_bBuildOfficialMissions && m_phase == WM_PHASE_BUILD && message == WM_DECOR11)
+ {
+ iconMenu++;
+ }
+
+ m_buttons[i].SetIconMenu(&table[m_index].buttons[i].iconMenu[1], iconMenu[0]);
+ m_buttons[i].SetToolTips(&table[m_index].buttons[i].toolTips[1], table[m_index].buttons[i].toolTips[0]);
+ }
+ return TRUE;
+}
+
+BOOL CEvent::LoadImageFromDisc()
+{
+ char res[100];
+
+ strcpy(res, table[m_index].backName);
+ if (res[0] && table[m_index].bCDrom)
+ AddCDPath(res);
+ return m_pPixmap->CacheAll(FALSE, m_hWnd, TRUE, TRUE, TRUE, 1, res, m_pDecor->GetRegion());
+}
+
+void CEvent::ReadInput()
+{
+ BOOL something;
+ MMRESULT joyPos;
+ int i;
+ UINT keyInput;
+ JOYINFOEX* joyInfo;
+ BOOL bSkateboard;
+ BOOL bHelicopter;
+ BOOL bCar;
+ BOOL bWater;
+ JOYINFOEX joy;
+ UINT bJoyID;
+
+
+ if (m_bMulti != FALSE)
+ {
+ //m_pDecor->TreatNetData();
+ }
+
+ if ((m_somethingJoystick == NULL) || (m_bDemoPlay != FALSE))
+ {
+ m_pDecor->SetJoystickEnable(FALSE);
+ }
+ else
+ {
+ m_pDecor->GetBlupiInfo(&bHelicopter, &bCar, &bSkateboard, &bWater);
+ something = TRUE;
+
+ if (((bHelicopter != FALSE) || (bCar != FALSE)) || (bSkateboard != FALSE))
+ {
+ something = FALSE;
+ }
+ bJoyID = m_joyID;
+ joyInfo = &joy;
+
+ for (i = 0; i != 13; i++)
+ {
+ joyInfo->dwSize = 0;
+ joyInfo = (JOYINFOEX*)&joyInfo->dwFlags;
+ }
+ joy.dwSize = 52;
+ joy.dwFlags = 255;
+
+ joyPos = joyGetPosEx(bJoyID, &joy);
+
+ if (joyPos == 0)
+ {
+ m_keyPress = 0;
+
+ if ((int)joy.dwXpos < 16384)
+ {
+ m_keyPress = KEY_LEFT;
+ }
+ if ((m_keyPress == KEY_NONE) && ((int)joy.dwYpos < 16384))
+ {
+ m_keyPress = KEY_UP;
+ }
+ if (((m_keyPress == KEY_NONE) || (something)) && (49152 < (int)joy.dwYpos))
+ {
+ m_keyPress = m_keyPress | KEY_DOWN;
+ }
+ if (((BYTE)joy.dwButtons & JOY_BUTTON1) != 0)
+ {
+ m_keyPress = m_keyPress & ~(KEY_DOWN | KEY_UP) | KEY_JUMP;
+ }
+ if (((BYTE)joy.dwButtons & JOY_BUTTON2) != 0)
+ {
+ if (bSkateboard == FALSE)
+ {
+ keyInput = m_keyPress & ~KEY_DOWN | KEY_UP | KEY_JUMP;
+ }
+ else
+ {
+ keyInput = m_keyPress & ~(KEY_DOWN | KEY_UP) | KEY_JUMP;
+ }
+ m_keyPress = keyInput;
+ }
+ if (((BYTE)joy.dwButtons & JOY_BUTTON3) != 0)
+ {
+ if (bHelicopter == FALSE)
+ {
+ if (bSkateboard == FALSE)
+ {
+ keyInput = m_keyPress | KEY_DOWN | KEY_JUMP;
+ }
+ else
+ {
+ keyInput = m_keyPress & ~(KEY_DOWN | KEY_UP) | KEY_JUMP;
+ }
+ }
+ else
+ {
+ keyInput = m_keyPress | KEY_DOWN;
+ }
+ m_keyPress = keyInput;
+ m_keyPress = keyInput & ~KEY_UP;
+ }
+ if (((BYTE)joy.dwButtons & JOY_BUTTON4) != 0)
+ {
+ m_keyPress = m_keyPress & ~(KEY_DOWN | KEY_UP) | KEY_FIRE;
+ }
+ m_pDecor->SetInput(m_keyPress);
+ m_pDecor->SetJoystickEnable(TRUE);
+ return;
+ }
+ }
+ return;
+}
+
+
+// CNetwork function needs to be implemented
+
+void CEvent::NetSetPause(BOOL bPause, BOOL bMulti)
+{
+ BOOL bPause_;
+
+ bPause_ = bPause;
+ m_pDecor->SetPause(bPause);
+ if ((m_phase == WM_PHASE_PLAY) || (m_phase == WM_PHASE_PLAYTEST))
+ {
+ if (bPause_ == FALSE)
+ {
+ m_pSound->RestartMusic();
+ }
+ else
+ {
+ m_pSound->SuspendMusic();
+ }
+ }
+ if ((m_bMulti != FALSE) && (bMulti != 0))
+ {
+ m_pNetwork->Send(&bPause, 3, DPSEND_GUARANTEED);
+ }
+ return;
+}
+
+void CEvent::NetSendLobby()
+{
+ NetPlayer* player;
+ UCHAR (packet)[132];
+ CNetwork* pNetwork;
+
+ *(UCHAR*)packet = m_multi;
+ pNetwork = m_pNetwork;
+ packet[0] = 132;
+ packet[1] = MESS_LOBBY;
+ player = pNetwork->m_players;
+ memcpy(packet, pNetwork, 128);
+ pNetwork->Send(packet, 132, DPSEND_GUARANTEED);
+ return;
+}
+
+int CEvent::NetSearchPlayer(DPID dpid)
+{
+ int i;
+ BYTE* pDpid;
+
+ i = 0;
+ for (pDpid = (BYTE*)m_pNetwork->m_players[0].dpid; !pDpid[-4] == 0 || (dpid != *pDpid); pDpid += 32)
+ {
+ if (i++ >= 4)
+ {
+ return -1;
+ }
+ }
+ return i;
+}
+
+void CEvent::NetStartPlay()
+{
+ BOOL host;
+ int i;
+ int* player;
+ char message[2];
+ char str[52];
+ CNetwork* pNetwork;
+
+ OutputNetDebug("CEvent::NetStartPlay");
+ host = m_pNetwork->IsHost();
+
+ if (host != FALSE)
+ {
+ message[0] = '\x02';
+ message[1] = '\a';
+ m_pNetwork->Send(message, 2, DPSEND_GUARANTEED);
+ OutputNetDebug("Sending_MESS_START");
+ }
+ m_pDecor->SetTeam(0);
+ pNetwork = m_pNetwork;
+
+ i = 0;
+ player = (int*) & pNetwork->m_players[0].dpid;
+
+ while ((((NetPlayer*)(player + -1))->bIsPresent == FALSE || (pNetwork->m_dpid != (DPID)player)))
+ {
+ i++;
+ player = player + 8;
+ if (3 < i)
+ {
+ m_bMulti = TRUE;
+ m_bPrivate = FALSE;
+ m_pDecor->SetMulti(TRUE);
+ return;
+ }
+ }
+ m_pDecor->SetTeam((int)pNetwork->m_players[i].team);
+ sprintf(str, "color=%d", (int)m_pNetwork->m_players[i].team);
+ OutputNetDebug(str);
+}
+
+void CEvent::NetSend(int message, USHORT data)
+{
+ UCHAR packet[4];
+
+ packet[2] = '\0';
+ packet[3] = '\0';
+ packet[1] = message;
+ packet[0] = 4;
+ *(USHORT*)packet = data;
+ m_pNetwork->Send(packet, 4, DPSEND_GUARANTEED);
+ return;
+}
+
+void CEvent::NetDraw()
+{
+ int player;
+
+ player = NetSearchPlayer(m_pNetwork->m_dpid);
+ m_pDecor->DrawMap(TRUE, player);
+ return;
+}
+
+void CEvent::ChatSend()
+{
+ int v3; // edx
+ char v5[4]; // [esp+Ch] [ebp-6Ch] BYREF
+ int dpid; // [esp+10h] [ebp-68h]
+ char str[100]; // [esp+14h] [ebp-64h] BYREF
+
+ if (m_textInput[0])
+ {
+ v3 = NetSearchPlayer(m_pNetwork->m_dpid);
+ strcpy(str, "<");
+ if (v3 != -1)
+ {
+ strcat(str, m_pNetwork->m_players[v3].name);
+ }
+ strcat(str, "> ");
+ strcat(str, m_textInput);
+ ChatPush(str);
+ v5[0] = 108;
+ v5[1] = 11;
+ dpid = m_pNetwork->m_dpid;
+ m_pNetwork->Send(v5, 108, 1);
+ m_textInput[0] = '\0';
+ m_textHiliStart = 0;
+ m_textHiliEnd = strlen(m_textInput);
+ m_textCursorIndex = 0;
+ SetEnable(WM_BUTTON20, 0);
+ }
+}
+
+void CEvent::ChatPush(char *str)
+{
+ int i; // eax
+ char *pText; // edx
+
+ for (i = 0; m_chatZone[0] != '\0'; i++)
+ {
+ if (i >= MAXCHAT)
+ {
+ CEvent::ChatPop();
+ pText = m_text;
+ goto LABEL_5;
+ }
+ }
+ pText = this->m_chatZone[i];
+LABEL_5:
+ strcpy(pText, str);
+ m_pSound->PlayImage(SOUND_TRESOR, POINT( LXIMAGE / 2, LYIMAGE / 2 ), -1);
+}
+
+void CEvent::ChatFlush()
+{
+ for (int i = 0; i < MAXCHAT; i++)
+ {
+ m_chatZone[i][0] = '\0';
+ }
+}
+
+void CEvent::ChatPop()
+{
+ char (*chatZone)[5];
+ int num;
+ int result;
+ char* text;
+
+ num = 5;
+ chatZone = m_chatZone;
+ do
+ {
+ memcpy(m_chatZone[num - 1], m_chatZone[num], strlen(m_chatZone[num]));
+ --num;
+ } while (num);
+ m_text[0] = 0;
+ return;
+}
+
+void CEvent::OutputNetDebug(const char* str)
+{
+ FILE* streamf;
+
+ streamf = (FILE*)m_pDecor->GetNetDebug();
+
+ if (m_pDecor->GetNetDebug() != FALSE)
+ {
+ if (fopen("debug.txt", "ab") != (FILE*)0)
+ {
+ fwrite(str, 1, strlen(str), streamf);
+ streamf = (FILE*)fclose(streamf);
+ }
+ }
+ return;
+}
+
+void AddCheatCode(char *pDst, char *pSrc)
+{
+ int i, j;
+
+ if ( pDst[0] != 0 ) strcat(pDst, " / ");
+
+ i = 0;
+ j = strlen(pDst);
+ while ( pSrc[i] != 0 )
+ {
+ pDst[j++] = tolower(pSrc[i++]);
+ }
+ pDst[j] = 0;
+}
+
+
+void CEvent::DrawTextCenter(int res, int x, int y, int font)
+{
+ char text[100];
+ POINT pos;
+
+ LoadString(res, text, 100);
+ pos.x = x;
+ pos.y = y;
+ ::DrawTextCenter(m_pPixmap, pos, text, font);
+}
+
+BOOL CEvent::DrawButtons()
+{
+ int i;
+ int lg, sound;
+ BOOL soundEnabled;
+ char res[100];
+ char res2[100];
+ POINT pos;
+ RECT rect;
+
+ if (m_phase != WM_PHASE_INSERT && m_phase != WM_PHASE_BYE && m_phase != WM_PHASE_INTRO1 && m_phase != WM_PHASE_INTRO2)
+ {
+ m_bChangeCheat = FALSE;
+
+ res2[0] = 0;
+ if (m_bBuildOfficialMissions)
+ {
+ AddCheatCode(res2, cheat_code[0]);
+ }
+ if (m_bAllMissions)
+ {
+ AddCheatCode(res2, cheat_code[1]);
+ }
+ if (m_pDecor->GetSuperBlupi())
+ {
+ AddCheatCode(res2, cheat_code[3]);
+ }
+ if (m_pDecor->GetDrawSecret())
+ {
+ AddCheatCode(res2, cheat_code[11]);
+ }
+ if (m_pDecor->GetNetPacked())
+ {
+ AddCheatCode(res2, cheat_code[19]);
+ }
+ if (!m_pDecor->GetNetMovePredict())
+ {
+ AddCheatCode(res2, cheat_code[21]);
+ }
+ m_pDecor->OutputNetDebug(res2);
+
+ if (m_phase != WM_PHASE_PLAY && m_phase != WM_PHASE_PLAYTEST && m_phase != WM_PHASE_BUILD)
+ {
+ m_pPixmap->DrawPart(-1, CHBACK, POINT(2, 2), RECT(2, 2, 302, 14), 1, FALSE);
+ }
+ DrawTextLeft(m_pPixmap, POINT(2, 2), res2, FONTLITTLE);
+ }
+
+ if (m_phase == WM_PHASE_INIT)
+ {
+ DrawText(m_pPixmap, POINT( 414, 446 ), "Version 2.2", FONTLITTLE);
+ }
+
+ if (m_phase == WM_PHASE_GAMER)
+ {
+ LoadString(TX_CHOOSEGAMER, res, 100);
+ DrawTextLeft(m_pPixmap, POINT( LXIMAGE / 2 - GetTextWidth(res) / 2, 26 ), res, FONTGOLD);
+ for (i = 0; i < MAXGAMER; i++)
+ {
+ DrawText(m_pPixmap, POINT( 110, 69 + i * DIMBUTTONY ), m_gamerNameList[i], FONTWHITE);
+ }
+ SetEnable(WM_PHASE_CLEARGAMER, m_gamerExist[m_gamer]);
+ }
+
+ if (m_phase == WM_PHASE_CREATE)
+ {
+ LoadString(TX_MULTI_CREATE, res, 50);
+ lg = GetTextWidth(res);
+ pos.x = (320 - lg) / 2;
+ pos.y = 103;
+ DrawTextLeft(m_pPixmap, pos, res, FONTSELECTED);
+ LoadString(TX_MULTI_GNAME, res, 100);
+ pos.x = (320 - lg) / 2;
+ pos.y = 190;
+ DrawTextLeft(m_pPixmap, pos, res, FONTSELECTED);
+ }
+
+ if (m_phase == WM_PHASE_NAMEGAMER)
+ {
+ LoadString(TX_CHOOSEGAMER, res, 100);
+ lg = GetTextWidth(res, 0);
+ pos.x = LXIMAGE / 2 - lg / 2;
+ pos.y = 102;
+ DrawTextLeft(m_pPixmap, pos, res, 1);
+ LoadString(TX_WRITENAME, res, 100);
+ lg = GetTextWidth(res, 100);
+ pos.x = LXIMAGE / 2 - lg / 2;
+ pos.y = 190;
+ DrawTextLeft(m_pPixmap, pos, res, 0);
+
+ PutTextInputBox(POINT( 320, 232 ));
+ }
+
+ if (m_phase == WM_PHASE_NAMEDESIGN)
+ {
+ LoadString(TX_DESIGNMISSION, res, 100);
+ lg = GetTextWidth(res, 0);
+ pos.x = 320 - lg / 2;
+ pos.y = 103;
+ DrawTextLeft(m_pPixmap, pos, res, 1);
+ LoadString(TX_NAMEOFMISSION, res, 100);
+ lg = GetTextWidth(res, 0);
+ pos.x = 320 - lg / 2;
+ pos.y = 190;
+ DrawTextLeft(m_pPixmap, pos, res, 0);
+
+ PutTextInputBox(POINT( 320, 232 ));
+ }
+
+ if (m_phase == WM_PHASE_CLEARGAMER)
+ {
+ LoadString(TX_CHOOSEGAMER, res, 100);
+ lg = GetTextWidth((char*)res, 0);
+ pos.y = 102;
+ pos.x = 320 - lg / 2;
+ DrawTextLeft(m_pPixmap, pos, (char*)res, 1);
+ LoadString(TX_DISCARDGAME, res, 100);
+ lg = GetTextWidth(res, 0);
+ pos.x = 320 - lg / 2;
+ pos.y = 210;
+ DrawTextLeft(m_pPixmap, pos, res, 0);
+ strcpy(res2, m_gamerName);
+ strcat(res2, "?");
+ lg = GetTextWidth(res2, 0);
+ pos.x = 320 - lg / 2;
+ pos.y = 230;
+ DrawTextLeft(m_pPixmap, pos, res2, 0);
+ }
+
+ if (m_phase == WM_PHASE_CLEARDESIGN)
+ {
+ LoadString(TX_DESIGNMISSION, res, 100);
+ lg = GetTextWidth(res, 0);
+ pos.y = 104;
+ pos.x = 320 - lg / 2;
+ DrawTextLeft(m_pPixmap, pos, res, 1);
+ LoadString(TX_DELETEMISSION, res, 100);
+ sprintf(res2, res, GetWorld());
+ lg = GetTextWidth(res2, 0);
+ pos.y = 210;
+ pos.x = 320 - lg / 2;
+ DrawTextLeft(m_pPixmap, pos, res2, 0);
+ strcpy(res2, m_pDecor->GetMissionTitle());
+
+ if (res2[0] == '\0')
+ {
+ LoadString(TX_NONAME, res, 100);
+ }
+ strcat(res2, "?");
+ lg = GetTextWidth(res2, 0);
+ pos.y = 230;
+ pos.x = 320 - lg / 2;
+ DrawTextLeft(m_pPixmap, pos, res, 0);
+ }
+
+ if (m_phase == WM_PHASE_SETUP || m_phase == WM_PHASE_SETUPp)
+ {
+ sound = m_pSound->GetAudioVolume();
+ soundEnabled = TRUE;
+ if ((sound == 0) || (m_pSound->GetEnable()) == FALSE)
+ {
+ soundEnabled = FALSE;
+ }
+ }
+
+ for (i = 0; table[m_index].buttons[i].message != 0; i++)
+ {
+ m_buttons[i].Draw();
+ }
+
+ if (m_phase == WM_PHASE_PLAY || m_phase == WM_PHASE_PLAYTEST)
+ {
+ if (m_pDecor->GetPause())
+ {
+ if (m_pDecor->GetTime() % 20 < 15)
+ {
+ DrawTextCenter(TX_PAUSE, LXIMAGE / 2, LYIMAGE / 2, 0);
+ }
+ }
+ else
+ {
+ if (m_bDemoRec)
+ {
+ LoadString(TX_DEMOREC, res, 100);
+ DrawTextLeft(m_pPixmap, POINT(10, 10), res, FONTGOLD);
+ }
+ if (m_bDemoPlay)
+ {
+ LoadString(TX_DEMOPLAY, res, 100);
+ DrawTextLeft(m_pPixmap, POINT(10, 10), res, FONTGOLD);
+ }
+ }
+
+ if (m_speed > 1)
+ {
+ sprintf(res, "x%d", m_speed);
+ DrawTextLeft(m_pPixmap, POINT(64, LYIMAGE - DIMTEXTY + 1), res, FONTWHITE);
+ }
+ }
+ if (m_phase == WM_PHASE_STOP)
+ {
+ LoadString(TX_GAMEPAUSE, res, 100);
+ lg = GetTextWidth(res);
+ pos.x = (319 - lg) / 2;
+ pos.y = 103;
+ DrawTextLeft(m_pPixmap, pos, res, FONTGOLD);
+ }
+ if (m_phase == WM_PHASE_HELP)
+ {
+ LoadString(TX_HELP, res, 100);
+ lg = GetTextWidth(res, 0);
+ pos.x = LXIMAGE / 2 - lg / 2;
+ pos.y = 65;
+ DrawTextLeft(m_pPixmap, pos, res, 1);
+ lg = 140;
+ UINT j;
+ for (j = 601; j < 625; j += 3)
+ {
+ if (m_somethingJoystick == NULL)
+ {
+ pos.y = j - 1;
+ }
+ else
+ {
+ pos.y = j;
+ }
+ LoadString(pos.y, res, 100);
+ pos.x = 110;
+ pos.y = lg;
+ DrawTextLeft(m_pPixmap, pos, res, 1);
+ LoadString(j + 1, res, 100);
+ pos.x = 230;
+ pos.y = lg;
+ DrawTextLeft(m_pPixmap, pos, res, 0);
+ lg += 20;
+ }
+ }
+ if (m_phase == WM_PHASE_MUSIC)
+ {
+ LoadString(TX_MUSIC, res, 100);
+ lg=GetTextWidth(res);
+ pos.x = (320 - lg) / 2;
+ pos.y = 84;
+ DrawTextLeft(m_pPixmap, pos, res, FONTGOLD);
+ }
+ if (m_phase == WM_PHASE_REGION)
+ {
+ LoadString(TX_REGION, res, 100);
+ lg = GetTextWidth(res);
+ pos.x = (320 - lg) / 2;
+ pos.y = 26;
+ DrawTextLeft(m_pPixmap, pos, res, FONTGOLD);
+ }
+ if (m_phase == WM_PHASE_INFO)
+ {
+ LoadString(TX_DESIGNMISSION, res, 100);
+ lg = GetTextWidth(res, 0);
+ pos.y = 37;
+ pos.x = 320 - lg / 2;
+ DrawTextLeft(m_pPixmap, pos, res, 0);
+ if (m_bDrawMap != FALSE)
+ {
+ pos.x = 148;
+ pos.y = 96;
+ m_pPixmap->DrawIcon(-1, 8, 0, pos, 0, FALSE);
+ }
+ LoadString(TX_MISSNUM, res, 100);
+ if (m_bPrivate)
+ m_private = m_private;
+ else
+ m_private = m_mission;
+ sprintf(res2, res, m_private);
+ lg = GetTextWidth(res2, 0);
+ pos.y = 106;
+ pos.x = 250 - lg / 2;
+ DrawTextLeft(m_pPixmap, pos, res2, 1);
+ strcpy(res2, m_pDecor->GetMissionTitle());
+ if (res2[0] == '\0')
+ {
+ LoadString(TX_NONAME, res, 100);
+ }
+ lg = GetTextWidth(res, 0);
+ pos.y = 269;
+ pos.x = 250 - lg / 2;
+ DrawTextLeft(m_pPixmap, pos, res, 0);
+ }
+ if (m_phase == WM_PHASE_LOST || m_phase == WM_PHASE_LOSTDESIGN || m_phase == WM_PHASE_WINMULTI)
+ {
+ LoadString(TX_LOST1 + GetWorld() % 5, res, 50);
+ DrawTextLeft(m_pPixmap, pos, res, FONTWHITE);
+ }
+ if (m_phase == WM_PHASE_WIN || m_phase == WM_PHASE_WINDESIGN || m_phase == WM_PHASE_LOSTMULTI)
+ {
+ LoadString(TX_WIN1 + GetWorld() % 5, res, 50);
+ DrawTextLeft(m_pPixmap, pos, res, FONTWHITE);
+ }
+ if (m_phase == WM_PHASE_LASTWIN)
+ {
+ int string;
+
+ if (m_bPrivate)
+ string = TX_LASTWIN3;
+ else
+ string = TX_LASTWIN2;
+ LoadString(string, res, 100);
+ pos.x = 60;
+ pos.y = 443;
+ DrawTextLeft(m_pPixmap, pos, res, 0);
+ }
+ if (m_phase == WM_PHASE_SETUP || m_phase == WM_PHASE_SETUPp)
+ {
+ lg = m_pSound->GetAudioVolume();
+ i = 1;
+ if ((lg == 0) || (m_pSound->GetEnable() == FALSE)) i = 0;
+ SetEnable(WM_BUTTON1, i);
+ i = 1;
+ if ((19 < lg) || (m_pSound->GetEnable() == FALSE)) i = 0;
+ SetEnable(WM_BUTTON2, i);
+ lg = m_pSound->GetMidiVolume();
+ i = 1;
+ if ((lg == 0) || (m_pSound->GetEnable() == FALSE)) i = 0;
+ SetEnable(WM_BUTTON3, i);
+ if ((19 < lg) || (m_pSound->GetEnable() == FALSE)) i = 0;
+ SetEnable(WM_BUTTON4, i);
+ if (m_pSound->GetEnable())
+ {
+ SetEnable(WM_BUTTON6, 0);
+ SetEnable(WM_BUTTON14, 0);
+ }
+ SetState(WM_BUTTON5, (m_pPixmap->GetTrueColorBack() == FALSE));
+ SetState(WM_BUTTON6, (m_pPixmap->GetTrueColorBack() != FALSE));
+ SetState(WM_BUTTON13, (m_jauges->GetHide() == FALSE));
+ SetState(WM_BUTTON14, (m_jauges->GetHide() != FALSE));
+ for (int j = 0; j < 6; j++)
+ {
+ SetState(j + WM_BUTTON7, ((int)m_somethingJoystick == j));
+ }
+ }
+ if (m_phase == WM_PHASE_SERVICE)
+ {
+ LoadString(0xEF, res, 100);
+ DrawTextLeft(m_pPixmap, POINT(LXIMAGE / 2 - GetTextWidth(res) / 2, 31), res, FONTGOLD);
+ LoadString(0xF0, res, 100);
+ DrawTextLeft(m_pPixmap, POINT(140, 79), res, FONTWHITE);
+ m_nbChoices = m_pNetwork->GetNbProviders();
+ pos = POINT(190, 122);
+ for (i = 0; i < m_nbChoices && i < 6; i++)
+ {
+ if (m_choicePageOffset + i > m_nbChoices) break;
+ strncpy(res, m_pNetwork->GetProviderName(m_choicePageOffset + i), 100);
+ strcpy(res + 45, "...");
+ DrawTextLeft(m_pPixmap, pos, res, m_choicePageOffset + i == m_choiceIndex ? FONTSELECTED : FONTWHITE);
+ pos.y += 40;
+ }
+ }
+ if (m_phase == WM_PHASE_SESSION)
+ {
+ LoadString(0xF3, res, 100);
+ DrawTextLeft(m_pPixmap, POINT(LXIMAGE / 2 - GetTextWidth(res) / 2, 31), res, FONTGOLD);
+ LoadString(0xF4, res, 100);
+ DrawTextLeft(m_pPixmap, POINT(120, 79), res, FONTWHITE);
+ m_nbChoices = m_pNetwork->GetNbSessions();
+ pos = POINT(170, 122);
+ for (i = 0; i < m_nbChoices && i < 6; i++)
+ {
+ if (m_choicePageOffset + i > m_nbChoices) break;
+ strncpy(res, m_pNetwork->GetSessionName(m_choicePageOffset + i), 100);
+ strcpy(res + 45, "...");
+ DrawTextLeft(m_pPixmap, pos, res, m_choicePageOffset + i == m_choiceIndex ? FONTSELECTED : FONTWHITE);
+ pos.y += 40;
+ }
+ }
+ if (m_phase == WM_PHASE_MULTI)
+ {
+ LoadString(0xFD, res, 100);
+ DrawTextLeft(m_pPixmap, POINT(LXIMAGE / 2 - GetTextWidth(res) / 2, 32), res, FONTGOLD);
+ LoadString(0xFE, res, 100);
+ DrawTextLeft(m_pPixmap, POINT(130, 82), res, FONTWHITE);
+ LoadString(0x11E, res, 100);
+ DrawTextLeft(m_pPixmap, POINT(288, 82), res, FONTWHITE);
+ LoadString(0x100, res, 100);
+ DrawTextLeft(m_pPixmap, POINT(80, 301), res, FONTWHITE);
+ if (m_bDrawMap)
+ {
+ m_pPixmap->DrawIcon(-1, CHMAP, 0, POINT(377, 75));
+ }
+ LoadString(0xFF, res, 100);
+ sprintf(res2, res, m_multi);
+ DrawTextLeft(m_pPixmap, POINT(479 - GetTextWidth(res2), 217), res, FONTWHITE);
+ pos = POINT(130, 110);
+ for (i = 0; i < MAXNETPLAYER; i++)
+ {
+ if (m_pNetwork->m_players[i].bIsPresent)
+ {
+ DrawTextLeft(m_pPixmap, pos, m_pNetwork->m_players[i].name, FONTLITTLE);
+ }
+ pos.y += 42;
+ }
+ pos = POINT(323, 80);
+ for (i = 0; i < MAXCHAT; i++)
+ {
+ if (m_chatZone[i][0] != '\0')
+ {
+ DrawText(m_pPixmap, pos, m_chatZone[i], FONTLITTLE);
+ }
+ pos.y += DIMLITTLEY;
+ }
+ PutTextInputBox(POINT(221, 418));
+ SetEnable(WM_BUTTON20, m_textInput[0] != '\0');
+ }
+ if (m_phase == WM_PHASE_READDESIGN)
+ {
+ LoadString(TX_OPENMISS, res, 100);
+ lg = GetTextWidth(res, 0);
+ pos.x = 320 - lg / 2;
+ pos.y = 31;
+ DrawTextLeft(m_pPixmap, pos, res, 1);
+ LoadString(TX_CONTENT, res, 100);
+ pos.x = 190;
+ pos.y = 79;
+ DrawTextLeft(m_pPixmap, pos, res, 0);
+
+ pos.x = 240;
+ pos.y = 122;
+ for (i = 0; i < m_nbChoices && i < 6; i++)
+ {
+ if (m_choicePageOffset + i >= m_nbChoices) break;
+ strncpy(res, m_filenameBuffer[m_choicePageOffset + i], 100);
+ strcpy(res + 45, "...");
+ DrawText(m_pPixmap, pos, res, m_choiceIndex == m_choicePageOffset + i ? FONTSELECTED : FONTWHITE);
+ pos.y += 40;
+ }
+ }
+ if (m_phase == WM_PHASE_WRITEDESIGN)
+ {
+ LoadString(0xA1, res, 100);
+ DrawTextLeft(m_pPixmap, POINT(LXIMAGE / 2 - GetTextWidth(res) / 2, 32), res, FONTGOLD);
+ LoadString(0xC2, res, 100);
+ DrawTextLeft(m_pPixmap, POINT(190, 79), res, FONTGOLD);
+
+ pos.x = 190;
+ pos.y = 107;
+ for (i = 0; i < m_nbChoices && i < 12; i++)
+ {
+ if (m_choicePageOffset + i >= m_nbChoices) break;
+ strncpy(res, m_filenameBuffer[m_choicePageOffset + i], 100);
+ strcpy(res + 45, "...");
+ DrawText(m_pPixmap, pos, res, FONTWHITE);
+ pos.y += DIMTEXTY;
+ }
+ }
+ if (m_phase == WM_PHASE_GREAD || m_phase == WM_PHASE_GREADp || m_phase == WM_PHASE_GWRITE)
+ {
+ if (m_phase == WM_PHASE_GWRITE)
+ {
+ LoadString(TX_SAVE_CGAME, res, 100);
+ }
+ else
+ {
+ LoadString(TX_LOAD_CGAME, res, 100);
+ }
+ DrawTextLeft(m_pPixmap, POINT(415 - GetTextWidth(res) / 2, 31), res, FONTGOLD);
+ LoadString(0x10F, res, 100);
+ DrawTextLeft(m_pPixmap, POINT(280, 78), res, FONTWHITE);
+ pos.y = 122;
+ for (i = 0; i < m_nbChoices && i < MAXSAVE; i++)
+ {
+ pos.x = 296;
+ sprintf(res, "%d", i + 1);
+ DrawTextLeft(m_pPixmap, pos, res, m_choiceIndex == i ? FONTGOLD : FONTWHITE);
+
+ // manually split the string into two draw calls if it contains a newline
+ char* line2 = strchr(m_filenameBuffer[i], '\n');
+ if (line2)
+ {
+ strcpy(res, m_filenameBuffer[i]);
+ res[line2 - res] = '\0'; // janky. pls verify
+ pos.x = 330;
+ pos.y -= DIMTEXTY / 2;
+ DrawTextLeft(m_pPixmap, pos, res, m_choiceIndex == i ? FONTSELECTED : FONTWHITE);
+ pos.y += DIMTEXTY;
+ DrawTextLeft(m_pPixmap, pos, line2 + 1, m_choiceIndex == i ? FONTSELECTED : FONTWHITE);
+ pos.y += DIMBUTTONY - DIMTEXTY / 2;
+ }
+ else
+ {
+ pos.x = 330;
+ DrawTextLeft(m_pPixmap, pos, res, m_choiceIndex == i ? FONTSELECTED : FONTWHITE);
+ pos.y += DIMBUTTONY;
+ }
+ }
+
+ if (m_choiceIndex >= 0)
+ {
+ if (m_bNamesExist[m_choiceIndex])
+ {
+ m_pPixmap->DrawIcon(-1, CHMAP, 0, POINT(19, 149));
+ }
+ }
+ }
+ if (m_phase == WM_PHASE_BYE)
+ {
+ LoadString(TX_FULL_END1, res, 100);
+ lg = GetTextWidth(res);
+ pos.x = 320 - lg / 2;
+ pos.y = 20;
+ DrawTextLeft(m_pPixmap, pos, res, FONTGOLD);
+ LoadString(TX_FULL_END2, res, 100);
+ lg = GetTextWidth(res);
+ pos.x = 320 - lg / 2;
+ pos.y = 40;
+ DrawTextLeft(m_pPixmap, pos, res, FONTGOLD);
+ LoadString(TX_FULL_END3, res, 100);
+ lg = GetTextWidth(res);
+ pos.x = 320 - lg / 2;
+ pos.y = 430;
+ DrawTextLeft(m_pPixmap, pos, res, FONTGOLD);
+ LoadString(TX_FULL_END4, res, 100);
+ lg = GetTextWidth(res);
+ pos.x = 320 - lg / 2;
+ pos.y = 450;
+ DrawTextLeft(m_pPixmap, pos, res, FONTGOLD);
+ }
+ if (m_phase == WM_PHASE_INSERT)
+ {
+ DrawTextCenter(TX_INSERT, LXIMAGE / 2, 20);
+ }
+
+ if (m_textToolTips[0] != '\0')
+ {
+ DrawTextLeft(m_pPixmap, m_posToolTips, m_textToolTips, FONTWHITE);
+ }
+
+ // now that the decomp is looking convincingly like the retail game,
+ // we should clearly differentiate the two when sharing WIP screenshots/videos to reduce confusion.
+ {
+ DrawTextLeft(m_pPixmap, POINT(LXIMAGE - GetTextWidth("DECOMP -- " __DATE__), 0), "DECOMP -- " __DATE__, FONTGOLD);
+ }
+ ///////
+
+ return TRUE;
+}
+
+void CEvent::PutTextInputBox(POINT pos)
+{
+ char textInput[100];
+ int text;
+ int num;
+ UINT textHili;
+ LONG posD;
+
+ text = GetTextWidth(m_textInput, 0);
+ posD = pos.x - text / 2;
+
+
+ if (0 < m_textHiliStart)
+ {
+ memcpy(textInput, (void*)text, m_textHiliStart);
+ textInput[m_textHiliStart] = 0;
+ pos.x = posD;
+ pos.y = pos.y;
+ DrawTextLeft(m_pPixmap, pos, textInput, 0);
+ text = GetTextWidth(textInput, 0);
+ posD += text;
+ }
+ if (m_textHiliStart < m_textHiliEnd)
+ {
+ textHili = m_textHiliEnd -= m_textHiliStart;
+ memcpy(textInput, m_textInput + m_textHiliStart, text);
+ textInput[textHili] = 0;
+ pos.x = posD;
+ pos.y = pos.y;
+ DrawTextLeft(m_pPixmap, pos, textInput, 2);
+ text += GetTextWidth(textInput, 0);
+ }
+ textHili = m_textCursorIndex >> 31;
+ if ((((m_textCursorIndex ^ textHili) - textHili & 15 ^ textHili) - textHili) < 8)
+ {
+ pos.x = posD;
+ pos.y = pos.y;
+ DrawTextLeft(m_pPixmap, pos, (char*)"|", 0);
+ }
+ num = m_textHiliEnd;
+
+ if (num < (int)strlen(m_textInput))
+ {
+ pos.x = posD;
+ pos.y = pos.y;
+ strcpy(textInput, m_textInput + num);
+ DrawTextLeft(m_pPixmap, pos, textInput, 0);
+ }
+ m_textCursorIndex++;
+ return;
+}
+
+/*
+BOOL CEvent::TextSomething()
+{
+ int textHiliStart;
+ char pText;
+
+ m_textHiliStart = textHiliStart;
+
+ if (m_textHiliEnd < textHiliStart)
+ {
+ return 0;
+ }
+
+ do {
+ m_textInput[textHiliStart] =
+ m_textHiliEnd + textHiliStart;
+ pText = m_textInput + textHiliStart;
+ textHiliStart = textHiliStart + 1;
+ } while (pText != '\0');
+ m_textHiliEnd = m_textHiliStart;
+ return 1;
+}
+*/
+
+POINT CEvent::GetLastMousePos()
+{
+ return m_oldMousePos;
+}
+
+BOOL CEvent::TreatEvent(UINT message, WPARAM wParam, LPARAM lParam)
+{
+ if (m_bDemoPlay)
+ {
+ if (message == WM_KEYDOWN ||
+ message == WM_KEYUP ||
+ message == WM_LBUTTONUP ||
+ message == WM_RBUTTONUP)
+ {
+ DemoPlayStop();
+ return TRUE;
+ }
+ if (message == WM_MOUSEMOVE)
+ {
+ return TRUE;
+ }
+ }
+
+ return TreatEventBase(message, wParam, lParam);
+}
+
+BOOL CEvent::TreatEventBase(UINT message, WPARAM wParam, LPARAM lParam)
+{
+ POINT pos;
+ int fwKeys;
+ int i;
+ char c;
+ BOOL bEnable;
+
+ pos = ConvLongToPos(lParam);
+ fwKeys = wParam;
+
+ switch (message)
+ {
+ case WM_KEYDOWN:
+ if (wParam >= 'A' && wParam <= 'Z')
+ {
+ if (m_posCheat == 0)
+ {
+ m_rankCheat = -1;
+ for (i = 0; i < 25; i++)
+ {
+ if ((char)wParam == cheat_code[i][0])
+ {
+ m_rankCheat = i;
+ break;
+ }
+ }
+ }
+ if (m_rankCheat != -1)
+ {
+ c = cheat_code[m_rankCheat][m_posCheat];
+ if (m_posCheat != 0 && m_rankCheat == 0) c++;
+ if ((char)wParam == c)
+ {
+ m_posCheat++;
+ if (cheat_code[m_rankCheat][m_posCheat] == 0)
+ {
+ bEnable = TRUE;
+ if (m_rankCheat == 0)
+ {
+ m_bBuildModify = FALSE;
+ m_pDecor->SetBuildOfficialMissions(m_bBuildOfficialMissions);
+ }
+ if (m_rankCheat == 1)
+ {
+ m_bAllMissions = !m_bAllMissions;
+ m_pDecor->SetAllMissions(m_bAllMissions);
+ bEnable = m_bAllMissions;
+ }
+ if (m_rankCheat == 2 ||
+ m_rankCheat == 6 ||
+ m_rankCheat == 7 ||
+ m_rankCheat == 8 ||
+ m_rankCheat == 9 ||
+ m_rankCheat == 10 ||
+ m_rankCheat == 12 ||
+ m_rankCheat == 13 ||
+ m_rankCheat == 14 ||
+ m_rankCheat == 15 ||
+ m_rankCheat == 16 ||
+ m_rankCheat == 17 ||
+ m_rankCheat == 18 ||
+ m_rankCheat == 22 ||
+ m_rankCheat == 23 ||
+ m_rankCheat == 24)
+ {
+ if (m_phase == WM_PHASE_PLAY || m_phase == WM_PHASE_PLAYTEST)
+ {
+ m_pDecor->CheatAction(m_rankCheat);
+ bEnable = TRUE;
+ }
+ }
+ if (m_rankCheat == 3)
+ {
+ m_pDecor->SetSuperBlupi(!m_pDecor->GetSuperBlupi());
+ bEnable = m_pDecor->GetSuperBlupi();
+ }
+ if (m_rankCheat == 4)
+ {
+ if (m_phase == WM_PHASE_PLAY || m_phase == WM_PHASE_PLAYTEST)
+ {
+ m_pDecor->SetNbVies(10);
+ }
+ else
+ {
+ if (m_nbVies >= 10)
+ break;
+ m_nbVies++;
+ }
+ bEnable = TRUE;
+ }
+ if (m_rankCheat == 5)
+ {
+ if (m_phase == WM_PHASE_PLAY || m_phase == WM_PHASE_PLAYTEST)
+ {
+ if (m_pDecor->GetNbVies() > 0)
+ {
+ m_pDecor->SetNbVies(m_pDecor->GetNbVies() - 1);
+ bEnable = TRUE;
+ break;
+ }
+ }
+ else
+ {
+ if (m_nbVies > 0)
+ {
+ m_nbVies--;
+ bEnable = TRUE;
+ }
+ }
+ }
+ if (m_rankCheat == 11)
+ {
+ bEnable = !m_pDecor->GetDrawSecret();
+ m_pDecor->SetDrawSecret(bEnable);
+
+ }
+ if (m_rankCheat == 19)
+ {
+ bEnable = !m_pDecor->GetNetPacked();
+ m_pDecor->SetNetPacked(bEnable);
+
+ }
+ if (m_rankCheat == 20)
+ {
+ bEnable = !m_pDecor->GetNetDebug();
+ m_pDecor->SetNetDebug(bEnable);
+ }
+ if (m_rankCheat == 21)
+ {
+ bEnable = !m_pDecor->GetNetMovePredict();
+ m_pDecor->SetNetMovePredict(bEnable);
+ }
+ if (m_phase != WM_PHASE_PLAY && m_phase != WM_PHASE_PLAYTEST)
+ {
+ ChangePhase(m_phase);
+ }
+ pos.x = LXIMAGE / 2;
+ pos.y = LYIMAGE / 2;
+ if (bEnable)
+ m_pSound->PlayImage(SOUND_RESSORT, pos, -1);
+ else
+ m_pSound->PlayImage(SOUND_JUMPEND, pos, -1);
+ m_rankCheat = -1;
+ m_posCheat = 0;
+ }
+ return TRUE;
+ }
+ else
+ {
+ m_rankCheat = -1;
+ m_posCheat = 0;
+ }
+ }
+ }
+
+ switch (wParam)
+ {
+ case VK_END:
+ DemoRecStop();
+ return TRUE;
+ case VK_ESCAPE:
+ if (m_bRunMovie)
+ {
+ StopMovie();
+ m_pSound->SetSuspendSkip(1);
+ return TRUE;
+ }
+ switch (m_phase)
+ {
+ case WM_PHASE_PLAY:
+ if (!m_bPrivate && !m_bMulti)
+ {
+ if (m_mission == 1)
+ {
+ return ChangePhase(WM_PHASE_GAMER);
+ }
+ if (m_mission % 10 == 0 && m_mission != 10)
+ {
+ SetMission(1);
+ m_phase = WM_PHASE_PLAY;
+ return ChangePhase(WM_PHASE_PLAY);
+ }
+ }
+ ChangePhase(WM_PHASE_STOP);
+ return TRUE;
+ case WM_PHASE_GREADp:
+ case WM_PHASE_GWRITE:
+ ChangePhase(WM_PHASE_STOP);
+ return TRUE;
+ case WM_PHASE_SETUP:
+ case WM_PHASE_NAMEGAMER:
+ case WM_PHASE_CLEARGAMER:
+ case WM_PHASE_GREAD:
+ case WM_PHASE_INFO:
+ case WM_PHASE_LOSTMULTI:
+ ChangePhase(WM_PHASE_GAMER);
+ return TRUE;
+ case WM_PHASE_SETUPp:
+ case WM_PHASE_HELP:
+ case WM_PHASE_STOP:
+ ChangePhase(WM_PHASE_PLAY);
+ return TRUE;
+ case WM_PHASE_PLAYTEST:
+ ChangePhase(WM_PHASE_QUITPLAYTEST);
+ return TRUE;
+ case WM_PHASE_LOST:
+ case WM_PHASE_LOSTDESIGN:
+ case WM_PHASE_BUILD:
+ case WM_PHASE_REGION:
+ case WM_PHASE_NAMEDESIGN:
+ case WM_PHASE_MUSIC:
+ case WM_PHASE_READDESIGN:
+ case WM_PHASE_WRITEDESIGN:
+ ChangePhase(WM_PHASE_INFO);
+ return TRUE;
+ case WM_PHASE_GAMER:
+ ChangePhase(WM_PHASE_INIT);
+ return TRUE;
+ case WM_PHASE_SERVICE:
+ ChangePhase(WM_PHASE_DP_CANCELSERVICE);
+ return TRUE;
+ case WM_PHASE_SESSION:
+ ChangePhase(WM_PHASE_DP_CANCELSESSION);
+ return TRUE;
+ case WM_PHASE_CREATE:
+ ChangePhase(WM_PHASE_DP_CANCELCREATE);
+ return TRUE;
+ case WM_PHASE_MULTI:
+ ChangePhase(WM_PHASE_DP_CANCELMULTI);
+ return TRUE;
+ case WM_PHASE_BYE:
+ PostMessage(m_hWnd, WM_CLOSE, 0, 0);
+ return FALSE;
+ default:
+ return TRUE;
+ }
+ break;
+ case VK_RETURN:
+ if (m_bRunMovie)
+ {
+ StopMovie();
+ m_pSound->SetSuspendSkip(1);
+ return TRUE;
+ }
+ switch (m_phase)
+ {
+ case WM_PHASE_PLAYTEST:
+ ChangePhase(WM_PHASE_QUITPLAYTEST);
+ return TRUE;
+ case WM_PHASE_SETUP:
+ case WM_PHASE_INIT:
+ case WM_PHASE_LOSTMULTI:
+ ChangePhase(WM_PHASE_GAMER);
+ return TRUE;
+ case WM_PHASE_NAMEGAMER:
+ strcpy(m_gamerName, m_textInput);
+ ChangePhase(WM_PHASE_GAMER);
+ return TRUE;
+ case WM_PHASE_NAMEDESIGN:
+ m_pDecor->SetMissionTitle(m_textInput);
+ ChangePhase(WM_PHASE_INFO);
+ return TRUE;
+ case WM_PHASE_INFO:
+ case WM_PHASE_STOP:
+ case WM_PHASE_HELP:
+ case WM_PHASE_SETUPp:
+ ChangePhase(WM_PHASE_PLAY);
+ return TRUE;
+ case WM_PHASE_BUILD:
+ case WM_PHASE_LOSTDESIGN:
+ case WM_PHASE_LOST:
+ ChangePhase(WM_PHASE_INFO);
+ return TRUE;
+ case WM_PHASE_SERVICE:
+ ChangePhase(WM_PHASE_DP_DOSERVICE);
+ return TRUE;
+ case WM_PHASE_CREATE:
+ ChangePhase(WM_PHASE_DP_DOCREATE);
+ return TRUE;
+ case WM_PHASE_MULTI:
+ ChatSend();
+ return TRUE;
+ case WM_PHASE_GREAD:
+ case WM_PHASE_GREADp:
+ if (m_choiceIndex >= 0 && CurrentRead(m_choiceIndex))
+ {
+ ChangePhase(WM_PHASE_PLAY);
+
+ }
+ return TRUE;
+ case WM_PHASE_GWRITE:
+ if (m_choiceIndex >= 0 && CurrentWrite(m_choiceIndex))
+ {
+ ChangePhase(WM_PHASE_PLAY);
+
+ }
+ return TRUE;
+ default:
+ return TRUE;
+ }
+ case VK_SHIFT:
+ m_keyPress |= KEY_FIRE;
+ break;
+ case VK_CONTROL:
+ m_keyPress |= KEY_JUMP;
+ break;
+ case VK_PAUSE:
+ NetSetPause(!m_pDecor->GetPause(), TRUE);
+ break;
+ case VK_LEFT:
+ m_keyPress |= KEY_LEFT;
+ break;
+ case VK_UP:
+ m_keyPress |= KEY_UP;
+ break;
+ case VK_RIGHT:
+ m_keyPress |= KEY_RIGHT;
+ break;
+ case VK_DOWN:
+ m_keyPress |= KEY_DOWN;
+ break;
+ case VK_HOME:
+ break;
+ case VK_SPACE:
+ if (m_bRunMovie)
+ {
+ StopMovie();
+ m_pSound->SetSuspendSkip(1);
+ return TRUE;
+ }
+ m_keyPress |= KEY_FIRE;
+ break;
+ case VK_F1:
+ if (this->m_phase == WM_PHASE_PLAY)
+ {
+ ChangePhase(WM_PHASE_HELP);
+ }
+ break;
+ case VK_F2:
+ if (this->m_phase == WM_PHASE_PLAY)
+ {
+ ChangePhase(WM_PHASE_SETUPp);
+ }
+ break;
+ case VK_F3:
+ if (this->m_phase == WM_PHASE_PLAY)
+ {
+ ChangePhase(WM_PHASE_GWRITE);
+ }
+ break;
+ case VK_F4:
+ if (this->m_phase != WM_PHASE_PLAY)
+ {
+ ChangePhase(WM_PHASE_GREADp);
+ }
+ break;
+ }
+
+ if (m_phase != WM_PHASE_PLAY && m_phase != WM_PHASE_PLAYTEST && m_phase != WM_PHASE_BUILD)
+ {
+ return FALSE;
+ }
+
+ m_pDecor->SetInput(m_keyPress);
+ DemoRecEvent();
+ return TRUE;
+
+ // Unknown Function
+ case WM_KEYUP:
+ switch (wParam)
+ {
+ case VK_SHIFT:
+ case VK_SPACE:
+ m_keyPress &= ~KEY_FIRE;
+ break;
+ case VK_CONTROL:
+ m_keyPress &= ~KEY_JUMP;
+ break;
+ case VK_LEFT:
+ m_keyPress &= ~KEY_LEFT;
+ break;
+ case VK_UP:
+ m_keyPress &= ~KEY_UP;
+ break;
+ case VK_RIGHT:
+ m_keyPress &= ~KEY_RIGHT;
+ break;
+ case VK_DOWN:
+ m_keyPress &= ~KEY_DOWN;
+ break;
+ }
+
+ m_pDecor->SetInput(m_keyPress);
+ return TRUE;
+
+ case WM_LBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ m_bMouseDown = TRUE;
+ MouseSprite(pos);
+ if (EventButtons(message, wParam, lParam)) return TRUE;
+ if (m_phase == WM_PHASE_BUILD)
+ {
+ //if (BuildDown(pos, fwKeys)) return TRUE;
+ }
+ if (m_phase == WM_PHASE_PLAY)
+ {
+ // if (PlayDown(pos, fwKeys)) return TRUE;
+ }
+ break;
+ case WM_MOUSEMOVE:
+ if (m_mouseType == MOUSETYPEGRA)
+ {
+ if (m_bShowMouse)
+ {
+ ShowCursor(FALSE); // cache la souris
+ m_pPixmap->MouseShow(TRUE); // montre sprite
+ m_bShowMouse = FALSE;
+ }
+ }
+ if (m_mouseType == MOUSETYPEWINPOS &&
+ (pos.x != m_oldMousePos.x ||
+ pos.y != m_oldMousePos.y))
+ {
+ m_oldMousePos = pos;
+ ClientToScreen(m_hWnd, &m_oldMousePos);
+ SetCursorPos(m_oldMousePos.x, m_oldMousePos.y); // (*)
+ }
+ m_oldMousePos = pos;
+
+ MouseSprite(pos);
+ if (EventButtons(message, wParam, lParam)) return TRUE;
+ if (m_phase == WM_PHASE_BUILD)
+ {
+ //if (BuildMove(pos, fwKeys)) return TRUE;
+ }
+ if (m_phase == WM_PHASE_PLAY)
+ {
+ //if (PlayMove(pos, fwKeys)) return TRUE;
+ }
+ break;
+
+ case WM_NCMOUSEMOVE:
+ if (m_mouseType == MOUSETYPEGRA)
+ {
+ if (!m_bShowMouse)
+ {
+ m_pPixmap->MouseShow(FALSE); // cache sprite
+ m_bShowMouse = TRUE;
+ }
+ }
+ break;
+
+ case WM_LBUTTONUP:
+ case WM_RBUTTONUP:
+ m_bMousePress = FALSE;
+ if (EventButtons(message, wParam, lParam)) return TRUE;
+ if (m_phase == WM_PHASE_BUILD)
+ {
+ if (BuildUp(pos, fwKeys)) return TRUE;
+ }
+ if (m_phase == WM_PHASE_PLAY)
+ {
+ //if (PlayUp(pos, fwKeys)) return TRUE;
+ }
+ if (m_phase == WM_PHASE_BYE)
+ {
+ PostMessage(m_hWnd, WM_CLOSE, 0, 0);
+ }
+ break;
+ case WM_PHASE_INTRO1:
+ case WM_PHASE_INTRO2:
+ case WM_PHASE_INIT:
+ case WM_PHASE_PLAY:
+ case WM_PHASE_BUILD:
+ case WM_PHASE_NAMEGAMER:
+ case WM_PHASE_CLEARGAMER:
+ case WM_PHASE_INFO:
+ case WM_PHASE_PLAYTEST:
+ case WM_PHASE_SETUP:
+ case WM_PHASE_MUSIC:
+ case WM_PHASE_PLAYMOVIE:
+ case WM_PHASE_WINMOVIE:
+ case WM_PHASE_SETUPp:
+ case WM_PHASE_REGION:
+ case WM_PHASE_GAMER:
+ case WM_PHASE_WINMOVIEDESIGN:
+ case WM_PHASE_WINMOVIEMULTI:
+ case WM_PHASE_BYE:
+ case WM_PHASE_NAMEDESIGN:
+ case WM_PHASE_WRITEDESIGN:
+ case WM_PHASE_READDESIGN:
+ case WM_PHASE_CLEARDESIGN:
+ case WM_PHASE_SERVICE:
+ case WM_PHASE_DP_DOSERVICE:
+ case WM_PHASE_DP_CANCELSERVICE:
+ case WM_PHASE_SESSION:
+ case WM_PHASE_DP_JOIN:
+ case WM_PHASE_DP_CREATELOBBY:
+ case WM_PHASE_DP_REFRESH:
+ case WM_PHASE_DP_CANCELSESSION:
+ case WM_PHASE_MULTI:
+ case WM_PHASE_DP_STARTMULTI:
+ case WM_PHASE_DP_CANCELMULTI:
+ case WM_PHASE_CREATE:
+ case WM_PHASE_DP_DOCREATE:
+ case WM_PHASE_DP_CANCELCREATE:
+ case WM_PHASE_STOP:
+ case WM_PHASE_HELP:
+ case WM_PHASE_GWRITE:
+ case WM_PHASE_GREADp:
+ case WM_PHASE_GREAD:
+ case WM_PHASE_QUITPLAY:
+ case WM_PHASE_1588:
+ if (ChangePhase(message)) return TRUE;
+ break;
+ case WM_PHASE_DOPLAY:
+ m_bPrivate = FALSE;
+ m_mission = 1;
+ if (CheckWorld1())
+ {
+ return ChangePhase(WM_PHASE_PLAY);
+ }
+ else
+ {
+ m_tryInsertCount = 40;
+ m_tryPhase = WM_PHASE_PLAY;
+ return ChangePhase(WM_PHASE_INSERT);
+ }
+ break;
+ case WM_PHASE_PRIVATE:
+ m_bPrivate = true;
+ return ChangePhase(WM_PHASE_INFO);
+ break;
+ case WM_PHASE_DEMO:
+ m_demoNumber = 0;
+ DemoPlayStart();
+ return FALSE;
+ break;
+ case WM_PHASE_DONAMEGAMER:
+ case WM_PHASE_DOCLEARGAMER:
+ case WM_PHASE_DONAMEDESIGN:
+ case WM_PHASE_DOWRITEDESIGN:
+ case WM_PHASE_DOREADDESIGN:
+ case WM_PHASE_DOCLEARDESIGN:
+ ChangeButtons(message);
+ return FALSE;
+ case WM_PREV:
+ i = (m_keyPress & KEY_JUMP) ? 10 : 1;
+ if (m_phase == WM_PHASE_MULTI)
+ {
+ m_multi -= i;
+ if (m_multi < 1) m_multi = 1;
+
+ m_bDrawMap = m_pDecor->Read(m_gamer, m_multi + 200, FALSE);
+ if (m_bDrawMap) DrawMap();
+
+ NetSendLobby();
+ NetAdjustLobbyButtons();
+ return TRUE;
+ }
+
+ if (m_bPrivate)
+ {
+ m_private -= i;
+ if (m_private < 1) m_private = 1;
+
+ return ChangePhase(WM_PHASE_INFO);
+ }
+ else
+ {
+ m_mission -= i;
+ if (m_mission < 1) m_mission = 1;
+
+ return ChangePhase(WM_PHASE_INFO);
+ }
+ break;
+ case WM_NEXT:
+ i = (m_keyPress & KEY_JUMP) ? 10 : 1;
+ if (m_phase == WM_PHASE_MULTI)
+ {
+ m_multi += i;
+ if (m_multi > 12) m_multi = 12;
+
+ m_bDrawMap = m_pDecor->Read(m_gamer, m_multi + 200, FALSE);
+ if (m_bDrawMap) DrawMap();
+
+ NetSendLobby();
+ NetAdjustLobbyButtons();
+ return TRUE;
+ }
+
+ if (m_bPrivate || !m_bBuildOfficialMissions)
+ {
+ m_private += i;
+ if (m_private > 20) m_private = 20;
+
+ return ChangePhase(WM_PHASE_INFO);
+ }
+ else
+ {
+ m_mission += i;
+ if (m_mission > 320) m_mission = 320;
+
+ return ChangePhase(WM_PHASE_INFO);
+ }
+ break;
+ case WM_DECOR1:
+ SetState(WM_DECOR1, 1);
+ SetState(WM_DECOR2, 0);
+ SetState(WM_DECOR3, 0);
+ SetState(WM_DECOR4, 0);
+ SetState(WM_DECOR5, 0);
+ SetState(WM_DECOR6, 0);
+ SetState(WM_DECOR7, 0);
+ SetState(WM_DECOR8, 0);
+ SetState(WM_DECOR9, 0);
+ SetState(WM_DECOR10, 0);
+ SetState(WM_DECOR11, 0);
+
+ i = GetMenu(WM_DECOR1);
+ m_pDecor->SetFieldCC38AndStuff(1, i);
+ m_menuIndex = 0;
+ m_menuDecor[0] = i;
+ break;
+
+ case WM_DECOR2:
+ SetState(WM_DECOR1, 0);
+ SetState(WM_DECOR2, 1);
+ SetState(WM_DECOR3, 0);
+ SetState(WM_DECOR4, 0);
+ SetState(WM_DECOR5, 0);
+ SetState(WM_DECOR6, 0);
+ SetState(WM_DECOR7, 0);
+ SetState(WM_DECOR8, 0);
+ SetState(WM_DECOR9, 0);
+ SetState(WM_DECOR10, 0);
+ SetState(WM_DECOR11, 0);
+
+ i = GetMenu(WM_DECOR2);
+ m_pDecor->SetFieldCC38AndStuff(2, i);
+ m_menuIndex = 1;
+ m_menuDecor[1] = i;
+ break;
+
+ case WM_DECOR3:
+ SetState(WM_DECOR1, 0);
+ SetState(WM_DECOR2, 0);
+ SetState(WM_DECOR3, 1);
+ SetState(WM_DECOR4, 0);
+ SetState(WM_DECOR5, 0);
+ SetState(WM_DECOR6, 0);
+ SetState(WM_DECOR7, 0);
+ SetState(WM_DECOR8, 0);
+ SetState(WM_DECOR9, 0);
+ SetState(WM_DECOR10, 0);
+ SetState(WM_DECOR11, 0);
+
+ i = GetMenu(WM_DECOR3);
+ m_pDecor->SetFieldCC38AndStuff(3, i);
+ m_menuIndex = 2;
+ m_menuDecor[2] = i;
+ break;
+
+ case WM_DECOR4:
+ SetState(WM_DECOR1, 0);
+ SetState(WM_DECOR2, 0);
+ SetState(WM_DECOR3, 0);
+ SetState(WM_DECOR4, 1);
+ SetState(WM_DECOR5, 0);
+ SetState(WM_DECOR6, 0);
+ SetState(WM_DECOR7, 0);
+ SetState(WM_DECOR8, 0);
+ SetState(WM_DECOR9, 0);
+ SetState(WM_DECOR10, 0);
+ SetState(WM_DECOR11, 0);
+
+ i = GetMenu(WM_DECOR4);
+ m_pDecor->SetFieldCC38AndStuff(4, i);
+ m_menuIndex = 3;
+ m_menuDecor[3] = i;
+ break;
+
+ case WM_DECOR5:
+ SetState(WM_DECOR1, 0);
+ SetState(WM_DECOR2, 0);
+ SetState(WM_DECOR3, 0);
+ SetState(WM_DECOR4, 0);
+ SetState(WM_DECOR5, 1);
+ SetState(WM_DECOR6, 0);
+ SetState(WM_DECOR7, 0);
+ SetState(WM_DECOR8, 0);
+ SetState(WM_DECOR9, 0);
+ SetState(WM_DECOR10, 0);
+ SetState(WM_DECOR11, 0);
+
+ i = GetMenu(WM_DECOR5);
+ m_pDecor->SetFieldCC38AndStuff(5, i);
+ m_menuIndex = 4;
+ m_menuDecor[4] = i;
+ break;
+
+ case WM_DECOR6:
+ SetState(WM_DECOR1, 0);
+ SetState(WM_DECOR2, 0);
+ SetState(WM_DECOR3, 0);
+ SetState(WM_DECOR4, 0);
+ SetState(WM_DECOR5, 0);
+ SetState(WM_DECOR6, 1);
+ SetState(WM_DECOR7, 0);
+ SetState(WM_DECOR8, 0);
+ SetState(WM_DECOR9, 0);
+ SetState(WM_DECOR10, 0);
+ SetState(WM_DECOR11, 0);
+
+ i = GetMenu(WM_DECOR6);
+ m_pDecor->SetFieldCC38AndStuff(6, i);
+ m_menuIndex = 5;
+ m_menuDecor[5] = i;
+ break;
+
+ case WM_DECOR7:
+ SetState(WM_DECOR1, 0);
+ SetState(WM_DECOR2, 0);
+ SetState(WM_DECOR3, 0);
+ SetState(WM_DECOR4, 0);
+ SetState(WM_DECOR5, 0);
+ SetState(WM_DECOR6, 0);
+ SetState(WM_DECOR7, 1);
+ SetState(WM_DECOR8, 0);
+ SetState(WM_DECOR9, 0);
+ SetState(WM_DECOR10, 0);
+ SetState(WM_DECOR11, 0);
+
+ i = GetMenu(WM_DECOR7);
+ m_pDecor->SetFieldCC38AndStuff(7, i);
+ m_menuIndex = 6;
+ m_menuDecor[6] = i;
+ break;
+
+ case WM_DECOR8:
+ SetState(WM_DECOR1, 0);
+ SetState(WM_DECOR2, 0);
+ SetState(WM_DECOR3, 0);
+ SetState(WM_DECOR4, 0);
+ SetState(WM_DECOR5, 0);
+ SetState(WM_DECOR6, 0);
+ SetState(WM_DECOR7, 0);
+ SetState(WM_DECOR8, 1);
+ SetState(WM_DECOR9, 0);
+ SetState(WM_DECOR10, 0);
+ SetState(WM_DECOR11, 0);
+
+ i = GetMenu(WM_DECOR8);
+ m_pDecor->SetFieldCC38AndStuff(8, i);
+ m_menuIndex = 7;
+ m_menuDecor[7] = i;
+ break;
+
+ case WM_DECOR9:
+ SetState(WM_DECOR1, 0);
+ SetState(WM_DECOR2, 0);
+ SetState(WM_DECOR3, 0);
+ SetState(WM_DECOR4, 0);
+ SetState(WM_DECOR5, 0);
+ SetState(WM_DECOR6, 0);
+ SetState(WM_DECOR7, 0);
+ SetState(WM_DECOR8, 0);
+ SetState(WM_DECOR9, 1);
+ SetState(WM_DECOR10, 0);
+ SetState(WM_DECOR11, 0);
+
+ i = GetMenu(WM_DECOR9);
+ m_pDecor->SetFieldCC38AndStuff(9, i);
+ m_menuIndex = 8;
+ m_menuDecor[8] = i;
+ break;
+
+ case WM_DECOR10:
+ SetState(WM_DECOR1, 0);
+ SetState(WM_DECOR2, 0);
+ SetState(WM_DECOR3, 0);
+ SetState(WM_DECOR4, 0);
+ SetState(WM_DECOR5, 0);
+ SetState(WM_DECOR6, 0);
+ SetState(WM_DECOR7, 0);
+ SetState(WM_DECOR8, 0);
+ SetState(WM_DECOR9, 0);
+ SetState(WM_DECOR10, 1);
+ SetState(WM_DECOR11, 0);
+
+ i = GetMenu(WM_DECOR10);
+ m_pDecor->SetFieldCC38AndStuff(10, i);
+ m_menuIndex = 9;
+ m_menuDecor[9] = i;
+ break;
+
+ case WM_DECOR11:
+ SetState(WM_DECOR1, 0);
+ SetState(WM_DECOR2, 0);
+ SetState(WM_DECOR3, 0);
+ SetState(WM_DECOR4, 0);
+ SetState(WM_DECOR5, 0);
+ SetState(WM_DECOR6, 0);
+ SetState(WM_DECOR7, 0);
+ SetState(WM_DECOR8, 0);
+ SetState(WM_DECOR9, 0);
+ SetState(WM_DECOR10, 0);
+ SetState(WM_DECOR11, 1);
+
+ i = GetMenu(WM_DECOR11);
+ m_pDecor->SetFieldCC38AndStuff(11, i);
+ m_menuIndex = 10;
+ m_menuDecor[10] = i;
+ break;
+
+ case WM_BUTTON0:
+ case WM_BUTTON1:
+ case WM_BUTTON2:
+ case WM_BUTTON3:
+ case WM_BUTTON4:
+ case WM_BUTTON5:
+ case WM_BUTTON6:
+ case WM_BUTTON7:
+ case WM_BUTTON8:
+ case WM_BUTTON9:
+ case WM_BUTTON10:
+ case WM_BUTTON11:
+ case WM_BUTTON12:
+ case WM_BUTTON13:
+ case WM_BUTTON14:
+ case WM_BUTTON15:
+ case WM_BUTTON16:
+ case WM_BUTTON17:
+ case WM_BUTTON18:
+ case WM_BUTTON19:
+ case WM_BUTTON20:
+ case WM_BUTTON21:
+ case WM_BUTTON22:
+ case WM_BUTTON23:
+ case WM_BUTTON24:
+ case WM_BUTTON25:
+ case WM_BUTTON26:
+ case WM_BUTTON27:
+ case WM_BUTTON28:
+ case WM_BUTTON29:
+ case WM_BUTTON30:
+ case WM_BUTTON31:
+ case WM_BUTTON32:
+ case WM_BUTTON33:
+ case WM_BUTTON34:
+ case WM_BUTTON35:
+ case WM_BUTTON36:
+ case WM_BUTTON37:
+ case WM_BUTTON38:
+ case WM_BUTTON39:
+ ChangeButtons(message);
+ break;
+ case WM_MOVIE:
+ StartMovie((char*)"movie\\essai.avi");
+ ChangePhase(WM_PHASE_INIT);
+ break;
+ }
+
+ return FALSE;
+}
+
+BOOL CEvent::LoadState(BOOL save)
+{
+ BOOL saveNum;
+ CEvent* pEvent;
+
+ saveNum = save;
+
+ if (m_pDecor->CurrentRead(m_gamer, save, (BOOL*)&pEvent, &save) == FALSE)
+ {
+ return FALSE;
+ }
+ m_bPrivate = save;
+ SetMission((int)pEvent);
+ m_saveIndex = saveNum;
+ return TRUE;
+}
+
+int CEvent::MousePosToSprite(POINT pos)
+{
+ int sprite;
+
+ sprite = SPRITE_POINTER;
+
+ if (m_phase != WM_PHASE_PLAY &&
+ m_phase != WM_PHASE_PLAYTEST &&
+ m_phase != WM_PHASE_BUILD &&
+ m_phase != WM_PHASE_BYE &&
+ !MouseOnButton(pos))
+ {
+ sprite = SPRITE_ARROW;
+ }
+ if (m_bWaitMouse)
+ {
+ sprite = SPRITE_WAIT;
+ }
+ if (m_bHideMouse)
+ {
+ sprite = SPRITE_EMPTY;
+ }
+ if (m_bDisableMouse)
+ {
+ sprite = SPRITE_DISABLE;
+ }
+
+ return sprite;
+}
+
+void CEvent::MouseSprite(POINT pos)
+{
+ m_mouseSprite = MousePosToSprite(pos);
+
+ m_pPixmap->SetMousePosSprite(pos, m_mouseSprite, m_bDemoPlay);
+ ChangeSprite(m_mouseSprite);
+}
+
+void CEvent::WaitMouse(BOOL bWait)
+{
+ m_bWaitMouse = bWait;
+
+ if ( bWait )
+ {
+ m_mouseSprite = SPRITE_WAIT;
+ }
+ else
+ {
+ m_mouseSprite = MousePosToSprite(GetMousePos());
+ }
+ m_pPixmap->SetMouseSprite(m_mouseSprite, m_bDemoPlay);
+ ChangeSprite(m_mouseSprite);
+}
+
+void CEvent::HideMouse(BOOL bHide)
+{
+ m_bHideMouse = bHide;
+ m_bDisableMouse = FALSE;
+
+ if ( bHide )
+ {
+ m_mouseSprite = SPRITE_EMPTY;
+ }
+ else
+ {
+ m_mouseSprite = MousePosToSprite(GetMousePos());
+ }
+ m_pPixmap->SetMouseSprite(m_mouseSprite, m_bDemoPlay);
+ ChangeSprite(m_mouseSprite);
+}
+
+void CEvent::DisableMouse(int bDisable)
+{
+ m_bDisableMouse = bDisable;
+
+ if (bDisable)
+ {
+ m_mouseSprite = SPRITE_DISABLE;
+ }
+ else
+ {
+ m_mouseSprite = MousePosToSprite(GetMousePos());
+ }
+ m_pPixmap->SetMouseSprite(m_mouseSprite, m_bDemoPlay);
+ ChangeSprite(m_mouseSprite);
+}
+
+BOOL CEvent::EventButtons(UINT message, WPARAM wParam, LPARAM lParam)
+{
+ POINT pos, test;
+ int i, lg, oldx, res;
+ UINT uid;
+
+ pos = GetMousePos();
+ m_textToolTips[0] = 0;
+ oldx = m_posToolTips.x;
+ m_posToolTips.x = -1;
+ if (m_phase != WM_PHASE_PLAY && m_phase != WM_PHASE_PLAYTEST && table[m_index].buttons[0].message)
+ {
+ i = 0;
+ while (table[m_index].buttons[i].message != 0)
+ {
+ res = m_buttons[i].GetToolTips(pos);
+ if (res != -1)
+ {
+ LoadString(res, m_textToolTips, 50);
+ lg = GetTextWidth(m_textToolTips);
+ pos.x += 10;
+ pos.y += 20;
+ if (pos.x > LXIMAGE - lg) pos.x = LXIMAGE - lg;
+ if (pos.y > LYIMAGE - 14) pos.y = LYIMAGE - 14;
+ m_posToolTips = pos;
+ break;
+ }
+ i++;
+ }
+ }
+ i = 0;
+ while (table[m_index].buttons[i].message != 0)
+ {
+ if (m_buttons[i].TreatEvent(message, wParam, lParam)) return TRUE;
+ i++;
+ }
+ if (m_phase == WM_PHASE_PLAY || m_phase == WM_PHASE_PLAYTEST)
+ {
+ if (m_menu.TreatEvent(message, wParam, lParam)) return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL CEvent::MouseOnButton(POINT pos)
+{
+ int i;
+
+ i = 0;
+ while ( table[m_index].buttons[i].message != 0 )
+ {
+ if ( m_buttons[i].MouseOnButton(pos) ) return TRUE;
+ i ++;
+ }
+
+ return FALSE;
+}
+
+int CEvent::SearchPhase(UINT phase)
+{
+ int i = 0;
+
+ while (table[i].phase != 0)
+ {
+ if (table[i].phase == phase) return i;
+ i++;
+ }
+
+ return -1;
+}
+
+int CEvent::GetWorld()
+{
+ //m_mission = mission;
+ if (m_bPrivate) return m_private;
+ if (m_bMulti) return m_multi+200;
+ else return m_mission;
+}
+
+int CEvent::GetPhysicalWorld()
+{
+ if ( m_bPrivate ) return m_bPrivate;
+ if ( m_bMulti ) return m_multi+200;
+ else return m_mission;
+}
+
+BOOL CEvent::IsPrivate()
+{
+ return m_bPrivate;
+}
+
+BOOL CEvent::IsMulti()
+{
+ return m_bMulti;
+}
+
+int CEvent::GetWorldGroup()
+{
+ if (m_mission % 10 != 0 && m_mission != 99)
+ {
+ m_mission = (m_mission / 10) * 10;
+ return -(m_mission >> 31);
+ }
+ m_mission = 1;
+ return m_mission / 10;
+}
+
+void CEvent::SetMission(int index)
+{
+ if (m_bPrivate != 0)
+ {
+ m_private = index;
+ return;
+ }
+ if (m_bMulti != 0)
+ {
+ m_multi = index;
+ return;
+ }
+ m_mission = index;
+ return;
+}
+
+UINT CEvent::GetPhase()
+{
+ return m_phase;
+}
+
+void CEvent::TryInsert()
+{
+ if ( m_tryInsertCount == 0 )
+ {
+ ChangePhase(m_tryPhase);
+ }
+ else
+ {
+ m_tryInsertCount --;
+ }
+}
+
+void CEvent::ReadAll()
+{
+ BOOL mission;
+ BOOL read;
+ BOOL bUser;
+ BOOL bPrivate;
+ BOOL bMission;
+
+ bUser = FALSE;
+
+ if ((-1 < m_choiceIndex) && (*(int*)((int)(m_filenameBuffer + -1) + m_choiceIndex * 4 + 216) != 0))
+ {
+ mission = m_pDecor->CurrentWrite(m_gamer, 999, bUser);
+
+ if (mission != FALSE)
+ {
+ read = m_pDecor->CurrentRead(m_gamer, m_choiceIndex, &bMission, &bPrivate);
+
+ if (read != FALSE)
+ {
+ m_pDecor->DrawMap(FALSE, -1);
+ }
+ m_pDecor->CurrentRead(m_gamer, 999, &bMission, &bPrivate);
+ }
+ }
+ return;
+}
+
+BOOL CEvent::SaveState(int rank)
+{
+ BOOL bMission;
+ BOOL bUser = FALSE;
+ char str[100];
+
+ bMission = m_pDecor->CurrentWrite(m_gamer, rank, bUser);
+
+ if (bMission == FALSE)
+ {
+ return FALSE;
+ }
+ LoadString(TX_GAMESAVED, str, 100);
+ m_pDecor->NotifPush(str);
+ // m_field959_0x6d10 = rank;
+ return TRUE;
+}
+
+void CEvent::SomethingUserMissions(char* lpFilename, LPCSTR fileSomething)
+{
+ char* str;
+
+ _mkdir("\\User");
+ strcpy(lpFilename, "\\User\\");
+ strcat(lpFilename, fileSomething);
+ str = strstr(lpFilename, ".xch");
+ if (!str || str - lpFilename != strlen(lpFilename) - 4)
+ strcat(lpFilename, ".xch");
+
+}
+
+// Add SomethingHubWorld once figured out.
+
+// Very rough code, needs improvement
+
+BOOL CEvent::ChangePhase(UINT phase)
+{
+ int i, mission;
+ char str[MAX_PATH];
+ char text[100];
+ char res[100];
+ BOOL bEnable;
+
+ text[0] = 0;
+
+ sprintf(str, "CEvent::ChangePhase [Begin] --- %d\r\n", phase - WM_USER);
+ OutputNetDebug(str);
+ if (phase == WM_PHASE_1588)
+ {
+ PostMessage(m_hWnd, WM_CLOSE, 0, 0);
+ return TRUE;
+ }
+ m_pDecor->SetDemoPlay(m_bDemoPlay);
+ if (m_mouseType == MOUSETYPEGRA && m_bFullScreen)
+ {
+ m_bShowMouse = FALSE;
+ }
+ if (phase == WM_PHASE_QUITPLAYTEST)
+ {
+ m_pDecor->Read(m_gamer, 999, TRUE);
+ phase = WM_PHASE_BUILD;
+ }
+
+ if (!m_bDemoPlay &&
+ phase != WM_PHASE_PLAY ||
+ m_phase != WM_PHASE_PLAY ||
+ phase != WM_PHASE_STOP ||
+ phase != WM_PHASE_SETUP ||
+ phase != WM_PHASE_HELP ||
+ phase != WM_PHASE_GREAD ||
+ phase != WM_PHASE_GREADp ||
+ phase != WM_PHASE_GWRITE)
+ {
+ m_pSound->StopMusic();
+ }
+
+ m_textToolTips[0] = 0;
+ m_posToolTips.x = -1;
+ m_pDecor->SetPause(FALSE);
+ m_bHili = FALSE;
+ m_bCtrlDown = FALSE;
+ m_bMouseDown = FALSE;
+ m_bInfoHelp = FALSE;
+
+
+ if (phase == WM_PHASE_INIT)
+ {
+ m_demoTime = 0;
+ }
+ if (phase == WM_PHASE_PLAY)
+ {
+ if (!m_bDemoPlay && GetWorld() > 299 && GetWorld() < 320)
+ {
+ DemoRecStart();
+ }
+ }
+ else
+ {
+ DemoRecStop();
+ }
+
+ if (phase == WM_PHASE_QUITPLAY)
+ {
+ if (!m_bPrivate)
+ {
+ if (!m_bMulti)
+ {
+ mission = m_mission;
+ if (mission != 1)
+ {
+ if (mission == 99 || mission % 10 == 0)
+ {
+ mission = 1;
+ }
+ else
+ {
+ mission = (mission / 10) * 10;
+ }
+ SetMission(mission);
+ m_phase = WM_PHASE_PLAY;
+
+ return ChangePhase(WM_PHASE_PLAY);
+ }
+ }
+ }
+ else if (!m_bMulti)
+ {
+ return ChangePhase(WM_PHASE_INFO);
+ }
+ }
+ if (phase == WM_PHASE_DP_DOSERVICE)
+ {
+ // ...
+ }
+ if (phase == WM_PHASE_DP_CANCELSERVICE)
+ {
+ // ...
+ }
+ if (phase == WM_PHASE_DP_JOIN)
+ {
+ // ...
+ }
+ if (phase == WM_PHASE_DP_CREATELOBBY)
+ {
+ // ...
+ }
+ if (phase == WM_PHASE_DP_REFRESH)
+ {
+ // ...
+ }
+ if (phase == WM_PHASE_DP_CANCELSESSION)
+ {
+ // ...
+ }
+ if (phase == WM_PHASE_DP_DOCREATE)
+ {
+ // ...
+ }
+ if (phase == WM_PHASE_DP_CANCELCREATE)
+ {
+ // ...
+ }
+ if (phase == WM_PHASE_DP_STARTMULTI)
+ {
+ // ...
+ }
+ if (phase == WM_PHASE_DP_CANCELMULTI)
+ {
+ // ...
+ }
+
+ if (SearchPhase(phase) < 0)
+ {
+ return 0;
+ }
+ m_pPixmap->MouseInvalidate();
+ HideMouse(FALSE);
+ WaitMouse(TRUE);
+
+ if (phase == WM_PHASE_GAMER || phase == WM_PHASE_PLAY)
+ {
+ OutputNetDebug("CEvent::ChangePhase [WriteInfo]\r\n");
+ WriteInfo(m_gamer);
+ }
+
+ int oldPhase = m_phase;
+ if ((oldPhase == WM_PHASE_BUILD && phase == WM_PHASE_INFO) || oldPhase == WM_PHASE_REGION || oldPhase == WM_PHASE_NAMEDESIGN || oldPhase == WM_PHASE_MUSIC)
+ {
+ m_pDecor->Write(m_gamer, GetWorld(), !m_bBuildOfficialMissions);
+ }
+
+ m_phase = phase;
+ m_index = SearchPhase(phase);
+ if (table[m_index].bLocked && !CheckWorld1())
+ {
+ m_tryInsertCount = 40;
+ m_tryPhase = m_phase;
+ return ChangePhase(WM_PHASE_INSERT);
+ }
+
+ if (table[m_index].backName[0] != '\0')
+ {
+ strcpy(str, table[m_index].backName);
+ if (str[0] != '\0')
+ {
+ if (table[m_index].bCDrom)
+ {
+ AddCDPath(str);
+ }
+ if (!m_pPixmap->BackgroundCache(0, str, POINT( LXIMAGE, LYIMAGE ), POINT( 0,0 ), FALSE))
+ {
+ OutputNetDebug("CEvent::ChangePhase [Cache error]\r\n");
+ WaitMouse(FALSE);
+ m_tryInsertCount = 40;
+ m_tryPhase = m_phase;
+ return ChangePhase(WM_PHASE_INSERT);
+ }
+ }
+ }
+
+ if (m_phase == WM_PHASE_PLAY && !m_bPrivate &&
+ oldPhase != WM_PHASE_SETUPp &&
+ oldPhase != WM_PHASE_HELP &&
+ oldPhase != WM_PHASE_GREAD &&
+ oldPhase != WM_PHASE_GREADp &&
+ oldPhase != WM_PHASE_GWRITE &&
+ oldPhase != WM_PHASE_STOP)
+ {
+ sprintf(str, "CEvent::ChangePhase [Read] %d, %d\r\n", m_gamer, GetWorld());
+ OutputNetDebug(str);
+
+ if (!m_pDecor->Read(m_gamer, GetWorld(), FALSE))
+ {
+ OutputNetDebug("CEvent::ChangePhase [Read error]\r\n");
+ m_tryInsertCount = 40;
+ m_tryPhase = m_phase;
+ return ChangePhase(WM_PHASE_INSERT);
+ }
+ m_pDecor->DrawMap(TRUE, -1);
+ }
+
+ if (m_phase != WM_PHASE_PLAY || m_bPrivate)
+ {
+ m_bDrawMap = m_pDecor->Read(m_gamer, GetWorld(), !m_bBuildOfficialMissions);
+ if (m_bDrawMap)
+ {
+ m_pDecor->DrawMap(TRUE, -1);
+ }
+ }
+
+ if (m_phase == WM_PHASE_INFO && m_bPrivate)
+ {
+
+ m_bDrawMap = m_pDecor->Read(m_gamer, GetWorld(), !m_bBuildOfficialMissions);
+ if (m_bDrawMap)
+ {
+ m_pDecor->DrawMap(TRUE, -1);
+ }
+
+ }
+
+ if ((m_phase == WM_PHASE_PLAY || m_phase == WM_PHASE_PLAYTEST) &&
+ oldPhase != WM_PHASE_SETUPp &&
+ oldPhase != WM_PHASE_HELP &&
+ oldPhase != WM_PHASE_GREAD &&
+ oldPhase != WM_PHASE_GREADp &&
+ oldPhase != WM_PHASE_GWRITE &&
+ oldPhase != WM_PHASE_STOP)
+ {
+ m_pDecor->AdaptDoors(m_bPrivate, GetWorld());
+ }
+
+ if (m_phase == WM_PHASE_TESTCD)
+ {
+ if (m_pDecor->Read(1, 1, FALSE))
+ {
+ return ChangePhase(WM_PHASE_INIT);
+ }
+ else
+ {
+ m_tryInsertCount = 40;
+ m_tryPhase = m_phase;
+ return ChangePhase(WM_PHASE_INSERT);
+ }
+ }
+
+ if (m_phase == WM_PHASE_PLAYTEST)
+ {
+ m_pDecor->Write(m_gamer, 999, TRUE);
+ m_pDecor->PlayPrepare(TRUE);
+ }
+
+ if (m_phase == WM_PHASE_PLAY &&
+ oldPhase != WM_PHASE_SETUPp &&
+ oldPhase != WM_PHASE_HELP &&
+ oldPhase != WM_PHASE_GREAD &&
+ oldPhase != WM_PHASE_GREADp &&
+ oldPhase != WM_PHASE_GWRITE &&
+ oldPhase != WM_PHASE_STOP)
+ {
+ if (m_bPrivate || m_bMulti)
+ {
+ m_pDecor->PlayPrepare(TRUE);
+ }
+ else
+ {
+ m_pDecor->PlayPrepare(FALSE);
+ m_pDecor->SetNbVies(m_nbVies);
+ }
+ }
+
+ if (m_phase == WM_PHASE_BUILD)
+ {
+ m_pDecor->BuildPrepare();
+ }
+
+ CreateButtons();
+ m_96B4 = 0;
+ m_menu.Delete();
+ if (m_phase == WM_PHASE_BUILD)
+ {
+
+ SetState(m_menuIndex + WM_DECOR1, 1);
+ SetMenu(WM_DECOR1, m_menuDecor[0]);
+ SetMenu(WM_DECOR2, m_menuDecor[1]);
+ SetMenu(WM_DECOR3, m_menuDecor[2]);
+ SetMenu(WM_DECOR4, m_menuDecor[3]);
+ SetMenu(WM_DECOR5, m_menuDecor[4]);
+ SetMenu(WM_DECOR6, m_menuDecor[5]);
+ SetMenu(WM_DECOR7, m_menuDecor[6]);
+ SetMenu(WM_DECOR8, m_menuDecor[7]);
+ SetMenu(WM_DECOR9, m_menuDecor[8]);
+ SetMenu(WM_DECOR10, m_menuDecor[9]);
+ SetMenu(WM_DECOR11, m_menuDecor[10]);
+ m_pDecor->SetFieldCC38AndStuff(m_menuIndex + 1, GetMenu(m_menuIndex + WM_DECOR1));
+ }
+ if (m_phase == WM_PHASE_PLAY || m_phase == WM_PHASE_PLAYTEST || m_phase == WM_PHASE_BUILD)
+ {
+ OutputNetDebug("CEvent::ChangePhase [LoadImages]\r\n");
+ m_pDecor->LoadImages();
+ }
+ if (m_phase == WM_PHASE_INFO)
+ {
+ bEnable = TRUE;
+ int world = 1;
+ if (GetWorld() == 0)
+ {
+ bEnable = FALSE;
+ }
+ SetEnable(WM_PREV, bEnable);
+ if (GetWorld() >= 320)
+ {
+ bEnable = FALSE;
+ }
+ if (m_bPrivate)
+ {
+ bEnable = GetWorld() < 20 - 1;
+ }
+ SetEnable(WM_NEXT, bEnable);
+ SetHide(WM_PHASE_BUILD, FALSE);
+ SetEnable(WM_PHASE_WRITEDESIGN, m_bDrawMap);
+ SetEnable(WM_PHASE_READDESIGN, !m_bDrawMap);
+ SetEnable(WM_PHASE_CLEARDESIGN, m_bDrawMap);
+ SetEnable(WM_PHASE_PLAYMOVIE, m_bDrawMap);
+ }
+ if (m_phase == WM_PHASE_GAMER)
+ {
+ WriteInfo(m_gamer);
+ BYTE door[200];
+ int i, j;
+ for (i = 0; i < 8; i++)
+ {
+ m_gamerNameList;
+ if (ReadInfo(i + 1))
+ {
+ m_bNamesExist[i] = TRUE;
+ strcpy(m_gamerNameList[i], m_gamerName);
+
+ m_pDecor->InitializeDoors(door);
+ int num = 0;
+ for (j = 0; j < 200; j++)
+ {
+ if (door[j] == 0)
+ {
+ num++;
+ }
+ }
+ if (num == 1)
+ {
+ LoadString(TX_NUMDOOROPEN, res, 100);
+ sprintf(text, res, num);
+ strcat(m_gamerNameList[i], text);
+ }
+ if (1 < num)
+ {
+ LoadString(TX_NUMDOORSOPEN, res, 100);
+ sprintf(text, res, num);
+ strcat(m_gamerNameList[i], text);
+ }
+ }
+ else
+ {
+ m_bNamesExist[i] = FALSE;
+ LoadString(TX_PLAYERFREE, m_gamerNameList[i], 100);
+ }
+ SetState(WM_BUTTON1 + i, m_gamer - 1 == i ? 1 : 0);
+ }
+ ReadInfo(m_gamer);
+ }
+ if (m_phase == WM_PHASE_NAMEGAMER)
+ {
+ strcpy(m_textInput, m_gamerName);
+ m_textHiliStart = 0;
+ m_textCursorIndex = 0;
+ m_textHiliEnd = strlen(m_textInput);
+ }
+ if (m_phase == WM_PHASE_NAMEDESIGN)
+ {
+ strcpy(m_textInput, m_pDecor->GetMissionTitle());
+ m_textHiliStart = 0;
+ m_textCursorIndex = 0;
+ m_textHiliEnd = strlen(m_textInput);
+ }
+ if (m_phase == WM_PHASE_MUSIC)
+ {
+ int music = m_pDecor->GetMusic();
+ for (int i = 0; i < 11; i++)
+ {
+ SetState(WM_BUTTON1 + i, i == music);
+ }
+ }
+ if (m_phase == WM_PHASE_REGION)
+ {
+ int region = m_pDecor->GetRegion();
+ for (int i = 0; i < 32; i++)
+ {
+ SetState(WM_BUTTON1 + i, i == region);
+ }
+ POINT dim = m_pDecor->GetDim();
+ if (dim.x == MAXCELX)
+ {
+ if (dim.y == MAXCELY)
+ {
+ SetState(WM_DIMS1, 1);
+ SetState(WM_DIMS2, 0);
+ SetState(WM_DIMS3, 0);
+ SetState(WM_DIMS4, 0);
+ }
+ if (dim.y == 0)
+ {
+ SetState(WM_DIMS1, 0);
+ SetState(WM_DIMS2, 1);
+ SetState(WM_DIMS3, 0);
+ SetState(WM_DIMS4, 0);
+ }
+ }
+ else if (dim.y == MAXCELY)
+ {
+ SetState(WM_DIMS1, 0);
+ SetState(WM_DIMS2, 0);
+ SetState(WM_DIMS3, 1);
+ SetState(WM_DIMS4, 0);
+ }
+ else
+ {
+ SetState(WM_DIMS1, 0);
+ SetState(WM_DIMS2, 0);
+ SetState(WM_DIMS3, 0);
+ SetState(WM_DIMS4, 1);
+ }
+ }
+ if (m_phase == WM_PHASE_SERVICE)
+ {
+ m_pNetwork->EnumProviders();
+ m_nbChoices = m_pNetwork->GetNbProviders();
+ m_choicePageOffset = 0;
+ m_choiceIndex = 0;
+ SetHide(WM_BUTTON10, TRUE);
+ SetHide(WM_BUTTON11, m_choicePageOffset + 6 >= (m_nbChoices + 5) / 6 * 6);
+ for (i = 0; i < 6; ++i)
+ {
+ if (m_choicePageOffset + i >= m_nbChoices)
+ {
+ SetHide(WM_BUTTON1 + i, TRUE);
+ }
+ else
+ {
+ SetHide(WM_BUTTON1 + i, FALSE);
+ SetState(WM_BUTTON1 + i, m_choicePageOffset + i == m_choiceIndex);
+ }
+ }
+ SetEnable(WM_PHASE_DP_DOSERVICE, m_nbChoices != 0);
+ }
+ if (m_phase == WM_PHASE_SESSION)
+ {
+ m_nbChoices = m_pNetwork->GetNbSessions();
+ m_choicePageOffset = 0;
+ m_choiceIndex = 0;
+ SetHide(WM_BUTTON10, 1);
+ SetHide(WM_BUTTON11, m_choicePageOffset + 6 >= (m_nbChoices + 5) / 6 * 6);
+ for (i = 0; i < 6; ++i)
+ {
+ if (m_choicePageOffset + i >= m_nbChoices)
+ {
+ SetHide(WM_BUTTON1 + i, TRUE);
+ }
+ else
+ {
+ SetHide(WM_BUTTON1, FALSE);
+ SetState(WM_BUTTON1 + i, m_choicePageOffset + i == m_choiceIndex);
+ }
+ }
+ SetEnable(WM_PHASE_DP_JOIN, m_nbChoices != 0);
+ }
+ if (m_phase == WM_PHASE_MULTI)
+ {
+ m_bDrawMap = m_pDecor->Read(m_gamer, m_multi + 200, 0);
+ for (i = 0; i < MAXNETPLAYER; i++)
+ {
+ m_pNetwork->m_players[i].bIsPresent = FALSE;
+ }
+ if (m_pNetwork->IsHost())
+ {
+ m_pNetwork->m_players[0].bIsPresent = TRUE;
+ m_pNetwork->m_players[0].ready = FALSE;
+ m_pNetwork->m_players[0].dpid = m_pNetwork->m_dpid;
+ m_pNetwork->m_players[0].team = 0;
+ strncpy(m_pNetwork->m_players[0].name, m_gamerName, 20);
+ m_pNetwork->m_players[0].name[19] = '\0';
+ }
+ else
+ {
+ char data[28];
+ data[0] = 28;
+ data[1] = MESS_2;
+ *&data[4] = m_pNetwork->m_dpid;
+ strncpy(data + 8, m_gamerName, 20);
+ m_pNetwork->Send(data, 28, 1);
+ }
+ if (m_bDrawMap)
+ {
+ DrawMap();
+ }
+ NetAdjustLobbyButtons();
+ ChatFlush();
+ m_textHiliStart = 0;
+ m_textInput[0] = 0;
+ m_textCursorIndex = 0;
+ m_textHiliEnd = strlen(m_textInput);
+ }
+ if (m_phase == WM_PHASE_CREATE)
+ {
+ m_textHiliStart = 0;
+ m_textInput[0] = 0;
+ m_textCursorIndex = 0;
+ m_textHiliEnd = strlen(m_textInput);
+ }
+ if (m_phase == WM_PHASE_STOP && m_bMulti)
+ {
+ SetEnable(WM_PHASE_GWRITE, 0);
+ SetEnable(WM_PHASE_GREADp, 0);
+ }
+ if (m_phase == WM_PHASE_WRITEDESIGN || m_phase == WM_PHASE_READDESIGN)
+ {
+ long hFile;
+ struct _finddata_t fBuffer;
+ BOOL bDo;
+ char temp[_MAX_FNAME];
+
+ m_nbChoices = 0;
+ hFile = _findfirst("\\User\\*.xch", &fBuffer);
+ if (hFile != -1)
+ {
+ do
+ {
+ strcpy(m_filenameBuffer[m_nbChoices++], fBuffer.name);
+ } while (_findnext(hFile, &fBuffer) == 0 &&
+ m_nbChoices < 100);
+ }
+ do
+ {
+ bDo = FALSE;
+
+ for (i = 0; i < m_nbChoices - 1; i++)
+ {
+ if (strcmp(m_filenameBuffer[i], m_filenameBuffer[i + 1]) > 0)
+ {
+ strcpy(temp, m_filenameBuffer[i]);
+ strcpy(m_filenameBuffer[i], m_filenameBuffer[i + 1]);
+ strcpy(m_filenameBuffer[i + 1], temp);
+ bDo = TRUE;
+ }
+ }
+
+ } while (bDo);
+ m_choicePageOffset = 0;
+ m_choiceIndex = 0;
+ }
+ if (m_phase == WM_PHASE_READDESIGN)
+ {
+ SetHide(WM_BUTTON10, m_choicePageOffset == 0);
+ SetHide(WM_BUTTON11, (((m_nbChoices + 5) /6 ) * 6 <= m_choicePageOffset + 6));
+ for (i = 0; i < 6; i++)
+ {
+ if (i + m_choicePageOffset < m_nbChoices)
+ {
+ SetHide(WM_BUTTON1 + i, FALSE);
+ SetState(WM_BUTTON1 + i, i + m_choicePageOffset == m_choiceIndex);
+ }
+ else
+ {
+ SetHide(WM_BUTTON1 + i, TRUE);
+ }
+ }
+ SetEnable(WM_PHASE_DOREADDESIGN, m_nbChoices != 0);
+ }
+ if (m_phase == WM_PHASE_WRITEDESIGN)
+ {
+ SetHide(WM_BUTTON10, m_choicePageOffset == 0);
+ SetHide(WM_BUTTON11, m_choicePageOffset + 12 >= 12 * ((m_nbChoices + 11) / 12));
+ strcpy(m_textInput, m_pDecor->GetMissionTitle());
+ if (!m_textInput[0])
+ {
+ LoadString(TX_MISSION2D, res, 100);
+ sprintf(m_textInput, res, GetWorld());
+ }
+ m_textHiliStart = 0;
+ m_textHiliEnd = strlen(m_textInput);
+ memcpy(&m_textInput[strlen(m_textInput)], ".xch", strlen(".xch") + 1);
+ m_textCursorIndex = 0;
+ }
+ if (m_phase == WM_PHASE_GWRITE || m_phase == WM_PHASE_GREADp || m_phase == WM_PHASE_GREAD)
+ {
+ m_fileIndex = m_saveIndex;
+
+ for (i = 0; i < 6; i++)
+ {
+ SetState(WM_BUTTON1 + i, i == m_fileIndex);
+ if (m_pDecor->Write(m_gamer, i, TRUE))
+ {
+ *m_bNamesExist = NULL;
+ LoadString(TX_MISSIONFREE, *m_filenameBuffer, 50);
+ if ((m_phase == WM_PHASE_GREAD) || (m_phase == WM_PHASE_GREADp))
+ {
+ SetEnable(WM_BUTTON1 + i, 0);
+ }
+ }
+ else
+ {
+ *m_bNamesExist = TRUE;
+
+ }
+ }
+ ReadAll();
+ if (m_fileIndex < 0)
+ {
+ i = 0;
+ }
+ else
+ {
+ i = (int)m_filenameBuffer - 1 + m_fileIndex * 4 + 216;
+ }
+ SetEnable(WM_BUTTON20, i);
+ }
+ if (m_phase == WM_PHASE_SETUP || m_phase == WM_PHASE_SETUPp)
+ {
+ m_0008 = 0;
+ int numDevs;
+ char pBuff[400];
+ DescInfo* info;
+ numDevs = joyGetNumDevs();
+ /*
+ if (numDevs > 0)
+ {
+ for (i = 0; i < numDevs; i++)
+ {
+ memset(pBuff, 0, sizeof(404));
+ if (!joyGetDevCapsA(i, (LPJOYCAPSA)pBuff, 404))
+ {
+ info->reserve1[3][4 * m_0008 + 220] = i;
+ }
+ }
+ }
+ */
+ }
+ if ((m_phase == WM_PHASE_PLAY || m_phase == WM_PHASE_PLAYTEST || m_phase == WM_PHASE_MUSIC) && !m_bDemoPlay)
+ {
+ if (!m_pSound->IsPlayingMusic())
+ {
+ int music = m_pDecor->GetMusic();
+ if (music > 0)
+ {
+ m_pSound->PlayMusic(m_hWnd, music);
+ }
+ }
+ else
+ {
+ m_pSound->AdaptVolumeMusic();
+ }
+ }
+ if (m_phase == WM_PHASE_PLAYMOVIE)
+ {
+ sprintf(m_movieToStart, "movie\\play%.3d.avi", GetWorld());
+ AddCDPath(m_movieToStart);
+ m_phaseAfterMovie = WM_PHASE_PLAY;
+ }
+ if (m_phase == WM_PHASE_WINMOVIE)
+ {
+ sprintf(m_movieToStart, "movie\\win%.3d.avi", GetWorld());
+ AddCDPath(m_movieToStart);
+ m_phaseAfterMovie = WM_PHASE_WIN;
+ }
+ if (m_phase == WM_PHASE_WINMOVIEDESIGN)
+ {
+ sprintf(m_movieToStart, "movie\\win%.3d.avi", GetWorld());
+ AddCDPath(m_movieToStart);
+ m_phaseAfterMovie = WM_PHASE_WINDESIGN;
+ }
+ if (m_phase == WM_PHASE_WINMOVIEMULTI)
+ {
+ sprintf(m_movieToStart, "movie\\win%.3d.avi", GetWorld());
+ AddCDPath(m_movieToStart);
+ m_phaseAfterMovie = WM_PHASE_LOSTMULTI; // ?
+ }
+ WaitMouse(FALSE);
+ if (m_phase == WM_PHASE_PLAY || m_phase == WM_PHASE_PLAYTEST)
+ {
+ DisableMouse(TRUE);
+ }
+ m_pDecor->VehicleSoundsPhase(phase);
+ OutputNetDebug("CEvent::ChangePhase [End]");
+
+ return TRUE;
+
+}
+
+// Implement LoadLevel
+
+void CEvent::MovieToStart()
+{
+ if (m_movieToStart[0] != 0)
+ {
+ HideMouse(TRUE);
+
+ if (StartMovie(m_movieToStart))
+ {
+ m_phase = m_phaseAfterMovie;
+ }
+ else
+ {
+ ChangePhase(m_phaseAfterMovie);
+ }
+
+ m_movieToStart[0] = 0;
+ }
+}
+
+void CEvent::MouseRelease()
+{
+ m_bMouseRelease = TRUE;
+ ShowCursor(TRUE);
+ return;
+}
+
+void CEvent::MouseCapture()
+{
+ m_bMouseRelease = FALSE;
+ ShowCursor(FALSE);
+ return;
+}
+
+BOOL CEvent::NetCreate(int session)
+{
+ BOOL created;
+
+ MouseRelease();
+ created = m_pNetwork->CreateProvider(session);
+ MouseCapture();
+ return created;
+}
+
+BOOL CEvent::NetEnumSessions()
+{
+ BOOL enumSess;
+
+ MouseRelease();
+ enumSess = m_pNetwork->EnumProviders();
+ MouseCapture();
+ return enumSess;
+}
+
+BOOL CEvent::BuildUp(POINT pos, int fwKeys)
+{
+ return TRUE;
+}
+
+int CEvent::PlaceBuildItem(POINT cel, int flags, int currentIcon)
+{
+ if (cel.x > 640)
+ return 0;
+ if (cel.y > 480)
+ return 0;
+ if ((flags & 2) != 0)
+ {
+ m_pDecor->DeleteCel(m_pDecor->ScreenPosToCelPos(cel));
+ return 1;
+ }
+ else
+ {
+ if (GetState(WM_DECOR1) == 1)
+ {
+ m_pDecor->DeleteCel(m_pDecor->ScreenPosToCelPos(cel));
+ }
+ if (GetState(WM_DECOR2) == 1)
+ {
+ m_pDecor->PlaceItemFromMenu1(cel, GetMenu(WM_DECOR2), flags, currentIcon);
+ }
+ }
+ return 1;
+}
+
+/*
+void CEvent::TryPhase()
+{
+ m_tryPhase = 1;
+ ShowCursor(1);
+}
+
+void CEvent::UnTryPhase()
+{
+ m_tryPhase = 0;
+ ShowCursor(1);
+}
+
+int CEvent::GetTryPhase()
+{
+ return m_tryPhase;
+}
+
+void CEvent::GetDoors(int doors)
+{
+ for (int i = 0; i < 200; i++)
+ {
+ doors[i] = (int)data[Gamer];
+ }
+}
+
+
+void CEvent::TableSomething()
+{
+ char filename[MAX_PATH];
+
+ if (strstr(filename, table[m_index].backName))
+ {
+ AddCDPath(filename);
+ }
+ if (!m_pPixmap->CacheAll(CHBACK, filename, totalDim, iconDim, FALSE, GetRegion()))
+ {
+ return;
+ }
+}
+*/
+
+
+
+BOOL CEvent::StartMovie(char* pFilename)
+{
+ RECT rect;
+ char filename[MAX_PATH];
+
+ if (!m_pMovie->GetEnable()) return FALSE;
+ if (!m_bMovie) return FALSE;
+
+ if (!m_pMovie->IsExist(pFilename)) return FALSE;
+
+ rect.left = 1;
+ rect.top = 1;
+ rect.right = LXIMAGE - 2;
+ rect.bottom = LYIMAGE - 2;
+
+ m_pSound->StopMusic();
+ m_pPixmap->SavePalette();
+
+ strcpy(filename, pFilename);
+ strcpy(filename + strlen(filename) - 4, ".blp");
+ m_pSound->Cache(SOUND_MOVIE, filename);
+
+ if (m_pMovie->Play(m_hWnd, rect, pFilename)) return FALSE;
+ m_bRunMovie = TRUE;
+ m_pSound->Play(SOUND_MOVIE, 0, 0);
+ return TRUE;
+}
+
+void CEvent::StopMovie()
+{
+ m_pMovie->Stop(m_hWnd);
+ m_pPixmap->RestorePalette();
+ m_pPixmap->MouseInvalidate();
+ m_pSound->Flush(SOUND_MOVIE);
+ ChangePhase(m_phase);
+ m_bRunMovie = FALSE;
+}
+
+BOOL CEvent::IsMovie()
+{
+ return m_bRunMovie;
+}
+
+BOOL CEvent::IsMouseRelease()
+{
+ return m_bMouseRelease;
+}
+
+BOOL CEvent::ReadLibelle(int world, BOOL bSchool, BOOL bHelp)
+{
+ FILE* file = NULL;
+ char* pBuffer = NULL;
+ char* pText;
+ char* pDest;
+ char indic;
+ int nb, h1, h2;
+
+ pBuffer = (char*)malloc(sizeof(char) * 2560);
+ if (pBuffer == NULL) goto error;
+ memset(pBuffer, 0, sizeof(char) * 2560);
+
+ //file = fopen
+
+
+error:
+ if (pBuffer != NULL) free(pBuffer);
+ if (file != NULL) fclose(file);
+ return FALSE;
+}
+
+void CEvent::SetNbVies(int lives)
+{
+ m_lives = lives;
+}
+
+void CEvent::SetSpeed(int speed)
+{
+ if ( speed > 2 ) speed = 2;
+
+ m_speed = speed;
+}
+
+int CEvent::GetSpeed()
+{
+ return m_speed;
+}
+
+BOOL CEvent::GetPause()
+{
+ return m_bPause;
+}
+
+int CEvent::MissionBack()
+{
+ int num = m_mission;
+
+ if (num % 10 == 0 ||
+ num == 99)
+ {
+ m_mission = 1;
+ return num / 10;
+ }
+ else
+ {
+ m_mission = num / 10 * 10;
+ return (num < 0);
+ }
+}
+
+void CEvent::DemoRecStart()
+{
+ m_pDemoBuffer = (DemoEvent*)malloc(MAXDEMO*sizeof(DemoEvent));
+ if ( m_pDemoBuffer == NULL ) return;
+ memset(m_pDemoBuffer, 0, MAXDEMO*sizeof(DemoEvent));
+
+ m_demoTime = 0;
+ m_demoIndex = 0;
+ m_bDemoRec = TRUE;
+ m_bDemoPlay = FALSE;
+
+ InitRandom();
+ m_pDecor->SetTime(0);
+ m_speed = 1;
+}
+
+void CEvent::DemoRecStop()
+{
+ FILE* file = NULL;
+ DemoHeader header;
+
+ if ( m_bDemoPlay ) return;
+
+ if ( m_pDemoBuffer != NULL )
+ {
+ DeleteFileA("data\\demo.3d.blp");
+ file = fopen("data\\demo.3d.blp", "wb");
+ if ( file != NULL )
+ {
+ memset(&header, 0, sizeof(DemoHeader));
+ header.majRev = 1;
+ header.minRev = 0;
+ header.bSchool = m_bSchool;
+ header.bPrivate = m_bPrivate;
+ fwrite(&header, sizeof(DemoHeader), 1, file);
+ fwrite(m_pDemoBuffer, sizeof(DemoEvent), m_demoIndex, file);
+ fclose(file);
+ }
+ free(m_pDemoBuffer);
+ m_pDemoBuffer = NULL;
+ }
+
+ m_bDemoRec = FALSE;
+ m_demoTime = 0;
+}
+
+BOOL CEvent::DemoPlayStart()
+{
+ char filename[MAX_PATH];
+ FILE* file = NULL;
+ DemoHeader header;
+ int nb, world, time, total, mission;
+
+ m_pDemoBuffer = (DemoEvent*)malloc(MAXDEMO * sizeof(DemoEvent));
+ if (m_pDemoBuffer == NULL) return FALSE;
+ memset(m_pDemoBuffer, 0, MAXDEMO * sizeof(DemoEvent));
+
+ sprintf(filename, "data\\demo%.3d.blp", m_demoNumber);
+ AddCDPath(filename); // ajoute l'acc�s au CD-Rom
+ file = fopen(filename, "rb");
+ if (file == NULL)
+ {
+ DemoPlayStop();
+ return FALSE;
+ }
+
+ nb = fread(&header, sizeof(DemoHeader), 1, file);
+ if (nb < 1)
+ {
+ DemoPlayStop();
+ return FALSE;
+ }
+ m_bSchool = header.bSchool;
+ m_bPrivate = header.bPrivate;
+ //m_pDecor->SetSkill(header.skill);
+
+ m_demoEnd = fread(m_pDemoBuffer, sizeof(DemoEvent), MAXDEMO, file);
+ fclose(file);
+
+ m_demoTime = 0;
+ m_demoIndex = 0;
+ m_bDemoPlay = TRUE;
+ m_bDemoRec = FALSE;
+
+ /*
+ if (!m_pDecor->CurrentRead(m_gamer, mission, FALSE))
+ {
+ DemoPlayStop();
+ return FALSE;
+ }
+ ChangePhase(WM_PHASE_PLAY);
+ InitRandom();
+ m_pDecor->SetTime(0);
+ m_speed = 1;
+ */
+ return TRUE;
+}
+
+void CEvent::DemoPlayStop()
+{
+ if (m_pDemoBuffer != NULL)
+ {
+ free(m_pDemoBuffer);
+ m_pDemoBuffer = NULL;
+ }
+ m_bDemoPlay = FALSE;
+ m_bDemoRec = FALSE;
+ m_demoTime = 0;
+ m_keyPress = 0;
+ m_pDecor->SetInput(0);
+ m_private = 1;
+ ChangePhase(WM_PHASE_INIT);
+}
+
+void CEvent::DemoStep()
+{
+ int time;
+ UINT message;
+ WPARAM wParam;
+ LPARAM lParam;
+ POINT pos;
+
+ if (m_phase == WM_PHASE_INIT)
+ {
+ if (m_demoTime > DEF_TIME_DEMO) // ~30 secondes �coul�es ?
+ {
+ m_demoNumber = 0;
+ DemoPlayStart(); // d�marre une d�mo automatique
+ }
+ }
+
+ if (m_bDemoPlay && // d�mo en lecture ?
+ m_pDemoBuffer != NULL)
+ {
+ while (TRUE)
+ {
+ time = m_pDemoBuffer[m_demoIndex].time;
+ if (time > m_demoTime) break;
+
+ message = m_pDemoBuffer[m_demoIndex].message;
+ wParam = m_pDemoBuffer[m_demoIndex].wParam;
+ lParam = m_pDemoBuffer[m_demoIndex].lParam;
+ m_demoIndex++;
+
+ if (message == WM_MOUSEMOVE &&
+ m_mouseType == MOUSETYPEWIN)
+ {
+ pos = ConvLongToPos(lParam);
+ ClientToScreen(m_hWnd, &pos);
+ SetCursorPos(pos.x, pos.y);
+ }
+
+ TreatEventBase(message, wParam, lParam);
+
+ if (m_demoIndex >= m_demoEnd)
+ {
+ m_demoNumber++; // d�mo suivante
+ if (!DemoPlayStart()) // d�marre la d�mo suivante
+ {
+ m_demoNumber = 0; // premi�re d�mo
+ DemoPlayStart(); // d�marre la d�mo
+ }
+ return;
+ }
+ }
+ }
+
+ m_demoTime++;
+}
+
+void CEvent::DemoRecEvent()
+{
+ if (m_bDemoRec)
+ {
+ m_pDemoBuffer[m_demoIndex].time = m_demoTime;
+ m_pDemoBuffer[m_demoIndex].input = m_keyPress;
+ m_demoIndex++;
+ if (m_demoIndex > MAXDEMO)
+ {
+ DemoRecStop();
+ }
+ }
+}
+
+BOOL CEvent::WriteInfo(int gamer)
+{
+ char filename[MAX_PATH];
+ FILE* file = NULL;
+ DescInfo info;
+ int nb;
+ int doors;
+ char text[100];
+
+ if (m_playerIndex = 0) return TRUE;
+ sprintf(filename, "data\\info%.3d.blp", gamer);
+ AddUserPath(filename);
+
+ file = fopen(filename, "wb");
+ if (file == NULL) goto error;
+
+ strcpy(text, m_gamerName);
+
+ info.majRev = 1;
+ info.minRev = 0;
+ info.prive = m_private;
+ info.mission = m_mission;
+ info.multi = m_multi;
+ info.nbVies = m_nbVies;
+ info.speed = m_speed;
+ info.bMovie = m_bMovie;
+ info.bHiliInfoButton = m_bHiliInfoButton;
+ info.bBuildOfficialMissions = m_bBuildOfficialMissions;
+
+ info.audioVolume = m_pSound->GetAudioVolume();
+ info.midiVolume = m_pSound->GetMidiVolume();
+
+ m_pDecor->InitializeDoors(info.doors);
+
+ nb = fwrite(&info, sizeof(DescInfo), 1, file);
+ if (nb < 1) goto error;
+
+ fclose(file);
+ return TRUE;
+
+error:
+ if (file != NULL) fclose(file);
+ return FALSE;
+
+}
+
+BOOL CEvent::ReadInfo(int gamer)
+{
+ char filename[MAX_PATH];
+ FILE* file = NULL;
+ DescInfo info;
+ int nb;
+ int i;
+ BYTE doors[200];
+ char buffer[100];
+
+ m_playerIndex = 1;
+ m_pDecor->InitGamer();
+ m_nbVies = 3;
+ m_mission = 1;
+ m_private = 1;
+ m_multi = 1;
+
+ LoadString(TX_READINFO, buffer, 100);
+ sprintf(m_gamerName, buffer, gamer);
+ sprintf(filename, "data\\info%.3d.blp", gamer);
+ AddUserPath(filename);
+
+
+ file = fopen(filename, "rb");
+ if (file == NULL) goto error;
+
+ nb = fread(&info, sizeof(DescInfo), 1, file);
+ if (nb < 1) goto error;
+
+ i = 0;
+
+ if (m_gamerName[i] != '\0')
+ strcpy(buffer, m_gamerName);
+
+
+ info.majRev = 1;
+ m_private = info.prive;
+ m_multi = info.multi;
+ m_nbVies = info.nbVies;
+ m_bMovie = info.bMovie;
+ m_mission = info.mission;
+ m_bHiliInfoButton = info.bHiliInfoButton;
+ m_speed = info.speed;
+ m_bBuildOfficialMissions = info.bBuildOfficialMissions;
+
+ m_pDecor->SetBuildOfficialMissions(info.bBuildOfficialMissions);
+ m_pSound->SetAudioVolume(info.audioVolume);
+ m_pSound->SetMidiVolume(info.midiVolume);
+ m_pDecor->MemorizeDoors(doors);
+ fclose(file);
+ return TRUE;
+
+error:
+ if (file != NULL) fclose(file);
+ return FALSE;
+}
+
+void CEvent::ChangeButtons(int message)
+{
+ int choice;
+ if (m_phase == WM_PHASE_GAMER && message >= WM_BUTTON1 && message <= WM_BUTTON10)
+ {
+ m_gamer = message - WM_BUTTON0;
+ for (int i = 0; i < 10; i++)
+ {
+ SetState(WM_BUTTON1 + i, i == m_gamer - 1);
+ }
+ ReadInfo(m_gamer);
+ }
+ if (m_phase == WM_PHASE_NAMEGAMER && message == WM_PHASE_DONAMEGAMER)
+ {
+ strcpy(m_gamerName, m_textInput);
+ WriteInfo(m_gamer);
+ ChangePhase(WM_PHASE_GAMER);
+ }
+ if (m_phase == WM_PHASE_NAMEDESIGN && message == WM_PHASE_DONAMEDESIGN)
+ {
+ m_pDecor->SetMissionTitle(m_textInput);
+ ChangePhase(WM_PHASE_INFO);
+ }
+ if (m_phase == WM_PHASE_CLEARGAMER && message == WM_PHASE_DOCLEARGAMER)
+ {
+ ClearGamer(m_gamer);
+ ChangePhase(WM_PHASE_GAMER);
+ }
+ if (m_phase == WM_PHASE_CLEARDESIGN && message == WM_PHASE_DOCLEARDESIGN)
+ {
+ m_pDecor->DeleteMission(m_gamer, GetWorld(), !m_bBuildOfficialMissions);
+ ChangePhase(WM_PHASE_INFO);
+ }
+ if (m_phase == WM_PHASE_MUSIC)
+ {
+ m_pDecor->SetMusic(message - WM_BUTTON0);
+ ChangePhase(m_phase);
+ }
+ if (m_phase == WM_PHASE_REGION)
+ {
+ if (message >= WM_BUTTON1 && message <= WM_BUTTON32)
+ {
+ m_pDecor->SetRegion(message - WM_BUTTON1);
+ ChangePhase(m_phase);
+ }
+ if (message >= WM_DIMS1 && message <= WM_DIMS4)
+ {
+ SetState(WM_DIMS1, 0);
+ SetState(WM_DIMS2, 0);
+ SetState(WM_DIMS3, 0);
+ SetState(WM_DIMS4, 0);
+ SetState(message, 1);
+ if (message == WM_DIMS1) m_pDecor->SetDim(POINT( MAXCELX, MAXCELY ));
+ if (message == WM_DIMS2) m_pDecor->SetDim(POINT( MAXCELX, 0 ));
+ if (message == WM_DIMS3) m_pDecor->SetDim(POINT( 0, MAXCELY ));
+ if (message == WM_DIMS4) m_pDecor->SetDim(POINT( 0, 0 ));
+ }
+ }
+ if (m_phase == WM_PHASE_SERVICE)
+ {
+ if (message >= WM_BUTTON1 && message <= WM_BUTTON6)
+ {
+ m_choiceIndex = message - WM_BUTTON1 + m_choicePageOffset;
+ }
+ if (message == WM_BUTTON10)
+ {
+ m_choicePageOffset -= 6;
+ if (m_choicePageOffset < 0) m_choicePageOffset = 0;
+ }
+ if (message == WM_BUTTON11)
+ {
+ m_choicePageOffset += 6;
+ }
+ SetHide(WM_BUTTON10, m_choicePageOffset == 0);
+ SetHide(WM_BUTTON11, (m_nbChoices + 5) / 6 * 6 <= m_choicePageOffset + 6);
+ for (int i = 0; i < 6; i++)
+ {
+ if (m_choicePageOffset + i < m_nbChoices)
+ {
+ SetHide(WM_BUTTON1 + i, FALSE);
+ SetState(WM_BUTTON1 + i, m_choicePageOffset == m_choiceIndex);
+ }
+ else
+ {
+ SetHide(WM_BUTTON1 + i, TRUE);
+ }
+ }
+ }
+ if (m_phase == WM_PHASE_SESSION)
+ {
+ if (message >= WM_BUTTON1 && message <= WM_BUTTON6)
+ {
+ m_choiceIndex = message - WM_BUTTON1 + m_choicePageOffset;
+ }
+ if (message == WM_BUTTON10)
+ {
+ m_choicePageOffset -= 6;
+ if (m_choicePageOffset < 0) m_choicePageOffset = 0;
+ }
+ if (message == WM_BUTTON11)
+ {
+ m_choicePageOffset += 6;
+ }
+ SetHide(WM_BUTTON10, m_choicePageOffset == 0);
+ SetHide(WM_BUTTON11, (m_nbChoices + 5) / 6 * 6 <= m_choicePageOffset + 6);
+ for (int i = 0; i < 6; i++)
+ {
+ if (m_choicePageOffset + i < m_nbChoices)
+ {
+ SetHide(WM_BUTTON1 + i, FALSE);
+ SetState(WM_BUTTON1 + i, m_choicePageOffset == m_choiceIndex);
+ }
+ else
+ {
+ SetHide(WM_BUTTON1 + i, TRUE);
+ }
+ }
+ }
+ if (m_phase == WM_PHASE_MULTI)
+ {
+ if (message >= WM_BUTTON1 && message <= WM_BUTTON4)
+ {
+ if (m_pNetwork->m_players[message - WM_BUTTON1].team >= MAXNETPLAYER)
+ {
+ m_pNetwork->m_players[message - WM_BUTTON1].team = 0;
+ }
+
+ if (m_pNetwork->IsHost())
+ {
+ NetSendLobby();
+ }
+ else
+ {
+ //TODO
+ //m_pNetwork->Send(...
+ }
+ //DrawMap();
+ //NetAdjustLobbyButtons();
+ }
+ if (message >= WM_BUTTON11 && message <= WM_BUTTON14)
+ {
+ m_pNetwork->m_players[message - WM_BUTTON11].ready ^= 1; // toggle ready
+ if (m_pNetwork->IsHost())
+ {
+ NetSendLobby();
+ }
+ else
+ {
+ //TODO
+ //m_pNetwork->Send(...
+ }
+ //NetAdjustLobbyButtons();
+ }
+ if (message == WM_BUTTON20)
+ {
+ ChatSend();
+ }
+ }
+ if (m_phase == WM_PHASE_READDESIGN)
+ {
+ BOOL bBuild;
+ char out[100];
+ char file[256];
+ if (message >= WM_BUTTON1 && message <= WM_BUTTON6)
+ {
+ m_choiceIndex = m_choicePageOffset + message - WM_BUTTON1;
+ }
+ if (message == WM_BUTTON10)
+ {
+ choice = m_choicePageOffset;
+ m_choicePageOffset = choice - 6;
+ if (choice - 6 < 0)
+ m_choicePageOffset = 0;
+ }
+ if (message == WM_BUTTON11)
+ m_choicePageOffset += 6;
+ if (message == WM_PHASE_DOREADDESIGN)
+ {
+ SomethingUserMissions(file, m_filenameBuffer[m_choiceIndex]);
+ bBuild = !m_bBuildOfficialMissions;
+ m_pDecor->GetMissionPath(out, m_gamer, GetWorld(), bBuild);
+ CopyMission(file, out);
+ ChangePhase(WM_PHASE_INFO);
+ }
+ SetHide(WM_BUTTON10, m_choicePageOffset == 0);
+ SetHide(WM_BUTTON11, m_choicePageOffset + 6 >= 6 * (m_nbChoices + 5) / 6);
+ for (int k = 0; k < 6; k++)
+ {
+ if (m_choicePageOffset + k >= m_nbChoices)
+ {
+ SetHide(k + WM_BUTTON1, 1);
+ }
+ else
+ {
+ SetHide(k + WM_BUTTON1, 0);
+ SetState(k + WM_BUTTON1, m_choicePageOffset + k == m_choiceIndex);
+ }
+ }
+ }
+ if (m_phase == WM_PHASE_WRITEDESIGN)
+ {
+ //TODO
+ }
+ if (m_phase == WM_PHASE_GREAD || m_phase == WM_PHASE_GREADp)
+ {
+ if (message >= WM_BUTTON1 && message <= WM_BUTTON6)
+ {
+ m_choiceIndex = message - WM_BUTTON1;
+ ReadAll();
+ for (int n = 0; n < 6; n++)
+ {
+ SetState(n + WM_BUTTON1, n == m_choiceIndex);
+ }
+ SetEnable(WM_BUTTON20, GetState(m_choiceIndex + WM_BUTTON1));
+ }
+ if (message == WM_BUTTON20 && GameSave(m_choiceIndex))
+ ChangePhase(WM_PHASE_PLAY);
+ }
+ if (m_phase == WM_PHASE_GWRITE)
+ {
+ if (message == WM_BUTTON1 && WM_BUTTON6)
+ {
+ m_choiceIndex = message - WM_BUTTON1;
+ ReadAll();
+ for (int n = 0; n < 6; n++)
+ {
+ SetState((n + WM_BUTTON1), n == m_choiceIndex);
+ }
+ SetEnable(WM_BUTTON20, GetState(m_choiceIndex + WM_BUTTON1));
+ }
+ //if (message == WM_BUTTON20 && )
+ }
+ if (m_phase == WM_PHASE_SETUP || m_phase == WM_PHASE_SETUPp)
+ {
+ int volume = m_pSound->GetAudioVolume();
+ int midi = m_pSound->GetMidiVolume();
+ if (message == WM_BUTTON1)
+ {
+ if (volume > 0)
+ m_pSound->SetAudioVolume(volume - 1);
+ }
+ if (message == WM_BUTTON2)
+ {
+ if (volume < 20)
+ m_pSound->SetAudioVolume(volume + 1);
+ }
+ if (message == WM_BUTTON3)
+ {
+ if (midi > 0)
+ {
+ m_pSound->SetMidiVolume(midi - 1);
+ m_pSound->SuspendMusic();
+ }
+ }
+ if (message == WM_BUTTON4)
+ {
+ if (midi < 20)
+ {
+ m_pSound->SetMidiVolume(volume + 1);
+ m_pSound->SuspendMusic();
+ }
+ }
+ if (message == WM_BUTTON5 && m_pPixmap->GetTrueColorBack())
+ {
+ m_pPixmap->SetTrueColorBack(0);
+ SetState(WM_BUTTON5, 1);
+ SetState(WM_BUTTON6, 0);
+ }
+ if (message == WM_BUTTON6 && !m_pPixmap->GetTrueColorBack())
+ {
+ m_pPixmap->SetTrueColorBack(1);
+ SetState(WM_BUTTON5, 0);
+ SetState(WM_BUTTON6, 1);
+ }
+ if (message == WM_BUTTON13 && m_pPixmap->GetTrueColorDecor())
+ {
+ m_pPixmap->SetTrueColorDecor(0);
+ SetState(WM_BUTTON13, 1);
+ SetState(WM_BUTTON14, 0);
+ }
+ if (message == WM_BUTTON14 && !m_pPixmap->GetTrueColorDecor())
+ {
+ m_pPixmap->SetTrueColorDecor(1);
+ SetState(WM_BUTTON13, 0);
+ SetState(WM_BUTTON14, 1);
+ }
+ }
+}
+
+BOOL CEvent::ClearGamer(int gamer)
+{
+ char filename[260];
+
+ m_playerIndex = 0;
+ sprintf(filename, "data\\info%.3d.blp", gamer);
+ AddUserPath(filename);
+ remove(filename);
+ return TRUE;
+}
+
+BOOL CEvent::CheckWorld1()
+{
+#if _CD
+ FILE* file;
+ char buf[260];
+
+ strcpy(buf, "data\\world001.blp");
+ AddCDPath(buf);
+ file = fopen(buf, "rb");
+ if (file)
+ {
+ fclose(file);
+ return TRUE;
+ }
+ return FALSE;
+#else
+ return TRUE;
+#endif
+}
+
+int CEvent::GameSave(int save)
+{
+ char buffer[100];
+
+ if (m_pDecor->CurrentWrite(m_gamer, save, TRUE))
+ {
+ //LoadString()
+ m_pDecor->NotifPush(buffer);
+ m_quicksaveIndex = save;
+ return 1;
+ }
+ return m_pDecor->CurrentWrite(m_gamer, save, TRUE);
+}
+
+BOOL CEvent::CopyMission(char *srcFileName, char *dstFileName)
+{
+ FILE *srcFile = NULL;
+ FILE *destFile = NULL;
+ size_t num;
+ BOOL bOK = TRUE;
+ void *buffer = malloc(2560);
+
+ if (buffer)
+ {
+ srcFile = fopen(srcFileName, "rb");
+ if (!srcFile) goto die;
+ destFile = fopen(dstFileName, "wb");
+ if (destFile)
+ {
+
+#if _LEGACY && defined(_IOERR)
+ // original code relies on implementation-specific behavior.
+ // incompatible with modern toolsets.
+ do
+ {
+ num = fread(buffer, 1, 2560, srcFile);
+ if (srcFile->_flag & _IOERR) break;
+ if (num <= 0)
+ {
+ bOK = FALSE;
+ break;
+ }
+ fwrite(buffer, 1, num, destFile);
+ } while (!(destFile->_flag & _IOERR));
+#else
+ do
+ {
+ num = fread(buffer, 1, 2560, srcFile);
+ if (ferror(srcFile)) break; // *
+ if (num <= 0)
+ {
+ bOK = FALSE;
+ break;
+ }
+ fwrite(buffer, 1, num, destFile);
+ } while (!ferror(destFile)); // *
+#endif // _LEGACY
+
+ }
+ }
+ if (srcFile) fclose(srcFile);
+die:
+ if (destFile) fclose(destFile);
+ if (buffer) free(buffer);
+ return bOK;
+
+}
+
+void CEvent::DrawMap()
+{
+ // TODO
+}
+
+void CEvent::NetAdjustLobbyButtons()
+{
+ // TODO
+}
+
+BOOL CEvent::CurrentRead(int rank)
+{
+ char buf[100];
+ int mission;
+ BOOL bPrivate;
+
+ if (m_pDecor->CurrentRead(m_gamer, rank, &mission, &bPrivate))
+ {
+ m_bPrivate = bPrivate;
+ SetMission(mission);
+ m_quicksaveIndex = rank;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL CEvent::CurrentWrite(int rank)
+{
+ char buf[100];
+ if (m_pDecor->CurrentWrite(m_gamer, rank))
+ {
+ LoadString(0x120u, buf, 100);
+ m_pDecor->NotifPush(buf);
+ m_quicksaveIndex = rank;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+// Passe les images d'introduction.
+
+void CEvent::IntroStep()
+{
+ m_introTime++;
+
+ if (m_introTime > 20 * 3)
+ {
+ if (m_phase == WM_PHASE_INTRO1)
+ {
+ ChangePhase(WM_PHASE_INTRO2);
+ return;
+ }
+
+ if (m_phase == WM_PHASE_INTRO2)
+ {
+ ChangePhase(WM_PHASE_INIT);
+ return;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/event.h b/src/event.h
new file mode 100644
index 0000000..a3f4599
--- /dev/null
+++ b/src/event.h
@@ -0,0 +1,323 @@
+// Event.h
+#ifndef EVENT_H
+#define EVENT_H
+
+/////////////////////////////////////////////////////////////////////////////
+
+#include "movie.h"
+#include "menu.h"
+#include "button.h"
+#include "text.h"
+
+typedef struct
+{
+ UINT message;
+ int type;
+ int iconMenu[20];
+ int x, y;
+ int toolTips[20];
+}
+Button;
+
+typedef struct
+{
+ UINT phase;
+ char backName[36];
+ BOOL bCDrom;
+ BOOL bLocked;
+ Button buttons[MAXBUTTON];
+}
+Phase;
+
+typedef struct
+{
+ short majRev;
+ short minRev;
+ short bSchool;
+ short bPrivate;
+ short world;
+ short skill;
+ short reserve1[99];
+}
+DemoHeader;
+
+typedef struct
+{
+ int time;
+ short input;
+ UINT message;
+ WPARAM wParam;
+ LPARAM lParam;
+}
+DemoEvent;
+
+
+class CEvent
+{
+public:
+ CEvent();
+ ~CEvent();
+
+
+ void OutputNetDebug(const char* str);
+ POINT GetMousePos();
+ void Create(HINSTANCE hInstance, HWND hWnd, CPixmap *pPixmap, CDecor *pDecor, CSound *pSound, CNetwork *pNetwork, CMovie *pMovie );
+ void SetFullScreen(BOOL bFullScreen);
+ void SetMouseType(int mouseType);
+ int GetWorld();
+ int GetWorldGroup();
+ void SetMission(int index);
+ int GetPhysicalWorld();
+ int GetImageWorld();
+ BOOL IsHelpHide();
+ BOOL ChangePhase(UINT phase);
+ BOOL LoadImageFromDisc();
+ UINT GetPhase();
+ void MovieToStart();
+ BOOL NetworkNuggets(int fuck);
+ void HandleInputs();
+ void ReadInput();
+ void TryInsert();
+ //void SomethingUserMissions(LPCSTR lpFileName, LPCSTR thing);
+ BOOL CopyMission(char* pMission, char* pFile);
+ void RestoreGame();
+ int MissionBack();
+ void TableSomething();
+ int PlaceBuildItem(POINT cel, int flags, int currentIcon);
+
+ int GetButtonIndex(int button);
+ int GetState(int button);
+ void SetState(int button, int state);
+ BOOL GetEnable(int button);
+ void SetEnable(int button, int bEnable);
+ void SetIconMenu(int button, int bSomething);
+ BOOL GetHide(int button);
+ void SetHide(int button, BOOL bHide);
+ int GetMenu(int button);
+ void SetMenu(int button, int menu);
+ void SomethingDecor();
+ BOOL IsMouseRelease();
+
+ void NetSetPause(BOOL bPause, BOOL bMulti);
+ void NetSendLobby();
+
+ BOOL DrawButtons();
+ BOOL TextSomething();
+ int MousePosToSprite(POINT pos);
+ void MouseSprite(POINT pos);
+ void WaitMouse(BOOL bWait);
+ void HideMouse(BOOL bHide);
+ void DisableMouse(int bFill);
+ POINT GetLastMousePos();
+ BOOL TreatEvent(UINT message, WPARAM wParam, LPARAM lParam);
+ BOOL TreatEventBase(UINT message, WPARAM wParam, LPARAM lParam);
+
+ void DecorAutoShift(POINT pos);
+
+ BOOL StartMovie(char *pFilename);
+ void StopMovie();
+ BOOL IsMovie();
+
+ void FlushInput();
+
+ void SetSpeed(int speed);
+ int GetSpeed();
+ BOOL GetPause();
+ void GetDoors(int doors);
+ BOOL IsShift();
+ BOOL IsMulti();
+ BOOL IsPrivate();
+
+ void DemoStep();
+ void DebugDisplay(char m);
+
+ void IntroStep();
+ void SetNbVies(int lives);
+
+ void ReadAll();
+ BOOL SaveState(int rank);
+ void SomethingUserMissions(char* lpFilename, LPCSTR fileSomething);
+
+ BOOL ClearGamer(int gamer);
+
+protected:
+ void DrawTextCenter(int res, int x, int y, int font=0);
+ BOOL CreateButtons();
+ BOOL EventButtons(UINT message, WPARAM wParam, LPARAM lParam);
+ BOOL MouseOnButton(POINT pos);
+ int SearchPhase(UINT phase);
+ void DecorShift(int dx, int dy);
+
+ void ChangeButtons(int message);
+
+ void BuildFloor(POINT cel, int insIcon);
+ void BuildWater(POINT cel, int insIcon);
+ BOOL BuildDown(POINT pos, int fwKeys, BOOL bMix=TRUE);
+ BOOL BuildMove(POINT pos, int fwKeys);
+ BOOL BuildUp(POINT pos, int fwKeys);
+
+ void PrivateLibelle();
+ BOOL ReadLibelle(int world, BOOL bSchool, BOOL bHelp);
+ BOOL WriteInfo(int gamer);
+ BOOL ReadInfo(int gamer);
+ BOOL LoadState(BOOL save);
+ void TryPhase();
+ void UnTryPhase();
+ int GetTryPhase();
+ BOOL ReadPlayer();
+ void PutTextInputBox(POINT pos);
+
+
+ void DemoRecStart();
+ void DemoRecStop();
+ BOOL DemoPlayStart();
+ void DemoPlayStop();
+ void DemoRecEvent();
+
+ // Network Functions
+ BOOL NetCreate(int session);
+ BOOL NetEnumSessions();
+ int NetSearchPlayer(DPID dpid);
+ void NetStartPlay();
+ void NetSend(int message, USHORT data);
+ void NetDraw();
+ void ChatSend();
+ void ChatPush(char* str);
+ void ChatPop();
+ void ChatFlush();
+
+ void MouseRelease();
+ void MouseCapture();
+ int GameSave(int save);
+
+ void DrawMap();
+ BOOL CheckWorld1();
+ void NetAdjustLobbyButtons();
+
+ BOOL CurrentRead(BOOL bPrivate);
+ BOOL CurrentWrite(int rank);
+
+
+protected:
+ int m_speed;
+ int m_exercice;
+ int m_quicksaveIndex;
+ int m_mission;
+ char m_gamerName[100];
+ char m_gamerNameList[MAXGAMER][100];
+ BOOL m_gamerExist[MAXGAMER];
+ void* m_somethingJoystick;
+ int m_menuIndex;
+ int m_choiceIndex;
+ int m_saveIndex;
+ int m_menuDecor[11];
+ BOOL m_bMouseRelease;
+ int m_private;
+ int m_bNamesExist[MAXGAMER];
+ int m_fileIndex;
+ int m_maxMission;
+ int m_phase;
+ int m_index;
+ int m_playerIndex;
+ BOOL m_bSchool;
+ BOOL m_bPrivate;
+ BOOL m_bDrawMap;
+ BOOL m_bMulti;
+ BOOL m_bBuildOfficialMissions;
+ BOOL m_bFullScreen;
+ int m_mouseType;
+ HWND m_hWnd;
+ CPixmap* m_pPixmap;
+ CDecor* m_pDecor;
+ CSound* m_pSound;
+ CMovie* m_pMovie;
+ CNetwork* m_pNetwork;
+ char m_movieToStart[MAX_PATH];
+ int m_phaseAfterMovie;
+ CButton m_buttons[MAXBUTTON];
+ int m_lastFloor[MAXBUTTON];
+ int m_lastObject[MAXBUTTON];
+ int m_lastHome[MAXBUTTON];
+ BOOL m_bRunMovie;
+ BOOL m_bBuildModify;
+ CJauge m_jauges[2];
+ CMenu m_menu;
+ BOOL m_bMenu;
+ POINT m_menuPos;
+ int m_menuNb;
+ int m_menuButtons[MAXBUTTON];
+ int m_menuErrors[MAXBUTTON];
+ int m_menuPerso;
+ POINT m_menuCel;
+ POINT m_oldMousePos;
+ BOOL m_bMousePress;
+ BOOL m_bMouseDown;
+ BOOL m_bHili;
+ int m_fileWorld[10];
+ int m_fileTime[10];
+ POINT m_posToolTips;
+ char m_textToolTips[50];
+ char m_textToolTips2[50];
+ int m_mouseSprite;
+ BOOL m_bDisableMouse;
+ BOOL m_bWaitMouse;
+ BOOL m_bHideMouse;
+ BOOL m_bShowMouse;
+ int m_rankCheat;
+ int m_posCheat;
+ BOOL m_bMovie;
+ BOOL m_bSpeed;
+ BOOL m_bHelp;
+ BOOL m_bAllMissions;
+ BOOL m_bChangeCheat;
+ int m_scrollSpeed;
+ BOOL m_bPause;
+ BOOL m_bShift;
+ int m_shiftPhase;
+ POINT m_shiftVector;
+ POINT m_shiftOffset;
+ char m_libelle[1000];
+ char m_filenameBuffer[100][256];
+ int m_tryPhase;
+ int m_tryInsertCount;
+ POINT m_posInfoButton;
+ POINT m_posHelpButton;
+ BOOL m_bHiliInfoButton;
+ BOOL m_bHiliHelpButton;
+ BOOL m_bInfoHelp;
+ BOOL m_bDemoRec;
+ BOOL m_bDemoPlay;
+ DemoEvent* m_pDemoBuffer;
+ int m_demoTime;
+ int m_demoIndex;
+ int m_demoEnd;
+ int m_demoNumber;
+ BOOL m_bCtrlDown;
+ POINT m_debugPos;
+ int m_introTime;
+ int m_joyID;
+ int m_gamer;
+ int m_textHiliStart;
+ int m_textHiliEnd;
+ int m_textCursorIndex;
+ char m_textInput[100];
+ char m_pPlayerName[100];
+ int m_lives;
+ int m_multi;
+ HINSTANCE m_hInstance;
+ char m_chatZone[100][5];
+ char m_text[100];
+ int m_keyPress;
+
+ int m_choicePageOffset;
+ int m_nbChoices;
+ int m_0008;
+ int m_6D30;
+ int m_96B4;
+ int m_nbVies;
+};
+
+extern
+int DirectoryThing(LPCSTR filename);
+
+#endif
\ No newline at end of file
diff --git a/src/jauge.cpp b/src/jauge.cpp
new file mode 100644
index 0000000..f94a787
--- /dev/null
+++ b/src/jauge.cpp
@@ -0,0 +1,144 @@
+// Jauge.cpp
+//
+
+#include
+//#include
+//#include
+#include
+#include "def.h"
+#include "pixmap.h"
+#include "sound.h"
+#include "decor.h"
+#include "jauge.h"
+#include "misc.h"
+
+
+
+/////////////////////////////////////////////////////////////////
+
+// Constructor
+
+CJauge::CJauge()
+{
+ m_type = 0;
+ m_bHide = TRUE;
+ m_bMinimizeRedraw = FALSE;
+ m_bRedraw = FALSE;
+}
+
+// Destructor
+
+CJauge::~CJauge()
+{
+}
+
+// Create a new Button.
+
+BOOL CJauge::Create(HWND hWnd, CPixmap *pPixmap, CSound *pSound,
+ POINT pos, int type, BOOL bMinimizeRedraw)
+{
+ m_hWnd = hWnd;
+ m_pPixmap = pPixmap;
+ m_pSound = pSound;
+ m_type = type;
+ m_bMinimizeRedraw = bMinimizeRedraw;
+ m_bHide = TRUE;
+ m_pos = pos;
+ m_dim.x = DIMJAUGEX;
+ m_dim.y = DIMJAUGEY;
+ m_level = 0;
+ m_bRedraw = TRUE;
+ return TRUE;
+}
+
+void CJauge::Draw()
+{
+ RECT rect;
+ char num2[12];
+
+ if (m_bMinimizeRedraw && !m_bRedraw) return;
+ m_bRedraw = FALSE;
+
+ if (m_bHide) // bouton cach� ?
+ {
+ rect.right = m_dim.x + m_pos.x;
+ rect.left = m_pos.x;
+ rect.top = m_pos.y;
+ rect.bottom = m_dim.y + m_pos.y;
+ m_pPixmap->DrawPart(-1, 0, m_pos, rect, 1, FALSE);
+ return;
+ }
+ int num = m_level * 114 / 100;
+
+ *(char*)num2 = (124) / 64;
+ rect.bottom = 22;
+ rect.left = LOWORD(num2);
+ rect.top = HIWORD(num2);
+ rect.right = HIWORD(num2);
+ m_pPixmap->DrawPart(-1, 5, m_pos, rect, 0, FALSE);
+ if (num > 0)
+ {
+ rect.bottom = num + 6;
+ rect.left = m_type * 22;
+ rect.top = (m_type + 1) * 22;
+ rect.right = 0;
+ m_pPixmap->DrawPart(-1, 5, m_pos, rect, 0, FALSE);
+ }
+
+}
+
+void CJauge::Redraw()
+{
+ m_bRedraw = TRUE;
+}
+
+void CJauge::SetLevel(int level)
+{
+ if ( level < 0 ) level = 0;
+ if ( level > 100 ) level = 100;
+
+ if ( m_level != level )
+ {
+ m_bRedraw = TRUE;
+ }
+
+ m_level = level;
+}
+
+int CJauge::GetLevel()
+{
+ return m_level;
+}
+
+
+int CJauge::GetType()
+{
+ return m_type;
+}
+
+
+void CJauge::SetType(int type)
+{
+ if ( m_type != type )
+ {
+ m_bRedraw = TRUE;
+ }
+
+ m_type = type;
+}
+
+BOOL CJauge::GetHide()
+{
+ return m_bHide;
+}
+
+void CJauge::SetHide(BOOL bHide)
+{
+ if ( m_bHide != bHide )
+ {
+ m_bRedraw = TRUE;
+ }
+
+ m_bHide = bHide;
+}
+
diff --git a/src/jauge.h b/src/jauge.h
new file mode 100644
index 0000000..780fe88
--- /dev/null
+++ b/src/jauge.h
@@ -0,0 +1,47 @@
+// Jauge.h
+#ifndef JAUGE_H
+#define JAUGE_H
+
+//////////////////////////////////////////////////////////////////////////
+
+#include "pixmap.h"
+#include "sound.h"
+
+class CJauge
+{
+public:
+ CJauge();
+ ~CJauge();
+
+ BOOL Create(HWND hWnd, CPixmap *pPixmap, CSound *pSound,
+ POINT pos, int type, BOOL bMinimizeRedraw);
+ void Draw();
+ void Redraw();
+
+ void SetLevel(int level);
+ int GetLevel();
+ void SetType(int type);
+ int GetType();
+
+ BOOL GetHide();
+ void SetHide(BOOL bHide);
+
+ POINT GetPos();
+ void SetRedraw();
+
+protected:
+ HWND m_hWnd;
+ CPixmap* m_pPixmap;
+ CSound* m_pSound;
+ BOOL m_bHide;
+ POINT m_pos;
+ POINT m_dim;
+ int m_type;
+ int m_level;
+ BOOL m_bMinimizeRedraw;
+ BOOL m_bRedraw;
+};
+
+/////////////////////////////////////////////////////////////////////////
+
+#endif
\ No newline at end of file
diff --git a/src/menu.cpp b/src/menu.cpp
new file mode 100644
index 0000000..753d71d
--- /dev/null
+++ b/src/menu.cpp
@@ -0,0 +1,158 @@
+// Menu.cpp
+//
+
+#include
+#include
+#include
+#include
+#include "def.h"
+#include "resource.h"
+#include "pixmap.h"
+#include "sound.h"
+#include "decor.h"
+#include "button.h"
+#include "menu.h"
+#include "text.h"
+#include "misc.h"
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+#define MARGMENU 0
+
+
+static short table_button_icon[] =
+{
+ 24, // go
+ 40, // stop
+ 32, // mange
+ 30, // carry
+ 31, // depose
+ 22, // abat
+ 27, // roc
+ 28, // cultive
+ 19, // build1 (cabane)
+ 25, // build2 (couveuse)
+ 35, // build3 (laboratoire)
+ 61, // build4 (mine)
+ 59, // build5 (usine)
+ 101, // build6 (t�l�porteur)
+ 20, // mur
+ 26, // palis
+ 42, // abat n
+ 43, // roc n
+ 23, // pont
+ 33, // tour
+ 34, // boit
+ 39, // labo
+ 54, // fleur
+ 55, // fleur n
+ 41, // dynamite
+ 58, // bateau
+ 60, // djeep
+ 64, // drapeau
+ 62, // extrait du fer
+ 65, // fabrique jeep
+ 63, // fabrique mine
+ 83, // fabrique disciple
+ 100, // repeat
+ 107, // qarmure
+ 106, // fabarmure
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+CMenu::CMenu()
+{
+ m_nbButtons = 0;
+ m_selRank = -1;
+}
+
+CMenu::~CMenu()
+{
+}
+
+void CMenu::Delete()
+{
+ m_nbButtons = 0;
+ m_selRank = -1;
+}
+
+BOOL CMenu::TreatEvent(UINT message, WPARAM wParam, LPARAM lParam)
+{
+ POINT pos;
+
+ if ( m_nbButtons == 0 ) return FALSE;
+
+ pos = ConvLongToPos(lParam);
+
+ switch( message )
+ {
+ case WM_LBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ if ( MouseDown(pos) ) return TRUE;
+ break;
+
+ case WM_MOUSEMOVE:
+ if ( MouseMove(pos) ) return TRUE;
+ break;
+ case WM_LBUTTONUP:
+ case WM_RBUTTONUP:
+ if ( MouseUp(pos) ) return TRUE;
+ break;
+ }
+
+ return FALSE;
+}
+
+int CMenu::Detect(POINT pos)
+{
+ int rank;
+
+ if ( pos.x < m_pos.x || pos.x > m_pos.x+m_dim.x ||
+ pos.y < m_pos.y || pos.y > m_pos.y+m_dim.y ) return -1;
+
+ rank = (pos.y-m_pos.y)/(DIMBUTTONY+MARGMENU);
+ rank += ((pos.x-m_pos.x)/(DIMBUTTONX+MARGMENU))*m_nbCel.y;
+
+ if ( rank >= m_nbButtons ) return -1;
+ return rank;
+}
+
+BOOL CMenu::MouseDown(POINT pos)
+{
+ return FALSE;
+}
+
+BOOL CMenu::MouseMove(POINT pos)
+{
+ m_mousePos = pos;
+ m_selRank = Detect(pos);
+
+ if ( pos.x < m_pos.x-(DIMBUTTONX+MARGMENU) ||
+ pos.x > m_pos.x+m_dim.x+(DIMBUTTONX+MARGMENU) ||
+ pos.y < m_pos.y-(DIMBUTTONY+MARGMENU) ||
+ pos.y > m_pos.y+m_dim.y+(DIMBUTTONY+MARGMENU) )
+ {
+ Delete(); // enl�ve le menu si souris trop loin !
+ }
+
+ return FALSE;
+}
+
+BOOL CMenu::MouseUp(POINT pos)
+{
+ m_mousePos = pos;
+ m_selRank = Detect(pos);
+
+ return FALSE;
+}
+
+void CMenu::Message()
+{
+ if ( m_selRank != -1 )
+ {
+ PostMessage(m_hWnd, WM_BUTTON0+m_selRank, 0, 0);
+ }
+}
diff --git a/src/menu.h b/src/menu.h
new file mode 100644
index 0000000..8c21a79
--- /dev/null
+++ b/src/menu.h
@@ -0,0 +1,53 @@
+// Menu.h
+#ifndef MENU_H
+#define MENU_H
+
+#include "decor.h"
+#include "pixmap.h"
+
+//////////////////////////////////////////////////////////////////////
+
+class CMenu
+{
+public:
+ CMenu();
+ ~CMenu();
+
+ BOOL Create(HWND hWnd, CPixmap *pPixmap, CSound *pSound,
+ POINT pos, int nbm, int *pButtons, int *pErrors,
+ int perso);
+ void Update(int nb, int *pButtons, int *pErrors);
+ void Delete();
+ void Draw();
+ int GetSel();
+ int GetRank();
+ BOOL IsError();
+ BOOL IsExist();
+ void Message();
+
+ BOOL TreatEvent(UINT message, WPARAM wParam, LPARAM lPararm);
+
+protected:
+ int Detect(POINT pos);
+ BOOL MouseDown(POINT pos);
+ BOOL MouseMove(POINT pos);
+ BOOL MouseUp(POINT pos);
+
+protected:
+ HWND m_hWnd;
+ CPixmap* m_pPixmap;
+ CDecor* m_pDecor;
+ CSound* m_pSound;
+ POINT m_pos;
+ POINT m_dim;
+ int m_nbButtons;
+ POINT m_nbCel;
+ int m_perso;
+ int m_buttons[MAXBUTTON];
+ int m_errors[MAXBUTTON];
+ UINT m_messages[MAXBUTTON];
+ int m_selRank;
+ POINT m_mousePos;
+};
+
+#endif
\ No newline at end of file
diff --git a/src/misc.cpp b/src/misc.cpp
new file mode 100644
index 0000000..9a4af20
--- /dev/null
+++ b/src/misc.cpp
@@ -0,0 +1,345 @@
+// Misc.cpp
+//
+
+#include
+#include
+#include
+#include
+#include "def.h"
+
+// Global Variables
+
+HINSTANCE g_hInstance;
+int g_lastSprite = 0;
+extern BOOL g_bFullScreen;
+extern int g_mouseType;
+extern char g_CDPath[MAX_PATH];
+
+//Initalize HInstance.
+
+void InitHInstance(HINSTANCE hInstance)
+{
+ g_hInstance = hInstance;
+}
+
+void OutputDebug(const char *pMessage)
+{
+#ifdef _DEBUG
+ OutputDebugString(pMessage);
+#endif
+}
+
+void LoadString(UINT nID, char *pBuffer, int lgBuffer)
+{
+ LoadString(g_hInstance, nID, pBuffer, lgBuffer);
+}
+
+void ChangeSprite(int sprite)
+{
+ HCURSOR hCursor = NULL;
+
+ if ( g_mouseType == MOUSETYPEGRA ) return;
+ if ( g_lastSprite == sprite ) return;
+
+ if ( sprite == SPRITE_ARROW ) hCursor = LoadCursorA(g_hInstance, "IDC_ARROW");
+ if ( sprite == SPRITE_POINTER ) hCursor = LoadCursorA(g_hInstance, "IDC_POINTER");
+ if ( sprite == SPRITE_ARROWU ) hCursor = LoadCursorA(g_hInstance, "IDC_ARROWU");
+ if ( sprite == SPRITE_ARROWD ) hCursor = LoadCursorA(g_hInstance, "IDC_ARROWD");
+ if ( sprite == SPRITE_ARROWL ) hCursor = LoadCursorA(g_hInstance, "IDC_ARROWL");
+ if ( sprite == SPRITE_ARROWR ) hCursor = LoadCursorA(g_hInstance, "IDC_ARROWR");
+ if ( sprite == SPRITE_ARROWUL ) hCursor = LoadCursorA(g_hInstance, "IDC_ARROWUL");
+ if ( sprite == SPRITE_ARROWUR ) hCursor = LoadCursorA(g_hInstance, "IDC_ARROWUR");
+ if ( sprite == SPRITE_ARROWDL ) hCursor = LoadCursorA(g_hInstance, "IDC_ARROWDL");
+ if ( sprite == SPRITE_ARROWDR ) hCursor = LoadCursorA(g_hInstance, "IDC_ARROWDR");
+ if ( sprite == SPRITE_WAIT ) hCursor = LoadCursorA(g_hInstance, "IDC_WAIT");
+ if ( sprite == SPRITE_EMPTY ) hCursor = LoadCursorA(g_hInstance, "IDC_EMPTY");
+ SetCursor(hCursor);
+
+ g_lastSprite = sprite;
+}
+
+POINT ConvLongToPos(LPARAM lParam)
+{
+ POINT pos;
+
+ pos.x = LOWORD(lParam);
+ pos.y = HIWORD(lParam);
+
+ return pos;
+}
+
+void InitRandom()
+{
+ srand(1);
+}
+
+int Random(int min, int max)
+{
+ long n;
+
+ n = rand();
+ n = min+(n%(max-min+1));
+
+ return (int)n;
+}
+
+void GetCurrentDir(char *pName, int lg)
+{
+ int i;
+
+ strncpy(pName, _pgmptr, lg-1);
+ pName[lg-1] = 0;
+
+ lg = strlen(pName);
+ if ( lg == 0 ) return;
+
+ for ( i=0 ; i 0 )
+ {
+ lg --;
+ if ( pName[lg] == '\\' )
+ {
+ pName[lg+1] = 0;
+ break;
+ }
+ }
+
+ if ( lg > 6 && strcmp(pName+lg-6, "\\debug\\") == 0 )
+ {
+ pName[lg-5] = 0; // ignore le dossier \debug !
+ }
+}
+
+void AddCDPath(char *pFilename)
+{
+ char temp[MAX_PATH];
+ int lg;
+ BOOL bDaniel = FALSE;
+
+ if ( g_CDPath[0] == 0 ) return;
+
+ lg = strlen(g_CDPath);
+ if ( lg > 14 && strstr(g_CDPath+lg-14, "\\daniel\\blupi\\") )
+ {
+ bDaniel = TRUE;
+ }
+
+#if _DEMO
+ strcpy(temp, g_CDPath);
+ strcat(temp, pFilename);
+#else
+ if ( !bDaniel &&
+ (strstr(pFilename, "image08\\") == pFilename ||
+ strstr(pFilename, "data\\") == pFilename ||
+ strstr(pFilename, "image16\\") == pFilename ||
+ strstr(pFilename, "sound\\")) )
+ {
+ strcpy(temp, g_CDPath);
+ strcat(temp, "..\\");
+ strcat(temp, pFilename);
+ }
+ else
+ {
+ strcpy(temp, g_CDPath);
+ strcat(temp, pFilename);
+ }
+#endif
+ strcpy(pFilename, temp);
+}
+
+void AddUserPath(char *pFilename)
+{
+#if _CD || _LEGACY
+ char temp[MAX_PATH];
+ char* pText;
+ int pos;
+ char last;
+ SECURITY_ATTRIBUTES att;
+
+ if ( g_CDPath[0] != 0 ) return;
+
+
+
+ strcpy(temp, "c:\\Speedy Blupi\\");
+
+ att.nLength = sizeof(SECURITY_ATTRIBUTES);
+ att.lpSecurityDescriptor = NULL;
+ att.bInheritHandle = FALSE;
+ CreateDirectory(temp, &att);
+
+ pText = strstr(pFilename, "\\");
+ if ( pText != NULL )
+ {
+ pos = strlen(temp)+(pText-pFilename)+1;
+ strcat(temp, pFilename);
+ last = temp[pos];
+ temp[pos] = 0;
+ CreateDirectoryA(temp, &att);
+ temp[pos] = last;
+ }
+ else
+ {
+ strcat(temp, pFilename);
+ }
+
+ strcpy(pFilename, temp);
+#endif
+}
+
+void TraceErrorDD(HRESULT hErr, const char *sFile, int nLine)
+{
+ char dderr[256];
+ char err[1024];
+
+ switch (hErr)
+ {
+ case DD_OK : sprintf(dderr, "DD_OK"); break;
+ case DDERR_ALREADYINITIALIZED : sprintf(dderr, "DDERR_ALREADYINITIALIZED"); break;
+ case DDERR_CANNOTATTACHSURFACE : sprintf(dderr, "DDERR_CANNOTATTACHSURFACE"); break;
+ case DDERR_CANNOTDETACHSURFACE : sprintf(dderr, "DDERR_CANNOTDETACHSURFACE"); break;
+ case DDERR_CURRENTLYNOTAVAIL : sprintf(dderr, "DDERR_CURRENTLYNOTAVAIL"); break;
+ case DDERR_EXCEPTION : sprintf(dderr, "DDERR_EXCEPTION"); break;
+ case DDERR_GENERIC : sprintf(dderr, "DDERR_GENERIC"); break;
+ case DDERR_HEIGHTALIGN : sprintf(dderr, "DDERR_HEIGHTALIGN"); break;
+ case DDERR_INCOMPATIBLEPRIMARY : sprintf(dderr, "DDERR_INCOMPATIBLEPRIMARY"); break;
+ case DDERR_INVALIDCAPS : sprintf(dderr, "DDERR_INVALIDCAPS"); break;
+ case DDERR_INVALIDCLIPLIST : sprintf(dderr, "DDERR_INVALIDCLIPLIST"); break;
+ case DDERR_INVALIDMODE : sprintf(dderr, "DDERR_INVALIDMODE"); break;
+ case DDERR_INVALIDOBJECT : sprintf(dderr, "DDERR_INVALIDOBJECT"); break;
+ case DDERR_INVALIDPARAMS : sprintf(dderr, "DDERR_INVALIDPARAMS"); break;
+ case DDERR_INVALIDPIXELFORMAT : sprintf(dderr, "DDERR_INVALIDPIXELFORMAT"); break;
+ case DDERR_INVALIDRECT : sprintf(dderr, "DDERR_INVALIDRECT"); break;
+ case DDERR_LOCKEDSURFACES : sprintf(dderr, "DDERR_LOCKEDSURFACES"); break;
+ case DDERR_NO3D : sprintf(dderr, "DDERR_NO3D"); break;
+ case DDERR_NOALPHAHW : sprintf(dderr, "DDERR_NOALPHAHW"); break;
+ case DDERR_NOCLIPLIST : sprintf(dderr, "DDERR_NOCLIPLIST"); break;
+ case DDERR_NOCOLORCONVHW : sprintf(dderr, "DDERR_NOCOLORCONVHW"); break;
+ case DDERR_NOCOOPERATIVELEVELSET : sprintf(dderr, "DDERR_NOCOOPERATIVELEVELSET"); break;
+ case DDERR_NOCOLORKEY : sprintf(dderr, "DDERR_NOCOLORKEY"); break;
+ case DDERR_NOCOLORKEYHW : sprintf(dderr, "DDERR_NOCOLORKEYHW"); break;
+ case DDERR_NODIRECTDRAWSUPPORT : sprintf(dderr, "DDERR_NODIRECTDRAWSUPPORT"); break;
+ case DDERR_NOEXCLUSIVEMODE : sprintf(dderr, "DDERR_NOEXCLUSIVEMODE"); break;
+ case DDERR_NOFLIPHW : sprintf(dderr, "DDERR_NOFLIPHW"); break;
+ case DDERR_NOGDI : sprintf(dderr, "DDERR_NOGDI"); break;
+ case DDERR_NOMIRRORHW : sprintf(dderr, "DDERR_NOMIRRORHW"); break;
+ case DDERR_NOTFOUND : sprintf(dderr, "DDERR_NOTFOUND"); break;
+ case DDERR_NOOVERLAYHW : sprintf(dderr, "DDERR_NOOVERLAYHW"); break;
+ case DDERR_NORASTEROPHW : sprintf(dderr, "DDERR_NORASTEROPHW"); break;
+ case DDERR_NOROTATIONHW : sprintf(dderr, "DDERR_NOROTATIONHW"); break;
+ case DDERR_NOSTRETCHHW : sprintf(dderr, "DDERR_NOSTRETCHHW"); break;
+ case DDERR_NOT4BITCOLOR : sprintf(dderr, "DDERR_NOT4BITCOLOR"); break;
+ case DDERR_NOT4BITCOLORINDEX : sprintf(dderr, "DDERR_NOT4BITCOLORINDEX"); break;
+ case DDERR_NOT8BITCOLOR : sprintf(dderr, "DDERR_NOT8BITCOLOR"); break;
+ case DDERR_NOTEXTUREHW : sprintf(dderr, "DDERR_NOTEXTUREHW"); break;
+ case DDERR_NOVSYNCHW : sprintf(dderr, "DDERR_NOVSYNCHW"); break;
+ case DDERR_NOZBUFFERHW : sprintf(dderr, "DDERR_NOZBUFFERHW"); break;
+ case DDERR_NOZOVERLAYHW : sprintf(dderr, "DDERR_NOZOVERLAYHW"); break;
+ case DDERR_OUTOFCAPS : sprintf(dderr, "DDERR_OUTOFCAPS"); break;
+ case DDERR_OUTOFMEMORY : sprintf(dderr, "DDERR_OUTOFMEMORY"); break;
+ case DDERR_OUTOFVIDEOMEMORY : sprintf(dderr, "DDERR_OUTOFVIDEOMEMORY"); break;
+ case DDERR_OVERLAYCANTCLIP : sprintf(dderr, "DDERR_OVERLAYCANTCLIP"); break;
+ case DDERR_OVERLAYCOLORKEYONLYONEACTIVE : sprintf(dderr, "DDERR_OVERLAYCOLORKEYONLYONEACTIVE"); break;
+ case DDERR_PALETTEBUSY : sprintf(dderr, "DDERR_PALETTEBUSY"); break;
+ case DDERR_COLORKEYNOTSET : sprintf(dderr, "DDERR_COLORKEYNOTSET"); break;
+ case DDERR_SURFACEALREADYATTACHED : sprintf(dderr, "DDERR_SURFACEALREADYATTACHED"); break;
+ case DDERR_SURFACEALREADYDEPENDENT : sprintf(dderr, "DDERR_SURFACEALREADYDEPENDENT"); break;
+ case DDERR_SURFACEBUSY : sprintf(dderr, "DDERR_SURFACEBUSY"); break;
+ case DDERR_CANTLOCKSURFACE : sprintf(dderr, "DDERR_CANTLOCKSURFACE"); break;
+ case DDERR_SURFACEISOBSCURED : sprintf(dderr, "DDERR_SURFACEISOBSCURED"); break;
+ case DDERR_SURFACELOST : sprintf(dderr, "DDERR_SURFACELOST"); break;
+ case DDERR_SURFACENOTATTACHED : sprintf(dderr, "DDERR_SURFACENOTATTACHED"); break;
+ case DDERR_TOOBIGHEIGHT : sprintf(dderr, "DDERR_TOOBIGHEIGHT"); break;
+ case DDERR_TOOBIGSIZE : sprintf(dderr, "DDERR_TOOBIGSIZE"); break;
+ case DDERR_TOOBIGWIDTH : sprintf(dderr, "DDERR_TOOBIGWIDTH"); break;
+ case DDERR_UNSUPPORTED : sprintf(dderr, "DDERR_UNSUPPORTED"); break;
+ case DDERR_UNSUPPORTEDFORMAT : sprintf(dderr, "DDERR_UNSUPPORTEDFORMAT"); break;
+ case DDERR_UNSUPPORTEDMASK : sprintf(dderr, "DDERR_UNSUPPORTEDMASK"); break;
+ case DDERR_VERTICALBLANKINPROGRESS : sprintf(dderr, "DDERR_VERTICALBLANKINPROGRESS"); break;
+ case DDERR_WASSTILLDRAWING : sprintf(dderr, "DDERR_WASSTILLDRAWING"); break;
+ case DDERR_XALIGN : sprintf(dderr, "DDERR_XALIGN"); break;
+ case DDERR_INVALIDDIRECTDRAWGUID : sprintf(dderr, "DDERR_INVALIDDIRECTDRAWGUID"); break;
+ case DDERR_DIRECTDRAWALREADYCREATED : sprintf(dderr, "DDERR_DIRECTDRAWALREADYCREATED"); break;
+ case DDERR_NODIRECTDRAWHW : sprintf(dderr, "DDERR_NODIRECTDRAWHW"); break;
+ case DDERR_PRIMARYSURFACEALREADYEXISTS : sprintf(dderr, "DDERR_PRIMARYSURFACEALREADYEXISTS"); break;
+ case DDERR_NOEMULATION : sprintf(dderr, "DDERR_NOEMULATION"); break;
+ case DDERR_REGIONTOOSMALL : sprintf(dderr, "DDERR_REGIONTOOSMALL"); break;
+ case DDERR_CLIPPERISUSINGHWND : sprintf(dderr, "DDERR_CLIPPERISUSINGHWND"); break;
+ case DDERR_NOCLIPPERATTACHED : sprintf(dderr, "DDERR_NOCLIPPERATTACHED"); break;
+ case DDERR_NOHWND : sprintf(dderr, "DDERR_NOHWND"); break;
+ case DDERR_HWNDSUBCLASSED : sprintf(dderr, "DDERR_HWNDSUBCLASSED"); break;
+ case DDERR_HWNDALREADYSET : sprintf(dderr, "DDERR_HWNDALREADYSET"); break;
+ case DDERR_NOPALETTEATTACHED : sprintf(dderr, "DDERR_NOPALETTEATTACHED"); break;
+ case DDERR_NOPALETTEHW : sprintf(dderr, "DDERR_NOPALETTEHW"); break;
+ case DDERR_BLTFASTCANTCLIP : sprintf(dderr, "DDERR_BLTFASTCANTCLIP"); break;
+ case DDERR_NOBLTHW : sprintf(dderr, "DDERR_NOBLTHW"); break;
+ case DDERR_NODDROPSHW : sprintf(dderr, "DDERR_NODDROPSHW"); break;
+ case DDERR_OVERLAYNOTVISIBLE : sprintf(dderr, "DDERR_OVERLAYNOTVISIBLE"); break;
+ case DDERR_NOOVERLAYDEST : sprintf(dderr, "DDERR_NOOVERLAYDEST"); break;
+ case DDERR_INVALIDPOSITION : sprintf(dderr, "DDERR_INVALIDPOSITION"); break;
+ case DDERR_NOTAOVERLAYSURFACE : sprintf(dderr, "DDERR_NOTAOVERLAYSURFACE"); break;
+ case DDERR_EXCLUSIVEMODEALREADYSET : sprintf(dderr, "DDERR_EXCLUSIVEMODEALREADYSET"); break;
+ case DDERR_NOTFLIPPABLE : sprintf(dderr, "DDERR_NOTFLIPPABLE"); break;
+ case DDERR_CANTDUPLICATE : sprintf(dderr, "DDERR_CANTDUPLICATE"); break;
+ case DDERR_NOTLOCKED : sprintf(dderr, "DDERR_NOTLOCKED"); break;
+ case DDERR_CANTCREATEDC : sprintf(dderr, "DDERR_CANTCREATEDC"); break;
+ case DDERR_NODC : sprintf(dderr, "DDERR_NODC"); break;
+ case DDERR_WRONGMODE : sprintf(dderr, "DDERR_WRONGMODE"); break;
+ case DDERR_IMPLICITLYCREATED : sprintf(dderr, "DDERR_IMPLICITLYCREATED"); break;
+ case DDERR_NOTPALETTIZED : sprintf(dderr, "DDERR_NOTPALETTIZED"); break;
+ case DDERR_UNSUPPORTEDMODE : sprintf(dderr, "DDERR_UNSUPPORTEDMODE"); break;
+ case DDERR_NOMIPMAPHW : sprintf(dderr, "DDERR_NOMIPMAPHW"); break;
+ case DDERR_INVALIDSURFACETYPE : sprintf(dderr, "DDERR_INVALIDSURFACETYPE"); break;
+ case DDERR_DCALREADYCREATED : sprintf(dderr, "DDERR_DCALREADYCREATED"); break;
+ case DDERR_CANTPAGELOCK : sprintf(dderr, "DDERR_CANTPAGELOCK"); break;
+ case DDERR_CANTPAGEUNLOCK : sprintf(dderr, "DDERR_CANTPAGEUNLOCK"); break;
+ case DDERR_NOTPAGELOCKED : sprintf(dderr, "DDERR_NOTPAGELOCKED"); break;
+ case DDERR_NOTINITIALIZED : sprintf(dderr, "DDERR_NOTINITIALIZED"); break;
+
+ default : sprintf(dderr, "Unknown Error"); break;
+ }
+ sprintf(err, "DirectDraw Error %s in file %s at line %d\n", dderr, sFile, nLine);
+ OutputDebug(err);
+}
+
+//----------------------------------------------------------------------
+//
+// Function : TraceErrorDS()
+//
+// Purpose : Traces an error (DirectSound)
+//
+//----------------------------------------------------------------------
+
+void TraceErrorDS(HRESULT hErr, const char *sFile, int nLine)
+{
+ char dserr[256];
+ char err[1024];
+
+ switch (hErr)
+ {
+ case DS_OK : sprintf(dserr, "DD_OK"); break;
+ case DSERR_ALLOCATED : sprintf(dserr, "DSERR_ALLOCATED"); break;
+ case DSERR_CONTROLUNAVAIL : sprintf(dserr, "DSERR_CONTROLUNAVAIL"); break;
+ case DSERR_INVALIDPARAM : sprintf(dserr, "DSERR_INVALIDPARAM"); break;
+ case DSERR_INVALIDCALL : sprintf(dserr, "DSERR_INVALIDCALL"); break;
+ case DSERR_GENERIC : sprintf(dserr, "DSERR_GENERIC"); break;
+ case DSERR_PRIOLEVELNEEDED : sprintf(dserr, "DSERR_PRIOLEVELNEEDED"); break;
+ case DSERR_OUTOFMEMORY : sprintf(dserr, "DSERR_OUTOFMEMORY"); break;
+ case DSERR_BADFORMAT : sprintf(dserr, "DSERR_BADFORMAT"); break;
+ case DSERR_UNSUPPORTED : sprintf(dserr, "DSERR_UNSUPPORTED"); break;
+ case DSERR_NODRIVER : sprintf(dserr, "DSERR_NODRIVER"); break;
+ case DSERR_ALREADYINITIALIZED : sprintf(dserr, "DSERR_ALREADYINITIALIZED"); break;
+ case DSERR_NOAGGREGATION : sprintf(dserr, "DSERR_NOAGGREGATION"); break;
+ case DSERR_BUFFERLOST : sprintf(dserr, "DSERR_BUFFERLOST"); break;
+ case DSERR_OTHERAPPHASPRIO : sprintf(dserr, "DSERR_OTHERAPPHASPRIO"); break;
+ case DSERR_UNINITIALIZED : sprintf(dserr, "DSERR_UNINITIALIZED"); break;
+
+ default : sprintf(dserr, "Unknown Error"); break;
+ }
+ sprintf(err, "DirectSound Error %s in file %s at line %d\n", dserr, sFile, nLine);
+ OutputDebug(err);
+}
+
diff --git a/src/misc.h b/src/misc.h
new file mode 100644
index 0000000..075e202
--- /dev/null
+++ b/src/misc.h
@@ -0,0 +1,27 @@
+// misc.h
+//
+#ifndef MISC_H
+#define MISC_H
+
+#include
+
+#pragma once
+
+extern void InitHInstance(HINSTANCE hInstance);
+extern void OutputDebug(const char *pMessage);
+extern void LoadString(unsigned nID, char *pBuffer, int lgBuffer);
+extern void ChangeSprite(int sprite);
+
+extern POINT ConvLongToPos(LPARAM lParam);
+
+extern void InitRandom();
+extern int Random(int min, int max);
+
+extern void GetCurrentDir(char *pName, int lg);
+extern void AddCDPath(char *pFilename);
+extern void AddUserPath(char *pFilename);
+
+extern void TraceErrorDD(HRESULT hErr, const char *sFile, int nLine);
+extern void TraceErrorDS(HRESULT hErr, const char *sFile, int nLine);
+
+#endif
\ No newline at end of file
diff --git a/src/movie.cpp b/src/movie.cpp
new file mode 100644
index 0000000..1196e8f
--- /dev/null
+++ b/src/movie.cpp
@@ -0,0 +1,298 @@
+// movie.cpp
+//
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+// #include
+#include "def.h"
+#include "movie.h"
+#include "misc.h"
+
+//----------------------------------------------------------------------------
+
+#define AVI_VIDEO "avivideo"
+
+#define IDM_PLAY 10
+#define IDM_RPLAY 11
+
+//----------------------------------------------------------------------------
+
+// Initialize avi libraries.
+
+BOOL CMovie::initAVI()
+{
+ MCI_DGV_OPEN_PARMS mciOpen;
+
+ // set up the open parameters
+ mciOpen.dwCallback = 0L;
+ mciOpen.wDeviceID = 0;
+ mciOpen.lpstrDeviceType = AVI_VIDEO;
+ mciOpen.lpstrElementName = NULL;
+ mciOpen.lpstrAlias = NULL;
+ mciOpen.dwStyle = 0;
+ mciOpen.hWndParent = NULL;
+
+ // try to open the driver
+ return (mciSendCommand(0, MCI_OPEN, (DWORD)(MCI_OPEN_TYPE),
+ (DWORD)(LPMCI_DGV_OPEN_PARMS)&mciOpen) == 0);
+}
+
+// Closes the opened AVI file and the opened device type. |
+
+void CMovie::termAVI()
+{
+ MCIDEVICEID mciID;
+ MCI_GENERIC_PARMS mciClose;
+
+ // Get the device ID for the opened device type and then close
+ // the device type.
+ mciID = mciGetDeviceIDA(AVI_VIDEO);
+ mciSendCommand(mciID, MCI_CLOSE, 0L,
+ (DWORD)(LPMCI_GENERIC_PARMS)&mciClose);
+}
+
+
+// Sets the movie rectange to be
+// centered within the app's window.
+
+void CMovie::positionMovie(HWND hWnd, RECT rect)
+{
+ // reposition the playback (child) window
+ MoveWindow(m_hwndMovie,
+ rect.left, rect.top,
+ rect.right, rect.bottom, TRUE);
+}
+
+// Close the movie and anything associated with it. |
+// This function clears the and flags |
+
+void CMovie::fileCloseMovie(HWND hWnd)
+{
+ MCI_GENERIC_PARMS mciGeneric;
+
+ mciSendCommand(m_wMCIDeviceID, MCI_CLOSE, 0L,
+ (DWORD)(LPMCI_GENERIC_PARMS)&mciGeneric);
+
+ m_fPlaying = FALSE; // can't be playing any longer
+ m_fMovieOpen = FALSE; // no more movies open
+
+ // cause a total repaint to occur
+ InvalidateRect(hWnd, NULL, TRUE);
+ UpdateWindow(hWnd);
+}
+
+
+// Open an AVI movie. Use CommDlg open box to
+// open and then handle the initialization to
+// show the movie and position it properly. Keep
+// the movie paused when opened.
+// Sets on success.
+
+BOOL CMovie::fileOpenMovie(HWND hWnd, RECT rect, char *pFilename)
+{
+ MCI_DGV_OPEN_PARMS mciOpen;
+ MCI_DGV_WINDOW_PARMS mciWindow;
+ MCI_DGV_STATUS_PARMS mciStatus;
+ char string[MAX_PATH];
+
+ if ( pFilename[1] == ':' ) // nom complet "D:\REP..." ?
+ {
+ strcpy(string, pFilename);
+ }
+ else
+ {
+ GetCurrentDir(string, MAX_PATH-30);
+ strcat(string, pFilename);
+ }
+
+ // we got a filename, now close any old movie and open the new one. */
+ if ( m_fMovieOpen ) fileCloseMovie(hWnd);
+
+ // we have a .AVI movie to open, use MCI
+ // set up the open parameters
+ mciOpen.dwCallback = 0L;
+ mciOpen.wDeviceID = 0;
+ mciOpen.lpstrDeviceType = NULL;
+ mciOpen.lpstrElementName = string;
+ mciOpen.lpstrAlias = NULL;
+ mciOpen.dwStyle = WS_CHILD;
+ mciOpen.hWndParent = hWnd;
+
+ // try to open the file
+ if ( mciSendCommand(0, MCI_OPEN,
+ (DWORD)(MCI_OPEN_ELEMENT|MCI_DGV_OPEN_PARENT|MCI_DGV_OPEN_WS),
+ (DWORD)(LPMCI_DGV_OPEN_PARMS)&mciOpen) == 0 )
+ {
+ // we opened the file o.k., now set up to play it.
+ m_wMCIDeviceID = mciOpen.wDeviceID; // save ID
+ m_fMovieOpen = TRUE; // a movie was opened
+
+ // show the playback window
+ mciWindow.dwCallback = 0L;
+ mciWindow.hWnd = NULL;
+ mciWindow.nCmdShow = SW_SHOW;
+ mciWindow.lpstrText = NULL;
+// mciSendCommand(m_wMCIDeviceID, MCI_WINDOW,
+// MCI_DGV_WINDOW_STATE,
+// (DWORD)(LPMCI_DGV_WINDOW_PARMS)&mciWindow);
+
+ // get the window handle
+ mciStatus.dwItem = MCI_DGV_STATUS_HWND;
+ mciSendCommand(m_wMCIDeviceID,
+ MCI_STATUS, MCI_STATUS_ITEM,
+ (DWORD)(LPMCI_STATUS_PARMS)&mciStatus);
+ m_hwndMovie = (HWND)mciStatus.dwReturn;
+
+ // now get the movie centered
+ positionMovie(hWnd, rect);
+
+ // cause an update to occur
+ InvalidateRect(hWnd, NULL, FALSE);
+ UpdateWindow(hWnd);
+
+ return TRUE;
+ }
+ else
+ {
+ // generic error for open
+ m_fMovieOpen = FALSE;
+
+ return FALSE;
+ }
+}
+
+// Play/pause the movie depending on the state
+// of the flag. |
+// This function sets the flag appropriately when done|
+
+void CMovie::playMovie(HWND hWnd, int nDirection)
+{
+ m_fPlaying = !m_fPlaying; // swap the play flag
+
+ if( !nDirection )
+ m_fPlaying = FALSE; // wDirection == NULL means PAUSE
+
+ // play/pause the AVI movie
+ if ( m_fPlaying )
+ {
+ DWORD dwFlags;
+ MCI_DGV_PLAY_PARMS mciPlay;
+
+ // init to play all
+ mciPlay.dwCallback = MAKELONG(hWnd,0);
+ mciPlay.dwFrom = mciPlay.dwTo = 0;
+ dwFlags = MCI_NOTIFY;
+ if ( nDirection == IDM_RPLAY )
+ dwFlags |= MCI_DGV_PLAY_REVERSE;
+
+ mciSendCommand(m_wMCIDeviceID, MCI_PLAY, dwFlags,
+ (DWORD)(LPMCI_DGV_PLAY_PARMS)&mciPlay);
+ }
+ else
+ {
+ MCI_DGV_PAUSE_PARMS mciPause;
+
+ // tell it to pause
+ mciSendCommand(m_wMCIDeviceID,MCI_PAUSE,0L,
+ (DWORD)(LPMCI_DGV_PAUSE_PARMS)&mciPause);
+ }
+}
+
+
+//----------------------------------------------------------------------------
+
+
+// Constructeur.
+
+CMovie::CMovie()
+{
+ m_bEnable = FALSE;
+ m_wMCIDeviceID = 0;
+ m_fPlaying = FALSE;
+ m_fMovieOpen = FALSE;
+}
+
+// Destructeur.
+
+CMovie::~CMovie()
+{
+ termAVI();
+}
+
+// Ouvre la librairie avi.
+
+BOOL CMovie::Create()
+{
+#if _EGAMES
+ m_bEnable = FALSE;
+ return FALSE;
+#else
+ if ( initAVI() )
+ {
+ m_bEnable = TRUE;
+ return TRUE;
+ }
+ else
+ {
+ m_bEnable = FALSE;
+ return FALSE;
+ }
+#endif
+}
+
+// Retourne l'�tat de DirectMovie.
+
+BOOL CMovie::GetEnable()
+{
+ return m_bEnable;
+}
+
+// Indique si un film existe.
+
+BOOL CMovie::IsExist(char *pFilename)
+{
+ char string[MAX_PATH];
+ FILE* file;
+
+ if ( pFilename[1] == ':' ) // nom complet "D:\REP..." ?
+ {
+ strcpy(string, pFilename);
+ }
+ else
+ {
+ GetCurrentDir(string, MAX_PATH-30);
+ strcat(string, pFilename);
+ }
+
+ file = fopen(string, "rb");
+ if ( file == NULL ) return FALSE;
+
+ fclose(file);
+ return TRUE;
+}
+
+// Montre un film avi.
+
+BOOL CMovie::Play(HWND hWnd, RECT rect, char *pFilename)
+{
+ if ( !m_bEnable ) return FALSE;
+ if ( !fileOpenMovie(hWnd, rect, pFilename) ) return FALSE;
+ playMovie(hWnd, IDM_PLAY);
+
+ return TRUE;
+}
+
+// Stoppe le film avi.
+
+void CMovie::Stop(HWND hWnd)
+{
+ if ( !m_bEnable ) return;
+ fileCloseMovie(hWnd);
+}
diff --git a/src/movie.h b/src/movie.h
new file mode 100644
index 0000000..7025e62
--- /dev/null
+++ b/src/movie.h
@@ -0,0 +1,34 @@
+// movie.h
+//
+#ifndef MOVIE_H
+#define MOVIE_H
+
+class CMovie
+{
+public:
+ CMovie();
+ ~CMovie();
+
+ BOOL Create();
+ BOOL GetEnable();
+ BOOL IsExist(char *pFilename);
+ BOOL Play(HWND hWnd, RECT rect, char *pFilename);
+ void Stop(HWND hWnd);
+
+protected:
+ void playMovie(HWND hWnd, int nDirection);
+ BOOL fileOpenMovie(HWND hWnd, RECT rect, char *pFilename);
+ void fileCloseMovie(HWND hWnd);
+ void positionMovie(HWND hWnd, RECT rect);
+ void termAVI();
+ BOOL initAVI();
+
+protected:
+ BOOL m_bEnable;
+ MCIDEVICEID m_wMCIDeviceID;
+ HWND m_hwndMovie;
+ BOOL m_fPlaying;
+ BOOL m_fMovieOpen;
+};
+
+#endif
diff --git a/src/network.cpp b/src/network.cpp
new file mode 100644
index 0000000..4366610
--- /dev/null
+++ b/src/network.cpp
@@ -0,0 +1,354 @@
+// Network.cpp
+//
+
+#include
+#include
+#include "dplay.h"
+#include "misc.h"
+#include "network.h"
+#include "def.h"
+
+// a0f94abe-11c3-d111-be62-0040f6944838
+static const GUID APP_GUID = { 0xbe4af9a0, 0xc311, 0x11d1, { 0xbe, 0x62, 0x00, 0x40, 0xf6, 0x94, 0x48, 0x38 } };
+
+CNetwork::CNetwork()
+{
+ m_pDP = NULL;
+ m_dpid = 0;
+ m_bHost = FALSE;
+ m_providers.nb = 0;
+ m_providers.pList = NULL;
+ m_sessions.nb = 0;
+ m_sessions.pList = NULL;
+ m_unknown.nb = 0;
+ m_unknown.pList = NULL;
+}
+
+CNetwork::~CNetwork()
+{
+ FreeProviderList();
+ FreeSessionList();
+ FreeUnknownList();
+ if (m_pDP) m_pDP->Release();
+}
+
+static BOOL EnumProvidersCallback(LPGUID lpguidSP, LPSTR lpSPName,
+ DWORD dwMajorVersion, DWORD dwMinorVersion, NamedGUIDList* lpContext)
+{
+ NamedGUID* lpGuid;
+ if (lpContext->nb < MAXSESSION)
+ {
+ lpGuid = &(*lpContext->pList)[lpContext->nb];
+ lpGuid->guid = *lpguidSP;
+ strcpy(lpGuid->name, lpSPName);
+ lpContext->nb++;
+ }
+ return TRUE;
+}
+
+BOOL CNetwork::EnumProviders()
+{
+ FreeProviderList();
+ m_providers.nb = 0;
+ m_providers.pList = (NamedGUID(*)[MAXSESSION]) malloc(MAXSESSION * sizeof(NamedGUID));
+
+ if (!m_providers.pList) return FALSE;
+#ifdef _UNICODE
+ if (DirectPlayEnumerate((LPDPENUMDPCALLBACK)EnumProvidersCallback, &m_providers) != DP_OK)
+#else
+ if (DirectPlayEnumerate((LPDPENUMDPCALLBACKA)EnumProvidersCallback, &m_providers) != DP_OK)
+#endif
+ {
+ FreeProviderList();
+ return FALSE;
+ }
+ return TRUE;
+}
+
+int CNetwork::GetNbProviders()
+{
+ return m_providers.nb;
+}
+
+char* CNetwork::GetProviderName(int index)
+{
+ if (index >= m_providers.nb) return NULL;
+ return (*m_providers.pList)[index].name;
+}
+
+BOOL CNetwork::CreateProvider(int index)
+{
+ LPDIRECTPLAY lpDP;
+ BOOL bOK = FALSE;
+
+ if (index >= m_providers.nb) return FALSE;
+
+ if (DirectPlayCreate(&m_providers.pList[index]->guid, &lpDP, 0) == DP_OK)
+ {
+ if (lpDP->QueryInterface(IID_IDirectPlay2A, (LPVOID*)&m_pDP) == DP_OK)
+ {
+ return TRUE;
+ }
+ }
+
+ if (lpDP) lpDP->Release();
+ return FALSE;
+}
+
+void CNetwork::FreeProviderList()
+{
+ if (m_providers.pList) free(m_providers.pList);
+
+ m_providers.nb = 0;
+ m_providers.pList = NULL;
+}
+
+
+static BOOL EnumSessionsCallback(LPDPSESSIONDESC2 lpThisSD,
+ LPDWORD lpdwTimeOut, DWORD dwFlags, NamedGUIDList* lpContext)
+{
+ NamedGUID* lpGuid;
+ if (dwFlags & DPESC_TIMEDOUT) return FALSE;
+
+ if (lpContext->nb < MAXSESSION)
+ {
+ lpGuid = &(*lpContext->pList)[lpContext->nb];
+ lpGuid->guid = lpThisSD->guidInstance;
+ strcpy(lpGuid->name, lpThisSD->lpszSessionNameA);
+ lpContext->nb++;
+ }
+ return TRUE;
+}
+
+BOOL CNetwork::EnumSessions()
+{
+ DPSESSIONDESC2 desc;
+
+ FreeSessionList();
+ m_sessions.nb = 0;
+ m_sessions.pList = (NamedGUID(*)[MAXSESSION]) malloc(MAXSESSION * sizeof(NamedGUID));
+
+ if (!m_sessions.pList) return FALSE;
+
+ ZeroMemory(&desc, sizeof(desc));
+
+ desc.guidApplication = APP_GUID;
+ desc.dwSize = sizeof(desc);
+
+ if (m_pDP->EnumSessions(&desc, 0, (LPDPENUMSESSIONSCALLBACK2)EnumSessionsCallback, &m_sessions, DPENUMSESSIONS_AVAILABLE) != DP_OK)
+ {
+ FreeSessionList();
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+int CNetwork::GetNbSessions()
+{
+ return m_sessions.nb;
+}
+
+char* CNetwork::GetSessionName(int index)
+{
+ if (index >= m_sessions.nb) return NULL;
+ return (*m_sessions.pList)[index].name;
+}
+
+BOOL CNetwork::JoinSession(int index, char* pPlayerName)
+{
+ DPNAME name;
+ DPSESSIONDESC2 desc;
+ HRESULT hr;
+
+ if (index > m_sessions.nb) return FALSE;
+
+ ZeroMemory(&desc, sizeof(desc));
+
+ desc.guidInstance = m_sessions.pList[index]->guid;
+
+ hr = m_pDP->Open(&desc, DPOPEN_OPENSESSION);
+ if (hr != DP_OK)
+ {
+ TraceErrorDP(hr);
+ return FALSE;
+ }
+
+ name.dwSize = sizeof(name);
+ name.dwFlags = 0;
+ name.lpszShortNameA = pPlayerName;
+ name.lpszLongNameA = NULL;
+ hr = m_pDP->CreatePlayer(&m_dpid, &name, NULL, NULL, 0, 0);
+ if (hr != DP_OK)
+ {
+ TraceErrorDP(hr);
+ m_pDP->Close();
+ return FALSE;
+ }
+ else
+ {
+ m_bHost = FALSE;
+ return TRUE;
+ }
+}
+
+void CNetwork::FreeSessionList()
+{
+ if (m_sessions.pList) free(m_sessions.pList);
+
+ m_sessions.nb = 0;
+ m_sessions.pList = NULL;
+}
+
+BOOL CNetwork::CreateSession(char* pSessionName, char* pPlayerName)
+{
+ DPNAME name;
+ DPSESSIONDESC2 desc;
+ HRESULT hr;
+
+ ZeroMemory(&desc, sizeof(desc));
+
+ desc.guidApplication = APP_GUID;
+ desc.lpszSessionNameA = pSessionName;
+ desc.dwSize = sizeof(desc);
+ desc.dwFlags = DPSESSION_KEEPALIVE | DPSESSION_MIGRATEHOST;
+ desc.dwMaxPlayers = MAXNETPLAYER;
+
+ hr = m_pDP->Open(&desc, DPOPEN_CREATE);
+ if (hr != DP_OK)
+ {
+ TraceErrorDP(hr);
+ return FALSE;
+ }
+ else
+ {
+ name.dwSize = sizeof(name);
+ name.dwFlags = 0;
+ name.lpszShortNameA = pPlayerName;
+ name.lpszLongNameA = NULL;
+ hr = m_pDP->CreatePlayer(&m_dpid, &name, NULL, NULL, 0, 0);
+ if (hr != DP_OK)
+ {
+ TraceErrorDP(hr);
+ m_pDP->Close();
+ return FALSE;
+ }
+ else
+ {
+ m_bHost = TRUE;
+ return TRUE;
+ }
+ }
+}
+
+BOOL CNetwork::Send(LPVOID lpData, DWORD dwDataSize, DWORD dwFlags)
+{
+ HRESULT hr;
+
+ if (!m_pDP) return FALSE;
+
+ if (hr = m_pDP->Send(m_dpid, 0, !!dwFlags, lpData, dwDataSize), hr != DP_OK)
+ {
+ TraceErrorDP(hr);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+BOOL CNetwork::Receive(LPVOID pDest, DWORD dwDataSize, LPDWORD lpdwPlayer)
+{
+ DPID from = 0, to = 0;
+ DWORD dataSize = 500;
+ char dataBuffer[500];
+ HRESULT hr;
+
+ hr = m_pDP->Receive(&from, &to, DPRECEIVE_ALL, dataBuffer, &dataSize);
+ if (hr != DP_OK)
+ {
+ if (hr != DPERR_NOMESSAGES) TraceErrorDP(hr);
+ return FALSE;
+ }
+
+ ZeroMemory(pDest, dwDataSize);
+
+ *lpdwPlayer = -1;
+ for (int i = 0; i < MAXNETPLAYER; i++)
+ {
+ if (m_players[i].bIsPresent && from == i)
+ {
+ *lpdwPlayer = i;
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+BOOL CNetwork::Close()
+{
+ return m_pDP->Close() == DP_OK;
+}
+
+void CNetwork::FreeUnknownList()
+{
+ if (m_unknown.pList) free(m_unknown.pList);
+
+ m_unknown.nb = 0;
+ m_unknown.pList = NULL;
+}
+
+BOOL CNetwork::IsHost()
+{
+ return m_bHost;
+}
+
+void TraceErrorDP(HRESULT hErr)
+{
+ char dperr[256];
+ char err[1024];
+
+ switch (hErr)
+ {
+ case DPERR_OUTOFMEMORY: sprintf(dperr, "DPERR_OUTOFMEMORY"); break;
+ case DPERR_UNSUPPORTED: sprintf(dperr, "DPERR_UNSUPPORTED"); break;
+ case DPERR_NOINTERFACE: sprintf(dperr, "DPERR_NOINTERFACE"); break;
+ case DPERR_GENERIC: sprintf(dperr, "DPERR_GENERIC"); break;
+ case DPERR_INVALIDPARAMS: sprintf(dperr, "DPERR_INVALIDPARAMS"); break;
+ case DPERR_ACTIVEPLAYERS: sprintf(dperr, "DPERR_ACTIVEPLAYERS"); break;
+ case DPERR_ACCESSDENIED: sprintf(dperr, "DPERR_ACCESSDENIED"); break;
+ case DPERR_CANTADDPLAYER: sprintf(dperr, "DPERR_CANTADDPLAYER"); break;
+ case DPERR_CANTCREATEPLAYER: sprintf(dperr, "DPERR_CANTCREATEPLAYER"); break;
+ case DPERR_CANTCREATEGROUP: sprintf(dperr, "DPERR_CANTCREATEGROUP"); break;
+ case DPERR_CANTCREATESESSION: sprintf(dperr, "DPERR_CANTCREATESESSION"); break;
+ case DPERR_CAPSNOTAVAILABLEYET: sprintf(dperr, "DPERR_CAPTSNOTAVAILABLEYET"); break;
+ case DPERR_ALREADYINITIALIZED: sprintf(dperr, "DPERR_ALREADYINITIALIZED"); break;
+ case DPERR_INVALIDFLAGS: sprintf(dperr, "DPERR_INVALIDFLAGS"); break;
+ case DPERR_EXCEPTION: sprintf(dperr, "DPERR_EXCEPTION"); break;
+ case DPERR_INVALIDPLAYER: sprintf(dperr, "DPERR_INVALIDPLAYER"); break;
+ case DPERR_INVALIDOBJECT: sprintf(dperr, "DPERR_INVALIDOBJECT"); break;
+ case DPERR_NOCONNECTION: sprintf(dperr, "DPERR_NOCONNECTION"); break;
+ case DPERR_NONAMESERVERFOUND: sprintf(dperr, "DPERR_NONAMESERVERFOUND"); break;
+ case DPERR_NOMESSAGES: sprintf(dperr, "DPERR_NOMESSAGES"); break;
+ case DPERR_NOSESSIONS: sprintf(dperr, "DPERR_NOSESSIONS"); break;
+ case DPERR_NOPLAYERS: sprintf(dperr, "DPERR_NOPLAYERS"); break;
+ case DPERR_TIMEOUT: sprintf(dperr, "DPERR_TIMEOUT"); break;
+ case DPERR_SENDTOOBIG: sprintf(dperr, "DPERR_SENDTOOBIG"); break;
+ case DPERR_BUSY: sprintf(dperr, "DPERR_BUSY"); break;
+ case DPERR_UNAVAILABLE: sprintf(dperr, "DPERR_UNAVAILABLE"); break;
+ case DPERR_PLAYERLOST: sprintf(dperr, "DPERR_PLAYERLOST"); break;
+ case DPERR_USERCANCEL: sprintf(dperr, "DPERR_USERCANCEL"); break;
+ case DPERR_BUFFERTOOLARGE: sprintf(dperr, "DPERR_BUFFERTOOLARGE"); break;
+ case DPERR_SESSIONLOST: sprintf(dperr, "DPERR_SESSIONLOST"); break;
+ case DPERR_APPNOTSTARTED: sprintf(dperr, "DPERR_APPNOTSTARTED"); break;
+ case DPERR_CANTCREATEPROCESS: sprintf(dperr, "DPERR_CANTCREATEPROCESS"); break;
+ case DPERR_UNKNOWNAPPLICATION: sprintf(dperr, "DPERR_UNKNOWNAPPLICATION"); break;
+ case DPERR_INVALIDINTERFACE: sprintf(dperr, "DPERR_INVALIDINTERFACE"); break;
+ case DPERR_NOTLOBBIED: sprintf(dperr, "DPERR_NOTLOBBIED"); break;
+ case DP_OK: sprintf(dperr, "DP_OK"); break;
+
+ default: sprintf(dperr, "Unknown Error"); break;
+ }
+ sprintf(err, "DirectPlay Error %s\n", dperr);
+ OutputDebug(err);
+}
\ No newline at end of file
diff --git a/src/network.h b/src/network.h
new file mode 100644
index 0000000..afb4b44
--- /dev/null
+++ b/src/network.h
@@ -0,0 +1,79 @@
+// Network.h
+
+#ifndef NETWORK_H
+#define NETWORK_H
+
+#include "dplay.h"
+#include "def.h"
+
+/////////////////////////////////////////////////////////////////////////////
+
+typedef struct
+{
+ char bIsPresent;
+ char ready;
+ char unk_2;
+ char unk_3;
+ DPID dpid;
+ short team;
+ char name[22];
+}
+NetPlayer;
+
+typedef struct
+{
+ GUID guid;
+ char name[100];
+}
+NamedGUID;
+
+typedef struct
+{
+ int nb;
+ NamedGUID (*pList)[MAXSESSION];
+}
+NamedGUIDList;
+
+class CNetwork
+{
+public:
+ CNetwork();
+ ~CNetwork();
+
+ BOOL EnumProviders();
+ int GetNbProviders();
+ char* GetProviderName(int index);
+ BOOL CreateProvider(int index);
+ void FreeProviderList();
+ BOOL EnumSessions();
+ int GetNbSessions();
+ char* GetSessionName(int index);
+ BOOL JoinSession(int index, char* pPlayerName);
+ void FreeSessionList();
+ BOOL CreateSession(char* pSessionName, char* pPlayerName);
+ BOOL Send(LPVOID lpData, DWORD dwDataSize, DWORD dwFlags);
+ BOOL Receive(LPVOID pDest, DWORD dwDataSize, LPDWORD lpdwPlayer);
+ BOOL Close();
+ void FreeUnknownList();
+ BOOL IsHost();
+
+ NetPlayer m_players[MAXNETPLAYER];
+ DPID m_dpid;
+
+protected:
+ LPDIRECTPLAY2 m_pDP;
+ NamedGUIDList m_providers;
+ NamedGUIDList m_sessions;
+ NamedGUIDList m_unknown;
+ BOOL m_bHost;
+};
+
+static BOOL EnumProvidersCallback(LPGUID lpguidSP, LPSTR lpSTName,
+ DWORD dwMajorVersion, DWORD dwMinorVersion, NamedGUIDList* lpContext);
+
+static BOOL EnumSessionsCallback(LPDPSESSIONDESC2 lpThisSD,
+ LPDWORD lpdwTimeOut, DWORD dwFlags, NamedGUIDList* lpContext);
+
+void TraceErrorDP(HRESULT hErr);
+
+#endif
\ No newline at end of file
diff --git a/src/obstacle.h b/src/obstacle.h
new file mode 100644
index 0000000..5fce98a
--- /dev/null
+++ b/src/obstacle.h
@@ -0,0 +1,593 @@
+#ifndef OBSTACLE_H
+#define OBSTACLE_H
+
+#define Q_EMPTY \
+ 0,0,0,0, \
+ 0,0,0,0, \
+ 0,0,0,0, \
+ 0,0,0,0
+#define Q_FULL \
+ 1,1,1,1, \
+ 1,1,1,1, \
+ 1,1,1,1, \
+ 1,1,1,1
+#define Q_TRIANGLE_RIGHT \
+ 1,1,1,1, \
+ 0,1,1,1, \
+ 0,0,0,1, \
+ 0,0,0,0
+#define Q_TRIANGLE_LEFT \
+ 1,1,1,1, \
+ 1,1,1,0, \
+ 1,0,0,0, \
+ 0,0,0,0
+#define Q_TOP_HALF \
+ 1,1,1,1, \
+ 1,1,1,1, \
+ 0,0,0,0, \
+ 0,0,0,0
+#define Q_TOP_QUARTER \
+ 1,1,1,1, \
+ 0,0,0,0, \
+ 0,0,0,0, \
+ 0,0,0,0
+#define Q_TOP_3_QUARTERS \
+ 1,1,1,1, \
+ 1,1,1,1, \
+ 1,1,1,1, \
+ 0,0,0,0
+#define Q_PILLAR \
+ 0,1,1,0, \
+ 0,1,1,0, \
+ 0,1,1,0, \
+ 0,1,1,0
+
+extern short table_decor_quart[] =
+{
+ Q_FULL, // 0
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_TRIANGLE_RIGHT,
+
+ Q_TRIANGLE_RIGHT, // 16
+ Q_TRIANGLE_LEFT,
+ Q_TRIANGLE_LEFT,
+
+ 1,1,1,1,
+ 1,1,1,1,
+ 0,0,1,1,
+ 0,0,0,0,
+
+ 1,1,1,1,
+ 1,1,1,1,
+ 1,1,0,0,
+ 1,1,0,0,
+
+ 1,1,1,1,
+ 1,1,1,1,
+ 1,1,0,0,
+ 0,0,0,0,
+
+ Q_EMPTY,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_TOP_HALF,
+ Q_TOP_QUARTER,
+ Q_FULL,
+ Q_FULL,
+
+ Q_FULL, // 32
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_TOP_3_QUARTERS,
+ Q_TOP_HALF,
+ Q_TOP_QUARTER,
+
+ Q_FULL, // 48
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+
+ Q_FULL, // 64
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_TRIANGLE_LEFT,
+ Q_TRIANGLE_RIGHT,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_FULL,
+ Q_FULL,
+
+ Q_FULL, // 80
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_EMPTY,
+ Q_EMPTY,
+
+ 1,1,1,1,
+ 1,1,1,1,
+ 1,1,1,1,
+ 1,1,0,0,
+
+ 1,1,1,1,
+ 1,1,1,1,
+ 1,1,0,0,
+ 1,1,0,0,
+
+ 1,1,1,1,
+ 1,1,1,1,
+ 1,1,1,1,
+ 0,1,1,1,
+
+ 1,1,1,1,
+ 1,1,1,1,
+ 0,0,1,1,
+ 0,0,1,1,
+
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+
+ Q_FULL, // 96
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+
+ 1,1,1,1,
+ 1,1,1,1,
+ 1,1,1,0,
+ 1,1,1,0,
+
+ 1,1,1,1,
+ 1,1,1,1,
+ 0,1,1,1,
+ 0,1,1,1,
+
+ Q_EMPTY,
+ Q_EMPTY,
+
+ Q_EMPTY, // 112
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+
+ 0,0,0,1,
+ 0,0,0,1,
+ 0,0,0,1,
+ 0,0,0,1,
+
+ Q_EMPTY,
+
+ Q_EMPTY, // 128
+
+ 1,0,0,0,
+ 1,0,0,0,
+ 1,0,0,0,
+ 1,0,0,0,
+
+ Q_EMPTY,
+ Q_EMPTY,
+
+ 0,0,0,0,
+ 0,0,0,0,
+ 0,0,0,0,
+ 1,1,1,1,
+
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_TOP_QUARTER,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+
+ Q_FULL, // 144
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_TRIANGLE_LEFT,
+ Q_TRIANGLE_RIGHT,
+ Q_FULL,
+ Q_FULL,
+ Q_EMPTY,
+ Q_EMPTY,
+
+ Q_EMPTY, // 160
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+
+ Q_EMPTY, // 176
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_PILLAR,
+ Q_PILLAR,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+
+ Q_FULL, // 192
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+
+ Q_EMPTY, // 208
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+
+ Q_FULL, // 224
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+
+ Q_EMPTY, // 240
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_TOP_3_QUARTERS,
+ Q_TOP_3_QUARTERS,
+
+ 1,1,1,1,
+ 1,1,1,1,
+ 1,1,1,0,
+ 0,0,0,0,
+
+ Q_FULL,
+ Q_FULL,
+
+ Q_TOP_3_QUARTERS, // 256
+ Q_FULL,
+ Q_FULL,
+ Q_TOP_3_QUARTERS,
+ Q_TOP_3_QUARTERS,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+
+ Q_EMPTY, // 272
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_FULL,
+ Q_FULL,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+
+ Q_EMPTY, // 288
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_FULL,
+ Q_EMPTY,
+ Q_EMPTY,
+
+ Q_FULL, // 304
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_TOP_HALF,
+ Q_TOP_HALF,
+ Q_TOP_HALF,
+ Q_TOP_HALF,
+ Q_TOP_HALF,
+ Q_TOP_HALF,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+
+ Q_EMPTY, // 320
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_TOP_QUARTER,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+
+ 1,1,1,1,
+ 1,1,1,1,
+ 0,1,1,0,
+ 0,1,1,0,
+
+ 1,1,1,1,
+ 1,1,1,1,
+ 0,1,1,0,
+ 0,1,1,0,
+
+ 1,1,1,1,
+ 1,1,1,1,
+ 0,1,1,0,
+ 0,1,1,0,
+
+ 1,1,1,1,
+ 1,1,1,1,
+ 0,1,1,0,
+ 0,1,1,0,
+
+ Q_PILLAR,
+ Q_PILLAR,
+
+ Q_PILLAR, // 336
+ Q_EMPTY,
+ Q_FULL,
+ Q_EMPTY,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+
+ Q_FULL, // 352
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_TOP_QUARTER,
+ Q_TOP_QUARTER,
+ Q_TOP_QUARTER,
+ Q_EMPTY,
+
+ Q_EMPTY, // 368
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_FULL,
+ Q_FULL,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+
+ Q_EMPTY, // 384
+ Q_EMPTY,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_FULL,
+ Q_EMPTY,
+ Q_EMPTY,
+
+ Q_EMPTY, // 400
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+
+ Q_EMPTY, // 416
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_EMPTY,
+ Q_PILLAR,
+ Q_PILLAR,
+ Q_PILLAR,
+ Q_PILLAR,
+ Q_PILLAR,
+ Q_PILLAR,
+ Q_PILLAR,
+ Q_PILLAR,
+ Q_PILLAR,
+ Q_PILLAR,
+ Q_PILLAR,
+
+ Q_PILLAR, // 432
+ Q_PILLAR,
+ Q_PILLAR,
+ Q_PILLAR,
+ Q_PILLAR,
+ Q_PILLAR,
+ Q_PILLAR,
+ Q_PILLAR,
+ Q_PILLAR
+};
+
+#endif
\ No newline at end of file
diff --git a/src/pixmap.cpp b/src/pixmap.cpp
new file mode 100644
index 0000000..a8c751c
--- /dev/null
+++ b/src/pixmap.cpp
@@ -0,0 +1,1920 @@
+// CPixmap.cpp
+//
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "def.h"
+#include "pixmap.h"
+#include "misc.h"
+#include "ddutil.h"
+#include "pixtables.h"
+
+#define DIRECTDRAW_VERSION 0x0500
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+// Constructeur.
+
+CPixmap::CPixmap()
+{
+ int i;
+
+ m_bFullScreen = FALSE;
+ m_bBenchmarkSuccess = TRUE;
+ m_bTrueColorBack = FALSE;
+ m_bTrueColorDecor = FALSE;
+ m_mouseType = MOUSETYPEGRA;
+ m_bDebug = TRUE;
+ m_bPalette = TRUE;
+
+ m_mouseSprite = SPRITE_WAIT;
+ MouseHotSpot();
+ m_mousePos.x = LXIMAGE/2;
+ m_mousePos.y = LYIMAGE/2;
+ m_mouseBackPos = m_mousePos;
+ m_bMouseBack = FALSE;
+ m_bMouseShow = TRUE;
+ m_bBackDisplayed = FALSE;
+
+ m_lpDD = NULL;
+ m_lpDDSPrimary = NULL;
+ m_lpDDSBack = NULL;
+ m_lpDDSMouse = NULL;
+ m_lpDDPal = NULL;
+ m_lpClipper = NULL;
+
+ for ( i=0 ; iRelease();
+ m_lpDDSPrimary = NULL;
+ }
+
+ if ( m_lpDDSBack != NULL )
+ {
+ m_lpDDSBack->Release();
+ m_lpDDSBack = NULL;
+ }
+
+ if ( m_lpDDSMouse != NULL )
+ {
+ m_lpDDSMouse->Release();
+ m_lpDDSMouse = NULL;
+ }
+
+ if ( m_lpDDPal != NULL )
+ {
+ m_lpDDPal->Release();
+ m_lpDDPal = NULL;
+ }
+
+ for ( i=0 ; iRelease();
+ m_lpDDSurface[i]= NULL;
+ }
+ }
+
+ if ( m_lpClipper != NULL )
+ {
+ m_lpClipper->Release();
+ m_lpClipper = NULL;
+ }
+
+ m_lpDD->Release();
+ m_lpDD = NULL;
+ }
+}
+
+
+void CPixmap::SetDebug(BOOL bDebug)
+{
+ m_bDebug = bDebug;
+ DDSetDebug(bDebug);
+}
+
+
+// Cr�e l'objet DirectDraw principal.
+// Retourne FALSE en cas d'erreur.
+
+BOOL CPixmap::Create(HWND hwnd, POINT dim,
+ BOOL bFullScreen, int mouseType, BOOL bTrueColorDecor, BOOL bTrueColor)
+{
+ DDSURFACEDESC ddsd;
+ int devcap;
+ HRESULT ddrval;
+ POINT pos;
+ HDC hdc;
+ DWORD colorMode;
+
+ hdc = CreateCompatibleDC(NULL);
+
+ if (hdc == NULL)
+ {
+ bTrueColor = 0;
+ bTrueColorDecor = 0;
+ }
+ else
+ {
+ devcap = GetDeviceCaps(hdc, SIZEPALETTE);
+ if ((devcap != NULL) && (devcap < 257))
+ {
+ bTrueColor = 0;
+ bTrueColorDecor = 0;
+ }
+ DeleteDC(hdc);
+ }
+
+ m_hWnd = hwnd;
+ m_bFullScreen = bFullScreen;
+ m_mouseType = mouseType;
+ m_dim = dim;
+ m_bTrueColorDecor = bTrueColorDecor;
+ m_bTrueColorBack = bTrueColor;
+
+ if ( m_mouseType == MOUSETYPEGRA )
+ {
+ // Cache d�finitivement la vilaine souris Windows.
+ ShowCursor(FALSE);
+
+ pos = m_mousePos;
+ ClientToScreen(m_hWnd, &pos);
+ SetCursorPos(pos.x, pos.y); // met la souris au centre
+ }
+
+ m_clipRect.left = 0;
+ m_clipRect.top = 0;
+ m_clipRect.right = dim.x;
+ m_clipRect.bottom = dim.y;
+
+ // Create the main DirectDraw object
+ ddrval = DirectDrawCreate(NULL, &m_lpDD, NULL);
+ if ( ddrval != DD_OK )
+ {
+ OutputDebug("Fatal error: DirectDrawCreate\n");
+ return FALSE;
+ }
+
+ // Get exclusive mode.
+ if ( m_bFullScreen )
+ {
+ ddrval = m_lpDD->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN);
+ }
+ else
+ {
+ ddrval = m_lpDD->SetCooperativeLevel(hwnd, DDSCL_NORMAL);
+ }
+ if ( ddrval != DD_OK )
+ {
+ OutputDebug("Fatal error: SetCooperativeLevel\n");
+ return FALSE;
+ }
+
+ // Set the video mode to 640x480x8.
+ if ( m_bFullScreen != FALSE)
+ {
+ if ((bTrueColor != 0) || (colorMode = 8, bTrueColorDecor != FALSE))
+ {
+ colorMode = 16;
+ }
+
+ ddrval = m_lpDD->SetDisplayMode(dim.x, dim.y, colorMode);
+ if ( ddrval != DD_OK )
+ {
+ OutputDebug("Fatal error: SetDisplayMode\n");
+ return FALSE;
+ }
+ }
+
+ // Create the primary surface with 1 back buffer.
+ ZeroMemory(&ddsd, sizeof(ddsd));
+ ddsd.dwSize = sizeof(ddsd);
+ ddsd.dwFlags = DDSD_CAPS;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+
+ ddrval = m_lpDD->CreateSurface(&ddsd, &m_lpDDSPrimary, NULL);
+ if ( ddrval != DD_OK )
+ {
+ TraceErrorDD(ddrval, "pixmap", 0);
+ OutputDebug("Fatal error: CreateSurface\n");
+ return FALSE;
+ }
+
+ // Create the back buffer.
+ ZeroMemory(&ddsd, sizeof(ddsd));
+ ddsd.dwSize = sizeof(ddsd);
+ ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH;
+//? ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
+ ddsd.dwWidth = dim.x;
+ ddsd.dwHeight = dim.y;
+
+ ddrval = m_lpDD->CreateSurface(&ddsd, &m_lpDDSBack, NULL);
+ if ( ddrval != DD_OK )
+ {
+ TraceErrorDD(ddrval, "pixmap", 0);
+ OutputDebug("Fatal error: CreateBackSurface\n");
+ return FALSE;
+ }
+
+ // Create the mouse buffer.
+ ZeroMemory(&ddsd, sizeof(ddsd));
+ ddsd.dwSize = sizeof(ddsd);
+ ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH;
+//? ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
+ ddsd.dwWidth = DIMBLUPIX;
+ ddsd.dwHeight = DIMBLUPIY;
+
+ ddrval = m_lpDD->CreateSurface(&ddsd, &m_lpDDSMouse, NULL);
+ if ( ddrval != DD_OK )
+ {
+ TraceErrorDD(ddrval, "pixmap", 0);
+ OutputDebug("Fatal error: CreateMouseSurface\n");
+ return FALSE;
+ }
+
+ // Create a DirectDrawClipper object. The object enables clipping to the
+ // window boundaries in the IDirectDrawSurface::Blt function for the
+ // primary surface.
+ if ( !m_bFullScreen )
+ {
+ ddrval = m_lpDD->CreateClipper(0, &m_lpClipper, NULL);
+ if ( ddrval != DD_OK )
+ {
+ TraceErrorDD(ddrval, "pixmap", 0);
+ OutputDebug("Can't create clipper\n");
+ return FALSE;
+ }
+
+ ddrval = m_lpClipper->SetHWnd(0, hwnd);
+ if ( ddrval != DD_OK )
+ {
+ TraceErrorDD(ddrval, "pixmap", 0);
+ OutputDebug("Can't set clipper window handle\n");
+ return FALSE;
+ }
+
+ ddrval = m_lpDDSPrimary->SetClipper(m_lpClipper);
+ if ( ddrval != DD_OK )
+ {
+ TraceErrorDD(ddrval, "pixmap", 0);
+ OutputDebug("Can't attach clipper to primary surface\n");
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+// Lib�re les bitmaps.
+
+BOOL CPixmap::Flush()
+{
+ return TRUE;
+}
+
+// Restitue les bitmaps.
+
+BOOL CPixmap::Restore()
+{
+ RestoreAll();
+ return TRUE;
+}
+
+void CPixmap::QuickIcon(int channel, int rank, POINT pos)
+{
+ int num;
+ RECT rect;
+
+ if ((unsigned)channel > CHMAX) return;
+
+ if (channel == CHOBJECT)
+ {
+ if (table_icon_object[0] <= rank) return;
+ rect.left = table_icon_object[rank * 6 + 0 + 1];
+ rect.top = table_icon_object[rank * 6 + 1 + 1];
+ rect.right = rect.left + table_icon_object[rank * 6 + 4 + 1];
+ rect.bottom = rect.top + table_icon_object[rank * 6 + 5 + 1];
+ pos.x += table_icon_object[rank * 6 + 2 + 1];
+ pos.y += table_icon_object[rank * 6 + 3 + 1];
+ }
+ else if (channel == CHELEMENT)
+ {
+ if (table_icon_element[0] <= rank) return;
+ rect.left = table_icon_element[rank * 6 + 0 + 1];
+ rect.top = table_icon_element[rank * 6 + 1 + 1];
+ rect.right = rect.left + table_icon_element[rank * 6 + 4 + 1];
+ rect.bottom = rect.top + table_icon_element[rank * 6 + 5 + 1];
+ pos.x += table_icon_element[rank * 6 + 2 + 1];
+ pos.y += table_icon_element[rank * 6 + 3 + 1];
+ }
+ else if (IsBlupiChannel(channel))
+ {
+ if (table_icon_blupi[0] <= rank) return;
+ rect.left = table_icon_blupi[rank * 6 + 0 + 1];
+ rect.top = table_icon_blupi[rank * 6 + 1 + 1];
+ rect.right = rect.left + table_icon_blupi[rank * 6 + 4 + 1];
+ rect.bottom = rect.top + table_icon_blupi[rank * 6 + 5 + 1];
+ pos.x += table_icon_blupi[rank * 6 + 2 + 1];
+ pos.y += table_icon_blupi[rank * 6 + 3 + 1];
+ }
+ else if (channel == CHEXPLO)
+ {
+ if (table_icon_explo[0] <= rank) return;
+ rect.left = table_icon_explo[rank * 6 + 0 + 1];
+ rect.top = table_icon_explo[rank * 6 + 1 + 1];
+ rect.right = rect.left + table_icon_explo[rank * 6 + 4 + 1];
+ rect.bottom = rect.top + table_icon_explo[rank * 6 + 5 + 1];
+ pos.x += table_icon_explo[rank * 6 + 2 + 1];
+ pos.y += table_icon_explo[rank * 6 + 3 + 1];
+ }
+ else
+ {
+ rect.right = m_iconDim[channel].x;
+ num = m_totalDim[channel].x / rect.right;
+ rect.bottom = m_iconDim[channel].y;
+ if (rank < 0)
+ {
+ return;
+ }
+ if ((m_totalDim[channel].y / rect.bottom) * num <= rank)
+ {
+ return;
+ }
+ rect.left = (rank % num) * rect.right;
+ rect.right = rect.left + rect.right;
+ rect.top = (rank / num) * rect.bottom;
+ rect.bottom = rect.top + rect.bottom;
+ }
+
+ num = m_clipRect.left;
+ if (pos.x < num)
+ {
+ num -= pos.x;
+ pos.x = m_clipRect.left;
+ rect.left += num;
+ }
+ num = (m_clipRect.right + rect.left) - pos.x;
+ if (num < rect.right)
+ {
+ rect.right = num;
+ }
+ num = m_clipRect.top;
+ if (pos.y < num)
+ {
+ num -= pos.y;
+ pos.y = m_clipRect.top;
+ rect.top += num;
+ }
+ num = (m_clipRect.bottom + rect.top) - pos.y;
+ if (num < rect.bottom)
+ {
+ rect.bottom = num;
+ }
+ if (rect.left < rect.right && rect.top < rect.bottom)
+ {
+ while (TRUE)
+ {
+ num = m_lpDDSBack->BltFast(pos.x, pos.y, m_lpDDSurface[channel], &rect, 1);
+ if (num == DD_OK) return;
+ if (num == DDERR_SURFACELOST && RestoreAll() != DD_OK) return;
+ if (num != DDERR_WASSTILLDRAWING) return;
+ }
+ }
+ return;
+}
+
+
+// Initialise la palette syst�me.
+
+BOOL CPixmap::InitSysPalette()
+{
+ HDC hdc;
+ int caps;
+
+ hdc = CreateCompatibleDC(NULL);
+ if ( hdc == NULL ) return FALSE;
+
+ if ( !m_bFullScreen )
+ {
+ caps = GetDeviceCaps(hdc, SIZEPALETTE);
+ if ( caps == 0 ) m_bPalette = FALSE;
+ else m_bPalette = TRUE;
+ }
+
+ GetSystemPaletteEntries(hdc, 0, 256, m_sysPal);
+ DeleteDC(hdc);
+ return TRUE;
+}
+
+BOOL CPixmap::GetTrueColorBack()
+{
+ return m_bTrueColorBack;
+}
+
+BOOL CPixmap::GetTrueColorDecor()
+{
+ return m_bTrueColorDecor;
+}
+
+void CPixmap::SetBenchmarkSuccess(BOOL bSuccess)
+{
+ m_bBenchmarkSuccess = bSuccess;
+}
+
+void CPixmap::SetTrueColorBack(BOOL bTrueColor)
+{
+ m_bTrueColorBack = bTrueColor;
+}
+
+void CPixmap::SetTrueColorDecor(BOOL bTrueColorDecor)
+{
+ m_bTrueColorDecor = bTrueColorDecor;
+}
+/*
+void CPixmap::DrawChar(int rank, POINT pos, double size)
+{
+ pos.x = (int)((double)pos.x + originX);
+ pos.y = (int)((double)pos.y + originY);
+ RECT rect;
+ rect.left = pos.x,
+ rect.top = pos.y,
+ rect.right = pos.x + (int)(32.0 * size),
+ rect.bottom = pos.y + (int)(32.0 * size);
+ DrawIcon(6, rank, rect, 1.0, FALSE);
+}
+*/
+
+// Indique si l'on utilise une palette.
+
+BOOL CPixmap::IsPalette()
+{
+ return m_bPalette;
+}
+
+
+// Rempli une zone rectangulaire avec une couleur uniforme.
+
+void CPixmap::Fill(RECT rect, COLORREF color)
+{
+ // � faire si n�cessaire ...
+}
+
+
+// Restore all lost objects.
+
+HRESULT CPixmap::RestoreAll()
+{
+ if ( m_bDebug ) OutputDebug("CPixmap::RestoreAll\n");
+ int i;
+ HRESULT ddrval;
+
+ if ( m_lpDDSPrimary && m_lpDDSPrimary->IsLost() )
+ {
+ ddrval = m_lpDDSPrimary->Restore();
+// if( ddrval != DD_OK ) return ddrval;
+ }
+
+ if ( m_lpDDSBack && m_lpDDSBack->IsLost() )
+ {
+ ddrval = m_lpDDSBack->Restore();
+// if( ddrval != DD_OK ) return ddrval;
+ }
+
+ if ( m_lpDDSMouse && m_lpDDSMouse->IsLost() )
+ {
+ ddrval = m_lpDDSMouse->Restore();
+// if( ddrval != DD_OK ) return ddrval;
+ }
+
+ for ( i=0 ; iIsLost() )
+ {
+ ddrval = m_lpDDSurface[i]->Restore();
+ if( ddrval == DD_OK )
+ {
+ DDReLoadBitmap(m_lpDDSurface[i], m_filename[i]);
+ }
+ }
+ }
+ return DD_OK;
+}
+
+// Effectue un appel BltFast.
+// Les modes sont 0=transparent, 1=opaque.
+
+HRESULT CPixmap::BltFast(int chDst, int channel,
+ POINT dst, RECT rcRect, int mode)
+{
+ DWORD dwTrans;
+ HRESULT ddrval;
+ int limit;
+
+ if ( mode == 0 ) dwTrans = DDBLTFAST_SRCCOLORKEY;
+ else dwTrans = DDBLTFAST_NOCOLORKEY;
+
+ // Effectue un peu de clipping.
+ if ( dst.x < m_clipRect.left )
+ {
+ rcRect.left += m_clipRect.left-dst.x;
+ dst.x = m_clipRect.left;
+ }
+ limit = (m_clipRect.right-dst.x)+rcRect.left;
+ if ( rcRect.right > limit )
+ {
+ rcRect.right = limit;
+ }
+ if ( dst.y < m_clipRect.top )
+ {
+ rcRect.top += m_clipRect.top-dst.y;
+ dst.y = m_clipRect.top;
+ }
+ limit = (m_clipRect.bottom-dst.y)+rcRect.top;
+ if ( rcRect.bottom > limit )
+ {
+ rcRect.bottom = limit;
+ }
+
+ if ( rcRect.left >= rcRect.right ||
+ rcRect.top >= rcRect.bottom ) return DD_OK;
+
+ while( TRUE )
+ {
+ if ( chDst < 0 )
+ {
+ ddrval = m_lpDDSBack->BltFast(dst.x, dst.y,
+ m_lpDDSurface[channel],
+ &rcRect, dwTrans);
+ }
+ else
+ {
+ ddrval = m_lpDDSurface[chDst]->BltFast(dst.x, dst.y,
+ m_lpDDSurface[channel],
+ &rcRect, dwTrans);
+ }
+ if ( ddrval == DD_OK ) break;
+
+ if ( ddrval == DDERR_SURFACELOST )
+ {
+ ddrval = RestoreAll();
+ if ( ddrval != DD_OK ) break;
+ }
+
+ if ( ddrval != DDERR_WASSTILLDRAWING ) break;
+ }
+
+ return ddrval;
+}
+
+// Effectue un appel BltFast.
+// Les modes sont 0=transparent, 1=opaque.
+
+HRESULT CPixmap::BltFast(LPDIRECTDRAWSURFACE lpDD,
+ int channel, POINT dst, RECT rcRect, int mode)
+{
+ DWORD dwTrans;
+ HRESULT ddrval;
+
+ if ( mode == 0 ) dwTrans = DDBLTFAST_SRCCOLORKEY;
+ else dwTrans = DDBLTFAST_NOCOLORKEY;
+
+ while( TRUE )
+ {
+ ddrval = lpDD->BltFast(dst.x, dst.y,
+ m_lpDDSurface[channel],
+ &rcRect, dwTrans);
+ if ( ddrval == DD_OK ) break;
+
+ if ( ddrval == DDERR_SURFACELOST )
+ {
+ ddrval = RestoreAll();
+ if ( ddrval != DD_OK ) break;
+ }
+
+ if ( ddrval != DDERR_WASSTILLDRAWING ) break;
+ }
+
+ return ddrval;
+}
+
+BOOL CPixmap::DrawMap(int channel, RECT src, RECT dest)
+{
+ HRESULT hErr;
+
+ if ((channel < 0) || (channel > MAXIMAGE))
+ {
+ return FALSE;
+ }
+
+ while (1)
+ {
+ hErr = m_lpDDSurface[channel]->Blt(&dest, m_lpDDSBack, &src, DDBLT_WAIT, NULL);
+ if (hErr == DD_OK) break;
+ if (hErr == DDERR_SURFACELOST) hErr = RestoreAll(); if (hErr != DD_OK) break;;
+ if (hErr == DDERR_WASSTILLDRAWING) break;
+ }
+ return (hErr == DD_OK);
+}
+
+// Sauve toute la palette de couleurs.
+
+BOOL CPixmap::SavePalette()
+{
+ HRESULT ddrval;
+
+ if ( m_lpDDPal == NULL ) return FALSE;
+
+ ddrval = m_lpDDPal->GetEntries(0, 0, 256, m_pal);
+
+ if ( ddrval != DD_OK ) return FALSE;
+ return TRUE;
+}
+
+// Restitue toute la palette de couleurs.
+
+BOOL CPixmap::RestorePalette()
+{
+ HRESULT ddrval;
+
+ ddrval = m_lpDDPal->SetEntries(0, 0, 256, m_pal);
+
+ if ( ddrval != DD_OK ) return FALSE;
+ return TRUE;
+}
+
+// Cherche une couleur dans la palette principale.
+// En mode plein �cran, il faut chercher dans la palette
+// correspondant aux images (obtenue avec SavePalette),
+// alors qu'en mode fen�tre, il faut chercher dans la
+// palette syst�me (obtenue avec InitSysPalette) !!!
+
+int CPixmap::SearchColor(int red, int green, int blue)
+{
+ int i, j, delta, min;
+
+ if ( m_bFullScreen )
+ {
+ for ( i=0 ; i<256 ; i++ )
+ {
+ if ( red == m_pal[i].peRed &&
+ green == m_pal[i].peGreen &&
+ blue == m_pal[i].peBlue ) return i;
+ }
+
+ // Cherche la couleur la plus proche.
+ min = 10000;
+ j = -1;
+ for ( i=0 ; i<256 ; i++ )
+ {
+ delta = abs(red - m_pal[i].peRed )+
+ abs(green - m_pal[i].peGreen)+
+ abs(blue - m_pal[i].peBlue );
+
+ if ( delta < min )
+ {
+ min = delta;
+ j = i;
+ }
+ }
+ }
+ else
+ {
+ if ( m_bPalette )
+ {
+ for ( i=0 ; i<256 ; i++ )
+ {
+ if ( red == m_sysPal[i].peRed &&
+ green == m_sysPal[i].peGreen &&
+ blue == m_sysPal[i].peBlue ) return i;
+ }
+
+ // Cherche la couleur la plus proche.
+ min = 10000;
+ j = -1;
+ for ( i=0 ; i<256 ; i++ )
+ {
+ delta = abs(red - m_sysPal[i].peRed )+
+ abs(green - m_sysPal[i].peGreen)+
+ abs(blue - m_sysPal[i].peBlue );
+
+ if ( delta < min )
+ {
+ min = delta;
+ j = i;
+ }
+ }
+ }
+ else
+ {
+ j = (blue >>3) &0x001F;
+ j |= ((green>>2)<< 5)&0x07E0;
+ j |= ((red >>3)<<11)&0xF800; // mode 5-6-5
+//? j = (blue >>3) &0x001F;
+//? j |= ((green>>3)<< 5)&0x03E0;
+//? j |= ((red >>3)<<10)&0x7C00; // mode 5-5-5
+ }
+ }
+ return j;
+}
+
+
+// Cache une image contenant des ic�nes.
+
+/*
+BOOL CPixmap::Cache(int channel, char *pFilename, POINT totalDim, POINT iconDim,
+ BOOL bUsePalette)
+{
+ HRESULT ddrval;
+
+ if ( channel < 0 || channel >= MAXIMAGE ) return FALSE;
+
+ if ( m_lpDDSurface[channel] != NULL )
+ {
+ Flush(channel);
+ }
+
+ // Create and set the palette.
+ if ( bUsePalette )
+ {
+ if ( m_bDebug ) OutputDebug("Use palette\n");
+ if ( m_lpDDPal != NULL )
+ {
+ if ( m_bDebug ) OutputDebug("Release palette\n");
+ m_lpDDPal->Release();
+ m_lpDDPal = NULL;
+ }
+
+ m_lpDDPal = DDLoadPalette(m_lpDD, pFilename);
+
+ if ( m_lpDDPal )
+ {
+ if ( m_bDebug ) OutputDebug("Set palette\n");
+ m_lpDDSPrimary->SetPalette(NULL); // indispensable !
+ ddrval = m_lpDDSPrimary->SetPalette(m_lpDDPal);
+ if ( ddrval != DD_OK )
+ {
+ TraceErrorDD(ddrval, pFilename, 1);
+ }
+ }
+ }
+
+ // Create the offscreen surface, by loading our bitmap.
+ m_lpDDSurface[channel] = DDLoadBitmap(m_lpDD, pFilename, 0, 0);
+
+ if ( m_lpDDSurface[channel] == NULL )
+ {
+ OutputDebug("Fatal error: DDLoadBitmap\n");
+ return FALSE;
+ }
+
+ // Set the color key to white
+ if ( m_bDebug ) OutputDebug("DDSetColorKey\n");
+ DDSetColorKey(m_lpDDSurface[channel], RGB(255,255,255)); // blanc
+
+ strcpy(m_filename[channel], pFilename);
+
+ m_totalDim[channel] = totalDim;
+ m_iconDim[channel] = iconDim;
+
+ return TRUE;
+}
+*/
+
+// Cache une image globale.
+
+BOOL CPixmap::Cache(int channel, char* pFilename, POINT totalDim, POINT iconDim, BOOL bUsePalette)
+{
+ HRESULT hErr;
+
+
+ if ((channel < 0) || (channel >= MAXIMAGE))
+ {
+ return FALSE;
+ }
+
+ if (m_lpDDSurface[channel] != NULL)
+ {
+ Flush(channel);
+ }
+
+ if ( bUsePalette )
+ {
+ if ( m_bDebug ) OutputDebug("Use Palette\n");
+ if (m_lpDDPal != NULL)
+ {
+ if ( m_bDebug ) OutputDebug("Release palette\n");
+ m_lpDDPal->Release();
+ m_lpDDPal = NULL;
+ }
+ }
+ m_lpDDPal = DDLoadPalette(m_lpDD, pFilename);
+
+ if ( m_lpDDPal )
+ {
+ if ( m_bDebug ) OutputDebug("Set palette\n");
+ m_lpDDSPrimary->SetPalette(NULL);
+ hErr = (m_lpDDSPrimary->SetPalette(m_lpDDPal));
+ if (hErr != DD_OK)
+ {
+ TraceErrorDD(hErr, pFilename, 1);
+ }
+ }
+ m_lpDDSurface[channel] = DDLoadBitmap(m_lpDD, pFilename, 0, 0);
+ if (m_lpDDSurface[channel] == NULL)
+ {
+ OutputDebug("Fatal error: DDLoadBitmap\n");
+ return FALSE;
+ }
+ if ( m_bDebug ) OutputDebug("DDSetColorKey\n");
+ DDSetColorKey(m_lpDDSurface[channel], RGB(255, 255, 255));
+
+ strcpy(m_filename[channel], pFilename);
+
+ m_totalDim[channel] = totalDim;
+ m_iconDim[channel] = iconDim;
+
+ return TRUE;
+}
+
+// Cache une image provenant d'un bitmap.
+
+// Probably not needed?
+
+
+/*
+BOOL CPixmap::Cache(int channel, HBITMAP hbm, POINT totalDim)
+{
+ if ( channel < 0 || channel >= MAXIMAGE ) return FALSE;
+
+ if ( m_lpDDSurface[channel] != NULL )
+ {
+ Flush(channel);
+ }
+
+ // Create the offscreen surface, by loading our bitmap.
+ m_lpDDSurface[channel] = DDConnectBitmap(m_lpDD, hbm);
+
+ if ( m_lpDDSurface[channel] == NULL )
+ {
+ OutputDebug("Fatal error: DDLoadBitmap\n");
+ return FALSE;
+ }
+
+ // Set the color key to white
+ DDSetColorKey(m_lpDDSurface[channel], RGB(255,255,255)); // blanc
+
+ m_totalDim[channel] = totalDim;
+ m_iconDim[channel] = totalDim;
+
+ return TRUE;
+}
+*/
+
+BOOL CPixmap::BackgroundCache(int channel, const char* pFilename, POINT totalDim, POINT iconDim, BOOL bUsePalette)
+{
+ BOOL decor;
+ char file[100];
+
+ decor = strstr(pFilename, "blupi") != pFilename &&
+ strstr(pFilename, "element") != pFilename &&
+ strstr(pFilename, "explo") != pFilename &&
+ strstr(pFilename, "object") != pFilename;
+ if (!bUsePalette && (!decor || m_bTrueColorBack))
+ {
+ strcpy(file, "image16\\");
+ strcat(file, pFilename);
+ if (Cache(channel, file, totalDim, iconDim, FALSE))
+ {
+ return TRUE;
+ }
+ }
+ strcpy(file, "image08\\");
+ strcat(file, pFilename);
+ return Cache(channel, file, totalDim, iconDim, bUsePalette);
+}
+
+BOOL CPixmap::CacheAll(BOOL cache, HWND hWnd, BOOL bFullScreen, BOOL bTrueColor, BOOL bTrueColorDecor, int mouseType, const char* pFilename, int region)
+{
+ SetDebug(TRUE);
+ char filename[100];
+ char image[12];
+ POINT totalDim;
+ POINT iconDim;
+ RECT rect;
+ POINT dim;
+
+
+ totalDim.x = 640;
+ totalDim.y = 480;
+ iconDim.x = 0;
+ iconDim.y = 0;
+
+ dim.x = LXIMAGE;
+ dim.y = LYIMAGE;
+
+ if (cache == FALSE)
+ {
+ delete this;
+ hWnd = m_hWnd;
+ bFullScreen = m_bFullScreen;
+ bTrueColor = m_bTrueColorBack;
+ bTrueColorDecor = m_bTrueColorDecor;
+ mouseType = m_mouseType;
+ }
+
+ if (Create(hWnd, dim, bFullScreen, mouseType, bTrueColorDecor, bTrueColor) == FALSE)
+ {
+ return FALSE;
+ }
+
+ OutputDebug("Image: init\n");
+ if (BackgroundCache(0, "init.blp", totalDim, iconDim, TRUE) == FALSE)
+ {
+ return FALSE;
+ }
+
+ OutputDebug("SavePalette\n");
+ SavePalette();
+ OutputDebug("InitSysPalette\n");
+ InitSysPalette();
+
+ if (cache == FALSE)
+ {
+ if (BackgroundCache(0, pFilename, totalDim, iconDim, FALSE) == FALSE)
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ *(char*)image = (LXIMAGE) << 64;
+ rect.bottom = LYIMAGE;
+ rect.left = LOWORD(image);
+ rect.top = HIWORD(image);
+ rect.right = HIWORD(image);
+ DrawImage(0, 0, rect, 1);
+ Display();
+ }
+ totalDim.x = 1024;
+ totalDim.y = 1280;
+ iconDim.x = 64;
+ iconDim.y = 64;
+ if (!BackgroundCache(CHOBJECT, "object.blp", totalDim, iconDim, FALSE) )
+ {
+ return FALSE;
+ }
+ SetTransparent(CHOBJECT, RGB(0, 0, 255));
+ totalDim.x = 960;
+ totalDim.y = 1200;
+ iconDim.x = 60;
+ iconDim.y = 60;
+ if (BackgroundCache(CHBLUPI, "blupi000.blp", totalDim, iconDim, FALSE) == FALSE)
+ {
+ return FALSE;
+ }
+ SetTransparent(CHBLUPI, RGB(0, 0, 255));
+ totalDim.x = 960;
+ totalDim.y = 1200;
+ iconDim.x = 60;
+ iconDim.y = 60;
+ if (BackgroundCache(CHBLUPI1, "blupi001.blp", totalDim, iconDim, FALSE) == FALSE)
+ {
+ return FALSE;
+ }
+ SetTransparent(CHBLUPI1, RGB(0, 0, 255));
+ totalDim.x = 960;
+ totalDim.y = 1200;
+ iconDim.x = 60;
+ iconDim.y = 60;
+ if (BackgroundCache(CHBLUPI2, "blupi002.blp", totalDim, iconDim, FALSE) == FALSE)
+ {
+ return FALSE;
+ }
+ SetTransparent(CHBLUPI2, RGB(0, 0, 255));
+ totalDim.x = 960;
+ totalDim.y = 1200;
+ iconDim.x = 60;
+ iconDim.y = 60;
+ if (BackgroundCache(CHBLUPI3, "blupi003.blp", totalDim, iconDim, FALSE) == FALSE)
+ {
+ return FALSE;
+ }
+ SetTransparent(CHBLUPI3, RGB(0, 0, 255));
+ totalDim.x = 64;
+ totalDim.y = 64;
+ iconDim.x = 64;
+ iconDim.y = 64;
+ if (BackgroundCache(CHTEMP, "temp.blp", totalDim, iconDim, FALSE) == FALSE)
+ {
+ return FALSE;
+ }
+ SetTransparent(CHTEMP, RGB(0, 0, 255));
+ totalDim.x = 208;
+ totalDim.y = 160;
+ iconDim.x = 208;
+ iconDim.y = 160;
+ if (BackgroundCache(CHMAP, "map.blp", totalDim, iconDim, FALSE) == FALSE)
+ {
+ return FALSE;
+ }
+ SetTransparent(CHMAP, RGB(0, 0, 255));
+ totalDim.x = 960;
+ totalDim.y = 1200;
+ iconDim.x = 60;
+ iconDim.y = 60;
+ if (BackgroundCache(CHELEMENT, "element.blp", totalDim, iconDim, FALSE) == FALSE)
+ {
+ return FALSE;
+ }
+ SetTransparent(CHELEMENT, RGB(0, 0, 255));
+ totalDim.x = 2048;
+ totalDim.y = 640;
+ iconDim.x = 128;
+ iconDim.y = 128;
+ if (BackgroundCache(CHEXPLO, "explo.blp", totalDim, iconDim, FALSE) == FALSE)
+ {
+ return FALSE;
+ }
+ SetTransparent(CHEXPLO, RGB(0, 0, 255));
+ sprintf(filename, "decor%.3d.blp", region);
+ totalDim.x = LXIMAGE;
+ totalDim.y = LYIMAGE;
+ iconDim.x = 0;
+ iconDim.y = 0;
+ if (BackgroundCache(CHDECOR, filename, totalDim, iconDim, FALSE) == FALSE)
+ {
+ return FALSE;
+ }
+ totalDim.x = 240;
+ totalDim.y = 1040;
+ iconDim.x = 40;
+ iconDim.y = 40;
+ if (BackgroundCache(CHBUTTON, "button00.blp", totalDim, iconDim, FALSE) == FALSE)
+ {
+ return FALSE;
+ }
+ SetTransparent(CHBUTTON, RGB(0, 0, 255));
+ totalDim.x = 124;
+ totalDim.y = 88;
+ iconDim.x = 124;
+ iconDim.y = 22;
+ if (BackgroundCache(CHJAUGE, "jauge.blp", totalDim, iconDim, FALSE) == FALSE)
+ {
+ return FALSE;
+ }
+ SetTransparent(CHJAUGE, RGB(0, 0, 255));
+ totalDim.x = 256;
+ totalDim.y = 384;
+ iconDim.x = 16;
+ iconDim.y = 16;
+ if (BackgroundCache(CHTEXT, "text.blp", totalDim, iconDim, FALSE) != FALSE)
+ {
+ SetTransparent(CHTEXT, RGB(0, 0, 255));
+ totalDim.x = 256;
+ totalDim.y = 96;
+ iconDim.x = 16;
+ iconDim.y = 12;
+ if (BackgroundCache(CHLITTLE, "little.blp", totalDim, iconDim, FALSE) != FALSE)
+ {
+ SetTransparent(CHLITTLE, RGB(0, 0, 255));
+ Benchmark();
+ return TRUE;
+ }
+ return FALSE;
+ }
+ return FALSE;
+}
+
+int CPixmap::Benchmark()
+{
+ timeb tstruct;
+ int i, j, t1, t2, time;
+ RECT rect;
+ POINT dest;
+
+ ftime(&tstruct);
+ t1 = tstruct.millitm;
+
+ for (j = 0; j < 10; j++)
+ {
+ dest.x = POSDRAWX;
+ dest.y = POSDRAWY;
+ rect.left = 29;
+ rect.right = 29 + LXIMAGE;
+ rect.top = 29;
+ rect.bottom = 29 + LYIMAGE;
+ DrawPart(-1, CHDECOR, dest, rect, 1);
+
+ dest.x = 13; // position quelconque non-multiple de 16
+ dest.y = 13;
+ for (i = 0; i < 120; i++)
+ {
+ QuickIcon(CHOBJECT, 1, dest);
+ }
+ }
+
+ ftime(&tstruct);
+ t2 = tstruct.millitm;
+
+ if (t1 > t2) t2 += 1000;
+ time = t2 - t1;
+
+ FILE* file = NULL;
+ char string[100];
+ sprintf(string, "Benchmark = %d\r\n", time);
+ file = fopen("data\\bench.blp", "wb");
+ if (file == NULL) return time;
+ fwrite(string, strlen(string), 1, file);
+ fclose(file);
+
+ return time;
+}
+
+
+// Purge une image.
+
+void CPixmap::Flush(int channel)
+{
+ if ( channel < 0 || channel >= MAXIMAGE ) return;
+ if ( m_lpDDSurface[channel] == NULL ) return;
+
+ m_lpDDSurface[channel]->Release();
+ m_lpDDSurface[channel]= NULL;
+}
+
+// D�finition de la couleur transparente.
+
+void CPixmap::SetTransparent(int channel, COLORREF color)
+{
+ if ( channel < 0 || channel >= MAXIMAGE ) return;
+ if ( m_lpDDSurface[channel] == NULL ) return;
+
+ DDSetColorKey(m_lpDDSurface[channel], color);
+ m_colorSurface[2*channel+0] = color;
+ m_colorSurface[2*channel+1] = color;
+}
+
+// D�finition de la couleur transparente.
+
+void CPixmap::SetTransparent2(int channel, COLORREF color1, COLORREF color2)
+{
+ if ( channel < 0 || channel >= MAXIMAGE ) return;
+ if ( m_lpDDSurface[channel] == NULL ) return;
+
+ DDSetColorKey2(m_lpDDSurface[channel], color1, color2);
+ m_colorSurface[2*channel+0] = color1;
+ m_colorSurface[2*channel+1] = color2;
+}
+
+
+// Modifie la r�gion de clipping.
+
+void CPixmap::SetClipping(RECT clip)
+{
+ m_clipRect.left = clip.left;
+ m_clipRect.top = clip.top;
+ m_clipRect.right = clip.right;
+ m_clipRect.bottom = clip.bottom;
+}
+
+// Retourne la r�gion de clipping.
+
+RECT CPixmap::GetClipping()
+{
+ return m_clipRect;
+}
+
+
+// Teste si un point fait partie d'une ic�ne.
+//Rough rewritten code, might need improvement
+
+
+
+
+// Dessine une partie d'image rectangulaire.
+// Les modes sont 0=transparent, 1=opaque.
+
+BOOL CPixmap::DrawIcon(int chDst, int channel, int rank, POINT pos,
+ int mode, BOOL bMask)
+{
+ int nbx, nby;
+ RECT rect;
+ HRESULT ddrval;
+ COLORREF oldColor1, oldColor2;
+ if (channel == CHOBJECT)
+ {
+ if (table_icon_object[0] <= rank) return FALSE;
+ rect.left = table_icon_object[rank * 6 + 0 + 1];
+ rect.top = table_icon_object[rank * 6 + 1 + 1];
+ rect.right = rect.left + table_icon_object[rank * 6 + 4 + 1];
+ rect.bottom = rect.top + table_icon_object[rank * 6 + 5 + 1];
+ pos.x += table_icon_object[rank * 6 + 2 + 1];
+ pos.y += table_icon_object[rank * 6 + 3 + 1];
+ }
+ else if (channel == CHELEMENT)
+ {
+ if (table_icon_element[0] <= rank) return FALSE;
+ rect.left = table_icon_element[rank * 6 + 0 + 1];
+ rect.top = table_icon_element[rank * 6 + 1 + 1];
+ rect.right = rect.left + table_icon_element[rank * 6 + 4 + 1];
+ rect.bottom = rect.top + table_icon_element[rank * 6 + 5 + 1];
+ pos.x += table_icon_element[rank * 6 + 2 + 1];
+ pos.y += table_icon_element[rank * 6 + 3 + 1];
+ }
+ else if (IsBlupiChannel(channel))
+ {
+ if (table_icon_blupi[0] <= rank) return FALSE;
+ rect.left = table_icon_blupi[rank * 6 + 0 + 1];
+ rect.top = table_icon_blupi[rank * 6 + 1 + 1];
+ rect.right = rect.left + table_icon_blupi[rank * 6 + 4 + 1];
+ rect.bottom = rect.top + table_icon_blupi[rank * 6 + 5 + 1];
+ pos.x += table_icon_blupi[rank * 6 + 2 + 1];
+ pos.y += table_icon_blupi[rank * 6 + 3 + 1];
+ }
+ else if (channel == CHEXPLO)
+ {
+ if (table_icon_explo[0] <= rank) return FALSE;
+ rect.left = table_icon_explo[rank * 6 + 0 + 1];
+ rect.top = table_icon_explo[rank * 6 + 1 + 1];
+ rect.right = rect.left + table_icon_explo[rank * 6 + 4 + 1];
+ rect.bottom = rect.top + table_icon_explo[rank * 6 + 5 + 1];
+ pos.x += table_icon_explo[rank * 6 + 2 + 1];
+ pos.y += table_icon_explo[rank * 6 + 3 + 1];
+ }
+ else
+ {
+ if (channel < 0 || channel >= MAXIMAGE) return FALSE;
+ if (m_lpDDSurface[channel] == NULL) return FALSE;
+ if (m_iconDim[channel].x == 0 ||
+ m_iconDim[channel].y == 0) return FALSE;
+
+ nbx = m_totalDim[channel].x / m_iconDim[channel].x;
+ nby = m_totalDim[channel].y / m_iconDim[channel].y;
+
+ if (rank < 0 || rank >= nbx * nby) return FALSE;
+
+ rect.left = (rank%nbx)*m_iconDim[channel].x;
+ rect.top = (rank / nbx)*m_iconDim[channel].y;
+ rect.right = rect.left + m_iconDim[channel].x;
+ rect.bottom = rect.top + m_iconDim[channel].y;
+ }
+
+ oldColor1 = m_colorSurface[2*channel+0];
+ oldColor2 = m_colorSurface[2*channel+1];
+ if ( bMask ) SetTransparent(channel, RGB(255,255,255)); // blanc
+ ddrval = BltFast(chDst, channel, pos, rect, mode);
+ if ( bMask ) SetTransparent2(channel, oldColor1, oldColor2);
+
+ if ( ddrval != DD_OK ) return FALSE;
+ return TRUE;
+}
+
+// Dessine une partie d'image rectangulaire.
+// Les modes sont 0=transparent, 1=opaque.
+//
+// Correspondances in,out :
+// 0,0 2,1 ...
+// 1,16 3,17
+//
+// 32,32 34,33
+// 33,48 35,49
+
+BOOL CPixmap::DrawIconDemi(int chDst, int channel, int rank, POINT pos,
+ int mode, BOOL bMask)
+{
+ int nbx, nby;
+ RECT rect;
+ HRESULT ddrval;
+ COLORREF oldColor1, oldColor2;
+
+ if ( channel < 0 || channel >= MAXIMAGE ) return FALSE;
+ if ( m_lpDDSurface[channel] == NULL ) return FALSE;
+
+ if ( m_iconDim[channel].x == 0 ||
+ m_iconDim[channel].y == 0 ) return FALSE;
+
+ nbx = m_totalDim[channel].x / m_iconDim[channel].x;
+ nby = m_totalDim[channel].y / (m_iconDim[channel].y/2);
+
+ rank = (rank/32)*32+((rank%32)/2)+((rank%2)*16);
+
+ if ( rank < 0 || rank >= nbx*nby ) return FALSE;
+
+ rect.left = (rank%nbx)* m_iconDim[channel].x;
+ rect.top = (rank/nbx)*(m_iconDim[channel].y/2);
+ rect.right = rect.left + m_iconDim[channel].x;
+ rect.bottom = rect.top +(m_iconDim[channel].y/2);
+
+ oldColor1 = m_colorSurface[2*channel+0];
+ oldColor2 = m_colorSurface[2*channel+1];
+ if ( bMask ) SetTransparent(channel, RGB(255,255,255)); // blanc
+ ddrval = BltFast(chDst, channel, pos, rect, mode);
+ if ( bMask ) SetTransparent2(channel, oldColor1, oldColor2);
+
+ if ( ddrval != DD_OK ) return FALSE;
+ return TRUE;
+}
+
+// Dessine une partie d'image rectangulaire.
+// Les modes sont 0=transparent, 1=opaque.
+
+BOOL CPixmap::DrawIconPart(int chDst, int channel, int rank, POINT pos,
+ int startY, int endY,
+ int mode, BOOL bMask)
+{
+ int nbx, nby;
+ RECT rect;
+ HRESULT ddrval;
+ COLORREF oldColor1, oldColor2;
+
+ if ( channel < 0 || channel >= MAXIMAGE ) return FALSE;
+ if ( m_lpDDSurface[channel] == NULL ) return FALSE;
+
+ if ( m_iconDim[channel].x == 0 ||
+ m_iconDim[channel].y == 0 ) return FALSE;
+
+ nbx = m_totalDim[channel].x / m_iconDim[channel].x;
+ nby = m_totalDim[channel].y / m_iconDim[channel].y;
+
+ if ( rank < 0 || rank >= nbx*nby ) return FALSE;
+
+ rect.left = (rank%nbx)*m_iconDim[channel].x;
+ rect.top = (rank/nbx)*m_iconDim[channel].y;
+ rect.right = rect.left + m_iconDim[channel].x;
+ rect.bottom = rect.top + endY;
+
+ pos.y += startY;
+ rect.top += startY;
+
+ oldColor1 = m_colorSurface[2*channel+0];
+ oldColor2 = m_colorSurface[2*channel+1];
+ if ( bMask ) SetTransparent(channel, RGB(255,255,255)); // blanc
+ ddrval = BltFast(chDst, channel, pos, rect, mode);
+ if ( bMask ) SetTransparent2(channel, oldColor1, oldColor2);
+
+ if ( ddrval != DD_OK ) return FALSE;
+ return TRUE;
+}
+
+// Dessine une partie d'image n'importe o�.
+// Les modes sont 0=transparent, 1=opaque.
+
+BOOL CPixmap::DrawPart(int chDst, int channel, POINT dest, RECT rect,
+ int mode, BOOL bMask)
+{
+ HRESULT ddrval;
+ COLORREF oldColor1, oldColor2;
+
+ if ( channel < 0 || channel >= MAXIMAGE ) return FALSE;
+ if ( m_lpDDSurface[channel] == NULL ) return FALSE;
+
+ oldColor1 = m_colorSurface[2*channel+0];
+ oldColor2 = m_colorSurface[2*channel+1];
+ if ( bMask ) SetTransparent(channel, RGB(255,255,255)); // blanc
+ ddrval = BltFast(chDst, channel, dest, rect, mode);
+ if ( bMask ) SetTransparent2(channel, oldColor1, oldColor2);
+
+ if ( ddrval != DD_OK ) return FALSE;
+ return TRUE;
+}
+
+// Dessine une partie d'image rectangulaire.
+// Les modes sont 0=transparent, 1=opaque.
+
+BOOL CPixmap::DrawImage(int chDst, int channel, RECT rect, int mode)
+{
+ POINT dst;
+ HRESULT ddrval;
+
+ if ( channel < 0 || channel >= MAXIMAGE ) return FALSE;
+ if ( m_lpDDSurface[channel] == NULL ) return FALSE;
+
+ dst.x = rect.left;
+ dst.y = rect.top;
+
+ ddrval = BltFast(chDst, channel, dst, rect, mode);
+
+ if ( ddrval != DD_OK ) return FALSE;
+
+ if ( channel == CHBACK )
+ {
+ MouseBackSave(); // sauve ce qui sera sous la souris
+ m_bBackDisplayed = FALSE;
+ }
+
+ return TRUE;
+}
+
+
+// Construit une ic�ne en utilisant un masque.
+
+BOOL CPixmap::BuildIconMask(int channelMask, int rankMask,
+ int channel, int rankSrc, int rankDst)
+{
+ int nbx, nby;
+ POINT posDst;
+ RECT rect;
+ HRESULT ddrval;
+
+ if ( channel < 0 || channel >= MAXIMAGE ) return FALSE;
+ if ( m_lpDDSurface[channel] == NULL ) return FALSE;
+
+ if ( m_iconDim[channel].x == 0 ||
+ m_iconDim[channel].y == 0 ) return FALSE;
+
+ nbx = m_totalDim[channel].x / m_iconDim[channel].x;
+ nby = m_totalDim[channel].y / m_iconDim[channel].y;
+
+ if ( rankSrc < 0 || rankSrc >= nbx*nby ) return FALSE;
+ if ( rankDst < 0 || rankDst >= nbx*nby ) return FALSE;
+
+ rect.left = (rankSrc%nbx)*m_iconDim[channel].x;
+ rect.top = (rankSrc/nbx)*m_iconDim[channel].y;
+ rect.right = rect.left + m_iconDim[channel].x;
+ rect.bottom = rect.top + m_iconDim[channel].y;
+ posDst.x = (rankDst%nbx)*m_iconDim[channel].x;
+ posDst.y = (rankDst/nbx)*m_iconDim[channel].y;
+ ddrval = BltFast(m_lpDDSurface[channel], channel, posDst, rect, 1);
+ if ( ddrval != DD_OK ) return FALSE;
+
+ if ( m_iconDim[channelMask].x == 0 ||
+ m_iconDim[channelMask].y == 0 ) return FALSE;
+
+ nbx = m_totalDim[channelMask].x / m_iconDim[channelMask].x;
+ nby = m_totalDim[channelMask].y / m_iconDim[channelMask].y;
+
+ if ( rankMask < 0 || rankMask >= nbx*nby ) return FALSE;
+
+ rect.left = (rankMask%nbx)*m_iconDim[channelMask].x;
+ rect.top = (rankMask/nbx)*m_iconDim[channelMask].y;
+ rect.right = rect.left + m_iconDim[channelMask].x;
+ rect.bottom = rect.top + m_iconDim[channelMask].y;
+ ddrval = BltFast(m_lpDDSurface[channel], channelMask, posDst, rect, 0);
+ if ( ddrval != DD_OK ) return FALSE;
+
+ return TRUE;
+}
+
+
+// Affiche le pixmap � l'�cran.
+// Retourne FALSE en cas d'erreur.
+
+BOOL CPixmap::Display()
+{
+ HRESULT ddrval;
+ RECT DestRect, MapRect;
+
+ m_bBackDisplayed = TRUE;
+
+ // Get screen coordinates of client window for blit
+ GetClientRect(m_hWnd, &DestRect);
+ ClientToScreen(m_hWnd, (LPPOINT)&DestRect);
+ ClientToScreen(m_hWnd, (LPPOINT)&DestRect+1);
+
+ MapRect.left = 0;
+ MapRect.top = 0;
+ MapRect.right = m_dim.x;
+ MapRect.bottom = m_dim.y;
+
+ // do the blit from back surface
+ ddrval = m_lpDDSPrimary->Blt
+ (
+ &DestRect, // destination rect
+ m_lpDDSBack,
+ &MapRect, // source rect
+ DDBLT_WAIT,
+ &m_DDbltfx
+ );
+ if ( ddrval == DDERR_SURFACELOST )
+ {
+ ddrval = RestoreAll();
+ }
+ if ( ddrval != DD_OK ) return FALSE;
+ return TRUE;
+}
+
+
+// Positionne la souris et change le lutin.
+
+void CPixmap::SetMousePosSprite(POINT pos, int sprite, BOOL bDemoPlay)
+{
+ if ( m_mousePos.x == pos.x &&
+ m_mousePos.y == pos.y &&
+ m_mouseSprite == sprite ) return;
+
+ m_mousePos = pos;
+ m_mouseSprite = sprite;
+ MouseHotSpot();
+
+ if ( !bDemoPlay )
+ {
+ MouseUpdate();
+ }
+}
+
+/*
+// Positionne la souris.
+
+void CPixmap::SetMousePos(POINT pos, BOOL bDemoPlay)
+{
+ if ( m_mousePos.x == pos.x &&
+ m_mousePos.y == pos.y ) return;
+
+ m_mousePos = pos;
+
+ if ( !bDemoPlay )
+ {
+ MouseUpdate();
+ }
+}
+*/
+
+// Change le lutin de la souris.
+
+void CPixmap::SetMouseSprite(int sprite, BOOL bDemoPlay)
+{
+ if ( m_mouseSprite == sprite ) return;
+
+ m_mouseSprite = sprite;
+ MouseHotSpot();
+
+ if ( !bDemoPlay )
+ {
+ MouseUpdate();
+ }
+}
+
+// Montre ou cache la souris.
+
+void CPixmap::MouseShow(BOOL bShow)
+{
+ m_bMouseShow = bShow;
+}
+
+// Met � jour le dessin de la souris.
+
+void CPixmap::MouseUpdate()
+{
+ RECT oldRect, newRect, rcRect;
+
+ if ( m_lpDDSurface[CHELEMENT] == NULL ) return;
+ if ( m_mouseType != MOUSETYPEGRA ) return;
+ if ( m_mouseSprite == SPRITE_EMPTY ) return;
+ if (m_mouseSprite == SPRITE_DISABLE) return;
+ if ( !m_bMouseShow ) return;
+
+ oldRect.left = m_mouseBackPos.x;
+ oldRect.top = m_mouseBackPos.y;
+ oldRect.right = m_mouseBackPos.x + DIMBLUPIX;
+ oldRect.bottom = m_mouseBackPos.y + DIMBLUPIY;
+
+ newRect.left = m_mousePos.x - m_mouseHotSpot.x;
+ newRect.top = m_mousePos.y - m_mouseHotSpot.y;
+ newRect.right = newRect.left + DIMBLUPIX;
+ newRect.bottom = newRect.top + DIMBLUPIY;
+
+ MouseBackRestore(); // enl�ve la souris dans m_lpDDSBack
+ MouseBackDraw(); // dessine la souris dans m_lpDDSBack
+
+ if ( m_bBackDisplayed )
+ {
+ if ( IntersectRect(&rcRect, &oldRect, &newRect) )
+ {
+ UnionRect(&rcRect, &oldRect, &newRect);
+ MouseQuickDraw(rcRect);
+ }
+ else
+ {
+ MouseQuickDraw(oldRect);
+ MouseQuickDraw(newRect);
+ }
+ }
+}
+
+// Dessine rapidement la souris dans l'�cran.
+// Il s'agit en fait de dessiner un petit morceau rectangulaire
+// de m_lpDDSBack dans l'�cran.
+
+BOOL CPixmap::MouseQuickDraw(RECT rect)
+{
+ HRESULT ddrval;
+ RECT DestRect;
+
+ if ( rect.left < 0 ) rect.left = 0;
+ if ( rect.right > LXIMAGE ) rect.right = LXIMAGE;
+ if ( rect.top < 0 ) rect.top = 0;
+ if ( rect.bottom > LYIMAGE ) rect.bottom = LYIMAGE;
+
+ // Get screen coordinates of client window for blit
+ DestRect = rect;
+ ClientToScreen(m_hWnd, (LPPOINT)&DestRect);
+ ClientToScreen(m_hWnd, (LPPOINT)&DestRect+1);
+
+ // do the blit from back surface
+ ddrval = m_lpDDSPrimary->Blt
+ (
+ &DestRect, // destination rect
+ m_lpDDSBack,
+ &rect, // source rect
+ DDBLT_WAIT,
+ &m_DDbltfx
+ );
+ if ( ddrval == DDERR_SURFACELOST )
+ {
+ ddrval = RestoreAll();
+ }
+ if ( ddrval != DD_OK ) return FALSE;
+ return TRUE;
+}
+
+// Invalide la copie sous la souris.
+
+void CPixmap::MouseInvalidate()
+{
+ m_bMouseBack = FALSE;
+}
+
+// Enl�ve la souris dans m_lpDDSBack.
+
+void CPixmap::MouseBackClear()
+{
+ if ( m_mouseType != MOUSETYPEGRA || m_mouseSprite == SPRITE_DISABLE) return;
+ MouseBackRestore(); // enl�ve la souris dans m_lpDDSBack
+}
+
+// Dessine la souris dans m_lpDDSBack.
+
+void CPixmap::MouseBackDraw()
+{
+ POINT dst;
+ RECT rcRect;
+
+ if ( m_lpDDSurface[CHELEMENT] == NULL ) return;
+ if ( m_mouseType != MOUSETYPEGRA ) return;
+ if ( m_mouseSprite == SPRITE_EMPTY || m_mouseSprite == SPRITE_DISABLE) return;
+ if ( !m_bMouseShow ) return;
+
+ MouseBackSave(); // sauve ce qui sera sous la souris
+
+ dst.x = m_mousePos.x - m_mouseHotSpot.x;
+ dst.y = m_mousePos.y - m_mouseHotSpot.y;
+ MouseRectSprite(&rcRect, &dst);
+
+ if ( dst.x < 0 )
+ {
+ rcRect.left -= dst.x;
+ dst.x = 0;
+ }
+ if ( dst.x + rcRect.right - rcRect.left > LXIMAGE )
+ {
+ rcRect.right -= (dst.x + rcRect.right - rcRect.left)-LXIMAGE;
+ }
+ if ( dst.y < 0 )
+ {
+ rcRect.top -= dst.y;
+ dst.y = 0;
+ }
+ if ( dst.y + rcRect.bottom - rcRect.top > LYIMAGE )
+ {
+ rcRect.bottom -= (dst.y + rcRect.bottom - rcRect.top)-LYIMAGE;
+ }
+
+ // Dessine le lutin dans m_lpDDSBack.
+ BltFast(m_lpDDSBack, CHELEMENT, dst, rcRect, 0);
+}
+
+// Sauve le fond sous la souris.
+// m_lpDDSMouse <- m_lpDDSBack
+
+void CPixmap::MouseBackSave()
+{
+ HRESULT ddrval;
+ POINT dst;
+ RECT rcRect;
+
+ if ( m_lpDDSurface[CHELEMENT] == NULL ) return;
+ if ( m_mouseType != MOUSETYPEGRA ) return;
+ if ( m_mouseSprite == SPRITE_EMPTY || m_mouseSprite == SPRITE_DISABLE) return;
+ if ( !m_bMouseShow ) return;
+
+ m_mouseBackPos.x = m_mousePos.x - m_mouseHotSpot.x;
+ m_mouseBackPos.y = m_mousePos.y - m_mouseHotSpot.y;
+ m_bMouseBack = TRUE;
+
+ dst.x = 0;
+ dst.y = 0;
+
+ rcRect.left = m_mouseBackPos.x;
+ rcRect.top = m_mouseBackPos.y;
+ rcRect.right = m_mouseBackPos.x + DIMBLUPIX;
+ rcRect.bottom = m_mouseBackPos.y + DIMBLUPIY;
+
+ if ( rcRect.left < 0 )
+ {
+ dst.x -= rcRect.left;
+ rcRect.left = 0;
+ }
+ if ( rcRect.right > LXIMAGE )
+ {
+ rcRect.right = LXIMAGE;
+ }
+ if ( rcRect.top < 0 )
+ {
+ dst.y -= rcRect.top;
+ rcRect.top = 0;
+ }
+ if ( rcRect.bottom > LYIMAGE )
+ {
+ rcRect.bottom = LYIMAGE;
+ }
+
+ while( TRUE )
+ {
+ ddrval = m_lpDDSMouse->BltFast(dst.x, dst.y,
+ m_lpDDSBack,
+ &rcRect, DDBLTFAST_NOCOLORKEY);
+ if ( ddrval == DD_OK ) break;
+
+ if ( ddrval == DDERR_SURFACELOST )
+ {
+ ddrval = RestoreAll();
+ if ( ddrval != DD_OK ) break;
+ }
+
+ if ( ddrval != DDERR_WASSTILLDRAWING ) break;
+ }
+}
+
+// Restitue le fond sous la souris.
+// m_lpDDSBack <- m_lpDDSMouse
+
+void CPixmap::MouseBackRestore()
+{
+ HRESULT ddrval;
+ POINT dst;
+ RECT rcRect;
+
+ if ( m_lpDDSurface[CHELEMENT] == NULL ) return;
+ if ( !m_bMouseBack ) return;
+
+ dst.x = m_mouseBackPos.x;
+ dst.y = m_mouseBackPos.y;
+
+ rcRect.left = 0;
+ rcRect.top = 0;
+ rcRect.right = DIMBLUPIX;
+ rcRect.bottom = DIMBLUPIY;
+
+ if ( dst.x < 0 )
+ {
+ rcRect.left -= dst.x;
+ dst.x = 0;
+ }
+ if ( dst.x+ rcRect.right - rcRect.left > LXIMAGE )
+ {
+ rcRect.right -= (dst.x+ rcRect.right - rcRect.left)-LXIMAGE;
+ }
+ if ( dst.y < 0 )
+ {
+ rcRect.top -= dst.y;
+ dst.y = 0;
+ }
+ if ( dst.y+ rcRect.top - rcRect.bottom > LYIMAGE )
+ {
+ rcRect.bottom -= (dst.y+ rcRect.top - rcRect.bottom)-LYIMAGE;
+ }
+
+ while( TRUE )
+ {
+ ddrval = m_lpDDSBack->BltFast(dst.x, dst.y,
+ m_lpDDSMouse,
+ &rcRect, DDBLTFAST_NOCOLORKEY);
+ if ( ddrval == DD_OK ) break;
+
+ if ( ddrval == DDERR_SURFACELOST )
+ {
+ ddrval = RestoreAll();
+ if ( ddrval != DD_OK ) break;
+ }
+
+ if ( ddrval != DDERR_WASSTILLDRAWING ) break;
+ }
+}
+
+// Affiche le contenu de m_lpDDSMouse dans le
+// coin sup/gauche.
+
+void CPixmap::MouseBackDebug()
+{
+ HRESULT ddrval;
+ RECT DestRect, MapRect;
+
+ // Get screen coordinates of client window for blit
+ GetClientRect(m_hWnd, &DestRect);
+ ClientToScreen(m_hWnd, (LPPOINT)&DestRect);
+ ClientToScreen(m_hWnd, (LPPOINT)&DestRect+1);
+
+ MapRect.left = 0;
+ MapRect.top = 0;
+ MapRect.right = DIMBLUPIX;
+ MapRect.bottom = DIMBLUPIY;
+
+ DestRect.right = DestRect.left + DIMBLUPIX;
+ DestRect.bottom = DestRect.top + DIMBLUPIY;
+
+ // do the blit from back surface
+ ddrval = m_lpDDSPrimary->Blt
+ (
+ &DestRect, // destination rect
+ m_lpDDSMouse,
+ &MapRect, // source rect
+ DDBLT_WAIT,
+ &m_DDbltfx
+ );
+ if ( ddrval == DDERR_SURFACELOST )
+ {
+ ddrval = RestoreAll();
+ }
+}
+
+// Retourne le rectangle correspondant au sprite
+// de la souris dans CHBLUPI.
+
+void CPixmap::MouseRectSprite(RECT *rect, POINT *offset)
+{
+ int rank, nbx;
+ RECT rcRect;
+
+ rank = 37;
+ if ( m_mouseSprite == SPRITE_POINTER ) rank = 38;
+ if ( m_mouseSprite == SPRITE_WAIT ) rank = 39;
+
+ rect->left = table_icon_element[rank * 6 + 0 + 1];
+ rect->right = rect->left + table_icon_element[rank * 6 + 4 + 1];
+ rect->top = table_icon_element[rank * 6 + 1 + 1];
+ rect->bottom = rect->top + table_icon_element[rank * 6 + 5 + 1];
+ offset->x += table_icon_element[rank * 6 + 2 + 1];
+ offset->y += table_icon_element[rank * 6 + 3 + 1];
+
+ return;
+}
+
+// Initialise le hot spot selon le sprite en cours.
+
+void CPixmap::MouseHotSpot()
+{
+ int rank;
+
+ static int table_mouse_hotspot[4*2] =
+ {
+ 25, 0,
+ 30, 30, // SPRITE_ARROW
+ 20, 15, // SPRITE_POINTER
+ 30, 30, // SPRITE_EMPTY
+ };
+
+ rank = m_mouseSprite;
+ if ( m_mouseSprite >= SPRITE_ARROW &&
+ m_mouseSprite <= SPRITE_WAIT )
+ {
+ m_mouseHotSpot.x = table_mouse_hotspot[rank*2+0];
+ m_mouseHotSpot.y = table_mouse_hotspot[rank*2+1];
+ }
+ else
+ {
+ m_mouseHotSpot.x = 0;
+ m_mouseHotSpot.y = 0;
+ }
+}
+
+
+static inline BOOL IsBlupiChannel(int channel)
+{
+ return channel == CHBLUPI || channel == CHBLUPI1 || channel == CHBLUPI2 || channel == CHBLUPI3;
+}
\ No newline at end of file
diff --git a/src/pixmap.h b/src/pixmap.h
new file mode 100644
index 0000000..0576d5b
--- /dev/null
+++ b/src/pixmap.h
@@ -0,0 +1,129 @@
+// CPixmap.h
+#ifndef PIXMAP_H
+#define PIXMAP_H
+
+#include
+
+/////////////////////////////////////////////////////////////
+
+#define MAXIMAGE 100
+#define DIRECTDRAW_VERSION 0x0500 // ????????????
+
+class CPixmap
+{
+public:
+ CPixmap();
+ ~CPixmap();
+
+ void SetDebug(BOOL bDebug);
+
+ BOOL Create(HWND hwnd, POINT dim, BOOL bFullScreen, int mouseType, BOOL bTrueColor, BOOL bTrueColorDecor);
+ BOOL Flush();
+ BOOL Restore();
+ BOOL InitSysPalette();
+ BOOL IsPalette();
+ void Fill(RECT rect, COLORREF color);
+
+ BOOL SavePalette();
+ BOOL RestorePalette();
+ int SearchColor(int red, int green, int blue);
+ BOOL Cache(int channel, char *pFilename, POINT totalDim, POINT iconDim, BOOL bUsePalette);
+ BOOL Cache(int channel, HBITMAP hbm, POINT totalDim);
+ BOOL BackgroundCache(int channel, const char* pFilename, POINT totalDim, POINT iconDim, BOOL bUsePalette);
+ BOOL CacheAll(BOOL cache, HWND hWnd, BOOL bFullScreen, BOOL bTrueColor, BOOL bTrueColorDecor, int mouseType, const char* pFilename, int region);
+ int Benchmark();
+ void Flush(int channel);
+ void SetTransparent(int channel, COLORREF color);
+ void SetTransparent2(int channel, COLORREF color1, COLORREF color2);
+ void SetClipping(RECT clip);
+ RECT GetClipping();
+ void HudIcon(int channel, int rank, POINT pos);
+ void QuickIcon(int channel, int rank, POINT pos);
+
+ BOOL IsIconPixel(int channel, int rank, POINT pos);
+
+ void DrawChar(int rank, POINT pos, double size);
+ BOOL DrawIcon(int chDst, int channel, int rank, POINT pos, int mode=0, BOOL bMask=FALSE);
+ BOOL DrawIconDemi(int chDst, int channel, int rank, POINT pos, int mode=0, BOOL bMask=FALSE);
+ BOOL DrawIconPart(int chDst, int channel, int rank, POINT pos, int startY, int endY, int mode=0, BOOL bMask=FALSE);
+ BOOL DrawPart(int chDst, int channel, POINT dest, RECT rect, int mode=0, BOOL bMask=FALSE);
+ BOOL DrawImage(int chDst, int channel, RECT rect, int mode=0);
+ BOOL DrawMap(int channel, RECT src, RECT dest);
+
+ BOOL BuildIconMask(int channelMask, int rankMask,
+ int channel, int rankSrc, int rankDst);
+
+ BOOL Display();
+
+ void SetMousePosSprite(POINT pos, int sprite, BOOL bDemoPlay);
+ void SetMousePos(POINT pos, BOOL bDemoPlay);
+ void SetMouseSprite(int sprite, BOOL bDemoPlay);
+ void MouseShow(BOOL bShow);
+ void MouseInvalidate();
+ void MouseBackClear();
+ void MouseBackDraw();
+ void SetBenchmarkSuccess(BOOL bSuccess);
+ void SetTrueColorBack(BOOL bTrueColor);
+ void SetTrueColorDecor(BOOL bTrueColorDecor);
+ BOOL GetTrueColorBack();
+ BOOL GetTrueColorDecor();
+
+protected:
+ HRESULT RestoreAll();
+ HRESULT BltFast(int chDst, int channel, POINT dst, RECT rcRect, int mode);
+ HRESULT BltFast(LPDIRECTDRAWSURFACE lpDD,
+ int channel, POINT dst, RECT rcRect, int mode);
+
+ void MouseUpdate();
+ BOOL MouseQuickDraw(RECT rect);
+ void MouseBackSave();
+ void MouseBackRestore();
+ void MouseBackDebug();
+ void MouseRectSprite(RECT *rect, POINT *offset);
+ void MouseHotSpot();
+
+
+
+protected:
+ BOOL m_bFullScreen;
+ BOOL m_bBenchmarkSuccess;
+ BOOL m_bTrueColorBack;
+ BOOL m_bTrueColorDecor;
+ BOOL m_field5_0x14; //Need to figure out
+ BOOL m_field5_0x18; //Need to figure out
+ int m_mouseType;
+ BOOL m_bDebug;
+ BOOL m_bPalette;
+ HWND m_hWnd;
+ POINT m_dim;
+ RECT m_clipRect;
+
+ POINT m_mousePos;
+ int m_mouseSprite;
+ POINT m_mouseHotSpot;
+ POINT m_mouseBackPos;
+ BOOL m_bMouseBack;
+ BOOL m_bMouseShow;
+ BOOL m_bBackDisplayed;
+
+ LPDIRECTDRAW m_lpDD;
+ LPDIRECTDRAWSURFACE m_lpDDSPrimary;
+ LPDIRECTDRAWSURFACE m_lpDDSBack;
+ LPDIRECTDRAWSURFACE m_lpDDSMouse;
+ IDirectDrawPalette* m_lpDDPal;
+ LPDIRECTDRAWSURFACE m_lpDDSurface[MAXIMAGE];
+ LPDIRECTDRAWCLIPPER m_lpClipper;
+ PALETTEENTRY m_pal[256];
+ PALETTEENTRY m_sysPal[256];
+ COLORREF m_colorSurface[2*MAXIMAGE];
+
+ char m_filename[MAXIMAGE][20];
+ POINT m_totalDim[MAXIMAGE];
+ POINT m_iconDim[MAXIMAGE];
+ DDBLTFX m_DDbltfx;
+
+};
+
+static inline BOOL IsBlupiChannel(int channel);
+
+#endif
\ No newline at end of file
diff --git a/src/pixtables.h b/src/pixtables.h
new file mode 100644
index 0000000..ca797ae
--- /dev/null
+++ b/src/pixtables.h
@@ -0,0 +1,1201 @@
+#ifndef PIXTABLES_H
+#define PIXTABLES_H
+
+// keep these structs for reference
+/*
+typedef struct {
+ short x;
+ short y;
+} ShortPOINT;
+
+typedef struct {
+ ShortPOINT pos;
+ ShortPOINT offset;
+ ShortPOINT size;
+} IconPack;
+*/
+
+
+extern short table_icon_blupi[] = {
+ 336,
+ 202,185, 17,9, 32,49,
+ 194,234, 17,8, 28,50,
+ 33,284, 12,8, 35,50,
+ 222,234, 15,8, 28,50,
+ 609,91, 11,12, 32,46,
+ 614,335, 18,7, 33,52,
+ 430,234, 19,8, 32,50,
+ 462,234, 19,8, 32,50,
+ 647,335, 18,7, 33,52,
+ 494,234, 19,8, 32,50,
+ 706,284, 19,8, 32,51,
+ 680,335, 12,7, 33,52,
+ 526,234, 12,8, 32,50,
+ 558,234, 12,8, 32,50,
+ 713,335, 12,7, 33,52,
+ 718,234, 11,8, 33,50,
+ 96,335, 11,8, 33,51,
+ 108,91, 16,15, 37,43,
+ 527,185, 15,11, 37,49,
+ 564,185, 14,11, 37,49,
+ 145,91, 7,15, 37,43,
+ 601,185, 8,11, 37,49,
+ 0,387, 9,8, 36,52,
+ 590,234, 17,8, 32,50,
+ 622,234, 11,8, 32,50,
+ 541,494, 8,2, 33,57,
+ 433,137, 19,10, 33,48,
+ 362,185, 20,9, 33,49,
+ 73,137, 20,11, 36,47,
+ 219,551, 9,2, 34,58,
+ 273,137, 8,10, 32,48,
+ 395,185, 7,9, 33,49,
+ 0,137, 4,12, 36,46,
+ 138,284, 15,10, 36,50,
+ 252,91, 16,15, 36,44,
+ 0,91, 19,19, 37,39,
+ 598,137, 7,12, 36,48,
+ 288,91, 5,15, 36,44,
+ 37,91, 1,19, 37,39,
+ 0,57, 6,18, 47,32,
+ 673,25, 8,18, 46,32,
+ 305,137, 14,10, 32,48,
+ 68,284, 13,8, 35,50,
+ 169,440, 11,4, 40,54,
+ 738,284, 13,9, 32,51,
+ 644,284, 15,9, 31,51,
+ 288,494, 10,5, 42,55,
+ 435,387, 9,8, 51,52,
+ 779,0, 21,32, 17,25,
+ 570,91, 21,14, 39,45,
+ 737,91, 25,13, 34,46,
+ 182,91, 24,13, 35,44,
+ 36,137, 22,12, 37,46,
+ 357,91, 25,13, 34,45,
+ 460,91, 23,13, 36,45,
+ 496,91, 2,14, 37,45,
+ 391,91, 2,13, 34,45,
+ 217,91, 2,13, 35,44,
+ 533,91, 2,13, 37,45,
+ 324,91, 2,13, 33,45,
+ 425,91, 2,13, 35,45,
+ 683,846, 4,0, 48,60,
+ 363,846, 7,0, 45,60,
+ 177,668, 4,1, 47,59,
+ 86,668, 6,1, 45,59,
+ 498,846, 5,0, 46,60,
+ 731,846, 8,0, 48,60,
+ 408,846, 8,0, 45,60,
+ 131,668, 9,1, 46,59,
+ 636,846, 8,0, 47,60,
+ 544,846, 9,0, 46,60,
+ 590,846, 3,0, 46,60,
+ 691,609, 10,1, 41,59,
+ 321,846, 9,0, 42,60,
+ 0,668, 10,1, 43,59,
+ 453,846, 11,0, 45,60,
+ 47,57, 6,18, 47,32,
+ 141,57, 5,18, 48,32,
+ 635,57, 2,17, 57,32,
+ 333,57, 3,18, 49,32,
+ 382,57, 4,18, 49,32,
+ 189,57, 5,18, 48,32,
+ 719,25, 8,18, 46,32,
+ 237,57, 8,18, 48,32,
+ 692,57, 1,17, 58,32,
+ 431,57, 8,18, 49,32,
+ 285,57, 8,18, 48,32,
+ 94,57, 8,18, 47,32,
+ 480,57, 4,18, 49,32,
+ 532,25, 7,18, 53,31,
+ 529,57, 5,17, 52,32,
+ 581,57, 0,17, 54,32,
+ 585,25, 0,17, 60,31,
+ 180,137, 16,5, 31,48,
+ 234,185, 15,4, 32,49,
+ 654,234, 15,3, 32,50,
+ 0,335, 15,2, 32,51,
+ 582,335, 15,3, 32,52,
+ 543,387, 15,4, 31,53,
+ 337,137, 13,5, 32,48,
+ 266,185, 14,4, 32,49,
+ 686,234, 14,3, 32,50,
+ 32,335, 14,2, 32,51,
+ 551,335, 15,3, 31,52,
+ 574,387, 15,4, 32,53,
+ 638,185, 10,4, 37,49,
+ 596,284, 6,3, 48,50,
+ 486,387, 2,1, 57,52,
+ 117,440, 2,2, 52,53,
+ 606,387, 7,4, 39,53,
+ 603,440, 3,6, 56,54,
+ 498,335, 4,9, 53,51,
+ 659,440, 3,6, 56,54,
+ 715,440, 2,6, 58,54,
+ 330,440, 3,6, 54,54,
+ 289,440, 9,6, 41,54,
+ 438,440, 1,6, 55,54,
+ 0,494, 2,6, 58,54,
+ 493,440, 5,6, 55,54,
+ 384,440, 6,6, 54,54,
+ 548,440, 5,6, 55,54,
+ 36,387, 21,8, 37,52,
+ 675,185, 20,8, 38,49,
+ 713,185, 20,9, 38,49,
+ 287,284, 20,9, 39,50,
+ 706,137, 20,9, 37,48,
+ 211,284, 20,8, 38,50,
+ 184,387, 2,8, 38,52,
+ 751,185, 2,8, 38,49,
+ 0,234, 2,9, 38,49,
+ 326,284, 2,9, 39,50,
+ 743,137, 3,9, 37,48,
+ 249,284, 2,8, 38,50,
+ 298,185, 17,9, 32,49,
+ 641,91, 11,12, 32,46,
+ 673,91, 17,12, 32,46,
+ 78,185, 18,9, 31,49,
+ 428,185, 13,9, 33,49,
+ 461,185, 13,9, 33,49,
+ 705,91, 11,12, 32,46,
+ 109,185, 11,9, 31,49,
+ 494,185, 14,9, 33,49,
+ 330,185, 15,9, 32,49,
+ 87,551, 1,1, 46,57,
+ 0,846, 13,0, 33,60,
+ 599,786, 20,0, 31,60,
+ 730,494, 18,0, 42,57,
+ 42,551, 13,1, 45,57,
+ 33,846, 14,0, 33,60,
+ 630,786, 9,0, 31,60,
+ 0,551, 0,0, 42,57,
+ 574,494, 11,1, 36,57,
+ 188,551, 18,0, 31,58,
+ 610,494, 17,0, 38,57,
+ 661,786, 15,0, 32,60,
+ 693,786, 9,0, 32,60,
+ 165,846, 14,0, 34,60,
+ 66,846, 16,0, 33,60,
+ 725,786, 18,0, 32,60,
+ 99,846, 12,0, 33,60,
+ 132,846, 11,0, 33,60,
+ 757,786, 10,0, 32,60,
+ 239,846, 6,0, 41,60,
+ 280,846, 6,0, 41,60,
+ 199,846, 6,0, 40,60,
+ 178,494, 15,0, 32,55,
+ 64,335, 14,0, 32,51,
+ 378,494, 11,0, 32,56,
+ 675,284, 11,0, 31,51,
+ 466,137, 19,10, 33,48,
+ 369,137, 20,10, 32,48,
+ 751,234, 20,8, 33,50,
+ 499,137, 19,10, 33,48,
+ 532,137, 8,10, 33,48,
+ 401,137, 8,10, 32,48,
+ 0,284, 7,8, 33,50,
+ 565,137, 8,10, 33,48,
+ 211,137, 18,10, 31,48,
+ 634,137, 12,10, 36,48,
+ 109,137, 10,10, 41,47,
+ 670,137, 12,10, 36,48,
+ 150,137, 11,10, 30,48,
+ 645,387, 12,5, 39,53,
+ 222,387, 12,7, 39,52,
+ 38,234, 12,9, 39,49,
+ 0,185, 12,10, 39,48,
+ 77,234, 12,9, 39,49,
+ 203,335, 12,7, 39,51,
+ 684,387, 9,5, 39,53,
+ 261,387, 9,7, 39,52,
+ 116,234, 9,9, 39,49,
+ 39,185, 9,10, 39,48,
+ 155,234, 9,9, 39,49,
+ 242,335, 9,7, 39,51,
+ 253,551, 14,0, 38,58,
+ 443,551, 8,0, 41,58,
+ 224,668, 0,0, 47,59,
+ 615,551, 0,0, 49,58,
+ 539,609, 6,0, 38,59,
+ 577,609, 4,0, 38,59,
+ 291,551, 5,0, 38,58,
+ 329,551, 8,0, 38,58,
+ 484,551, 11,0, 41,58,
+ 271,668, 13,0, 47,59,
+ 664,551, 11,0, 49,58,
+ 615,609, 16,0, 38,59,
+ 653,609, 18,0, 38,59,
+ 367,551, 17,0, 38,58,
+ 723,387, 12,5, 39,53,
+ 0,440, 9,5, 39,53,
+ 210,494, 5,3, 39,55,
+ 209,440, 4,4, 40,54,
+ 410,494, 3,2, 40,56,
+ 648,494, 6,0, 41,57,
+ 525,551, 6,0, 45,58,
+ 318,668, 6,0, 48,59,
+ 249,494, 16,3, 39,55,
+ 249,440, 16,4, 40,54,
+ 450,494, 17,2, 40,56,
+ 689,494, 13,0, 41,57,
+ 570,551, 9,0, 45,58,
+ 366,668, 6,0, 48,59,
+ 746,335, 8,6, 35,52,
+ 73,387, 8,6, 37,52,
+ 39,440, 8,5, 39,53,
+ 78,440, 9,5, 39,53,
+ 300,387, 7,6, 43,52,
+ 281,335, 8,7, 42,51,
+ 323,335, 9,7, 42,51,
+ 365,335, 10,7, 42,51,
+ 343,387, 8,6, 43,52,
+ 407,335, 8,7, 43,51,
+ 129,335, 12,9, 37,51,
+ 174,284, 11,10, 37,50,
+ 502,284, 10,8, 47,50,
+ 450,335, 10,7, 48,51,
+ 386,387, 10,6, 49,52,
+ 510,668, 3,0, 57,59,
+ 0,609, 4,1, 56,58,
+ 567,668, 3,0, 57,59,
+ 624,668, 2,0, 58,59,
+ 287,609, 0,1, 60,58,
+ 682,668, 2,0, 58,59,
+ 414,668, 6,0, 48,59,
+ 462,668, 6,0, 48,59,
+ 740,668, 0,0, 58,59,
+ 347,609, 0,1, 60,58,
+ 290,727, 1,0, 59,59,
+ 0,727, 1,0, 58,59,
+ 56,609, 2,1, 56,58,
+ 58,727, 1,0, 58,59,
+ 713,551, 2,1, 55,58,
+ 133,551, 4,2, 55,57,
+ 410,284, 14,8, 46,50,
+ 365,284, 15,8, 45,50,
+ 549,284, 1,8, 47,50,
+ 456,284, 1,8, 46,50,
+ 690,0, 7,36, 44,24,
+ 648,0, 8,36, 42,24,
+ 570,0, 10,36, 38,24,
+ 536,0, 12,36, 34,24,
+ 608,0, 9,36, 40,24,
+ 734,0, 7,36, 45,24,
+ 140,185, 18,9, 31,49,
+ 306,234, 18,8, 31,50,
+ 337,234, 18,8, 31,50,
+ 330,494, 6,3, 48,55,
+ 490,494, 3,0, 51,56,
+ 250,234, 17,8, 28,50,
+ 103,284, 13,8, 35,50,
+ 278,234, 15,8, 28,50,
+ 467,609, 10,1, 36,59,
+ 503,609, 11,1, 36,59,
+ 405,551, 10,1, 38,58,
+ 43,668, 5,1, 43,59,
+ 732,609, 11,1, 42,59,
+ 504,25, 15,15, 28,31,
+ 448,25, 15,16, 28,29,
+ 108,0, 15,18, 28,20,
+ 360,0, 15,16, 28,23,
+ 476,25, 15,13, 28,30,
+ 645,25, 15,13, 28,32,
+ 388,0, 15,18, 28,23,
+ 136,0, 15,21, 28,20,
+ 202,25, 15,18, 28,27,
+ 171,185, 11,9, 31,49,
+ 368,234, 11,8, 31,50,
+ 399,234, 11,8, 31,50,
+ 110,387, 14,7, 37,52,
+ 147,387, 14,7, 37,52,
+ 166,335, 14,8, 37,51,
+ 116,727, 0,1, 58,59,
+ 174,727, 1,1, 58,59,
+ 169,609, 1,2, 59,58,
+ 232,727, 2,1, 58,59,
+ 112,609, 3,2, 57,58,
+ 59,786, 0,1, 60,59,
+ 119,786, 0,1, 60,59,
+ 179,786, 0,1, 60,59,
+ 349,727, 1,1, 59,59,
+ 239,786, 0,1, 60,59,
+ 408,727, 1,1, 59,59,
+ 299,786, 0,1, 60,59,
+ 359,786, 0,1, 60,59,
+ 228,609, 1,2, 59,58,
+ 419,786, 0,1, 60,59,
+ 407,609, 0,2, 60,58,
+ 479,786, 0,1, 60,59,
+ 467,727, 1,1, 59,59,
+ 539,786, 0,1, 60,59,
+ 526,727, 1,1, 59,59,
+ 585,727, 1,1, 59,59,
+ 644,727, 1,1, 59,59,
+ 703,727, 1,1, 59,59,
+ 0,786, 1,1, 59,59,
+ 58,494, 0,6, 60,54,
+ 118,494, 0,6, 60,54,
+ 279,25, 3,33, 55,27,
+ 334,25, 0,33, 59,27,
+ 416,0, 0,36, 60,23,
+ 49,0, 0,39, 59,19,
+ 476,0, 0,36, 60,23,
+ 143,25, 1,33, 59,26,
+ 393,25, 2,32, 55,28,
+ 242,137, 18,12, 31,48,
+ 74,91, 16,18, 34,42,
+ 750,57, 14,25, 40,34,
+ 0,25, 11,33, 45,25,
+ 0,0, 7,39, 49,19,
+ 311,0, 5,38, 49,22,
+ 164,0, 5,38, 49,21,
+ 213,0, 5,39, 49,21,
+ 262,0, 5,39, 49,21,
+ 45,25, 5,35, 49,25,
+ 94,25, 5,33, 49,26,
+ 230,25, 5,32, 49,27,
+};
+
+extern short table_icon_element[] = {
+ 289,
+ 308,153, 9,20, 51,40,
+ 51,194, 8,19, 52,41,
+ 730,153, 8,19, 51,41,
+ 767,194, 9,18, 49,42,
+ 0,321, 10,17, 47,43,
+ 768,278, 11,17, 44,43,
+ 207,321, 12,16, 41,44,
+ 812,278, 10,17, 44,43,
+ 47,321, 8,17, 47,43,
+ 250,236, 5,18, 51,42,
+ 680,153, 6,19, 50,41,
+ 781,153, 5,19, 51,41,
+ 0,24, 7,36, 44,24,
+ 44,24, 7,36, 44,24,
+ 803,0, 8,36, 42,24,
+ 647,0, 10,36, 38,24,
+ 367,24, 12,35, 34,25,
+ 575,0, 11,36, 36,24,
+ 723,0, 9,36, 40,24,
+ 88,24, 7,36, 44,24,
+ 435,24, 6,35, 46,25,
+ 54,50, 10,28, 39,27,
+ 187,50, 12,28, 34,28,
+ 0,50, 16,28, 27,27,
+ 255,50, 13,28, 35,28,
+ 93,50, 10,28, 40,27,
+ 290,50, 13,28, 35,28,
+ 27,50, 16,28, 27,27,
+ 221,50, 12,28, 34,28,
+ 644,50, 7,16, 49,31,
+ 548,50, 8,16, 48,31,
+ 422,50, 19,16, 25,31,
+ 472,50, 12,16, 38,31,
+ 693,50, 6,16, 50,31,
+ 596,50, 7,16, 48,31,
+ 447,50, 19,16, 25,31,
+ 510,50, 12,16, 38,31,
+ 581,24, 16,17, 29,26,
+ 442,0, 19,16, 15,22,
+ 396,584, 14,1, 33,59,
+ 666,321, 11,12, 37,46,
+ 703,321, 11,12, 37,46,
+ 740,321, 11,12, 37,46,
+ 830,116, 11,22, 37,37,
+ 325,50, 11,31, 38,28,
+ 277,0, 6,41, 47,19,
+ 49,368, 5,12, 51,48,
+ 525,418, 5,8, 51,52,
+ 132,24, 7,0, 44,24,
+ 176,24, 7,0, 44,24,
+ 845,0, 8,0, 42,24,
+ 685,0, 10,0, 38,24,
+ 401,24, 12,0, 34,25,
+ 611,0, 11,0, 36,24,
+ 763,0, 9,0, 40,24,
+ 220,24, 7,0, 44,24,
+ 481,24, 6,0, 46,25,
+ 447,153, 6,18, 45,41,
+ 103,194, 3,18, 52,41,
+ 155,194, 3,18, 52,41,
+ 442,194, 0,18, 60,41,
+ 265,194, 1,18, 59,41,
+ 359,153, 9,18, 44,41,
+ 324,194, 1,18, 59,41,
+ 207,194, 2,18, 58,41,
+ 832,153, 7,18, 51,41,
+ 492,153, 10,18, 45,41,
+ 0,194, 7,18, 51,41,
+ 795,116, 14,23, 35,37,
+ 330,321, 10,9, 42,44,
+ 248,321, 10,9, 41,44,
+ 129,321, 11,9, 39,44,
+ 500,321, 12,8, 37,45,
+ 468,321, 14,8, 32,45,
+ 94,321, 12,9, 35,44,
+ 168,321, 10,9, 39,44,
+ 542,194, 9,10, 42,42,
+ 584,194, 8,10, 44,42,
+ 585,368, 2,9, 56,49,
+ 697,368, 0,9, 60,49,
+ 641,368, 2,9, 56,49,
+ 475,368, 3,9, 55,49,
+ 757,368, 0,9, 60,49,
+ 530,368, 3,9, 55,49,
+ 217,368, 8,9, 50,49,
+ 100,368, 17,9, 38,49,
+ 177,368, 10,9, 40,49,
+ 138,368, 5,9, 39,49,
+ 267,368, 2,9, 50,49,
+ 363,50, 1,31, 59,29,
+ 408,236, 2,16, 57,42,
+ 406,278, 0,14, 59,42,
+ 465,278, 0,12, 59,42,
+ 465,236, 2,9, 57,42,
+ 383,194, 0,7, 59,41,
+ 524,278, 0,4, 59,42,
+ 0,278, 1,2, 58,42,
+ 522,236, 2,2, 57,42,
+ 58,278, 2,16, 58,42,
+ 116,278, 2,14, 58,42,
+ 174,278, 2,12, 58,42,
+ 232,278, 2,9, 58,42,
+ 290,278, 2,7, 58,42,
+ 579,236, 2,4, 57,42,
+ 636,236, 3,2, 57,42,
+ 348,278, 2,2, 58,42,
+ 693,236, 1,16, 57,42,
+ 301,236, 4,14, 51,42,
+ 720,194, 8,12, 47,42,
+ 0,236, 6,9, 50,42,
+ 50,236, 6,7, 50,42,
+ 628,194, 7,4, 46,42,
+ 816,194, 7,2, 49,42,
+ 352,236, 2,2, 56,42,
+ 750,236, 3,16, 57,42,
+ 100,236, 9,14, 50,42,
+ 583,153, 8,12, 48,41,
+ 150,236, 8,9, 50,42,
+ 631,153, 8,7, 49,41,
+ 674,194, 10,4, 46,42,
+ 200,236, 6,2, 50,42,
+ 807,236, 3,2, 57,42,
+ 558,116, 16,25, 31,34,
+ 182,83, 9,25, 45,33,
+ 636,83, 4,25, 54,33,
+ 216,116, 3,25, 56,33,
+ 690,83, 4,25, 54,33,
+ 227,83, 9,25, 45,33,
+ 743,50, 16,25, 31,33,
+ 119,153, 25,19, 15,40,
+ 166,153, 23,19, 18,40,
+ 202,153, 22,19, 19,40,
+ 48,153, 20,19, 18,39,
+ 184,153, 18,19, 18,40,
+ 149,153, 17,19, 17,40,
+ 134,153, 17,19, 15,40,
+ 456,526, 20,3, 25,57,
+ 481,526, 19,3, 27,57,
+ 508,526, 19,3, 27,57,
+ 432,526, 21,3, 24,57,
+ 395,526, 24,3, 17,57,
+ 373,526, 27,3, 10,57,
+ 383,526, 27,3, 12,57,
+ 412,526, 23,3, 20,57,
+ 318,526, 1,3, 55,56,
+ 112,584, 2,1, 52,58,
+ 640,526, 1,2, 56,57,
+ 576,418, 1,5, 56,52,
+ 317,368, 3,5, 52,49,
+ 817,368, 8,2, 40,50,
+ 323,471, 9,2, 41,55,
+ 60,471, 7,3, 47,54,
+ 833,584, 0,0, 60,60,
+ 336,584, 0,2, 60,58,
+ 774,584, 1,0, 59,60,
+ 575,584, 2,1, 58,59,
+ 277,584, 1,2, 59,58,
+ 719,584, 2,0, 55,60,
+ 110,526, 2,2, 58,55,
+ 164,584, 0,2, 56,58,
+ 168,526, 1,5, 59,55,
+ 587,526, 5,2, 53,57,
+ 519,584, 3,0, 56,59,
+ 369,368, 5,3, 52,49,
+ 688,418, 8,5, 40,53,
+ 372,321, 5,10, 48,44,
+ 221,153, 8,14, 43,40,
+ 583,278, 0,17, 60,42,
+ 53,418, 0,8, 60,50,
+ 308,418, 0,7, 60,51,
+ 833,418, 0,5, 60,53,
+ 107,471, 0,4, 60,54,
+ 113,418, 0,8, 60,50,
+ 368,418, 0,7, 60,51,
+ 0,471, 0,5, 60,53,
+ 167,471, 0,4, 60,54,
+ 210,0, 24,11, 16,16,
+ 66,153, 5,19, 53,39,
+ 535,0, 26,34, 10,24,
+ 195,0, 21,37, 15,16,
+ 376,0, 19,35, 22,21,
+ 457,0, 14,32, 27,22,
+ 545,0, 12,32, 30,24,
+ 398,0, 8,35, 44,21,
+ 527,24, 2,35, 54,25,
+ 324,0, 5,38, 52,20,
+ 133,50, 2,32, 54,27,
+ 0,584, 12,2, 36,58,
+ 36,584, 11,2, 38,58,
+ 810,526, 13,2, 33,58,
+ 764,526, 18,2, 23,58,
+ 754,526, 25,2, 10,58,
+ 787,526, 18,2, 23,58,
+ 843,526, 13,2, 33,58,
+ 74,584, 11,2, 38,58,
+ 820,321, 7,5, 49,47,
+ 645,116, 6,14, 48,35,
+ 542,83, 5,13, 47,33,
+ 96,83, 6,11, 43,33,
+ 0,368, 4,5, 49,47,
+ 693,116, 6,14, 48,35,
+ 589,83, 8,13, 47,33,
+ 139,83, 11,11, 43,33,
+ 741,116, 0,14, 54,36,
+ 498,116, 0,13, 60,33,
+ 589,116, 2,11, 56,34,
+ 440,116, 2,13, 58,33,
+ 0,153, 9,14, 48,37,
+ 227,471, 0,6, 60,54,
+ 0,83, 15,25, 32,33,
+ 272,83, 9,25, 45,33,
+ 744,83, 4,25, 54,33,
+ 272,116, 3,25, 56,33,
+ 798,83, 4,25, 54,33,
+ 317,83, 9,25, 45,33,
+ 774,50, 16,25, 31,33,
+ 32,83, 15,25, 32,33,
+ 362,83, 9,25, 45,33,
+ 0,116, 4,25, 54,33,
+ 328,116, 3,25, 56,33,
+ 54,116, 4,25, 54,33,
+ 407,83, 9,25, 45,33,
+ 805,50, 16,25, 31,33,
+ 64,83, 15,25, 32,33,
+ 452,83, 9,25, 45,33,
+ 108,116, 4,25, 54,33,
+ 384,116, 3,25, 56,33,
+ 162,116, 4,25, 54,33,
+ 497,83, 9,25, 45,33,
+ 836,50, 16,25, 31,33,
+ 287,471, 18,4, 36,55,
+ 227,526, 9,2, 43,56,
+ 428,418, 1,6, 47,52,
+ 257,418, 2,6, 51,51,
+ 632,418, 4,6, 56,52,
+ 364,471, 12,3, 43,55,
+ 674,584, 8,0, 45,60,
+ 633,584, 9,0, 41,60,
+ 211,418, 12,8, 46,51,
+ 270,526, 9,2, 48,56,
+ 429,584, 7,0, 45,59,
+ 474,584, 4,0, 45,59,
+ 837,24, 7,34, 53,26,
+ 314,24, 6,36, 53,24,
+ 484,0, 6,37, 51,23,
+ 264,24, 5,36, 50,24,
+ 785,24, 3,34, 52,26,
+ 226,0, 6,44, 51,16,
+ 95,0, 7,47, 50,13,
+ 145,0, 7,47, 50,13,
+ 48,0, 9,51, 47,9,
+ 0,0, 8,55, 48,5,
+ 610,24, 10,34, 42,26,
+ 652,24, 10,34, 44,26,
+ 740,24, 10,34, 45,26,
+ 696,24, 10,34, 44,26,
+ 671,471, 3,3, 55,55,
+ 726,471, 3,3, 55,55,
+ 781,471, 3,3, 55,55,
+ 458,471, 4,3, 53,55,
+ 511,471, 4,3, 53,55,
+ 407,471, 5,3, 51,55,
+ 564,471, 4,3, 53,55,
+ 836,471, 3,3, 55,55,
+ 0,526, 3,3, 55,55,
+ 55,526, 3,3, 55,55,
+ 0,418, 3,6, 53,50,
+ 421,368, 3,4, 54,49,
+ 696,526, 1,1, 58,57,
+ 220,584, 1,1, 57,58,
+ 535,526, 3,1, 52,57,
+ 475,418, 6,5, 50,52,
+ 778,418, 4,3, 55,53,
+ 617,471, 5,3, 54,55,
+ 289,321, 9,9, 41,44,
+ 725,278, 7,11, 43,43,
+ 537,321, 10,8, 40,45,
+ 643,278, 11,10, 40,43,
+ 502,194, 10,11, 40,42,
+ 577,321, 9,8, 41,45,
+ 264,153, 9,10, 44,40,
+ 683,278, 7,10, 42,43,
+ 537,153, 8,13, 46,41,
+ 777,321, 10,7, 43,47,
+ 728,418, 6,3, 50,53,
+ 618,321, 7,5, 48,45,
+ 173,418, 9,6, 38,51,
+ 420,321, 5,10, 48,44,
+ 403,153, 7,14, 44,41,
+};
+
+extern short table_icon_explo[] = {
+ 100,
+ 157,0, 48,51, 32,28,
+ 253,132, 36,32, 58,61,
+ 0,541, 10,14, 107,105,
+ 113,877, 5,7, 117,116,
+ 0,761, 6,7, 116,113,
+ 345,649, 11,6, 113,112,
+ 127,437, 12,12, 110,98,
+ 206,541, 11,8, 113,107,
+ 224,342, 11,8, 111,95,
+ 304,259, 11,8, 115,83,
+ 0,259, 3,2, 123,71,
+ 129,74, 9,2, 111,51,
+ 127,995, 5,3, 118,120,
+ 336,877, 5,4, 119,118,
+ 244,1116, 2,3, 124,121,
+ 211,1361, 2,1, 125,125,
+ 124,1486, 2,2, 126,126,
+ 214,761, 2,13, 110,115,
+ 0,995, 1,10, 127,118,
+ 336,1361, 2,3, 126,125,
+ 0,1361, 10,3, 92,125,
+ 250,1486, 2,2, 126,126,
+ 368,1116, 3,7, 125,121,
+ 330,32, 2,87, 124,41,
+ 0,32, 4,96, 123,32,
+ 208,32, 4,91, 122,37,
+ 0,649, 1,20, 127,108,
+ 0,437, 1,33, 127,95,
+ 0,1237, 1,6, 127,122,
+ 319,541, 6,20, 122,108,
+ 376,1486, 25,1, 84,127,
+ 198,1613, 1,1, 127,127,
+ 0,877, 7,4, 113,116,
+ 107,541, 14,13, 99,106,
+ 235,649, 11,8, 110,111,
+ 223,259, 32,32, 81,83,
+ 116,761, 6,13, 98,115,
+ 374,1613, 35,0, 81,128,
+ 0,1116, 6,7, 122,121,
+ 0,74, 29,83, 93,45,
+ 240,74, 0,77, 128,51,
+ 81,1741, 6,0, 104,128,
+ 0,1741, 47,0, 81,128,
+ 122,1116, 6,7, 122,121,
+ 357,437, 12,24, 110,104,
+ 368,995, 16,7, 56,121,
+ 88,1613, 4,1, 110,127,
+ 0,1486, 4,2, 124,126,
+ 324,761, 3,4, 99,116,
+ 230,877, 6,2, 106,117,
+ 237,437, 8,1, 120,102,
+ 127,1237, 17,2, 110,123,
+ 360,1237, 9,4, 119,124,
+ 335,342, 0,32, 124,95,
+ 311,132, 35,35, 66,61,
+ 127,342, 19,15, 97,91,
+ 245,995, 3,3, 123,120,
+ 237,1237, 4,3, 123,123,
+ 127,649, 7,13, 108,109,
+ 92,1361, 4,2, 119,125,
+ 233,195, 3,0, 60,64,
+ 174,195, 1,0, 59,64,
+ 415,195, 2,0, 62,64,
+ 293,195, 2,0, 61,64,
+ 0,195, 0,0, 63,63,
+ 354,195, 2,0, 61,64,
+ 185,1741, 24,0, 84,144,
+ 364,1741, 10,0, 110,144,
+ 269,1741, 18,0, 95,144,
+ 0,342, 1,45, 127,83,
+ 0,132, 6,6, 54,58,
+ 436,74, 8,6, 53,58,
+ 377,132, 8,2, 54,62,
+ 200,132, 4,3, 53,61,
+ 118,195, 3,0, 56,64,
+ 63,195, 2,0, 55,64,
+ 431,132, 0,1, 52,63,
+ 152,132, 1,3, 48,61,
+ 54,132, 1,4, 49,60,
+ 103,132, 1,4, 49,60,
+ 401,74, 12,6, 35,58,
+ 368,74, 15,9, 33,55,
+ 93,74, 12,13, 36,51,
+ 454,32, 15,22, 30,42,
+ 290,0, 13,32, 29,32,
+ 105,0, 15,38, 25,26,
+ 0,0, 22,53, 15,11,
+ 325,1613, 39,0, 49,128,
+ 123,259, 14,52, 100,76,
+ 0,1613, 26,1, 88,127,
+ 15,0, 23,11, 18,17,
+ 33,0, 23,13, 21,19,
+ 130,0, 21,15, 27,27,
+ 319,0, 16,13, 36,32,
+ 167,32, 12,12, 41,36,
+ 123,32, 11,16, 44,34,
+ 355,0, 10,21, 48,32,
+ 240,0, 9,26, 50,30,
+ 189,0, 9,30, 51,28,
+ 54,0, 9,35, 51,25,
+};
+
+extern short table_icon_object[] = {
+ 441,
+ 504,687, 0,0, 64,64,
+ 568,687, 0,0, 64,64,
+ 632,687, 0,0, 64,64,
+ 696,687, 0,0, 64,64,
+ 760,687, 0,0, 64,64,
+ 824,687, 0,0, 64,64,
+ 888,687, 0,0, 64,64,
+ 952,687, 0,0, 64,64,
+ 0,751, 0,0, 64,64,
+ 64,751, 0,0, 64,64,
+ 128,751, 0,0, 64,64,
+ 192,751, 0,0, 64,64,
+ 256,751, 0,0, 64,64,
+ 320,751, 0,0, 64,64,
+ 384,751, 0,0, 64,64,
+ 961,623, 1,0, 63,64,
+ 0,687, 1,0, 63,64,
+ 448,751, 0,0, 64,64,
+ 512,751, 0,0, 64,64,
+ 553,187, 0,0, 64,58,
+ 576,751, 0,0, 64,64,
+ 814,133, 0,0, 64,53,
+ 640,751, 0,0, 64,64,
+ 704,751, 0,0, 64,64,
+ 768,751, 0,0, 64,64,
+ 878,133, 0,0, 64,53,
+ 832,751, 0,0, 64,64,
+ 892,559, 6,0, 52,64,
+ 259,84, 0,0, 64,44,
+ 789,48, 0,0, 64,35,
+ 896,751, 0,0, 64,64,
+ 960,751, 0,0, 64,64,
+ 706,369, 1,1, 63,63,
+ 769,369, 1,1, 63,63,
+ 63,687, 1,0, 63,64,
+ 0,815, 0,0, 64,64,
+ 126,432, 0,1, 64,63,
+ 64,815, 0,0, 64,64,
+ 190,432, 0,1, 64,63,
+ 254,432, 0,1, 64,63,
+ 832,369, 1,1, 63,63,
+ 318,432, 0,1, 64,63,
+ 382,432, 0,1, 64,63,
+ 446,432, 0,1, 64,63,
+ 510,432, 0,1, 64,63,
+ 159,187, 0,1, 64,54,
+ 0,84, 0,1, 64,39,
+ 917,48, 0,1, 64,36,
+ 0,0, 0,0, 1,1,
+ 1,0, 0,0, 1,1,
+ 2,0, 0,0, 1,1,
+ 3,0, 0,0, 1,1,
+ 4,0, 0,0, 1,1,
+ 5,0, 0,0, 1,1,
+ 6,0, 0,0, 1,1,
+ 7,0, 0,0, 1,1,
+ 8,0, 0,0, 1,1,
+ 9,0, 0,0, 1,1,
+ 10,0, 0,16, 1,1,
+ 11,0, 0,0, 1,1,
+ 12,0, 0,0, 1,1,
+ 13,0, 0,0, 1,1,
+ 14,0, 0,0, 1,1,
+ 15,0, 0,0, 1,1,
+ 16,0, 0,0, 1,1,
+ 17,0, 0,0, 1,1,
+ 18,0, 0,0, 1,1,
+ 19,0, 0,0, 1,1,
+ 584,48, 0,32, 64,32,
+ 0,48, 0,36, 64,28,
+ 64,48, 0,36, 64,28,
+ 302,48, 0,33, 64,31,
+ 853,48, 0,29, 64,35,
+ 128,815, 0,0, 64,64,
+ 704,187, 0,2, 62,59,
+ 946,307, 1,1, 63,62,
+ 64,559, 13,0, 37,64,
+ 402,559, 8,0, 49,64,
+ 192,815, 0,0, 64,64,
+ 256,815, 0,0, 64,64,
+ 320,815, 0,0, 64,64,
+ 384,815, 0,0, 64,64,
+ 448,815, 0,0, 64,64,
+ 512,815, 0,0, 64,64,
+ 576,815, 0,0, 64,64,
+ 640,815, 0,0, 64,64,
+ 704,815, 0,0, 64,64,
+ 768,815, 0,0, 64,64,
+ 403,623, 0,0, 62,64,
+ 832,815, 0,0, 64,64,
+ 896,815, 0,0, 64,64,
+ 960,815, 0,0, 64,64,
+ 0,307, 0,4, 64,60,
+ 64,307, 0,4, 64,60,
+ 128,307, 0,4, 64,60,
+ 192,307, 0,4, 64,60,
+ 0,879, 0,0, 64,64,
+ 64,879, 0,0, 64,64,
+ 128,879, 0,0, 64,64,
+ 730,0, 22,45, 16,19,
+ 207,84, 6,18, 52,44,
+ 251,187, 6,7, 53,55,
+ 680,247, 4,2, 56,60,
+ 617,187, 12,2, 28,59,
+ 0,187, 15,3, 35,54,
+ 465,187, 16,2, 39,58,
+ 964,133, 14,4, 34,54,
+ 189,369, 0,1, 64,62,
+ 0,369, 0,1, 63,62,
+ 253,369, 0,1, 64,62,
+ 945,84, 0,9, 64,49,
+ 0,133, 0,9, 64,49,
+ 64,133, 0,9, 64,49,
+ 128,133, 0,9, 64,49,
+ 192,133, 0,9, 64,49,
+ 256,133, 0,9, 64,49,
+ 320,133, 0,9, 64,49,
+ 384,133, 0,9, 64,49,
+ 451,559, 9,0, 49,64,
+ 500,559, 9,0, 49,64,
+ 549,559, 9,0, 49,64,
+ 598,559, 9,0, 49,64,
+ 647,559, 9,0, 49,64,
+ 696,559, 9,0, 49,64,
+ 745,559, 9,0, 49,64,
+ 794,559, 9,0, 49,64,
+ 465,623, 2,0, 62,64,
+ 527,623, 2,0, 62,64,
+ 589,623, 2,0, 62,64,
+ 651,623, 0,0, 62,64,
+ 713,623, 0,0, 62,64,
+ 775,623, 0,0, 62,64,
+ 442,307, 0,3, 64,61,
+ 506,307, 0,3, 64,61,
+ 570,307, 0,3, 64,61,
+ 317,369, 0,0, 64,62,
+ 381,369, 0,0, 64,62,
+ 445,369, 0,0, 64,62,
+ 465,0, 0,0, 64,14,
+ 192,879, 0,0, 64,64,
+ 256,879, 0,0, 64,64,
+ 320,879, 0,0, 64,64,
+ 384,879, 0,0, 64,64,
+ 448,879, 0,0, 64,64,
+ 126,687, 1,0, 63,64,
+ 512,879, 0,0, 64,64,
+ 189,687, 1,0, 63,64,
+ 895,369, 1,1, 63,63,
+ 958,369, 1,0, 63,63,
+ 576,879, 0,0, 64,64,
+ 0,432, 1,0, 63,63,
+ 63,432, 1,1, 63,63,
+ 574,432, 0,1, 64,63,
+ 63,369, 1,1, 63,62,
+ 638,432, 0,0, 64,63,
+ 252,687, 1,0, 63,64,
+ 640,879, 0,0, 64,64,
+ 126,369, 0,1, 63,62,
+ 766,187, 12,4, 40,60,
+ 806,187, 12,4, 40,60,
+ 846,187, 12,4, 40,60,
+ 886,187, 12,4, 40,60,
+ 926,187, 12,4, 40,60,
+ 966,187, 12,4, 40,60,
+ 0,247, 12,4, 40,60,
+ 40,247, 12,4, 40,60,
+ 385,84, 12,16, 40,48,
+ 425,84, 12,16, 40,48,
+ 465,84, 12,16, 40,48,
+ 505,84, 12,16, 40,48,
+ 545,84, 12,16, 40,48,
+ 585,84, 12,16, 40,48,
+ 625,84, 12,16, 40,48,
+ 665,84, 12,16, 40,48,
+ 80,247, 12,4, 40,60,
+ 120,247, 12,4, 40,60,
+ 160,247, 12,4, 40,60,
+ 200,247, 12,4, 40,60,
+ 240,247, 12,4, 40,60,
+ 280,247, 12,4, 40,60,
+ 320,247, 12,4, 40,60,
+ 360,247, 12,4, 40,60,
+ 255,495, 21,0, 22,64,
+ 370,495, 18,0, 28,64,
+ 400,247, 12,4, 40,60,
+ 704,879, 0,0, 64,64,
+ 768,879, 0,0, 64,64,
+ 832,879, 0,0, 64,64,
+ 896,879, 0,0, 64,64,
+ 960,879, 0,0, 64,64,
+ 0,943, 0,0, 64,64,
+ 64,943, 0,0, 64,64,
+ 128,943, 0,0, 64,64,
+ 192,943, 0,0, 64,64,
+ 256,943, 0,0, 64,64,
+ 320,943, 0,0, 64,64,
+ 384,943, 0,0, 64,64,
+ 448,943, 0,0, 64,64,
+ 512,943, 0,0, 64,64,
+ 104,623, 3,0, 59,64,
+ 843,559, 8,0, 49,64,
+ 576,943, 0,0, 64,64,
+ 78,0, 0,8, 64,5,
+ 448,133, 18,14, 28,50,
+ 758,133, 18,12, 28,52,
+ 223,187, 18,9, 28,55,
+ 786,133, 18,12, 28,52,
+ 476,133, 18,14, 28,50,
+ 437,187, 18,7, 28,57,
+ 736,247, 2,4, 59,60,
+ 768,307, 3,2, 58,62,
+ 648,369, 3,1, 58,63,
+ 826,307, 3,2, 59,62,
+ 795,247, 3,4, 59,60,
+ 640,943, 0,0, 64,64,
+ 704,943, 0,0, 64,64,
+ 768,943, 0,0, 64,64,
+ 832,943, 0,0, 64,64,
+ 896,943, 0,0, 64,64,
+ 960,943, 0,0, 64,64,
+ 0,1007, 0,0, 64,64,
+ 64,1007, 0,0, 64,64,
+ 128,1007, 0,0, 64,64,
+ 944,559, 6,0, 52,64,
+ 0,623, 6,0, 52,64,
+ 52,623, 6,0, 52,64,
+ 192,1007, 0,0, 64,64,
+ 256,1007, 0,0, 64,64,
+ 320,1007, 0,0, 64,64,
+ 384,1007, 0,0, 64,64,
+ 448,1007, 0,0, 64,64,
+ 512,1007, 0,0, 64,64,
+ 576,1007, 0,0, 64,64,
+ 640,1007, 0,0, 64,64,
+ 704,1007, 0,0, 64,64,
+ 277,495, 21,0, 22,64,
+ 299,495, 21,0, 22,64,
+ 315,687, 0,0, 63,64,
+ 555,369, 4,1, 46,63,
+ 181,559, 9,0, 42,64,
+ 355,559, 12,0, 47,64,
+ 265,559, 15,0, 45,64,
+ 601,369, 9,1, 47,63,
+ 504,187, 4,6, 49,58,
+ 338,0, 27,53, 5,10,
+ 768,1007, 0,0, 64,64,
+ 832,1007, 0,0, 64,64,
+ 896,1007, 0,0, 64,64,
+ 960,1007, 0,0, 64,64,
+ 0,1071, 0,0, 64,64,
+ 64,1071, 0,0, 64,64,
+ 304,187, 0,1, 64,55,
+ 504,133, 0,1, 64,50,
+ 568,133, 0,1, 64,50,
+ 163,623, 2,0, 60,64,
+ 223,623, 2,0, 60,64,
+ 694,133, 0,0, 64,51,
+ 837,623, 0,0, 62,64,
+ 128,1071, 0,0, 64,64,
+ 368,187, 0,0, 62,56,
+ 632,133, 2,0, 62,51,
+ 192,1071, 0,0, 64,64,
+ 256,1071, 0,0, 64,64,
+ 320,1071, 0,0, 64,64,
+ 151,0, 0,0, 62,8,
+ 20,0, 3,60, 58,4,
+ 430,187, 0,4, 7,57,
+ 762,307, 58,0, 6,62,
+ 384,1071, 0,0, 64,64,
+ 256,307, 0,4, 64,60,
+ 885,307, 0,0, 61,62,
+ 645,187, 5,0, 59,59,
+ 320,307, 0,4, 64,60,
+ 854,247, 1,4, 63,60,
+ 378,687, 0,0, 63,64,
+ 283,623, 4,0, 60,64,
+ 448,1071, 0,0, 64,64,
+ 634,307, 0,3, 64,61,
+ 512,1071, 0,0, 64,64,
+ 899,623, 2,0, 62,64,
+ 702,432, 0,0, 64,63,
+ 406,0, 4,0, 59,13,
+ 213,0, 1,55, 61,9,
+ 576,1071, 0,0, 64,64,
+ 640,1071, 0,0, 64,64,
+ 0,22, 0,0, 64,24,
+ 274,0, 0,55, 64,9,
+ 218,495, 0,0, 16,64,
+ 192,495, 52,0, 12,64,
+ 704,1071, 0,0, 64,64,
+ 768,1071, 0,0, 64,64,
+ 832,1071, 0,0, 64,64,
+ 896,1071, 0,0, 64,64,
+ 960,1071, 0,0, 64,64,
+ 0,1135, 0,0, 64,64,
+ 64,1135, 0,0, 64,64,
+ 128,1135, 0,0, 64,64,
+ 192,1135, 0,0, 64,64,
+ 256,1135, 0,0, 64,64,
+ 320,1135, 0,0, 64,64,
+ 384,1135, 0,0, 64,64,
+ 448,1135, 0,0, 64,64,
+ 538,0, 0,0, 64,17,
+ 602,0, 0,47, 64,17,
+ 512,1135, 0,0, 64,64,
+ 28,559, 18,0, 36,64,
+ 223,559, 22,0, 42,64,
+ 204,495, 27,0, 14,64,
+ 310,559, 0,0, 45,64,
+ 440,247, 12,4, 40,60,
+ 705,84, 12,16, 40,48,
+ 585,22, 0,1, 64,26,
+ 649,22, 0,1, 64,26,
+ 713,22, 0,1, 64,26,
+ 777,22, 0,1, 64,26,
+ 522,22, 1,1, 63,26,
+ 841,22, 0,1, 64,26,
+ 917,247, 1,0, 63,60,
+ 35,187, 2,0, 61,54,
+ 323,84, 1,0, 62,47,
+ 64,84, 1,0, 62,40,
+ 648,48, 1,0, 62,33,
+ 461,22, 2,0, 61,26,
+ 746,0, 2,0, 61,19,
+ 96,187, 1,0, 63,54,
+ 126,84, 1,0, 63,43,
+ 710,48, 1,0, 63,33,
+ 871,0, 1,0, 63,22,
+ 343,0, 1,0, 63,11,
+ 934,0, 1,0, 63,22,
+ 766,432, 0,0, 64,63,
+ 830,432, 0,0, 64,63,
+ 894,432, 0,0, 64,63,
+ 958,432, 0,0, 64,63,
+ 398,495, 18,0, 28,64,
+ 426,495, 18,0, 28,64,
+ 454,495, 18,0, 28,64,
+ 576,1135, 0,0, 64,64,
+ 640,1135, 0,0, 64,64,
+ 704,1135, 0,0, 64,64,
+ 0,495, 0,0, 64,63,
+ 768,1135, 0,0, 64,64,
+ 832,1135, 0,0, 64,64,
+ 896,1135, 0,0, 64,64,
+ 960,1135, 0,0, 64,64,
+ 0,1199, 0,0, 64,64,
+ 64,1199, 0,0, 64,64,
+ 128,1199, 0,0, 64,64,
+ 192,1199, 0,0, 64,64,
+ 256,1199, 0,0, 64,64,
+ 320,1199, 0,0, 64,64,
+ 64,495, 0,0, 64,63,
+ 384,1199, 0,0, 64,64,
+ 448,1199, 0,0, 64,64,
+ 512,1199, 0,0, 64,64,
+ 128,495, 0,0, 64,63,
+ 576,1199, 0,0, 64,64,
+ 343,623, 4,0, 60,64,
+ 441,687, 0,0, 63,64,
+ 640,1199, 0,0, 64,64,
+ 698,307, 0,0, 64,61,
+ 384,307, 4,0, 58,61,
+ 704,1199, 0,0, 64,64,
+ 768,1199, 0,0, 64,64,
+ 64,22, 0,0, 64,24,
+ 128,22, 0,0, 64,24,
+ 192,22, 0,0, 64,24,
+ 256,22, 0,2, 64,24,
+ 384,22, 0,6, 64,25,
+ 905,22, 0,13, 64,26,
+ 320,22, 0,23, 64,24,
+ 807,0, 0,35, 64,20,
+ 666,0, 0,46, 64,18,
+ 832,1199, 0,0, 64,64,
+ 896,1199, 0,0, 64,64,
+ 234,495, 23,0, 21,64,
+ 345,495, 21,0, 25,64,
+ 509,369, 23,1, 21,63,
+ 246,48, 4,33, 56,31,
+ 474,48, 5,32, 55,32,
+ 366,48, 5,32, 54,32,
+ 529,48, 4,32, 55,32,
+ 420,48, 5,32, 54,32,
+ 192,48, 5,33, 54,31,
+ 101,559, 12,0, 40,64,
+ 141,559, 12,0, 40,64,
+ 960,1199, 0,0, 64,64,
+ 0,1263, 0,0, 64,64,
+ 64,1263, 0,0, 64,64,
+ 128,1263, 0,0, 64,64,
+ 192,1263, 0,0, 64,64,
+ 256,1263, 0,0, 64,64,
+ 320,1263, 0,0, 64,64,
+ 384,1263, 0,0, 64,64,
+ 448,1263, 0,0, 64,64,
+ 512,1263, 0,0, 64,64,
+ 576,1263, 0,0, 64,64,
+ 640,1263, 0,0, 64,64,
+ 128,48, 0,36, 64,28,
+ 321,495, 20,0, 24,64,
+ 704,1263, 0,0, 64,64,
+ 768,1263, 0,0, 64,64,
+ 832,1263, 0,0, 64,64,
+ 896,1263, 0,0, 64,64,
+ 530,369, 20,0, 25,63,
+ 942,133, 22,0, 22,54,
+ 189,84, 24,0, 18,44,
+ 773,48, 24,0, 16,35,
+ 448,22, 26,0, 13,26,
+ 529,0, 28,0, 9,17,
+ 142,0, 28,0, 9,7,
+ 480,247, 12,4, 40,60,
+ 520,247, 12,4, 40,60,
+ 560,247, 12,4, 40,60,
+ 600,247, 12,4, 40,60,
+ 640,247, 12,4, 40,60,
+ 745,84, 12,16, 40,48,
+ 785,84, 12,16, 40,48,
+ 825,84, 12,16, 40,48,
+ 865,84, 12,16, 40,48,
+ 905,84, 12,16, 40,48,
+ 482,495, 18,0, 28,64,
+ 510,495, 18,0, 28,64,
+ 538,495, 18,0, 28,64,
+ 566,495, 18,0, 28,64,
+ 594,495, 18,0, 28,64,
+ 622,495, 18,0, 28,64,
+ 650,495, 18,0, 28,64,
+ 678,495, 18,0, 28,64,
+ 706,495, 18,0, 28,64,
+ 734,495, 18,0, 28,64,
+ 762,495, 18,0, 28,64,
+ 790,495, 18,0, 28,64,
+ 818,495, 18,0, 28,64,
+ 846,495, 18,0, 28,64,
+ 874,495, 18,0, 28,64,
+ 902,495, 18,0, 28,64,
+ 930,495, 18,0, 28,64,
+ 958,495, 18,0, 28,64,
+ 986,495, 18,0, 28,64,
+ 0,559, 18,0, 28,64,
+};
+
+#endif
\ No newline at end of file
diff --git a/src/resource.h b/src/resource.h
new file mode 100644
index 0000000..7f8aefa
--- /dev/null
+++ b/src/resource.h
@@ -0,0 +1,262 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Eggbert 2.rc
+//
+#pragma once
+
+
+#define TX_IONAMEEX 100
+#define TX_IOFREE 101
+#define TX_OWNMISSION 102
+#define TX_TESTMISSION 103
+#define TX_BUTTON_JOUER 104
+#define TX_BUTTON_APPRENDRE 105
+#define TX_BUTTON_QUITTER 106
+#define TX_BUTTON_PREVP 107
+#define TX_BUTTON_NEXTP 108
+#define TX_BUTTON_PLAYP 109
+#define TX_BUTTON_BUILDP 110
+#define TX_BUTTON_TERM 111
+#define TX_BUTTON_READP 112
+#define TX_BUTTON_WRITEP 113
+#define TX_BUTTON_CANCELP 114
+#define TX_BUTTON_CONTP 115
+#define TX_BUTTON_REPEAT 116
+#define TX_CHOOSEPLAYER 117
+#define TX_PLAYERSNAME 118
+#define TX_BUTTON_TERMC 119
+#define TX_CHOOSESIZE 120
+#define TX_BUTTON_HVSCROLL 121
+#define TX_BUTTON_ONLYHSCROLL 122
+#define TX_BUTTON_ONLYVSCROLL 123
+#define TX_BUTTON_TESTMISSION 124
+#define TX_PAUSE 125
+#define TX_TINY 126
+#define TX_CLEARPLAYER 127
+#define TX_SETTINGS 128
+#define TX_CHOOSEMUSIC 129
+#define TX_BUTTON_SETUP1 130
+#define TX_BUTTON_SETUP2 131
+#define TX_BUTTON_SETUP3 132
+#define TX_BUTTON_SETUP4 133
+#define TX_NOMUSIC 134
+#define TX_MUSIC1 135
+#define TX_MUSIC2 136
+#define TX_MUSIC3 137
+#define TX_MUSIC4 138
+#define TX_MUSIC5 139
+#define TX_MUSIC6 140
+#define TX_MUSIC7 141
+#define TX_MUSIC8 142
+#define TX_MUSIC9 143
+#define TX_BUTTON_REGION 144
+#define TX_DISCARDGAME 145
+#define TX_EGGBERT 146
+#define TX_DESIGNMISSION 147
+#define TX_CHOOSEGAMER 148
+#define TX_MUSIC 149
+#define TX_TRAININGNUM 150
+#define TX_MISSIONNUM 151
+#define TX_MISSIONTIME 152
+#define TX_SIZE 153
+#define TX_BUTTON_SETUP5 154
+#define TX_BUTTON_SETUP6 155
+#define TX_BUTTON_SETUP7 156
+#define TX_BUTTON_SETUP8 157
+#define TX_CONFYES 158
+#define TX_CONFNO 159
+#define TX_SETTING 160
+#define TX_SAVECURRENTMISS 161
+#define TX_SOUNDVOL 162
+#define TX_MUSICVOL 163
+#define TX_COLORDEP 164
+#define TX_INPUT 165
+#define TX_OPENMISS 166
+#define TX_READINFO 167
+#define TX_PLAYERFREE 168
+#define TX_NUMDOOROPEN 169
+#define TX_NUMDOORSOPEN 170
+#define TX_MUSIC10 171
+#define TX_WRITENAME 172
+#define TX_NONE 173
+#define TX_CONFIRM 174
+#define TX_CANCEL 175
+#define TX_YES 176
+#define TX_NO 177
+#define TX_REGION 178
+#define TX_SUS 179
+#define TX_BUTTON_SETUP 180
+#define TX_SAVES 181
+#define TX_INSERT 182
+#define TX_DELETEMISS 183
+#define TX_DELETEMISSION 184
+#define TX_NAMEOFMISS 185
+#define TX_NAMEOFMISSION 186
+#define TX_NONAME 187
+#define TX_DESIGN 188
+#define TX_MISSNUM 189
+#define TX_MISSTIME 190
+#define TX_MISSION2D 191
+#define TX_SHOWNEXT 192
+#define TX_SHOWPREV 193
+#define TX_CONTENT 194
+#define TX_SINGLEPLAYER 195
+#define TX_MUTLIPLAYER 196
+#define TX_MULTIPLAYER 196
+#define TX_GAMEPAUSE 197
+#define TX_CANCELLAST 198
+#define TX_PLAYDEMO 199
+#define TX_HADFUN 200
+#define TX_OGCREATION 201
+#define TX_WEBSITE 202
+#define TX_FULL_END1 203
+#define TX_FULL_END2 204
+#define TX_FULL_END3 205
+#define TX_FULL_END4 206
+#define TX_CHOOSECOLOR 207
+#define TX_CLICKREADY 208
+#define TX_BUTTON_SKILL 209
+#define TX_EASY 210
+#define TX_HARD 211
+#define TX_BUTTON_DEMO 212
+#define TX_DEMOREC 213
+#define TX_DEMOPLAY 214
+#define TX_SHOWCONNECTION 242
+#define TX_GAMEJOIN 247
+#define TX_CREATE_MULTIGAME 248
+#define TX_UPDATELIST 249
+#define TX_MULTI_CREATE 250
+#define TX_MULTI_GNAME 251
+#define TX_OPEN 264
+#define TX_HELP 268
+#define TX_LOAD_CGAME 269
+#define TX_SAVE_CGAME 270
+#define TX_MISSIONFREE 272
+#define TX_GAMESAVED 288
+#define TX_NOTINDEMO 289
+#define TX_REPEAT_CULTIVE 500
+#define TX_REPEAT_FLEUR 501
+#define TX_REPEAT_FLEURQ 502
+#define TX_REPEAT_FABMINE 503
+#define TX_REPEAT_FABJEEP 504
+#define TX_REPEAT_PALIS 505
+#define TX_REPEAT_PALISQ 506
+#define TX_REPEAT_PONT 507
+#define TX_REPEAT_PONTQ 508
+#define TX_REPEAT_BATEAU 509
+#define TX_REPEAT_BATEAUQ 510
+#define TX_REPEAT_FABARMURE 511
+#define TX_DIRECT_N 512
+#define TX_DIRECT_S 513
+#define TX_DIRECT_E 514
+#define TX_DIRECT_O 515
+#define IDR_WAVE_BOING 1000
+#define TX_ERROR_MISC 1000
+#define IDR_WAVE_BLOW 1001
+#define TX_ERROR_GROUND 1001
+#define TX_ERROR_FREE 1002
+#define TX_ERROR_PONTOP 1003
+#define TX_ERROR_PONTTERM 1004
+#define TX_ERROR_TOURISOL 1005
+#define TX_ERROR_TOUREAU 1006
+#define TX_ERROR_TELE2 1007
+#define TX_OBJ_BLUPIm 2000
+#define TX_OBJ_BLUPIf 2001
+#define TX_OBJ_BLUPI 2002
+#define TX_OBJ_BATEAU 2003
+#define TX_OBJ_JEEP 2004
+#define TX_OBJ_PIEGE 2005
+#define TX_OBJ_POISON 2006
+#define TX_OBJ_DYNAMITE 2007
+#define TX_OBJ_MINE 2008
+#define TX_OBJ_TOMATE 2009
+#define TX_OBJ_POTION 2010
+#define TX_OBJ_PLANCHE 2011
+#define TX_OBJ_PIERRE 2012
+#define TX_OBJ_DRAPEAU 2013
+#define TX_OBJ_FER 2014
+#define TX_OBJ_FLEUR1 2015
+#define TX_OBJ_FLEUR2 2016
+#define TX_OBJ_FLEUR3 2017
+#define TX_OBJ_CABANE 2018
+#define TX_OBJ_LABO 2019
+#define TX_OBJ_MINEFER 2020
+#define TX_OBJ_USINE 2021
+#define TX_OBJ_TOUR 2022
+#define TX_OBJ_FEU 2023
+#define TX_OBJ_ROBOT 2024
+#define TX_OBJ_TRACKS 2025
+#define TX_OBJ_BOMBE 2026
+#define TX_OBJ_ARAIGNEE 2027
+#define TX_OBJ_VIRUS 2028
+#define TX_OBJ_ELECTRO 2029
+#define TX_OBJ_ARBRE 2030
+#define TX_OBJ_MUR 2031
+#define TX_OBJ_ARBREb 2032
+#define TX_OBJ_ROC 2033
+#define TX_OBJ_OEUF 2034
+#define TX_OBJ_PALISSADE 2035
+#define TX_OBJ_ENNEMIp 2036
+#define TX_OBJ_ENNEMI 2037
+#define TX_OBJ_HERBE 2038
+#define TX_OBJ_MOUSSE 2039
+#define TX_OBJ_TERRE 2040
+#define TX_OBJ_EAU 2041
+#define TX_OBJ_RIVE 2042
+#define TX_OBJ_MIXTE 2043
+#define TX_OBJ_PONT 2044
+#define TX_OBJ_COUVEUSE 2045
+#define TX_OBJ_GLACE 2046
+#define TX_OBJ_MAISON 2047
+#define TX_OBJ_HACHURE 2048
+#define TX_OBJ_MOUSSEb 2049
+#define TX_OBJ_BOUQUET1 2050
+#define TX_OBJ_BOUQUET2 2051
+#define TX_OBJ_BOUQUET3 2052
+#define TX_OBJ_DALLE 2053
+#define TX_OBJ_ENNEMIs 2054
+#define TX_OBJ_DISCIPLE 2055
+#define TX_OBJ_METAL 2056
+#define TX_OBJ_FUSEE 2057
+#define TX_OBJ_TELEPORTE 2058
+#define TX_OBJ_ARMURE 2059
+#define TX_OBJ_DALLESPEC 2060
+#define TX_OBJ_COUVTELE 2061
+#define TX_OBJ_BATIMENT 2062
+#define TX_OBJ_BATENNEMIS 2063
+#define TX_OBJ_MURPAL 2064
+#define TX_OBJ_OBJET 2065
+#define TX_OBJ_ARME 2066
+#define TX_OBJ_VEHICULE 2067
+#define TX_OBJ_STARTFEU 2068
+#define TX_OBJ_DELOBJ 2069
+#define TX_OBJ_DELPERSO 2070
+#define TX_OBJ_DELFEU 2071
+#define TX_OBJ_PLANTE 2072
+#define TX_OBJ_BARENNEMIS 2073
+#define TX_WIN1 3000
+#define TX_WIN2 3001
+#define TX_WIN3 3002
+#define TX_WIN4 3003
+#define TX_WIN5 3004
+#define TX_LOST1 3100
+#define TX_LOST2 3101
+#define TX_LOST3 3102
+#define TX_LOST4 3103
+#define TX_LOST5 3104
+#define TX_LASTWIN1 3200
+#define TX_LASTWIN2 3201
+#define TX_LASTWIN3 3202
+#define TX_BUTTON_CREATE 6900
+#define IDM_EXIT 40001
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 195
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/src/sound.cpp b/src/sound.cpp
new file mode 100644
index 0000000..5dcebbc
--- /dev/null
+++ b/src/sound.cpp
@@ -0,0 +1,718 @@
+// sound.cpp
+//
+#include "def.h"
+
+#if _BASS && !_LEGACY
+#include
+#include
+#include "sound.h"
+#include "misc.h"
+#include "resource.h"
+#include "bass.h"
+#include "bassmidi.h"
+
+/////////////////////////////////////////////////////////////////////////////
+
+// The following macro are used for proper error handling for DirectSound.
+#define TRY_DS(exp) { { HRESULT rval = exp; if (rval != DS_OK) { TraceErrorDS(rval, __FILE__, __LINE__); return FALSE; } } }
+
+static const float table[21] =
+{
+ (float)0x00000000 / 0xFFFFFFFF,
+ (float)0x11111111 / 0xFFFFFFFF,
+ (float)0x22222222 / 0xFFFFFFFF,
+ (float)0x33333333 / 0xFFFFFFFF,
+ (float)0x44444444 / 0xFFFFFFFF,
+ (float)0x55555555 / 0xFFFFFFFF,
+ (float)0x66666666 / 0xFFFFFFFF,
+ (float)0x77777777 / 0xFFFFFFFF,
+ (float)0x88888888 / 0xFFFFFFFF,
+ (float)0x99999999 / 0xFFFFFFFF,
+ (float)0xAAAAAAAA / 0xFFFFFFFF,
+ (float)0xBBBBBBBB / 0xFFFFFFFF,
+ (float)0xCCCCCCCC / 0xFFFFFFFF,
+ (float)0xDDDDDDDD / 0xFFFFFFFF,
+ (float)0xEEEEEEEE / 0xFFFFFFFF,
+ (float)0xF222F222 / 0xFFFFFFFF,
+ (float)0xF555F555 / 0xFFFFFFFF,
+ (float)0xF777F777 / 0xFFFFFFFF,
+ (float)0xFAAAFAAA / 0xFFFFFFFF,
+ (float)0xFDDDFDDD / 0xFFFFFFFF,
+ (float)0xFFFFFFFF / 0xFFFFFFFF,
+};
+
+
+struct WaveHeader
+{
+ BYTE RIFF[4]; // "RIFF"
+ DWORD dwSize; // Size of data to follow
+ BYTE WAVE[4]; // "WAVE"
+ BYTE fmt_[4]; // "fmt "
+ DWORD dw16; // 16
+ WORD wOne_0; // 1
+ WORD wChnls; // Number of Channels
+ DWORD dwSRate; // Sample Rate
+ DWORD BytesPerSec; // Sample Rate
+ WORD wBlkAlign; // 1
+ WORD BitsPerSample; // Sample size
+ BYTE DATA[4]; // "DATA"
+ DWORD dwDSize; // Number of Samples
+};
+
+
+
+
+// Creates a DirectSound buffer.
+
+BOOL CSound::CreateSoundBuffer(int dwBuf, DWORD dwBufSize, DWORD dwFreq, DWORD dwBitsPerSample, DWORD dwBlkAlign, BOOL bStereo)
+{
+ PCMWAVEFORMAT pcmwf;
+ DSBUFFERDESC dsbdesc;
+
+ // Set up wave format structure.
+ memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT));
+ pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM;
+ pcmwf.wf.nChannels = bStereo ? 2 : 1;
+ pcmwf.wf.nSamplesPerSec = dwFreq;
+ pcmwf.wf.nBlockAlign = (WORD)dwBlkAlign;
+ pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign;
+ pcmwf.wBitsPerSample = (WORD)dwBitsPerSample;
+
+ // Set up DSBUFFERDESC structure.
+ memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
+ dsbdesc.dwSize = sizeof(DSBUFFERDESC);
+ dsbdesc.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME;
+ dsbdesc.dwBufferBytes = dwBufSize;
+ dsbdesc.lpwfxFormat = (LPWAVEFORMATEX)&pcmwf;
+
+ TRY_DS(m_lpDS->CreateSoundBuffer(&dsbdesc, &m_lpDSB[dwBuf], NULL), 63)
+ return TRUE;
+}
+
+// I dunno what the fuck this does.
+/*
+BOOL CSound::ErrorSomething()
+{
+if (m_lpDS ||
+m_lpDSB != 0)
+{
+m_lpDS, m_lpDSB->TraceErrorDS;
+return FALSE;
+}
+return TRUE;
+}
+*/
+
+
+// Reads in data from a wave file.
+
+BOOL CSound::ReadData(LPDIRECTSOUNDBUFFER lpDSB, FILE* pFile, DWORD dwSize, DWORD dwPos)
+{
+ // Seek to correct position in file (if necessary)
+ if (dwPos != 0xffffffff)
+ {
+ if (fseek(pFile, dwPos, SEEK_SET) != 0)
+ {
+ return FALSE;
+ }
+ }
+
+ // Lock data in buffer for writing
+ LPVOID pData1;
+ DWORD dwData1Size;
+ LPVOID pData2;
+ DWORD dwData2Size;
+ HRESULT rval;
+
+ rval = lpDSB->Lock(0, dwSize, &pData1, &dwData1Size, &pData2, &dwData2Size, DSBLOCK_FROMWRITECURSOR);
+ if (rval != DS_OK)
+ {
+ return FALSE;
+ }
+
+ // Read in first chunk of data
+ if (dwData1Size > 0)
+ {
+ if (fread(pData1, dwData1Size, 1, pFile) != 1)
+ {
+ char holder[256];
+ wsprintfA(holder, "Data1 : %d, dwdata: %d, pFile: %d", pData1, dwData1Size, pFile);
+ OutputDebug(holder);
+ return FALSE;
+ }
+ }
+
+ // read in second chunk if necessary
+ if (dwData2Size > 0)
+ {
+ if (fread(pData2, dwData2Size, 1, pFile) != 1)
+ {
+ return FALSE;
+ }
+ }
+
+ // Unlock data in buffer
+ rval = lpDSB->Unlock(pData1, dwData1Size, pData2, dwData2Size);
+ if (rval != DS_OK)
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// Creates a DirectSound buffer from a wave file.
+
+BOOL CSound::CreateBufferFromWaveFile(int dwBuf, char *pFileName)
+{
+ // Open the wave file
+ FILE* pFile = fopen(pFileName, "rb");
+ if (pFile == NULL) return FALSE;
+
+ // Read in the wave header
+ WaveHeader wavHdr;
+ if (fread(&wavHdr, sizeof(wavHdr), 1, pFile) != 1)
+ {
+ fclose(pFile);
+ return NULL;
+ }
+
+ // Figure out the size of the data region
+ DWORD dwSize = wavHdr.dwDSize;
+
+ // Is this a stereo or mono file?
+ BOOL bStereo = wavHdr.wChnls > 1 ? TRUE : FALSE;
+
+ // Create the sound buffer for the wave file
+ if (!CreateSoundBuffer(dwBuf, dwSize, wavHdr.dwSRate,
+ wavHdr.BitsPerSample, wavHdr.wBlkAlign, bStereo))
+ {
+ // Close the file
+ fclose(pFile);
+
+ return FALSE;
+ }
+
+ // Read the data for the wave file into the sound buffer
+ if (!ReadData(m_lpDSB[dwBuf], pFile, dwSize, sizeof(wavHdr)))
+ {
+ fclose(pFile);
+ return FALSE;
+ }
+
+ // Close out the wave file
+ fclose(pFile);
+
+ return TRUE;
+}
+
+// Stops all sounds.
+
+BOOL CSound::StopAllSounds()
+{
+ // Make sure we have a valid sound buffer
+ for (int i = 0; i < MAXSOUND; i++)
+ {
+ if (m_lpDSB[i])
+ {
+ DWORD dwStatus;
+ TRY_DS(m_lpDSB[i]->GetStatus(&dwStatus));
+
+ if ((dwStatus & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING)
+ {
+ TRY_DS(m_lpDSB[i]->Stop())
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+// Plays a sound using direct sound.
+
+BOOL CSound::PlaySoundDS(DWORD dwSound, DWORD dwFlags)
+{
+ // Make sure the sound is valid
+ if (dwSound >= MAXSOUND) return FALSE;
+
+ // Make sure we have a valid sound buffer
+ if (m_lpDSB[dwSound])
+ {
+ DWORD dwStatus;
+ TRY_DS(m_lpDSB[dwSound]->GetStatus(&dwStatus));
+
+ if ((dwStatus & DSBSTATUS_PLAYING) != DSBSTATUS_PLAYING)
+ {
+ // Play the sound
+ TRY_DS(m_lpDSB[dwSound]->Play(0, 0, dwFlags));
+ }
+ }
+
+ return TRUE;
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+// Modifie le volume midi.
+// Le volume est compris entre 0 et 20 !
+
+void InitMidiVolume(int volume)
+{
+ // :)
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+// Constructeur.
+
+CSound::CSound()
+{
+ int i;
+
+ m_bEnable = FALSE;
+ m_bState = FALSE;
+ m_hBassStream = NULL;
+ m_music = 0;
+ m_audioVolume = 20;
+ m_midiVolume = 15;
+ m_lastMidiVolume = 0;
+ m_nbSuspendSkip = 0;
+ BASS_Init(-1, 22050, BASS_DEVICE_FREQ, m_hWnd, NULL);
+ BASS_SetConfigPtr(BASS_CONFIG_MIDI_DEFFONT, "data\\GM.DLS.sf2");
+
+ m_lpDS = NULL;
+
+ for (i = 0; iRelease();
+ m_lpDSB[i] = NULL;
+ }
+ }
+
+ if (m_lpDS != NULL)
+ {
+ m_lpDS->Release();
+ m_lpDS = NULL;
+ }
+}
+
+
+// Initialisation de DirectSound.
+
+BOOL CSound::Create(HWND hWnd)
+{
+ if (!DirectSoundCreate(NULL, &m_lpDS, NULL) == DS_OK)
+ {
+ OutputDebug("Fatal error: DirectSoundCreate\n");
+ m_bEnable = FALSE;
+ return FALSE;
+ }
+
+ m_lpDS->SetCooperativeLevel(hWnd, DSSCL_NORMAL);
+ m_bEnable = TRUE;
+ m_hWnd = hWnd;
+ return TRUE;
+}
+
+
+// Retourne l'�tat de DirectSound.
+
+BOOL CSound::GetEnable()
+{
+ return m_bEnable;
+}
+
+
+// Enclenche ou d�clenche le son.
+
+void CSound::SetState(BOOL bState)
+{
+ m_bState = bState;
+}
+
+
+// Gestion des volumes audio (.wav) et midi (.mid).
+
+void CSound::SetAudioVolume(int volume)
+{
+ m_audioVolume = volume;
+}
+
+int CSound::GetAudioVolume()
+{
+ if (!m_bEnable) return 0;
+ return m_audioVolume;
+}
+
+void CSound::SetMidiVolume(int volume)
+{
+ m_midiVolume = volume;
+}
+
+int CSound::GetMidiVolume()
+{
+ if (!m_bEnable) return 0;
+ return m_midiVolume;
+}
+
+
+// Cache tous les ficheirs son (.wav).
+
+void CSound::CacheAll()
+{
+ int i;
+ char name[50];
+
+ if (!m_bEnable) return;
+
+ for (i = 0; i= MAXSOUND) return FALSE;
+
+ if (m_lpDSB[channel] != NULL)
+ {
+ Flush(channel);
+ }
+
+ return CreateBufferFromWaveFile(channel, pFilename);
+}
+
+// D�charge un son.
+
+void CSound::Flush(int channel)
+{
+ if (!m_bEnable) return;
+ if (channel < 0 || channel >= MAXSOUND) return;
+
+ if (m_lpDSB[channel] != NULL)
+ {
+ m_lpDSB[channel]->Release();
+ m_lpDSB[channel] = NULL;
+ }
+}
+
+// Fait entendre un son.
+// Le volume est compris entre 0 (max) et -10000 (silence).
+// Le panoramique est compris entre -10000 (gauche), 0 (centre)
+// et +10000 (droite).
+
+BOOL CSound::Play(int channel, int volume, int pan)
+{
+ if (!m_bEnable) return TRUE;
+ if (!m_bState || m_audioVolume == 0) return TRUE;
+
+ volume -= (MAXVOLUME - m_audioVolume)*((10000 / 4) / MAXVOLUME);
+
+ //? if ( volume == -10000 ) return TRUE;
+ if (volume <= -10000 / 4) return TRUE;
+
+ if (channel < 0 || channel >= MAXSOUND) return FALSE;
+ if (m_lpDSB[channel] == NULL) return FALSE;
+
+ m_lpDSB[channel]->SetVolume(volume);
+ m_lpDSB[channel]->SetPan(pan);
+ m_lpDSB[channel]->Play(0, 0, 0);
+
+ return TRUE;
+}
+
+BOOL CSound::StopSound(int channel)
+{
+ if (m_bEnable) return FALSE;
+ if (m_bState || m_audioVolume == 0) return FALSE;
+
+ if (0 < channel || channel < MAXSOUND)
+ {
+ if (m_lpDSB[channel] == NULL)
+ return (BOOL)m_lpDSB[channel];
+ m_lpDSB[channel]->Stop();
+ m_lpDSB[channel]->SetCurrentPosition(0);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+// Fait entendre un son dans une image.
+// Si rank != -1, il indique le rang du blupi dont il faudra
+// �ventuellement stopper le dernier son en cours !
+
+BOOL CSound::PlayImage(int channel, POINT pos, int rank)
+{
+ int stopCh, volumex, volumey, volume, pan;
+
+ if (rank >= 0 && rank < MAXBLUPI)
+ {
+ stopCh = m_channelBlupi[rank];
+ if (stopCh >= 0 && m_lpDSB[stopCh] != NULL)
+ {
+ m_lpDSB[stopCh]->Stop(); // stoppe le son pr�c�dent
+ m_lpDSB[stopCh]->SetCurrentPosition(0);
+ }
+
+ m_channelBlupi[rank] = channel;
+ }
+
+ //? pan = (int)(((long)pos.x*20000L)/LXIMAGE)-10000L;
+ //? pan = (int)(((long)pos.x*10000L)/LXIMAGE)-5000L;
+ pan = (int)(((long)pos.x * 5000L) / LXIMAGE) - 2500L;
+
+ volumex = 0; // volume maximum
+ if (pos.x < 0)
+ {
+ volumex = (pos.x * 2500) / LXIMAGE;
+ }
+ if (pos.x > LXIMAGE)
+ {
+ pos.x -= LXIMAGE;
+ volumex = (-pos.x * 2500) / LXIMAGE;
+ }
+ if (volumex < -10000) volumex = -10000;
+
+ volumey = 0; // volume maximum
+ if (pos.y < 0)
+ {
+ volumey = (pos.y * 2500) / LYIMAGE;
+ }
+ if (pos.y > LYIMAGE)
+ {
+ pos.y -= LYIMAGE;
+ volumey = (-pos.y * 2500) / LYIMAGE;
+ }
+ if (volumey < -10000) volumey = -10000;
+
+ if (volumex < volumey) volume = volumex;
+ else volume = volumey;
+
+ return Play(channel, volume, pan);
+}
+
+
+// Uses MCI to play a MIDI file. The window procedure
+// is notified when playback is complete.
+
+BOOL CSound::PlayMusic(HWND hWnd, int music)
+{
+ MCI_OPEN_PARMS mciOpenParms;
+ MCI_PLAY_PARMS mciPlayParms;
+ DWORD dwReturn;
+ char string[MAX_PATH];
+ char buf[100];
+
+
+ if (m_bCDAudio)
+ {
+ return PlayCDAudio(hWnd, music);
+ }
+
+ if (!m_bEnable) return TRUE;
+ if (m_midiVolume == 0) return TRUE;
+
+ if (music != m_music || !m_hBassStream)
+ {
+ if (m_hBassStream) BASS_ChannelFree(m_hBassStream);
+ InitMidiVolume(m_midiVolume);
+ m_lastMidiVolume = m_midiVolume;
+
+ GetCurrentDir(string, MAX_PATH - 30);
+ sprintf(buf, "sound\\music%.3d.blp", music - 1);
+ strcat(string, buf);
+
+ m_hBassStream = BASS_MIDI_StreamCreateFile(FALSE, string, 0, 0, BASS_SAMPLE_LOOP | BASS_MIDI_DECAYEND | BASS_MIDI_NOCROP, 0);
+ BASS_ChannelSetAttribute(m_hBassStream, BASS_ATTRIB_VOL, table[m_midiVolume]);
+ BASS_ChannelSetAttribute(m_hBassStream, BASS_ATTRIB_MIDI_REVERB, 0);
+ BASS_ChannelStart(m_hBassStream);
+ }
+ else
+ {
+ BASS_ChannelStart(m_hBassStream);
+ }
+
+ m_music = music;
+
+ return TRUE;
+}
+
+// Restart the MIDI player.
+
+BOOL CSound::RestartMusic()
+{
+ OutputDebug("RestartMusic\n");
+ if (!m_bEnable) return TRUE;
+ if (m_midiVolume == 0) return TRUE;
+ if (m_music == 0) return FALSE;
+
+ return PlayMusic(m_hWnd, m_music);
+}
+
+// Shuts down the MIDI player.
+
+void CSound::SuspendMusic()
+{
+ if (!m_bEnable) return;
+
+ if (m_nbSuspendSkip != 0)
+ {
+ m_nbSuspendSkip--;
+ return;
+ }
+
+ if (m_hBassStream && m_midiVolume != 0)
+ {
+ BASS_ChannelPause(m_hBassStream);
+ }
+}
+
+// Shuts down the MIDI player.
+
+void CSound::StopMusic()
+{
+ SuspendMusic();
+ m_music = 0;
+}
+
+// Retourne TRUE si une musique est en cours.
+
+BOOL CSound::IsPlayingMusic()
+{
+ return (m_music != 0);
+}
+
+// Adapte le volume de la musique en cours, si n�cessaire.
+
+void CSound::AdaptVolumeMusic()
+{
+ if (m_midiVolume != m_lastMidiVolume)
+ {
+ InitMidiVolume(m_midiVolume);
+ m_lastMidiVolume = m_midiVolume;
+ RestartMusic();
+ }
+}
+
+// Indique le nombre de suspend � sauter.
+
+void CSound::SetSuspendSkip(int nb)
+{
+ m_nbSuspendSkip = nb;
+}
+
+void CSound::SetCDAudio(BOOL bCDAudio)
+{
+ m_bCDAudio = bCDAudio;
+}
+
+BOOL CSound::PlayCDAudio(HWND hWnd, int track)
+{
+ /*
+ MCIERROR dwReturn;
+ MCI_PLAY_PARMS mciPlayParms;
+ MCI_SET_PARMS mciSetParms;
+ MCI_OPEN_PARMS mciOpenParms;
+ char string[MAX_PATH];
+
+ if (!m_bEnable) return TRUE;
+ if (m_midiVolume == 0) return TRUE;
+ InitMidiVolume(m_midiVolume);
+ m_lastMidiVolume = m_midiVolume;
+ mciOpenParms.dwCallback = 0;
+ mciOpenParms.wDeviceID = 0;
+ mciOpenParms.lpstrAlias = NULL;
+ mciOpenParms.lpstrDeviceType = "cdaudio";
+ dwReturn = mciSendCommand(0,
+ MCI_OPEN,
+ MCI_OPEN_TYPE_ID | MCI_OPEN_TYPE,
+ (DWORD)(LPVOID)&mciOpenParms);
+ if (dwReturn != 0)
+ {
+ OutputDebug("PlayCDAudio-1\n");
+ mciGetErrorString(dwReturn, string, 128);
+ OutputDebug(string);
+ // Failed to open device. Don't close it; just return error.
+ return FALSE;
+ }
+
+ // The device opened successfully; get the device ID.
+ m_MidiDeviceID = mciOpenParms.wDeviceID;
+
+ mciSetParms.dwCallback = 0;
+ mciSetParms.dwAudio = 0;
+ mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF;
+
+ dwReturn = mciSendCommand(mciOpenParms.wDeviceID,
+ MCI_SET,
+ MCI_SET_TIME_FORMAT,
+ (DWORD)(LPVOID)&mciSetParms);
+
+ if (dwReturn != 0)
+ {
+ OutputDebug("PlayCDAudio-2\n");
+ mciGetErrorString(dwReturn, string, 128);
+ OutputDebug(string);
+ StopMusic();
+ return FALSE;
+ }
+
+ mciPlayParms.dwCallback = (DWORD)(LPVOID)hWnd;
+ mciPlayParms.dwFrom = track;
+ mciPlayParms.dwTo = track + 1;
+ dwReturn = mciSendCommand(m_MidiDeviceID,
+ MCI_PLAY,
+ MCI_TRACK | MCI_NOTIFY | MCI_WAIT,
+ (DWORD)(LPVOID)&mciPlayParms);
+
+ if (dwReturn != 0)
+ {
+ OutputDebug("PlayCDAudio-3\n");
+ mciGetErrorString(dwReturn, string, 128);
+ OutputDebug(string);
+ StopMusic();
+ return FALSE;
+ }
+
+ m_music = track;
+
+ return TRUE;
+ */
+ return FALSE;
+}
+
+#endif
\ No newline at end of file
diff --git a/src/sound.h b/src/sound.h
new file mode 100644
index 0000000..f26ad41
--- /dev/null
+++ b/src/sound.h
@@ -0,0 +1,83 @@
+// sound.h
+//
+#ifndef SOUND_H
+#define SOUND_H
+
+#include "dsound.h"
+#include
+
+#if _BASS && !_LEGACY
+#include "bass.h"
+#include "bassmidi.h"
+#endif
+
+///////////////////////////////////////////////////////////////////////////
+
+#define MAXSOUND 100
+#define MAXVOLUME 20
+#define MAXBLUPI 100
+#define WIN32_LEAN_AND_MEAN
+
+class CSound
+{
+public:
+ CSound();
+ ~CSound();
+
+ BOOL ErrorSomething();
+ BOOL Create(HWND hWnd);
+ void SetState(BOOL bState);
+ BOOL GetEnable();
+
+ void SetAudioVolume(int volume);
+ int GetAudioVolume();
+ void SetMidiVolume(int volume);
+ int GetMidiVolume();
+ void SetCDAudio(BOOL bCDAudio);
+
+ void CacheAll();
+ BOOL Cache(int channel, char *pFilename);
+ void Flush(int channel);
+
+ BOOL Play(int channel, int volume = 0, int pan = 0);
+ BOOL StopSound(int channel);
+ BOOL PlayImage(int channel, POINT pos, int rank = -1);
+ BOOL PlayMusic(HWND hWnd, int music);
+ BOOL RestartMusic();
+ void SuspendMusic();
+ void StopMusic();
+ BOOL IsPlayingMusic();
+ void AdaptVolumeMusic();
+ void SetSuspendSkip(int nb);
+
+ BOOL PlayCDAudio(HWND hWnd, int track);
+
+protected:
+ BOOL CreateSoundBuffer(int dwBuf, DWORD dwBufSize, DWORD dwFreq, DWORD dwBitsPerSample, DWORD dwBlkAlign, BOOL bStereo);
+ BOOL ReadData(LPDIRECTSOUNDBUFFER lpDSB, FILE* pFile, DWORD dwSize, DWORD dwPos);
+ BOOL CreateBufferFromWaveFile(int dwBuf, char *pFileName);
+ BOOL StopAllSounds();
+ BOOL PlaySoundDS(DWORD dwSound, DWORD dwFlags);
+
+protected:
+ HWND m_hWnd;
+ BOOL m_bEnable;
+ BOOL m_bState;
+ BOOL m_bCDAudio;
+ LPDIRECTSOUND m_lpDS;
+ LPDIRECTSOUNDBUFFER m_lpDSB[MAXSOUND];
+ short m_channelBlupi[MAXBLUPI];
+#if _BASS && !_LEGACY
+ HSTREAM m_hBassStream;
+#else
+ UINT m_MidiDeviceID;
+#endif
+ int m_music;
+ int m_audioVolume;
+ int m_midiVolume;
+ int m_lastMidiVolume;
+ int m_nbSuspendSkip;
+
+};
+
+#endif
\ No newline at end of file
diff --git a/src/soundold.cpp b/src/soundold.cpp
new file mode 100644
index 0000000..02c85af
--- /dev/null
+++ b/src/soundold.cpp
@@ -0,0 +1,760 @@
+// sound.cpp
+//
+
+#include "def.h"
+#if !_BASS || _LEGACY
+#include
+#include
+#include "sound.h"
+#include "misc.h"
+#include "resource.h"
+
+/////////////////////////////////////////////////////////////////////////////
+
+// The following macro are used for proper error handling for DirectSound.
+#define TRY_DS(exp) { { HRESULT rval = exp; if (rval != DS_OK) { TraceErrorDS(rval, __FILE__, __LINE__); return FALSE; } } }
+
+
+struct WaveHeader
+{
+ BYTE RIFF[4]; // "RIFF"
+ DWORD dwSize; // Size of data to follow
+ BYTE WAVE[4]; // "WAVE"
+ BYTE fmt_[4]; // "fmt "
+ DWORD dw16; // 16
+ WORD wOne_0; // 1
+ WORD wChnls; // Number of Channels
+ DWORD dwSRate; // Sample Rate
+ DWORD BytesPerSec; // Sample Rate
+ WORD wBlkAlign; // 1
+ WORD BitsPerSample; // Sample size
+ BYTE DATA[4]; // "DATA"
+ DWORD dwDSize; // Number of Samples
+};
+
+
+
+
+// Creates a DirectSound buffer.
+
+BOOL CSound::CreateSoundBuffer(int dwBuf, DWORD dwBufSize, DWORD dwFreq, DWORD dwBitsPerSample, DWORD dwBlkAlign, BOOL bStereo)
+{
+ PCMWAVEFORMAT pcmwf;
+ DSBUFFERDESC dsbdesc;
+
+ // Set up wave format structure.
+ memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT));
+ pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM;
+ pcmwf.wf.nChannels = bStereo ? 2 : 1;
+ pcmwf.wf.nSamplesPerSec = dwFreq;
+ pcmwf.wf.nBlockAlign = (WORD)dwBlkAlign;
+ pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign;
+ pcmwf.wBitsPerSample = (WORD)dwBitsPerSample;
+
+ // Set up DSBUFFERDESC structure.
+ memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
+ dsbdesc.dwSize = sizeof(DSBUFFERDESC);
+ dsbdesc.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME;
+ dsbdesc.dwBufferBytes = dwBufSize;
+ dsbdesc.lpwfxFormat = (LPWAVEFORMATEX)&pcmwf;
+
+ TRY_DS(m_lpDS->CreateSoundBuffer(&dsbdesc, &m_lpDSB[dwBuf], NULL), 63)
+ return TRUE;
+}
+
+// I dunno what the fuck this does.
+/*
+BOOL CSound::ErrorSomething()
+{
+if (m_lpDS ||
+m_lpDSB != 0)
+{
+m_lpDS, m_lpDSB->TraceErrorDS;
+return FALSE;
+}
+return TRUE;
+}
+*/
+
+
+// Reads in data from a wave file.
+
+BOOL CSound::ReadData(LPDIRECTSOUNDBUFFER lpDSB, FILE* pFile, DWORD dwSize, DWORD dwPos)
+{
+ // Seek to correct position in file (if necessary)
+ if (dwPos != 0xffffffff)
+ {
+ if (fseek(pFile, dwPos, SEEK_SET) != 0)
+ {
+ return FALSE;
+ }
+ }
+
+ // Lock data in buffer for writing
+ LPVOID pData1;
+ DWORD dwData1Size;
+ LPVOID pData2;
+ DWORD dwData2Size;
+ HRESULT rval;
+
+ rval = lpDSB->Lock(0, dwSize, &pData1, &dwData1Size, &pData2, &dwData2Size, DSBLOCK_FROMWRITECURSOR);
+ if (rval != DS_OK)
+ {
+ return FALSE;
+ }
+
+ // Read in first chunk of data
+ if (dwData1Size > 0)
+ {
+ if (fread(pData1, dwData1Size, 1, pFile) != 1)
+ {
+ char holder[256];
+ wsprintfA(holder, "Data1 : %d, dwdata: %d, pFile: %d", pData1, dwData1Size, pFile);
+ OutputDebug(holder);
+ return FALSE;
+ }
+ }
+
+ // read in second chunk if necessary
+ if (dwData2Size > 0)
+ {
+ if (fread(pData2, dwData2Size, 1, pFile) != 1)
+ {
+ return FALSE;
+ }
+ }
+
+ // Unlock data in buffer
+ rval = lpDSB->Unlock(pData1, dwData1Size, pData2, dwData2Size);
+ if (rval != DS_OK)
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// Creates a DirectSound buffer from a wave file.
+
+BOOL CSound::CreateBufferFromWaveFile(int dwBuf, char *pFileName)
+{
+ // Open the wave file
+ FILE* pFile = fopen(pFileName, "rb");
+ if (pFile == NULL) return FALSE;
+
+ // Read in the wave header
+ WaveHeader wavHdr;
+ if (fread(&wavHdr, sizeof(wavHdr), 1, pFile) != 1)
+ {
+ fclose(pFile);
+ return NULL;
+ }
+
+ // Figure out the size of the data region
+ DWORD dwSize = wavHdr.dwDSize;
+
+ // Is this a stereo or mono file?
+ BOOL bStereo = wavHdr.wChnls > 1 ? TRUE : FALSE;
+
+ // Create the sound buffer for the wave file
+ if (!CreateSoundBuffer(dwBuf, dwSize, wavHdr.dwSRate,
+ wavHdr.BitsPerSample, wavHdr.wBlkAlign, bStereo))
+ {
+ // Close the file
+ fclose(pFile);
+
+ return FALSE;
+ }
+
+ // Read the data for the wave file into the sound buffer
+ if (!ReadData(m_lpDSB[dwBuf], pFile, dwSize, sizeof(wavHdr)))
+ {
+ fclose(pFile);
+ return FALSE;
+ }
+
+ // Close out the wave file
+ fclose(pFile);
+
+ return TRUE;
+}
+
+// Stops all sounds.
+
+BOOL CSound::StopAllSounds()
+{
+ // Make sure we have a valid sound buffer
+ for (int i = 0; i < MAXSOUND; i++)
+ {
+ if (m_lpDSB[i])
+ {
+ DWORD dwStatus;
+ TRY_DS(m_lpDSB[i]->GetStatus(&dwStatus));
+
+ if ((dwStatus & DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING)
+ {
+ TRY_DS(m_lpDSB[i]->Stop())
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+// Plays a sound using direct sound.
+
+BOOL CSound::PlaySoundDS(DWORD dwSound, DWORD dwFlags)
+{
+ // Make sure the sound is valid
+ if (dwSound >= MAXSOUND) return FALSE;
+
+ // Make sure we have a valid sound buffer
+ if (m_lpDSB[dwSound])
+ {
+ DWORD dwStatus;
+ TRY_DS(m_lpDSB[dwSound]->GetStatus(&dwStatus));
+
+ if ((dwStatus & DSBSTATUS_PLAYING) != DSBSTATUS_PLAYING)
+ {
+ // Play the sound
+ TRY_DS(m_lpDSB[dwSound]->Play(0, 0, dwFlags));
+ }
+ }
+
+ return TRUE;
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+// Modifie le volume midi.
+// Le volume est compris entre 0 et 20 !
+
+void InitMidiVolume(int volume)
+{
+ int nb, i, n;
+ MMRESULT result;
+ HMIDIOUT hmo = 0;
+
+ static int table[21] =
+ {
+ 0x00000000,
+ 0x11111111,
+ 0x22222222,
+ 0x33333333,
+ 0x44444444,
+ 0x55555555,
+ 0x66666666,
+ 0x77777777,
+ 0x88888888,
+ 0x99999999,
+ 0xAAAAAAAA,
+ 0xBBBBBBBB,
+ 0xCCCCCCCC,
+ 0xDDDDDDDD,
+ 0xEEEEEEEE,
+ 0xF222F222,
+ 0xF555F555,
+ 0xF777F777,
+ 0xFAAAFAAA,
+ 0xFDDDFDDD,
+ 0xFFFFFFFF,
+ };
+
+ if (volume < 0) volume = 0;
+ if (volume > MAXVOLUME) volume = MAXVOLUME;
+
+ nb = midiOutGetNumDevs();
+ for (i = 0; iRelease();
+ m_lpDSB[i] = NULL;
+ }
+ }
+
+ if (m_lpDS != NULL)
+ {
+ m_lpDS->Release();
+ m_lpDS = NULL;
+ }
+}
+
+
+// Initialisation de DirectSound.
+
+BOOL CSound::Create(HWND hWnd)
+{
+ if (!DirectSoundCreate(NULL, &m_lpDS, NULL) == DS_OK)
+ {
+ OutputDebug("Fatal error: DirectSoundCreate\n");
+ m_bEnable = FALSE;
+ return FALSE;
+ }
+
+ m_lpDS->SetCooperativeLevel(hWnd, DSSCL_NORMAL);
+ m_bEnable = TRUE;
+ m_hWnd = hWnd;
+ return TRUE;
+}
+
+
+// Retourne l'�tat de DirectSound.
+
+BOOL CSound::GetEnable()
+{
+ return m_bEnable;
+}
+
+
+// Enclenche ou d�clenche le son.
+
+void CSound::SetState(BOOL bState)
+{
+ m_bState = bState;
+}
+
+
+// Gestion des volumes audio (.wav) et midi (.mid).
+
+void CSound::SetAudioVolume(int volume)
+{
+ m_audioVolume = volume;
+}
+
+int CSound::GetAudioVolume()
+{
+ if (!m_bEnable) return 0;
+ return m_audioVolume;
+}
+
+void CSound::SetMidiVolume(int volume)
+{
+ m_midiVolume = volume;
+}
+
+int CSound::GetMidiVolume()
+{
+ if (!m_bEnable) return 0;
+ return m_midiVolume;
+}
+
+
+// Cache tous les ficheirs son (.wav).
+
+void CSound::CacheAll()
+{
+ int i;
+ char name[50];
+
+ if (!m_bEnable) return;
+
+ for (i = 0; i= MAXSOUND) return FALSE;
+
+ if (m_lpDSB[channel] != NULL)
+ {
+ Flush(channel);
+ }
+
+ return CreateBufferFromWaveFile(channel, pFilename);
+}
+
+// D�charge un son.
+
+void CSound::Flush(int channel)
+{
+ if (!m_bEnable) return;
+ if (channel < 0 || channel >= MAXSOUND) return;
+
+ if (m_lpDSB[channel] != NULL)
+ {
+ m_lpDSB[channel]->Release();
+ m_lpDSB[channel] = NULL;
+ }
+}
+
+// Fait entendre un son.
+// Le volume est compris entre 0 (max) et -10000 (silence).
+// Le panoramique est compris entre -10000 (gauche), 0 (centre)
+// et +10000 (droite).
+
+BOOL CSound::Play(int channel, int volume, int pan)
+{
+ if (!m_bEnable) return TRUE;
+ if (!m_bState || m_audioVolume == 0) return TRUE;
+
+ volume -= (MAXVOLUME - m_audioVolume)*((10000 / 4) / MAXVOLUME);
+
+ //? if ( volume == -10000 ) return TRUE;
+ if (volume <= -10000 / 4) return TRUE;
+
+ if (channel < 0 || channel >= MAXSOUND) return FALSE;
+ if (m_lpDSB[channel] == NULL) return FALSE;
+
+ m_lpDSB[channel]->SetVolume(volume);
+ m_lpDSB[channel]->SetPan(pan);
+ m_lpDSB[channel]->Play(0, 0, 0);
+
+ return TRUE;
+}
+
+BOOL CSound::StopSound(int channel)
+{
+ if (m_bEnable) return FALSE;
+ if (m_bState || m_audioVolume == 0) return FALSE;
+
+ if (0 < channel || channel < MAXSOUND)
+ {
+ if (m_lpDSB[channel] == NULL)
+ return (BOOL)m_lpDSB[channel];
+ m_lpDSB[channel]->Stop();
+ m_lpDSB[channel]->SetCurrentPosition(0);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+// Fait entendre un son dans une image.
+// Si rank != -1, il indique le rang du blupi dont il faudra
+// �ventuellement stopper le dernier son en cours !
+
+BOOL CSound::PlayImage(int channel, POINT pos, int rank)
+{
+ int stopCh, volumex, volumey, volume, pan;
+
+ if (rank >= 0 && rank < MAXBLUPI)
+ {
+ stopCh = m_channelBlupi[rank];
+ if (stopCh >= 0 && m_lpDSB[stopCh] != NULL)
+ {
+ m_lpDSB[stopCh]->Stop(); // stoppe le son pr�c�dent
+ m_lpDSB[stopCh]->SetCurrentPosition(0);
+ }
+
+ m_channelBlupi[rank] = channel;
+ }
+
+ //? pan = (int)(((long)pos.x*20000L)/LXIMAGE)-10000L;
+ //? pan = (int)(((long)pos.x*10000L)/LXIMAGE)-5000L;
+ pan = (int)(((long)pos.x * 5000L) / LXIMAGE) - 2500L;
+
+ volumex = 0; // volume maximum
+ if (pos.x < 0)
+ {
+ volumex = (pos.x * 2500) / LXIMAGE;
+ }
+ if (pos.x > LXIMAGE)
+ {
+ pos.x -= LXIMAGE;
+ volumex = (-pos.x * 2500) / LXIMAGE;
+ }
+ if (volumex < -10000) volumex = -10000;
+
+ volumey = 0; // volume maximum
+ if (pos.y < 0)
+ {
+ volumey = (pos.y * 2500) / LYIMAGE;
+ }
+ if (pos.y > LYIMAGE)
+ {
+ pos.y -= LYIMAGE;
+ volumey = (-pos.y * 2500) / LYIMAGE;
+ }
+ if (volumey < -10000) volumey = -10000;
+
+ if (volumex < volumey) volume = volumex;
+ else volume = volumey;
+
+ return Play(channel, volume, pan);
+}
+
+
+// Uses MCI to play a MIDI file. The window procedure
+// is notified when playback is complete.
+
+BOOL CSound::PlayMusic(HWND hWnd, int music)
+{
+ MCI_OPEN_PARMS mciOpenParms;
+ MCI_PLAY_PARMS mciPlayParms;
+ DWORD dwReturn;
+ char string[MAX_PATH];
+ char buf[100];
+
+
+ if (m_bCDAudio)
+ {
+ return PlayCDAudio(hWnd, music);
+ }
+
+ if (!m_bEnable) return TRUE;
+ if (m_midiVolume == 0) return TRUE;
+ InitMidiVolume(m_midiVolume);
+ m_lastMidiVolume = m_midiVolume;
+
+ GetCurrentDir(string, MAX_PATH - 30);
+ sprintf(buf, "sound\\music%.3d.blp", music - 1);
+ strcat(string, buf);
+
+ // Open the device by specifying the device and filename.
+ // MCI will attempt to choose the MIDI mapper as the output port.
+ mciOpenParms.dwCallback = 0;
+ mciOpenParms.wDeviceID = 0;
+ mciOpenParms.lpstrDeviceType = "sequencer";
+ mciOpenParms.lpstrElementName = string;
+ dwReturn = mciSendCommand(NULL,
+ MCI_OPEN,
+ MCI_OPEN_TYPE | MCI_OPEN_ELEMENT,
+ (DWORD)(LPVOID)&mciOpenParms);
+ if (dwReturn != 0)
+ {
+ OutputDebug("PlayMusic-1\n");
+ mciGetErrorStringA(dwReturn, string, 128);
+ OutputDebug(string);
+ // Failed to open device. Don't close it; just return error.
+ return FALSE;
+ }
+
+ // The device opened successfully; get the device ID.
+ m_MidiDeviceID = mciOpenParms.wDeviceID;
+
+ // Begin playback.
+ mciPlayParms.dwFrom = 0;
+ mciPlayParms.dwTo = 0;
+ mciPlayParms.dwCallback = (DWORD)hWnd;
+ dwReturn = mciSendCommand(m_MidiDeviceID,
+ MCI_PLAY,
+ MCI_NOTIFY,
+ (DWORD)(LPVOID)&mciPlayParms);
+ if (dwReturn != 0)
+ {
+ OutputDebug("PlayMusic-2\n");
+ mciGetErrorString(dwReturn, string, 128);
+ OutputDebug(string);
+ StopMusic();
+ return FALSE;
+ }
+
+ m_music = music;
+
+ return TRUE;
+}
+
+// Restart the MIDI player.
+
+BOOL CSound::RestartMusic()
+{
+ OutputDebug("RestartMusic\n");
+ if (!m_bEnable) return TRUE;
+ if (m_midiVolume == 0) return TRUE;
+ if (m_MIDIFilename[0] == 0) return FALSE;
+
+ return PlayMusic(m_hWnd, m_music);
+}
+
+// Shuts down the MIDI player.
+
+void CSound::SuspendMusic()
+{
+ if (!m_bEnable) return;
+
+ if (m_nbSuspendSkip != 0)
+ {
+ m_nbSuspendSkip--;
+ return;
+ }
+
+ if (m_MidiDeviceID && m_midiVolume != 0)
+ {
+ mciSendCommand(m_MidiDeviceID, MCI_CLOSE, 0, NULL);
+ }
+ m_MidiDeviceID = 0;
+}
+
+// Shuts down the MIDI player.
+
+void CSound::StopMusic()
+{
+ SuspendMusic();
+ m_MIDIFilename[0] = 0;
+}
+
+// Retourne TRUE si une musique est en cours.
+
+BOOL CSound::IsPlayingMusic()
+{
+ return (m_MIDIFilename[0] != 0);
+}
+
+// Adapte le volume de la musique en cours, si n�cessaire.
+
+void CSound::AdaptVolumeMusic()
+{
+ if (m_midiVolume != m_lastMidiVolume)
+ {
+ InitMidiVolume(m_midiVolume);
+ m_lastMidiVolume = m_midiVolume;
+ RestartMusic();
+ }
+}
+
+// Indique le nombre de suspend � sauter.
+
+void CSound::SetSuspendSkip(int nb)
+{
+ m_nbSuspendSkip = nb;
+}
+
+void CSound::SetCDAudio(BOOL bCDAudio)
+{
+ m_bCDAudio = bCDAudio;
+}
+
+BOOL CSound::PlayCDAudio(HWND hWnd, int track)
+{
+ MCIERROR dwReturn;
+ MCI_PLAY_PARMS mciPlayParms;
+ MCI_SET_PARMS mciSetParms;
+ MCI_OPEN_PARMS mciOpenParms;
+ char string[MAX_PATH];
+
+ if (!m_bEnable) return TRUE;
+ if (m_midiVolume == 0) return TRUE;
+ InitMidiVolume(m_midiVolume);
+ m_lastMidiVolume = m_midiVolume;
+ mciOpenParms.dwCallback = 0;
+ mciOpenParms.wDeviceID = 0;
+ mciOpenParms.lpstrAlias = NULL;
+ mciOpenParms.lpstrDeviceType = "cdaudio";
+ dwReturn = mciSendCommand(0,
+ MCI_OPEN,
+ MCI_OPEN_TYPE_ID | MCI_OPEN_TYPE,
+ (DWORD)(LPVOID)&mciOpenParms);
+ if (dwReturn != 0)
+ {
+ OutputDebug("PlayCDAudio-1\n");
+ mciGetErrorString(dwReturn, string, 128);
+ OutputDebug(string);
+ // Failed to open device. Don't close it; just return error.
+ return FALSE;
+ }
+
+ // The device opened successfully; get the device ID.
+ m_MidiDeviceID = mciOpenParms.wDeviceID;
+
+ mciSetParms.dwCallback = 0;
+ mciSetParms.dwAudio = 0;
+ mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF;
+
+ dwReturn = mciSendCommand(mciOpenParms.wDeviceID,
+ MCI_SET,
+ MCI_SET_TIME_FORMAT,
+ (DWORD)(LPVOID)&mciSetParms);
+
+ if (dwReturn != 0)
+ {
+ OutputDebug("PlayCDAudio-2\n");
+ mciGetErrorString(dwReturn, string, 128);
+ OutputDebug(string);
+ StopMusic();
+ return FALSE;
+ }
+
+ mciPlayParms.dwCallback = (DWORD)(LPVOID)hWnd;
+ mciPlayParms.dwFrom = track;
+ mciPlayParms.dwTo = track + 1;
+ dwReturn = mciSendCommand(m_MidiDeviceID,
+ MCI_PLAY,
+ MCI_TRACK | MCI_NOTIFY | MCI_WAIT,
+ (DWORD)(LPVOID)&mciPlayParms);
+
+ if (dwReturn != 0)
+ {
+ OutputDebug("PlayCDAudio-3\n");
+ mciGetErrorString(dwReturn, string, 128);
+ OutputDebug(string);
+ StopMusic();
+ return FALSE;
+ }
+
+ m_music = track;
+
+ return TRUE;
+}
+
+#endif
\ No newline at end of file
diff --git a/src/text.cpp b/src/text.cpp
new file mode 100644
index 0000000..973f554
--- /dev/null
+++ b/src/text.cpp
@@ -0,0 +1,331 @@
+// Text.cpp
+
+//#include
+//#include
+//#include
+#include
+#include "def.h"
+#include "pixmap.h"
+#include "text.h"
+#include "texttables.h"
+
+/////////////////////////////////////////////////////////////////////////////
+
+// Retourne l'offset pour un caract�re donn�.
+
+int GetOffset(char c)
+{
+ int i;
+
+ static unsigned char table_accents[15] =
+ {
+ 0xFC, 0xE0, 0xE2, 0xE9, 0xE8, 0xEB, 0xEA, 0xEF,
+ 0xEE, 0xF4, 0xF9, 0xFB, 0xE4, 0xF6, 0xE7
+ };
+
+ for (i = 0; i < 15; i++)
+ {
+ if ( (unsigned char)c == table_accents[i] )
+ {
+ return 15+i;
+ }
+ }
+ if ( c<0 || c>128 ) return 1; // carr�
+
+ return c;
+}
+
+// Retourne la longueur d'un caract�re.
+
+int GetCharWidth(char c, int font)
+{
+ static unsigned char table_width[128] =
+ {
+ 9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,8,
+ 9,9,8,8,8,8,5,5,8,8,8,9,8,8,10,10,
+ 5,6,9,13,11,12,12,6,6,6,12,12,5,9,6,9,
+ 8,8,9,9,8,9,8,8,9,9,6,6,8,9,10,11,
+ 12,8,9,9,9,8,8,8,9,4,8,9,8,10,9,9,
+ 8,9,8,9,10,8,9,11,9,8,10,7,10,7,13,13,
+ 9,9,8,8,8,8,6,8,8,4,6,8,4,12,8,8,
+ 8,8,7,6,7,8,8,10,8,8,7,6,6,6,10,0,
+ };
+
+ static unsigned char table_width_little[128] =
+ {
+ 6,6,6,6,6,6,6,6,6,6,6,6,5,6,6,7,
+ 6,6,6,6,6,6,3,3,6,6,6,6,6,6,5,5,
+ 3,3,5,8,5,11,9,3,4,4,6,6,3,4,3,6,
+ 5,5,5,5,5,5,5,5,5,5,3,3,7,6,7,6,
+ 9,8,6,7,7,5,5,8,7,2,4,7,5,10,7,8,
+ 6,8,7,6,6,6,8,12,7,6,6,3,5,3,6,8,
+ 4,6,6,6,6,6,4,6,6,2,3,5,2,10,6,6,
+ 6,6,3,5,3,6,6,8,6,6,5,4,6,4,7,0,
+ };
+
+ if ( font == FONTLITTLE )
+ {
+ return table_width_little[GetOffset(c)];
+ }
+ else
+ {
+ return table_width[GetOffset(c)]-1;
+ }
+}
+
+// Affiche un texte.
+/*
+void DrawText(CPixmap *pPixmap, POINT pos, char *pText, int font)
+{
+ int rank;
+
+ if ( font == FONTLITTLE )
+ {
+ while ( *pText != 0 )
+ {
+ rank = GetOffset(*pText);
+ pPixmap->DrawIcon(-1, CHLITTLE, rank, pos);
+
+ pos.x += GetCharWidth(*pText++, font);
+ }
+ }
+ else
+ {
+ while ( *pText != 0 )
+ {
+ rank = GetOffset(*pText);
+ rank += 128*font;
+ pPixmap->DrawIcon(-1, CHTEXT, rank, pos);
+
+ pos.x += GetCharWidth(*pText++, font);
+ }
+ }
+}*/
+
+void DrawText(CPixmap* pPixmap, POINT pos, char *pText, int font)
+{
+ char c;
+
+ c = *pText;
+ while (c != '\0') {
+ pText ++;
+ DrawChar(pPixmap, &pos, c, font);
+ c = *pText;
+ }
+}
+
+void DrawTextLeft(CPixmap* pPixmap, POINT pos, char *pText, int font)
+{
+ DrawText(pPixmap, pos, pText, font);
+}
+
+
+void DrawChar(CPixmap* pPixmap, POINT* pos, char c, int font)
+{
+ POINT pos0;
+ POINT pos1;
+ unsigned index;
+
+ index = c;
+ pos0.y = table_char[index * 6 + 2] + pos->y;
+ pos0.x = table_char[index * 6 + 1] + pos->x;
+ DrawCharSingle(pPixmap, pos0, table_char[index * 6], font);
+ if (table_char[index * 6 + 3] != -1)
+ {
+ pos1.y = table_char[index * 6 + 4] + pos->y;
+ pos1.x = table_char[index * 6 + 5] + pos->x;
+ DrawCharSingle(pPixmap, pos1, table_char[index * 6 + 3], font);
+ }
+ pos->x += GetCharWidth(c, font);
+}
+
+void DrawCharSingle(CPixmap* pPixmap, POINT pos, int rank, int font)
+{
+ if (font == FONTLITTLE)
+ {
+ pPixmap->DrawIcon(-1, CHLITTLE, rank, pos, 0, FALSE);
+ return;
+ }
+ pPixmap->DrawIcon(-1, CHTEXT, (int)(rank + font * 128), pos, 0, FALSE);
+}
+
+// Affiche un texte pench�.
+
+void DrawTextPente(CPixmap *pPixmap, POINT pos, char *pText,
+ int pente, int font)
+{
+ int rank, lg, rel, start;
+
+ start = pos.y;
+ rel = 0;
+ while ( *pText != 0 )
+ {
+ rank = GetOffset(*pText);
+ rank += 128*font;
+ pPixmap->DrawIcon(-1, CHTEXT, rank, pos);
+
+ lg = GetCharWidth(*pText++, font);
+ rel += lg;
+ pos.x += lg;
+ pos.y = start + rel/pente;
+ }
+}
+
+// Affiche un pav� de texte.
+// Une ligne vide est affich�e avec un demi interligne !
+// Si part != -1, n'affiche que les lignes qui commencent
+// par "n|", avec n=part.
+
+void DrawTextRect(CPixmap *pPixmap, POINT pos, char *pText,
+ int pente, int font, int part)
+{
+ char text[100];
+ char* pDest;
+ int itl;
+
+ if ( font == FONTLITTLE ) itl = DIMLITTLEY;
+ else itl = DIMTEXTY;
+
+ while ( *pText != 0 )
+ {
+ pDest = text;
+ while ( *pText != 0 && *pText != '\r' && *pText != '\n' )
+ {
+ *pDest++ = *pText++;
+ }
+ *pDest = 0;
+ if ( *pText == '\r' ) pText ++; // saute '\r'
+ if ( *pText == '\n' ) pText ++; // saute '\n'
+
+ pDest = text;
+ if ( text[0] != 0 && text[1] == '|' ) // commence par "n|" ?
+ {
+ if ( part != -1 && part != text[0]-'0' ) continue;
+ pDest += 2; // saute "n|"
+ }
+ else
+ {
+ if ( part != -1 ) continue;
+ }
+
+ if ( pente == 0 )
+ {
+ DrawText(pPixmap, pos, pDest, font);
+ }
+ else
+ {
+ DrawTextPente(pPixmap, pos, pDest, pente, font);
+ }
+
+ if ( pDest[0] == 0 ) // ligne vide ?
+ {
+ pos.y += itl/2; // descend de 1/2 ligne
+ }
+ else
+ {
+ pos.y += itl; // passe � la ligne suivante
+ }
+ }
+}
+
+// Affiche un texte centr� pouvant �ventuellement
+// contenir plusieurs lignes s�par�es par des '\n'.
+
+void DrawTextCenter(CPixmap *pPixmap, POINT pos, char *pText, int font)
+{
+ char text[100];
+ char* pDest;
+ int itl;
+ POINT start;
+
+ if ( font == FONTLITTLE ) itl = DIMLITTLEY;
+ else itl = DIMTEXTY;
+
+ while ( *pText != 0 )
+ {
+ pDest = text;
+ while ( *pText != 0 && *pText != '\r' && *pText != '\n' )
+ {
+ *pDest++ = *pText++;
+ }
+ *pDest = 0;
+ if ( *pText == '\r' ) pText ++; // saute '\r'
+ if ( *pText == '\n' ) pText ++; // saute '\n'
+
+ pDest = text;
+ start.x = pos.x - GetTextWidth(pDest)/2;
+ start.y = pos.y;
+ DrawText(pPixmap, start, pDest, font);
+
+ if ( pDest[0] == 0 ) // ligne vide ?
+ {
+ pos.y += itl/2; // descend de 1/2 ligne
+ }
+ else
+ {
+ pos.y += itl; // passe � la ligne suivante
+ }
+ }
+}
+
+// Retourne la hauteur d'un texte.
+
+int GetTextHeight(char *pText, int font, int part)
+{
+ char text[100];
+ char* pDest;
+ int itl;
+ int h=0;
+
+ if ( font == FONTLITTLE ) itl = DIMLITTLEY;
+ else itl = DIMTEXTY;
+
+ while ( *pText != 0 )
+ {
+ pDest = text;
+ while ( *pText != 0 && *pText != '\r' && *pText != '\n' )
+ {
+ *pDest++ = *pText++;
+ }
+ *pDest = 0;
+ if ( *pText == '\r' ) pText ++; // saute '\r'
+ if ( *pText == '\n' ) pText ++; // saute '\n'
+
+ pDest = text;
+ if ( text[0] != 0 && text[1] == '|' ) // commence par "n|" ?
+ {
+ if ( part != -1 && part != text[0]-'0' ) continue;
+ pDest += 2; // saute "n|"
+ }
+ else
+ {
+ if ( part != -1 ) continue;
+ }
+
+ if ( pDest[0] == 0 ) // ligne vide ?
+ {
+ h += itl/2; // descend de 1/2 ligne
+ }
+ else
+ {
+ h += itl; // passe � la ligne suivante
+ }
+ }
+
+ return h;
+}
+
+// Retourne la longueur d'un texte.
+
+int GetTextWidth(char *pText, int font)
+{
+ int width = 0;
+
+ while ( *pText != 0 )
+ {
+ width += GetCharWidth(*pText++, font);
+ }
+
+ return width;
+}
+
diff --git a/src/text.h b/src/text.h
new file mode 100644
index 0000000..404774e
--- /dev/null
+++ b/src/text.h
@@ -0,0 +1,62 @@
+// Text.h
+#ifndef TEXT_H
+#define TEXT_H
+
+#define FONTWHITE 0
+#define FONTGOLD 1
+#define FONTSELECTED 2
+#define FONTLITTLE 10
+
+typedef struct
+{
+ char charIcon;
+ char charOffsetX;
+ char charOffsetY;
+ char accentIcon;
+ char accentOffsetX;
+ char accentOffsetY;
+}
+CharOffset;
+
+extern
+void DrawText(CPixmap *pPixmap, POINT pos, char *pText, int font);
+
+extern
+void DrawTextLeft(CPixmap* pPixmap, POINT pos, char *text, int font);
+
+extern
+void DrawTextNew(CPixmap *pPixmap, POINT pos, char* pText, int font);
+
+extern
+void DrawChar(CPixmap* pPixmap, POINT* pos, char c, int font);
+
+extern
+void DrawCharSingle(CPixmap* pPixmap, POINT pos, int rank, int font);
+
+extern
+void DrawTextNew(CPixmap* pPixmap, POINT pos, char* pText, int font);
+
+extern
+void DrawTextPente(CPixmap *pPixmap, POINT pos, char *pText,
+ int pente, int font=0);
+
+extern
+void DrawTextRect(CPixmap *pPixmap, POINT pos, char *pText,
+ int pente, int font=0, int part=-1);
+
+extern
+void DrawTextCenter(CPixmap *pPixmap, POINT pos, char *pText, int font=0);
+
+extern
+int GetTextHeight(char *pText, int font=0, int part=-1);
+
+extern
+int GetTextWidth(char *pText, int font=0);
+
+extern
+void DrawBignum(CPixmap *pPixmap, POINT pos, int num);
+
+extern
+int GetBignumWidth(int num);
+
+#endif
\ No newline at end of file
diff --git a/src/texttables.h b/src/texttables.h
new file mode 100644
index 0000000..c94e91c
--- /dev/null
+++ b/src/texttables.h
@@ -0,0 +1,1677 @@
+#ifndef TEXTTABLES_H
+#define TEXTTABLES_H
+
+extern int table_width[] =
+{
+ 32,
+ 32,
+ 32,
+ 32,
+ 32,
+ 32,
+ 32,
+ 32,
+ 32,
+ 32,
+ 32,
+ 32,
+ 32,
+ 32,
+ 14,
+ 13,
+ 15,
+ 15,
+ 15,
+ 15,
+ 15,
+ 15,
+ 11,
+ 12,
+ 14,
+ 13,
+ 13,
+ 15,
+ 15,
+ 14,
+ 0,
+ 0,
+ 9,
+ 5,
+ 10,
+ 25,
+ 17,
+ 22,
+ 18,
+ 5,
+ 9,
+ 9,
+ 14,
+ 13,
+ 6,
+ 10,
+ 6,
+ 14,
+ 18,
+ 10,
+ 14,
+ 14,
+ 17,
+ 16,
+ 16,
+ 17,
+ 15,
+ 16,
+ 5,
+ 6,
+ 9,
+ 12,
+ 10,
+ 14,
+ 25,
+ 18,
+ 16,
+ 17,
+ 18,
+ 16,
+ 16,
+ 19,
+ 20,
+ 15,
+ 15,
+ 15,
+ 14,
+ 24,
+ 22,
+ 22,
+ 15,
+ 24,
+ 16,
+ 18,
+ 15,
+ 19,
+ 18,
+ 29,
+ 20,
+ 18,
+ 19,
+ 8,
+ 13,
+ 8,
+ 12,
+ 20,
+ 7,
+ 15,
+ 15,
+ 13,
+ 15,
+ 15,
+ 13,
+ 14,
+ 14,
+ 6,
+ 8,
+ 14,
+ 6,
+ 21,
+ 16,
+ 14,
+ 14,
+ 13,
+ 12,
+ 14,
+ 11,
+ 13,
+ 13,
+ 19,
+ 16,
+ 15,
+ 14,
+ 10,
+ 5,
+ 11,
+ 16,
+ 0
+};
+
+
+extern char table_char[] =
+ {
+ 0,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 2,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 4,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 5,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 6,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 7,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 8,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 9,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 10,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 11,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 12,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 14,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 32,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 33,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 34,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 35,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 36,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 37,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 38,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 39,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 40,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 41,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 42,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 43,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 44,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 45,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 46,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 47,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 48,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 49,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 50,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 51,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 52,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 53,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 54,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 55,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 56,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 57,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 58,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 59,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 60,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 61,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 62,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 63,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 64,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 65,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 66,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 67,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 68,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 69,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 70,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 71,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 72,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 73,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 74,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 75,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 76,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 77,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 78,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 79,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 80,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 81,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 82,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 83,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 84,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 85,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 86,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 87,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 88,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 89,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 90,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 91,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 92,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 93,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 94,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 95,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 96,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 97,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 98,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 99,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 100,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 101,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 102,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 103,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 104,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 105,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 106,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 107,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 108,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 109,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 110,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 111,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 112,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 113,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 114,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 115,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 116,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 117,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 118,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 119,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 120,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 121,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 122,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 123,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 124,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 125,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 126,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 127,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 5,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 4,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 16,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 97,
+ 0,
+ 0,
+ 2,
+ 2,
+ 0,
+ 17,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 27,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 29,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 19,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 18,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 21,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 20,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 105,
+ 0,
+ 0,
+ 2,
+ -1,
+ 0,
+ 23,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 22,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 110,
+ 0,
+ 0,
+ 126,
+ -1,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 111,
+ 0,
+ 0,
+ 2,
+ 1,
+ 0,
+ 24,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 28,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 25,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 117,
+ 0,
+ 0,
+ 2,
+ 2,
+ 0,
+ 26,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 15,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0
+ };
+
+#endif
\ No newline at end of file
diff --git a/src/wave.cpp b/src/wave.cpp
new file mode 100644
index 0000000..f11a909
--- /dev/null
+++ b/src/wave.cpp
@@ -0,0 +1,270 @@
+
+/*****************************************************************
+ *
+ * Copyright (c) 1996 Microsoft Corporation
+ *
+ * File: wave.cpp
+ * Content: Routines for getting waves from resources
+ * Author: Dave Edson; modified by Peter Donnelly
+ *
+ ******************************************************************/
+
+#include
+#include "wave.h"
+
+typedef struct tagWAVEFILE
+ {
+ DWORD cbSize; // Size of file
+ LPWAVEFORMATEX pwfxInfo; // Wave Header
+ LPBYTE pbData; // Wave Bits
+ }
+WAVEFILE, *LPWAVEFILE;
+
+
+// Function Prototypes
+BOOL wave_ParseWaveMemory(void *pvRes,
+ WAVEFORMATEX **ppWaveHeader,
+ BYTE **ppbWaveData,
+ DWORD *pcbWaveSize);
+
+
+/////////////////////////////////////////////////////////////////
+//
+// WAVE_LoadResource: Gets a wave file into the memory pointed
+// to by pWaveFile from a resource.
+//
+/////////////////////////////////////////////////////////////////
+
+LPVOID WAVE_LoadResource
+ (int ID, // ID of resource
+ HMODULE hModule, // hInst of app with WAVE
+ LPWAVEFILE pWaveFile) // Points to the struct to fill
+{
+ HRSRC hResInfo;
+ HGLOBAL hResData;
+ void *pvRes;
+ DWORD dwSize;
+ LPVOID lpMemory;
+
+ // Find the resource and load into memory
+ if (((hResInfo = FindResourceA(hModule, MAKEINTRESOURCEA(ID), "WAVE")) != NULL) &&
+ ((hResData = LoadResource(hModule, hResInfo)) != NULL) &&
+ ((pvRes = LockResource(hResData)) != NULL))
+ {
+ // If we found it, copy the bits from the resource into
+ // our own chunk of memory
+ dwSize = SizeofResource(hModule, hResInfo);
+ lpMemory = malloc (dwSize);
+ memcpy (lpMemory, pvRes, dwSize);
+ UnlockResource(hResData);
+ FreeResource(hResData);
+
+ // Parse it out
+ if (wave_ParseWaveMemory(lpMemory,
+ &(pWaveFile->pwfxInfo),
+ &(pWaveFile->pbData),
+ &(pWaveFile->cbSize)))
+ {
+ return lpMemory; // OK
+ }
+ }
+
+ return NULL;
+}
+
+//////////////////////////////////////////////////////////////////
+//
+// wave_ParseWaveMemory
+// Parses a chunk of memory into the header and samples.
+// This is done by looking for the "fmt " and "data"
+// fields in the memory.
+//
+//////////////////////////////////////////////////////////////////
+
+BOOL wave_ParseWaveMemory
+
+ (LPVOID lpChunkOfMemory, // Points to raw ram
+ LPWAVEFORMATEX *lplpWaveHeader, // Points to pointer to header
+ LPBYTE *lplpWaveSamples,// Points to pointer to samples
+ LPDWORD lpcbWaveSize) // Points to size
+{
+ LPDWORD pdw;
+ LPDWORD pdwEnd;
+ DWORD dwRiff;
+ DWORD dwType;
+ DWORD dwLength;
+
+ // Set defaults to NULL or zero
+ if (lplpWaveHeader)
+ *lplpWaveHeader = NULL;
+
+ if (lplpWaveSamples)
+ *lplpWaveSamples = NULL;
+
+ if (lpcbWaveSize)
+ *lpcbWaveSize = 0;
+
+ // Set up DWORD pointers to the start of the chunk
+ // of memory.
+ pdw = (DWORD *)lpChunkOfMemory;
+
+ // Get the type and length of the chunk of memory
+ dwRiff = *pdw++;
+ dwLength = *pdw++;
+ dwType = *pdw++;
+
+ // Using the mmioFOURCC macro (part of Windows SDK), ensure
+ // that this is a RIFF WAVE chunk of memory
+ if (dwRiff != mmioFOURCC('R', 'I', 'F', 'F'))
+ return FALSE; // not even RIFF
+
+ if (dwType != mmioFOURCC('W', 'A', 'V', 'E'))
+ return FALSE; // not a WAV
+
+ // Find the pointer to the end of the chunk of memory
+ pdwEnd = (DWORD *)((BYTE *)pdw + dwLength-4);
+
+ // Run through the bytes looking for the tags
+ while (pdw < pdwEnd)
+ {
+ dwType = *pdw++;
+ dwLength = *pdw++;
+
+ switch (dwType)
+ {
+ // Found the format part
+ case mmioFOURCC('f', 'm', 't', ' '):
+
+ if (lplpWaveHeader && !*lplpWaveHeader)
+ {
+ if (dwLength < sizeof(WAVEFORMAT))
+ return FALSE; // something's wrong! Not a WAV
+
+ // Set the lplpWaveHeader to point to this part of
+ // the memory chunk
+ *lplpWaveHeader = (LPWAVEFORMATEX)pdw;
+
+ // Check to see if the other two items have been
+ // filled out yet (the bits and the size of the
+ // bits). If so, then this chunk of memory has
+ // been parsed out and we can exit
+ if ((!lplpWaveSamples || *lplpWaveSamples) &&
+ (!lpcbWaveSize || *lpcbWaveSize))
+ {
+ return TRUE;
+ }
+ }
+ break;
+
+ // Found the samples
+ case mmioFOURCC('d', 'a', 't', 'a'):
+
+ if ((lplpWaveSamples && !*lplpWaveSamples) ||
+ (lpcbWaveSize && !*lpcbWaveSize))
+ {
+ // Point the samples pointer to this part of the
+ // chunk of memory.
+ if (lplpWaveSamples) *lplpWaveSamples = (LPBYTE)pdw;
+
+ // Set the size of the wave
+ if (lpcbWaveSize) *lpcbWaveSize = dwLength;
+
+ // Make sure we have our header pointer set up.
+ // If we do, we can exit
+ if (!lplpWaveHeader || *lplpWaveHeader)
+ return TRUE;
+ }
+ break;
+
+ } // End case
+
+ // Move the pointer through the chunk of memory
+ pdw = (DWORD *)((BYTE *)pdw + ((dwLength+1)&~1));
+ }
+
+ // Failed! If we made it here, we did not get all the pieces
+ // of the wave
+ return FALSE;
+} // wave_ParseWaveMemory
+
+
+//////////////////////////////////////////////////////////////////
+//
+// LoadWave
+// Gets the sound data and loads it into a DirectSound
+// secondary buffer.
+//
+//
+//////////////////////////////////////////////////////////////////
+
+void LoadWave(HINSTANCE hinst, int ResourceID,
+ LPDIRECTSOUND lpds,
+ LPDIRECTSOUNDBUFFER &lpDSB)
+ {
+// These variables are used in Steps 1 and 2
+ LPVOID lpWaveData;
+ WAVEFILE WaveFile;
+ DSBUFFERDESC dsbd;
+
+ // These variables are used in step 3, further down below
+ LPVOID pbData = NULL;
+ LPVOID pbData2 = NULL;
+ DWORD dwLength;
+ DWORD dwLength2;
+
+
+ lpWaveData = WAVE_LoadResource (ResourceID, hinst, &WaveFile );
+
+ // Step 1: Set up the direct sound buffer.
+ memset(&dsbd, 0, sizeof(DSBUFFERDESC));
+
+ dsbd.dwSize = sizeof(DSBUFFERDESC);
+ // We want a buffer that lives on the sound card's memory
+ // (DSBCAPS_STATIC) and can have the pan, volume, and
+ // frequency adjusted (DSBCAPS_CTRLDEFAULT)
+ dsbd.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_STATIC ;
+
+ // Set up the size and format
+ dsbd.dwBufferBytes = WaveFile.cbSize;
+ dsbd.lpwfxFormat = WaveFile.pwfxInfo; // Must be a PCM format!
+
+ // Step 2: Create the buffer
+ if (DS_OK != lpds->CreateSoundBuffer(&dsbd, &lpDSB, NULL))
+ {
+ OutputDebugStringA("Failed to create sound buffer\n");
+ return;
+ }
+// Once this code succeeds, lpDSB will point to a DirectSoundBuffer.
+// At this point, you can copy blocks of sound data into the buffer,
+// using the Lock and Unlock interfaces on the DirectSoundBuffer:
+
+ // Lock down the DirectSound buffer
+ if (DS_OK == lpDSB->Lock
+ (0, // Offset into buffer to start writing
+ WaveFile.cbSize, // Size of wave file to copy in
+ &pbData, // Points to first block of sound data
+ &dwLength, // Length of first block of data
+ &pbData2, // Points to second block of sound data
+ &dwLength2, // Length of second block of data
+ 0L)) // Flags
+ {
+ // Copy first chunk
+ memcpy(pbData, WaveFile.pbData, dwLength);
+
+ // Copy second chunk
+ if (dwLength2)
+ memcpy(pbData2, WaveFile.pbData+dwLength , dwLength2);
+
+ // Free up the memory allocated in the WAVE_LoadFile function, since we
+ // have copied it to the buffer
+ free (lpWaveData);
+
+ // Unlock the buffer
+ if (DS_OK != lpDSB->Unlock(pbData, dwLength, pbData2, dwLength2))
+ OutputDebugStringA("Unlock failed");
+ }
+ else
+ {
+ OutputDebugStringA("Lock failed");
+ }
+ } // LoadWave
diff --git a/src/wave.h b/src/wave.h
new file mode 100644
index 0000000..de0ce98
--- /dev/null
+++ b/src/wave.h
@@ -0,0 +1,14 @@
+/***********************************************
+ * Sound related stuff, I dunno
+************************************************/
+
+#ifndef WAVE_H
+#define WAVE_H
+
+#include
+
+void LoadWave(HINSTANCE hinst, int ResourceID,
+ LPDIRECTSOUND lpds,
+ LPDIRECTSOUNDBUFFER &lpDSB);
+
+#endif
\ No newline at end of file
diff --git a/util/extract_phasetable.py b/util/extract_phasetable.py
new file mode 100644
index 0000000..64f0e82
--- /dev/null
+++ b/util/extract_phasetable.py
@@ -0,0 +1,68 @@
+# JUMMY WAS HERE
+# extract phase table from speedy blupi 2.2 english ver
+
+import sys
+import io
+
+offset = 0x3d400
+
+outs = []
+
+with io.open('BLUPI.exe', 'rb') as f:
+ data = f.read()
+ outs.append('static Phase table[] =')
+ outs.append('{')
+ for i in range(39):
+
+ poff = offset + i * 7084
+ p = int.from_bytes(data[poff : poff + 4], 'little')
+ if p == 0:
+ outs.append('{0}')
+ break
+ outs.append('{')
+ outs.append(str(p) + ',')
+ outs.append('"' + data[poff + 4 : poff + 36].decode('ascii').rstrip('\x00') + '",')
+ outs.append('TRUE,' if int.from_bytes(data[poff + 36 : poff + 40], 'little') != 0 else 'FALSE,')
+ outs.append('TRUE,' if int.from_bytes(data[poff + 40 : poff + 44], 'little') != 0 else 'FALSE,')
+ outs.append('{')
+ for j in range(40):
+ boff = poff + 44 + j * 176
+ b = int.from_bytes(data[boff : boff + 4], 'little')
+ if b == 0:
+ outs.append('{0}')
+ break
+ else:
+ outs.append('{')
+ outs.append(str(b) + ',')
+ s = ''
+ s += str(int.from_bytes(data[boff + 4 : boff + 8], 'little')) + ', '
+ m = int.from_bytes(data[boff + 8 : boff + 12], 'little')
+ if m == 0:
+ s += '{0},'
+ else:
+ s += '{' + str(m) + ', '
+ for k in range(m):
+ moff = boff + 12 + k * 4
+ s += str(int.from_bytes(data[moff : moff + 4], 'little')) + ', '
+ s += '},'
+ outs.append(str(s))
+ outs.append(str(int.from_bytes(data[boff + 88 : boff + 92], 'little')) + ', ' + str(int.from_bytes(data[boff + 92 : boff + 96], 'little')) + ',')
+ s = ''
+ t = int.from_bytes(data[boff + 96 : boff + 100], 'little')
+ if t == 0:
+ s += '{0}'
+ else:
+ s += '{ ' + str(t) + ', '
+ for k in range(t):
+ toff = boff + 100 + k * 4
+ s += str(int.from_bytes(data[toff : toff + 4], 'little')) + ', '
+ s += '}'
+ outs.append(str(s))
+ outs.append('},')
+ outs.append('},')
+ outs.append('},')
+ outs.append('},')
+outs.append('};')
+
+with io.open('out.h', 'wb') as f2:
+ f2.write(bytearray('\n'.join(outs), 'ascii'))
diff --git a/util/extract_pixtables.py b/util/extract_pixtables.py
new file mode 100644
index 0000000..a1fd321
--- /dev/null
+++ b/util/extract_pixtables.py
@@ -0,0 +1,31 @@
+# JUMMY WAS HERE
+# extract pixtables from speedy blupi 2.2 english ver
+
+import sys
+import io
+
+offsets = {}
+offsets['table_icon_blupi'] = 0x81bf8
+offsets['table_icon_element'] = 0x84070
+offsets['table_icon_explo'] = 0x84e00
+offsets['table_icon_object'] = 0x82bc0
+
+outs = {}
+
+with io.open('BLUPI.exe', 'rb') as f:
+ data = f.read()
+ for k, v in offsets.items():
+ lg = int.from_bytes(data[v : v + 2], 'little')
+ outs[k] = []
+ outs[k].append("extern short " + k + "[]{");
+ outs[k].append(str(lg) + ',');
+ for i in range(lg):
+ string = ''
+ for j in range(6):
+ string += str(int.from_bytes(data[v + i*12 + j*2 + 2 : v + i*12 + j*2 + 4], 'little')) + ','
+ if j % 2 == 1:
+ string += ' '
+ outs[k].append(string)
+ outs[k].append('};')
+with io.open('out.h', 'wb') as f2:
+ f2.write(bytearray(('\n\n'.join(['\n'.join(w) for w in [v for _, v in outs.items()]])), 'ascii'))
diff --git a/util/extract_tableblupi.py b/util/extract_tableblupi.py
new file mode 100644
index 0000000..8bfda46
--- /dev/null
+++ b/util/extract_tableblupi.py
@@ -0,0 +1,15 @@
+# JUMMY WAS HERE
+# extract table_blupi from speedy blupi 2.2 english ver
+
+import sys
+import io
+
+offset = 0x34e60
+out = []
+
+with io.open('BLUPI.exe', 'rb') as f:
+ data = f.read()
+ for i in range(2842):
+ out.append (int.from_bytes(data[offset + i * 4 : offset + i * 4 + 4], byteorder='little', signed=True))
+with io.open('out.h', 'wb') as f2:
+ f2.write(bytearray(', '.join(map(str,out)), 'ascii'))
diff --git a/util/extract_tablemirror.py b/util/extract_tablemirror.py
new file mode 100644
index 0000000..7495192
--- /dev/null
+++ b/util/extract_tablemirror.py
@@ -0,0 +1,15 @@
+# JUMMY WAS HERE
+# extract table_mirror from speedy blupi 2.2 english ver
+
+import sys
+import io
+
+offset = 0x37ac8
+out = []
+
+with io.open('BLUPI.exe', 'rb') as f:
+ data = f.read()
+ for i in range(335):
+ out.append (int.from_bytes(data[offset + i * 4 : offset + i * 4 + 4], byteorder='little', signed=True))
+with io.open('out.h', 'wb') as f2:
+ f2.write(bytearray(', '.join(map(str,out)), 'ascii'))