pax_global_header00006660000000000000000000000064146450752560014530gustar00rootroot0000000000000052 comment=713c833826c47e4decd78f6f28a4a1bd8f1527ea mupen64plus-video-glide64-src-2.6.0/000077500000000000000000000000001464507525600170645ustar00rootroot00000000000000mupen64plus-video-glide64-src-2.6.0/.gitattributes000066400000000000000000000007661464507525600217700ustar00rootroot00000000000000* text=auto # normal text files *.6 text AUTHORS text *.c text *.cfg text *.cht text *.conf text COPYING text *.cpp text *.def text *-license text *.h text *.html text *.ini text INSTALL text LICENSES text Makefile text *.py text README text RELEASE text *.S text *.sh text *.txt text *.ver text # windows specific text files *.sln text eol=crlf *.vcproj text eol=crlf *.vcxproj text eol=crlf *.vcxproj.filters text eol=crlf # binary files *.gz binary *.ttf binary cursor.tex binary font.tex binary mupen64plus-video-glide64-src-2.6.0/.github/000077500000000000000000000000001464507525600204245ustar00rootroot00000000000000mupen64plus-video-glide64-src-2.6.0/.github/workflows/000077500000000000000000000000001464507525600224615ustar00rootroot00000000000000mupen64plus-video-glide64-src-2.6.0/.github/workflows/build.yml000066400000000000000000000101531464507525600243030ustar00rootroot00000000000000name: Glide64 on: push: paths-ignore: - '.{gitattributes,gitignore,travis.yml}' - '*.md,appveyor.yml,README' pull_request: paths-ignore: - '.{gitattributes,gitignore,travis.yml}' - '*.md,appveyor.yml,README' workflow_dispatch: jobs: Linux: strategy: fail-fast: false matrix: include: - cc: GCC arch: x64 - cc: GCC arch: x86 - cc: Clang arch: x64 - cc: Clang arch: x86 name: Linux / ${{ matrix.cc }} / ${{ matrix.arch }} runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - name: Get build dependencies and arrange the environment run: | git clone --depth 1 https://github.com/mupen64plus/mupen64plus-core.git ../mupen64plus-core export C_CLANG_SUFFIX="-15" C_GCC_SUFFIX="-12" export BUILD_DEPS="libgl1-mesa-dev libsdl1.2-dev libsdl2-dev" ./../mupen64plus-core/.github/workflows/scripts/ci_install_ubuntu_deps.sh ${{ matrix.arch }} ${{ matrix.cc }} - name: Build and related stuff, backup binaries run: | export C_CLANG_SUFFIX="-15" C_GCC_SUFFIX="-12" export PATH="$(pwd)/../mupen64plus-core/.github/workflows/scripts:${PATH}" export OPTFLAGS="-O2 -flto -msse2" export CONFIG_OVERRIDE="SDL_CONFIG="sdl-config"" ci_build.sh ${{ matrix.arch }} ${{ matrix.cc }} export CONFIG_OVERRIDE="SDL_CONFIG="sdl2-config"" ci_build.sh ${{ matrix.arch }} ${{ matrix.cc }} makepkg - name: Upload artifact if: matrix.cc == 'GCC' uses: actions/upload-artifact@v4 with: name: ${{ env.PKG_NAME }} path: pkg/*.tar.gz MSYS2: strategy: fail-fast: false matrix: include: - cc: GCC arch: x64 cross: x86_64 env: MINGW64 - cc: GCC arch: x86 cross: i686 env: MINGW32 name: Windows / MSYS2 ${{ matrix.cc }} / ${{ matrix.arch }} runs-on: windows-2022 defaults: run: shell: msys2 {0} steps: - uses: actions/checkout@v4 - uses: msys2/setup-msys2@v2 with: msystem: ${{ matrix.env }} update: true install: >- git libtool make mingw-w64-${{ matrix.cross }}-gcc mingw-w64-${{ matrix.cross }}-toolchain mingw-w64-${{ matrix.cross }}-ntldd mingw-w64-${{ matrix.cross }}-SDL - name: Build and related stuff, backup binaries run: | echo "NOTE: Building in MSYS2 against SDL2 always fails..." echo "" git clone --depth 1 https://github.com/mupen64plus/mupen64plus-core.git ../mupen64plus-core export OPTFLAGS="-O2 -flto -msse2" ./../mupen64plus-core/.github/workflows/scripts/ci_build.sh ${{ matrix.arch }} ${{ matrix.cc }} - name: Backup dependencies, etc... run: | ./../mupen64plus-core/.github/workflows/scripts/ci_backup_mingw_deps.sh ${{ matrix.env }} - name: Upload artifact uses: actions/upload-artifact@v4 with: name: ${{ env.PKG_NAME }} path: pkg/* Nightly-build: runs-on: ubuntu-latest if: github.ref_name == 'master' needs: [Linux, MSYS2] steps: - uses: actions/checkout@v4 - name: Download artifacts uses: actions/download-artifact@v4 with: path: binaries - name: Get some tools run: | git clone --depth 1 https://github.com/mupen64plus/mupen64plus-core.git ../mupen64plus-core sudo apt-get update sudo apt-get -y install hashdeep - name: Creating new artifacts and update nightly-build run: | ./../mupen64plus-core/.github/workflows/scripts/ci_nightly_artifacts.sh - name: Nightly-build uses: ncipollo/release-action@v1 with: prerelease: true allowUpdates: true removeArtifacts: true replacesArtifacts: false tag: nightly-build artifacts: pkg/* mupen64plus-video-glide64-src-2.6.0/.github/workflows/schedule.yml000066400000000000000000000100611464507525600247760ustar00rootroot00000000000000name: Glide64 - Scheduled on: schedule: - cron: '10 14 21 * *' jobs: Linux: strategy: fail-fast: false matrix: include: - cc: GCC arch: x64 - cc: GCC arch: x86 - cc: Clang arch: x64 - cc: Clang arch: x86 name: Linux / ${{ matrix.cc }} / ${{ matrix.arch }} runs-on: ubuntu-22.04 if: github.repository == 'mupen64plus/mupen64plus-video-glide64' steps: - uses: actions/checkout@v4 - name: Get build dependencies and arrange the environment run: | git clone --depth 1 https://github.com/mupen64plus/mupen64plus-core.git ../mupen64plus-core export C_CLANG_SUFFIX="-15" C_GCC_SUFFIX="-12" export BUILD_DEPS="libgl1-mesa-dev libsdl1.2-dev libsdl2-dev" ./../mupen64plus-core/.github/workflows/scripts/ci_install_ubuntu_deps.sh ${{ matrix.arch }} ${{ matrix.cc }} - name: Build and related stuff, backup binaries run: | export C_CLANG_SUFFIX="-15" C_GCC_SUFFIX="-12" export PATH="$(pwd)/../mupen64plus-core/.github/workflows/scripts:${PATH}" export OPTFLAGS="-O2 -flto -msse2" export CONFIG_OVERRIDE="SDL_CONFIG="sdl-config"" ci_build.sh ${{ matrix.arch }} ${{ matrix.cc }} export CONFIG_OVERRIDE="SDL_CONFIG="sdl2-config"" ci_build.sh ${{ matrix.arch }} ${{ matrix.cc }} makepkg - name: Upload artifact if: matrix.cc == 'GCC' uses: actions/upload-artifact@v4 with: name: ${{ env.PKG_NAME }} path: pkg/*.tar.gz MSYS2: strategy: fail-fast: false matrix: include: - cc: GCC arch: x64 cross: x86_64 env: MINGW64 - cc: GCC arch: x86 cross: i686 env: MINGW32 name: Windows / MSYS2 ${{ matrix.cc }} / ${{ matrix.arch }} runs-on: windows-2022 if: github.repository == 'mupen64plus/mupen64plus-video-glide64' defaults: run: shell: msys2 {0} steps: - uses: actions/checkout@v4 - uses: msys2/setup-msys2@v2 with: msystem: ${{ matrix.env }} update: true install: >- git libtool make mingw-w64-${{ matrix.cross }}-gcc mingw-w64-${{ matrix.cross }}-toolchain mingw-w64-${{ matrix.cross }}-ntldd mingw-w64-${{ matrix.cross }}-SDL - name: Build and related stuff, backup binaries run: | echo "NOTE: Building in MSYS2 against SDL2 always fails..." echo "" git clone --depth 1 https://github.com/mupen64plus/mupen64plus-core.git ../mupen64plus-core export OPTFLAGS="-O2 -flto -msse2" ./../mupen64plus-core/.github/workflows/scripts/ci_build.sh ${{ matrix.arch }} ${{ matrix.cc }} - name: Backup dependencies, etc... run: | ./../mupen64plus-core/.github/workflows/scripts/ci_backup_mingw_deps.sh ${{ matrix.env }} - name: Upload artifact uses: actions/upload-artifact@v4 with: name: ${{ env.PKG_NAME }} path: pkg/* Nightly-build: runs-on: ubuntu-latest if: github.ref_name == 'master' needs: [Linux, MSYS2] steps: - uses: actions/checkout@v4 - name: Download artifacts uses: actions/download-artifact@v4 with: path: binaries - name: Get some tools run: | git clone --depth 1 https://github.com/mupen64plus/mupen64plus-core.git ../mupen64plus-core sudo apt-get update sudo apt-get -y install hashdeep - name: Creating new artifacts and update nightly-build run: | ./../mupen64plus-core/.github/workflows/scripts/ci_nightly_artifacts.sh - name: Nightly-build uses: ncipollo/release-action@v1 with: prerelease: true allowUpdates: true removeArtifacts: true replacesArtifacts: false tag: nightly-build artifacts: pkg/* mupen64plus-video-glide64-src-2.6.0/.gitignore000066400000000000000000000001031464507525600210460ustar00rootroot00000000000000/projects/unix/_obj*/ /projects/unix/mupen64plus-video-glide64*.so mupen64plus-video-glide64-src-2.6.0/.travis.yml000066400000000000000000000016231464507525600211770ustar00rootroot00000000000000sudo: false dist: trusty language: cpp compiler: - gcc - clang addons: apt: packages: - git - libsdl1.2-dev - libsdl2-dev - libgl1-mesa-dev - pkg-config before_install: - git clone --depth=1 --branch=master git://github.com/mupen64plus/mupen64plus-core.git deps/mupen64plus-core env: - NO_ASM=0 - NO_ASM=1 script: - make -C projects/unix APIDIR="$(pwd)/deps/mupen64plus-core/src/api/" V=1 clean && LDFLAGS="-Wl,--no-add-needed -Wl,--no-undefined" OPTFLAGS="-O2" make SDL_CONFIG=sdl-config CC="${CC}" CXX="${CXX}" -j$(nproc) -C projects/unix APIDIR="$(pwd)/deps/mupen64plus-core/src/api/" V=1 all - make -C projects/unix APIDIR="$(pwd)/deps/mupen64plus-core/src/api/" V=1 clean && LDFLAGS="-Wl,--no-add-needed -Wl,--no-undefined" OPTFLAGS="-O2" make SDL_CONFIG=sdl2-config CC="${CC}" CXX="${CXX}" -j$(nproc) -C projects/unix APIDIR="$(pwd)/deps/mupen64plus-core/src/api/" V=1 all mupen64plus-video-glide64-src-2.6.0/COPYING000066400000000000000000000431031464507525600201200ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) 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 this service 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 make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. 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. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), 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 distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the 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 a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE 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. 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 convey 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 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision 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, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This 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. mupen64plus-video-glide64-src-2.6.0/data/000077500000000000000000000000001464507525600177755ustar00rootroot00000000000000mupen64plus-video-glide64-src-2.6.0/data/Glide64.ini000066400000000000000000001020321464507525600216720ustar00rootroot00000000000000; UCODE: ; These are ucode crcs used in the uCode detector. ; If a crc is not found here, the plugin will ask you ; to add it. All these values are in hexadecimal. ; ; uCodes: ; -1 - Unknown, display error ; 0 - RSP SW 2.0X (Super Mario 64) ; 1 - F3DEX 1.XX (Star Fox 64) ; 2 - F3DEX 2.XX (The Legend of Zelda: Ocarina of Time) ; 3 - F3DEX ? (WaveRace) ; 4 - RSP SW 2.0D EXT (Star Wars: Shadows of the Empire) ; 5 - RSP SW 2.0 (Diddy Kong Racing); ; 6 - S2DEX 1.XX (Yoshi's Story - SimCity 2000) ; 7 - RSP SW PD (Perfect Dark) ; 8 - F3DEXBG 2.08 (Conker's Bad Fur Day) [UCODE] 006bd77f=0 03044b84=2 030f4b84=2 05165579=1 05777c62=1 057e7c62=1 07200895=1 0bf36d36=2 0d7bbffb=-1 0d7cbffb=5 0ff79527=2 0ff795bf=-1 1118b3e0=1 168e9cd5=2 1a1e18a0=2 1a1e1920=2 1a62dbaf=2 1a62dc2f=2 1de712ff=1 1ea9e30f=6 21f91834=2 21f91874=2 22099872=2 24cd885b=1 26a7879a=1 299d5072=6 2b291027=2 2b5a89c2=6 2c7975d6=1 2f71d1d5=2 2f7dd1d5=2 327b933d=1 339872a6=1 377359b6=2 3a1c2b34=0 3a1cbac3=0 3f7247fb=0 3ff1a4ca=1 4165e1fd=0 4340ac9b=1 440cfad6=1 47d46e86=7 485abff2=2 4fe6df78=1 5182f610=0 5257cd2a=1 5414030c=1 5414030d=1 559ff7d4=1 5b5d36e3=4 5b5d3763=3 5d1d6f53=0 5d3099f1=2 5df1408c=1 5ef4e34a=1 6075e9eb=1 60c1dcc4=1 6124a508=2 630a61fb=2 63be08b1=5 63be08b3=5 64ed27e5=1 65201989=2 65201a09=2 66c0b10a=1 679e1205=2 6bb745c9=6 6d8f8f8a=2 6e4d50af=0 6eaa1da8=1 72a4f34e=1 73999a23=1 74af0a74=6 753be4a5=2 794c3e28=6 7df75834=1 7f2d0a2e=1 82f48073=1 841ce10f=1 844b55b5=-1 863e1ca7=1 86b1593e=-1 8805ffea=1 8d5735b2=1 8d5735b3=1 8ec3e124=-1 93d11f7b=2 93d11ffb=2 93d1ff7b=2 9551177b=2 955117fb=2 95cd0062=2 97d1b58a=1 a2d0f88e=2 a346a5cc=1 aa86cb1d=2 aae4a5b9=2 ad0a6292=2 ad0a6312=2 ae08d5b9=0 b1821ed3=1 b4577b9c=1 b54e7f93=0 b62f900f=2 ba65ea1e=2 ba86cb1d=8 bc03e969=0 bc45382e=2 be78677c=1 bed8b069=1 c3704e41=1 c46dbc3d=1 c99a4c6c=1 c901ce73=2 c901cef3=2 cb8c9b6c=2 cee7920f=1 cfa35a45=2 d1663234=1 d20dedbf=6 d2a9f59c=1 d41db5f7=1 d5604971=0 d57049a5=1 d5c4dc96=-1 d5d68b1f=0 d802ec04=1 da13ab96=2 de7d67d4=2 e1290fa2=2 e41ec47e=0 e65cb4ad=2 e89c2b92=1 e9231df2=1 ec040469=1 ee47381b=1 ef54ee35=1 f9893f70=-1 fb816260=1 ff372492=-1 ; Game specific settings ; ; In the [DEFAULT] section there are the default options for a game, which can ; be overriden in the section with the game's internal name. ; ; offset_x: the x offset on the screen, in pixels of 320x240 resolution ; offset_y: the y offset on the screen, in pixels of 320x240 resolution ; scale_x: the peccentage to scale in the x axis, 100000 representing 100% ; scale_y: the percentage to scale in the y axis, 100000 representing 100% [DEFAULT] offset_x = 0 offset_y = 0 scale_x = 100000 scale_y = 100000 alt_tex_size = 0 use_sts1_only = 0 PPL = 0 force_microcheck = 0 texrect_zbuf = 0 fix_tex_coord = 0 optimize_texrect = 1 optimize_write = 0 hires_buf_clear = 1 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 soft_depth_compare = 0 force_depth_compare = 0 fillcolor_fix = 0 depth_bias = 20 increase_texrect_edge = 0 decrease_fillrect_edge = 0 increase_primdepth = 0 stipple_mode = 2 stipple_pattern = 1041204192 [1080 SNOWBOARDING] optimize_texrect = 1 alt_tex_size = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 2 fb_smart = 1 fb_clear = 1 fb_read_alpha = 0 [A Bug's Life] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [AIDYN_CHRONICLES] filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [All-Star Baseball '0] force_depth_compare = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [All-Star Baseball 99] filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [All Star Baseball 99] filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [ARMYMENAIRCOMBAT] increase_texrect_edge = 1 filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [BURABURA POYON] fix_tex_coord = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 ;Bakushou Jinsei 64 - Mezease! Resort Ou. [ÊÞ¸¼®³¼Þݾ²64] fb_info_disable = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [BAKU-BOMBERMAN] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [BAKUBOMB2] filtering = 1 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [BANGAIOH] filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Banjo-Kazooie] filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [BANJO KAZOOIE 2] filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [BANJO TOOIE] filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [BASS HUNTER 64] fix_tex_coord = 1 filtering = 0 depthmode = 1 fog = 1 buff_clear = 0 swapmode = 2 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [BEETLE ADVENTURE JP] wrap_big_tex = 1 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Beetle Adventure Rac] wrap_big_tex = 1 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Big Mountain 2000] filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [BIOFREAKS] filtering = 0 depthmode = 0 fog = 1 buff_clear = 0 swapmode = 0 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [BioHazard II] detect_cpu_write = 1 fix_tex_coord = 128 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 2 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Blast Corps] filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 0 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [Blastdozer] filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 0 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [Body Harvest] filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [BODY HARVEST] filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [BOMBERMAN64E] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [BOMBERMAN64U] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [BOMBERMAN64U2] filtering = 1 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [BRUNSWICKBOWLING] filtering = 0 depthmode = 0 fog = 1 buff_clear = 0 swapmode = 0 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Bust A Move 3 DX] filtering = 2 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Bust A Move '99] filtering = 2 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Bust A Move 2] fix_tex_coord = 1 filtering = 2 depthmode = 1 fog = 0 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [CARMAGEDDON64] wrap_big_tex = 1 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [CASTLEVANIA] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 1 fb_read_alpha = 0 [CASTLEVANIA2] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 1 fb_read_alpha = 0 [CENTRE COURT TENNIS] soft_depth_compare = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Chameleon Twist2] filtering = 1 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [CITY TOUR GP] force_microcheck = 1 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Command&Conquer] fix_tex_coord = 1 filtering = 1 depthmode = 1 fog = 0 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [CONKER BFD] optimize_texrect = 1 ignore_previous = 1 filtering = 1 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 1 fb_read_alpha = 0 [CruisnExotica] filtering = 1 depthmode = 1 fog = 1 buff_clear = 0 swapmode = 0 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [custom robo] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [CUSTOMROBOV2] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [CyberTiger] fix_tex_coord = 16 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [DAFFY DUCK STARRING] filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 wrap_big_tex = 1 [DeadlyArts] soft_depth_compare = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [DERBYSTALLION 64] fix_tex_coord = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [D K DISPLAY] filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 1 fb_read_alpha = 0 [Donald Duck Goin' Qu] detect_cpu_write = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Donald Duck Quack At] detect_cpu_write = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [DONKEY KONG 64] lodmode = 1 depth_bias = 64 filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 1 fb_read_alpha = 0 [Doom64] fillcolor_fix = 1 filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [DOOM64] fillcolor_fix = 1 filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [DR.MARIO 64] fix_tex_coord = 256 optimize_write = 1 filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [DRACULA MOKUSHIROKU] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 1 fb_read_alpha = 0 [DRACULA MOKUSHIROKU2] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 1 fb_read_alpha = 0 [Dual heroes JAPAN] filtering = 1 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Dual heroes PAL] filtering = 1 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Dual heroes USA] filtering = 1 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [DUKE NUKEM] increase_primdepth = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [EARTHWORM JIM 3D] increase_primdepth = 1 filtering = 1 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Eltail] filtering = 2 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [EVANGELION] filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [EXCITEBIKE64] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [extreme_g] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [EXTREME_G] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [extremeg] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [´¸½ÄذÑG2] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 1 fb_read_alpha = 0 [Extreme G 2] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 1 fb_read_alpha = 0 [F1 POLE POSITION 64] filtering = 2 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [F1RacingChampionship] filtering = 0 depthmode = 0 fog = 1 buff_clear = 0 swapmode = 0 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [F1 WORLD GRAND PRIX] soft_depth_compare = 1 wrap_big_tex = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 0 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [F1 WORLD GRAND PRIX2] wrap_big_tex = 1 soft_depth_compare = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 0 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [F-ZERO X] filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 ;Fushigi no Dungeon - Furai no Shiren 2 (J) [F3 ̳ײɼÚÝ2] decrease_fillrect_edge = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [GANBAKE GOEMON] alt_tex_size = 1 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [G.A.S.P!!Fighters'NE] soft_depth_compare = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [GAUNTLET LEGENDS] filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 2 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Getter Love!!] filtering = 2 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Gex 3 Deep Cover Gec] filtering = 1 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [GEX: ENTER THE GECKO] filtering = 1 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Glover] filtering = 1 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [GOEMON2 DERODERO] filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [GOEMONS GREAT ADV] filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [GOLDENEYE] filtering = 1 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [GOLDEN NUGGET 64] filtering = 2 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [GT64] force_microcheck = 1 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 ; Hamster Monogatori [ÊѽÀ°ÓɶÞÀØ64] force_microcheck = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [HARVESTMOON64] filtering = 0 depthmode = 0 fog = 0 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 ; Harvest Moon 64 JAP [ÎÞ¸¼Þ®³ÓɶÞÀØ2] filtering = 0 depthmode = 0 fog = 0 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [HEXEN] detect_cpu_write = 1 filtering = 1 depthmode = 1 fog = 1 buff_clear = 0 swapmode = 2 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [HSV ADVENTURE RACING] wrap_big_tex = 1 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Holy Magic Century] filtering = 2 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [HUMAN GRAND PRIX] filtering = 2 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [·×¯Ä¶²¹Â 64ÀÝòÀÞÝ] filtering = 1 depthmode = 0 fog = 1 buff_clear = 0 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Iggy's Reckin' Balls] fix_tex_coord = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [I S S 64] filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 0 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [I.S.S.2000] filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [ITF 2000] filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [IT&F SUMMERGAMES] filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [J_league 1997] fix_tex_coord = 1 filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [J LEAGUE LIVE 64] wrap_big_tex = 1 filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [JEREMY MCGRATH SUPER] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 0 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [JET FORCE GEMINI] ignore_previous = 1 alt_tex_size = 1 filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [J F G DISPLAY] ignore_previous = 1 alt_tex_size = 1 filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [Kirby64] filtering = 1 depthmode = 0 fog = 1 buff_clear = 0 swapmode = 0 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Killer Instinct Gold] filtering = 0 depthmode = 0 fog = 0 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [KILLER INSTINCT GOLD] filtering = 0 depthmode = 0 fog = 0 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [KNIFE EDGE] wrap_big_tex = 1 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Knockout Kings 2000] filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [LCARS - WT_Riker] filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [LEGORacers] detect_cpu_write = 1 filtering = 0 depthmode = 1 fog = 1 buff_clear = 0 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 1 [LET'S SMASH] soft_depth_compare = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [LT DUCK DODGERS] wrap_big_tex = 1 filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [MACE] fix_tex_coord = 8 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Madden NFL 2002] fix_tex_coord = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [MAGICAL TETRIS] force_microcheck = 1 filtering = 0 depthmode = 1 fog = 0 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [MAJORA'S MASK] wrap_big_tex = 1 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 1 fb_read_alpha = 0 [MARIOKART64] stipple_mode = 1 stipple_pattern = 4286595040 filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [MarioGolf64] fb_info_disable = 1 ignore_aux_copy = 1 optimize_texrect = 1 hires_buf_clear = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 1 fb_read_alpha = 0 [MarioParty] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 2 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [MarioParty2] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 2 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [MarioParty3] fix_tex_coord = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [MARIO STORY] hires_buf_clear = 0 optimize_texrect = 0 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 2 fb_smart = 1 fb_clear = 0 fb_read_alpha = 1 [MASTERS'98] wrap_big_tex = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [Mega Man 64] increase_texrect_edge = 1 filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [MGAH VOL1] force_microcheck = 1 filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [MICKEY USA] alt_tex_size = 1 filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 1 fb_read_alpha = 0 [MICKEY USA PAL] alt_tex_size = 1 filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 1 fb_read_alpha = 0 [MICROMACHINES64TURBO] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [MISCHIEF MAKERS] filtering = 2 depthmode = 1 fog = 0 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [MK_MYTHOLOGIES] filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Monaco GP Racing 2] filtering = 0 depthmode = 0 fog = 1 buff_clear = 0 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Monaco Grand Prix] filtering = 0 depthmode = 0 fog = 1 buff_clear = 0 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [MortalKombatTrilogy] filtering = 2 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [MS. PAC-MAN MM] detect_cpu_write = 1 filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [MYSTICAL NINJA] alt_tex_size = 1 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [NASCAR 99] filtering = 0 depthmode = 0 fog = 1 buff_clear = 0 swapmode = 0 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [NASCAR 2000] filtering = 0 depthmode = 0 fog = 1 buff_clear = 0 swapmode = 0 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [NBA Courtside 2] filtering = 0 depthmode = 0 fog = 1 buff_clear = 0 swapmode = 0 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [NEWTETRIS] fix_tex_coord = 1 increase_texrect_edge = 1 filtering = 0 depthmode = 0 fog = 0 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [NFL QBC '99] force_depth_compare = 1 wrap_big_tex = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [NFL Quarterback Club] wrap_big_tex = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [NINTAMAGAMEGALLERY64] force_microcheck = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 ; Nushi Zuri 64 [ǼÂÞØ64] force_microcheck = 1 wrap_big_tex = 0 filtering = 0 depthmode = 0 fog = 1 buff_clear = 0 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [OLYMPIC HOCKEY] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [OgreBattle64] fb_info_disable = 1 force_depth_compare = 1 filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [PAPER MARIO] hires_buf_clear = 0 optimize_texrect = 0 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 2 fb_smart = 1 fb_clear = 0 fb_read_alpha = 1 [Parlor PRO 64] force_microcheck = 1 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Perfect Dark] decrease_fillrect_edge = 1 optimize_texrect = 0 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 1 fb_read_alpha = 0 [PERFECT DARK] decrease_fillrect_edge = 1 optimize_texrect = 0 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 1 fb_read_alpha = 0 [Pilot Wings64] alt_tex_size = 0 filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [PUZZLE LEAGUE N64] PPL = 1 fb_hires_disable = 1 force_microcheck = 1 fix_tex_coord = 1 filtering = 2 depthmode = 1 fog = 0 buff_clear = 0 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 1 [PUZZLE LEAGUE] PPL = 1 fb_hires_disable = 1 force_microcheck = 1 fix_tex_coord = 1 filtering = 2 depthmode = 1 fog = 0 buff_clear = 0 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 1 [POKEMON SNAP] filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 1 fb_read_alpha = 0 [POKEMON STADIUM] optimize_texrect = 0 filtering = 0 depthmode = 1 fog = 1 buff_clear = 0 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 1 [POKEMON STADIUM 2] optimize_texrect = 0 filtering = 0 depthmode = 1 fog = 1 buff_clear = 0 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 1 [POKEMON STADIUM G&S] optimize_texrect = 0 filtering = 0 depthmode = 1 fog = 1 buff_clear = 0 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 1 [POLARISSNOCROSS] fix_tex_coord = 5 filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [quarterback_club_98] optimize_texrect = 0 hires_buf_clear = 0 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 0 fb_smart = 1 fb_clear = 0 fb_read_alpha = 1 [Quest 64] filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Racing Simulation 2] filtering = 0 depthmode = 0 fog = 1 buff_clear = 0 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [RAINBOW SIX] increase_texrect_edge = 1 filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Rally'99] filtering = 1 depthmode = 1 fog = 1 buff_clear = 0 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [RALLY CHALLENGE] filtering = 1 depthmode = 1 fog = 1 buff_clear = 0 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [Rayman 2] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 detect_cpu_write = 1 [READY 2 RUMBLE] fix_tex_coord = 64 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Ready to Rumble] fix_tex_coord = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Resident Evil II] detect_cpu_write = 1 fix_tex_coord = 128 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 2 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [RIDGE RACER 64] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [ROAD RASH 64] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Robopon64] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [RockMan Dash] increase_texrect_edge = 1 filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [RUGRATS IN PARIS] filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [RUSH 2049] force_texrect_zbuf = 1 filtering = 1 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [SCARS] filtering = 1 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [SD HIRYU STADIUM] force_microcheck = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Shadowman] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Silicon Valley] filtering = 1 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [South Park: Chef's L] fix_tex_coord = 4 filtering = 1 depthmode = 1 fog = 0 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [South Park Chef's Lu] fix_tex_coord = 4 filtering = 1 depthmode = 1 fog = 0 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [STARCRAFT 64] detect_cpu_write = 1 filtering = 2 depthmode = 1 fog = 0 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [STAR SOLDIER] force_microcheck = 1 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 0 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Supercross] filtering = 0 depthmode = 1 fog = 1 buff_clear = 0 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [SUPER MARIO 64] depth_bias = 32 lodmode = 1 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [SUPERMARIO64] depth_bias = 32 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 ;Susume! Taisen Puzzle Dama Toukon! Marumata Chou (J) [½½Ò!À²¾ÝÊß½ÞÙÀÞÏ] force_microcheck = 1 filtering = 0 depthmode = 1 fog = 0 buff_clear = 1 swapmode = 0 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 ;Tamagotchi World 64 (J) [ÐÝÅÃÞÀϺޯÁܰÙÄÞ] use_sts1_only = 1 filtering = 0 depthmode = 0 fog = 0 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Taz Express] filtering = 1 depthmode = 0 fog = 1 buff_clear = 0 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [TETRISPHERE] alt_tex_size = 1 use_sts1_only = 1 increase_texrect_edge = 1 filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [THE LEGEND OF ZELDA] depth_bias = 60 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 1 fb_read_alpha = 0 [THE MASK OF MUJURA] wrap_big_tex = 1 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 1 fb_read_alpha = 0 [THPS2] filtering = 1 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [THPS3] filtering = 1 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Tigger's Honey Hunt] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [TOM AND JERRY] depth_bias = 2 filtering = 1 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Tonic Trouble] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 detect_cpu_write = 1 [TONY HAWK PRO SKATER] filtering = 1 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [TONY HAWK SKATEBOARD] filtering = 1 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Top Gear Hyper Bike] fb_info_disable = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Top Gear Overdrive] fb_info_disable = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [TOP GEAR RALLY] depth_bias = 64 fillcolor_fix = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [TOP GEAR RALLY 2] filtering = 1 depthmode = 1 fog = 1 buff_clear = 0 swapmode = 2 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [TRIPLE PLAY 2000] wrap_big_tex = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [TSUMI TO BATSU] filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 1 fb_read_alpha = 0 [TSUWAMONO64] force_microcheck = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [TWINE] filtering = 1 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [TWISTED EDGE] filtering = 0 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 1 fb_read_alpha = 0 [Ultraman Battle JAPA] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Virtual Pool 64] filtering = 0 depthmode = 1 fog = 1 buff_clear = 0 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [V-RALLY] fix_tex_coord = 3 filtering = 1 depthmode = 0 fog = 1 buff_clear = 0 swapmode = 0 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [Waialae Country Club] wrap_big_tex = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 0 fb_read_alpha = 0 [Wipeout 64] filtering = 1 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [WONDER PROJECT J2] filtering = 0 depthmode = 0 fog = 1 buff_clear = 0 swapmode = 0 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [World Cup 98] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 0 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [WRESTLEMANIA 2000] filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [YAKOUTYUU2] ;force_microcheck = 1 filtering = 0 depthmode = 0 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [YOSHI STORY] fix_tex_coord = 32 filtering = 1 depthmode = 1 fog = 0 buff_clear = 1 swapmode = 1 fb_smart = 0 fb_clear = 0 fb_read_alpha = 0 [ZELDA MAJORA'S MASK] wrap_big_tex = 1 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 1 fb_read_alpha = 0 [ZELDA MASTER QUEST] depth_bias = 60 filtering = 1 depthmode = 1 fog = 1 buff_clear = 1 swapmode = 1 fb_smart = 1 fb_clear = 1 fb_read_alpha = 0 ;EOF mupen64plus-video-glide64-src-2.6.0/projects/000077500000000000000000000000001464507525600207155ustar00rootroot00000000000000mupen64plus-video-glide64-src-2.6.0/projects/msvc9/000077500000000000000000000000001464507525600217565ustar00rootroot00000000000000mupen64plus-video-glide64-src-2.6.0/projects/msvc9/mupen64plus-video-glide64.sln000066400000000000000000000016301464507525600272360ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 10.00 # Visual C++ Express 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupen64plus-video-glide64", "mupen64plus-video-glide64.vcproj", "{F3E6138A-C318-4020-B408-A9A24D8B3DE7}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {F3E6138A-C318-4020-B408-A9A24D8B3DE7}.Debug|Win32.ActiveCfg = Debug|Win32 {F3E6138A-C318-4020-B408-A9A24D8B3DE7}.Debug|Win32.Build.0 = Debug|Win32 {F3E6138A-C318-4020-B408-A9A24D8B3DE7}.Release|Win32.ActiveCfg = Release|Win32 {F3E6138A-C318-4020-B408-A9A24D8B3DE7}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal mupen64plus-video-glide64-src-2.6.0/projects/msvc9/mupen64plus-video-glide64.vcproj000066400000000000000000000232031464507525600277450ustar00rootroot00000000000000 mupen64plus-video-glide64-src-2.6.0/projects/unix/000077500000000000000000000000001464507525600217005ustar00rootroot00000000000000mupen64plus-video-glide64-src-2.6.0/projects/unix/Makefile000077500000000000000000000313261464507525600233500ustar00rootroot00000000000000#/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * # * Mupen64plus-video-glide64 - Makefile * # * Mupen64Plus homepage: https://mupen64plus.org/ * # * Copyright (C) 2010 Jon Ring * # * Copyright (C) 2007-2009 Richard Goedeken * # * Copyright (C) 2007-2008 DarkJeztr Tillin9 * # * * # * 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 2 of the License, or * # * (at your option) any later version. * # * * # * This program is distributed in the hope that it will be useful, * # * but WITHOUT ANY WARRANTY; without even the implied warranty of * # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * # * GNU General Public License for more details. * # * * # * You should have received a copy of the GNU General Public License * # * along with this program; if not, write to the * # * Free Software Foundation, Inc., * # * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ # Makefile for Glide64 plugin in Mupen64Plus # detect operating system UNAME ?= $(shell uname -s) OS := NONE ifeq ("$(UNAME)","Linux") OS = LINUX SO_EXTENSION = so SHARED = -shared endif ifeq ("$(UNAME)","linux") OS = LINUX SO_EXTENSION = so SHARED = -shared endif ifneq ("$(filter GNU hurd,$(UNAME))","") OS = LINUX SO_EXTENSION = so SHARED = -shared endif ifeq ("$(UNAME)","Darwin") OS = OSX SO_EXTENSION = dylib SHARED = -bundle endif ifeq ("$(UNAME)","FreeBSD") OS = FREEBSD SO_EXTENSION = so SHARED = -shared endif ifeq ("$(UNAME)","OpenBSD") OS = FREEBSD SO_EXTENSION = so SHARED = -shared endif ifneq ("$(filter GNU/kFreeBSD kfreebsd,$(UNAME))","") OS = LINUX SO_EXTENSION = so SHARED = -shared endif ifeq ("$(patsubst MINGW%,MINGW,$(UNAME))","MINGW") OS = MINGW SO_EXTENSION = dll SHARED = -shared PIC = 0 endif ifeq ("$(OS)","NONE") $(error OS type "$(UNAME)" not supported. Please file bug report at 'https://github.com/mupen64plus/mupen64plus-core/issues') endif # detect system architecture HOST_CPU ?= $(shell uname -m) CPU := NONE ifneq ("$(filter x86_64 amd64,$(HOST_CPU))","") CPU := X86 ifeq ("$(BITS)", "32") ARCH_DETECTED := 64BITS_32 PIC ?= 0 else ARCH_DETECTED := 64BITS PIC ?= 1 endif endif ifneq ("$(filter pentium i%86,$(HOST_CPU))","") CPU := X86 ARCH_DETECTED := 32BITS PIC ?= 0 endif ifneq ("$(filter ppc macppc socppc powerpc,$(HOST_CPU))","") CPU := PPC ARCH_DETECTED := 32BITS BIG_ENDIAN := 1 PIC ?= 1 NO_ASM := 1 $(warning Architecture "$(HOST_CPU)" not officially supported.') endif ifneq ("$(filter ppc64 powerpc64,$(HOST_CPU))","") CPU := PPC ARCH_DETECTED := 64BITS BIG_ENDIAN := 1 PIC ?= 1 NO_ASM := 1 $(warning Architecture "$(HOST_CPU)" not officially supported.') endif ifneq ("$(filter arm%,$(HOST_CPU))","") ifeq ("$(filter arm%b,$(HOST_CPU))","") CPU := ARM ARCH_DETECTED := 32BITS PIC ?= 1 NO_ASM := 1 $(warning Architecture "$(HOST_CPU)" not officially supported.') endif endif ifeq ("$(CPU)","NONE") $(error CPU type "$(HOST_CPU)" not supported. Please file bug report at 'https://github.com/mupen64plus/mupen64plus-core/issues') endif SRCDIR = ../../src OBJDIR = _obj$(POSTFIX) # base CFLAGS, LDLIBS, and LDFLAGS OPTFLAGS ?= -O3 -flto WARNFLAGS ?= -Wall CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -ffast-math -fno-strict-aliasing -fvisibility=hidden -I$(SRCDIR) -I$(SRCDIR)/wrapper -DGCC CXXFLAGS += -fvisibility-inlines-hidden LDFLAGS += $(SHARED) ifeq ($(CPU), X86) CFLAGS += -msse endif # Since we are building a shared library, we must compile with -fPIC on some architectures # On 32-bit x86 systems we do not want to use -fPIC because we don't have to and it has a big performance penalty on this arch ifeq ($(PIC), 1) CFLAGS += -fPIC else CFLAGS += -fno-PIC endif ifeq ($(BIG_ENDIAN), 1) CFLAGS += -DM64P_BIG_ENDIAN endif # tweak flags for 32-bit build on 64-bit system ifeq ($(ARCH_DETECTED), 64BITS_32) ifeq ($(OS), FREEBSD) $(error Do not use the BITS=32 option with FreeBSD, use -m32 and -m elf_i386) endif ifneq ($(OS), OSX) ifeq ($(OS), MINGW) LDFLAGS += -Wl,-m,i386pe else CFLAGS += -m32 LDFLAGS += -Wl,-m,elf_i386 endif endif endif ifeq ($(ARCH_DETECTED), 64BITS) ifeq ($(OS), MINGW) LDFLAGS += -Wl,-m,i386pep endif endif # set special flags per-system ifeq ($(OS), LINUX) # only export api symbols LDFLAGS += -Wl,-version-script,$(SRCDIR)/video_api_export.ver LDLIBS += -ldl endif ifeq ($(OS), OSX) # Select the proper SDK # Also, SDKs are stored in a different location since XCode 4.3 OSX_SDK ?= $(shell sw_vers -productVersion | cut -f1 -f2 -d .) OSX_XCODEMAJ = $(shell xcodebuild -version | grep '[0-9]*\.[0-9]*' | cut -f2 -d ' ' | cut -f1 -d .) OSX_XCODEMIN = $(shell xcodebuild -version | grep '[0-9]*\.[0-9]*' | cut -f2 -d ' ' | cut -f2 -d .) OSX_XCODEGE43 = $(shell echo "`expr $(OSX_XCODEMAJ) \>= 4``expr $(OSX_XCODEMIN) \>= 3`") ifeq ($(OSX_XCODEGE43), 11) OSX_SYSROOT := /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs else OSX_SYSROOT := /Developer/SDKs endif ifeq ($(CPU), X86) ifeq ($(ARCH_DETECTED), 64BITS) CFLAGS += -pipe -arch x86_64 -mmacosx-version-min=$(OSX_SDK) -isysroot $(OSX_SYSROOT)/MacOSX$(OSX_SDK).sdk LDFLAGS += -bundle LDLIBS += -ldl else CFLAGS += -pipe -mmmx -msse -fomit-frame-pointer -arch i686 -mmacosx-version-min=$(OSX_SDK) -isysroot $(OSX_SYSROOT)/MacOSX$(OSX_SDK).sdk LDFLAGS += -bundle LDLIBS += -ldl endif endif endif ifeq ($(OS), FREEBSD) LDLIBS += -lc endif # search for OpenGL libraries ifeq ($(OS), OSX) GL_LDLIBS = -framework OpenGL endif ifeq ($(OS), MINGW) GL_LDLIBS = -lopengl32 endif ifeq ($(origin GL_CFLAGS) $(origin GL_LDLIBS), undefined undefined) ifeq ($(origin PKG_CONFIG), undefined) PKG_CONFIG = $(CROSS_COMPILE)pkg-config ifeq ($(shell which $(PKG_CONFIG) 2>/dev/null),) $(error $(PKG_CONFIG) not found) endif endif ifeq ($(shell $(PKG_CONFIG) --modversion gl 2>/dev/null),) $(error No OpenGL development libraries found!) endif GL_CFLAGS += $(shell $(PKG_CONFIG) --cflags gl) GL_LDLIBS += $(shell $(PKG_CONFIG) --libs gl) endif CFLAGS += $(GL_CFLAGS) LDLIBS += $(GL_LDLIBS) # test for presence of SDL ifeq ($(origin SDL_CFLAGS) $(origin SDL_LDLIBS), undefined undefined) SDL_CONFIG = $(CROSS_COMPILE)sdl2-config ifeq ($(shell which $(SDL_CONFIG) 2>/dev/null),) SDL_CONFIG = $(CROSS_COMPILE)sdl-config ifeq ($(shell which $(SDL_CONFIG) 2>/dev/null),) $(error No SDL development libraries found!) else $(warning Using SDL 1.2 libraries) endif endif ifeq ($(OS),OSX) SDL_CFLAGS += $(shell $(SDL_CONFIG) --cflags) # sdl2-config on mac screws up when we're trying to build a library and not an executable # SDL 1.3 is supposed to fix that, if it's ever released SDL_LDLIBS += -L/usr/local/lib -lSDL -Wl,-framework,Cocoa else SDL_CFLAGS += $(shell $(SDL_CONFIG) --cflags) SDL_LDLIBS += $(shell $(SDL_CONFIG) --libs) endif endif CFLAGS += $(SDL_CFLAGS) LDLIBS += $(SDL_LDLIBS) # set mupen64plus core API header path ifneq ("$(APIDIR)","") CFLAGS += "-I$(APIDIR)" else TRYDIR = ../../../mupen64plus-core/src/api ifneq ("$(wildcard $(TRYDIR)/m64p_types.h)","") CFLAGS += -I$(TRYDIR) else TRYDIR = /usr/local/include/mupen64plus ifneq ("$(wildcard $(TRYDIR)/m64p_types.h)","") CFLAGS += -I$(TRYDIR) else TRYDIR = /usr/include/mupen64plus ifneq ("$(wildcard $(TRYDIR)/m64p_types.h)","") CFLAGS += -I$(TRYDIR) else $(error Mupen64Plus API header files not found! Use makefile parameter APIDIR to force a location.) endif endif endif endif # reduced compile output when running make without V=1 ifneq ($(findstring $(MAKEFLAGS),s),s) ifndef V Q_CC = @echo ' CC '$@; Q_CXX = @echo ' CXX '$@; Q_LD = @echo ' LD '$@; endif endif # set base program pointers and flags CC = $(CROSS_COMPILE)gcc CXX = $(CROSS_COMPILE)g++ RM ?= rm -f INSTALL ?= install MKDIR ?= mkdir -p COMPILE.c = $(Q_CC)$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c COMPILE.cc = $(Q_CXX)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c LINK.o = $(Q_LD)$(CXX) $(CXXFLAGS) $(LDFLAGS) $(TARGET_ARCH) # set special flags for given Makefile parameters ifeq ($(DEBUG),1) CFLAGS += -g INSTALL_STRIP_FLAG ?= else INSTALL_STRIP_FLAG ?= -s endif ifeq ($(NO_ASM), 1) CFLAGS += -DNO_ASM endif # set installation options ifeq ($(PREFIX),) PREFIX := /usr/local endif ifeq ($(SHAREDIR),) SHAREDIR := $(PREFIX)/share/mupen64plus endif ifeq ($(LIBDIR),) LIBDIR := $(PREFIX)/lib endif ifeq ($(PLUGINDIR),) PLUGINDIR := $(LIBDIR)/mupen64plus endif # list of source files to compile SOURCE = \ $(SRCDIR)/3dmath.cpp \ $(SRCDIR)/CRC.cpp \ $(SRCDIR)/Combine.cpp \ $(SRCDIR)/Config.cpp \ $(SRCDIR)/Debugger.cpp \ $(SRCDIR)/DepthBufferRender.cpp \ $(SRCDIR)/Ini.cpp \ $(SRCDIR)/Main.cpp \ $(SRCDIR)/TexBuffer.cpp \ $(SRCDIR)/TexCache.cpp \ $(SRCDIR)/Util.cpp \ $(SRCDIR)/rdp.cpp \ $(SRCDIR)/wrapper/2xsai.cpp \ $(SRCDIR)/wrapper/combiner.cpp \ $(SRCDIR)/wrapper/config.cpp \ $(SRCDIR)/wrapper/filter.cpp \ $(SRCDIR)/wrapper/geometry.cpp \ $(SRCDIR)/wrapper/hq2x.cpp \ $(SRCDIR)/wrapper/hq4x.cpp \ $(SRCDIR)/wrapper/main.cpp \ $(SRCDIR)/wrapper/textures.cpp ifeq ($(OS),MINGW) SOURCE += $(SRCDIR)/osal_dynamiclib_win32.c else SOURCE += $(SRCDIR)/osal_dynamiclib_unix.c endif # generate a list of object files build, make a temporary directory for them OBJECTS := $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.o, $(filter %.c, $(SOURCE))) OBJECTS += $(patsubst $(SRCDIR)/%.cpp, $(OBJDIR)/%.o, $(filter %.cpp, $(SOURCE))) OBJDIRS = $(dir $(OBJECTS)) $(shell $(MKDIR) $(OBJDIRS)) # build targets TARGET = mupen64plus-video-glide64$(POSTFIX).$(SO_EXTENSION) targets: @echo "Mupen64plus-video-glide64 N64 Graphics plugin makefile. " @echo " Targets:" @echo " all == Build Mupen64plus-video-glide64 plugin" @echo " clean == remove object files" @echo " rebuild == clean and re-build all" @echo " install == Install Mupen64Plus-video-glide64 plugin" @echo " uninstall == Uninstall Mupen64Plus-video-glide64 plugin" @echo " Options:" @echo " BITS=32 == build 32-bit binaries on 64-bit machine" @echo " NO_ASM=1 == build without inline assembly code (x86 MMX/SSE)" @echo " APIDIR=path == path to find Mupen64Plus Core headers" @echo " OPTFLAGS=flag == compiler optimization (default: -O3 -flto)" @echo " WARNFLAGS=flag == compiler warning levels (default: -Wall)" @echo " PIC=(1|0) == Force enable/disable of position independent code" @echo " POSTFIX=name == String added to the name of the the build (default: '')" @echo " Install Options:" @echo " PREFIX=path == install/uninstall prefix (default: /usr/local)" @echo " SHAREDIR=path == path to install shared data files (default: PREFIX/share/mupen64plus)" @echo " LIBDIR=path == library prefix (default: PREFIX/lib)" @echo " PLUGINDIR=path == path to install plugin libraries (default: LIBDIR/mupen64plus)" @echo " DESTDIR=path == path to prepend to all installation paths (only for packagers)" @echo " Debugging Options:" @echo " DEBUG=1 == add debugging symbols" @echo " V=1 == show verbose compiler output" all: $(TARGET) install: $(TARGET) $(INSTALL) -d "$(DESTDIR)$(PLUGINDIR)" $(INSTALL) -m 0644 $(INSTALL_STRIP_FLAG) $(TARGET) "$(DESTDIR)$(PLUGINDIR)" $(INSTALL) -d "$(DESTDIR)$(SHAREDIR)" $(INSTALL) -m 0644 "$(SRCDIR)/../data/Glide64.ini" "$(DESTDIR)$(SHAREDIR)" uninstall: $(RM) "$(DESTDIR)$(PLUGINDIR)/$(TARGET)" $(RM) "$(DESTDIR)$(SHAREDIR)/Glide64.ini" clean: $(RM) -r $(OBJDIR) $(TARGET) rebuild: clean all # build dependency files CFLAGS += -MD -MP -include $(OBJECTS:.o=.d) CXXFLAGS += $(CFLAGS) # standard build rules $(OBJDIR)/%.o: $(SRCDIR)/%.c $(COMPILE.c) -o $@ $< $(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(COMPILE.cc) -o $@ $< $(TARGET): $(OBJECTS) $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@ .PHONY: all clean install uninstall targets mupen64plus-video-glide64-src-2.6.0/src/000077500000000000000000000000001464507525600176535ustar00rootroot00000000000000mupen64plus-video-glide64-src-2.6.0/src/3dmath.cpp000066400000000000000000000261461464507525600215500ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * Copyright (c) 2008 Günther * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** #define M64P_PLUGIN_PROTOTYPES 1 #include "m64p_types.h" #include "m64p_plugin.h" #include "m64p_config.h" #include "m64p_vidext.h" #include "3dmath.h" #if !defined(NO_ASM) #include #endif void calc_light (VERTEX *v) { float light_intensity = 0.0f; float color[3] = {rdp.light[rdp.num_lights].r, rdp.light[rdp.num_lights].g, rdp.light[rdp.num_lights].b}; for (DWORD l=0; lvec); if (light_intensity > 0.0f) { color[0] += rdp.light[l].r * light_intensity; color[1] += rdp.light[l].g * light_intensity; color[2] += rdp.light[l].b * light_intensity; } } if (color[0] > 1.0f) color[0] = 1.0f; if (color[1] > 1.0f) color[1] = 1.0f; if (color[2] > 1.0f) color[2] = 1.0f; v->r = (BYTE)(color[0]*255.0f); v->g = (BYTE)(color[1]*255.0f); v->b = (BYTE)(color[2]*255.0f); } __inline void TransformVector (float *src, float *dst, float mat[4][4]) { dst[0] = mat[0][0]*src[0] + mat[1][0]*src[1] + mat[2][0]*src[2]; dst[1] = mat[0][1]*src[0] + mat[1][1]*src[1] + mat[2][1]*src[2]; dst[2] = mat[0][2]*src[0] + mat[1][2]*src[1] + mat[2][2]*src[2]; } //* void calc_linear (VERTEX *v) { float vec[3]; TransformVector (v->vec, vec, rdp.model); // TransformVector (v->vec, vec, rdp.combined); NormalizeVector (vec); float x, y; if (!rdp.use_lookat) { x = vec[0]; y = vec[1]; } else { x = DotProduct (rdp.lookat[0], vec); y = DotProduct (rdp.lookat[1], vec); } if (rdp.cur_cache[0]) { // scale >> 6 is size to map to v->ou = (acosf(x)/3.1415f) * (rdp.tiles[rdp.cur_tile].org_s_scale >> 6); v->ov = (acosf(y)/3.1415f) * (rdp.tiles[rdp.cur_tile].org_t_scale >> 6); } } //*/ /* void calc_linear (VERTEX *v) { float vec[3]; TransformVector (v->vec, vec, rdp.combined); NormalizeVector (vec); if (rdp.cur_cache[0]) { // scale >> 6 is size to map to v->ou = (acosf(vec[0])/3.1415f) * (rdp.tiles[rdp.cur_tile].org_s_scale >> 6); v->ov = (acosf(vec[1])/3.1415f) * (rdp.tiles[rdp.cur_tile].org_t_scale >> 6); } } //*/ void calc_sphere (VERTEX *v) { //RDP("calc_sphere\n"); float vec[3]; int s_scale, t_scale; if (settings.chopper) { s_scale = std::min(rdp.tiles[rdp.cur_tile].org_s_scale >> 6, static_cast(rdp.tiles[rdp.cur_tile].lr_s)); t_scale = std::min(rdp.tiles[rdp.cur_tile].org_t_scale >> 6, static_cast(rdp.tiles[rdp.cur_tile].lr_t)); } else { s_scale = rdp.tiles[rdp.cur_tile].org_s_scale >> 6; t_scale = rdp.tiles[rdp.cur_tile].org_t_scale >> 6; } TransformVector (v->vec, vec, rdp.model); // TransformVector (v->vec, vec, rdp.combined); NormalizeVector (vec); float x = DotProduct (rdp.lookat[0], vec); float y = DotProduct (rdp.lookat[1], vec); v->ou = (x * 0.5f + 0.5f) * s_scale; v->ov = (y * 0.5f + 0.5f) * t_scale; } void __stdcall MulMatricesNOSSE(float m1[4][4],float m2[4][4],float r[4][4]) { /*for (int i=0; i<4; i++) { for (int j=0; j<4; j++) { r[i][j] = m1[i][0] * m2[0][j] + m1[i][1] * m2[1][j] + m1[i][2] * m2[2][j] + m1[i][3] * m2[3][j]; } }*/ r[0][0] = m1[0][0]*m2[0][0] + m1[0][1]*m2[1][0] + m1[0][2]*m2[2][0] + m1[0][3]*m2[3][0]; r[0][1] = m1[0][0]*m2[0][1] + m1[0][1]*m2[1][1] + m1[0][2]*m2[2][1] + m1[0][3]*m2[3][1]; r[0][2] = m1[0][0]*m2[0][2] + m1[0][1]*m2[1][2] + m1[0][2]*m2[2][2] + m1[0][3]*m2[3][2]; r[0][3] = m1[0][0]*m2[0][3] + m1[0][1]*m2[1][3] + m1[0][2]*m2[2][3] + m1[0][3]*m2[3][3]; r[1][0] = m1[1][0]*m2[0][0] + m1[1][1]*m2[1][0] + m1[1][2]*m2[2][0] + m1[1][3]*m2[3][0]; r[1][1] = m1[1][0]*m2[0][1] + m1[1][1]*m2[1][1] + m1[1][2]*m2[2][1] + m1[1][3]*m2[3][1]; r[1][2] = m1[1][0]*m2[0][2] + m1[1][1]*m2[1][2] + m1[1][2]*m2[2][2] + m1[1][3]*m2[3][2]; r[1][3] = m1[1][0]*m2[0][3] + m1[1][1]*m2[1][3] + m1[1][2]*m2[2][3] + m1[1][3]*m2[3][3]; r[2][0] = m1[2][0]*m2[0][0] + m1[2][1]*m2[1][0] + m1[2][2]*m2[2][0] + m1[2][3]*m2[3][0]; r[2][1] = m1[2][0]*m2[0][1] + m1[2][1]*m2[1][1] + m1[2][2]*m2[2][1] + m1[2][3]*m2[3][1]; r[2][2] = m1[2][0]*m2[0][2] + m1[2][1]*m2[1][2] + m1[2][2]*m2[2][2] + m1[2][3]*m2[3][2]; r[2][3] = m1[2][0]*m2[0][3] + m1[2][1]*m2[1][3] + m1[2][2]*m2[2][3] + m1[2][3]*m2[3][3]; r[3][0] = m1[3][0]*m2[0][0] + m1[3][1]*m2[1][0] + m1[3][2]*m2[2][0] + m1[3][3]*m2[3][0]; r[3][1] = m1[3][0]*m2[0][1] + m1[3][1]*m2[1][1] + m1[3][2]*m2[2][1] + m1[3][3]*m2[3][1]; r[3][2] = m1[3][0]*m2[0][2] + m1[3][1]*m2[1][2] + m1[3][2]*m2[2][2] + m1[3][3]*m2[3][2]; r[3][3] = m1[3][0]*m2[0][3] + m1[3][1]*m2[1][3] + m1[3][2]*m2[2][3] + m1[3][3]*m2[3][3]; } void __stdcall MulMatricesSSE(float m1[4][4],float m2[4][4],float r[4][4]) { #if defined(__GNUC__) && !defined(NO_ASM) /* [row][col]*/ typedef float v4sf __attribute__ ((vector_size (16))); v4sf row0 = _mm_loadu_ps(m2[0]); v4sf row1 = _mm_loadu_ps(m2[1]); v4sf row2 = _mm_loadu_ps(m2[2]); v4sf row3 = _mm_loadu_ps(m2[3]); for (int i = 0; i < 4; ++i) { v4sf leftrow = _mm_loadu_ps(m1[i]); // Fill tmp with four copies of leftrow[0] v4sf tmp = leftrow; tmp = _mm_shuffle_ps (tmp, tmp, 0); // Calculate the four first summands v4sf destrow = tmp * row0; // Fill tmp with four copies of leftrow[1] tmp = leftrow; tmp = _mm_shuffle_ps (tmp, tmp, 1 + (1 << 2) + (1 << 4) + (1 << 6)); destrow += tmp * row1; // Fill tmp with four copies of leftrow[2] tmp = leftrow; tmp = _mm_shuffle_ps (tmp, tmp, 2 + (2 << 2) + (2 << 4) + (2 << 6)); destrow += tmp * row2; // Fill tmp with four copies of leftrow[3] tmp = leftrow; tmp = _mm_shuffle_ps (tmp, tmp, 3 + (3 << 2) + (3 << 4) + (3 << 6)); destrow += tmp * row3; _mm_storeu_ps(r[i], destrow); } #elif !defined(NO_ASM) __asm { mov eax, dword ptr [r] mov ecx, dword ptr [m1] mov edx, dword ptr [m2] movaps xmm0,[edx] movaps xmm1,[edx+16] movaps xmm2,[edx+32] movaps xmm3,[edx+48] // r[0][0],r[0][1],r[0][2],r[0][3] movaps xmm4,xmmword ptr[ecx] movaps xmm5,xmm4 movaps xmm6,xmm4 movaps xmm7,xmm4 shufps xmm4,xmm4,00000000b shufps xmm5,xmm5,01010101b shufps xmm6,xmm6,10101010b shufps xmm7,xmm7,11111111b mulps xmm4,xmm0 mulps xmm5,xmm1 mulps xmm6,xmm2 mulps xmm7,xmm3 addps xmm4,xmm5 addps xmm4,xmm6 addps xmm4,xmm7 movaps xmmword ptr[eax],xmm4 // r[1][0],r[1][1],r[1][2],r[1][3] movaps xmm4,xmmword ptr[ecx+16] movaps xmm5,xmm4 movaps xmm6,xmm4 movaps xmm7,xmm4 shufps xmm4,xmm4,00000000b shufps xmm5,xmm5,01010101b shufps xmm6,xmm6,10101010b shufps xmm7,xmm7,11111111b mulps xmm4,xmm0 mulps xmm5,xmm1 mulps xmm6,xmm2 mulps xmm7,xmm3 addps xmm4,xmm5 addps xmm4,xmm6 addps xmm4,xmm7 movaps xmmword ptr[eax+16],xmm4 // r[2][0],r[2][1],r[2][2],r[2][3] movaps xmm4,xmmword ptr[ecx+32] movaps xmm5,xmm4 movaps xmm6,xmm4 movaps xmm7,xmm4 shufps xmm4,xmm4,00000000b shufps xmm5,xmm5,01010101b shufps xmm6,xmm6,10101010b shufps xmm7,xmm7,11111111b mulps xmm4,xmm0 mulps xmm5,xmm1 mulps xmm6,xmm2 mulps xmm7,xmm3 addps xmm4,xmm5 addps xmm4,xmm6 addps xmm4,xmm7 movaps xmmword ptr[eax+32],xmm4 // r[3][0],r[3][1],r[3][2],r[3][3] movaps xmm4,xmmword ptr[ecx+48] movaps xmm5,xmm4 movaps xmm6,xmm4 movaps xmm7,xmm4 shufps xmm4,xmm4,00000000b shufps xmm5,xmm5,01010101b shufps xmm6,xmm6,10101010b shufps xmm7,xmm7,11111111b mulps xmm4,xmm0 mulps xmm5,xmm1 mulps xmm6,xmm2 mulps xmm7,xmm3 addps xmm4,xmm5 addps xmm4,xmm6 addps xmm4,xmm7 movaps xmmword ptr[eax+48],xmm4 } #endif // _WIN32 } MULMATRIX MulMatrices = MulMatricesNOSSE; void math_init() { BOOL IsSSE = FALSE; #if defined(__GNUC__) && !defined(NO_ASM) int edx, eax; #if defined(__x86_64__) asm volatile(" cpuid; " : "=a"(eax), "=d"(edx) : "0"(1) : "rbx", "rcx" ); #else asm volatile(" push %%ebx; " " push %%ecx; " " cpuid; " " pop %%ecx; " " pop %%ebx; " : "=a"(eax), "=d"(edx) : "0"(1) : ); #endif // Check for SSE if (edx & (1 << 25)) IsSSE = TRUE; #elif !defined(NO_ASM) DWORD dwEdx; __try { __asm { mov eax,1 cpuid mov dwEdx,edx } } __except(EXCEPTION_EXECUTE_HANDLER) { return; } if (dwEdx & (1<<25)) { if (dwEdx & (1<<24)) { __try { __asm xorps xmm0, xmm0 IsSSE = TRUE; } __except(EXCEPTION_EXECUTE_HANDLER) { return; } } } #endif // _WIN32 if (IsSSE) { MulMatrices = MulMatricesSSE; WriteLog(M64MSG_INFO, "SSE detected.\n"); } } mupen64plus-video-glide64-src-2.6.0/src/3dmath.h000066400000000000000000000050441464507525600212070ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** #include #include "rdp.h" #include "m64p.h" __inline float DotProduct(float *v1, float *v2) { float result; result = v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; return(result); } __inline void NormalizeVector(float *v) { float len; len = sqrtf(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); if (len > 0.0f) { v[0] /= len; v[1] /= len; v[2] /= len; } } __inline void InverseTransformVector (float *src, float *dst, float mat[4][4]) { dst[0] = mat[0][0]*src[0] + mat[0][1]*src[1] + mat[0][2]*src[2]; dst[1] = mat[1][0]*src[0] + mat[1][1]*src[1] + mat[1][2]*src[2]; dst[2] = mat[2][0]*src[0] + mat[2][1]*src[1] + mat[2][2]*src[2]; } void calc_light (VERTEX *v); void calc_linear (VERTEX *v); void calc_sphere (VERTEX *v); void math_init(); typedef void (__stdcall *MULMATRIX)(float m1[4][4],float m2[4][4],float r[4][4]); extern MULMATRIX MulMatrices; mupen64plus-video-glide64-src-2.6.0/src/AUTHORS000066400000000000000000000000651464507525600207240ustar00rootroot00000000000000Dave2001 Gonetz Gugaman Hacktarux Josh Ziggy Günthermupen64plus-video-glide64-src-2.6.0/src/CRC.cpp000066400000000000000000000047131464507525600207730ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** // // CRC32 calculation functions // // Created by Gonetz, 2004 // //**************************************************************** #include "CRC.h" #define CRC32_POLYNOMIAL 0x04C11DB7 unsigned int CRCTable[ 256 ]; unsigned int Reflect( unsigned long ref, char ch ) { unsigned int value = 0; // Swap bit 0 for bit 7 // bit 1 for bit 6, etc. for (char i = 1; i < (ch + 1); i++) { if(ref & 1) value |= 1 << (ch - i); ref >>= 1; } return value; } void CRC_BuildTable() { unsigned int crc; for (unsigned i = 0; i <= 255; i++) { crc = Reflect( i, 8 ) << 24; for (unsigned j = 0; j < 8; j++) crc = (crc << 1) ^ (crc & (1 << 31) ? CRC32_POLYNOMIAL : 0); CRCTable[i] = Reflect( crc, 32 ); } } mupen64plus-video-glide64-src-2.6.0/src/CRC.h000066400000000000000000000054751464507525600204460ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * Copyright (c) 2008 Günther * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** // // CRC32 calculation functions // // Created by Gonetz, 2004 // //**************************************************************** #if !defined(WIN32) && defined(GCC) #define Crc32 _Crc32 #define CRCTable _CRCTable #endif extern unsigned int CRCTable[ 256 ]; void CRC_BuildTable(); inline unsigned int CRC_Calculate( unsigned int crc, const void *buffer, unsigned int count ) { #if !defined(__GNUC__) && !defined(NO_ASM) unsigned int Crc32=crc; __asm { mov esi, buffer mov edx, count add edx, esi mov ecx, crc loop1: mov bl, byte ptr [esi] movzx eax, cl inc esi xor al, bl shr ecx, 8 mov ebx, [CRCTable+eax*4] xor ecx, ebx cmp edx, esi jne loop1 xor Crc32, ecx } return Crc32; #else unsigned int result = crc; for (const char * p = (const char*)buffer; p != (const char*)buffer + count; ++p) { unsigned char al = result; al ^= *p; result >>= 8; result ^= CRCTable[al]; } result ^= crc; return result; #endif } mupen64plus-video-glide64-src-2.6.0/src/Changes.txt000066400000000000000000001704461464507525600220000ustar00rootroot00000000000000 2/09/02 Version 0.04 Released Sunday, 2/10/02, 4:35 PM * Completely redid combine modes to allow for multiple equation types * The new combining method seems to have made enemies in Star Fox flash when you hit them like they are supposed to. * Also in the new combine mode system, unimplemented combiners should now show as bright red. Monday, 2/11/02, -:-- PM * Added many new combine modes Tuesday, 2/12/02, 5:29 PM * Fixed it so that it will now use the tile descriptor given in uc0:texture instead of assuming 0. Wednesday, 2/13/02, 6:53 PM * Added 1964 support. The problem was that 1964 reloads the plugin when it switches to fullscreen. Also, I wasn't logging DllMain, which was why I didn't notice the error. Now it switches to fullscreen at the next dlist, meaning no reloading the dll since we last called grGlideInit. Monday, 2/18/02, 1:26 PM * Added triangle caching, now things should run a lot faster since it only has to do matrix transformations once per vertex instead of every time the vertex is used. * Also, vertex transformations are now done during the vertex instruction, which fixed the problem with Banjo's seperated body parts. The vertices were using two different matrices and doing the transformations at draw time was only using the last matrix that was set. 2:45 PM * Now it should only calculate lighting once per vertex also, but I didn't see any speed increase... maybe something went wrong? Tuesday, 2/19/02, 8:59 PM * Started on uCode 2 (5 in the compat. list), F3DEX 2.XX. This is the uCode that Zelda64 uses. So far I have written the instruction table, and implemented uc2:moveword for segment offset. I'm really amazed that it now runs without ANY undefined instructions. 11:13 PM * Gugaman has fixed the lighting speed problem! Now it goes a lot faster. The vertex normals were being normalized in a loop with all the lights, and also a lot of the variables are now declared as 'register'. We also took out an unused vector. 11:56 PM * We optimized it again! This time I moved the normalizing code totally out of the light calculation. I am also now calculating lighting before copying, which now allows it to only calculate once per frame. Thursday, 2/21/02, 8:51 PM * Yesterday I got my Zelda wireframes working. Today I added textures, and am currently researching how T1 works. * Sometimes triangles were empty (all three points were the same), which would mess up the click detection code. Now it's a lot easier to navigate the triangles, and it should speed up a little more too (barely). Saturday, 2/23/02, 5:14 PM * Added texture swapping support, things look better now in Super Smash Brothers and Pilotwings. 8:51 PM * I found out what's going on with most of my texture problems. I've severely underestimated the use of mask. Not only can it be used for mirroring, but it can be used to determine size as well. It's time to do the major change I've been avoiding all this time... triangle and texture splitting. * Also, by using mask, it fixes all those very odd settilesize problems, like the Quest64 fireball spell. 11:52 PM * I've partially implemented texture splitting, it seems to load the two textures correctly. Sunday, 2/24/02, 1:49 AM * Fixed the missing triangles problem with Zelda and Super Smash Brothers, the uc2:tri1 command uses cmd0 for it's vertices instead of cmd1. 8:35 AM * Ok, when I turned on my computer this morning, it deleted my Util.cpp and I lost my texture splitting. It was already messed up, so I would just have to redo it anyway. I'm going to do triangle splitting first now, texture splitting isn't as important. 9:15 AM * Gonetz (Gonetz@ngs.ru) submitted a speedup idea, to pre-multiply matrices so that they do not have to be calculated with each vertex. I had a little trouble implementing it because I was trying to do model*proj instead of proj*model or vice versa for both. Monday, 2/25/02, 6:46 PM * I've totally redone the combiner * Texture wraps and mirrors with clamp are now used in texture loading, super smash brothers almost works correctly now * Texture CRC checks now should be correct Saturday, 3/02/02, 2:58 PM * Wheeee!!! I've speeded up compiling time by A LOT by using a precompiled header. * I've figured out how to fake the LOD into letting me do texture interpolation. * I've implemented many zelda combine modes. Tuesday, 3/05/02, 5:35 PM * YAY!!! Icepir8 has shown me how to do lighting correctly. I was using an unsigned byte when the light direction requires it to be signed. Someday in-between Tuesday and Friday, 3/??/02, whatever PM * I've implemented the Zelda fire combine mode Friday, 3/08/02, 12:04 AM * Gonetz sent me the file to implement Waverace's ucode. I tested it and it works. He also gave several suggestions for improving the combiner, which I will do in the next few days. Saturday, 3/09/02 9:00 PM * I've done yet another combiner, this time it doesn't have a gigantic switch statement. This combiner is based on ideas by Gonetz, and combined with some of my own. * Icepir8 just told me that if I transformed my normals on vertex load instead of transforming light vectors, I could save a lot of calculations. 10:58 PM * Okay, I'm done with the new lighting system. I don't see any speedup because something else is seriously slowing my plugin down. Sunday, 3/10/02 3:18 PM * Gonetz has told me how to fix a matrix problem in Waverace. Now there is no large dolphin. The problem is that I need to clear the matrix stack count every frame. I had this code before, but took it out for some reason. Monday, 3/11/02 8:33 PM * Implemented a "GFX plugin has caused an exception" dialog, that makes it go back from fullscreen and prevents it from crashing on exceptions. (try/catch in ProcessDList) * Figured out how force blending and other such works, not implemented yet though. 10:12 PM * Implemented some force blending, for things like mario kart player select. Tuesday, 3/12/02 9:48 PM * Fixed kokiri faces bug, I had read somewhere that palettes had to be aligned to 8-bytes, but this was obviously not true. The palette in zelda was using an ending value of 'C'. Wednesday, 3/13/02 6:17 PM * Defined the real values for combine modes rather than a shortened, one-for-all-slots version. Now I don't get odd things like "use prim_lodfrac for starfox menu item alpha", instead it is "1". All of the combine descriptions need to be converted though :( 8:21 PM * I redid lighting again, this time a mixture of both methods. I first translate the light vector by the inverse model matrix, and then use that in ucx:vertex to calculate lighting. This way I do not have to transform every single normal, rather, one light vector per group. Thursday, 3/14/02 6:55 PM * Got waverace texrects to show by setting the default alpha for shade in fillrects to 0. Saturday, 3/16/02 2:54 PM * Fixed clamping problem, was using tiles 0 and 1 always, when it should've been rdp.cur_tile and rdp.cur_tile+1. Now Banjo-Kazooie wraps everything correctly. * Added many many more combine modes for the new combiner over the past few days. 5:29 PM * Revised the debugger, now it can run in any resolution. Also redid the texture viewer so that it's simpler, and supports TMU1. 9:12 PM * Added the two .3df files to the program as resources, they had to be as "RCDATA", even though nothing specified that. No more extra .3df files are required. The font texture is now loaded from a 1-bit alpha texture, using some assembly code, and the cursor texture is the same. I also added a colored text option, so that the combiners and headers of the debugger are color-coded. Sunday, 3/17/02 10:45 PM * Fixed translucency problems finally. Now Link shows up fully opaque and nothing else messes up. ALPHA_CVG_SEL does in fact mean full alpha, but I wasn't handling rdp:setothermode so I was getting it where I shouldn't have been. * Fixed flickering problems in games such as Snowboard Kids and Paper Mario. The problem was that some games use more than one DList per frame, and I was flipping on every DList. Now it flips on UpdateScreen instead of on the DList. Tuesday, 3/19/02 4:50 PM * Made it so that outputting text without scaling is possible, FPS counter doesn't scale in case of resolution too low to see. * Added check box for FPS counter 9:45 PM * Added a bunch of new options to the dialog but all they do now is save to the INI, nothing is implemented yet for when they are set. Friday, 3/22/02 3:48 PM * Bleh, I'm sick today, 102.8 temperature, however, the computer isn't causing a headache, so I will continue working. * Implemented a bunch of the options yesterday, such as logging, etc. (no more #defines needed) * Upgraded computer to Win2k SP2. Mario's face screen goes a little faster now, but not much else changed. * Took out the now useless VERTEX_N structure since lighting is now calculated in UC:VERTEX. * Gonetz sent the software culling I asked for. I'm going to try and improve this by doing everything I can in UC:VERTEX, and also a flag in vertex for clip_z, to determine whether we can use a precalculated x/z and y/z value. 6:21 PM * Pre-calculated x/z, y/z in UC:VERTEX, use if not z-clipping. The real reason I did this is for software culling, so they don't have to be re-calculated. * Made it so that vertices will only calculate u/v coordinates once, or not again until the texture attributes are updated. z-clipping doesn't matter for this, u/v were calculated before the clipping in the first place. * Changed the type passed into DrawTri to VERTEX** to make it work with clip_tri. (modified from Gonetz's original to allow for u/v calculate once (previous comment)). 8:12 PM * Now screen coordinates, 1/z, u/z, and v/z are precalculated also. (unless z-clipping) * Actually added software culling, I think it sped the plugin up by a lot. Saturday, 3/23/02 8:54 PM * Found that the reason for the Zelda magic bar and Aerogauge fire messing up is that yes, textures can only be wrapped on powers of two, but they can be clamped anywhere, whatever is specified by lr-ul. I'm going to redo a lot of my texture code soon, and I will incorporate this fix (manually clamp to the full power of two texture) Monday, 3/25/02 12:53 PM * STILL sick, 100.9 temperature today. * Fixed a bug with resolution switches, it wasn't setting the resolution width and height, only video mode. Also, when you switch resolutions it will turn off the debugger. Tuesday, 3/26/02 5:21 PM * After trying to implement frustrum clipping, I have finally decided that my method of 2d clipping is better. I am however using the inequalities x<-z, x>z, y<-z, and y>z in several places though. * I've implemented culldl for Zelda, not sure of any speedup since I didn't really look at the speed before I changed it. Wednesday, 3/27/02 10:30 AM * Fixed uc2:geom_mode so that now both clr and set are shifted before they are used, instead of shifting the final result. Now the culling in zelda works properly. 3:07 PM * Fixed culldl in ucode2, was using ||s instead of &&s, &&s didn't work b/c it needs to check the volume between the vertices instead of the vertices themselves. Now it checks that each condition is met at least once to decide whether to draw or not. * Fixed a bug where it would log the alpha combiner also if the color combiner was unimplemented. Thursday, 3/28/02 7:16 PM * Unimplemented combiner text descriptions now show up as red, the alpha as a brighter red so you can easily tell them apart. Friday, 3/29/02 4:29 PM * Implemented many many many more combiners. * Implemented branch_z for ucode 2 so that Death Mountain Trail and the well work. * Implemented prim depth source and alpha compare for texrects, made lens of truth work backwards. Saturday, 3/30/02 4:27 PM * Added more descriptive update() function, now outputs everything it's trying to do, also TexCache outputs things to debug texture loading crashes. * Converted some things such as texture loads to BMASK/WMASK/DMASK format (different masking method, fixed one illegal operation in zelda subscreen). * Manually clamped all textures, which fixed the zelda magic bar, and several other texture border issues, like the subscreen. Tuesday, 4/02/02 8:54 PM * Gonetz sent many new combiners * Implemented a lookup for the first byte of combiners Wednesday, 4/03/02 5:06 PM * Gonetz sent new combiners again * Oops, realized that I didn't do as I had planned with the alpha combine lookup, I meant to use 0x0FF00000 instead of 0xFF000000 since the first 4 bits are not used. It is fixed now. * Now it always uses Glide64.ini no matter what the name of the plugin (dll file) is, so you can have multiple versions of the plugin using the same ini. Thursday, 4/04/02 11:25 PM * Made shade values full for texrects (for dual heroes) * !!! Added CMB_MULT and CMB_SET stuff to texrects! A long time ago I thought texrects would only have textures, and then later forgot to put these in. Now combiners should work MUCH more often on texrects. * Changed from full alpha and full color for texrects to just full alpha, and black color (for the zelda menu). 12:35 AM * Changed my mind again about the texrect color thing, now all four values are full (dual heroes needed this) Friday, 4/05/02 6:15 PM * Made the plugin faster by not drawing fillrects that had an alpha value lower than 5 (usually one fullscreen rect per frame) * Made it faster again by not setting the uv_calculated for every possible vertex on texture load, now it acts more like a CRC * Lemmy has led me to the zelda fixed view problem. There was an unimplemented instruction, background as he calls it (0x0A), which draws a fullscreen 320x240x16 rectangle. It is not yet implemented yet though. 10:55 PM * FINALLY, after a million hours of working on the temple of time problem, GokuSS4 tells me that Lemmy can help fix my problem. Lemmy said that there is a command that draws a 320x240x16 texture on the screen. Knowing the command was not enough though, using the address it gave, I got static. Icepir8 and I eventually figured out that the address actually pointed to a structure whose fourth element was a pointer to the actual texture. The temple of time, and all other fixed view problems, now work. Sunday, 4/07/02 10:21 PM * Implemented a bazillion new combiners from Ogy's list. * Fixed mario texrects, on cycle_mode=copy, it doesn't use combine, but rather texture. 12:22 AM * Clipped texrects properly so that they do not stretch as they go off the screen. They are also clipped to scissor instead of screen now also. Monday, 4/08/02 11:40 PM * Fixed a problem with the scissor rect being too big for the screen. Tuesday, 4/09/02 6:17 PM (.04944) * Fixed the zelda orange texrect problem, Gonetz implemented a combiner for Kirby 64 that was actually already implemented. I commented his duplicate, and it worked again. 12:03 AM * Switched the order of alpha compare/CVG_X_ALPHA * Made it so that XLU surfaces do not update the z-buffer Thursday, 4/11/02 6:34 PM (0.1 Beta #1 -> Ogy, Jeremy, Quvack, Slougi) (0.1 Beta #2 -> Ogy, Jeremy, Gugaman) (0.1 Beta #2+ -> Jeremy, Gonetz) (0.1 Beta #3 -> Gonetz, Ogy, Scorpiove) * Gonetz sent new combiners. * Gonetz has finally agreed that it is time to release. I'll send to Ogy after just a few more fixes. * Disabled most recent thing added, xlu surfaces, just in case because of release. * Changed unimplemented combiners to show T0 instead of the last combiner used, since most objects use T0 at least somewhere. * Found bug in texrect clipping, the fast on/off cut return was wrong. 10:24 PM * Fixed texture swapping in certain games like Super Smash Bros by swapping the x value instead of the address. * Made it so that unimp.txt is not created unless unimp logging is enabled. 11:44 PM * Spherical mapping fixed, works now in every instance I've seen. * Option added for 'Buffer clear on every frame' Friday, 4/12/02 4:44 PM * Bug fixed when Glide64 was not as Glide64.dll, I had typed in "Glide64.dll" instead of getting the full path. (0.1 Beta #4 -> Ogy, Falcon4Ever, Jeremy, Gugaman, McLeod, Scorpiove) Sunday, 4/14/02 2:03 PM * Switched from ac_one on unimplemented to ac_t0, b/c it causes less problems with translucent things. 4:00 PM * Fixed a Ridge Racer crash that had to do with texrects being off the screen. The reason my previous offscreen clipping code didn't work for the y-axis was because I needed to flip the coordinates, not the borders, to make ul_y < lr_y. * Fixed a problem in fillrect. If fillrect used fill color, it would check if it had less than 5 alpha to determine whether to draw or not. The problem is... fillrect only has 1 bit of alpha and I didn't think about that when I wrote the compare. Now some black rectangles that didn't show up before now will. The only problem is that this may slow the plugin b/c of a fullscreen clear that now must occur. 9:37 PM (0.1 Beta #5 -> Gugaman, Ogy, Scorpiove, Quvack) 2:11 PM (0.1 Beta #6 -> Gonetz, Ogy, Scorpiove, Quvack, IceLord) * Added ToolTips for all configuration options. Monday, 4/15/02 7:31 PM * Finished up ToolTip text * Disabled FPS counter because of bugs it has 8:11 PM * Finished wireframes for texrects and fillrects. * Added an option to select the colors to use for wireframes. Wednesday, 4/17/02 7:49 PM * Changed address mask in uc0:displaylist to 0xFFFFFF instead of 0x3FFFFF. * & also in ProcessDList (Zelda: MM runs now, complete gfx errors). * Put an &BMASK at the end of segoffset. * Glanced through ucode02.h replacing incorrect masks. * Changed a 0x3FFFFF in TexCache Thursday, 4/18/02 9:49 PM * Scissor added to update * THE INFAMOUS RESOLUTION PROBLEM IS FIXED!!! After a while of looking at things, the resolution problem that was present in many games is now fixed. I noticed two variables of name VI_X_SCALE and VI_Y_SCALE. These contained values typically 0x200 and 0x400 normally, but when something was stretched in the y-axis, VI_Y_SCALE = 0x800, double the original. By using division between the current and original, you get the correct scaling. Friday, 4/19/02 5:32 PM * Made it so that tooltips can be easily disabled (for those without the platform sdk) by commenting the line in Gfx #1.3.h that says "#define USE_TOOLTIPS" 11:20 PM * CMB_MULT and CMB_ADD/SUB are now completely unrelated in values, and it performs the add/sub operation first. ** 0.1 released ** Tuesday, 4/23/02 10:43 PM * Made it so that the uc2:BG command doesn't use the z-buffer. * Added uc2:BG to the log. * Made uc2:BG use alpha (for alpha compare) * Going to start on a HUGE texture loading change... allowing modification of textures while loading and also faster loads, possibly using some assembly. Sunday, 5/05/02 6:01 PM * Figuring out many things about texture sizes, assembly going well so far * Improved the debugger, allowing a NULL triangle selection. Also, as when you press space bar to go to the texture of the selected triangle, you can now press the left control key to go to the last on-screen triangle that used the selected texture. This is useful to find what a messed-up texture is supposed to be of, since you can see where it was on the screen. Also, if the texture was not used this frame, it selects NULL, which doesn't display any triangle information. 6:27 PM * Made it so that interpolation of 0.0 or 1.0 ONLY uses the needed texture, because the other one may not have had its tile descriptor even set, loading a useless noise texture. (INTER macros in Combine.cpp) 9:25 PM * 16-bit RGBA seems to be as far as it can go... starting LoadTile emulation now. Saturday, 5/18/02 1:22 PM * Lots of school recently, no time to work * Fully re-implemented both LoadBlock and LoadTile in order to account for non-aligned textures * Implemented a new texture format: 4-bit CI. This should be the hardest of all. * Made it so that tri_n numbers should be correct even if not in fullscreen mode 4:22 PM * Implemented 8-bit CI by slightly modifying the 4-bit CI code. * Seperated the load functions into different files based on size since they are quite large. 6:18 PM * Oops, fixed a problem with building on normal 'debug' and 'release' modes, where it wasn't including the .obj file. 6:55 PM * Finished 4-bit I textures. 11:27 PM * *Gugaman* (accidentally typed Gonetz the first time) has helped me implement both 4-bit CI and 16-bit IA textures. Sunday, 5/19/02 8:46 AM * Oops, from the simplified version of Gugaman's 16-bit IA, I forgot to take out a ror 16. 5:50 PM * Remade the whole texture loading routine... The whole thing is completely different. Combine and TexCache are now somewhat merged to allow for use of the maximum amount of memory. All vertex coordinates may need swapping to the right tmus since t0 no longer represents tmu0. Texture loading is now located in TexCache.cpp instead of Util.cpp. I have tested with multitexturing also, and it works. * Gugaman sent me 8-bit AI and I this morning. I just changed I to use alpha instead of intensity. (first time i've seen it) 6:08 PM * Changed the debugger: space bar doesn't work the same. You must now select either page t0 (keyboard 2) or page t1 (keyboard 3) and then press space bar. Then it will select the CORRECT TMU AUTOMATICALLY and the corresponding texture in it. 6:29 PM * Made it so that pressing 'G' will switch on and off a grid for the cache viewer (large view on page 0). 7:19 PM * Fixed Gugaman's routines again... he didn't understand what the << 1 on ext was for in my routines; it was to multiply by the number of bytes per destination pixel. I had to take this out on the 8-bit ones. Tuesday, 5/28/02 2:22 PM * School is now out and I have more time to work on the plugin * Spherical mapping finally fixed for good. The size to use is the scale value >> 6. I found this information in a really strange place. * 32-bit textures implemented Wednesday, 5/29/02 12:33 PM * Fixed the fillrect problem. Recently i changed it so that TexCache() is REQUIRED to set the combine mode from Combine(), even if no texture is used. I had not yet updated fillrect to reflect this. Friday, 5/31/02 8:09 PM * Wrote all Wrap/Mirror/Clamp functions, for both 16-bit and 8-bit. 12:27 AM * Rewrote the tmu selection functions to remove support for 3 tmus and add support for 1 tmu. * Improved single-tmu support by a lot by forcing it to select a texture. Saturday, 6/01/02 9:46 PM * Added a log flush option to make it so that the log will be completely written before a crash or exception. * Made it so that a maximum count of 256 entries can be loaded by loadtlut by masking by 0xFF instead of 0x3FF. No more goldeneye exception. 1:58 AM * Finally cracked the goldeneye triangle instruction. Now triangles in goldeneye show correctly, but the textures are still messed up. (something about palettes) Sunday, 6/02/02 1:54 PM * Found why goldeneye palettes weren't working correctly. I noticed in the log that the settextureimage address was not being changed from the texture and the palette. So, I made loadblock and loadtile increment the settextureimage address as they load. 3:30 PM * Slightly optimized the 16-bit RGBA loading by using better RORs and SHLs instead of masking and shifting to swap the alpha bit. * Implemented IA-16 format for palettized textures. Now goldeneye works almost perfectly, but kinda slow. 4:44 PM * Found out that you do NOT increment the settextureimage address with loadtile. (HAL logo, SSB) Monday, 6/03/02 3:22 PM * Figured out why 32-bit texture's pixel swapping was not working correctly. Since I am not loading 32-bit textures exactly how the N64 would, they need to swap 64-bit words instead of 32-bit ones. 4:46 PM * Ack!!! If you switched to fullscreen before the ROM started running, it would set to single-tmu mode. I had to move the "rdp.num_tmu = 1" out of rdp_reset and into InitiateGfx so that it would only occur when the plugin is first loaded. * Fixed texrects in Mario Kart and probably some other things. Texrects use a different texture tile # than the one specified in uc0:texture, so it needed updating. 5:05 PM * Made it so that both tmu texture caches refresh at once. This may seem like a bad thing, because then it has more textures to load at once, but it's not. Before, after one tmu would refresh, it would have the most open memory and therefore get all the textures. If the other TMU was really close to being filled, it would never be refreshed. 6:53 PM * Added Voodoo 1 support. It was 5 lines of code. All I had to do was make it so that if mirroring was not supported, and was used, it would multiply the size by two. Then it would automatically mirror the smaller texture to the full size. * Added a check for clamping/mirroring/wrapping/mask for the cache, so that if anything changes, the texture can load differently. Tuesday, 6/04/02 7:52 PM * Fixed a bunch of things with alpha compare. Also made it so that it looks more like UltraHLE. I haven't found a single problem with it that wasn't there before, and the hands in Hexen show, and SSB is fixed. * 0.1762 3:17 AM * Made palette CRCs multiply the content by the location so that even if the contents are the same but in different locations, the CRC will be different. * Going to make sure to write version numbers here so I know what has changed. * 0.177 VC++ 6.0 SP 5 installed VC++ 6.0 Processor Pack installed Wednesday, 6/05/02 11:05 AM * Finished adding the negative count checks for mirror/wrap. For some reason, i had only implemented 2 of the 4. * Fixed a combiner that caused tony hawk to be bad. * 0.1771 7:25 PM * Changed alpha compare some more, making it so that force-blend overrides CVG_X_ALPHA. No problems observed so far, and it fixed Bomberman Hero. * Made z-buffer clearing fillrects faster by checking if cimg=zimg. * 0.178 10:25 PM * Implemented basic modifyvtx for texture coordinates, something is still not right. * Changed it so that coordinates are scaled in vertex instead of when they are drawn (this is correct). 11:29 PM * Improved the debugger again, allowing you to push left/right to cycle throught the triangles (by ID numbers). * Added vertex numbers to the debugger so you can tell which vertex is which (remember, 1 is the first vertex because of the way it clips. 2 is the 2nd vertex, and 0 is the third). * Fixed uc2:modifyvtx. I knew the solution the whole time, and I remember thinking about it, but when I looked at the macro I didn't see what I wanted so I let it go. Then later I come back and there it is! I needed to divide the vertex number by two. * 0.179 12:52 AM * Fixed the road in F-Zero by making it so that alpha_cvg_sel can occur with force_blend. Luckily, i had made a mistake before and thought something was set that really wasn't. As far as I can tell, nothing new broke. * Paper Mario wasn't working well because of an odd palette copy, so me & Gonetz decided just to change the combiner to T1 instead of T0*T1. (0xe2f10054) * 0.1791 Saturday, 6/15/02 4:10 PM * Large textures now load correctly, so now I need to do the math part. 9:21 PM * Improved upon the CRC code, removing the need for address checks. Now it multiplies the CRC by the position so that the O and U in mario are not the same. * 0.1792 Monday, 6/24/02 7:41 PM * Gonetz sent combiners again * Wrote the texture splitting code for texrects, still not working yet though. * Triangles in both texrects and triangles are drawn with grDrawVertexArrayContiguous which allows vertices to be in a linear array, rendering the pointer table i had made useless. I don't believe I hadn't discovered this function before. * YAYYYY!!!!!!!! I've finally finished large texture support. Actually half-finished. It works PERFECTLY for texrects, but not yet for triangles. No seams, nothing. EVERY SINGLE GAME I've tried so far (using texrects) works. About 80% of games with the problem used texrects. * 0.18 10:17 PM * Made it so that textures with masks that are greater than 8 just use the tile size. I haven't seen anything broken by this yet, and it speeds up some odd games. * 0.181 12:23 AM * Moved a -1 earlier in texrect, helped fix some coordinate problems. As far as I can tell, texrects are now good in terms of coordinates. There are still some lines, but that cannot be helped. It's caused by the fact that there are so many of them. The only way to solve is to blend between them. 2:29 AM * Made split texrects clamp so that if they need to wrap, they can do it without getting black lines across them. 5:01 AM * Added "Automatic" filtering mode. * Finally found what was causing versions since 0.1792 to go slow. I had called grFinish after grBufferSwap to see if it helped the FPS counter. It didn't and it made the plugin go REALLY REALLY SLOW. * Implemented the rest of rdp:setothermode for uc2. Health meter in Zelda now correct & you can't see him in the menu. * 0.182 Tuesday, 6/25/02 2:21 PM * Rewrote the texture cache searching algorithm so that it only has to search a few textures instead of all the textures. It takes the highest byte of the crc and only searches the textures that had that same value. * 0.183 4:26 PM * Got into really big conversations and all of the sudden, the whole FPS thing hit me at once! UpdateScreen() is actually a VERTICAL INTERRUPT!!! This is why it is called twice per every ProcessDList(). The TV is updating at 60hz but mario only at 30. This also explains why when I used UpdateScreen() instead of the buffer swap, I got the % of speed * 60. 5:41 PM * Added 4 types of speed counters. There is the FPS counter (frames per second), VI/s counter (vertical interrupts per second), NTSC % (percent speed on a (U) game), and PAL % (percent speed on a (E) game). * Added an option to clear top/bottom of screen like a NTSC TV. * 0.184 1:45 AM * Re-implemented the uc2:background command. Note to self: whenever textures don't show, check what's ABOUT to be put into grTexCombine() Wednesday, 6/26/02 2:10 AM * The trees in Majora's Mask were screwed up since I changed the texture code to actually emulate the tmem. I believe this is because it would wrap to the other side of tmem. I've implemented a somewhat fix for this. It will work with power of two wraps. Thursday, 6/27/02 2:05 PM * Rearranged clipping code to allow for large texture support. Also it now only performs z-clipping if NEEDED, and not always. This also allows for vertices to be copied only once, and not twice. * OMG. Sooo glad i found this... uCode 1 games were not setting the scr_off flags when they were off the screen. This is why i noticed problems when rearranging the clipping code. 6:34 PM * YAAAAAAY!!!! Large texture code for triangles is now complete!!! I can't find a single game that has the problem anymore!!! 12:10 AM * Added a tmem boundary check for LoadTile. It should fix many exceptions. So far I have seen it fix the exception in Extreme-G 2 and 1080 Snowboarding. Friday, 6/28/02 8:55 PM * I've been researching this alternate way of getting texture sizes that makes 1080 and several other games run much better. The only way there appears to be to do this is to make a game specific INI. I have already done this. It makes it so i can have a [DEFAULT] section and then override it with other values from each game. * Bad config error... for some reason, you cannot attach a tooltip hook and then set a lot of checks or your config dialog goes blank. If you create the hook afterwards though, it works. * Changed the order of clamping/wrapping so that it can clamp before it wraps if it needs to. 10:35 PM * Fixed bug in clamp/wrap, it needs to do ALL of s clamp/wrap before it moves on to t. * 0.192 11:18 PM * Made it so that fill mode (3) doesn't add 1 to the lower right coordinate like copy mode (2) does. Those things that were fill before are now copy because of when i implemented the rest of rdp:setothermode. 12:33 AM * Added text that says when in windowed mode: "Glide64" "Gfx cannot be drawn in windowed mode" "Press Alt+Enter to switch to fullscreen". *0.193 Sunday, 6/30/02 6:46 PM * Now allows Alt+Tab and other key combinations to be pressed. * Gugaman and I have been working with the IRP and I think we've finally found a solution. All of the games work so far, so we'll keep testing & find out. 10:46 PM * No problems observed with the IRP. * Added clock feature suggested on message board. Monday, 7/01/02 3:44 PM * Put in a "break;" after fog, so it doesn't move right on to lightcol. * Implemented lots of new combiners for Pokemon Stadium 2 and Megaman. * Changed alpha compare a little, adding a check for the combination of CVG_ALPHA_SEL and alpha compare. *0.197 8:15 PM * Fixed alignment for triangles. Now it is how it should be. It has eliminated the line errors in the Zelda select screens & many other things. * 0.2 in final form Tuesday, 7/02/02 11:38 PM * Fixed prim_z for extreme-g 2 by ignoring the matrix it uses. * TEMPORARILY CHANGED if ((rdp.render_mode & 0x00000C00) == 0x00000C00) to if (rdp.render_mode & 0x00000800) IN DECAL CHECK - fixes castlevania text, but not sure of other things. * Nothing seems to have broken, keeping for now... 3:47 AM * Changed enviornment mapping to 0x00080000 instead of 0x00040000 to fix F-Zero car textures. * Changed combiner for F-Zero cars to look right. * 0.202 Wednesday, 7/03/02 8:26 PM * Realized that non z-clipped vertices did not use the precalculated values like they were supposed to. [added to beta also] 9:55 PM * Changed alpha test value to 0x80, since that will be optimum b/c it is right in the middle of the texel. Also, it was required for Blues Brothers. * Fixed 4-bit CI for 16-bit IA textures. * Took out the C2, C3 init that Gonetz requested. 1:32 AM * Added self-jump checking to fix Gauntlet Legends & another check. * 0.21 Thursday, 7/04/02 9:02 PM * Put in some framebuffer support. The copy works ok, but when to use is VERY VERY BUGGY. * Completely redesigned the othermode functions so that multiple things could be set at once. Also, there is no such thing as "rdp.rendermode" now, it's a part of rdp.othermode_l, as rdp.mode_h changed to rdp.othermode_h. 10:22 PM * Enhanced the debugger, listing all of the othermode settings, with the current ones highlighted in green on page 6 and 7 of the debugger. 10:42 PM * Now that you can set any combination of othermodes at once, i modified my rdp:setothermode command to set ALL at once instead of one at a time. * Fixed alpha compare so that, like there is no compare when ALPHA_CVG_SEL (full alpha), there is no compare when force-blending to full alpha either. 1:27 AM * Worked past 2-3 hours decoding new ucode for Star Wars: Shadow of the Empire. Works near perfect as far as I can tell now. * 0.220 Saturday, 7/06/02 7:14 PM * Implemented basic ucode #5, Diddy Kong Racing. Icepir8 and I still need to figure out how it selects which matrix to use though. * Fixed a bug where the rdp_setothermode was using an unknown command instead of the othermode commands in ucodes other than 2. Sunday, 7/07/02 1:37 AM * Did LOTS with Diddy Kong Racing today, the only thing that seems left is the billboarding. * Billboarding done, uses vtx 0 as offset, then adds the current to it. Monday, 7/08/02 3:00 PM * Gonetz sent some more combines for diddy 12:47 AM * Fixed some more stuff in Diddy, like the transparent walls. * Added texture-modification code. Now it is possible to do things for combiners that would be impossible otherwise. Now you can see the selection in DKR, and also the LOT of Zelda OOT works. Don't have save of MM, so can't implement that one yet. * 0.230 Tuesday, 7/09/02 6:08 PM * Fixed cache bug where it wasn't always setting the mod flags, therefore refreshing faster and faster each time. * Added culling to DKR ucode, works much better now. * partially fixed LOT in MM, but the outside is still solid. * 0.231 Thursday, 7/12/02 * 0.2 released Sunday, 7/14/02 5:51 PM * Fixed the Great Fairy's hair color using texture modification. * Fixed the RUSH games, for some reason they have size set to 0, so I used *gfx.VI_WIDTH_REG instead to determine the size. * 0.232 * Used texture mod again to fix the SF rush 2049 wings. 11:44 PM * Added a whole bunch of impossible combines by using the texture modification. * Fixed Snowboard Kids by implementing the modifyvtx for ucode 0. (same as 2) Monday, 7/15/02 9:07 AM * Fixed items in Super Smash Brothers by implementing the moveword matrix command. It took me a while to figure out that it was incrementing in the x direction and not the y, and also that you actually add the positive decimal part, EVEN WHEN WHOLE NUMBER IS NEGATIVE. * 0.235 1:02 PM * Added new INI code, should be no more corrupting. 3:21 PM * Added culling for Diddy Kong Racing & fixed a non-working combine for the background color. * Added huuuuge semi-combiner for flashing characters in SSB. * Added support for clearing z-buffer using a texrect (SSB black rectangle). * 0.237 1:18 AM * Added a framebuffer workaround for Zelda: MM LOT. Now it works without needing to use framebuffer copies. * 0.240 Tuesday, 7/16/02 11:30 PM * Found out that the LOT and telescope problems are with prim_depth. It enables but doesn't set a depth value. * Rice gave me plenty more new things to do :) * The dlist with count command now implemented in f3dex 2.xx ucode. Cruisin' Exotica works. (Rice's help) * 0.241 12:27 AM * Added the movemem matrix command, WWF No Mercy works now. * 0.242 Wednesday, 7/17/02 5:53 PM * Fixed SERIOUS bug in CI textures, it would not use the correct format. * Fixed combine for link's sword swirl. * Added new buffer swapping method that fixes flashing. * 0.247 Friday, 7/19/02 4:20 PM * Made LoadTile boundary checking MUCH better; now checks if >= and also for last write so even if it's not aligned properly it will cut anything that goes above. Paper Mario level up fixed. * Added several combines for xg2. * V-Sync option added. This only takes effect if it's set to "Software Controlled" in the 3dfx Hub. 7:37 PM * Made it possible to continue after a gfx exception. 8:29 PM * Got fillrects to align perfectly now by forcing the coordinates to DWORD instead of float. * Got rid of the floating point error in fillrects and scissor by adding 0.01f. Saturday, 7/20/02 3:54 PM * Made it so that texrects on copy mode will use full alpha but also have alpha compare. * 0.250 released 11:51 PM * Made it so that fillrects use the z-buffer as specified and not always update, no compare. Banjo-Tooie fixed. Sunday, 7/21/02 8:01 PM * Fixed 12 PM clock bug, and added 24-hour clock option. * Made a REAL error log. * Fixed stats not showing up by redoing alpha compare for texrects. * 0.253 released * Took out if(!force_full_alpha) from alpha compare. 2:46 AM * Added first part of S2DEX ucode; the obj_loadtxtr and bg_copy. * Found out that uc2_bg and uc6_bgcopy were the exact same thing... I think F3DEX sorta "borrowed" it. Set the F3DEX one to the S2DEX one. Tuesday, 7/23/02 11:10 PM * Added lots more to the S2DEX ucode, yoshi's story is now about as good as it can get. The background uses framebuffer, so... * Microcode switching should be ok now for the most part. 11:31 * Added combiner for WWF No Mercy rules. * Allowed things to have negative viewport; MK mythologies fixed. /*Gonetz*/ Friday, 10/18/02 12.40 I'm going to fix depth problem * step 1. Added new coordinate to VERTEX - w. Replaced all .z and ->z by .w and ->w b/c old z is actually w. Affected files: rdp.h Ucode00.h ucode01.h ucode02.h ucode03.h ucode04.h ucode05.h Debugger.cpp Util.cpp Tested. Nothing seems to be broken :) * step 2. z coordinate is now calculated in all ucodes. * step 3. using z for w buffer. z/w actually. Corrected all clipping functions. Ops, does not work :( I forgot, z/w is in range (-1,1). (z/w + 1)/2 does not work well either. * Idea: use "screenZ=(z/w)*0x3fe0 + 0x3fe0" formula for z and Z buffer instead of W buffer. Wow, it's work! Taz and Gex appears at last :) But some problem remains. Some triangles are missing. I think it's b/c of z clipping Saturday, 10/19/02 13.00 * Found stupid bug in clipping functions which is result of cut'n'paste editing. Now picture is close to perfect. But some triangles are still missing, for example water near castle in Mario64. * Replaced all _z slot names by _w. * Fixed z for texrect and fillrect. Strange, but primdepth does not work well for z - DukeNukem64 has errors with it. I use primdepth + 8, all works quite well now. Need to test it more. 23:15 * According to manual, correct formula for z is: screenZ = 32*((z/w)*view_scale[2] + view_trans[2]) I use it now, nothing is changed, but may be some games use other value for view_scale[2] and view_trans[2] then default 0x1ff Sunday, 10/20/02 17.20 * Z clipping is finally fixed. I thought that z should be 0 after Z clipping, but it actually must be clipped the same way as x and y. Now all works perfect!!! Nokonec to, blin :) * Added missing combines for Taz express and Road Rush * 0.260 Tuesday, 10/22/02 20.20 * Started to implement ucode for Perfect Dark. I took info about it from Icepir8's plugin. Changes: ucode.h - new ucode ucode07.h - vertex and tri4 implemented ucode00.h - matrix. mask removed to be compatible with PD rdp.h - tex_coord_addr added rdp.cpp - rdp_reset, tex_coord_addr initialization - rsp_reserved2, tex_coord_addr value config.cpp - new ucode Wednesday, 10/23/02 13.30 * new combines and tex modes added. Thursday, 10/31/02 * Fixed Rayman2. Changes: ucode00.h - implemented gSPForceMatrix command in movemem. All 3FFFFF mask replaced by FFFFFF ucode01.h - 3FFFFF mask in vertex replaced by FFFFFF combine.cpp - implemented missed combines for Rayman2 Saturday, 11/9/02 15.30 * rdp_texrect(): float Z = 32704.0f replaced by float Z = 1.0f; That fixed onscreen info in xg2. * Fixed combine for Bug's life. Start menu background appears. * Fixed uc2:modifyvtx. Main menu background in Bug's life appears * Fixed constant depth processing in do_triangle_stuff(). Main menu in Bug's life works (somehow) * Fixed combine for Bomberman2. Water is transparent now. * Monsters poked through walls in DukeNukem64 was caused by depth bias level value. Replaced depth bias level from 0x20 to 0x18. No need of "rdp.prim_depth + 8.0f" hack in rdp_texrect() anymore. * heap of new combines implemented Saturday, 11/16/02 * Since z in N64 is in range [0, 32704], I decided to multiply it by 2. It improves quality of depth buffer. Changes: Util.cpp - do_triangle_stuff() Rdp.cpp - rdp_texrect() Sunday, 11/17/02 * Added hacks in texrect and fillrect to avoid black screen in ZeldaMM "Link meets princess Zelda" cut scene and in between days. Changes: Rdp.h - new flag Rdp.cpp - hacks in rdp_texrect() and rdp_fillrect() ucode06.h - hacks in uc6_bg_copy() and DrawImage() Monday, 11/18/02 * Added hack into uc2:modifyvtx, (x,z). Tarzan is fixed * new combines and tex modes added. * Altered combine for flame in Zeldas. It looks good :) Redone similar combines. Tuesday, 11/19/02 * Added new settings parameter - depth buffer mode. User can choose either new Z-buffer mode or old W-buffer one. W-buffer is useful in games, where Z-buffer causes poke-through artefacts. I've got Dave2001's last version. Many things are not finished, but I inserted some of his fixes into current version: * Made it so games only report ucode error only once. * Backwards viewport needs backwards culling ;) fixed DKR Adventure 2 mode (mirrored tracks). I'm not sure about other ucodes, so I haven't changed the culling for them yet. * Oops, loadblock boundary check was in bytes instead of qwords. Xena problem fixed. * Fixed mod_tex_inter_col_using_col1; it was using a 32-bit color when it was really only 16-bit. This fixed the colors of the WWF No Mercy menus. Saturday, 12/14/02 * heap of new combines implemented Sunday, 12/15/02 * Fixed Banjo-Tooie. Changes: Rdp.cpp - rdp_texrect() - new hack rdp_fillrect() - old hack, removed by Dave2001 for some reason after 0.250 * Fixed backgroung fire on level 23, Doom64 I've modified alpha compare condition in Util.cpp * Changed Zelda MM hack in texrect. * implemented heap of new combines Wednesday, 12/18/02 * Changed Zelda MM hack in texrect so it should not affect other games anymore. Konami logo is fixed in many games. * implemented new combines Friday, 12/27/02 * Removed perfect dark microcode from final version - need more work b4 release * 0.3 Wednesday, 01/07/03 * Changed fillrect so it usses fillcolor allways, but it calculates it differently depending on cycle mode. I don't know why Dave2001 implemented so complex color transformation for this function, but I think it was a reason for that, so I left it as is for FILL mode, but for 1 and 2 cycle mode I use normal fillcolor. Car selection screen in SF Rush is fixed. * Changed texrect - I force depth compare when primdepth is used. Car selection in SF Rush 2049 is fixed. ? * Changed fillrect again. Privious modification causes many gfx erorrs. * Added depth value check in texrect. Primdepth value can be too high. Sunday, 01/19/03 * Added new buffer swapping method which prevents flicker in Paper Mario (not everywhere yet). * Implemented many combiners for Paper Mario. Friday, 01/31/03 * Fixed uc0_moveword LIGHTCOL. n was calculated wrong. Background in "star soldier vanishing earth" fixed. Saturday, 02/01/03 * Implemented calls of GS2DEX ucode functions from F3DEX2 ucode. 2D stuff in Bomberman 2 is fixed. * Changed uc6_obj_sprite so it uses combiner instead of just texture. Required for some objects in Bomberman 2 * 0.31 Wednesday, 02/12/03 * Added new setting - ignore_short_dlist. It allows me to avoid weird bug in Tonic Trouble, when game get caught in an endless loop, drawing title screen. * Found an error in ini which was the reason why Dave's work for Yoshi Story caused an exception. F3DEX1 ucode which Yoshi uses in the begining, was mistakenly set to 6. Yoshi is working with last Dave's version now Thursday, 02/13/03 * Moved Dave's code for Yoshi into current version. It works * 0.312 Friday, 02/14/03 * Fixed uc6_obj_sprite so sprite can be translucent. It needed for Yoshi statistics screen. * Trying to fix garbage appeared on top of the screen in Yoshi. no results :( Saturday, 02/15/03 * While trying to fix topscreen garbage, I begin to understand, how the things work :) Texrect function copies texture into framebuffer(DRAM) instead of drawing it. Dave chose very strange and complex way to do it - he loaded texture, copied it's data into special texture buffer, and then copied it from that buffer into framebuffer. I have modified his code. I directly copy data from texture address into framebuffer adress. It's faster, more easy and less buggy :) But it does not fix topscreen garbage problem. This problem is solved somehow in PJ 1.5 plugin though. Thursday, 02/27/03 * Fixed DrawImage routine, so it works correct with scaled images. Zoom in Yoshi works * Implemeted uc6_obj_rectangle. Pokemon Puzzle League is almost playable now. But some textures are broken. Saturday, 03/01/03 * Worked on Pokemon puzzle league: Fixed DrawImage routine, so it can draw images with odd value of width and height. Added possibility to use combiners with backgrounds. (almost) no problems with background remained in this game. I need to solve problem with 8bit CI textures, wich became broken after loading of 32bit RGB textures. Saturday, 03/08/03 * Fixed rdp_loadtlut(), so it will not get off pallete array bounds. It fixes Inferno area in Banjo 2 and may be some other games. Tuesday, 03/11/03 * Finnaly found why CI textures became broken after 32bit texture load in PPL. It was a bug in uc6_obj_loadtxtr (). Dave forgot to set tile size there, so after 32bit texture load it was equal to 3, and all non 32bit textures was swapped wrong. Now all textures in PPL look correct, the game is almost playable :) Wednesday, 03/12/03 * Implemented loading of title screen in games which draw image before first ProcessDList (Rayman2, Tonic Trouble, Wave Race...) I found solution in sources of Rice's great plugin. Friday, 03/14/03 * Fixed texture problem in PPL when it uses F3DEX 1 ucode! Tile's ul_s and lr_s coordinates were set to 0 by settilesize - 1 texel was clamped to all triangle. Solution: take ul_s and lr_s from next loadtile. It works! Saturday, 03/15/03 * Fixed bricks in 3D mode. Bricks use CI texture, and for some reason u and v coordinates of loaded vertex are two time bigger then they must be, when vertex uses CI. Solution: check format in uc0_texture() and change s_scale and t_scale for CI format Sunday, 03/16/03 * Implemented uc0_moveword() move_point. Cruise in USA works perfectly now! Monday, 03/17/03 * Fixed many bugs which causes an exception in PPL. * Added new special fix - wrap textures too big for tmem. It's Dave's old hack for trees in Zelda MM intro. It breaks texture in Zelda's N64 logo and may break other things, so I've made it optional Tuesday, 03/18/03 * Fixed candle's flame in Paper Mario - error in alpha combine * My fix for car selection screen in SF Rush 2049 breaks particle in Rayman. I don't know, how to make both things working :( Another special fix for SF Rush 2049 only Wednesday, 03/19/03 * Fixed pointer in Bust a Move 2! This game has the same problem with CI textures, as PPL, so fix for PPL fixes this game too :) Saturday, 03/22/03 * Implemented branch_z function for F3DEX 1 ucode. It's used in SF Rush. All texture problems in this game are fixed! * Added new special fix - "use depth compare for fillrect". Using depth compare in fillrect fixes car selection screen in SF Rush, and doing this much better, then my previous hack. This option changes N64 logo in Zeldas though, so it's off by default. Sunday, 03/23/03 * Fixed most of tecture errors in V-Rally 99. The same problem - too large u and v coordinates. This fix is a hack indeed. I'm tired of all that hacks, but I could not find, why vertex loaded incorrectly. And besides, all in-game statistics is missing :( Monday, 03/17/03 * I forgot to implement call of uc6_ldtx_rect_r from zelda ucode. That's why in-game statistics in V-Rally 99 was missing. Wednesday, 03/26/03 * Fixed combiners using in sprite commands. Combine() is not used if in "copy" mode V-Rally looks exactly as on N64. Tuesday, 03/27/03 * Allowed negative viewport for zelda ucode. Destruction Derby Professional Championship is fixed. Saturday, 03/29/03 * Fixed crc calculation for 8-bit color textures. Burning cars in Destruction Derby are burned :) Monday, 04/07/03 * Implemented TextureRectangleFlip - text in Wetrix fixed Thursday, 04/10/03 * Fixed uc6_obj_rectangle_r - text in Yoshi has correct size. * 0.4 Friday, 04/17/03 * Fixed trail problem in Zelda OOT. Rice sent me an idea how it can be done. Actually it was already implemented by Dave, but values for depth bias level were incorrect. Sunday, 04/19/03 * Implemented Sprite2D microcode. Backgrounds in Silicon Valley are fixed Fixed primdepth loading. Billboard objects in Silicon Valley are fixed too. Wednesday, 04/30/03 * Fixed palette loading (load_palette). This fixed nemu in StarCraft. Yet again the solution (idea) was found in sources of Rice's plugin. *0.41 ? * fixed compatibility of Zelda OOT MQ with 1964 Sunday, 05/18/03 * Added hack for sun in zeldas. Wednesday, 05/21/03 * Implemented palette loading in Sprite2D microcode and fixed many things in it. 2D stuff in wipeout works. Tuesday, 06/03/03 *New hack in texrect to remove black screen in Sin and Punishment Thursday, 06/05/03 * fixed uc1_line3d - map in Doom64 * changed blender mode for fillrect - sky in Doom64 * fixed combiners for walls and weapons in Doom64 Saturday, 06/07/03 * changed texture mods for CI textures. I'm changing palette before texture loading instead of modifying already loaded texture. This is more faster and more precise. Sunday, 06/08/03 * added new hotkey - texture filtering mode can be changed during gameplay by pressing BACKSPACE. This is Raziel64's idea. * Implemented frame buffer emulation. I use 2 pass approach. First pass - detect frame buffer usage - very fast. Second pass - normal display list processing, but with knowledge how frame buffers will be used. * Added ExtendedPlay's Banshee hack. * Added "special game settings" section in the ini * New hotkeys for motion blur and read always * Many other fixes * New configuration dialog, based on property sheets V. 05 * Fixed ucode for Perfect Dark. It works without glitches now * Added support for Jet Force Gemini and Mickey's Speedway into Diddy's ucode. * Added partial yuv textures support. I failed to decode them with the method described in the manual - something wrong with the coefficients. Thus I found correct formula in Internet, it works. I have optimized decode procedure specially for Ogre Battle 64, it hardly will work with other game. * Implemented new frame buffer related functions - FBRead and FBWrite. FBRead could help to emulate frame buffer effect which previously required "read always" option. FBWrite makes Dr.Mario playable * Implemented hardware texture emulation. Huge and hard work. * Failed to do correct fog emulation. I tried to use fogcoord extension, like in Orkin's plugin. It works, but fog is not smooth. * Added large texture support for sprite microcode * Fixed texrect_flip * Changes in the configuration dialog v. 07 SP8 - New version * I have switched to RGBA color format. This format is used by N64 itself. I can't understand, why Dave decided to use ARGB. With RGBA I don't need to do color conversions, and everything is more simple. Besides, OpenGL also uses RGBA format only, so port to OpenGL will be more simple. * I've made another attempt to implement fog via fog coord extension. This time I set fog coord after all clipping. It still not perfect for clipped surfaces but no major glitches this time. I decided to use it. * I have found why kicked out fighter in Super Smash Bros has black rectangle bourder. This black rectangle have to be rendered into the depth buffer. Weird thing. I've made check that texrect will not be drawn if current color buffer is depth buffer. This problem is fixed. * I have found that walls in Perfect Dark are incorrect again. That was caused by my hack in the combiner for car setup in Top Gear Rally. I have corrected this hack. It does not use LOD if mipmap_level is the same as current_texture. * I have implemented depth buffer render. Of course, it takes a lot of CPU time. But I found fast algorithm with fixed point arithmetics, so I can run some games fullspeed even on my 1ghz Celeron. * Hacktarux suggested me to use N64 format for z value, so Glide will loose precision on the same place as N64 itself. I finally understood what he ment, and implemented it. Well, all old poke-through problems with z-buffer are gone, but new one appeared. This method does not work. But I noticed, that conversion from my z to N64 z is not linear. It gives enough precision for large z at the cost of loosing precision with small z. I decided to use floated point z conversion which works similary - (z/65535)*z*2. Great! No problems with close objects and much less problems with far ones. After that I have removed w-buffer mode entirely. It's not compatible with fog-coord anyway. I also removed old fog algorithm. * Implemented 32bit frame buffer support (convert 16bit glide frame buffer into 32bit N64 ones). * Fixed frame buffer effects detection algorithm to support rear-view mirror in Roadsters. Later I found how to make it working without fb support - just remove corresponding texrects. Rear-view mirror now works full speed on any videocard. Monday, 27 Dec 04 * Fixed grid in Mario Golf. The error appeared after rewriting of modifyvtx function. It was caused by unset x,y and zsrc is on. Tuesday, 28 Dec 04 * Fixed combiner for road in Zelda OOT. * My ZtoN64Z causes problems for small z. As result text in Tigger Honey Hunt is disappeared. Tuned ZtoN64Z so it does not transform small z now. Not sure, it can cause other problems. * Added new hack - increase texrect size. Rice uses similar hack to fix new tetris and mega man 64. The new tetris is fully playable now with texture coordinate fix. Sunday, 02 Jan 2005 * Added prim_depth using in fillrect. Tuesday, 04 Jan 05 * Rewrited fog again * Implemented special fog mode, when object is not fogged, but became transparent instead. Wednesday, 05 Jan 2005 * Fixed depth buffer clear in fillrect. * Removed depth compare hack from fillrect * Fixed out of range bug in depth render. Sunday, 16 Jan 2005 * Fixed depth problem in Destruction Derby. Maximum depth value must be <= 65534 * Fixed depth problem in sprite microcode - z conversion must not be used in set_sprite_combine_mode. * Fixed color combiner for fire electric pen. * Fixed fog when fog multiplier is negative. * Added combiners for Paper Mario * Fixed texcoord hack for Polaris Snow Cross Monday, 17 Jan 2005 * Added combiners for Paper Mario Tuesday, 18 Jan 2005 * Fixed text in Doraemon - Mittsu no Seireiseki. This is the second game, which uses CPU frame buffer writes. * Added dithred alpha support. I found 2 undocumented Glide functions: grStippleMode and grStipplePattern. They work almost the same as similar functions in OpenGl. Dithred alpha test is used in Mario64, and now it works very good. Thursday, 20 Jan 2005 * Added per-pixel LOD calculation. It was quite hard to get decent result. Peach/Bowser portrait's transition in Mario64 works fine, Perfect Dark is acceptable too. Only Utils.cpp is changed. Friday, 21 Jan 2005 * Added LOD option to the configuration panel * Added missing tooltips * Added stipple options to ini file. 22-30 Jan 2005 * RE2. fix in DrawImage. * RE2. depth buffer render to video memory to fix depth problem. Slow * RE2. Found how movies work. 2 mode implemented - stretched and in the native resoluton. * RE2. Added depth buffer render via HWFBE. Fast and perfect. * Fixed depth problem with prim depth. * Fixed depth problem with texrects which uses prim depth - depth write must be off while depth compare must be on. * Fixed some combiners. Tuesday, 1 Feb 2005 * !Changed rdp_loadblock. texture image address will not changed if lr_s is 0. This fixes Twisted Edge Extreme Snowboarding background. Thursday, 3 Feb 2005 * Added hack for backgrounds in WCW Nitro. * Removed zelda hack from DrawImage. WCW Nitro backgrounds did not work because of this hack. * Added hack for texture generation in Chopper Attack. This hack was used for all games and this caused one glitch in Super Mario, so I made it optional. * Fixed partially Horisont Scaner in Perfect Dark. Glitch was caused by one option on texrect, which prevents to draw texrects wich use previous frame as texture. For Horisont Scaner the same color buffer is used each frame (strange). * Added missing combiner for Perfect Dark. Friday, 4 Feb 2005 * Added GUI option "Show RE2 videos in native resolution" * Fixed videos crash with PJ64. For some reason first frame has height > 256, so I had write above bounds here. * Implemented several combiners for Paper Mario and Tony Hawk. Tuesday, 8 Feb 2005 * Fixed "Tidal wave" in Paper Mario. It's quite complex frame buffer effect, many things were changed in FB emulation. It still has problem with HWFBE. Wednesday, 9 Feb 2005 * Fixed (rather hacked) viewport problem in RE2. 12-13 Feb 2005 * Added suport for cloaking effect in Perfect Dark. It was hard - the game may use about 30 auxilary frame buffers here. New frame buffer type was added - aux_copy. HWFBE does not work correct here. Monday, 14 Feb 2005 * Source cleaning. Tuesday, 15 Feb 2005 * More source cleaning * Fixed combiner for boost mode in Beetle Adventure Racing. 23-27 Feb 2005 * A lot of changes in fb emulation and in HWFBE. Tidal wave in Paper Mario, cloaking effect and motion blur in Perfect Dark, replay in 1080... 1 Apr 2005 * Paper Mario intro. There is a kind of fb effect. I have changed main ci height calculation in fb_setcolorimage and in rdp_setcolorimage to make it working. * Paper Mario intro. Added a hack into blender to remove weird texrect when bowser throw up flame. These changes were originally not mentioned here: Glide64 Wonder and Wonder Plus * April 2005 to November 2005 glide64-wonder+-linux * unknown glide64-wonder+-linux v10 * March 2007 glide64-wonder+-linux v11 * April 2007 glide64-wonder+-linux v12 * May 2007 Glide64-amd64 v0.9 * forked from glide64-wonder+-linux v12 * Ported all GCC and nasm assembler to AMD64 and corrected various other 64 Bit portability problems -- 2008-02-01 Günther mupen64plus-video-glide64-src-2.6.0/src/Combine.cpp000066400000000000000000014017721464507525600217470ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * Copyright (c) 2008 Günther * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** // March 08, 2002: // * New combiner method by Gonetz and Dave2001 //**************************************************************** #define M64P_PLUGIN_PROTOTYPES 1 #include "m64p_types.h" #include "m64p_plugin.h" #include "m64p_config.h" #include "m64p_vidext.h" #include "Util.h" #include "Combine.h" #ifndef _WIN32 #include #endif // _WIN32 #define FASTSEARCH // Enable fast combine mode searching algorithm float percent_org, percent, r, g, b; DWORD lod_frac; DWORD cc_lookup[257]; DWORD ac_lookup[257]; COMBINE cmb; //**************************************************************** // Macros //**************************************************************** #define MOD_0(mode) cmb.mod_0 = mode #define MOD_0_COL(color) cmb.modcolor_0 = color #define MOD_0_COL1(color) cmb.modcolor1_0 = color #define MOD_0_COL2(color) cmb.modcolor2_0 = color #define MOD_0_FAC(factor) cmb.modfactor_0 = factor #define MOD_1(mode) cmb.mod_1 = mode #define MOD_1_COL(color) cmb.modcolor_1 = color #define MOD_1_COL1(color) cmb.modcolor1_1 = color #define MOD_1_COL2(color) cmb.modcolor2_1 = color #define MOD_1_FAC(factor) cmb.modfactor_1 = factor #define A_BLEND(f1,f2) cmb.abf1=f1,cmb.abf2=f2 // To make a color or alpha combine #define CCMB(fnc,fac,loc,oth) \ cmb.c_fnc = fnc, \ cmb.c_fac = fac, \ cmb.c_loc = loc, \ cmb.c_oth = oth #define ACMB(fnc,fac,loc,oth) \ cmb.a_fnc = fnc, \ cmb.a_fac = fac, \ cmb.a_loc = loc, \ cmb.a_oth = oth #define CCMBEXT(a,a_mode,b,b_mode,c,c_invert,d,d_invert) \ cmb.c_ext_a = a, \ cmb.c_ext_a_mode = a_mode, \ cmb.c_ext_b = b, \ cmb.c_ext_b_mode = b_mode, \ cmb.c_ext_c = c, \ cmb.c_ext_c_invert = c_invert, \ cmb.c_ext_d= d, \ cmb.c_ext_d_invert = d_invert, \ cmb.cmb_ext_use |= COMBINE_EXT_COLOR #define ACMBEXT(a,a_mode,b,b_mode,c,c_invert,d,d_invert) \ cmb.a_ext_a = a, \ cmb.a_ext_a_mode = a_mode, \ cmb.a_ext_b = b, \ cmb.a_ext_b_mode = b_mode, \ cmb.a_ext_c = c, \ cmb.a_ext_c_invert = c_invert, \ cmb.a_ext_d= d, \ cmb.a_ext_d_invert = d_invert, \ cmb.cmb_ext_use |= COMBINE_EXT_ALPHA #define T0CCMBEXT(a,a_mode,b,b_mode,c,c_invert,d,d_invert) \ cmb.t0c_ext_a = a, \ cmb.t0c_ext_a_mode = a_mode, \ cmb.t0c_ext_b = b, \ cmb.t0c_ext_b_mode = b_mode, \ cmb.t0c_ext_c = c, \ cmb.t0c_ext_c_invert = c_invert, \ cmb.t0c_ext_d= d, \ cmb.t0c_ext_d_invert = d_invert, \ cmb.tex_cmb_ext_use |= TEX_COMBINE_EXT_COLOR #define T0ACMBEXT(a,a_mode,b,b_mode,c,c_invert,d,d_invert) \ cmb.t0a_ext_a = a, \ cmb.t0a_ext_a_mode = a_mode, \ cmb.t0a_ext_b = b, \ cmb.t0a_ext_b_mode = b_mode, \ cmb.t0a_ext_c = c, \ cmb.t0a_ext_c_invert = c_invert, \ cmb.t0a_ext_d= d, \ cmb.t0a_ext_d_invert = d_invert, \ cmb.tex_cmb_ext_use |= TEX_COMBINE_EXT_ALPHA #define T1CCMBEXT(a,a_mode,b,b_mode,c,c_invert,d,d_invert) \ cmb.t1c_ext_a = a, \ cmb.t1c_ext_a_mode = a_mode, \ cmb.t1c_ext_b = b, \ cmb.t1c_ext_b_mode = b_mode, \ cmb.t1c_ext_c = c, \ cmb.t1c_ext_c_invert = c_invert, \ cmb.t1c_ext_d= d, \ cmb.t1c_ext_d_invert = d_invert, \ cmb.tex_cmb_ext_use |= TEX_COMBINE_EXT_COLOR #define T1ACMBEXT(a,a_mode,b,b_mode,c,c_invert,d,d_invert) \ cmb.t1a_ext_a = a, \ cmb.t1a_ext_a_mode = a_mode, \ cmb.t1a_ext_b = b, \ cmb.t1a_ext_b_mode = b_mode, \ cmb.t1a_ext_c = c, \ cmb.t1a_ext_c_invert = c_invert, \ cmb.t1a_ext_d= d, \ cmb.t1a_ext_d_invert = d_invert, \ cmb.tex_cmb_ext_use |= TEX_COMBINE_EXT_ALPHA // To use textures #define USE_T0() \ rdp.best_tex = 0; \ cmb.tex |= 1, \ cmb.tmu0_func = GR_COMBINE_FUNCTION_LOCAL #define USE_T1() \ if (num_tmu > 1) { \ rdp.best_tex = 1; \ cmb.tex |= 2, \ cmb.tmu1_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_func = GR_COMBINE_FUNCTION_SCALE_OTHER, \ cmb.tmu0_fac = GR_COMBINE_FACTOR_ONE; \ } \ else { \ USE_T0(); \ } #define T0_ADD_T1() \ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.tmu1_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_func = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, \ cmb.tmu0_fac = GR_COMBINE_FACTOR_ONE #define T0_MUL_T1() \ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.tmu1_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_func = GR_COMBINE_FUNCTION_SCALE_OTHER, \ cmb.tmu0_fac = GR_COMBINE_FACTOR_LOCAL #define T0_MUL_T1_ADD_T0() \ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.tmu1_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_func = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, \ cmb.tmu0_fac = GR_COMBINE_FACTOR_LOCAL #define T0A_MUL_T1() \ rdp.best_tex = 1; \ cmb.tex |= 3, \ cmb.tmu1_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_func = GR_COMBINE_FUNCTION_SCALE_OTHER, \ cmb.tmu0_fac = GR_COMBINE_FACTOR_LOCAL_ALPHA #define T0_MUL_T1A() \ rdp.best_tex = 1; \ cmb.tex |= 3, \ cmb.tmu1_func = GR_COMBINE_FUNCTION_LOCAL_ALPHA, \ cmb.tmu0_func = GR_COMBINE_FUNCTION_SCALE_OTHER, \ cmb.tmu0_fac = GR_COMBINE_FACTOR_LOCAL #define T0_INTER_T1_USING_FACTOR(factor) \ if (factor == 0xFF) { \ USE_T1(); \ } \ else if (factor == 0x00) { \ USE_T0(); \ }\ else {\ if (factor <= 0x80) rdp.best_tex = 0; \ else rdp.best_tex = 1; \ cmb.tex |= 3, \ cmb.tmu1_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_func = GR_COMBINE_FUNCTION_BLEND, \ cmb.tmu0_fac = GR_COMBINE_FACTOR_DETAIL_FACTOR, \ percent = (float)factor / 255.0f, \ cmb.dc0_detailmax = cmb.dc1_detailmax = percent; \ } #define T1_INTER_T0_USING_FACTOR(factor) /* inverse of above */\ if (factor == 0xFF) { \ USE_T0(); \ } \ else if (factor == 0x00) { \ USE_T1(); \ }\ else {\ if (factor <= 0x80) rdp.best_tex = 0; \ else rdp.best_tex = 1; \ cmb.tex |= 3, \ cmb.tmu1_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_func = GR_COMBINE_FUNCTION_BLEND, \ cmb.tmu0_fac = GR_COMBINE_FACTOR_DETAIL_FACTOR, \ percent = (255 - factor) / 255.0f, \ cmb.dc0_detailmax = cmb.dc1_detailmax = percent; \ } #define T0_INTER_T1_USING_T0() \ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.tmu1_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_func = GR_COMBINE_FUNCTION_BLEND, \ cmb.tmu0_fac = GR_COMBINE_FACTOR_LOCAL #define T1_INTER_T0_USING_T0() \ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.tmu1_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_func = GR_COMBINE_FUNCTION_BLEND, \ cmb.tmu0_fac = GR_COMBINE_FACTOR_ONE_MINUS_LOCAL #define T0_INTER_T1_USING_T1() \ if (!cmb.combine_ext) { \ T0_INTER_T1_USING_FACTOR(0x7F); \ }\ else {\ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.t1c_ext_a = GR_CMBX_LOCAL_TEXTURE_RGB, \ cmb.t1c_ext_a_mode = GR_FUNC_MODE_ZERO, \ cmb.t1c_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB, \ cmb.t1c_ext_b_mode = GR_FUNC_MODE_ZERO, \ cmb.t1c_ext_c = GR_CMBX_ZERO, \ cmb.t1c_ext_c_invert = 0, \ cmb.t1c_ext_d= GR_CMBX_B, \ cmb.t1c_ext_d_invert = 0, \ cmb.t0c_ext_a = GR_CMBX_OTHER_TEXTURE_RGB, \ cmb.t0c_ext_a_mode = GR_FUNC_MODE_X, \ cmb.t0c_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB, \ cmb.t0c_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X, \ cmb.t0c_ext_c = GR_CMBX_OTHER_TEXTURE_RGB, \ cmb.t0c_ext_c_invert = 0, \ cmb.t0c_ext_d= GR_CMBX_B, \ cmb.t0c_ext_d_invert = 0, \ cmb.tex_cmb_ext_use |= TEX_COMBINE_EXT_COLOR; \ } #define T0_INTER_T1_USING_T1A() \ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.tmu1_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_func = GR_COMBINE_FUNCTION_BLEND, \ cmb.tmu0_fac = GR_COMBINE_FACTOR_OTHER_ALPHA #define T0_INTER_T1_USING_PRIM() \ if (!cmb.combine_ext) { \ T0_INTER_T1_USING_FACTOR ((rdp.prim_color&0xFF)); \ }\ else {\ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.t1c_ext_a = GR_CMBX_LOCAL_TEXTURE_RGB, \ cmb.t1c_ext_a_mode = GR_FUNC_MODE_ZERO, \ cmb.t1c_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB, \ cmb.t1c_ext_b_mode = GR_FUNC_MODE_ZERO, \ cmb.t1c_ext_c = GR_CMBX_ZERO, \ cmb.t1c_ext_c_invert = 0, \ cmb.t1c_ext_d= GR_CMBX_B, \ cmb.t1c_ext_d_invert = 0, \ cmb.t0c_ext_a = GR_CMBX_OTHER_TEXTURE_RGB, \ cmb.t0c_ext_a_mode = GR_FUNC_MODE_X, \ cmb.t0c_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB, \ cmb.t0c_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X, \ cmb.t0c_ext_c = GR_CMBX_TMU_CCOLOR, \ cmb.t0c_ext_c_invert = 0, \ cmb.t0c_ext_d= GR_CMBX_B, \ cmb.t0c_ext_d_invert = 0, \ cmb.tex_ccolor = rdp.prim_color, \ cmb.tex_cmb_ext_use |= TEX_COMBINE_EXT_COLOR; \ } #define T1_INTER_T0_USING_PRIM() /* inverse of above */\ if (!cmb.combine_ext) { \ T1_INTER_T0_USING_FACTOR ((rdp.prim_color&0xFF)); \ }\ else {\ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.t1c_ext_a = GR_CMBX_LOCAL_TEXTURE_RGB, \ cmb.t1c_ext_a_mode = GR_FUNC_MODE_ZERO, \ cmb.t1c_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB, \ cmb.t1c_ext_b_mode = GR_FUNC_MODE_ZERO, \ cmb.t1c_ext_c = GR_CMBX_ZERO, \ cmb.t1c_ext_c_invert = 0, \ cmb.t1c_ext_d= GR_CMBX_B, \ cmb.t1c_ext_d_invert = 0, \ cmb.t0c_ext_a = GR_CMBX_LOCAL_TEXTURE_RGB, \ cmb.t0c_ext_a_mode = GR_FUNC_MODE_X, \ cmb.t0c_ext_b = GR_CMBX_OTHER_TEXTURE_RGB, \ cmb.t0c_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X, \ cmb.t0c_ext_c = GR_CMBX_TMU_CCOLOR, \ cmb.t0c_ext_c_invert = 0, \ cmb.t0c_ext_d= GR_CMBX_B, \ cmb.t0c_ext_d_invert = 0, \ cmb.tex_ccolor = rdp.prim_color, \ cmb.tex_cmb_ext_use |= TEX_COMBINE_EXT_COLOR; \ } #define T0_INTER_T1_USING_ENV() \ if (!cmb.combine_ext) { \ T0_INTER_T1_USING_FACTOR ((rdp.env_color&0xFF)); \ }\ else {\ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.t1c_ext_a = GR_CMBX_LOCAL_TEXTURE_RGB, \ cmb.t1c_ext_a_mode = GR_FUNC_MODE_ZERO, \ cmb.t1c_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB, \ cmb.t1c_ext_b_mode = GR_FUNC_MODE_ZERO, \ cmb.t1c_ext_c = GR_CMBX_ZERO, \ cmb.t1c_ext_c_invert = 0, \ cmb.t1c_ext_d= GR_CMBX_B, \ cmb.t1c_ext_d_invert = 0, \ cmb.t0c_ext_a = GR_CMBX_OTHER_TEXTURE_RGB, \ cmb.t0c_ext_a_mode = GR_FUNC_MODE_X, \ cmb.t0c_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB, \ cmb.t0c_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X, \ cmb.t0c_ext_c = GR_CMBX_TMU_CCOLOR, \ cmb.t0c_ext_c_invert = 0, \ cmb.t0c_ext_d= GR_CMBX_B, \ cmb.t0c_ext_d_invert = 0, \ cmb.tex_ccolor = rdp.env_color, \ cmb.tex_cmb_ext_use |= TEX_COMBINE_EXT_COLOR; \ } #define T1_INTER_T0_USING_ENV() /* inverse of above */\ if (!cmb.combine_ext) { \ T1_INTER_T0_USING_FACTOR ((rdp.env_color&0xFF)); \ }\ else {\ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.t1c_ext_a = GR_CMBX_LOCAL_TEXTURE_RGB, \ cmb.t1c_ext_a_mode = GR_FUNC_MODE_ZERO, \ cmb.t1c_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB, \ cmb.t1c_ext_b_mode = GR_FUNC_MODE_ZERO, \ cmb.t1c_ext_c = GR_CMBX_ZERO, \ cmb.t1c_ext_c_invert = 0, \ cmb.t1c_ext_d= GR_CMBX_B, \ cmb.t1c_ext_d_invert = 0, \ cmb.t0c_ext_a = GR_CMBX_LOCAL_TEXTURE_RGB, \ cmb.t0c_ext_a_mode = GR_FUNC_MODE_X, \ cmb.t0c_ext_b = GR_CMBX_OTHER_TEXTURE_RGB, \ cmb.t0c_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X, \ cmb.t0c_ext_c = GR_CMBX_TMU_CCOLOR, \ cmb.t0c_ext_c_invert = 0, \ cmb.t0c_ext_d= GR_CMBX_B, \ cmb.t0c_ext_d_invert = 0, \ cmb.tex_ccolor = rdp.env_color, \ cmb.tex_cmb_ext_use |= TEX_COMBINE_EXT_COLOR; \ } #define T0_INTER_T1_USING_SHADEA() \ if (!cmb.combine_ext) { \ T0_INTER_T1_USING_FACTOR (0x7F); \ }\ else {\ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.t1c_ext_a = GR_CMBX_LOCAL_TEXTURE_RGB, \ cmb.t1c_ext_a_mode = GR_FUNC_MODE_ZERO, \ cmb.t1c_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB, \ cmb.t1c_ext_b_mode = GR_FUNC_MODE_ZERO, \ cmb.t1c_ext_c = GR_CMBX_ZERO, \ cmb.t1c_ext_c_invert = 0, \ cmb.t1c_ext_d= GR_CMBX_B, \ cmb.t1c_ext_d_invert = 0, \ cmb.t0c_ext_a = GR_CMBX_OTHER_TEXTURE_RGB, \ cmb.t0c_ext_a_mode = GR_FUNC_MODE_X, \ cmb.t0c_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB, \ cmb.t0c_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X, \ cmb.t0c_ext_c = GR_CMBX_ITALPHA, \ cmb.t0c_ext_c_invert = 0, \ cmb.t0c_ext_d= GR_CMBX_B, \ cmb.t0c_ext_d_invert = 0, \ cmb.tex_cmb_ext_use |= TEX_COMBINE_EXT_COLOR; \ } #define T1_INTER_T0_USING_SHADEA() \ if (!cmb.combine_ext) { \ T0_INTER_T1_USING_FACTOR (0x7F); \ }\ else {\ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.t1c_ext_a = GR_CMBX_LOCAL_TEXTURE_RGB, \ cmb.t1c_ext_a_mode = GR_FUNC_MODE_ZERO, \ cmb.t1c_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB, \ cmb.t1c_ext_b_mode = GR_FUNC_MODE_ZERO, \ cmb.t1c_ext_c = GR_CMBX_ZERO, \ cmb.t1c_ext_c_invert = 0, \ cmb.t1c_ext_d= GR_CMBX_B, \ cmb.t1c_ext_d_invert = 0, \ cmb.t0c_ext_a = GR_CMBX_LOCAL_TEXTURE_RGB, \ cmb.t0c_ext_a_mode = GR_FUNC_MODE_X, \ cmb.t0c_ext_b = GR_CMBX_OTHER_TEXTURE_RGB, \ cmb.t0c_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X, \ cmb.t0c_ext_c = GR_CMBX_ITALPHA, \ cmb.t0c_ext_c_invert = 0, \ cmb.t0c_ext_d= GR_CMBX_B, \ cmb.t0c_ext_d_invert = 0, \ cmb.tex_cmb_ext_use |= TEX_COMBINE_EXT_COLOR; \ } #define T1_SUB_T0() \ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.tmu1_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_func = GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL, \ cmb.tmu0_fac = GR_COMBINE_FACTOR_ONE #define T1_SUB_T0_MUL_T0() \ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.tmu1_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_func = GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL, \ cmb.tmu0_fac = GR_COMBINE_FACTOR_LOCAL #define T1_MUL_PRIMLOD_ADD_T0() \ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.tmu1_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_func = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, \ cmb.tmu0_fac = GR_COMBINE_FACTOR_DETAIL_FACTOR, \ percent = (float)(lod_frac) / 255.0f, \ cmb.dc0_detailmax = cmb.dc1_detailmax = percent #define T1_MUL_PRIMA_ADD_T0() \ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.tmu1_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_func = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, \ cmb.tmu0_fac = GR_COMBINE_FACTOR_DETAIL_FACTOR, \ percent = (float)(rdp.prim_color&0xFF) / 255.0f, \ cmb.dc0_detailmax = cmb.dc1_detailmax = percent #define T1_MUL_ENVA_ADD_T0() \ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.tmu1_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_func = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, \ cmb.tmu0_fac = GR_COMBINE_FACTOR_DETAIL_FACTOR, \ percent = (float)(rdp.env_color&0xFF) / 255.0f, \ cmb.dc0_detailmax = cmb.dc1_detailmax = percent #define T0_SUB_PRIM_MUL_PRIMLOD_ADD_T1() \ T0_ADD_T1 (); \ MOD_0 (TMOD_TEX_SUB_COL_MUL_FAC); \ MOD_0_COL (rdp.prim_color & 0xFFFFFF00); \ MOD_0_FAC (lod_frac & 0xFF); #define T1_SUB_PRIM_MUL_PRIMLOD_ADD_T0() \ if (cmb.combine_ext) \ { \ T1CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, \ GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_NEGATIVE_X, \ GR_CMBX_DETAIL_FACTOR, 0, \ GR_CMBX_ZERO, 0); \ T0CCMBEXT(GR_CMBX_OTHER_TEXTURE_RGB, GR_FUNC_MODE_X, \ GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, \ GR_CMBX_ZERO, 1, \ GR_CMBX_ZERO, 0); \ cmb.tex_ccolor = rdp.prim_color; \ cmb.tex |= 3; \ percent = (float)(lod_frac) / 255.0f; \ cmb.dc0_detailmax = cmb.dc1_detailmax = percent; \ } \ else \ { \ T0_ADD_T1 (); \ MOD_1 (TMOD_TEX_SUB_COL_MUL_FAC); \ MOD_1_COL (rdp.prim_color & 0xFFFFFF00); \ MOD_1_FAC (lod_frac & 0xFF); \ } #define PRIM_INTER_T0_USING_SHADEA() \ if (!cmb.combine_ext) { \ USE_T0 (); \ }\ else {\ rdp.best_tex = 0; \ cmb.tex |= 1, \ cmb.t0c_ext_a = GR_CMBX_LOCAL_TEXTURE_RGB, \ cmb.t0c_ext_a_mode = GR_FUNC_MODE_X, \ cmb.t0c_ext_b = GR_CMBX_TMU_CCOLOR, \ cmb.t0c_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X, \ cmb.t0c_ext_c = GR_CMBX_ITALPHA, \ cmb.t0c_ext_c_invert = 0, \ cmb.t0c_ext_d= GR_CMBX_B, \ cmb.t0c_ext_d_invert = 0, \ cmb.tex_ccolor = rdp.prim_color, \ cmb.tex_cmb_ext_use |= TEX_COMBINE_EXT_COLOR; \ } #define A_USE_T0() \ cmb.tex |= 1, \ cmb.tmu0_a_func = GR_COMBINE_FUNCTION_LOCAL #define A_USE_T1() \ if (num_tmu > 1) { \ cmb.tex |= 2, \ cmb.tmu1_a_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_a_func = GR_COMBINE_FUNCTION_SCALE_OTHER, \ cmb.tmu0_a_fac = GR_COMBINE_FACTOR_ONE; \ } \ else { \ A_USE_T0(); \ } #define A_T0_ADD_T1() \ cmb.tex |= 3, \ cmb.tmu1_a_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_a_func = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, \ cmb.tmu0_a_fac = GR_COMBINE_FACTOR_ONE #define A_T0_SUB_T1() \ cmb.tex |= 3, \ cmb.tmu1_a_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_a_func = GR_COMBINE_FUNCTION_BLEND_LOCAL, \ cmb.tmu0_a_fac = GR_COMBINE_FACTOR_OTHER_ALPHA #define A_T0_MUL_T1() \ cmb.tex |= 3, \ cmb.tmu1_a_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_a_func = GR_COMBINE_FUNCTION_SCALE_OTHER, \ cmb.tmu0_a_fac = GR_COMBINE_FACTOR_LOCAL #define A_T0_INTER_T1_USING_T0A() \ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.tmu1_a_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_a_func = GR_COMBINE_FUNCTION_BLEND, \ cmb.tmu0_a_fac = GR_COMBINE_FACTOR_LOCAL_ALPHA #define A_T1_INTER_T0_USING_T0A() \ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.tmu1_a_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_a_func = GR_COMBINE_FUNCTION_BLEND, \ cmb.tmu0_a_fac = GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA #define A_T0_INTER_T1_USING_T1A() \ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.tmu1_a_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_a_func = GR_COMBINE_FUNCTION_BLEND, \ cmb.tmu0_a_fac = GR_COMBINE_FACTOR_OTHER_ALPHA #define A_T0_INTER_T1_USING_FACTOR(factor) \ if (factor == 0xFF) { \ A_USE_T1(); \ } \ else if (factor == 0x00) { \ A_USE_T0(); \ }\ else { \ cmb.tex |= 3, \ cmb.tmu1_a_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_a_func = GR_COMBINE_FUNCTION_BLEND, \ cmb.tmu0_a_fac = GR_COMBINE_FACTOR_DETAIL_FACTOR, \ percent = (float)factor / 255.0f, \ cmb.dc0_detailmax = cmb.dc1_detailmax = percent; \ } #define A_T1_INTER_T0_USING_FACTOR(factor) /* inverse of above */\ if (factor == 0xFF) { \ A_USE_T0(); \ } \ else if (factor == 0x00) { \ A_USE_T1(); \ }\ else { \ cmb.tex |= 3, \ cmb.tmu1_a_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_a_func = GR_COMBINE_FUNCTION_BLEND, \ cmb.tmu0_a_fac = GR_COMBINE_FACTOR_DETAIL_FACTOR, \ percent = (255 - factor) / 255.0f, \ cmb.dc0_detailmax = cmb.dc1_detailmax = percent; \ } #define A_T0_INTER_T1_USING_SHADEA() \ if (!cmb.combine_ext) { \ A_T0_INTER_T1_USING_FACTOR (0x7F); \ }\ else {\ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.t1a_ext_a = GR_CMBX_LOCAL_TEXTURE_ALPHA, \ cmb.t1a_ext_a_mode = GR_FUNC_MODE_ZERO, \ cmb.t1a_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA, \ cmb.t1a_ext_b_mode = GR_FUNC_MODE_ZERO, \ cmb.t1a_ext_c = GR_CMBX_ZERO, \ cmb.t1a_ext_c_invert = 0, \ cmb.t1a_ext_d= GR_CMBX_B, \ cmb.t1a_ext_d_invert = 0, \ cmb.t0a_ext_a = GR_CMBX_OTHER_TEXTURE_ALPHA, \ cmb.t0a_ext_a_mode = GR_FUNC_MODE_X, \ cmb.t0a_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA, \ cmb.t0a_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X, \ cmb.t0a_ext_c = GR_CMBX_ITALPHA, \ cmb.t0a_ext_c_invert = 0, \ cmb.t0a_ext_d= GR_CMBX_B, \ cmb.t0a_ext_d_invert = 0, \ cmb.tex_cmb_ext_use |= TEX_COMBINE_EXT_ALPHA; \ } #define A_T1_MUL_PRIMLOD_ADD_T0() \ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.tmu1_a_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_a_func = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, \ cmb.tmu0_a_fac = GR_COMBINE_FACTOR_DETAIL_FACTOR, \ percent = (float)(lod_frac) / 255.0f, \ cmb.dc0_detailmax = cmb.dc1_detailmax = percent #define A_T1_MUL_PRIMA_ADD_T0() \ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.tmu1_a_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_a_func = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, \ cmb.tmu0_a_fac = GR_COMBINE_FACTOR_DETAIL_FACTOR, \ percent = (float)(rdp.prim_color&0xFF) / 255.0f, \ cmb.dc0_detailmax = cmb.dc1_detailmax = percent #define A_T1_MUL_ENVA_ADD_T0() \ rdp.best_tex = 0; \ cmb.tex |= 3, \ cmb.tmu1_a_func = GR_COMBINE_FUNCTION_LOCAL, \ cmb.tmu0_a_func = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, \ cmb.tmu0_a_fac = GR_COMBINE_FACTOR_DETAIL_FACTOR, \ percent = (float)(rdp.env_color&0xFF) / 255.0f, \ cmb.dc0_detailmax = cmb.dc1_detailmax = percent // UNIMP - writes to the unimplemented log, if it's enabled #ifdef UNIMP_LOG #define UNIMPMODE() { \ std::ofstream unimp; \ unimp.open("unimp.txt", std::ios::app); \ unimp << out_buf; \ unimp.close(); \ } #else #define UNIMPMODE() #endif // Bright red, sets up a bright red combine #ifdef BRIGHT_RED // Bright red, sets up a bright red combine during the alpha stage #define BrightRed() { \ CCMB (GR_COMBINE_FUNCTION_LOCAL, \ GR_COMBINE_FACTOR_NONE, \ GR_COMBINE_LOCAL_CONSTANT, \ GR_COMBINE_OTHER_NONE); \ ACMB (GR_COMBINE_FUNCTION_LOCAL, \ GR_COMBINE_FACTOR_NONE, \ GR_COMBINE_LOCAL_CONSTANT, \ GR_COMBINE_OTHER_NONE); \ cmb.ccolor = 0xFF0000FF; \ } #else #define BrightRed() #endif #define CC(x) cmb.ccolor=(x)&0xFFFFFF00 #define CC_PRIM() cmb.ccolor=rdp.prim_color&0xFFFFFF00 #define CC_PRIMA() { cmb.ccolor=rdp.prim_color&0xFF; cmb.ccolor=(cmb.ccolor<<8)|(cmb.ccolor<<16)|(cmb.ccolor<<24); } #define CC_1SUBPRIMA() { cmb.ccolor=(~rdp.prim_color)&0xFF; cmb.ccolor=(cmb.ccolor<<8)|(cmb.ccolor<<16)|(cmb.ccolor<<24); } #define CC_1SUBPRIM() cmb.ccolor=(~rdp.prim_color)&0xFFFFFF00 #define CC_ENV() cmb.ccolor=rdp.env_color&0xFFFFFF00 #define CC_1SUBENV() cmb.ccolor=(~rdp.env_color)&0xFFFFFF00 #define CC_ENVA() { cmb.ccolor=rdp.env_color&0xFF; cmb.ccolor=(cmb.ccolor<<8)|(cmb.ccolor<<16)|(cmb.ccolor<<24); } #define CC_PRIMLOD() { cmb.ccolor = (lod_frac<<24) | (lod_frac<<16) | (lod_frac<<8); } #define CC_K5() { cmb.ccolor = (rdp.K5<<24) | (rdp.K5<<16) | (rdp.K5<<8); } #define CC_PRIMMULENV() { \ cmb.ccolor=(BYTE)( ((rdp.prim_color & 0xFF000000) >> 24) * (((rdp.env_color & 0xFF000000) >> 24) /255.0f) ) << 24 | \ (BYTE)( ((rdp.prim_color & 0x00FF0000) >> 16) * (((rdp.env_color & 0x00FF0000) >> 16) /255.0f) ) << 16 | \ (BYTE)( ((rdp.prim_color & 0x0000FF00) >> 8) * (((rdp.env_color & 0x0000FF00) >> 8) /255.0f) ) << 8 ; \ } #define CC_PRIMSUBENV() { \ cmb.ccolor=(BYTE)( ((rdp.prim_color & 0xFF000000) >> 24) - (((rdp.env_color & 0xFF000000) >> 24) ) ) << 24 | \ (BYTE)( ((rdp.prim_color & 0x00FF0000) >> 16) - (((rdp.env_color & 0x00FF0000) >> 16) ) ) << 16 | \ (BYTE)( ((rdp.prim_color & 0x0000FF00) >> 8) - (((rdp.env_color & 0x0000FF00) >> 8) ) ) << 8 ; \ } #define MULSHADE(color) { \ rdp.col[0] *= (float)((color & 0xFF000000) >> 24) / 255.0f; \ rdp.col[1] *= (float)((color & 0x00FF0000) >> 16) / 255.0f; \ rdp.col[2] *= (float)((color & 0x0000FF00) >> 8) / 255.0f; \ rdp.cmb_flags |= CMB_MULT; \ } #define MULSHADE_PRIM() { \ rdp.col[0] *= (float)((rdp.prim_color & 0xFF000000) >> 24) / 255.0f; \ rdp.col[1] *= (float)((rdp.prim_color & 0x00FF0000) >> 16) / 255.0f; \ rdp.col[2] *= (float)((rdp.prim_color & 0x0000FF00) >> 8) / 255.0f; \ rdp.cmb_flags |= CMB_MULT; \ } #define MULSHADE_PRIMA() { \ rdp.col[0] *= (float)(rdp.prim_color & 0xFF) / 255.0f; \ rdp.col[1] *= (float)(rdp.prim_color & 0xFF) / 255.0f; \ rdp.col[2] *= (float)(rdp.prim_color & 0xFF) / 255.0f; \ rdp.cmb_flags |= CMB_MULT; \ } #define MULSHADE_ENV() { \ rdp.col[0] *= (float)((rdp.env_color & 0xFF000000) >> 24) / 255.0f; \ rdp.col[1] *= (float)((rdp.env_color & 0x00FF0000) >> 16) / 255.0f; \ rdp.col[2] *= (float)((rdp.env_color & 0x0000FF00) >> 8) / 255.0f; \ rdp.cmb_flags |= CMB_MULT; \ } #define MULSHADE_ENVA() { \ rdp.col[0] *= (float)(rdp.env_color & 0xFF) / 255.0f; \ rdp.col[1] *= (float)(rdp.env_color & 0xFF) / 255.0f; \ rdp.col[2] *= (float)(rdp.env_color & 0xFF) / 255.0f; \ rdp.cmb_flags |= CMB_MULT; \ } #define MULSHADE_1MPRIM() { \ rdp.col[0] *= 1.0f-((float)((rdp.prim_color & 0xFF000000) >> 24)/255.0f); \ rdp.col[1] *= 1.0f-((float)((rdp.prim_color & 0x00FF0000) >> 16)/255.0f); \ rdp.col[2] *= 1.0f-((float)((rdp.prim_color & 0x0000FF00) >> 8)/255.0f); \ rdp.cmb_flags |= CMB_MULT; \ } #define MULSHADE_1MENV() { \ rdp.col[0] *= 1.0f-((float)((rdp.env_color & 0xFF000000) >> 24)/255.0f); \ rdp.col[1] *= 1.0f-((float)((rdp.env_color & 0x00FF0000) >> 16)/255.0f); \ rdp.col[2] *= 1.0f-((float)((rdp.env_color & 0x0000FF00) >> 8)/255.0f); \ rdp.cmb_flags |= CMB_MULT; \ } //Added by Gonetz #define MULSHADE_PRIMSUBENV() { \ rdp.col[0] *= (float)( ((rdp.prim_color & 0xFF000000) >> 24) - ((rdp.env_color & 0xFF000000) >> 24) )/255.0f; \ rdp.col[1] *= (float)( ((rdp.prim_color & 0x00FF0000) >> 16) - ((rdp.env_color & 0x00FF0000) >> 16) )/255.0f; \ rdp.col[2] *= (float)( ((rdp.prim_color & 0x0000FF00) >> 8) - ((rdp.env_color & 0x0000FF00) >> 8) )/255.0f; \ rdp.cmb_flags |= CMB_MULT; \ } //Added by Gonetz #define MULSHADE_ENVSUBPRIM() { \ rdp.col[0] *= (float)( ((rdp.env_color & 0xFF000000) >> 24) - ((rdp.prim_color & 0xFF000000) >> 24) )/255.0f; \ rdp.col[1] *= (float)( ((rdp.env_color & 0x00FF0000) >> 16) - ((rdp.prim_color & 0x00FF0000) >> 16) )/255.0f; \ rdp.col[2] *= (float)( ((rdp.env_color & 0x0000FF00) >> 8) - ((rdp.prim_color & 0x0000FF00) >> 8) )/255.0f; \ rdp.cmb_flags |= CMB_MULT; \ } //Added by Gonetz #define MULSHADE_PRIMLOD() { \ rdp.col[0] *= (float)(lod_frac & 0xFF) / 255.0f; \ rdp.col[1] *= (float)(lod_frac & 0xFF) / 255.0f; \ rdp.col[2] *= (float)(lod_frac & 0xFF) / 255.0f; \ rdp.cmb_flags |= CMB_MULT; \ } //Added by Gonetz #define MULSHADE_K5() { \ rdp.col[0] *= (float)rdp.K5 / 255.0f; \ rdp.col[1] *= (float)rdp.K5 / 255.0f; \ rdp.col[2] *= (float)rdp.K5 / 255.0f; \ rdp.cmb_flags |= CMB_MULT; \ } #define MULSHADE_SHADEA() rdp.cmb_flags |= CMB_MULT_OWN_ALPHA; #define SUBSHADE_PRIM() { \ rdp.coladd[0] *= (float)((rdp.prim_color & 0xFF000000) >> 24) / 255.0f; \ rdp.coladd[1] *= (float)((rdp.prim_color & 0x00FF0000) >> 16) / 255.0f; \ rdp.coladd[2] *= (float)((rdp.prim_color & 0x0000FF00) >> 8) / 255.0f; \ rdp.cmb_flags |= CMB_SUB; \ } #define SUBSHADE_ENV() { \ rdp.coladd[0] *= (float)((rdp.env_color & 0xFF000000) >> 24) / 255.0f; \ rdp.coladd[1] *= (float)((rdp.env_color & 0x00FF0000) >> 16) / 255.0f; \ rdp.coladd[2] *= (float)((rdp.env_color & 0x0000FF00) >> 8) / 255.0f; \ rdp.cmb_flags |= CMB_SUB; \ } #define SUBSHADE_PRIMSUBENV() { \ rdp.coladd[0] *= (float)( ((rdp.prim_color & 0xFF000000) >> 24) - ((rdp.env_color & 0xFF000000) >> 24) )/255.0f; \ rdp.coladd[1] *= (float)( ((rdp.prim_color & 0x00FF0000) >> 16) - ((rdp.env_color & 0x00FF0000) >> 16) )/255.0f; \ rdp.coladd[2] *= (float)( ((rdp.prim_color & 0x0000FF00) >> 8) - ((rdp.env_color & 0x0000FF00) >> 8) )/255.0f; \ rdp.cmb_flags |= CMB_SUB; \ } #define SUBSHADE_PRIMMULENV() { \ rdp.coladd[0] *= (float)( ((rdp.prim_color & 0xFF000000) >> 24) * ((rdp.env_color & 0xFF000000) >> 24) )/255.0f; \ rdp.coladd[1] *= (float)( ((rdp.prim_color & 0x00FF0000) >> 16) * ((rdp.env_color & 0x00FF0000) >> 16) )/255.0f; \ rdp.coladd[2] *= (float)( ((rdp.prim_color & 0x0000FF00) >> 8) * ((rdp.env_color & 0x0000FF00) >> 8) )/255.0f; \ rdp.cmb_flags |= CMB_SUB; \ } #define ADDSHADE_PRIM() { \ rdp.coladd[0] *= (float)((rdp.prim_color & 0xFF000000) >> 24) / 255.0f; \ rdp.coladd[1] *= (float)((rdp.prim_color & 0x00FF0000) >> 16) / 255.0f; \ rdp.coladd[2] *= (float)((rdp.prim_color & 0x0000FF00) >> 8) / 255.0f; \ rdp.cmb_flags |= CMB_ADD; \ } #define ADDSHADE_ENV() { \ rdp.coladd[0] *= (float)((rdp.env_color & 0xFF000000) >> 24) / 255.0f; \ rdp.coladd[1] *= (float)((rdp.env_color & 0x00FF0000) >> 16) / 255.0f; \ rdp.coladd[2] *= (float)((rdp.env_color & 0x0000FF00) >> 8) / 255.0f; \ rdp.cmb_flags |= CMB_ADD; \ } #define ADDSHADE_PRIMSUBENV() { \ rdp.coladd[0] *= (float)( ((rdp.prim_color & 0xFF000000) >> 24) - ((rdp.env_color & 0xFF000000) >> 24) )/255.0f; \ rdp.coladd[1] *= (float)( ((rdp.prim_color & 0x00FF0000) >> 16) - ((rdp.env_color & 0x00FF0000) >> 16) )/255.0f; \ rdp.coladd[2] *= (float)( ((rdp.prim_color & 0x0000FF00) >> 8) - ((rdp.env_color & 0x0000FF00) >> 8) )/255.0f; \ rdp.cmb_flags |= CMB_ADD; \ } #define COLSUBSHADE_PRIM() { \ rdp.coladd[0] *= (float)((rdp.prim_color & 0xFF000000) >> 24) / 255.0f; \ rdp.coladd[1] *= (float)((rdp.prim_color & 0x00FF0000) >> 16) / 255.0f; \ rdp.coladd[2] *= (float)((rdp.prim_color & 0x0000FF00) >> 8) / 255.0f; \ rdp.cmb_flags |= CMB_COL_SUB_OWN; \ } #define SETSHADE_PRIM() { \ rdp.col[0] *= (float)((rdp.prim_color & 0xFF000000) >> 24) / 255.0f; \ rdp.col[1] *= (float)((rdp.prim_color & 0x00FF0000) >> 16) / 255.0f; \ rdp.col[2] *= (float)((rdp.prim_color & 0x0000FF00) >> 8) / 255.0f; \ rdp.cmb_flags = CMB_SET; \ } #define SETSHADE_ENV() { \ rdp.col[0] *= (float)((rdp.env_color & 0xFF000000) >> 24) / 255.0f; \ rdp.col[1] *= (float)((rdp.env_color & 0x00FF0000) >> 16) / 255.0f; \ rdp.col[2] *= (float)((rdp.env_color & 0x0000FF00) >> 8) / 255.0f; \ rdp.cmb_flags = CMB_SET; \ } #define SETSHADE_1MPRIM() { \ rdp.col[0] *= 1.0f-((float)((rdp.prim_color & 0xFF000000) >> 24)/255.0f); \ rdp.col[1] *= 1.0f-((float)((rdp.prim_color & 0x00FF0000) >> 16)/255.0f); \ rdp.col[2] *= 1.0f-((float)((rdp.prim_color & 0x0000FF00) >> 8)/255.0f); \ rdp.cmb_flags = CMB_SET; \ } #define SETSHADE_1MENV() { \ rdp.col[0] *= 1.0f-((float)((rdp.env_color & 0xFF000000) >> 24)/255.0f); \ rdp.col[1] *= 1.0f-((float)((rdp.env_color & 0x00FF0000) >> 16)/255.0f); \ rdp.col[2] *= 1.0f-((float)((rdp.env_color & 0x0000FF00) >> 8)/255.0f); \ rdp.cmb_flags = CMB_SET; \ } #define SETSHADE_PRIMA() { \ rdp.col[0] *= (float)(rdp.prim_color & 0xFF) / 255.0f; \ rdp.col[1] *= (float)(rdp.prim_color & 0xFF) / 255.0f; \ rdp.col[2] *= (float)(rdp.prim_color & 0xFF) / 255.0f; \ rdp.cmb_flags = CMB_SET; \ } #define SETSHADE_1MPRIMA() { \ rdp.col[0] *= (float)((~rdp.prim_color) & 0xFF) / 255.0f; \ rdp.col[1] *= (float)((~rdp.prim_color) & 0xFF) / 255.0f; \ rdp.col[2] *= (float)((~rdp.prim_color) & 0xFF) / 255.0f; \ rdp.cmb_flags = CMB_SET; \ } #define SETSHADE_PRIMSUBENV() { \ rdp.col[0] *= (float)( ((rdp.prim_color & 0xFF000000) >> 24) - ((rdp.env_color & 0xFF000000) >> 24) )/255.0f; \ rdp.col[1] *= (float)( ((rdp.prim_color & 0x00FF0000) >> 16) - ((rdp.env_color & 0x00FF0000) >> 16) )/255.0f; \ rdp.col[2] *= (float)( ((rdp.prim_color & 0x0000FF00) >> 8) - ((rdp.env_color & 0x0000FF00) >> 8) )/255.0f; \ rdp.cmb_flags = CMB_SET; \ } #define SETSHADE_ENVSUBPRIM() { \ rdp.col[0] *= (float)( ((rdp.env_color & 0xFF000000) >> 24) - ((rdp.prim_color & 0xFF000000) >> 24) )/255.0f; \ rdp.col[1] *= (float)( ((rdp.env_color & 0x00FF0000) >> 16) - ((rdp.prim_color & 0x00FF0000) >> 16) )/255.0f; \ rdp.col[2] *= (float)( ((rdp.env_color & 0x0000FF00) >> 8) - ((rdp.prim_color & 0x0000FF00) >> 8) )/255.0f; \ rdp.cmb_flags = CMB_SET; \ } #define SETSHADE_PRIMLOD() { \ rdp.col[0] *= (float)(lod_frac & 0xFF) / 255.0f; \ rdp.col[1] *= (float)(lod_frac & 0xFF) / 255.0f; \ rdp.col[2] *= (float)(lod_frac & 0xFF) / 255.0f; \ rdp.cmb_flags = CMB_SET; \ } #define SETSHADE_1MPRIMLOD() { \ rdp.col[0] *= (float)(~lod_frac & 0xFF) / 255.0f; \ rdp.col[1] *= (float)(~lod_frac & 0xFF) / 255.0f; \ rdp.col[2] *= (float)(~lod_frac & 0xFF) / 255.0f; \ rdp.cmb_flags = CMB_SET; \ } #define SETSHADE_SHADE_A() { \ rdp.cmb_flags = CMB_SETSHADE_SHADEALPHA; \ } #define INTERSHADE_2(color,factor) { \ rdp.col_2[0] = (((color) >> 24) & 0xFF) / 255.0f; \ rdp.col_2[1] = (((color) >> 16) & 0xFF) / 255.0f; \ rdp.col_2[2] = (((color) >> 8) & 0xFF) / 255.0f; \ rdp.shade_factor = (factor) / 255.0f; \ rdp.cmb_flags_2 = CMB_INTER; \ } #define CA(x) cmb.ccolor|=(x)&0xFF #define CA_PRIM() cmb.ccolor|=rdp.prim_color&0xFF #define CA_INVPRIM() cmb.ccolor|=0xFF-(rdp.prim_color&0xFF) #define CA_INVENV() cmb.ccolor|=0xFF-(rdp.env_color&0xFF) #define CA_ENV() cmb.ccolor|=rdp.env_color&0xFF #define CA_ENV1MPRIM() cmb.ccolor|= (DWORD)(((rdp.env_color&0xFF)/255.0f) * (((~(rdp.prim_color&0xFF)) & 0xff)/255.0f) * 255.0f); #define CA_PRIMENV() cmb.ccolor |= (DWORD)(((rdp.env_color&0xFF)/255.0f) * ((rdp.prim_color&0xFF)/255.0f) * 255.0f); #define CA_PRIMLOD() cmb.ccolor |= lod_frac; #define CA_PRIM_MUL_PRIMLOD() cmb.ccolor |= (int)(((rdp.prim_color&0xFF) * lod_frac) / 255.0f); #define CA_ENV_MUL_PRIMLOD() cmb.ccolor |= (int)(((rdp.env_color&0xFF) * lod_frac) / 255.0f); #define MULSHADE_A_PRIM() { \ rdp.col[3] *= (float)(rdp.prim_color & 0xFF) / 255.0f; \ rdp.cmb_flags |= CMB_A_MULT; \ } #define MULSHADE_A_1MPRIM() { \ rdp.col[3] *= 1.0f-((float)(rdp.prim_color & 0xFF) / 255.0f); \ rdp.cmb_flags |= CMB_A_MULT; \ } #define MULSHADE_A_ENV() { \ rdp.col[3] *= (float)(rdp.env_color & 0xFF) / 255.0f; \ rdp.cmb_flags |= CMB_A_MULT; \ } //Added by Gonetz #define MULSHADE_A_PRIMSUBENV() { \ rdp.col[3] *= (float)( (rdp.prim_color & 0xFF) - (rdp.env_color & 0xFF) ) / 255.0f; \ rdp.cmb_flags |= CMB_A_MULT; \ } //Added by Gonetz #define MULSHADE_A_ENVSUBPRIM() { \ rdp.col[3] *= (float)( (rdp.env_color & 0xFF) - (rdp.prim_color & 0xFF) ) / 255.0f; \ rdp.cmb_flags |= CMB_A_MULT; \ } #define SETSHADE_A(color) { \ rdp.col[3] *= (float)(color&0xFF)/255.0f; \ rdp.cmb_flags |= CMB_A_SET; \ } #define SETSHADE_A_PRIM() { \ rdp.col[3] *= (float)(rdp.prim_color & 0xFF) / 255.0f; \ rdp.cmb_flags |= CMB_A_SET; \ } #define SETSHADE_A_ENV() { \ rdp.col[3] *= (float)(rdp.env_color & 0xFF) / 255.0f; \ rdp.cmb_flags |= CMB_A_SET; \ } #define SETSHADE_A_INVENV() { \ rdp.col[3] *= (float)(0xFF - (rdp.env_color & 0xFF)) / 255.0f; \ rdp.cmb_flags |= CMB_A_SET; \ } #define SUBSHADE_A_PRIM() { \ rdp.coladd[3] *= (float)(rdp.prim_color & 0xFF) / 255.0f; \ rdp.cmb_flags |= CMB_A_SUB; \ } #define SUBSHADE_A_ENV() { \ rdp.coladd[3] *= (float)(rdp.env_color & 0xFF) / 255.0f; \ rdp.cmb_flags |= CMB_A_SUB; \ } #define ADDSHADE_A_PRIM() { \ rdp.coladd[3] *= (float)(rdp.prim_color & 0xFF) / 255.0f; \ rdp.cmb_flags |= CMB_A_ADD; \ } #define ADDSHADE_A_ENV() { \ rdp.coladd[3] *= (float)(rdp.env_color & 0xFF) / 255.0f; \ rdp.cmb_flags |= CMB_A_ADD; \ } //**************************************************************** // Combine Functions //**************************************************************** // These are in a somewhat ordered way, using the A constants below. T0 comes before // T1 comes before PRIM, ... except for CMB, which always comes at the end, where // the CMB comes first in the name. T0 and T1 are always interleaved, because they use the // same function. // Keep going in alphabetical order, but do not break the order of variables! // ex: A*C + B*C -> T0_MUL_PRIM_ADD_ENV_MUL_PRIM, // Although prim comes before env, we have already used prim as C, so it must stay as C // and would NOT become T0_MUL_PRIM_ADD_PRIM_MUL_ENV // // New version ordered by: // t0 // prim // env // shade static void cc_one () { CCMB (GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE); // CC (0xFFFFFF00); CC (0xFFFFFF00); } static void cc_zero () { CCMB (GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE); CC (0x00000000); } static void cc_t0 () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); USE_T0 (); } static void cc_t1 () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); USE_T1 (); } static void cc_t0_mul_t1 () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); T0_MUL_T1 (); } static void cc_t0_mul_t1_add_t0 () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); T0_MUL_T1_ADD_T0 (); } static void cc_t1_inter_t0_using_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); T1_INTER_T0_USING_ENV (); } static void cc_prim () { CCMB (GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE); CC_PRIM (); } static void cc_env () { CCMB (GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE); CC_ENV (); } static void cc_shade () { CCMB (GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_NONE); } static void cc_shadea () { CCMB (GR_COMBINE_FUNCTION_LOCAL_ALPHA, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_NONE); } static void cc_t0_mul_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); USE_T0 (); } static void cc_t0_mul_prima () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIMA (); USE_T0 (); } static void cc_t1_mul_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); USE_T1 (); } //Added by Gonetz static void cc__t1_inter_t0_using_enva__mul_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); BYTE factor = (BYTE)(rdp.env_color&0xFF); T1_INTER_T0_USING_FACTOR (factor); } static void cc__t1_inter_one_using_env__mul_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); if (cmb.combine_ext) { T1CCMBEXT(GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_RGB, 1, GR_CMBX_B, 0); T0CCMBEXT(GR_CMBX_OTHER_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 1, GR_CMBX_ZERO, 0); cmb.tex |= 2; cmb.tex_ccolor = rdp.env_color; } else { USE_T1 (); } } //Added by Gonetz static void cc_prim_mul_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); SETSHADE_PRIM (); } static void cc_prim_mul_prima () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIM (); SETSHADE_PRIMA (); } static void cc_t1_mul_prima () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIMA (); USE_T1 (); } static void cc_t1_mul_enva () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_ENVA (); USE_T1 (); } static void cc_t0_mul_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_ENV (); USE_T0 (); } static void cc_t1_mul_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_ENV (); USE_T1 (); } //Added by Gonetz static void cc_t0_mul_enva () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_ENVA (); USE_T0 (); } static void cc_t0_mul_enva_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); SETSHADE_PRIM (); CC_ENVA (); USE_T0 (); } static void cc_t0_mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); USE_T0 (); } static void cc_t0_mul_shadea () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); SETSHADE_SHADE_A (); USE_T0 (); } static void cc_t0_mul_k5 () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_K5 (); USE_T0 (); } static void cc_t1_mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); USE_T1 (); } //Added by Gonetz static void cc__t0_add_t1__mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); T0_ADD_T1 (); } //Added by Gonetz static void cc__t1_inter_t0_using_enva__mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); BYTE factor = (BYTE)(rdp.env_color&0xFF); T1_INTER_T0_USING_FACTOR (factor); } //Added by Gonetz static void cc__t1_inter_t0_using_shadea__mul_shade () { if (!cmb.combine_ext) { cc_t0_mul_shade (); return; } CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_ITALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_ITRGB, 0, GR_CMBX_ZERO, 0); T1_INTER_T0_USING_SHADEA (); } //Added by Gonetz static void cc__t0_inter_env_using_enva__mul_shade () { // (env-t0)*env_a+t0, (cmb-0)*shade+0 CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); if (cmb.combine_ext) { T0CCMBEXT(GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_TMU_CALPHA, 0, GR_CMBX_B, 0); cmb.tex |= 1; cmb.tex_ccolor = rdp.env_color; } else { USE_T0 (); MOD_0 (TMOD_TEX_INTER_COLOR_USING_FACTOR); MOD_0_COL (rdp.env_color & 0xFFFFFF00); MOD_0_FAC (rdp.env_color&0xFF); } } static void cc__t1_sub_t0_mul_primlod_add_prim__mul_shade () { if (cmb.combine_ext) { T1CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_B, 0); T0CCMBEXT(GR_CMBX_OTHER_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_DETAIL_FACTOR, 0, GR_CMBX_ZERO, 0); cmb.tex |= 3; percent = (float)lod_frac / 255.0f; cmb.dc0_detailmax = cmb.dc1_detailmax = percent; CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_X, GR_CMBX_ITRGB, 0, GR_CMBX_ZERO, 0); CC_PRIM (); } else { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); T0_INTER_T1_USING_FACTOR (lod_frac); } } static void cc__t1_sub_prim_mul_t0__mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); if (cmb.combine_ext) { T1CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_B, 0); T0CCMBEXT(GR_CMBX_OTHER_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_LOCAL_TEXTURE_RGB, 0, GR_CMBX_ZERO, 0); cmb.tex_ccolor = rdp.prim_color; cmb.tex |= 3; } else { T0_MUL_T1 (); } } static void cc__t1_sub_t0_mul_t0_add_shade__mul_shade () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); if (cmb.combine_ext) { T1CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_B, 0); T0CCMBEXT(GR_CMBX_OTHER_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_LOCAL_TEXTURE_RGB, 0, GR_CMBX_ITRGB, 0); cmb.tex |= 3; } else { T1_SUB_T0_MUL_T0 (); } } static void cc__t0_mul_prima_add_prim_mul__shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); if (cmb.combine_ext) { T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_ZERO, GR_CMBX_TMU_CALPHA, 0, GR_CMBX_B, 0); cmb.tex_ccolor = rdp.prim_color; cmb.tex |= 1; } else { MOD_0 (TMOD_TEX_SCALE_FAC_ADD_COL); MOD_0_COL (rdp.prim_color & 0xFFFFFF00); MOD_0_FAC (rdp.prim_color & 0xFF); USE_T0 (); } } static void cc__prim_inter_t0_using_shadea__mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); PRIM_INTER_T0_USING_SHADEA (); } //Added by Gonetz static void cc_prim_mul_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); SETSHADE_ENV (); } static void cc_prim_mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); } static void cc_prim_mul_shadea () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); SETSHADE_SHADE_A (); CC_PRIM (); } static void cc_env_mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); } static void cc_env_mul_enva () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_OTHER_ALPHA, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); CA_ENV (); } // ** A+B ** static void cc_t0_add_t1 () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); T0_ADD_T1 (); } static void cc_t0_add_prim () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); USE_T0 (); } static void cc__t0_mul_t1__add_prim () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); T0_MUL_T1 (); } static void cc_t0_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_ENV (); USE_T0 (); } //Added by Gonetz static void cc__t0_mul_t1__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_ENV (); T0_MUL_T1 (); } static void cc_t0_add_shade () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); USE_T0 (); } static void cc_prim_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); SETSHADE_PRIM (); } static void cc_t0_add_prim_mul_one_sub_t0_add_t0 () //Aded by Gonetz { if (cmb.combine_ext) { T0CCMBEXT(GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_RGB, 1, GR_CMBX_B, 0); CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_ZERO, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 1, GR_CMBX_ZERO, 0); cmb.tex_ccolor = rdp.prim_color; cmb.tex |= 1; } else { cc_t0_add_prim (); } } static void cc_one_sub_prim_mul_t0_add_prim(); static void cc__one_sub_prim_mul_t0_add_prim__mul_prima_add__one_sub_prim_mul_t0_add_prim () //Aded by Gonetz { if (cmb.combine_ext) { T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_ZERO, GR_CMBX_TMU_CCOLOR, 1, GR_CMBX_B, 0); CCMBEXT(GR_CMBX_ZERO, GR_FUNC_MODE_ZERO, GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_CONSTANT_COLOR, 0, GR_CMBX_B, 0); cmb.tex_ccolor = rdp.prim_color; CC_PRIMA(); cmb.tex |= 3; //hw frame buffer allocated as tile1, but not used in combiner } else { cc_one_sub_prim_mul_t0_add_prim(); // cc_t0 (); } } static void cc_prim_add_shade () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); } static void cc_env_add_shade () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); } // ** A-B ** static void cc__t0_inter_t1_using_enva__sub_env () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_ENV (); BYTE factor = (BYTE)(rdp.env_color&0xFF); T0_INTER_T1_USING_FACTOR (factor); } static void cc_t0_sub_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); USE_T0 (); } // ** A-B*C ** static void cc_env_sub__t0_sub_t1_mul_primlod__mul_prim () //Aded by Gonetz { if (cmb.combine_ext) { T1CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_B, 0); T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_OTHER_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_ITRGB, 0, GR_CMBX_ZERO, 0); cmb.tex |= 3; CCMBEXT(GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_X, GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_ZERO, 1, GR_CMBX_ZERO, 0); SETSHADE_PRIM (); MULSHADE_PRIMLOD (); CC_ENV (); } else { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SETSHADE_PRIM (); CC_ENV (); T1_INTER_T0_USING_FACTOR (lod_frac); } } static void cc_one_sub__one_sub_t0_mul_enva_add_prim__mul_prim () //Aded by Gonetz { if (cmb.combine_ext) { T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ONE_MINUS_X, GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_ZERO, GR_CMBX_DETAIL_FACTOR, 0, GR_CMBX_B, 0); cmb.tex_ccolor = rdp.prim_color; cmb.tex |= 1; percent = (float)(rdp.env_color&0xFF) / 255.0f; cmb.dc0_detailmax = cmb.dc1_detailmax = percent; CCMBEXT(GR_CMBX_ZERO, GR_FUNC_MODE_X, GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_CONSTANT_COLOR, 0, GR_CMBX_ZERO, 1); CC_PRIM (); } else { cc_one (); } } // ** A+B*C ** //Aded by Gonetz static void cc_t0_add_env_mul_k5 () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); float scale = rdp.K5 / 255.0f; BYTE r = (BYTE)(rdp.env_color >> 24) & 0xFF; r = (BYTE)(r*scale); BYTE g = (BYTE)(rdp.env_color >> 16) & 0xFF; g = (BYTE)(g*scale); BYTE b = (BYTE)(rdp.env_color >> 8) & 0xFF; b = (BYTE)(b*scale); CC((r<<24)|(g<<16)|(b<<8)); USE_T0 (); } static void cc_t0_add_shade_mul_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_ENV (); USE_T0 (); } static void cc__t1_mul_t0_add_t0__add_prim_mul_shade () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_PRIM (); rdp.best_tex = 0; cmb.tex |= 3; cmb.tmu1_func = GR_COMBINE_FUNCTION_LOCAL; cmb.tmu0_func = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL; cmb.tmu0_fac = GR_COMBINE_FACTOR_LOCAL; } // ** A*B+C ** //Added by Gonetz static void cc_t0_mul_prim_add_t1 () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); if (cmb.combine_ext) { T1CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_B, 0); T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_OTHER_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_TMU_CCOLOR, 0, GR_CMBX_B, 0); cmb.tex |= 3; cmb.tex_ccolor = rdp.prim_color; } else { MOD_0 (TMOD_TEX_MUL_COL); MOD_0_COL (rdp.prim_color & 0xFFFFFF00); T0_ADD_T1 (); } } static void cc_t1_mul_prim_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SETSHADE_PRIM (); CC_PRIM (); USE_T0 (); } //Added by Gonetz static void cc_t0_mul_prim_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SETSHADE_PRIM (); CC_ENV (); USE_T0 (); } //Added by Gonetz static void cc_t1_mul_prim_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SETSHADE_PRIM (); CC_ENV (); USE_T1 (); } static void cc__t0_add_primlod__mul_prim_add_env () { if (cmb.combine_ext) { T1CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_X, GR_CMBX_ZERO, 1, GR_CMBX_ZERO, 0); T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_X, GR_CMBX_ZERO, 1, GR_CMBX_ZERO, 0); CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_ZERO, GR_CMBX_ITRGB, 0, GR_CMBX_B, 0); CC_PRIMLOD (); cmb.tex_ccolor = cmb.ccolor; CC_ENV (); SETSHADE_PRIM (); cmb.tex |= 1; } else { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIMLOD (); MOD_0 (TMOD_TEX_ADD_COL); MOD_0_COL (cmb.ccolor & 0xFFFFFF00); SETSHADE_PRIM (); CC_ENV (); USE_T0 (); } } //Added by Gonetz static void cc_t0_mul_prim_mul_shade_add_prim_mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_PRIM (); USE_T0 (); } //Added by Gonetz static void cc__t0_inter_t1_using_primlod__mul_prim_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SETSHADE_PRIM (); CC_ENV (); T0_INTER_T1_USING_FACTOR (lod_frac); } static void cc__t1_sub_prim_mul_enva_add_t0__mul_prim_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); SETSHADE_ENV (); if (cmb.combine_ext) { T1CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_DETAIL_FACTOR, 0, GR_CMBX_ZERO, 0); T0CCMBEXT(GR_CMBX_OTHER_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_ZERO, 1, GR_CMBX_ZERO, 0); cmb.tex_ccolor = rdp.prim_color; cmb.tex |= 3; percent = (float)(rdp.env_color&0xFF) / 255.0f; cmb.dc0_detailmax = cmb.dc1_detailmax = percent; } else { MOD_1 (TMOD_TEX_SUB_COL_MUL_FAC); MOD_1_COL (rdp.prim_color & 0xFFFFFF00); MOD_1_FAC (rdp.env_color & 0xFF); T0_ADD_T1 (); } } //Added by Gonetz static void cc__t0_inter_t1_using_primlod__mul_shade_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); T0_INTER_T1_USING_FACTOR (lod_frac); } //Added by Gonetz static void cc__t1_sub_prim_mul_primlod_add_t0__mul_prim_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SETSHADE_PRIM (); CC_ENV (); T1_SUB_PRIM_MUL_PRIMLOD_ADD_T0 (); } //Aded by Gonetz static void cc__t0_mul_t1__mul_prim_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); MULSHADE_PRIM (); T0_MUL_T1 (); } //Aded by Gonetz static void cc__t0_mul_t1__mul_env_add_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); T0_MUL_T1 (); } static void cc__t0_mul_t1__mul_shade_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIM (); T0_MUL_T1 (); } //Added by Gonetz static void cc__t0_add_t1__mul_shade_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); T0_ADD_T1 (); } static void cc__t1_mul_prima_add_t0__mul_shade_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); T1_MUL_PRIMA_ADD_T0 (); } //Added by Gonetz static void cc__t0_inter_t1_using_enva__mul_shade_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); BYTE factor = (BYTE)(rdp.env_color&0xFF); T0_INTER_T1_USING_FACTOR (factor); } //Added by Gonetz static void cc_t0_mul_primlod_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); SETSHADE_PRIM (); CC_PRIMLOD (); USE_T0 (); } //Added by Gonetz static void cc__t0_inter_t1_using_primlod__mul_shade_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIM (); T0_INTER_T1_USING_FACTOR (lod_frac); } //Added by Gonetz static void cc__t1_sub_t0_mul_primlod_add_prim__mul_shade_add_shade () { if (cmb.combine_ext) { T1CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_B, 0); T0CCMBEXT(GR_CMBX_OTHER_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_DETAIL_FACTOR, 0, GR_CMBX_ZERO, 0); cmb.tex |= 3; percent = (float)lod_frac / 255.0f; cmb.dc0_detailmax = cmb.dc1_detailmax = percent; CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_X, GR_CMBX_ITRGB, 0, GR_CMBX_ITRGB, 0); CC_PRIM (); } else { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); T0_INTER_T1_USING_FACTOR (lod_frac); } } //Added by Gonetz static void cc__t0_inter_t1_using_half__mul_prim_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SETSHADE_PRIM (); CC_ENV (); T0_INTER_T1_USING_FACTOR (0x7F); } //Added by Gonetz static void cc__t0_inter_t1_using_t1__mul_prim_add_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); T0_INTER_T1_USING_T1 (); } //Added by Gonetz static void cc_one_sub_t1_mul_t0a_add_t0_mul_env_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); MOD_0 (TMOD_TEX_MUL_COL); MOD_0_COL (rdp.env_color & 0xFFFFFF00); rdp.best_tex = 0; cmb.tex |= 3; cmb.tmu1_func = GR_COMBINE_FUNCTION_LOCAL; cmb.tmu1_invert = 1; cmb.tmu0_func = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL; cmb.tmu0_fac = GR_COMBINE_FACTOR_LOCAL_ALPHA; } //Added by Gonetz static void cc__t0_inter_t1_using_t1__mul_shade_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIM (); T0_INTER_T1_USING_T1 (); } //Added by Gonetz static void cc_t0_mul_prim_add_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); USE_T0 (); } static void cc_t1_mul_prim_add_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); USE_T1 (); } //Added by Gonetz static void cc_t0_mul_env_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SETSHADE_ENV (); CC_PRIM (); USE_T0 (); } //Added by Gonetz static void cc_t1_mul_env_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SETSHADE_ENV (); CC_PRIM (); USE_T1 (); } //Added by Gonetz static void cc__t0_mul_t1__mul_env_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SETSHADE_ENV (); CC_PRIM (); T0_MUL_T1 (); } //Added by Gonetz static void cc__t0_add_t1__mul_env_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SETSHADE_ENV (); CC_PRIM (); T0_ADD_T1 (); } //Added by Gonetz static void cc__t1_sub_t0__mul_env_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SETSHADE_ENV (); CC_PRIM (); T1_SUB_T0 (); } //Added by Gonetz static void cc_t0_mul_env_add_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); USE_T0 (); } static void cc_t0_mul_shade_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIM (); USE_T0 (); } static void cc_t1_mul_shade_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIM (); USE_T1 (); } static void cc_t0_mul_shade_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); USE_T0 (); } static void cc__t0_add_primlod__mul_shade_add_env () { if (cmb.combine_ext) { T1CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_X, GR_CMBX_ZERO, 1, GR_CMBX_ZERO, 0); T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_X, GR_CMBX_ZERO, 1, GR_CMBX_ZERO, 0); CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_ZERO, GR_CMBX_ITRGB, 0, GR_CMBX_B, 0); CC_PRIMLOD (); cmb.tex_ccolor = cmb.ccolor; CC_ENV (); cmb.tex |= 1; } else { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); DWORD color = (lod_frac<<24) | (lod_frac<<16) | (lod_frac<<8); MOD_0 (TMOD_TEX_ADD_COL); MOD_0_COL (color & 0xFFFFFF00); CC_ENV (); USE_T0 (); } } static void cc__t0_mul_prima_add_prim_mul__shade_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); if (cmb.combine_ext) { T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_ZERO, GR_CMBX_TMU_CALPHA, 0, GR_CMBX_B, 0); cmb.tex_ccolor = rdp.prim_color; cmb.tex |= 1; } else { MOD_0 (TMOD_TEX_SCALE_FAC_ADD_COL); MOD_0_COL (rdp.prim_color & 0xFFFFFF00); MOD_0_FAC (rdp.prim_color & 0xFF); USE_T0 (); } } //Added by Gonetz static void cc_t0_mul_shadea_add_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_LOCAL_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); USE_T0 (); } static void cc_prim_mul_prima_add_prim () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_LOCAL_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIM (); CA_PRIM (); SETSHADE_PRIM (); } static void cc_prim_mul_prima_add_t0 () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); SETSHADE_PRIM (); SETSHADE_PRIMA (); USE_T0 (); } static void cc_prim_mul_env_add_t0 () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); SETSHADE_PRIM (); SETSHADE_ENV (); USE_T0 (); } static void cc_prim_mul_shade_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); MULSHADE_PRIM (); } static void cc_env_mul_shade_add_env () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); MULSHADE_ENV (); } // ** A*B+C*D ** static void cc_t0_mul_prim_add_one_sub_prim_mul_shade () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); MULSHADE_1MPRIM (); USE_T0 (); } static void cc_t0_mul_prim_add_shade_sub_env_mul_prim () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); SUBSHADE_ENV () MULSHADE_PRIM (); USE_T0 (); } static void cc_t0_mul_prim_add_shade_mul_shadea_mul_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); MULSHADE_PRIM (); MULSHADE_SHADEA (); USE_T0 (); } static void cc_t0_mul_env_add_prim_mul_shade () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); MULSHADE_PRIM (); CC_ENV (); USE_T0 (); } static void cc_t0_mul_enva_add_prim_mul_shade () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); MULSHADE_PRIM (); CC_ENVA (); USE_T0 (); } static void cc_t0_mul_shade_add_prim_mul_env () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIMMULENV (); USE_T0 (); } static void cc_prim_mul_env_add_one_sub_prim_mul_shade () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); MULSHADE_1MPRIM (); CC_PRIMMULENV (); } // ** A*B*C ** static void cc_t0_mul_prim_mul_prim () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); SETSHADE_PRIM (); SETSHADE_PRIM (); USE_T0 (); } static void cc_t0_mul_prim_mul_prima () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); SETSHADE_PRIM (); SETSHADE_PRIMA (); USE_T0 (); } static void cc_t0_mul_enva_mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_ENVA (); USE_T0 (); } static void cc_t0_mul_primlod_mul_prim () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); cmb.ccolor = (rdp.prim_color*lod_frac)&0xFFFFFF00; USE_T0 (); } static void cc_t0_mul_primlod_mul_shade () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_PRIMLOD (); USE_T0 (); } static void cc__t0_mul_t1__mul_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); T0_MUL_T1 (); } static void cc__t1_mul_t1_add_t0__mul_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); if (cmb.combine_ext) { T1CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_B, 0); T0CCMBEXT(GR_CMBX_OTHER_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_OTHER_TEXTURE_RGB, 0, GR_CMBX_B, 0); cmb.tex |= 3; } else { T0_ADD_T1 (); } } static void cc__t0_mul_t1__mul_prima () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIMA (); T0_MUL_T1 (); } static void cc__t0_mul_t1__mul_env () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_ENV (); T0_MUL_T1 (); } static void cc__t0_mul_t1__mul_enva () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_ENVA (); T0_MUL_T1 (); } static void cc__t0_mul_t1__mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); T0_MUL_T1 (); } static void cc__t0a_mul_t1__mul_prim () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); T0A_MUL_T1 (); } static void cc__t0_mul_t1a__mul_shade () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); T0_MUL_T1A (); } static void cc__t0a_mul_t1__mul_shade () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); T0A_MUL_T1 (); } static void cc_t0_mul_prim_mul_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); SETSHADE_PRIM (); SETSHADE_ENV (); // notice that setshade multiplies USE_T0 (); } static void cc_t0_mul_prim_mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_PRIM (); USE_T0 (); } static void cc_t0_mul_prim_mul_shadea () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); SETSHADE_PRIM (); MULSHADE_SHADEA(); USE_T0 (); } static void cc_t0_mul_prima_mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_PRIMA (); USE_T0 (); } static void cc_t0_mul_one_sub_prim_mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_1MPRIM (); USE_T0 (); } static void cc_t0_mul_one_sub_env_mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_1MENV (); USE_T0 (); } static void cc_t1_mul_prim_mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_PRIM (); USE_T1 (); } //Added by Gonetz static void cc_t0_mul_1mprim_mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_1MPRIM (); USE_T0 (); } static void cc_t0_mul_env_mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_ENV (); USE_T0 (); } static void cc_t0_mul_shade_mul_shadea () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_SHADEA (); USE_T0 (); } static void cc_prim_mul_env_mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); MULSHADE_PRIM (); } static void cc_prim_mul_one_sub_env_mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_1SUBENV (); MULSHADE_PRIM (); } // ** A*B*C+D ** static void cc_t0_mul_prim_mul_shade_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); MULSHADE_PRIM (); USE_T0 (); } //Added by Gonetz static void cc_t0_mul_prim_mul_shadea_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_LOCAL_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); CC_ENV (); SETSHADE_ENV (); MULSHADE_A_PRIM (); USE_T0 (); } // (A*B+C)*D static void cc__t0a_mul_prim_add_t0__mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MOD_0 (TMOD_COL_MUL_TEXA_ADD_TEX); MOD_0_COL (rdp.prim_color & 0xFFFFFF00); USE_T0 (); } static void cc__t0a_mul_env_add_t0__mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MOD_0 (TMOD_COL_MUL_TEXA_ADD_TEX); MOD_0_COL (rdp.env_color & 0xFFFFFF00); USE_T0 (); } // ** A*B*C+D*E ** //Added by Gonetz static void cc_t0_mul_prim_mul_shade_add_prim_mul_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIMMULENV (); MULSHADE_PRIM (); USE_T0 (); } //Added by Gonetz static void cc_t0_mul_one_sub_prim_mul_shade_add_prim_mul_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIMMULENV (); MULSHADE_1MPRIM (); USE_T0 (); } //Added by Gonetz static void cc_t0_mul_one_sub_prim_mul_shadea_add_prim_mul_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIMMULENV (); SETSHADE_1MPRIM (); MULSHADE_SHADEA (); USE_T0 (); } //Added by Gonetz static void cc_t0_mul_one_sub_env_mul_shade_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); MULSHADE_1MENV (); USE_T0 (); } static void cc_t0_mul_prima_mul_shade_add_prim_mul_one_sub_prima () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); MULSHADE_PRIMA (); USE_T0 (); BYTE fac = 255 - (BYTE)(rdp.prim_color&0xFF); float col[3]; col[0] = (float)((rdp.prim_color & 0xFF000000) >> 24) / 255.0f; col[1] = (float)((rdp.prim_color & 0x00FF0000) >> 16) / 255.0f; col[2] = (float)((rdp.prim_color & 0x0000FF00) >> 8) / 255.0f; CC ( ((BYTE)(col[0]*fac))<<24 | ((BYTE)(col[1]*fac))<<16 | ((BYTE)(col[2]*fac))<<8 | fac ); } // ** A*(1-B)+C ** static void cc_t0_mul_1menv_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIM (); SETSHADE_1MENV (); USE_T0 (); } // ** (A+B)*C ** static void cc_t0_add_prim_mul_shade () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MOD_0 (TMOD_TEX_ADD_COL); MOD_0_COL (rdp.prim_color & 0xFFFFFF00); USE_T0 (); } static void cc_t0_mul__prim_add_env () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); SETSHADE_PRIM (); ADDSHADE_ENV (); USE_T0 (); } static void cc_t1_mul__prim_add_env () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); SETSHADE_PRIM (); ADDSHADE_ENV (); USE_T1 (); } // ** (A-B)*C ** static void cc__t0_mul_prim_add_shade__sub_env_mul_shade () { if (cmb.combine_ext) { T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_ITRGB, GR_FUNC_MODE_ZERO, GR_CMBX_TMU_CCOLOR, 0, GR_CMBX_B, 0); cmb.tex_ccolor = rdp.prim_color; cmb.tex |= 1; CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_ITRGB, 0, GR_CMBX_ZERO, 0); CC_ENV (); } else { cc_t0_mul_prim_mul_shade (); } } static void cc__t0_sub_env_mul_shade__sub_prim_mul_shade () { if (cmb.combine_ext) { T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_ITRGB, 0, GR_CMBX_ZERO, 0); cmb.tex_ccolor = rdp.env_color; cmb.tex |= 1; CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_ITRGB, 0, GR_CMBX_ITRGB, 0); CC_PRIM (); } else { cc_t0_mul_shade (); } } static void cc_t0_sub_env_mul_shade () { if (cmb.combine_ext) { CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_ITRGB, 0, GR_CMBX_ZERO, 0); CC_ENV (); } else { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); if (rdp.env_color & 0xFFFFFF00) { MOD_0 (TMOD_TEX_SUB_COL); MOD_0_COL (rdp.env_color & 0xFFFFFF00); } } USE_T0 (); } static void cc_one_sub_t0_mul_prim () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_BLEND_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE); CC_PRIM (); USE_T0 (); } static void cc_shade_sub_prim_mul_t0 () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIM (); USE_T0 (); } static void cc_shade_sub_prim_mul_env () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); SUBSHADE_PRIM (); } static void cc_shade_sub_env_mul_t0 () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); USE_T0 (); } static void cc_shade_sub_prim_mul__t0_inter_t1_using_primlod () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIM (); T0_INTER_T1_USING_FACTOR (lod_frac); } static void cc_shade_sub_env_mul__t0_inter_t1_using_primlod () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); T0_INTER_T1_USING_FACTOR (lod_frac); } static void cc_one_sub__t0_mul_t1__mul_shade () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_BLEND, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC (0); T0_MUL_T1 (); } static void cc_one_sub_env_mul_t0 () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_ENV (); USE_T0 (); } static void cc_one_sub_env_mul__t0_inter_t1_using_primlod () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_ENV (); T0_INTER_T1_USING_FACTOR (lod_frac); } static void cc_one_sub_env_mul_shade () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); } // ** (1-A)*B + A*C ** static void cc_t0_mul_env_add_1mt0_mul_shade () { CCMB (GR_COMBINE_FUNCTION_BLEND, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); USE_T0 (); } // ** (1-A)*B+C ** static void cc_one_sub_shade_mul__t1_sub_prim_mul_primlod_add_t0__add_shade () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); T1_SUB_PRIM_MUL_PRIMLOD_ADD_T0 (); } // ** (1-A)*B*C ** static void cc_one_sub_t0_mul_prim_mul_shade () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_BLEND_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_NONE); MULSHADE_PRIM (); USE_T0 (); } // ** (A-B)*C*D ** static void cc_prim_sub_env_mul_t0_mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_ITERATED); MULSHADE_PRIMSUBENV (); USE_T0 (); } // ** (A-B)*C+D ** static void cc_t0_sub_t1_mul_prim_mul_shade_add_t1 () //Aded by Gonetz { if (cmb.combine_ext) { T1CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_B, 0); T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_OTHER_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_ITRGB, 0, GR_CMBX_B, 0); CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); MULSHADE_PRIM (); cmb.tex |= 3; } else { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); T0_ADD_T1 (); } } static void cc_t0_sub_prim_mul_t0a_add_prim () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); USE_T0 (); } static void cc_t0_sub_prim_mul_prima_add_prim () //Aded by Gonetz { // * not guaranteed to work if another iterated alpha is set CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); SETSHADE_PRIM (); SETSHADE_1MPRIMA (); CC_PRIMA (); USE_T0 (); } static void cc_t0_sub_prim_mul_shadea_add_prim () //Aded by Gonetz { // * not guaranteed to work if another iterated alpha is set CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_LOCAL_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); SETSHADE_PRIM (); USE_T0 (); } static void cc_t0_sub_prim_mul_env_add_shade () //Aded by Gonetz { if (cmb.combine_ext) { T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_ZERO, 1, GR_CMBX_ZERO, 0); cmb.tex |= 1; cmb.tex_ccolor = rdp.prim_color; CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_ITRGB, GR_FUNC_MODE_ZERO, GR_CMBX_CONSTANT_COLOR, 0, GR_CMBX_B, 0); CC_ENV (); } else { cc_t0_mul_env_add_shade (); } } static void cc__t0_inter_t1_using_shadea__sub_prim_mul_env_add_shade () //Aded by Gonetz { if (cmb.combine_ext) { CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_ITRGB, GR_FUNC_MODE_ZERO, GR_CMBX_CONSTANT_COLOR, 0, GR_CMBX_B, 0); //have to pass shade alpha to combiner ACMBEXT(GR_CMBX_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_ITALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_ZERO, 0); } else { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); } CC_ENV (); SUBSHADE_PRIMMULENV (); T0_INTER_T1_USING_SHADEA (); } static void cc_t0_sub_prim_mul_env_add_prim () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); SETSHADE_PRIM (); SETSHADE_1MENV (); USE_T0 (); } static void cc_t0_sub_prim_mul_enva_add_prim () //Aded by Gonetz { // * not guaranteed to work if another iterated alpha is set CCMB (GR_COMBINE_FUNCTION_BLEND, GR_COMBINE_FACTOR_LOCAL_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); CA_ENV (); USE_T0 (); } static void cc_t0_sub_prim_mul_primlod_add_env () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_ENV (); MOD_0 (TMOD_TEX_SUB_COL_MUL_FAC); MOD_0_COL (rdp.prim_color & 0xFFFFFF00); MOD_0_FAC (lod_frac & 0xFF); USE_T0 (); } static void cc_t0_sub__prim_mul_env () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); SETSHADE_PRIM (); SETSHADE_ENV (); USE_T0 (); } static void cc__t0_mul_t1__sub_prim_mul__t0t1a__add_prim () //Aded by Gonetz { // * not guaranteed to work if another iterated alpha is set CCMB (GR_COMBINE_FUNCTION_BLEND, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); T0_MUL_T1 (); A_T0_MUL_T1 (); } static void cc__t1_inter_t0_using_enva__sub_prim_mul_prima_add_prim () //Aded by Gonetz { // * not guaranteed to work if another iterated alpha is set CCMB (GR_COMBINE_FUNCTION_BLEND, GR_COMBINE_FACTOR_LOCAL_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); CA_PRIM (); BYTE factor = (BYTE)(rdp.env_color&0xFF); T1_INTER_T0_USING_FACTOR (factor); } static void cc__t0_mul_shade__sub_env_mul_shadea_add_env () //Aded by Gonetz { if (rdp.tiles[rdp.cur_tile].format == 4) { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_OTHER_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); } else if (rdp.tiles[rdp.cur_tile].format == 2) { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); USE_T0 (); } else { cc_t0 (); } } static void cc_t0_sub_env_mul_k5_add_prim () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); MOD_0 (TMOD_TEX_SUB_COL_MUL_FAC); MOD_0_COL (rdp.env_color & 0xFFFFFF00); MOD_0_FAC (rdp.K5); USE_T0 (); } static void cc__t0_inter_t1_using_t0__sub_shade_mul_prima_add_shade () //Aded by Gonetz { if (cmb.combine_ext) { cmb.tex |= 3; CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_ITRGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_CONSTANT_COLOR, 0, GR_CMBX_B, 0); CC_PRIMA(); } else { // * not guaranteed to work if another iterated alpha is set CCMB (GR_COMBINE_FUNCTION_BLEND, GR_COMBINE_FACTOR_LOCAL_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); SETSHADE_A_PRIM (); } // T0_INTER_T1_USING_T0 (); T1_INTER_T0_USING_T0 (); //strange, but this one looks better } static void cc_t0_sub__prim_mul_shade__mul_enva_add__prim_mul_shade () //Aded by Gonetz { // * not guaranteed to work if another iterated alpha is set CCMB (GR_COMBINE_FUNCTION_BLEND, GR_COMBINE_FACTOR_LOCAL_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_PRIM (); SETSHADE_A_ENV (); USE_T0 (); } static void cc_t0_sub_env_mul_t0_add_env () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_BLEND, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_ENV (); USE_T0 (); //(t0-env)*t0+env = t0*t0 + (1-t0)*env } static void cc_t0_sub_env_mul_prim_add_shade () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); MOD_0 (TMOD_TEX_SUB_COL); MOD_0_COL (rdp.env_color & 0xFFFFFF00); USE_T0 (); } static void cc_t0_sub_env_mul_shade_add_prim () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIM (); MOD_0 (TMOD_TEX_SUB_COL); MOD_0_COL (rdp.env_color & 0xFFFFFF00); USE_T0 (); } static void cc__t0_sub_env_mul_shade_add_prim__mul_shade () //Aded by Gonetz { if (!cmb.combine_ext) { cc_t0_sub_env_mul_shade_add_prim (); return; } T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_ITRGB, 0, GR_CMBX_ZERO, 0); cmb.tex_ccolor = rdp.env_color; cmb.tex |= 1; CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_X, GR_CMBX_ITRGB, 0, GR_CMBX_ZERO, 0); CC_PRIM (); } static void cc__t0_inter_t1_using_primlod__sub_env_mul_shade_add_env () { // (t1-t0)*primlod+t0, (cmb-env)*shade+env if (cmb.combine_ext) { CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_ITRGB, 0, GR_CMBX_B, 0); } else { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); } CC_ENV (); T0_INTER_T1_USING_FACTOR (lod_frac); } static void cc_t0_sub_env_mul_enva_add_prim () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); MOD_0 (TMOD_TEX_SUB_COL_MUL_FAC); MOD_0_COL (rdp.env_color & 0xFFFFFF00); MOD_0_FAC (rdp.env_color & 0xFF); USE_T0 (); } static void cc_one_sub_t0_mul_prim_add_t0 () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); USE_T0 (); //(1-t)*prim+t == (1-prim)*t+prim } static void cc_one_sub_t1_mul_prim_add_t1 () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); USE_T1 (); //(1-t)*prim+t == (1-prim)*t+prim } static void cc_one_sub_t1_mul_env_add_t1 () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_ENV (); USE_T1 (); //(1-t)*env+t == (1-env)*t+env } static void cc_one_sub_t0_mul_primlod_add_t0 () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIMLOD (); USE_T0 (); //(1-t)*primlod+t == (1-primlod)*t+primlod } static void cc_one_sub_t0_mul_prima_add_t0 () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); USE_T0 (); //(1-t)*prima+t == (1-prima)*t+prima } static void cc_one_sub__t0_inter_t1_using_enva__mul_prim_add__t0_inter_t1_using_enva () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); BYTE factor = (BYTE)(rdp.env_color&0xFF); T0_INTER_T1_USING_FACTOR (factor); //(1-t)*prim+t == (1-prim)*t+prim } static void cc_one_sub_t0_mul_shade_add_t0 () { CCMB (GR_COMBINE_FUNCTION_BLEND, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC (0xFFFFFFFF); USE_T0 (); } static void cc_one_sub_prim_mul_t0_add_prim () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); USE_T0 (); } static void cc__one_sub_prim_mul_shade__mul_t0_add__prim_mul_shade () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_PRIM (); USE_T0 (); } static void cc_one_sub_prim_mul_t1_add_prim () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); USE_T1 (); } static void cc_one_sub_prim_mul_env_add_prim () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIM (); SETSHADE_ENV (); } static void cc_one_sub_prim_mul_shade_add_shade () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_1SUBPRIM (); } static void cc_t0_inter_env_using_prima () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); USE_T0 (); MOD_0 (TMOD_TEX_INTER_COLOR_USING_FACTOR); MOD_0_COL (rdp.env_color & 0xFFFFFF00); MOD_0_FAC (rdp.prim_color & 0xFF); } static void cc_t0_inter_env_using_enva () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); USE_T0 (); MOD_0 (TMOD_TEX_INTER_COLOR_USING_FACTOR); MOD_0_COL (rdp.env_color & 0xFFFFFFFF); MOD_0_FAC (rdp.env_color & 0xFF); } static void cc_t0_inter_noise_using_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); USE_T0 (); MOD_0 (TMOD_TEX_INTER_NOISE_USING_COL); MOD_0_COL (rdp.prim_color); rdp.noise = noise_texture; } static void cc_t0_inter_noise_using_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); USE_T0 (); MOD_0 (TMOD_TEX_INTER_NOISE_USING_COL); MOD_0_COL (rdp.env_color); rdp.noise = noise_texture; } static void cc_t0_sub_env_mul_enva_add_env () { CCMB (GR_COMBINE_FUNCTION_BLEND, GR_COMBINE_FACTOR_LOCAL_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_ENV (); CA_ENV (); USE_T0 (); } //Added by Gonetz static void cc_one_sub_prim_mul__t0_mul_t1__add__prim_mul_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_1SUBPRIM (); SETSHADE_PRIM (); SETSHADE_ENV (); T0_MUL_T1 (); } //Added by Gonetz static void cc_one_sub_prim_mul__t0_inter_t1_using_enva__add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_1SUBPRIM (); SETSHADE_PRIM (); BYTE factor = (BYTE)(rdp.env_color&0xFF); T0_INTER_T1_USING_FACTOR (factor); } static void cc_one_sub_env_mul__t0_inter_t1_using_primlod__add_env () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_ENV (); T0_INTER_T1_USING_FACTOR (lod_frac); } static void cc_one_sub_env_mul__t1_sub_prim_mul_primlod_add_t0__add_env () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_ENV (); T1_SUB_PRIM_MUL_PRIMLOD_ADD_T0 (); } static void cc_one_sub_env_mul_t0_add_prim_mul_env () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_1SUBENV (); SETSHADE_PRIM (); SETSHADE_ENV (); USE_T0 (); } static void cc_one_sub_env_mul_t0_add_env () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_ENV (); USE_T0 (); } static void cc_one_sub_env_mul_t0_add_shade () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_1SUBENV (); USE_T0 (); } static void cc_one_sub_env_mul_prim_add_env () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); SETSHADE_PRIM (); } static void cc_one_sub_env_mul_prim_add_shade () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_1SUBENV (); cmb.ccolor=(BYTE)( ((rdp.prim_color & 0xFF000000) >> 24) * (((cmb.ccolor & 0xFF000000) >> 24) /255.0f) ) << 24 | (BYTE)( ((rdp.prim_color & 0x00FF0000) >> 16) * (((cmb.ccolor & 0x00FF0000) >> 16) /255.0f) ) << 16 | (BYTE)( ((rdp.prim_color & 0x0000FF00) >> 8) * (((cmb.ccolor & 0x0000FF00) >> 8) /255.0f) ) << 8; } static void cc_one_sub_env_mul_shade_add_env () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); } static void cc_one_sub_env_mul_prim_add__t0_inter_t1_using_env () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); SETSHADE_PRIM (); SETSHADE_1MENV (); //BYTE factor = (BYTE)(rdp.env_color&0xFF); T0_INTER_T1_USING_ENV (); } static void cc_one_sub_shade_mul_t0_add_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); USE_T0 (); } static void cc_one_sub_shade_mul__t0_mul_shadea__add_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); if (cmb.combine_ext) { T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_ITALPHA, 0, GR_CMBX_ZERO, 0); cmb.tex |= 1; } else { USE_T0 (); } } static void cc_one_sub_shade_mul_env_add_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); } static void cc_one_sub_shade_mul_shadea_add_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_LOCAL_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC (0xFFFFFFFF); } ///* static void cc_t0_sub_env_mul_prim_add_env () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); SETSHADE_1MPRIM(); SETSHADE_ENV(); CC_PRIM (); USE_T0 (); //(t0-env)*prim+env == t0*prim + env*(1-prim) } //*/ static void cc__t0_inter_t1_using_t1a__sub_env_mul_enva_add_env () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_BLEND, GR_COMBINE_FACTOR_LOCAL_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); cmb.ccolor = rdp.env_color; T0_INTER_T1_USING_T1A (); } static void cc_t0_sub_shade_mul_t0a_add_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); USE_T0 (); A_USE_T0 (); } static void cc_t0_sub_shade_mul_prima_add_shade () //Aded by Gonetz { // * not guaranteed to work if another iterated alpha is set CCMB (GR_COMBINE_FUNCTION_BLEND, GR_COMBINE_FACTOR_LOCAL_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); SETSHADE_A_PRIM (); USE_T0 (); } static void cc_t0_sub_shade_mul_shadea_add_shade () //Aded by Gonetz { // * not guaranteed to work if another iterated alpha is set CCMB (GR_COMBINE_FUNCTION_BLEND, GR_COMBINE_FACTOR_LOCAL_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); USE_T0 (); } static void cc_prim_sub_t0_mul_env_add_t0 () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_1SUBENV (); SETSHADE_PRIM (); SETSHADE_ENV (); USE_T0 (); //(prim-t0)*env+t0 == prim*env + t0*(1-env) } static void cc_prim_sub_env_mul_t0_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIM (); SETSHADE_PRIMSUBENV (); USE_T0 (); } static void cc_prim_sub_env_mul_t0_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); SETSHADE_ENV (); USE_T0 (); } static void cc_prim_sub_env_mul__t0_mul_prim__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); SETSHADE_ENV (); if (cmb.combine_ext) { T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_TMU_CCOLOR, 0, GR_CMBX_ZERO, 0); cmb.tex_ccolor = rdp.prim_color; cmb.tex |= 1; } else { USE_T0 (); } } static void cc_prim_sub_env_mul_t0_mul_shade_add_env () { if (cmb.combine_ext) { T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_TMU_CCOLOR, 0, GR_CMBX_ZERO, 0); CC_PRIMSUBENV (); cmb.tex_ccolor = cmb.ccolor; cmb.tex |= 1; CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); } else { cc_t0_mul_prim_mul_shade (); } } static void cc_prim_sub_env_mul__t0_sub_t0_mul_prima__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); SETSHADE_ENV (); rdp.best_tex = 0; cmb.tex |= 1; cmb.tmu0_func = GR_COMBINE_FUNCTION_BLEND_LOCAL; cmb.tmu0_fac = GR_COMBINE_FACTOR_DETAIL_FACTOR; percent = (float)(rdp.prim_color&0xFF) / 255.0f; cmb.dc0_detailmax = cmb.dc1_detailmax = percent; } static void cc_prim_sub_env_mul__t0_add_t1a__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); SETSHADE_ENV (); rdp.best_tex = 0; cmb.tex |= 3; cmb.tmu1_func = GR_COMBINE_FUNCTION_LOCAL_ALPHA; cmb.tmu0_func = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL; cmb.tmu0_fac = GR_COMBINE_FACTOR_ONE; } static void cc_prim_sub_env_mul__t0_sub_prim_mul_enva_add_t0__add_env () { // (t0-prim)*env_a+t0, (prim-env)*cmb+env CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); SETSHADE_PRIM (); USE_T0 (); MOD_0 (TMOD_TEX_SUB_COL_MUL_FAC_ADD_TEX); MOD_0_COL (rdp.prim_color & 0xFFFFFF00); MOD_0_FAC (rdp.env_color & 0xFF); } static void cc_prim_sub_env_mul__t1_sub_prim_mul_enva_add_t0__add_env () { // (t0-prim)*env_a+t0, (prim-env)*cmb+env CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); SETSHADE_PRIM (); if (cmb.combine_ext) { if (rdp.tiles[rdp.cur_tile].format > 2) { T1CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_B, 0); T0CCMBEXT(GR_CMBX_OTHER_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_DETAIL_FACTOR, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); } else { T1CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_DETAIL_FACTOR, 0, GR_CMBX_ZERO, 0); T0CCMBEXT(GR_CMBX_OTHER_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_ZERO, 1, GR_CMBX_ZERO, 0); } cmb.tex_ccolor = rdp.prim_color; cmb.tex |= 3; cmb.dc0_detailmax = cmb.dc1_detailmax = (float)(rdp.env_color&0xFF) / 255.0f; } else { MOD_1 (TMOD_TEX_SUB_COL_MUL_FAC); MOD_1_COL (rdp.prim_color & 0xFFFFFF00); MOD_1_FAC (rdp.env_color & 0xFF); T0_ADD_T1 (); } } static void cc__prim_sub_env_mul_t0_add_env__mul_k5 () { CCMB (GR_COMBINE_FUNCTION_BLEND, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); float factor = (float)rdp.K5 / 255.0f; BYTE r = (BYTE)((rdp.prim_color >> 24) & 0xFF); r = (BYTE)((float)r * factor); BYTE g = (BYTE)((rdp.prim_color >> 16) & 0xFF); g = (BYTE)((float)g * factor); BYTE b = (BYTE)((rdp.prim_color >> 8) & 0xFF); b = (BYTE)((float)b * factor); CC ((r<<24) | (g<<16) | (b<<8)); SETSHADE_ENV (); MULSHADE_K5 (); USE_T0 (); } static void cc_prim_sub_env_mul_t1_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); SETSHADE_ENV (); USE_T1 (); } static void cc_prim_sub_env_mul_t1_add_env_mul_t0 () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); MOD_1 (TMOD_COL_INTER_COL1_USING_TEX); MOD_1_COL (rdp.env_color & 0xFFFFFF00); MOD_1_COL1 (rdp.prim_color & 0xFFFFFF00); T0_MUL_T1 (); } //Added by Gonetz static void cc_prim_sub_env_mul_t0a_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); SETSHADE_PRIM (); USE_T0 (); } //Added by Gonetz static void cc_prim_sub_env_mul_t1a_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); SETSHADE_PRIM (); USE_T1 (); } //Added by Gonetz static void cc_prim_sub_env_mul__t0_mul_t1__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); SETSHADE_ENV (); T0_MUL_T1 (); } //Added by Gonetz static void cc_prim_sub_env_mul__t0_add_t1__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); SETSHADE_ENV (); T0_ADD_T1 (); } //Added by Gonetz static void cc_prim_sub_env_mul__t0_mul_enva__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); SETSHADE_PRIMSUBENV (); MULSHADE_ENVA (); USE_T0 (); } //Added by Gonetz static void cc_prim_sub_env_mul__t0_mul_shade__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); MULSHADE_PRIMSUBENV (); USE_T0 (); } //Added by Gonetz static void cc_prim_sub_env_mul__prim_inter_t0_using_shadea__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); if (cmb.combine_ext) { SETSHADE_PRIM (); PRIM_INTER_T0_USING_SHADEA (); } else { MULSHADE_SHADEA (); SETSHADE_PRIMSUBENV (); USE_T0 (); } } //Added by Gonetz static void cc_prim_sub_env_mul__t0_sub_prim_mul_primlod_add_t0__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); SETSHADE_ENV (); if (cmb.combine_ext) { T0CCMBEXT(GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_DETAIL_FACTOR, 0, GR_CMBX_B, 0); cmb.tex_ccolor = rdp.prim_color; cmb.tex |= 1; percent = (float)(lod_frac) / 255.0f; cmb.dc0_detailmax = cmb.dc1_detailmax = percent; } else { USE_T0 (); MOD_0 (TMOD_TEX_SUB_COL_MUL_FAC_ADD_TEX); MOD_0_COL (rdp.prim_color & 0xFFFFFF00); MOD_0_FAC (lod_frac & 0xFF); } } static void cc_prim_sub_env_mul__t0_sub_prim_mul_primlod_add_shade__add_env () { if (!cmb.combine_ext) { cc_prim_sub_env_mul_t0_add_env (); return; } T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_DETAIL_FACTOR, 0, GR_CMBX_ITRGB, 0); CCMBEXT(GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_X, GR_CMBX_ITRGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_TEXTURE_RGB, 0, GR_CMBX_B, 0); cmb.tex_ccolor = rdp.prim_color; CC_PRIM (); SETSHADE_ENV (); cmb.tex |= 1; percent = (float)(lod_frac) / 255.0f; cmb.dc0_detailmax = cmb.dc1_detailmax = percent; } static void cc_prim_sub_env_mul__t0_sub_shade_mul_primlod_add_shade__add_env () { if (!cmb.combine_ext) { cc_prim_sub_env_mul_t0_add_env (); return; } T1CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_ITRGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_DETAIL_FACTOR, 0, GR_CMBX_B, 0); T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_ITRGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_DETAIL_FACTOR, 0, GR_CMBX_B, 0); CCMBEXT(GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_X, GR_CMBX_ITRGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_TEXTURE_RGB, 0, GR_CMBX_B, 0); cmb.tex_ccolor = rdp.prim_color; CC_PRIM (); SETSHADE_ENV (); cmb.tex |= 1; percent = (float)(lod_frac) / 255.0f; cmb.dc0_detailmax = cmb.dc1_detailmax = percent; } //Added by Gonetz static void cc_lavatex_sub_prim_mul_shade_add_lavatex () { if (!cmb.combine_ext) { cc_t0_add_t1 (); return; } CCMBEXT(GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_ITRGB, 0, GR_CMBX_B, 0); CC_PRIM (); T0_SUB_PRIM_MUL_PRIMLOD_ADD_T1 (); } //Added by Gonetz static void cc_prim_sub_env_mul__t0_sub_prim_mul_primlod_add_t1__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); SETSHADE_ENV (); T0_SUB_PRIM_MUL_PRIMLOD_ADD_T1 (); } //Added by Gonetz static void cc_prim_sub_env_mul__t1_sub_prim_mul_primlod_add_t0__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); SETSHADE_ENV (); T1_SUB_PRIM_MUL_PRIMLOD_ADD_T0 (); } //Added by Gonetz static void cc_prim_sub_env_mul__t0_inter_t1_using_t1__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); SETSHADE_ENV (); T0_INTER_T1_USING_T1 (); } //Added by Gonetz static void cc_prim_sub_env_mul__t0_inter_t1_using_enva_alpha__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); SETSHADE_ENV (); BYTE factor = (BYTE)(rdp.env_color&0xFF); T0_INTER_T1_USING_FACTOR (factor); A_T0_INTER_T1_USING_FACTOR (factor); } //Added by Gonetz static void cc_prim_sub_env_mul__t0_mul_t1__add_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIMSUBENV (); USE_T0 (); // T0_MUL_T1 (); } //Added by Gonetz static void cc_prim_sub_env_mul_shade_add_t0 () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_PRIMSUBENV (); USE_T0 (); } //Added by Gonetz static void cc_prim_sub_env_mul_prima_add_t0 () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); SETSHADE_PRIMSUBENV (); SETSHADE_PRIMA (); USE_T0 (); } //Added by Gonetz static void cc_prim_sub_env_mul_shade_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); MULSHADE_PRIMSUBENV (); } static void cc_prim_sub_env_mul_shadea_add_env () { // * not guaranteed to work if another iterated alpha is set CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_OTHER_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); SETSHADE_PRIM (); } //Added by Gonetz static void cc_prim_sub_env_mul__t0_inter_t1_using_prima__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); SETSHADE_PRIM (); BYTE factor = (BYTE)(rdp.prim_color&0xFF); T0_INTER_T1_USING_FACTOR (factor); } //Added by Gonetz static void cc_prim_sub_env_mul__t1_inter_t0_using_prima__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); SETSHADE_PRIM (); BYTE factor = (BYTE)(rdp.prim_color&0xFF); T1_INTER_T0_USING_FACTOR (factor); } static void cc_prim_sub_env_mul__t0_inter_t1_using_enva__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); SETSHADE_PRIM (); BYTE factor = (BYTE)(rdp.env_color&0xFF); T0_INTER_T1_USING_FACTOR (factor); } static void cc_prim_sub_env_mul__t1_inter_t0_using_enva__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); SETSHADE_PRIM (); BYTE factor = (BYTE)(rdp.env_color&0xFF); T1_INTER_T0_USING_FACTOR (factor); } static void cc_prim_sub_env_mul__t1_inter_t0_using_primlod__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); SETSHADE_PRIM (); T1_INTER_T0_USING_FACTOR (lod_frac); } static void cc_prim_sub_env_mul__t0_mul_enva_add_t1__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); SETSHADE_PRIM (); if (cmb.combine_ext) { T1CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_ZERO, 1, GR_CMBX_ZERO, 0); T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_OTHER_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_DETAIL_FACTOR, 0, GR_CMBX_B, 0); cmb.tex |= 3; percent = (float)(rdp.env_color&0xFF) / 255.0f; cmb.dc0_detailmax = cmb.dc1_detailmax = percent; } else { T0_ADD_T1 (); } } static void cc_prim_sub_env_mul__t1_mul_enva_add_t0__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); SETSHADE_PRIM (); T1_MUL_ENVA_ADD_T0 (); } //Added by Gonetz static void cc_prim_sub_env_mul_primlod_add__t0_inter_t1_using_primlod () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIMSUBENV(); float factor = lod_frac / 255.0f; cmb.ccolor=(BYTE)( ((cmb.ccolor & 0xFF000000) >> 24) * factor ) << 24 | (BYTE)( ((cmb.ccolor & 0x00FF0000) >> 16) * factor ) << 16 | (BYTE)( ((cmb.ccolor & 0x0000FF00) >> 8) * factor ) << 8; T0_INTER_T1_USING_FACTOR (lod_frac); } static void cc_prim_sub_env_mul__t0_inter_t1_using_primlod__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); SETSHADE_PRIM (); T0_INTER_T1_USING_FACTOR (lod_frac); } static void cc_prim_sub_env_mul__t1_mul_primlod_add_t0__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); SETSHADE_PRIM (); T1_MUL_PRIMLOD_ADD_T0 (); } static void cc_prim_sub_env_mul__t1_sub_prim_mul_t0_add_t0__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); SETSHADE_PRIM (); if (cmb.combine_ext) { T1CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_ZERO, 1, GR_CMBX_ZERO, 0); T0CCMBEXT(GR_CMBX_OTHER_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_RGB, 0, GR_CMBX_B, 0); cmb.tex_ccolor = rdp.prim_color; cmb.tex |= 3; } else { MOD_1 (TMOD_TEX_SUB_COL); MOD_1_COL (rdp.prim_color & 0xFFFFFF00); T0_MUL_T1_ADD_T0 (); } } //Added by Gonetz static void cc__prim_sub_env_mul_prim_add_t0__mul_prim () { if (cmb.combine_ext) { T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_ITRGB, GR_FUNC_MODE_X, GR_CMBX_ZERO, 1, GR_CMBX_ZERO, 0); cmb.tex |= 1; SETSHADE_PRIMSUBENV (); SETSHADE_PRIM (); CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_ITRGB, GR_FUNC_MODE_ZERO, GR_CMBX_CONSTANT_COLOR, 0, GR_CMBX_ZERO, 0); CC_PRIM() ; } else { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); SETSHADE_PRIMSUBENV (); SETSHADE_PRIM (); USE_T0 (); } } //Added by Gonetz static void cc_prim_sub_env_mul_prim_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SETSHADE_PRIMSUBENV (); SETSHADE_PRIM (); CC_ENV (); } //Added by Gonetz static void cc_prim_sub_env_mul_enva_add_t0 () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_ENVA (); SETSHADE_PRIMSUBENV (); USE_T0 (); } //Added by Gonetz static void cc_prim_sub_shade_mul_t0_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); COLSUBSHADE_PRIM (); USE_T0 (); } //Added by Gonetz static void cc_prim_sub_shade_mul__t1_sub_prim_mul_primlod_add_t0__add_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); T1_SUB_PRIM_MUL_PRIMLOD_ADD_T0 (); } static void cc_prim_sub_shade_mul_t1a_add_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); USE_T1 (); } //Added by Gonetz static void cc_prim_sub_shade_mul_t0_add_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); USE_T0 (); } //Added by Gonetz static void cc_prim_sub_shade_mul_t1_add_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); USE_T1 (); } //Added by Gonetz static void cc_prim_sub_shade_mul__t0_inter_t1_using_enva__add_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); BYTE factor = (BYTE)(rdp.env_color&0xFF); T0_INTER_T1_USING_FACTOR (factor); } //Added by Gonetz static void cc_prim_sub_shade_mul__t0_inter_t1_using_shadea__add_shade () { if (cmb.combine_ext) { CCMBEXT(GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_X, GR_CMBX_ITRGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_TEXTURE_RGB, 0, GR_CMBX_B, 0); } else { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); } CC_PRIM (); T0_INTER_T1_USING_SHADEA (); } //Added by Gonetz static void cc_prim_sub_shade_mul_prima_add_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_OTHER_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); CA_PRIM (); } //Added by Gonetz static void cc_prim_sub_shade_mul_env_add_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIMMULENV (); MULSHADE_1MENV (); } //Added by Gonetz static void cc_prim_sub_shade_mul_shadea_add_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_LOCAL_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); } static void cc_env_sub_prim_mul_t0_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); SETSHADE_PRIM (); USE_T0 (); } static void cc_env_sub_prim_mul_t1_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); SETSHADE_PRIM (); USE_T1 (); } static void cc_env_sub_prim_mul_t0a_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); SETSHADE_PRIM (); A_USE_T0 (); } static void cc_env_sub_prim_mul_t1a_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); SETSHADE_PRIM (); A_USE_T1 (); } static void cc_env_sub_prim_mul__t0_add_t1__add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); SETSHADE_PRIM (); T0_ADD_T1 (); } static void cc_env_sub_prim_mul__t0_mul_t1__add_prim () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); SETSHADE_PRIM (); T0_MUL_T1 (); } static void cc_env_sub_prim_mul__t0t1a__add_prim () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); SETSHADE_PRIM (); A_T0_MUL_T1 (); } static void cc_env_sub_prim_mul__t0_inter_t1_using_t1__add_prim () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); SETSHADE_PRIM (); T0_INTER_T1_USING_T1 (); } static void cc_env_sub_prim_mul__t0_inter_t1_using_half__add_prim () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); SETSHADE_PRIM (); T0_INTER_T1_USING_FACTOR (0x7F); } static void cc_env_sub_prim_mul__t1_inter_t0_using_t0__add_prim () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); SETSHADE_PRIM (); T1_INTER_T0_USING_T0 (); } static void cc_env_sub_shade_mul__t0_mul_t1__add_shade () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); T0_MUL_T1 (); } static void cc_env_sub_prim_mul_prima_add_prim () //Aded by Gonetz { // * not guaranteed to work if another iterated alpha is set CCMB (GR_COMBINE_FUNCTION_BLEND, GR_COMBINE_FACTOR_LOCAL_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIM (); CA_PRIM (); SETSHADE_ENV (); } static void cc_env_sub_prim_mul_enva_add_prim () //Aded by Gonetz { // * not guaranteed to work if another iterated alpha is set CCMB (GR_COMBINE_FUNCTION_BLEND, GR_COMBINE_FACTOR_OTHER_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); CA_ENV (); SETSHADE_PRIM (); } static void cc_env_sub_prim_mul_shade_add_prim () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIM (); MULSHADE_ENVSUBPRIM (); } static void cc_env_sub_prim_mul_shadea_add_prim () //Added by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIM (); MULSHADE_SHADEA (); SETSHADE_ENVSUBPRIM (); } static void cc_env_sub_prim_mul__t0_inter_t1_using_prima__add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); SETSHADE_PRIM (); BYTE factor = (BYTE)(rdp.prim_color&0xFF); T0_INTER_T1_USING_FACTOR (factor); } static void cc_env_sub_prim_mul__t0_inter_t1_using_primlod__add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); SETSHADE_PRIM (); T0_INTER_T1_USING_FACTOR (lod_frac); } static void cc_env_sub_primshade_mul_t0_add_primshade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); MULSHADE_PRIM (); USE_T0 (); } static void cc_env_sub_primshade_mul_t1_add_primshade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); MULSHADE_PRIM (); USE_T1 (); } static void cc_env_sub_shade_mul_t0_add_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); USE_T0 (); } static void cc_env_sub_shade_mul_t1_add_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); USE_T1 (); } //Added by Gonetz static void cc_env_sub_shade_mul__t0_inter_t1_using_shadea__add_shade () { if (cmb.combine_ext) { CCMBEXT(GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_X, GR_CMBX_ITRGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_TEXTURE_RGB, 0, GR_CMBX_B, 0); } else { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); } CC_ENV (); T0_INTER_T1_USING_SHADEA (); } //Added by Gonetz static void cc_env_sub_shade_mul_enva_add_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_OTHER_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); cmb.ccolor = rdp.env_color; } /* static void cc_env_sub__prim_inter_t0_using_shadea__mul_shade_add_env () { // (t0-prim)*shade_alpha+prim, (env-cmb)*shade+cmb if (cmb.combine_ext) { CCMBEXT(GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_X, GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_ITRGB, 0, GR_CMBX_B, 0); CC_ENV (); PRIM_INTER_T0_USING_SHADEA (); } else { cc_t0_mul_shadea (); } } */ //Added by Gonetz static void cc_shade_sub_t0_mul_shadea_add_t0 () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_SHADEA (); USE_T0 (); } static void cc_shade_sub_prim_mul__t0_inter_t1_using_primlod__add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIM (); T0_INTER_T1_USING_FACTOR (lod_frac); } static void cc_shade_sub_prim_mul_t0_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIM (); USE_T0 (); } static void cc_shade_sub_prim_mul__t0_mul_t1__add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIM (); T0_MUL_T1 (); } //Added by Gonetz static void cc_shade_sub_prim_mul_t1_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIM (); USE_T1 (); } //Added by Gonetz static void cc_shade_sub_env_mul__t0_mul_t1__add__t0_mul_t1 () { if (cmb.combine_ext) { CCMBEXT(GR_CMBX_ITRGB, GR_FUNC_MODE_X, GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_TEXTURE_RGB, 0, GR_CMBX_TEXTURE_RGB, 0); CC_ENV (); T0_MUL_T1 (); } else { cc_t0_mul_t1 (); } } //Added by Gonetz static void cc_shade_sub_env_mul_t0_add_prim () { if (rdp.cur_image && (rdp.cur_image->format != 0)) { cc_prim (); return; } CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIM (); SUBSHADE_ENV (); USE_T0 (); } //Added by Gonetz static void cc_shade_sub_env_mul__t0_inter_t1_using_primlod__add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIM (); SUBSHADE_ENV (); T0_INTER_T1_USING_FACTOR (lod_frac); } //Added by Gonetz static void cc_shade_sub_env_mul__t0_inter_t1_using_primlod__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); T0_INTER_T1_USING_FACTOR (lod_frac); } //Added by Gonetz static void cc_shade_sub_env_mul__t0_mul_t1__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); T0_MUL_T1 (); } //Added by Gonetz static void cc_shade_sub_env_mul__t1_sub_prim_mul_primlod_add_t0__add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); SETSHADE_ENV (); T1_SUB_PRIM_MUL_PRIMLOD_ADD_T0 (); } //Added by Gonetz static void cc_shade_sub_env_mul_t0_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); USE_T0 (); } //Added by Gonetz static void cc_shade_sub_env_mul_t0_mul_prim_add_prim_mul_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_PRIMMULENV (); SUBSHADE_ENV (); MULSHADE_PRIM() USE_T0 (); } //Added by Gonetz static void cc_shade_sub_env_mul_t1_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CC_ENV (); USE_T1 (); } //Added by Gonetz static void cc_shade_sub_env_mul_prim_add_t0 () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); SUBSHADE_ENV (); MULSHADE_PRIM (); USE_T0 (); } static void cc__t0_add_prim_mul_shade__mul_shade_add_env () { if (!cmb.combine_ext) { cc_shade_sub_env_mul_prim_add_t0 (); return; } T1CCMBEXT(GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_ITRGB, 0, GR_CMBX_B, 0); T0CCMBEXT(GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_ITRGB, 0, GR_CMBX_B, 0); CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_ZERO, GR_CMBX_ITRGB, 0, GR_CMBX_B, 0); cmb.tex_ccolor = rdp.prim_color; CC_ENV (); cmb.tex |= 1; } static void cc__t0_add_prim_mul_shade__mul_shade () { if (!cmb.combine_ext) { cc_shade_sub_env_mul_prim_add_t0 (); return; } T0CCMBEXT(GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_ITRGB, 0, GR_CMBX_B, 0); CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_ZERO, GR_FUNC_MODE_ZERO, GR_CMBX_ITRGB, 0, GR_CMBX_ZERO, 0); cmb.tex_ccolor = rdp.prim_color; cmb.tex |= 1; } //Added by Gonetz static void cc_shade_sub_env_mul_prim_add_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SUBSHADE_ENV (); MULSHADE_PRIM (); CC_ENV (); } //Added by Gonetz static void cc_shade_sub_env_mul_prima_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SUBSHADE_ENV (); MULSHADE_PRIMA (); CC_PRIM (); } static void cc_shade_sub_env_mul_k5_add_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SUBSHADE_ENV (); DWORD temp = rdp.prim_color; rdp.prim_color = rdp.K5; MULSHADE_PRIMA (); rdp.prim_color = temp; CC_PRIM (); } // ** A inter B using C ** static void cc_t0_inter_t1_using_t1a () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); T0_INTER_T1_USING_T1A (); } static void cc_t0_inter_t1_using_prima () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); BYTE factor = (BYTE)(rdp.prim_color&0xFF); T0_INTER_T1_USING_FACTOR (factor); } static void cc_t1_inter_t0_using_prima () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); BYTE factor = (BYTE)(rdp.prim_color&0xFF); T1_INTER_T0_USING_FACTOR (factor); } static void cc_t1_inter_t0_using_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); T1_INTER_T0_USING_PRIM (); } static void cc_t0_inter_t1_using_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); T0_INTER_T1_USING_ENV (); } static void cc_t0_inter_t1_using_enva () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); BYTE factor = (BYTE)(rdp.env_color&0xFF); T0_INTER_T1_USING_FACTOR (factor); } static void cc__t0_inter_t1_using_prim__inter_env_using_enva () { // (t1-t0)*prim+t0, (env-cmb)*env_a+cmb if (!cmb.combine_ext) { cc_t0_inter_t1_using_prima (); return; } T1CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_B, 0); T0CCMBEXT(GR_CMBX_OTHER_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_TMU_CCOLOR, 0, GR_CMBX_B, 0); cmb.tex_ccolor = rdp.prim_color; cmb.tex |= 3; CCMBEXT(GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_X, GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_CONSTANT_ALPHA, 0, GR_CMBX_B, 0); cmb.ccolor = rdp.env_color; } static void cc__t0_inter_t1_using_shade__inter_env_using_enva () { // (t1-t0)*shade+t0, (env-cmb)*env_a+cmb if (!cmb.combine_ext) { cc_t0_inter_t1_using_enva (); return; } T1CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_B, 0); T0CCMBEXT(GR_CMBX_OTHER_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_ITRGB, 0, GR_CMBX_B, 0); cmb.tex |= 3; CCMBEXT(GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_X, GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_CONSTANT_ALPHA, 0, GR_CMBX_B, 0); cmb.ccolor = rdp.env_color; } static void cc__t1_inter_env_using_t0__inter_prim_using_shadea () { //(env-t1)*t0+t1, (prim-cmb)*shadea+cmb if (!cmb.combine_ext) { cc_t0_add_t1 (); return; } T1CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_B, 0); T0CCMBEXT(GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_X, GR_CMBX_OTHER_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_LOCAL_TEXTURE_RGB, 0, GR_CMBX_B, 0); cmb.tex |= 3; cmb.tex_ccolor = rdp.env_color; CCMBEXT(GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_X, GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_ITALPHA, 0, GR_CMBX_B, 0); CC_PRIM(); } //Added by Gonetz static void cc_t1_inter_t0_using_shadea () { if (cmb.combine_ext) { CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_ITALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 1, GR_CMBX_ZERO, 0); } else { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); } T1_INTER_T0_USING_SHADEA (); } //Added by Gonetz static void cc_t0_inter_t1_using_primlod () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); T0_INTER_T1_USING_FACTOR (lod_frac); } //Added by Gonetz static void cc_t1_inter_t0_using_primlod () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); T1_INTER_T0_USING_FACTOR (lod_frac); } //Added by Gonetz static void cc_t1_inter_t0_using_t0 () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); T1_INTER_T0_USING_T0 (); } //Added by Gonetz static void cc_t0_inter_t1_using_k5 () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); T0_INTER_T1_USING_FACTOR (rdp.K5); } static void cc_t0_inter_env_using_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); USE_T0 (); MOD_0 (TMOD_TEX_INTER_COL_USING_COL1); MOD_0_COL (rdp.env_color & 0xFFFFFF00); MOD_0_COL1 (rdp.prim_color & 0xFFFFFF00); } //Added by Gonetz static void cc_t0_inter_prim_using_primlod () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); USE_T0 (); MOD_0 (TMOD_TEX_INTER_COLOR_USING_FACTOR); MOD_0_COL (rdp.prim_color & 0xFFFFFF00); MOD_0_FAC (lod_frac & 0xFF); } static void cc_t0_inter_shade_using_primlod () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIMLOD(); cmb.ccolor=(~cmb.ccolor)&0xFFFFFF00; MULSHADE_PRIMLOD (); USE_T0 (); //(shade-t0)*primlod+t0 = t0*(1-primlod)+shade*primlod } //Added by Gonetz static void cc__env_inter_t0_using_primlod__mul_prim () { //((t0-env)*primlod+env)*prim = t0*prim*primlod+env*prim*(1-primlod); CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_PRIM (); cmb.ccolor = ((((cmb.ccolor & 0xFF000000) >> 24) * (lod_frac & 0xFF))<<24) | ((((cmb.ccolor & 0x00FF0000) >> 16) * (lod_frac & 0xFF))<<16) | ((((cmb.ccolor & 0x0000FF00) >> 8) * (lod_frac & 0xFF))<<8); SETSHADE_PRIM (); SETSHADE_ENV (); SETSHADE_1MPRIMLOD (); USE_T0 (); } //Added by Gonetz static void cc_env_inter_prim_using_primlod () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SETSHADE_PRIMSUBENV (); SETSHADE_PRIMLOD (); CC_ENV (); } // ** (A-B)*C+D*E ** static void cc_one_sub_env_mul_prim_add__t0_mul_env () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_ENV (); SETSHADE_1MENV (); SETSHADE_PRIM (); USE_T0 (); } // ** (A inter B using C) * D ** //Added by Gonetz static void cc__t0_inter_t1_using_prima__mul_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); BYTE factor = (BYTE)(rdp.prim_color&0xFF); T0_INTER_T1_USING_FACTOR (factor); CC_PRIM (); } //Added by Gonetz static void cc__t1_inter_t0_using_prima__mul_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); BYTE factor = (BYTE)(rdp.prim_color&0xFF); T1_INTER_T0_USING_FACTOR (factor); CC_PRIM (); } //Added by Gonetz static void cc__t0_inter_t1_using_prim__mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); //BYTE factor = (BYTE)(rdp.prim_color&0xFF); T0_INTER_T1_USING_PRIM (); } //Added by Gonetz static void cc__t0_inter_t1_using_prima__mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); BYTE factor = (BYTE)(rdp.prim_color&0xFF); T0_INTER_T1_USING_FACTOR (factor); } //Added by Gonetz static void cc__t1_inter_t0_using_prima__mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); BYTE factor = (BYTE)(rdp.prim_color&0xFF); T1_INTER_T0_USING_FACTOR (factor); } static void cc__t0_inter_t1_using_env__mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); T0_INTER_T1_USING_ENV (); } static void cc__t0_inter_t1_using_enva__mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); BYTE factor = (BYTE)(rdp.env_color&0xFF); T0_INTER_T1_USING_FACTOR (factor); } static void cc__t0_inter_t1_using_enva__mul_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); BYTE factor = (BYTE)(rdp.env_color&0xFF); T0_INTER_T1_USING_FACTOR (factor); } //Added by Gonetz static void cc__t0_inter_t1_using_enva__mul_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_ENV (); BYTE factor = (BYTE)(rdp.env_color&0xFF); T0_INTER_T1_USING_FACTOR (factor); } //Added by Gonetz static void cc__t0_inter_t1_using_primlod__mul_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); T0_INTER_T1_USING_FACTOR (lod_frac); } //Added by Gonetz static void cc__t0_inter_t1_using_primlod__mul_prima () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIMA (); T0_INTER_T1_USING_FACTOR (lod_frac); } //Added by Gonetz static void cc__t1_mul_primlod_add_t0__mul_prim () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); T1_MUL_PRIMLOD_ADD_T0 (); } //Added by Gonetz static void cc__t0_inter_t1_using_primlod__mul_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_ENV (); T0_INTER_T1_USING_FACTOR (lod_frac); } //Added by Gonetz static void cc__t1_mul_primlod_add_t0__mul_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_ENV (); T1_MUL_PRIMLOD_ADD_T0 (); } //Added by Gonetz static void cc__t1_inter_t0_using_prim__mul_env () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_ENV (); T1_INTER_T0_USING_PRIM (); } static void cc__t0_inter_t1_using_primlod__mul_shade () { if (rdp.LOD_en && (rdp.mipmap_level == 0)) { cc_t0_mul_shade (); return; } CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); T0_INTER_T1_USING_FACTOR (lod_frac); } static void cc__t1_inter_t0_using_primlod__mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); T1_INTER_T0_USING_FACTOR (lod_frac); } static void cc__t0_inter_t1_using_half__mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); T0_INTER_T1_USING_FACTOR (0x7F); } static void cc__t0_inter_t1_using_t0__mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); T0_INTER_T1_USING_T0(); } static void cc__t0_inter_t1_using_t1a__mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); T0_INTER_T1_USING_T1A(); } static void cc__t0_inter_t1_using_shadea__mul_shade () { if (cmb.combine_ext) { CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_ITALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_ITRGB, 0, GR_CMBX_ZERO, 0); } else { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); } T0_INTER_T1_USING_SHADEA (); } static void cc__t0_inter_t1_using_k5__mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); T0_INTER_T1_USING_FACTOR (rdp.K5); } static void cc__t1_inter_t0_using_k5__mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); T1_INTER_T0_USING_FACTOR (rdp.K5); } static void cc_t0_inter_prim_using_prima () { if (cmb.combine_ext) { T0CCMBEXT(GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_TMU_CALPHA, 0, GR_CMBX_B, 0); cmb.tex_ccolor = rdp.prim_color; cmb.tex |= 1; CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); } else { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CC_1SUBPRIMA (); SETSHADE_PRIM (); SETSHADE_PRIMA (); USE_T0 (); } } static void cc__t0_inter_prim_using_t0a__mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MOD_0 (TMOD_TEX_INTER_COL_USING_TEXA); MOD_0_COL (rdp.prim_color & 0xFFFFFF00); USE_T0 (); } static void cc__env_inter_prim_using_t0__mul_prim () { // (prim-env)*t0+env, (cmb-0)*prim+0 CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIM (); MOD_0 (TMOD_COL_INTER_COL1_USING_TEX); MOD_0_COL (rdp.env_color & 0xFFFFFF00); MOD_0_COL1 (rdp.prim_color & 0xFFFFFF00); USE_T0 (); } static void cc__env_inter_prim_using_t0__mul_shade () { // amazing... mace actually uses the blender as part of the combine if ((rdp.othermode_l & 0xFFFF0000) == 0x03820000 || (rdp.othermode_l & 0xFFFF0000) == 0x00910000) { // blender: // 1ST = CLR_IN * A_IN + CLR_BL * 1MA // OUT = 1ST * 0 + 1ST * 1 CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MOD_0 (TMOD_COL2_INTER__COL_INTER_COL1_USING_TEX__USING_TEXA); MOD_0_COL (rdp.env_color & 0xFFFFFF00); MOD_0_COL1 (rdp.prim_color & 0xFFFFFF00); MOD_0_COL2 (rdp.blend_color & 0xFFFFFF00); USE_T0 (); } else { //(prim-env)*t0+env, (shade-0)*cmb+0 CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MOD_0 (TMOD_COL_INTER_COL1_USING_TEX); MOD_0_COL (rdp.env_color & 0xFFFFFF00); MOD_0_COL1 (rdp.prim_color & 0xFFFFFF00); USE_T0 (); } } static void cc__prim_inter_t0_using_env__mul_shade () { // (t0-prim)*env+prim, (cmb-0)*shade+0 if ((rdp.prim_color & 0xFFFFFF00) == 0) { cc_t0_mul_env_mul_shade (); return; } CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MOD_0 (TMOD_COL_INTER_TEX_USING_COL1); MOD_0_COL (rdp.prim_color & 0xFFFFFF00); MOD_0_COL1 (rdp.env_color & 0xFFFFFF00); USE_T0 (); } static void cc_prim_sub__prim_sub_t0_mul_prima__mul_shade () { // (prim-t0)*prim_a+0, (prim-cmb)*shade+0 if (cmb.combine_ext) { T0CCMBEXT(GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_TMU_CALPHA, 0, GR_CMBX_ZERO, 0); cmb.tex_ccolor = rdp.prim_color; cmb.tex |= 1; CCMBEXT(GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_X, GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_ITRGB, 0, GR_CMBX_ZERO, 0); CC_PRIM(); } else { if ((rdp.prim_color & 0xFFFFFF00) == 0) { cc_t0_mul_prima_mul_shade (); return; } CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MOD_0 (TMOD_COL_INTER_TEX_USING_COL1); MOD_0_COL (rdp.prim_color & 0xFFFFFF00); BYTE prima = (BYTE)(rdp.prim_color&0xFF); MOD_0_COL1 ((prima<<24)|(prima<<16)|(prima<<8)); USE_T0 (); } } static void cc__prim_inter_env_using_t0__mul_shade () { // (env-prim)*t0+prim, (cmb-0)*shade+0 CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MOD_0 (TMOD_COL_INTER_COL1_USING_TEX); MOD_0_COL (rdp.prim_color & 0xFFFFFF00); MOD_0_COL1 (rdp.env_color & 0xFFFFFF00); USE_T0 (); } static void cc__env_inter_prim_using_t0a__mul_t0 () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); MOD_0 (TMOD_COL_INTER_COL1_USING_TEXA__MUL_TEX); MOD_0_COL (rdp.env_color & 0xFFFFFF00); MOD_0_COL1 (rdp.prim_color & 0xFFFFFF00); USE_T0 (); } static void cc__env_inter_prim_using__t0_sub_shade_mul_primlod_add_env () { // (t0-shade)*lodf+env, (prim-env)*cmb+env if (cmb.combine_ext) { T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_ITRGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_DETAIL_FACTOR, 0, GR_CMBX_TMU_CCOLOR, 0); cmb.tex_ccolor = rdp.env_color; percent = (float)lod_frac / 255.0f; cmb.dc0_detailmax = cmb.dc1_detailmax = percent; cmb.tex |= 1; CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CC_PRIMSUBENV (); } else { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL, GR_COMBINE_FACTOR_ONE,//TEXTURE_RGB, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE);//CONSTANT); MOD_0 (TMOD_COL_INTER_COL1_USING_TEX); MOD_0_COL (rdp.env_color & 0xFFFFFF00); MOD_0_COL1 (rdp.prim_color & 0xFFFFFF00); USE_T0 (); MULSHADE_PRIMSUBENV (); MULSHADE_PRIMLOD(); SUBSHADE_PRIMSUBENV (); } } static void cc__prim_inter_t0_using_t0__mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MOD_0 (TMOD_COL_INTER_TEX_USING_TEX); MOD_0_COL (rdp.prim_color & 0xFFFFFF00); USE_T0 (); } static void cc__env_inter_t0_using_t0a__mul_shade () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MOD_0 (TMOD_COL_INTER_TEX_USING_TEXA); MOD_0_COL (rdp.env_color & 0xFFFFFF00); USE_T0 (); } static void cc_shade_mul_prima () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_ITERATED); MULSHADE_PRIMA (); } static void cc_shade_mul_shadea () { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_ITERATED); MULSHADE_SHADEA (); } static void cc__t0_mul_shade__inter_env_using_enva () { // (t0-0)*shade+0, (env-cmb)*env_a+cmb ** INC ** if (cmb.combine_ext) { T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_ITRGB, 0, GR_CMBX_ZERO, 0); cmb.tex |= 1; CCMBEXT(GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_X, GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_ITALPHA, 0, GR_CMBX_B, 0); CC_ENV (); SETSHADE_A_ENV (); } else { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); INTERSHADE_2 (rdp.env_color & 0xFFFFFF00, rdp.env_color & 0xFF); USE_T0 (); MOD_0 (TMOD_TEX_INTER_COLOR_USING_FACTOR); MOD_0_COL (rdp.env_color & 0xFFFFFF00); MOD_0_FAC (rdp.env_color & 0xFF); } } static void cc__t0_mul_shade__inter_one_using_shadea () { if (cmb.combine_ext) { T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X, GR_CMBX_ITRGB, 0, GR_CMBX_ZERO, 0); cmb.tex |= 1; CCMBEXT(GR_CMBX_ZERO, GR_FUNC_MODE_X, GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_ONE_MINUS_X, GR_CMBX_ITALPHA, 0, GR_CMBX_B, 0); } else { cc_t0_mul_shade (); } } //**************************************************************** static void ac_one () { ACMB (GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE); cmb.ccolor |= 0xFF; } static void ac_t0 () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); A_USE_T0 (); } static void ac_zero () { if (cmb.tex > 0) { ac_t0 (); return; } ACMB (GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE); cmb.ccolor &= 0xFFFFFF00; } static void ac_t1 () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); if (settings.BAR && rdp.tiles[rdp.cur_tile].format == 3) A_USE_T0 (); else A_USE_T1 (); } static void ac_prim () { ACMB (GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE); CA_PRIM (); } static void ac_primlod () { ACMB (GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE); CA_PRIMLOD (); } static void ac_one_sub_prim () { ACMB (GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE); CA_INVPRIM (); } static void ac_env () { ACMB (GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE); CA_ENV (); } static void ac_shade () { ACMB (GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_NONE); } // ** A+B ** static void ac_t0_add_t1 () //Aded by Gonetz { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); A_T0_ADD_T1 (); } static void ac__t0_mul_prim__add__t1_mul_primlod () //Aded by Gonetz { if (lod_frac == 0) { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); A_USE_T0 (); } else if ((rdp.prim_color&0xFF) == 0) { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIMLOD (); A_USE_T1 (); } else { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); A_T0_ADD_T1 (); } } static void ac_t0_add_prim () //Aded by Gonetz { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); A_USE_T0 (); } static void ac_t0_add_env () //Aded by Gonetz { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_ENV (); A_USE_T0 (); } /* static void ac_t1_add_env () //Added by Gonetz { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_ENV (); A_USE_T1 (); } */ static void ac__t0_add_t1__add_prim () //Aded by Gonetz { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); A_T0_ADD_T1 (); } static void ac_prim_add_shade () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CA_PRIM (); } static void ac_env_add_shade () //Aded by Gonetz { CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CA_ENV (); } // ** A*B ** static void ac_t0_mul_t0 () //Added by Gonetz { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); A_USE_T0 (); } static void ac_t0_mul_t1 () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); A_T0_MUL_T1 (); } static void ac_t0_mul_t1_add_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); A_T0_MUL_T1 (); } static void ac_t0_mul_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); A_USE_T0 (); } static void ac_t0_mul_prim_mul_primlod () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM_MUL_PRIMLOD (); A_USE_T0 (); } static void ac_t1_mul_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); A_USE_T1 (); } //Added by Gonetz static void ac__t1_sub_one_mul_primlod_add_t0__mul_prim () { if (cmb.combine_ext) { T1ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); T0ACMBEXT(GR_CMBX_OTHER_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_TMU_CALPHA, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_DETAIL_FACTOR, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (0xFF) ; percent = (float)lod_frac / 255.0f; } else { cmb.tmu1_a_func = GR_COMBINE_FUNCTION_BLEND_LOCAL; cmb.tmu1_a_fac = GR_COMBINE_FACTOR_DETAIL_FACTOR; percent = (255 - lod_frac) / 255.0f; cmb.tmu0_a_func = GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA; cmb.tmu0_a_fac = GR_COMBINE_FACTOR_OTHER_ALPHA; } ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); cmb.dc0_detailmax = cmb.dc1_detailmax = percent; cmb.tex |= 3; } static void ac__t0_sub_t1_mul_enva_add_t0__mul_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); if (cmb.combine_ext) { T1ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); T0ACMBEXT(GR_CMBX_OTHER_TEXTURE_ALPHA, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_TMU_CALPHA, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (rdp.env_color&0xFF) ; cmb.tex |= 3; } else { A_T0_MUL_T1 (); } } static void ac__t0_sub_one_mul_enva_add_t0__mul_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); if (cmb.combine_ext) { T0ACMBEXT(GR_CMBX_ITALPHA, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_TMU_CALPHA, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); SETSHADE_A(0xFF); cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (rdp.env_color&0xFF) ; cmb.tex |= 1; } else { A_USE_T0 (); } } static void ac__t0_sub_t1_mul_primlod_add_t0__mul_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); if (cmb.combine_ext) { T1ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); T0ACMBEXT(GR_CMBX_OTHER_TEXTURE_ALPHA, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_DETAIL_FACTOR, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); cmb.tex |= 3; percent = (float)lod_frac / 255.0f; cmb.dc0_detailmax = cmb.dc1_detailmax = percent; } else { A_T0_INTER_T1_USING_FACTOR (lod_frac); } } static void ac__t1_sub_prim_mul_primlod_add_t0__mul_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); if (cmb.combine_ext) { T1ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); T0ACMBEXT(GR_CMBX_OTHER_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_TMU_CALPHA, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_DETAIL_FACTOR, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); cmb.tex |= 3; cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (rdp.prim_color&0xFF); percent = (float)lod_frac / 255.0f; cmb.dc0_detailmax = cmb.dc1_detailmax = percent; } else { A_T0_INTER_T1_USING_FACTOR (lod_frac); } } static void ac__t1_sub_t0_mul_enva_add_t1__mul_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); if (cmb.combine_ext) { T1ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); T0ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_OTHER_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_TMU_CALPHA, 0, GR_CMBX_B, 0); cmb.tex |= 3; cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (rdp.env_color&0xFF); } else { BYTE factor = (BYTE)(rdp.env_color&0xFF); A_T0_INTER_T1_USING_FACTOR (factor); } } static void ac__t0_sub_one_mul_enva_add_t1__mul_prim () { if (cmb.combine_ext) { T1ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); T0ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_OTHER_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_TMU_CALPHA, 0, GR_CMBX_B, 0); cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (rdp.env_color&0xFF) ; cmb.tex |= 3; ACMBEXT(GR_CMBX_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_CONSTANT_ALPHA, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_ITALPHA, 0, GR_CMBX_ZERO, 0); CA_ENV (); SETSHADE_A_PRIM (); } else { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); SETSHADE_A_PRIM (); SETSHADE_A_ENV (); A_T0_MUL_T1 (); } } static void ac__t1_mul_prima_add_t0__mul_env () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_ENV (); A_T1_MUL_PRIMA_ADD_T0 (); } static void ac__t1_mul_enva_add_t0__mul_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); A_T1_MUL_ENVA_ADD_T0 (); } static void ac_t0_mul_primlod () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIMLOD (); A_USE_T0 (); } static void ac_t1_mul_primlod () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIMLOD (); A_USE_T1 (); } //Added by Gonetz static void ac__t0_add_t1__mul_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); A_T0_ADD_T1 (); } //Added by Gonetz static void ac__t0_add_t1__mul_primlod () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIMLOD (); A_T0_ADD_T1 (); } //Added by Gonetz static void ac__t0_mul_t1__mul_primlod () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIMLOD (); A_T0_MUL_T1 (); } static void ac_t0_mul_env () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_ENV (); A_USE_T0 (); } static void ac_t0_mul_env_mul_primlod () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_ENV_MUL_PRIMLOD (); A_USE_T0 (); } static void ac_t1_mul_env () //Added by Gonetz { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_ENV (); A_USE_T1 (); } static void ac__t1_sub_one_mul_primlod_add_t0__mul_env () { if (cmb.combine_ext) { T1ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); T0ACMBEXT(GR_CMBX_OTHER_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_TMU_CALPHA, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_DETAIL_FACTOR, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (0xFF) ; percent = (float)lod_frac / 255.0f; } else { cmb.tmu1_a_func = GR_COMBINE_FUNCTION_BLEND_LOCAL; cmb.tmu1_a_fac = GR_COMBINE_FACTOR_DETAIL_FACTOR; percent = (255 - lod_frac) / 255.0f; cmb.tmu0_a_func = GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA; cmb.tmu0_a_fac = GR_COMBINE_FACTOR_OTHER_ALPHA; } ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_ENV (); cmb.dc0_detailmax = cmb.dc1_detailmax = percent; cmb.tex |= 3; } static void ac_t0_mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); A_USE_T0 (); } static void ac_t1_mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); A_USE_T1 (); } //Added by Gonetz static void ac__t0_add_t1__mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); A_T0_ADD_T1 (); } static void ac__t1_mul_prima_add_t0__mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); A_T1_MUL_PRIMA_ADD_T0 (); } //Added by Gonetz static void ac__t0_sub_t1__mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); if (cmb.combine_ext) { T1ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_B, 0); T0ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_OTHER_TEXTURE_ALPHA, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_ZERO, 1, GR_CMBX_ZERO, 0); cmb.tex |= 3; } else { A_T0_SUB_T1 (); } } static void ac__t1_mul_t1_add_t1__mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); if (cmb.combine_ext) { T1ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); T0ACMBEXT(GR_CMBX_OTHER_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 1, GR_CMBX_ZERO, 0); cmb.tex |= 2; } else { A_USE_T1 (); } } static void ac__t1_mul_enva_add_t0__mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); A_T1_MUL_ENVA_ADD_T0 (); } static void ac__t1_sub_one_mul_primlod_add_t0__mul_shade () { if (cmb.combine_ext) { T1ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); T0ACMBEXT(GR_CMBX_OTHER_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_TMU_CALPHA, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_DETAIL_FACTOR, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (0xFF) ; percent = (float)lod_frac / 255.0f; } else { cmb.tmu1_a_func = GR_COMBINE_FUNCTION_BLEND_LOCAL; cmb.tmu1_a_fac = GR_COMBINE_FACTOR_DETAIL_FACTOR; percent = (255 - lod_frac) / 255.0f; cmb.tmu0_a_func = GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA; cmb.tmu0_a_fac = GR_COMBINE_FACTOR_OTHER_ALPHA; } ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); cmb.dc0_detailmax = cmb.dc1_detailmax = percent; cmb.tex |= 3; } static void ac__t1_sub_shade_mul_primlod_add_t0__mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); if (cmb.combine_ext) { T1ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); T0ACMBEXT(GR_CMBX_OTHER_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_ITALPHA, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_DETAIL_FACTOR, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); cmb.tex |= 3; percent = (float)lod_frac / 255.0f; cmb.dc0_detailmax = cmb.dc1_detailmax = percent; } else { A_T0_INTER_T1_USING_FACTOR (lod_frac); } } //Added by Gonetz static void ac_prim_mul_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CA_PRIM (); SETSHADE_A_PRIM (); } //Added by Gonetz static void ac_prim_mul_primlod () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CA_PRIMLOD (); SETSHADE_A_PRIM (); } static void ac_prim_mul_env () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CA_ENV (); SETSHADE_A_PRIM (); } static void ac__prim_sub_one_mul_primlod_add_t0__mul_env () { if (cmb.combine_ext) { T0ACMBEXT(GR_CMBX_ITALPHA, GR_FUNC_MODE_X, GR_CMBX_TMU_CALPHA, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_DETAIL_FACTOR, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); SETSHADE_A_PRIM (); cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (0xFF) ; percent = (float)lod_frac / 255.0f; cmb.dc0_detailmax = cmb.dc1_detailmax = percent; cmb.tex |= 1; } else { A_USE_T0 (); } ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_ENV (); } static void ac_prim_mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CA_PRIM (); } static void ac_env_mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CA_ENV (); } static void ac_primlod_mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CA_PRIMLOD (); } // ** A-B ** static void ac_prim_sub_t0 () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); A_USE_T0 (); MOD_0 (TMOD_FULL_COLOR_SUB_TEX); MOD_0_COL (rdp.prim_color); } // ** A*B+C ** static void ac_t1_mul_prima_add_t0 () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); A_T1_MUL_PRIMA_ADD_T0 (); } //Added by Gonetz static void ac_t0_mul_prim_add_env () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SETSHADE_A_PRIM (); CA_ENV (); A_USE_T0 (); } //Added by Gonetz static void ac__t0_add_t1__mul_prim_add_env () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SETSHADE_A_PRIM (); CA_ENV (); A_T0_ADD_T1 (); } //Aded by Gonetz static void ac__t0_inter_t1_using_enva__mul_prim_add_env () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SETSHADE_A_PRIM (); CA_ENV (); BYTE factor = (BYTE)(rdp.env_color&0xFF); A_T0_INTER_T1_USING_FACTOR (factor); } //Aded by Gonetz static void ac_t0_mul_primlod_add_t0 () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); if (cmb.combine_ext) { T0ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_DETAIL_FACTOR, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); cmb.tex |= 1; percent = (float)lod_frac / 255.0f; cmb.dc0_detailmax = cmb.dc1_detailmax = percent; } else { A_USE_T0 (); } } //Aded by Gonetz static void ac_t1_mul_primlod_add_t0 () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); A_T1_MUL_PRIMLOD_ADD_T0 (); } //Aded by Gonetz static void ac_t0_mul_primlod_add_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CA_PRIMLOD (); SETSHADE_A_PRIM (); A_USE_T0 (); } //Aded by Gonetz static void ac__t0_add_t1__mul_primlod_add_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CA_PRIMLOD (); SETSHADE_A_PRIM (); A_T0_ADD_T1 (); } //Added by Gonetz static void ac_t0_mul_env_add_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SETSHADE_A_ENV (); CA_PRIM (); A_USE_T0 (); } //Added by Gonetz static void ac_t1_mul_prim_add_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SETSHADE_A_PRIM (); CA_PRIM (); A_USE_T1 (); } //Added by Gonetz static void ac_prim_mul_shade_add_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CA_PRIM (); } //Added by Gonetz static void ac_t0_mul_shade_add_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CA_PRIM (); A_USE_T0 (); } static void ac_t0_mul_shade_add_env () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CA_ENV (); A_USE_T0 (); } // ** A*B+C*D ** static void ac_t0_mul_prim_add_shade_mul_one_minus_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); MULSHADE_A_1MPRIM (); CA_PRIM (); A_USE_T0 (); } // ** A*B*C ** static void ac__t0_mul_t1__mul_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); A_T0_MUL_T1 (); } static void ac__t0_mul_t1__mul_env () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_ENV (); A_T0_MUL_T1 (); } static void ac__t0_mul_t1__mul_env_mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_A_ENV (); A_T0_MUL_T1 (); } static void ac__t0_mul_t1__mul_prim_mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_A_PRIM (); A_T0_MUL_T1 (); } static void ac__t0_mul_t1__mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); A_T0_MUL_T1 (); } //Added by Gonetz static void ac_t0_mul_prim_mul_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); SETSHADE_A_PRIM (); MULSHADE_A_PRIM (); A_USE_T0 (); } static void ac_t0_mul_prim_mul_env () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIMENV(); A_USE_T0 (); } static void ac_t0_mul_prim_mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_A_PRIM (); A_USE_T0 (); } static void ac_t1_mul_prim_mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_A_PRIM (); A_USE_T1 (); } static void ac_t0_mul_env_mul_shade () { if (rdp.cur_image && (rdp.cur_image->format != 0)) { ac_shade (); return; } ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_A_ENV (); A_USE_T0 (); } static void ac_t1_mul_env_mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_A_ENV (); A_USE_T1 (); } static void ac_t0_mul_primlod_mul_prim () //Aded by Gonetz { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); cmb.ccolor |= (DWORD)(lod_frac * (rdp.prim_color&0xFF) / 255); A_USE_T0 (); } // ** (A+B)*C ** static void ac_prim_add_env_mul_t0 () //Aded by Gonetz { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); SETSHADE_A_PRIM (); ADDSHADE_A_ENV (); A_USE_T0 (); } static void ac_t1_add_prim_mul_env () //Aded by Gonetz { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CA_ENV (); SETSHADE_A_PRIM (); SETSHADE_A_ENV (); A_USE_T1 (); //(t1+prim)*env = t1*env + prim*env } // ** A-B*C ** static void ac_t0_sub_prim_mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_A_PRIM (); A_USE_T0 (); } // ** (A-B)*C ** static void ac__t1_mul_primlod_add_t0__sub_env_mul_prim () //Aded by Gonetz { if (cmb.combine_ext) { ACMBEXT(GR_CMBX_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_CONSTANT_ALPHA, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_ITALPHA, 0, GR_CMBX_ZERO, 0); CA_ENV (); SETSHADE_A_PRIM (); } else { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); } A_T1_MUL_PRIMLOD_ADD_T0 (); } static void ac_one_sub_t0_mul_prim () //Aded by Gonetz { ACMB (GR_COMBINE_FUNCTION_BLEND_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE); CA_PRIM (); A_USE_T0 (); } static void ac_one_sub_t0_mul_shade () //Aded by Gonetz { if (!rdp.hires_tex) { ac_zero(); return; } ACMB (GR_COMBINE_FUNCTION_BLEND_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_NONE); A_USE_T0 (); } static void ac_one_sub_prim_mul_t0 () //Aded by Gonetz { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); A_USE_T0 (); } static void ac_one_sub_env_mul_t0 () //Aded by Gonetz { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_ENV (); A_USE_T0 (); } static void ac_one_sub_shade_mul_t0 () //Aded by Gonetz { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); A_USE_T0 (); } static void ac_prim_sub_shade_mul_t0 () //Aded by Gonetz { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CA_PRIM (); A_USE_T0 (); } static void ac_shade_sub_env_mul_t0 () //Aded by Gonetz { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CA_ENV (); A_USE_T0 (); } // ** (A-B)*C*D ** static void ac_one_sub_t0_mul_prim_mul_shade () //Aded by Gonetz { ACMB (GR_COMBINE_FUNCTION_BLEND_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_NONE); MULSHADE_A_PRIM (); A_USE_T0 (); } // ** (A-B)*C+D ** static void ac__t0_sub_prim_mul_shade_add_shade__mul_env () //Aded by Gonetz { if (cmb.combine_ext) { T0ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_TMU_CALPHA, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_ITALPHA, 0, GR_CMBX_ITALPHA, 0); cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (rdp.prim_color&0xFF) ; cmb.tex |= 1; ACMBEXT(GR_CMBX_ZERO, GR_FUNC_MODE_ZERO, GR_CMBX_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_CONSTANT_ALPHA, 0, GR_CMBX_ZERO, 0); CA_ENV(); } else { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_A_ENV (); MOD_0 (TMOD_TEX_SUB_COL); MOD_0_COL (rdp.prim_color & 0xFF); A_USE_T0 (); } } static void ac_t0_sub_one_mul_enva_add_t1 () //Aded by Gonetz { if (cmb.combine_ext) { T1ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); T0ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_OTHER_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_TMU_CALPHA, 0, GR_CMBX_B, 0); cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (rdp.env_color&0xFF) ; cmb.tex |= 3; ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_ENV(); } else { ac__t0_mul_t1__mul_env (); } } static void ac_t1_sub_one_mul_enva_add_t0 () //Aded by Gonetz { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); if (cmb.combine_ext) { T1ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); T0ACMBEXT(GR_CMBX_OTHER_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_ITALPHA, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_TMU_CALPHA, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (rdp.env_color&0xFF) ; SETSHADE_A (0xFF); cmb.tex |= 3; } else { A_USE_T0 (); } } static void ac_t1_sub_one_mul_primlod_add_t0 () //Aded by Gonetz { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); if (cmb.combine_ext) { T1ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); T0ACMBEXT(GR_CMBX_OTHER_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_TMU_CALPHA, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_DETAIL_FACTOR, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (0xFF) ; percent = (float)lod_frac / 255.0f; cmb.dc0_detailmax = cmb.dc1_detailmax = percent; cmb.tex |= 3; } else { // A_T0_MUL_T1 (); // A_T1_MUL_PRIMLOD_ADD_T0 (); cmb.tmu1_a_func = GR_COMBINE_FUNCTION_BLEND_LOCAL; cmb.tmu1_a_fac = GR_COMBINE_FACTOR_DETAIL_FACTOR; percent = (255 - lod_frac) / 255.0f; cmb.tmu0_a_func = GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA; cmb.tmu0_a_fac = GR_COMBINE_FACTOR_OTHER_ALPHA; cmb.dc0_detailmax = cmb.dc1_detailmax = percent; cmb.tex |= 3; } } static void ac_t1_sub_prim_mul_shade_add_prim () //Aded by Gonetz { if (cmb.combine_ext) { T1ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_TMU_CALPHA, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_ITALPHA, 0, GR_CMBX_B, 0); T0ACMBEXT(GR_CMBX_OTHER_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 1, GR_CMBX_ZERO, 0); cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (rdp.prim_color&0xFF) ; cmb.tex |= 2; ACMBEXT(GR_CMBX_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_ZERO, GR_FUNC_MODE_X, GR_CMBX_ZERO, 1, GR_CMBX_ZERO, 0); } else { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CA_PRIM (); MOD_1 (TMOD_TEX_SUB_COL); MOD_1_COL (rdp.prim_color & 0xFF); A_USE_T1 (); } } static void ac_t0_sub_env_mul_prim_add_env () //Aded by Gonetz { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SETSHADE_A_PRIM (); CA_ENV1MPRIM (); A_USE_T0 (); //(t0-env)*prim+env == t0*prim + env*(1-prim) } static void ac__one_sub_t0_mul_t1_add_t0__mul_prim () //Aded by Gonetz { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); rdp.best_tex = 0; cmb.tex |= 3; cmb.tmu1_a_func = GR_COMBINE_FUNCTION_LOCAL; cmb.tmu0_a_func = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL; cmb.tmu0_a_fac = GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA; } static void ac_one_sub_t0_mul_prim_add_t0 () //Aded by Gonetz { ACMB (GR_COMBINE_FUNCTION_BLEND, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); SETSHADE_A_PRIM (); CA (0xFF); A_USE_T0 (); } static void ac_one_sub_t0_mul_env_add_t0 () //Aded by Gonetz { ACMB (GR_COMBINE_FUNCTION_BLEND, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); SETSHADE_A_ENV (); CA (0xFF); A_USE_T0 (); } static void ac_one_sub_t0_mul_primlod_add_prim () //Aded by Gonetz { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); SETSHADE_A_PRIM (); CA_PRIMLOD(); A_USE_T0 (); } static void ac_prim_sub_t0_mul_env_add_t0 () //Aded by Gonetz { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CA_INVENV (); SETSHADE_A_PRIM (); SETSHADE_A_ENV (); A_USE_T0 (); //(prim-t0)*env+t0 = prim*env + t0*(1-env) } static void ac_prim_sub_env_mul_t0_add_env () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CA_PRIM (); SETSHADE_A_ENV (); A_USE_T0 (); } static void ac_prim_sub_env_mul_t1_add_env () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CA_PRIM (); SETSHADE_A_ENV (); A_USE_T1 (); } //Added by Gonetz static void ac_prim_sub_env_mul_shade_add_env () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CA_ENV (); MULSHADE_A_PRIMSUBENV (); } //Added by Gonetz static void ac_prim_sub_env_mul_shade_add_env_mul_t1 () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CA_ENV (); MULSHADE_A_PRIMSUBENV (); A_USE_T1 (); } //Added by Gonetz static void ac_prim_sub_shade_mul_t0_add_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CA_PRIM (); A_USE_T0 (); } //Added by Gonetz static void ac_one_sub_shade_mul_t1_add_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); A_USE_T1 (); } //Added by Gonetz static void ac_one_sub_env_mul_shade_add_env () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CA_ENV (); } //Added by Gonetz static void ac_env_sub_prim_mul_t0_add_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CA_ENV (); SETSHADE_A_PRIM (); A_USE_T0 (); } static void ac_env_sub_prim_mul_shade_add_prim () //Added by Gonetz { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CA_PRIM (); MULSHADE_A_ENVSUBPRIM (); } static void ac_env_sub_primshade_mul_t1_add_primshade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CA_ENV (); MULSHADE_A_PRIM (); A_USE_T1 (); } static void ac_one_sub_prim_mul_t0_add_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CA (0xFF); SETSHADE_A_PRIM (); A_USE_T0 (); } static void ac_one_sub_prim_mul_t0_add__prim_mul_env () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_CONSTANT); CA_INVPRIM (); SETSHADE_A_PRIM (); SETSHADE_A_ENV (); A_USE_T0 (); } // ** A inter B using C ** static void ac_t0_inter_t1_using_prima () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); BYTE factor = (BYTE)(rdp.prim_color&0xFF); A_T0_INTER_T1_USING_FACTOR (factor); } static void ac_t1_inter_t0_using_prima () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); BYTE factor = (BYTE)(rdp.prim_color&0xFF); A_T1_INTER_T0_USING_FACTOR (factor); } static void ac_t0_inter_t1_using_primlod () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); A_T0_INTER_T1_USING_FACTOR (lod_frac); } static void ac_t0_inter_t1_using_enva () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); BYTE factor = (BYTE)(rdp.env_color&0xFF); A_T0_INTER_T1_USING_FACTOR (factor); } static void ac_t1_inter_t0_using_enva () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); BYTE factor = (BYTE)(rdp.env_color&0xFF); A_T1_INTER_T0_USING_FACTOR (factor); } //Added by Gonetz static void ac_t0_inter_t1_using_t0a () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); A_T0_INTER_T1_USING_T0A (); } //Added by Gonetz static void ac_t0_inter_t1_using_t1a () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); A_T0_INTER_T1_USING_T1A (); } //Added by Gonetz static void ac_t0_inter_t1_using_shadea () { if (cmb.combine_ext) { ACMBEXT(GR_CMBX_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_ITALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 1, GR_CMBX_ZERO, 0); } else { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE); } A_T0_INTER_T1_USING_SHADEA (); } // ** (A inter B using C) * D ** static void ac__t0_inter_t1_using_primlod__mul_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); A_T0_INTER_T1_USING_FACTOR (lod_frac); } static void ac__t1_mul_primlod_add_t0__mul_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); A_T1_MUL_PRIMLOD_ADD_T0 (); } static void ac__t0_inter_t1_using_primlod__mul_env () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_ENV (); A_T0_INTER_T1_USING_FACTOR (lod_frac); } static void ac__t1_mul_primlod_add_t0__mul_env () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_ENV (); A_T1_MUL_PRIMLOD_ADD_T0 (); } static void ac__t0_inter_t1_using_primlod__mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); A_T0_INTER_T1_USING_FACTOR (lod_frac); } static void ac__t1_mul_primlod_add_t0__mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); A_T1_MUL_PRIMLOD_ADD_T0 (); } //Added by Gonetz static void ac__t0_inter_t1_using_prima__mul_env () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_ENV (); BYTE factor = (BYTE)(rdp.prim_color&0xFF); A_T0_INTER_T1_USING_FACTOR (factor); } //Added by Gonetz static void ac__t1_inter_t0_using_t0a__mul_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); A_T1_INTER_T0_USING_T0A (); } static void ac__t1_inter_t0_using_prima__mul_env () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_ENV (); BYTE factor = (BYTE)(rdp.prim_color&0xFF); A_T1_INTER_T0_USING_FACTOR (factor); } //Added by Gonetz static void ac__t0_inter_t1_using_prima__mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); BYTE factor = (BYTE)(rdp.prim_color&0xFF); A_T0_INTER_T1_USING_FACTOR (factor); } static void ac__t1_inter_t0_using_prima__mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); BYTE factor = (BYTE)(rdp.prim_color&0xFF); A_T1_INTER_T0_USING_FACTOR (factor); } static void ac__t0_inter_t1_using_enva__mul_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); BYTE factor = (BYTE)(rdp.env_color&0xFF); A_T0_INTER_T1_USING_FACTOR (factor); } static void ac__env_sub_one_mul_t1_add_t0__mul_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); if (cmb.combine_ext) { T1ACMBEXT(GR_CMBX_TMU_CALPHA, GR_FUNC_MODE_X, GR_CMBX_ITALPHA, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0, GR_CMBX_ZERO, 0); T0ACMBEXT(GR_CMBX_OTHER_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_ZERO, 1, GR_CMBX_ZERO, 0); SETSHADE_A(0xFF); cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (rdp.env_color&0xFF) ; cmb.tex |= 3; } else { BYTE factor = (BYTE)(rdp.env_color&0xFF); A_T0_INTER_T1_USING_FACTOR (factor); } } static void ac__t0_inter_t1_using_enva__mul_primlod () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIMLOD (); BYTE factor = (BYTE)(rdp.env_color&0xFF); A_T0_INTER_T1_USING_FACTOR (factor); } static void ac__t0_inter_t1_using_enva__mul_prim_mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); MULSHADE_PRIM (); BYTE factor = (BYTE)(rdp.env_color&0xFF); A_T0_INTER_T1_USING_FACTOR (factor); } //Added by Gonetz static void ac__t0_inter_t1_using_t0a__mul_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); A_T0_INTER_T1_USING_T0A (); } //Added by Gonetz static void ac__t0_inter_t1_using_t1a__mul_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); A_T0_INTER_T1_USING_T1A (); } //Added by Gonetz static void ac__t0_inter_t1_using_shadea__mul_prim () { if (cmb.combine_ext) { ACMBEXT(GR_CMBX_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_ITALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_CONSTANT_ALPHA, 0, GR_CMBX_ZERO, 0); A_T0_INTER_T1_USING_SHADEA (); } else { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); A_T0_INTER_T1_USING_FACTOR (0x7F); } CA_PRIM (); } //Added by Gonetz static void ac__t0_inter_t1_using_shadea__mul_env () { if (cmb.combine_ext) { ACMBEXT(GR_CMBX_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_ITALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_CONSTANT_ALPHA, 0, GR_CMBX_ZERO, 0); A_T0_INTER_T1_USING_SHADEA (); } else { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); A_T0_INTER_T1_USING_FACTOR (0x7F); } CA_ENV (); } //Added by Gonetz static void ac__t0_inter_t1_using_enva__mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); BYTE factor = (BYTE)(rdp.env_color&0xFF); A_T0_INTER_T1_USING_FACTOR (factor); } //Added by Gonetz static void ac__t0_inter_t1_using_primlod__mul_shade_add_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); CA_PRIM (); A_T0_INTER_T1_USING_FACTOR (lod_frac); } //Added by Gonetz static void ac__t0_inter_t1_using_primlod__mul_env_add__t0_inter_t1_using_primlod () { if (cmb.combine_ext) { ACMBEXT(GR_CMBX_ZERO, GR_FUNC_MODE_ZERO, GR_CMBX_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_CONSTANT_ALPHA, 0, GR_CMBX_B, 0); CA_ENV (); } else { ACMB (GR_COMBINE_FUNCTION_BLEND, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SETSHADE_A_ENV (); CA (0xFF); } A_T0_INTER_T1_USING_FACTOR (lod_frac); } static void ac__t1_sub_one_mul_enva_add_t0__mul_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); if (cmb.combine_ext) { T1ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); T0ACMBEXT(GR_CMBX_OTHER_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_TMU_CALPHA, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_DETAIL_FACTOR, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (0xFF) ; cmb.tex |= 3; cmb.dc0_detailmax = cmb.dc1_detailmax = (float)(rdp.env_color&0xFF) / 255.0f; } else { // (t1-1)*env+t0, (cmb-0)*prim+0 A_T0_MUL_T1 (); MOD_1 (TMOD_TEX_SCALE_FAC_ADD_FAC); MOD_1_FAC (rdp.env_color & 0xFF); } } static void ac__t1_sub_one_mul_enva_add_t0__mul_shade () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_LOCAL, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_TEXTURE); CA_PRIM (); if (cmb.combine_ext) { T1ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO, GR_CMBX_ZERO, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); T0ACMBEXT(GR_CMBX_OTHER_TEXTURE_ALPHA, GR_FUNC_MODE_X, GR_CMBX_TMU_CALPHA, GR_FUNC_MODE_NEGATIVE_X, GR_CMBX_DETAIL_FACTOR, 0, GR_CMBX_LOCAL_TEXTURE_ALPHA, 0); cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | 0xFF ; percent = (rdp.env_color&0xFF) / 255.0f; cmb.dc0_detailmax = cmb.dc1_detailmax = percent; cmb.tex |= 3; } else { BYTE factor = (BYTE)(rdp.env_color&0xFF); A_T0_INTER_T1_USING_FACTOR (factor); } } static void ac_zero_sub_prim_mul_t0_add_prim () { ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_ITERATED); SETSHADE_A (0); CA_PRIM (); A_USE_T0 (); } static void ac_one_sub_t0_mul_primshade () { ACMB (GR_COMBINE_FUNCTION_BLEND_LOCAL, GR_COMBINE_FACTOR_TEXTURE_ALPHA, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_NONE); MULSHADE_A_PRIM (); A_USE_T0 (); } //**************************************************************** // Combine List // // 3/13/02: I have converted the combine descriptions, now using // the correct values for each slot, instead of a one-for-all- // slot version. All of the descriptions marked with 'z' have // not yet been converted or checked. I have not totally redone // the modes, because they should be for the most part correct // as they are, even with the wrong descriptions. [Dave2001] //**************************************************************** //#define cmb(x) (DWORD)(x) #define cmb(x) (x) typedef void (*cmb_func)(); struct cmb_list_entry { DWORD key; cmb_func func; }; static cmb_list_entry color_cmb_list[] = { // { #CCSTART } // intro, Aidyn Chronicles. Added by Gonetz // (0-cmb)*env+cmb, (t1-t0)*0+t0 { 0x05083812, cmb(cc_t0) }, //terminal, Spacestation Silicon Valley. Added by Gonetz // (0-0)*0+cmb, (0-0)*0+prim { 0x1fff7fff, cmb(cc_prim) }, //chip in Spacestation Silicon Valley intro. Added by Gonetz // (0-0)*0+cmb, (prim-0)*shade+0 { 0x1fffe4f3, cmb(cc_prim_mul_shade) }, // car, beetle adventure racing. Added by Gonetz // (t1-t0)*t0+t0, (cmb-shade)*prima+shade **can work incorrect** { 0x21128a40, cmb(cc__t0_inter_t1_using_t0__sub_shade_mul_prima_add_shade) }, // Treasure opening, zelda // (t1-prim)*t0+t0, (prim-env)*cmb+env { 0x2132a053, cmb(cc_prim_sub_env_mul__t1_sub_prim_mul_t0_add_t0__add_env) }, // Water, doubut no mori // (t1-0)*t0+t0, (prim-0)*shade+cmb { 0x21f204f3, cmb(cc__t1_mul_t0_add_t0__add_prim_mul_shade) }, // enemy transparent, paper mario. Addd by Gonetz // (t1-t0)*t1+t0, (env-prim)*cmb+prim { 0x22126035, cmb(cc_env_sub_prim_mul__t0_inter_t1_using_t1__add_prim) }, // snowhead temple, zelda 2. Addd by Gonetz // (t1-t0)*t1+t0, (cmb-0)*shade+prim { 0x221264f0, cmb(cc__t0_inter_t1_using_t1__mul_shade_add_prim) }, // snowhead temple entrance, zelda 2. Addd by Gonetz // (t1-t0)*t1+t0, (cmb-0)*prim+shade { 0x221283f0, cmb(cc__t0_inter_t1_using_t1__mul_prim_add_shade) }, // teleportation, Spacestation Silicon Valley. Added by Gonetz // (t1-t0)*t1+t0, (prim-env)*cmb+env { 0x2212a053, cmb(cc_prim_sub_env_mul__t0_inter_t1_using_t1__add_env) }, // Some gannon spell, zelda // (t1-0)*t1+t0, (prim-0)*cmb+0 { 0x22f2e0f3, cmb(cc__t1_mul_t1_add_t0__mul_prim) }, // battle tanks 2 [Ogy] // (1-0)*t1+t0, (env-prim)*cmb+prim { 0x22f66035, cmb(cc_env_sub_prim_mul__t0_add_t1__add_prim) }, // GASP Fighters // (1-0)*t1+t0, (shade-0)*cmb+0 { 0x22f6e0f4, cmb(cc__t0_add_t1__mul_shade) }, // parts of a car, F1 World Grand Prix. Added by Gonetz // (1-0)*t1+t0, (cmb-0)*shade+0 { 0x22f6e4f0, cmb(cc__t0_add_t1__mul_shade) }, // ???, zelda // (noise-0)*t1+t0, (prim-env)*cmb+env { 0x22f7a053, cmb(cc_prim_sub_env_mul__t0_add_t1__add_env) }, // flashing arrow over buoy, wave race. Added by Gonetz // (t1-t0)*prim+t0, (env-cmb)*enva+cmb ** INC ** { 0x23120c05, cmb(cc__t0_inter_t1_using_prim__inter_env_using_enva) }, // ground, zelda2. Added by Gonetz // (t1-t0)*prim+t0, (cmb-0)*shade+0 { 0x2312e4f0, cmb(cc__t0_inter_t1_using_prim__mul_shade) }, // wwf rules // (env-t0)*prim+t0 { 0x23152315, cmb(cc_t0_inter_env_using_prim) }, // Paper Mario // (1-t0)*prim+t0, (1-t0)*t0+cmb ** INC ** { 0x23160116, cmb(cc_t0_add_prim_mul_one_sub_t0_add_t0) }, // intro, castlevania. Added by Gonetz // (1-t0)*prim+t0 { 0x23162316, cmb(cc_one_sub_t0_mul_prim_add_t0) }, // Explosions, aerofighter's assault // (1-t0)*prim+t0, (shade-0)*cmb+0 { 0x2316e0f4, cmb(cc_t0_mul_shade) }, //beetle adventure racing. Added by Gonetz // (1-t0)*prim+t0, (cmb-0)*shade+0 **INC** { 0x2316e4f0, cmb(cc_one_sub_t0_mul_prim_mul_shade) }, // Unknown player background, smash bros // (noise-t0)*prim+t0 ** INC ** // 0x23172317, cmb(cc_t0), { 0x23172317, cmb(cc_t0_inter_noise_using_prim) }, // paper mario. Added by Gonetz // (noise-prim)*prim+t0 ** INC ** { 0x23372337, cmb(cc_t0_add_prim) }, // strange mirror in stone temple, zelda 2. Added by Gonetz // (prim-env)*prim+t0, (cmb-0)*prim+0 ** INC ** { 0x2353e3f0, cmb(cc__prim_sub_env_mul_prim_add_t0__mul_prim) }, // Gilded sword, zelda 2. Added by Gonetz // (shade-env)*prim+t0, (cmb-0)*shade+env ** INC ** { 0x2354a4f0, cmb(cc__t0_add_prim_mul_shade__mul_shade_add_env) }, // Razor sword, zelda 2. Added by Gonetz // (shade-env)*prim+t0, (cmb-0)*shade+0 ** INC ** { 0x2354e4f0, cmb(cc__t0_add_prim_mul_shade__mul_shade) }, // menu, Mischief Makers. Added by Gonetz // (0-env)*prim+t0, (cmb-0)*shade+0 { 0x235f235f, cmb(cc_t0_sub__prim_mul_env) }, // Deadly Arts logo. Added by Gonetz // (t0-0)*prim+t0 { 0x23f123f1, cmb(cc_t0_mul_prim) }, // pokemon attack, Pokemon Stadium 2. Added by Gonetz // (shade-0)*prim+t0, (cmb-0)*shade+0 ** INC ** { 0x23f4e4f0, cmb(cc_t0_mul_shade) }, // Mischief Makers logo. Added by Gonetz // (env-0)*prim+t0 { 0x23f523f5, cmb(cc_prim_mul_env_add_t0) }, // Taken out bomb, zelda // (1-0)*prim+t0 { 0x23f623f6, cmb(cc_t0_add_prim) }, // Jabu-Jabu's Belly, zelda // (noise-0)*prim+t0 { 0x23f723f7, cmb(cc_t0_add_prim) }, // carmagedon // (0-0)*prim+t0 { 0x23ff23ff, cmb(cc_t0) }, // water, diddy kong racing. Added by Gonetz // (t1-t0)*shade+t0, (env-cmb)*env_a+cmb **INC** { 0x24120c05, cmb(cc__t0_inter_t1_using_shade__inter_env_using_enva) }, // ground, f-zero x // (prim-t0)*shade+t0 ** INC ** { 0x24132413, cmb(cc__one_sub_prim_mul_shade__mul_t0_add__prim_mul_shade) }, // intro, F1 Racing Championship. Added by Gonetz // (env-t0)*shade+t0 ** INC * { 0x24152415, cmb(cc_one_sub_t0_mul_shade_add_t0) }, // Sky, pilotwings // (1-t0)*shade+t0 { 0x24162416, cmb(cc_one_sub_t0_mul_shade_add_t0) }, // zelda 2 [Ogy]. Added by Gonetz // (prim-env)*shade+t0, (prim-prim)*shade+cmb ** INC ** ? { 0x24530433, cmb(cc_prim_sub_env_mul_shade_add_t0) }, // waves, Dr. Mario // (0-center)*shade+t0 { 0x246f246f, cmb(cc_t0_sub_shade) }, // lums, Rayman2. Added by Gonetz // (t0-0)*shade+t0 ** INC ** { 0x24f124f1, cmb(cc_t0) }, //this one works better // 0x24f124f1, cmb(cc_t0_mul_shade), // Goemon, mystical ninja. Added by Gonetz // (prim-0)*shade+t0 { 0x24f324f3, cmb(cc_t0_add_prim_mul_shade) }, // Sky, waverace //z (t1-t0)*env+t0 ** INC ** { 0x25122512, cmb(cc_t0_inter_t1_using_env) }, // Rare logo, Jet Force. Added by Gonetz // (t1-t0)*env+t0, (cmb-0)*prim+0 ** INC ** { 0x2512e3f0, cmb(cc__t0_inter_t1_using_enva__mul_prim) }, // ridge recer, unimp log. Added by Gonetz // (t1-t0)*env+t0, (cmb-0)*shade+0 ** INC ** { 0x2512e4f0, cmb(cc__t0_inter_t1_using_env__mul_shade) }, // menu, Mischief Makers. Added by Gonetz //(prim-t0)*env+t0 ** INC ** { 0x25132513, cmb(cc_one_sub_env_mul_t0_add_prim_mul_env) }, // Battle border, quest64 // (1-t0)*env+t0 { 0x25162516, cmb(cc_one_sub_env_mul_t0_add_env) }, // Paper Mario // (noise-t0)*env+t0 { 0x25172517, cmb(cc_t0_inter_noise_using_env) }, // the lamp in the bomb shop in town, zelda 2 [Ogy]. Added by Gonetz // (t0-t1)*env+t0, (1-env)*prim+cmb ** INC ** { 0x25210356, cmb(cc_one_sub_env_mul_prim_add__t0_inter_t1_using_env) }, // Darmani's necklace, zelda 2 [Ogy]. Added by Gonetz // (prim-shade)*env+t0, (cmb-0)*shade+0 ** INC ** { 0x2543e4f0, cmb(cc_t0_mul_shade_add_prim_mul_env) }, // 0x2543e4f0, cmb(cc_t0_mul_shade), // mystical ninja. Added by Gonetz // (1-0)*env+t0 { 0x25f625f6, cmb(cc_t0_add_env) }, // smoke, Starshot. Added by Gonetz // (1-0)*env+t0, (1-0)*cmb+0 { 0x25f6e0f6, cmb(cc_t0_add_env) }, // mega shock, Paper Mario. Added by Gonetz // (t1-0)*scale+t0, (env-center)*cmb+prim { 0x26f26065, cmb(cc__t0_add_t1__mul_env_add_prim) }, // character select, Duck Dodgers. Added by Gonetz // (prim-t0)*t0_alpha+t0, (cmb-0)*shade+0 **INC** { 0x2813e4f0, cmb(cc__t0_inter_prim_using_t0a__mul_shade) }, // intro, Duck Dodgers. Added by Gonetz // (shade-t0)*t0_alpha+t0 **INC** { 0x28142814, cmb(cc_t0) }, // F1 World Grand Prix. Added by Gonetz // (prim-0)*t0_a+t0, (cmb-0)*shade+0 ** INC ** { 0x28f3e4f0, cmb(cc__t0a_mul_prim_add_t0__mul_shade) }, // battle tanks 2 [Ogy] // (env-0)*t0_a+t0, (cmb-0)*shade+0 { 0x28f5e4f0, cmb(cc__t0a_mul_env_add_t0__mul_shade) }, // blastcorps, unimp log. Added by Gonetz // (t1-t0)*t1_alpha+t0 { 0x29122912, cmb(cc_t0_inter_t1_using_t1a) }, // paper mario. Added by Gonetz // (t1-t0)*t1_alpha+t0, (cmb-env)*env_a+env { 0x2912ac50, cmb(cc__t0_inter_t1_using_t1a__sub_env_mul_enva_add_env) }, // Rally 2000. Added by Gonetz // (t1-t0)*t1_alpha+t0, (cmb-0)*shade+0 { 0x2912e4f0, cmb(cc__t0_inter_t1_using_t1a__mul_shade) }, // ??? in zelda ending, zelda // (1-0)*t1_alpha+t0, (prim-env)*cmb+env { 0x29f6a053, cmb(cc_prim_sub_env_mul__t0_add_t1a__add_env) }, // Sky, zelda //z (t1-t0)*prim_a+t0 { 0x2a122a12, cmb(cc_t0_inter_t1_using_prima) }, // battle tanks [Ogy] // (t1-t0)*prim_a+t0, (env-prim)*cmb+prim { 0x2a126035, cmb(cc_env_sub_prim_mul__t0_inter_t1_using_prima__add_prim) }, // clothes, zelda 2. Added by Gonetz // (t1-t0)*prim_a+t0, (prim-env)*cmb+env { 0x2a12a053, cmb(cc_prim_sub_env_mul__t0_inter_t1_using_prima__add_env) }, // flame, Doraemon 2. Added by Gonetz // (t1-t0)*prim_a+t0, (cmb-0)*prim+0 { 0x2a12e3f0, cmb(cc__t0_inter_t1_using_prima__mul_prim) }, // logo, PD. Added by Gonetz // (t1-t0)*prim_a+t0, (cmb-0)*shade+0 { 0x2a12e4f0, cmb(cc__t0_inter_t1_using_prima__mul_shade) }, // 1080 snowboarding [Ogy] - 7/03/02 fixed by Dave2001. 15 Mar 2005 fixed by Gonetz. // (prim-t0)*prim_a+t0 { 0x2a132a13, cmb(cc_t0_inter_prim_using_prima) }, // menu background, Paper Mario // (prim-t0)*prim_a+t0, (prim-t1)*prim_a+t1 { 0x2a134a23, cmb(cc_t0_inter_prim_using_prima) }, // 0x2a134a23, cmb(cc_t0), // Mickey USA // (prim-t0)*prim_a+t0, (cmb-0)*shade+0 ** INC ** { 0x2a13e4f0, cmb(cc_t0_mul_shade) }, // gunfire, Sin and Punishmen. Added by Gonetz // (env-t0)*prima+t0 **INC** { 0x2a152a15, cmb(cc_t0_inter_env_using_prima) }, // Mystical Ninja // (0-t0)*prima+t0, (prim-env)*cmb+env ** INC ** { 0x2a1fa053, cmb(cc_prim_sub_env_mul__t0_sub_t0_mul_prima__add_env) }, // arena, Pokemon Stadium 2. Added by Gonetz // (shade-prim)*prim_a+t0 ** INC ** { 0x2a342a34, cmb(cc_t0_mul_shade) }, // Paper Mario // (t1-k4)*prim_a+t0, (t1-k4)*cmb_a+cmb ** INC ** { 0x2a720772, cmb(cc_t0_add_t1) }, // GASP Fighters. Added by Gonetz // (t0-0)*prim_a+t0, (cmb-center)*scale+0 ** INC ** { 0x2af1e660, cmb(cc_t0_mul_prima) }, // F1 World Grand Prix. Added by Gonetz // (t1-0)*prim_a+t0, (cmb-0)*shade+env { 0x2af2a4f0, cmb(cc__t1_mul_prima_add_t0__mul_shade_add_env) }, // tidal wave, Paper Mario. Added by Gonetz // (prim-0)*prim_a+t0 { 0x2af32af3, cmb(cc_prim_mul_prima_add_t0) }, //Spacestation Silicon Valley intro. Added by Gonetz // (t1-t0)*shade_alpha+t0, (prim-shade)*cmb+shade ** INC ** { 0x2b128043, cmb(cc_prim_sub_shade_mul__t0_inter_t1_using_shadea__add_shade) }, // water, Rocket Robot in Wheels // (t1-t0)*shade_alpha+t0, (env-shade)*cmb+shade ** INC ** { 0x2b128045, cmb(cc_env_sub_shade_mul__t0_inter_t1_using_shadea__add_shade) }, // arena, Pokemon Stadium 2 // (t1-t0)*shade_alpha+t0, (cmb-prim)*env+shade ** INC ** { 0x2b128530, cmb(cc__t0_inter_t1_using_shadea__sub_prim_mul_env_add_shade) }, // Rocket Robot in Wheels intro // (t1-t0)*shade_a+t0, (shade-0)*cmb+0 ** INC ** { 0x2b12e0f4, cmb(cc__t0_inter_t1_using_shadea__mul_shade) }, // water, Mickey USA // (t1-t0)*shade_a+t0, (cmb-0)*shade+0 ** INC ** { 0x2b12e4f0, cmb(cc__t0_inter_t1_using_shadea__mul_shade) }, // Extreme G. Added by Gonetz // (shade-t0)*shade_alpha+t0 { 0x2b142b14, cmb(cc_shade_sub_t0_mul_shadea_add_t0) }, // Jet Force Gemini. Added by Gonetz // (shade-t0)*shade_alpha+t0, (cmb-0)*prim+0 ** INC ** { 0x2b14e3f0, cmb(cc_t0_mul_prim_add_shade_mul_shadea_mul_prim) }, // Earthquake pokemon attack, Pokemon Stadium 2 [gokuss4]. Added by Gonetz // (t1-0)*shade_alpha+t0, (prim-env)*cmb+env ** INC ** { 0x2bf2a053, cmb(cc_prim_sub_env_mul__t0_add_t1__add_env) }, // pads, Pokemon Stadium 2. Added by Gonetz // (0-0)*shade_alpha+t0, (prim-env)*cmba+env { 0x2bffa753, cmb(cc_prim_sub_env_mul_t0a_add_env) }, // paper mario. Added by Gonetz // (t1-t0)*env_a+t0, (1-cmb)*prim+cmb { 0x2c120306, cmb(cc_one_sub__t0_inter_t1_using_enva__mul_prim_add__t0_inter_t1_using_enva) }, // Amoeba boss, water temple, zelda // (t1-t0)*env_a+t0, (cmb-env)*prim+t0 ** INC ** { 0x2c122350, cmb(cc__t0_inter_t1_using_enva__sub_env) }, // paper mario. Added by Gonetz // (t1-t0)*env_a+t0 { 0x2c122c12, cmb(cc_t0_inter_t1_using_enva) }, // paper mario. Added by Gonetz // (t1-t0)*env_a+t0, (1-prim)*cmb+prim { 0x2c126036, cmb(cc_one_sub_prim_mul__t0_inter_t1_using_enva__add_prim) }, // water, jet force. Added by Gonetz // (t1-t0)*env_a+t0, (prim-shade)*cmb+shade { 0x2c128043, cmb(cc_prim_sub_shade_mul__t0_inter_t1_using_enva__add_shade) }, // Faries, zelda //z (t1-t0)*env_a+t0, (prim-env)*cmb+env { 0x2c12a053, cmb(cc_prim_sub_env_mul__t0_inter_t1_using_enva__add_env) }, // paper mario. Added by Gonetz // (t1-t0)*env_a+t0, (prim-center)*cmb+env { 0x2c12a063, cmb(cc_prim_sub_env_mul__t0_inter_t1_using_enva__add_env) }, // pads, Pokemon Stadium 2. Added by Gonetz // (t1-t0)*env_a+t0, (cmb-prim)*shade+env ** INC ** { 0x2c12a430, cmb(cc__t0_inter_t1_using_enva__mul_shade_add_env) }, // Scary dead thing boss, zelda // (t1-t0)*env_a+t0, (cmb-t1)*cmb_a+env { 0x2c12a720, cmb(cc__t0_inter_t1_using_enva__mul_env) }, // something in a menu, PokemonStadium2, [Raziel64] // (t1-t0)*env_a+t0, (prim-env)*cmb_a+env { 0x2c12a753, cmb(cc_prim_sub_env_mul__t0_inter_t1_using_enva_alpha__add_env) }, // Water in zora's place, zelda // (t1-t0)*env_a+t0, (cmb-0)*prim+0 { 0x2c12e3f0, cmb(cc__t0_inter_t1_using_enva__mul_prim) }, // Ground, zelda //z (t1-t0)*env_a+t0, (cmb-k5)*shade+cmb_a { 0x2c12e4f0, cmb(cc__t0_inter_t1_using_enva__mul_shade) }, // zelda, uninmp log. Added by Gonetz //(t1-t0)*env_a+t0, (cmb-0)*env+0 { 0x2c12e5f0, cmb(cc__t0_inter_t1_using_enva__mul_env) }, // Spheres, waverace //z (env-t0)*env_a+t0 { 0x2c152c15, cmb(cc_t0_inter_env_using_enva) },//cmb(cc_t0) }, // backgrounds, Mario Golf. Added by Gonetz // (env-t0)*env_a+t0, (shade-0)*cmb+0 { 0x2c15e0f4, cmb(cc__t0_inter_env_using_enva__mul_shade) }, // ground on Volcano level, DKR, [Raziel64] // (env-t0)*env_a+t0, (cmb-0)*shade+0 { 0x2c15e4f0, cmb(cc__t0_inter_env_using_enva__mul_shade) }, // Nintendo 'N', zelda //z (t0-prim)*env_a+t0, (prim-env)*cmb+env { 0x2c31a053, cmb(cc_prim_sub_env_mul__t0_sub_prim_mul_enva_add_t0__add_env) }, // Nintendo title & saria's song, zelda //z (t1-prim)*env_a+t0, (prim-env)*cmb+env { 0x2c32a053, cmb(cc_prim_sub_env_mul__t1_sub_prim_mul_enva_add_t0__add_env) }, // Hover boots flying, zelda // (t1-prim)*env_a+t0, (prim-0)*cmb+env { 0x2c32a0f3, cmb(cc__t1_sub_prim_mul_enva_add_t0__mul_prim_add_env) }, // star beam, paper mario // (prim-env)*env_a+t0 { 0x2c532c53, cmb(cc_prim_sub_env_mul_enva_add_t0) }, // Kotake & koume's hair, zelda // (t1-0)*env_a+t0, (prim-env)*cmb+env { 0x2cf2a053, cmb(cc_prim_sub_env_mul__t1_mul_enva_add_t0__add_env) }, //Goldeneye, [Jeremy]. Added by Gonetz // (t0-t0)*lodf+t0, (cmb-0)*prim+0 { 0x2d11e3f0, cmb(cc_t0_mul_prim) }, // Indy Racing 2000. Added by Gonetz // (t1-t0)*lodf+t0, (env-cmb)*prima+cmb ** INC ** { 0x2d120a05, cmb(cc_t0_inter_t1_using_primlod) }, // (t1-t0)*lodf+t0 { 0x2d122d12, cmb(cc_t0_inter_t1_using_primlod) }, //broken wall, beetle adventure racing. Added by Gonetz // (t1-t0)*lodf+t0, (shade-prim)*cmb+prim { 0x2d126034, cmb(cc_shade_sub_prim_mul__t0_inter_t1_using_primlod__add_prim) }, //Intro, CBFD. Added by Gonetz // (t1-t0)*lodf+t0, (shade-env)*cmb+prim // 0x2d126054, cmb(cc_shade_sub_env_mul_t0_add_prim) }, { 0x2d126054, cmb(cc_shade_sub_env_mul__t0_inter_t1_using_primlod__add_prim) }, // bassmasters 2000 [Ogy] // (t1-t0)*lodf+t0, (env-0)*cmb+prim ** INC ** { 0x2d1260f5, cmb(cc_t0_mul_env_add_prim) }, // sign, CBFD. Added by Gonetz // (t1-t0)*lodf+t0, (cmb-env)*shade+prim ** INC ** { 0x2d126450, cmb(cc_t0_sub_env_mul_shade_add_prim) }, // landscape, Cruis'n Exotica. Added by Gonetz // (t1-t0)*lodf+t0, (cmb-0)*shade+prim { 0x2d1264f0, cmb(cc__t0_inter_t1_using_primlod__mul_shade_add_prim) }, // blast corps [Ogy] // (t1-t0)*lodf+t0, (0-0)*0+shade { 0x2d129fff, cmb(cc__t0_inter_t1_using_primlod__mul_shade) }, // End of level, zelda // (t1-t0)*lodf+t0, (prim-env)*cmb+env { 0x2d12a053, cmb(cc_prim_sub_env_mul__t0_inter_t1_using_primlod__add_env) }, // Rocket Robot in Wheels intro // (t1-t0)*lodf+t0, (shade-env)*cmb+env { 0x2d12a054, cmb(cc_shade_sub_env_mul__t0_inter_t1_using_primlod__add_env) }, // basket, Fox Sport // (t1-t0)*lodf+t0, (prim-env)*t0+env { 0x2d12a153, cmb(cc_prim_sub_env_mul__t0_inter_t1_using_primlod__add_env) }, // paper mario. Added by Gonetz // (t1-t0)*lodf+t0, (cmb-0)*prim+env ** INC ** { 0x2d12a3f0, cmb(cc__t0_inter_t1_using_primlod__mul_prim_add_env) }, // Tony Hawk Pro Skater // (t1-t0)*lodf+t0, (cmb-0)*shade+env { 0x2d12a4f0, cmb(cc__t0_inter_t1_using_primlod__mul_shade_add_env) }, // part of a building, Spiderman. Added by Gonetz // (t1-t0)*lodf+t0, (cmb-env)*cmba+env ** INC ** { 0x2d12a750, cmb(cc_t0_inter_t1_using_primlod) }, // Mike Piazza's Strike Zone // (t1-t0)*lodf+t0, (shade-prim)*cmb+0 { 0x2d12e034, cmb(cc_shade_sub_prim_mul__t0_inter_t1_using_primlod) }, // intro, F1 Racing Championship. Added by Gonetz // (t1-t0)*lodf+t0, (shade-env)*cmb+0 { 0x2d12e054, cmb(cc_shade_sub_env_mul__t0_inter_t1_using_primlod) }, // stands, F1 Racing Championship. Added by Gonetz // (t1-t0)*lodf+t0, (1-env)*cmb+0 { 0x2d12e056, cmb(cc_one_sub_env_mul__t0_inter_t1_using_primlod) }, // court, Mario Tennis. Added by Gonetz // (t1-t0)*lodf+t0, (prim-0)*cmb+0 { 0x2d12e0f3, cmb(cc__t0_inter_t1_using_primlod__mul_prim) }, // Rocket Robot in Wheels intro // (t1-t0)*lodf+t0, (shade-0)*cmb+0 { 0x2d12e0f4, cmb(cc__t0_inter_t1_using_primlod__mul_shade) }, // cars wheels, SF Rush 2049. Added by Gonetz // (t1-t0)*lodf+t0, (cmb-0)*prim+0 { 0x2d12e3f0, cmb(cc__t0_inter_t1_using_primlod__mul_prim) }, // Bridge, sf rush // (t1-t0)*lodf+t0, (cmb-0)*shade+0 { 0x2d12e4f0, cmb(cc__t0_inter_t1_using_primlod__mul_shade) }, // blast corps [Ogy] // (t1-t0)*lodf+t0, (t0-0)*shade+0 { 0x2d12e4f1, cmb(cc_t0_mul_shade) }, // field, Mike Piazza's Strike Zone // (t1-t0)*lodf+t0, (cmb-prim)*env+0 ** INC ** { 0x2d12e530, cmb(cc__t0_inter_t1_using_primlod__mul_env) }, // radar, Perfect Dark // (t1-t0)*lodf+t0, (cmb-0)*env+0 { 0x2d12e5f0, cmb(cc__t0_inter_t1_using_primlod__mul_env) }, // planet, Blast Corps // (t1-t0)*lodf+t0, (cmb-0)*prima+0 { 0x2d12eaf0, cmb(cc__t0_inter_t1_using_primlod__mul_prima) }, // zelda 2. Added by Gonetz // (t0-t0)*primlod+t0, (prim-env)*cmb+env { 0x2e11a053, cmb(cc_prim_sub_env_mul_t0_add_env) }, // zelda 2. Added by Gonetz // (t1-t0)*primlod+t0, (0-0)*shade+cmb { 0x2e1204ff, cmb(cc_t0_inter_t1_using_primlod) }, // zelda 2. Added by Gonetz // (t1-t0)*primlod+t0, (env-prim)*primlod+cmb { 0x2e120d35, cmb(cc_prim_sub_env_mul_primlod_add__t0_inter_t1_using_primlod) }, // lamppost, Ridge Racer. Added by Gonetz // (t1-t0)*primlod+t0 { 0x2e122e12, cmb(cc_t0_inter_t1_using_primlod) }, // Hearts, zelda //z (t1-t0)*primlod+t0, (shade-prim)*cmb+prim { 0x2e126034, cmb(cc_shade_sub_prim_mul__t0_inter_t1_using_primlod__add_prim) }, // Sunny Day, Pokemon Stadium 2 [gokuss4]. Added by Gonetz // (t1-t0)*primlod+t0, (env-prim)*cmb+prim { 0x2e126035, cmb(cc_env_sub_prim_mul__t0_inter_t1_using_primlod__add_prim) }, // snowhead temple, zelda 2. Added by Gonetz // (t1-t0)*primlod+t0, (cmb-env)*shade+prim ** INC ** { 0x2e126450, cmb(cc__t0_inter_t1_using_primlod__mul_shade_add_prim) }, // snow on a wall, snowhead temple, zelda 2. Added by Gonetz // (t1-t0)*primlod+t0, (cmb-0)*shade+prim { 0x2e1264f0, cmb(cc__t0_inter_t1_using_primlod__mul_shade_add_prim) }, // Morning Sun, Pokemon Stadium 2 [gokuss4]. Added by Gonetz // (t1-t0)*primlod+t0, (cmb-0)*0+prim ** INC **? { 0x2e127ff0, cmb(cc_prim) }, // arena, Pokemon Stadium 2. Added by Gonetz // (t1-t0)*primlod+t0, (cmb-prim)*shade+shade ** INC ** { 0x2e128430, cmb(cc__t0_inter_t1_using_primlod__mul_shade) }, // Pokemon Stadium 2. Added by Gonetz // (t1-t0)*primlod+t0, (cmb-env)*cmb+env ** INC ** { 0x2e12a050, cmb(cc_t0_inter_t1_using_primlod) }, // End of level heart, zelda // (t1-t0)*primlod+t0, (prim-env)*cmb+env { 0x2e12a053, cmb(cc_prim_sub_env_mul__t0_inter_t1_using_primlod__add_env) }, // Huge turtle appearance, zelda 2. Added by Gonetz // (t1-t0)*primlod+t0, (1-env)*cmb+env { 0x2e12a056, cmb(cc_one_sub_env_mul__t0_inter_t1_using_primlod__add_env) }, // frozen octorok, zelda 2. Added by Gonetz // (t1-t0)*primlod+t0, (prim-env)*t1+env { 0x2e12a253, cmb(cc_prim_sub_env_mul_t1_add_env) }, // fall headwaters, zelda 2. Added by Gonetz // (t1-t0)*primlod+t0, (cmb-env)*shade+env ** INC ** { 0x2e12a450, cmb(cc__t0_inter_t1_using_primlod__sub_env_mul_shade_add_env) }, // zelda 2. Added by Gonetz // (t1-t0)*primlod+t0, (cmb-0)*t1+0 ** INC ** ? { 0x2e12e2f0, cmb(cc_t0_inter_t1_using_primlod) }, // zelda 2. Added by Gonetz // (t1-t0)*primlod+t0, (cmb-0)*prim+0 { 0x2e12e3f0, cmb(cc__t0_inter_t1_using_primlod__mul_prim) }, // sky, PGA European Tour // (t1-t0)*primlod+t0, (cmb-env)*shade+0 ** INC ** { 0x2e12e450, cmb(cc__t0_inter_t1_using_primlod__mul_shade) }, // Kirby's pool, smash bros // (t1-t0)*primlod+t0, (cmb-0)*shade+0 { 0x2e12e4f0, cmb(cc__t0_inter_t1_using_primlod__mul_shade) }, //Spacestation Silicon Valley intro. Added by Gonetz // (prim-t0)*primlod+t0, (cmb-0)*shade+0 **INC** { 0x2e132e13, cmb(cc_t0_inter_prim_using_primlod) }, // explosions, daikatana. Added by Gonetz // (prim-t0)*primlod+t0, (cmb-0)*shade+0 **INC** { 0x2e13e4f0, cmb(cc_t0_mul_shade) }, //Mike Piazza's Strike Zone logo. Added by Gonetz // (shade-t0)*primlod+t0 { 0x2e142e14, cmb(cc_t0_inter_shade_using_primlod) }, // Cartridge color (transfer pak) }, Pokemon Stadium 2 [gokuss4]. Added by Gonetz // (1-t0)*primlod+t0 { 0x2e162e16, cmb(cc_one_sub_t0_mul_primlod_add_t0) }, // pokemon attack, Pokemon Stadium 2. Added by Gonetz // (1-t0)*primlod+t0, (prim-0)*cmb+0 **INC** { 0x2e16e0f3, cmb(cc_t0_mul_prim) }, // zelda 2. Added by Gonetz // (t1-t1)*primlod+t0, (prim-env)*cmb+env { 0x2e22a053, cmb(cc_prim_sub_env_mul_t0_add_env) }, // Shadow Ball, Pokemon Stadium 2 [gokuss4]. Added by Gonetz // (0-t1)*primlod+t0, (prim-env)*cmb+env ** INC ** { 0x2e2fa053, cmb(cc_prim_sub_env_mul_t0_add_env) }, // Skulltula coin solid, zelda // (t0-prim)*primlod+t0, (prim-env)*cmb+env { 0x2e31a053, cmb(cc_prim_sub_env_mul__t0_sub_prim_mul_primlod_add_t0__add_env) }, // Triforce lines, zelda // (t1-prim)*primlod+t0, (prim-shade)*cmb+shade { 0x2e328043, cmb(cc_prim_sub_shade_mul__t1_sub_prim_mul_primlod_add_t0__add_shade) }, // moon when majora defeated, zelda 2. Added by Gonetz // (t1-prim)*primlod+t0, (1-shade)*cmb+shade { 0x2e328046, cmb(cc_one_sub_shade_mul__t1_sub_prim_mul_primlod_add_t0__add_shade) }, // Fire, zelda //z (t1-prim)*primlod+t0, (prim-env)*cmb+env ** INC ** { 0x2e32a053, cmb(cc_prim_sub_env_mul__t1_sub_prim_mul_primlod_add_t0__add_env) }, // zelda 2 [Ogy]. Added by Gonetz // (t1-prim)*primlod+t0, (shade-env)*cmb+env { 0x2e32a054, cmb(cc_shade_sub_env_mul__t1_sub_prim_mul_primlod_add_t0__add_env) }, // Scary face, pokemon stadium 2 // (t1-prim)*primlod+t0, (1-env)*cmb+env { 0x2e32a056, cmb(cc_one_sub_env_mul__t1_sub_prim_mul_primlod_add_t0__add_env) }, // zelda 2. Added by Gonetz // (t1-prim)*primlod+t0, (prim-0)*cmb+env { 0x2e32a0f3, cmb(cc__t1_sub_prim_mul_primlod_add_t0__mul_prim_add_env) }, // zelda 2. Added by Gonetz // (t1-0)*primlod+t0, (prim-env)*cmb+env { 0x2ef2a053, cmb(cc_prim_sub_env_mul__t1_mul_primlod_add_t0__add_env) }, // zelda 2. Added by Gonetz // (t1-0)*primlod+t0, (cmb-0)*prim+0 { 0x2ef2e3f0, cmb(cc__t1_mul_primlod_add_t0__mul_prim) }, // zelda 2. Added by Gonetz // (t1-0)*primlod+t0, (cmb-0)*env+0 { 0x2ef2e5f0, cmb(cc__t1_mul_primlod_add_t0__mul_env) }, // gun, Doom64. Added by Gonetz // (1-0)*primlod+t0, (cmb-0)*prim+env { 0x2ef6a3f0, cmb(cc__t0_add_primlod__mul_prim_add_env) }, // walls, Doom64. Added by Gonetz // (1-0)*primlod+t0, (cmb-0)*shade+env { 0x2ef6a4f0, cmb(cc__t0_add_primlod__mul_shade_add_env) }, // Pokemon Stadium 2. Added by Gonetz // (noise-0)*primlod+t0, (prim-env)*cmb+env ** INC ** { 0x2ef7a053, cmb(cc_prim_sub_env_mul_t0_add_env) }, // Tony Hawk's Pro Skater. Added by Gonetz // (t1-t0)*k5+t0 { 0x2f122f12, cmb(cc_t0_inter_t1_using_k5) }, // F1 World Grand Prix. Added by Gonetz // (t1-t0)*k5+t0, (cmb-0)*shade+0 **INC** { 0x2f12e4f0, cmb(cc__t0_inter_t1_using_k5__mul_shade) }, // Turok 3 [scorpiove]. Added by Gonetz // (t0-k4)*k5+t0 { 0x2f712f71, cmb(cc_t0) }, // THPS 3 // (env-0)*k5+t0, { 0x2ff52ff5, cmb(cc_t0_add_env_mul_k5) }, // super bowling // (0-0)*k5+t0, { 0x2fff0000, cmb(cc_t0) }, // super bowling // (0-0)*k5+t0 { 0x2fff2fff, cmb(cc_t0) }, // RARE logo, blast corps. Added by Gonetz // (t0-0)*0+t0 { 0x3ff13ff1, cmb(cc_t0) }, // the ground below the scarecrow in the trading post in town, zelda 2 [Ogy]. Added by Gonetz // (t1-0)*0+t0, (cmb-0)*shade+0 { 0x3ff2e4f0, cmb(cc_t0_mul_shade) }, // intro, background, Dezaemon 3D // (1-0)*0+t0 { 0x3ff63ff6, cmb(cc_t0) }, // Tony Hawk's Pro Skater. Added by Gonetz // ((0-0)*0+t0, (t1-0)*shade+cmb ** INC ** { 0x3fff04f2, cmb(cc_t0) }, // Dr. Mario [Ogy]. Added by Gonetz // ((0-0)*0+t0, (prim-cmb)*env+cmb { 0x3fff0503, cmb(cc_prim_sub_t0_mul_env_add_t0) }, // Stained glass, quest64 // (0-0)*0+t0, (1-0)*env+cmb { 0x3fff05f6, cmb(cc_t0_add_env) }, // Health bar, killer instinct gold // (0-0)*0+t0, (prim-env)*prim_a+cmb { 0x3fff0a53, cmb(cc_prim_sub_env_mul_prima_add_t0) }, // Runes, Turok - Dinosaur Hunter. Added by Gonetz // (0-0)*0+t0, (env-cmb)*env_a+cmb { 0x3fff0c05, cmb(cc_t0_inter_env_using_enva) }, // intro, Mission Impossible. Added by Gonetz // (k5-k5)*0+t0, (0-0)*scale+t0 { 0x3fff26ff, cmb(cc_t0) }, // TM, mario //z (k5-k5)*0+t0 { 0x3fff3fff, cmb(cc_t0) }, // Intro, CBFD. Added by Gonetz // ((0-0)*0+t0, (shade-env)*cmb+prim { 0x3fff6054, cmb(cc_shade_sub_env_mul_t0_add_prim) }, // paper mario. Added by Gonetz // ((0-0)*0+t0, (prim-env)*cmb+env { 0x3fffa053, cmb(cc_prim_sub_env_mul_t0_add_env) }, // Objects in arena, pokemon stadium 2 // (0-0)*0+t0, (cmb-prim)*shade+env { 0x3fffa430, cmb(cc_t0_mul_prim) }, // intro, F1 Racing Championship. Added by Gonetz // (0-0)*0+t0, (shade-env)*cmb+0 { 0x3fffe054, cmb(cc_shade_sub_env_mul_t0) }, // stands, F1 Racing Championship. Added by Gonetz // (0-0)*0+t0, (1-env)*cmb+0 { 0x3fffe056, cmb(cc_one_sub_env_mul_t0) }, // ? (from log) // (0-0)*0+t0, (prim-0)*cmb+0 { 0x3fffe0f3, cmb(cc_t0_mul_prim) }, // background, GASP Fighters // (0-0)*0+t0, (shade-0)*cmb+0 { 0x3fffe0f4, cmb(cc_t0_mul_shade) }, // zelda 2 [Ogy]. Added by Gonetz // (0-0)*0+t0, (env-0)*cmb+0 { 0x3fffe0f5, cmb(cc_t0_mul_env) }, // logo, v-rally 99 // (0-0)*0+t0, (prim-0)*t0+0 { 0x3fffe1f3, cmb(cc_t0_mul_prim) }, // target hit, zelda 2. Added by Gonetz // (0-0)*0+t0, (cmb-0)*prim+0 { 0x3fffe3f0, cmb(cc_t0_mul_prim) }, // Ms. Pac-Man intro background. Added by Gonetz // (0-0)*0+t0, (cmb-0)*shade+0 { 0x3fffe4f0, cmb(cc_t0_mul_shade) }, // Wonder Project J2 logo. Added by Gonetz // (0-0)*0+t0, (t0-0)*shade+0 { 0x3fffe4f1, cmb(cc_t0_mul_shade) }, // tire trace, Monster truck madness. Added by Gonetz // (0-0)*0+t0, (cmb-0)*env+0 { 0x3fffe5f0, cmb(cc_t0_mul_env) }, // Gauntlet Legends intro. Added by Gonetz // (0-0)*0+t0, (cmb-0)*ecale+0 { 0x3fffe6f0, cmb(cc_t0) }, // tire trace, beetle adventure racing. Added by Gonetz // (t1-t0)*t0+t1, (cmb-t0)*shade+t1 **INC** { 0x41124410, cmb(cc__t0_inter_t1_using_t0__mul_shade) }, // Paper Mario. Added by Gonetz // (t0-t1)*t0+t1 **INC** { 0x41214121, cmb(cc_t1_inter_t0_using_t0) }, // Powered Star Beam, Paper Mario. Added by Gonetz // (t0-t1)*t0+t1, (env-prim)*cmb+prim **INC** { 0x41216035, cmb(cc_env_sub_prim_mul__t1_inter_t0_using_t0__add_prim) }, // wetrix raiseland [Raziel64]. Added by Gonetz // (prim-t1)*t0+t1, (env-t0)*cmb+cmb **INC** { 0x41230015, cmb(cc_env_sub_prim_mul__t0_mul_t1__add_prim) }, // SCARS. Added by Gonetz // (t1-t0)*t0+t1, (cmb-t0)*shade+t1 **INC** { 0x41250b03, cmb(cc__t0_inter_t1_using_half__mul_shade) }, //beetle adventure racing. Added by Gonetz //(env-t1)*t0+t1, (prim-cmb)*shadea+cmb **INC** { 0x4221e4f0, cmb(cc__t1_inter_env_using_t0__inter_prim_using_shadea) }, // paper mario. Added by Gonetz // (t0-t0)*prim+t1, (t1-cmb)*cmb+env **INC** weird { 0x4311a002, cmb(cc_env) }, // background, Wetrix level 1, [Raziel64]. Added by Gonetz // (t0-t1)*prim+t1 { 0x43214321, cmb(cc_t1_inter_t0_using_prim) }, // grass, ISS 2k. Added by Gonetz // (t0-t1)*prim+t1, (cmb-0)*env+0 **INC** { 0x4321e5f0, cmb(cc__t1_inter_t0_using_prim__mul_env) }, // intro, Paper Mario // (t0-0)*prim+t1 { 0x43f143f1, cmb(cc_t0_mul_prim_add_t1) }, // F1 World Grand Prix. Added by Gonetz // (t0-0)*prim+t1, (cmb-0)*shade+env **INC** { 0x43f1a4f0, cmb(cc__t0_add_t1__mul_shade_add_env) }, // field, ISS64. Added by Gonetz // (t0-t1)*shade+t1, (cmb-t1)*prim+t1 ** INC ** { 0x44214320, cmb(cc_t0_sub_t1_mul_prim_mul_shade_add_t1) }, // 0x44214320, cmb(cc__t0_add_t1__mul_prim) }, // water, goemon great adventure // (t0-t1)*env+t1 ** INC ** { 0x45214521, cmb(cc_t1_inter_t0_using_env) }, // characters, Ogre Battle. Added by Gonetz // (1-t1)*env+t1, (1-cmb)*prim+cmb ** INC ** { 0x45260306, cmb(cc_one_sub_t1_mul_prim_add_t1) }, // characters, Ogre Battle. Added by Gonetz // (1-t1)*env+t1 { 0x45264526, cmb(cc_one_sub_t1_mul_env_add_t1) }, // characters, Ogre Battle. Added by Gonetz // (1-t1)*env+t1, (cmb-0)*prim+0 ** INC ** { 0x4526e3f0, cmb(cc__t1_inter_one_using_env__mul_prim) }, // explosion, body harvest. Added by Gonetz // (t0-t1)*scale+t1, (env-prim)*cmb+prim ** INC ** { 0x46216035, cmb(cc_env_sub_prim_mul__t0_inter_t1_using_half__add_prim) }, // Water, AeroGauge. Added by Gonetz // (t0-t1)*prima+t1, (0-0)*0+cmb { 0x4a214a21, cmb(cc_t1_inter_t0_using_prima) }, // flame, castlevania 2. Added by Gonetz // (t0-t1)*prima+t1, (prim-env)*cmb+env { 0x4a21a053, cmb(cc_prim_sub_env_mul__t1_inter_t0_using_prima__add_env) }, // shadows, Mario Tennis. Added by Gonetz // (t0-t1)*prima+t1, (prim-0)*cmb+0 { 0x4a21e0f3, cmb(cc__t1_inter_t0_using_prima__mul_prim) }, // menu, Mario Golf. Added by Gonetz // (t0-t1)*prima+t1, (shade-0)*cmb+0 { 0x4a21e0f4, cmb(cc__t1_inter_t0_using_prima__mul_shade) }, // intro, castlevania 2. Added by Gonetz // (t0-t1)*prima+t1, (cmb-0)*prim+0 { 0x4a21e3f0, cmb(cc__t1_inter_t0_using_prima__mul_prim) }, // water on map, Ogre Battle64. Added by Gonetz // (t0-t1)*prima+t1, (cmb-0)*shade+0 { 0x4a21e4f0, cmb(cc__t1_inter_t0_using_prima__mul_shade) }, // Ice, Paper Mario // (t0-t1)*shade_a+t1 { 0x4b214b21, cmb(cc_t1_inter_t0_using_shadea) }, // Grass, Beetle Adventure Racing // (t0-t1)*shade_a+t1, (cmb-0)*shade+0 { 0x4b21e4f0, cmb(cc__t1_inter_t0_using_shadea__mul_shade) }, // Ground at kotake & koume, zelda // (t1-t0)*env_a+t0, (prim-env)*cmb+env { 0x4c12a053, cmb(cc_prim_sub_env_mul__t0_inter_t1_using_enva__add_env) }, // Tony Hawk's Pro Skater. Added by Gonetz // (t0-t1)*env_a+t1, (cmb-0)*shade+cmb ** INC ** { 0x4c2104f0, cmb(cc__t1_inter_t0_using_enva__mul_shade) }, // bikes, xg2. Added by Gonetz // (t0-t1)*env_a+t1, (cmb-prim)*prima+prim { 0x4c216a30, cmb(cc__t1_inter_t0_using_enva__sub_prim_mul_prima_add_prim) }, // Yoshi Story // (t0-t1)*env_a+t1, (prim-env)*cmb+env { 0x4c21a053, cmb(cc_prim_sub_env_mul__t1_inter_t0_using_enva__add_env) }, // arena, Pokemon Stadium 1. Added by Gonetz // (t0-t1)*env_a+t1, (cmb-0)*prim+0 { 0x4c21e3f0, cmb(cc__t1_inter_t0_using_enva__mul_prim) }, // "end of chapter" text, paper mario. Added by Gonetz // (1-t1)*env_a+t1, (cmb-0)*t1+0 ** INC ** { 0x4c26e2f0, cmb(cc_t0_mul_t1) }, // 0x4c26e2f0, cmb(cc_t1_mul_enva) }, // Zelda opening door, zelda // (t0-prim)*env_a+t1, (prim-env)*t0+env { 0x4c31a053, cmb(cc_prim_sub_env_mul_t0_add_env) }, // Kotake & koume magic poof, zelda // (t0-0)*env_a+t1, (prim-env)*cmb+env { 0x4cf1a053, cmb(cc_prim_sub_env_mul__t0_mul_enva_add_t1__add_env) }, // ground in stone temple, zelda 2. Added by Gonetz // (t1-t0)*primlod+t1, (cmb-0)*prim+0 { 0x4e12e3f0, cmb(cc__t0_inter_t1_using_primlod__mul_prim) }, // pokemon attack, Pokemon Stadium 2. Added by Gonetz // (noise-t0)*primlod+t1, (prim-env)*cmb+env ** INC ** { 0x4e17a053, cmb(cc_prim_sub_env_mul__t0_inter_t1_using_primlod__add_env) }, // menu, pokemon stadium 1, [Raziel64] // (t0-t1)*lodf+t1, (prim-env)*cmb+env { 0x4e214e21, cmb(cc_t1_inter_t0_using_primlod) }, // Pokemon backgrounds, pokemon stadium 2 // (t0-t1)*lodf+t1, (prim-env)*cmb+env { 0x4e21a053, cmb(cc_prim_sub_env_mul__t1_inter_t0_using_primlod__add_env) }, // zelda 2 [Ogy]. Added by Gonetz // (t0-t1)*primlod+t1, (t1-cmb)*prim+env ** INC ** { 0x4e21a302, cmb(cc_env_sub__t0_sub_t1_mul_primlod__mul_prim) }, // Magnitude, pokemon stadium 2 // (t0-t1)*primlod+t1, (prim-env)*cmb_a+env { 0x4e21a753, cmb(cc_prim_sub_env_mul__t1_inter_t0_using_primlod__add_env) }, // zelda 2 [Ogy]. Added by Gonetz // (t0-t1)*primlod+t1, (cmb-0)*shade+0 { 0x4e21e4f0, cmb(cc__t1_inter_t0_using_primlod__mul_shade) }, // lava in snowhead temple, zelda 2. Added by Gonetz // (t0-prim)*primlod+t1, (cmb-prim)*shade+cmb ** INC ** { 0x4e310430, cmb(cc_lavatex_sub_prim_mul_shade_add_lavatex) }, // Skulltula coin, zelda // (t0-prim)*primlod+t1, (prim-env)*cmb+env { 0x4e31a053, cmb(cc_prim_sub_env_mul__t0_sub_prim_mul_primlod_add_t1__add_env) }, // Pokemon background, pokemon stadium 2 // (noise-shade)*primlod+t1, (prim-env)*cmb+env { 0x4e47a053, cmb(cc_prim_sub_env_mul_t1_add_env) }, // Reflect, Pokemon Stadium 2 [gokuss4]. Added by Gonetz // (t0-0)*primlod+t1, (prim-env)*cmb+env { 0x4ef1a053, cmb(cc_prim_sub_env_mul__t0_add_t1__add_env) }, //beetle adventure racing. Added by Gonetz //(t0-t1)*k5+t1, (cmb-0)*shade+0 { 0x4f21e4f0, cmb(cc__t1_inter_t0_using_k5__mul_shade) }, // Spiderman. Added by Gonetz //(t0-t1)*k5+t1, (cmb-0)*env+0 { 0x4f21e5f0, cmb(cc_t1_mul_env) }, // N64 logo, Ogre Battle. Added by Gonetz //(0-0)*0+t1 { 0x5fff5fff, cmb(cc_t1) }, // reversing light, Monster truck madness. Added by Gonetz //(0-0)*0+t0, (0-0)*0+prim { 0x5fff7fff, cmb(cc_prim) }, // battle tanks [Ogy] // (0-0)*0+t1, (env-shade)*cmb+shade { 0x5fff8045, cmb(cc_env_sub_shade_mul_t1_add_shade) }, // minigame, pokemon stadium 1. Added by Gonetz // (0-0)*0+t1, (prim-env)*cmb+env { 0x5fffa053, cmb(cc_prim_sub_env_mul_t1_add_env) }, // F1 World Grand Prix. Added by Gonetz // (t0-prim)*t0+prim, (cmb-0)*shade { 0x6131e4f0, cmb(cc__prim_inter_t0_using_t0__mul_shade) }, // aerofighter's assault [Ogy] // (shade-prim)*t0+prim { 0x61346134, cmb(cc_shade_sub_prim_mul_t0_add_prim) }, // club blow, Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz // (shade-prim)*t0+prim, (cmb-env)*cmb_a+env ** INC ** { 0x6134a750, cmb(cc_shade_sub_prim_mul_t0_add_prim) }, // lava, beetle adventure racing // (shade-prim)*t0+prim, (cmb-0)*t1+0 ** INC ** { 0x6134e2f0, cmb(cc_shade_sub_prim_mul__t0_mul_t1__add_prim) }, // Monster truck madness intro. Added by Gonetz // (env-prim)*t0+prim, (cmb-0)*scale+cmb ** INC ** { 0x613506f0, cmb(cc_env_sub_prim_mul_t0_add_prim) }, // pokemon attack, Pokemon stadium 1 // (env-prim)*t0+prim, (cmb-0)*0+cmb { 0x61351ff0, cmb(cc_env_sub_prim_mul_t0_add_prim) }, // Paper Mario, fortune teller spheres // (env-prim)*t0+prim, (cmb-0)*t1+t0 ** INC ** { 0x613522f0, cmb(cc_t0_mul_t1_add_t0) }, // Later hearts, zelda // (env-prim)*t0+prim { 0x61356135, cmb(cc_env_sub_prim_mul_t0_add_prim) }, // Mission Impossible. Added by Gonetz // (env-prim)*t0+prim, (shade-0)*cmb+0 ** INC ** { 0x6135e0f4, cmb(cc_t0_mul_shade) }, // crashing other vehicle, Monster truck madness [Raziel64]. Added by Gonetz // (env-prim)*t0+prim, (cmb-0)*t0+0 ** INC ** { 0x6135e1f0, cmb(cc_env_sub_prim_mul_t0_add_prim) }, // Tony Hawk's Pro Skater. Added by Gonetz // (env-prim)*t0+prim, (cmb-0)*t1+0 ** INC ** { 0x6135e2f0, cmb(cc_env_sub_prim_mul_t0_add_prim) }, // aerofighter's assault [Ogy] // (env-prim)*t0+prim, (cmb-0)*shade+0 ** INC ** { 0x6135e4f0, cmb(cc__prim_inter_env_using_t0__mul_shade) }, // "time out", paper mario. Added by Gonetz // (1-prim)*t0+prim, (1-cmb)*enva+cmb ** INC ** { 0x61360c06, cmb(cc_one_sub_prim_mul_t0_add_prim) }, // intro, paper mario. Added by Gonetz // (1-prim)*t0+prim, (cmb-0)*prima+t0 ** INC ** { 0x61362af0, cmb(cc__one_sub_prim_mul_t0_add_prim__mul_prima_add__one_sub_prim_mul_t0_add_prim) }, // paper mario. Added by Gonetz // (1-prim)*t0+prim { 0x61366136, cmb(cc_one_sub_prim_mul_t0_add_prim) }, // arena, Pokemon Stadium 2. Added by Gonetz // (1-prim)*t0+prim, (cmb-env)*shade+shade ** INC ** { 0x61368450, cmb(cc_t0_mul_shade) }, // F1 World Grand Prix. Added by Gonetz // (1-prim)*t0+prim, (cmb-0)*shade+0 ** INC ** { 0x6136e4f0, cmb(cc_t0_mul_shade) }, // Xena. Added by Gonetz // (0-prim)*t0+prim { 0x613f613f, cmb(cc_one_sub_t0_mul_prim) }, // Kirby64 end [Raziel64]. Added by Gonetz // (prim-env)*t0+prim { 0x61536153, cmb(cc_prim_sub_env_mul_t0_add_prim) }, // Xena. Added by Gonetz // (shade-env)*t0+prim { 0x61546154, cmb(cc_shade_sub_env_mul_t0_add_prim) }, // Karts, mario kart //z (center-env)*t0+prim { 0x61566156, cmb(cc_t0_mul_1menv_add_prim) }, // Famista64. Added by Gonetz //(t0-0)*t0+prim { 0x61f161f1, cmb(cc_t0_mul_prim) }, // Pokemon Stadium 2. Added by Gonetz //(shade-0)*t0+prim { 0x61f461f4, cmb(cc_t0_mul_shade_add_prim) }, // Doom. Added by Gonetz //(1-0)*t0+prim { 0x61f661f6, cmb(cc_t0_add_prim) }, // tire trace, beetle adventure racing. Added by Gonetz // (shade-prim)*t1+prim, (cmb-0)*t1+0 **INC** { 0x6234e2f0, cmb(cc_shade_sub_prim_mul_t1_add_prim) }, // Text, turok // (env-prim)*t1+prim { 0x62356235, cmb(cc_env_sub_prim_mul_t1_add_prim) }, // Pokemon Stadium 2, [gokuss4]. Added by Gonetz // (env-prim)*t1+prim, (cmb-0)*t1+0 ** INC ** { 0x6235e2f0, cmb(cc_env_sub_prim_mul_t1_add_prim) }, // bike trace, xg2 intro. Added by Gonetz // (1-prim)*t1+prim { 0x62366236, cmb(cc_one_sub_prim_mul_t1_add_prim) }, // aerofighter's assault [Ogy] // (1-prim)*t1+prim, (cmb-0)*0+env { 0x6236bff0, cmb(cc_one_sub_prim_mul_t1_add_prim) }, // Tennis court, mario tennis // (t0-0)*t1+prim { 0x62f162f1, cmb(cc__t0_mul_t1__add_prim) }, // Rush2. Added by Gonetz // (prim-prim)*prim+prim { 0x63336333, cmb(cc_prim) }, //Bowser in final battle, Paper Mario. Added by Gonetz // (t1-0)*prim+prim { 0x63f263f2, cmb(cc_t1_mul_prim_add_prim) }, // wetrix, icelayer, [Raziel64]. Added by Gonetz // (t0-prim)*shade+prim ** INC ** { 0x64316431, cmb(cc_t0_mul_shade) }, // KI. Added by Gonetz // (env-prim)*shade+prim { 0x64356435, cmb(cc_env_sub_prim_mul_shade_add_prim) }, // xg2. Added by Gonetz // (1-prim)*shade+prim, (t0-0)*cmb+0 ** INC ** { 0x6436e0f1, cmb(cc_t0_mul_one_sub_prim_mul_shade) }, // Intro, CBFD. Added by Gonetz // (t0-env)*shade+prim { 0x64516451, cmb(cc_t0_sub_env_mul_shade_add_prim) }, // sword in final battle, zelda 2. Added by Gonetz // (t0-env)*shade+prim, (cmb-0)*shade+0 ** INC ** { 0x6451e4f0, cmb(cc__t0_sub_env_mul_shade_add_prim__mul_shade) }, // Road Rush. Added by Gonetz // (t0-0)*shade+prim { 0x64f164f1, cmb(cc_t0_mul_shade_add_prim) }, // paper mario. Added by Gonetz // (1-0)*shade+prim { 0x64f664f6, cmb(cc_prim_add_shade) }, // Character select, smash bros // (t0-prim)*env+prim { 0x65316531, cmb(cc_t0_sub_prim_mul_env_add_prim) }, // Clear screen intro, banjo kazooie // (t0-prim)*env+prim, (cmb-0)*shade+0 // 0x6531e4f0, cmb(cc_t0_mul_env_mul_shade) }, { 0x6531e4f0, cmb(cc__prim_inter_t0_using_env__mul_shade) }, // Dragonfly feet, banjo kazooie // (1-prim)*env+prim, (cmb-0)*shade+0 ** INC ** { 0x6536e4f0, cmb(cc_env_mul_shade) }, // Lava piranha atack, Paper Mario // (t1-k4)*env+prim ** INC ** { 0x65726572, cmb(cc_t1_mul_env_add_prim) }, // zelda 2 [Ogy]. Added by Gonetz // (t0-0)*env+prim, (1-t1)*t0a+cmb ** INC ** { 0x65f10826, cmb(cc_one_sub_t1_mul_t0a_add_t0_mul_env_add_prim) }, // clocks while warping through time, zelda 2 // (t0-0)*env+prim, (cmb-0)*0+cmb { 0x65f11ff0, cmb(cc_t0_mul_env_add_prim) }, // Helicopter, Nuclear Strike. Added by Gonetz // (t0-0)*env+prim { 0x65f165f1, cmb(cc_t0_mul_env_add_prim) }, // Mystical Ninja // (1-0)*env+prim { 0x65f665f6, cmb(cc_prim_add_env) }, // duke nukem: zero hour [Ogy] // (noise-0)*env+prim ** INC ** { 0x65f765f7, cmb(cc_prim_add_env) }, // "terminator", CBFD // (0-0)*env+prim { 0x65ff65ff, cmb(cc_prim) }, // Cliffs, Taz express. Added by Gonetz // (t0-0)*scale+prim { 0x66f166f1, cmb(cc_t0_add_prim) }, // Taz express. Added by Gonetz // (t0-0)*scale+prim, (cmb-0)*shade+0 { 0x66f1e4f0, cmb(cc_t0_add_prim_mul_shade) }, // NFL Quarterback Club 98 Menu [CpUMasteR] // (prim-0)*scale+prim { 0x66f366f3, cmb(cc_prim) }, // Character, dual heroes // (t0-prim)*t0_a+prim { 0x68316831, cmb(cc_t0_sub_prim_mul_t0a_add_prim) }, // Indy Racing 2000. Added by Gonetz // (t0-prim)*t0_a+prim, (cmb-0)*shade+0 ** INC ** { 0x6831e4f0, cmb(cc_t0_mul_shade) }, // text, Sin and Punishmen. Added by Gonetz // (env-prim)*t0_a+prim ** INC ** { 0x68356835, cmb(cc_env_sub_prim_mul_t0a_add_prim) }, // menu, PD. Added by Gonetz // (env-prim)*t1_a+prim { 0x69356935, cmb(cc_env_sub_prim_mul_t1a_add_prim) }, // 0x69356935, cmb(cc_t1) }, //xg2. Added by Gonetz // (t0-prim)*prima+prim { 0x6a316a31, cmb(cc_t0_sub_prim_mul_prima_add_prim) }, // menu, battle phoenix 64. Added by Gonetz // (env-prim)*prima+prim { 0x6a356a35, cmb(cc_env_sub_prim_mul_prima_add_prim) }, // ground, KI. Added by Gonetz // (shade-env)*prima+prim { 0x6a546a54, cmb(cc_shade_sub_env_mul_prima_add_prim) }, // F1 World Grand Prix. Added by Gonetz // (t0-0)*prima+prim, (shade-0)*cmb+env **INC** { 0x6af1a0f4, cmb(cc__t0_mul_prima_add_prim_mul__shade_add_env) }, //broken wall, beetle adventure racing. Added by Gonetz // (t0-0)*prima+prim, (cmb-0)*shade+0 **INC** { 0x6af1e4f0, cmb(cc__t0_mul_prima_add_prim_mul__shade) }, // Genie, diddy kong racing // (t0-prim)*shade_alpha+prim, (env-cmb)*shade+cmb // 0x6b310405, cmb(cc_env_sub__prim_inter_t0_using_shadea__mul_shade_add_env) }, { 0x6b310405, cmb(cc_t0_mul_shadea) }, // Extreme G. Added by Gonetz // (t0-prim)*shade_alpha+prim ** INC ** { 0x6b316b31, cmb(cc_t0_sub_prim_mul_shadea_add_prim) }, // water block, Paper Mario. Added by Gonetz // (t0-prim)*shade_alpha+prim, (prim-env)*cmb+env ** INC ** { 0x6b31a053, cmb(cc_prim_sub_env_mul__prim_inter_t0_using_shadea__add_env) }, // water, Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz // (t0-prim)*shade_alpha+prim, (cmb-0)*shade+0 ** INC ** { 0x6b31e4f0, cmb(cc__prim_inter_t0_using_shadea__mul_shade) }, // F1 World Grand Prix. Added by Gonetz // (env-prim)*shade_alpha+prim, (shade-cmb)*cmb_a+cmb ** INC ** { 0x6b350704, cmb(cc_env_sub_prim_mul_shade_add_prim) }, // lullaby, Paper Mario. Added by Gonetz // (env-prim)*shade_alpha+prim { 0x6b356b35, cmb(cc_env_sub_prim_mul_shadea_add_prim) }, // Some gannon spell, zelda // (noise-t0)*env_a+prim, (0-prim)*cmb+1 ** INC ** { 0x6c17c03f, cmb(cc_one_sub__one_sub_t0_mul_enva_add_prim__mul_prim) }, //Goldeneye, [Jeremy]. Added by Gonetz // (t0-prim)*env_a+prim { 0x6c316c31, cmb(cc_t0_sub_prim_mul_enva_add_prim) }, // button, Sin and Punishmen. Added by Gonetz // (env-prim)*env_a+prim { 0x6c356c35, cmb(cc_env_sub_prim_mul_enva_add_prim) }, // fallen stars at star summit, Paper Mario. Added by Gonetz // (t0-env)*env_a+prim, (1-0)*primlod+cmb { 0x6c510ef6, cmb(cc_t0_sub_env_mul_enva_add_prim) }, // focus, Paper Mario. Added by Gonetz // (t0-env)*env_a+prim, (cmb-shade)*shadea+shade ** INC ** { 0x6c518b40, cmb(cc_t0_sub_shade_mul_shadea_add_shade) }, // Ring, pokemon stadium 2 // (t0-0)*env_a+prim, (1-0)*cmb+0 { 0x6cf1e0f6, cmb(cc_t0_mul_enva_add_prim) }, // Jet Force // (noise-0)*env_a+prim { 0x6cf76cf7, cmb(cc_prim) }, // snowhead temple, zelda 2. Added by Gonetz // (t1-t0)*primlod+prim, (cmb-0)*shade+shade { 0x6e1284f0, cmb(cc__t1_sub_t0_mul_primlod_add_prim__mul_shade_add_shade) }, // zelda 2. Added by Gonetz // (t1-t0)*primlod+prim, (cmb-0)*shade+0 ** INC ** { 0x6e12e4f0, cmb(cc__t1_sub_t0_mul_primlod_add_prim__mul_shade) }, // sky, daikatana. Added by Gonetz // (t0-prim)*primlod+prim, (cmb-0)*shade+0 { 0x6e31e4f0, cmb(cc_t0_mul_shade) }, // ball's track, NFL Blitz. Added by Gonetz // (t0-0)*primlod+prim { 0x6ef16ef1, cmb(cc_t0_mul_primlod_add_prim) }, // Earthquake pokemon attack, Pokemon Stadium 2 [gokuss4]. Added by Gonetz // (t0-0)*primlod+prim, (cmb-env)*cmb_a+env ** INC ** { 0x6ef1a750, cmb(cc_t0_mul_primlod_add_prim) }, // rope, CBFD // (t0-env)*k5+prim { 0x6f516f51, cmb(cc_t0_sub_env_mul_k5_add_prim) }, // super bowling // (0-0)*k5+prim { 0x6fff6fff, cmb(cc_prim) }, // intro, Aidyn Chronicles. Added by Gonetz // (0-0)*0+prim, (0-0)*0+prim { 0x79fb7788, cmb(cc_prim) }, // Menu, megaman // (1-0)*0+prim { 0x7ff67ff6, cmb(cc_prim) }, // sky, PGA European Tour // (0-0)*0+prim, (env-0)*t0+cmb { 0x7fff01f5, cmb(cc_t0_mul_env_add_prim) }, // sky, Spiderman. Added by Gonetz // (0-0)*0+prim, (t1-0)*shade+cmb { 0x7fff04f2, cmb(cc_t1_mul_shade_add_prim) }, // ball's shadow, ISS 2k. Added by Gonetz // (0-0)*0+prim, (1-cmb)*env+cmb { 0x7fff0506, cmb(cc_one_sub_prim_mul_env_add_prim) }, // Necklace, quest64 // (0-0)*0+prim, (1-0)*env+cmb { 0x7fff05f6, cmb(cc_prim_add_env) }, // Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz // (0-0)*0+prim, (1-cmb)*cmba+cmb ** INC ** { 0x7fff0706, cmb(cc_prim) }, // Dobutsu no Mori. Added by Gonetz //(k5-k5)*0+prim, (cmb-0)*0+cmb { 0x7fff1ff0, cmb(cc_prim) }, // Intro background, starfox //z (k5-k5)*0+prim { 0x7fff7fff, cmb(cc_prim) }, // train smoke, Dobutsu No Mori. Added by Gonetz //(0-0)*0+prim, (shade-0)*cmb+0 { 0x7fffe0f4, cmb(cc_prim_mul_shade) }, // Donald Duck intro. Added by Gonetz //(0-0)*0+prim, (cmb-0)*prim+0 { 0x7fffe3f0, cmb(cc_prim_mul_prim) }, // Ms. Pac-Man intro. Added by Gonetz //(0-0)*0+prim, (cmb-0)*shade+0 { 0x7fffe4f0, cmb(cc_prim_mul_shade) }, // zelda 2. Added by Gonetz //(t1-t0)*t0+shade, (cmb-0)*shade+0 { 0x8112e4f0, cmb(cc__t1_sub_t0_mul_t0_add_shade__mul_shade) }, // branches, Beetle Adventure Racing //(t0-shade)*t0+shade, (t0-cmb)*prim+cmb **INC** { 0x81410301, cmb(cc_t0_mul_prim) }, // Namco logo, Famista 64 //(prim-shade)*t0+shade, (env-cmb)*t0+cmb **INC** { 0x81430105, cmb(cc_prim_sub_shade_mul_t0_add_shade) }, // pikachu, hey you pikachu //(prim-shade)*t0+shade, (env-cmb)*enva+cmb **INC** { 0x81430c05, cmb(cc_prim_sub_shade_mul_t0_add_shade) }, // Mario's head, mario //Added by Gonetz //(prim-shade)*t0+shade { 0x81438143, cmb(cc_prim_sub_shade_mul_t0_add_shade) }, // Iguana background, turok // (env-shade)*t0+shade { 0x81458145, cmb(cc_env_sub_shade_mul_t0_add_shade) }, // Bubbles in Jabu-Jabu's belly, zelda // (1-shade)*t0+shade { 0x81468146, cmb(cc_one_sub_shade_mul_t0_add_shade) }, // duck dodgers intro. Added by Gonetz // (1-shade)*t0+shade, (cmb-0)*shade+0 **INC** { 0x8146e4f0, cmb(cc_one_sub_shade_mul_t0_add_shade) }, // intro, Madden Footbal // (1-env)*t0+shade { 0x81568156, cmb(cc_one_sub_env_mul_t0_add_shade) }, // sky in doom. Added by Gonetz // (prim-0)*t0+shade, (cmb-0)*primlod+env **INC** { 0x81f3aef0, cmb(cc_t0_mul_prim_add_shade) }, // commercial? in IIS98. Added by Gonetz // (1-0)*t0+shade { 0x81f681f6, cmb(cc_t0_add_shade) }, //beetle adventure racing. Added by Gonetz //(prim-shade)*t1+shade, (cmb-0)*t1+0 **INC** { 0x8243e2f0, cmb(cc_prim_sub_shade_mul_t1_add_shade) }, // Scorpion fire breath, MK4 [Jeremy]. Added by Gonetz // (t0-shade)*prim+shade { 0x83418341, cmb(cc_t0_mul_prim_add_one_sub_prim_mul_shade) }, // Menu background, wwf no mercy // (env-shade)*prim+shade { 0x83458345, cmb(cc_prim_mul_env_add_one_sub_prim_mul_shade) }, // Pokemon selection window background, pokemon stadium 2 // (noise-shade)*prim+shade { 0x83478347, cmb(cc_shade) }, // crown of king of ikana, zelda 2. Added by Gonetz // (t0-env)*prim+shade { 0x83518351, cmb(cc_t0_sub_env_mul_prim_add_shade) }, // crown of king of ikana, zelda 2. Added by Gonetz // (t0-env)*prim+shade, (cmb-0)*cmb+0 ** INC ** { 0x8351e0f0, cmb(cc_t0_sub_env_mul_prim_add_shade) }, // salesman's shirt in the bomb shop in town, zelda 2 [Ogy]. Added by Gonetz // (t0-env)*prim+shade, (cmb-0)*shade+0 ** INC ** { 0x8351e4f0, cmb(cc_t0_mul_prim_mul_shade) }, // intro, Madden Footbal // (1-env)*prim+shade { 0x83568356, cmb(cc_one_sub_env_mul_prim_add_shade) }, // Buss hunter 64. Added by Gonetz // (t0-0)*prim+shade { 0x83f183f1, cmb(cc_t0_mul_prim_add_shade) }, // huge water lilies, zelda 2 [Ogy]. Added by Gonetz // (t0-0)*prim+shade, (cmb-env)*shade+0 ** INC ** { 0x83f1e450, cmb(cc__t0_mul_prim_add_shade__sub_env_mul_shade) }, // Objects in arena, pokemon stadium 2 // (t1-0)*prim+shade, (cmb-0)*prim_a+0 - not going to bother with prim_a since it is FF { 0x83f2eaf0, cmb(cc_t1_mul_prim_add_shade) }, // Pokemon Stadium 2. Added by Gonetz // (t0-prim)*shade+shade ** INC ** { 0x84318431, cmb(cc_t0_mul_shade) }, // big N, Pokemon Stadium 2. Added by Gonetz // (1-prim)*shade+shade ** INC ** { 0x84368436, cmb(cc_one_sub_prim_mul_shade_add_shade) }, // arena, PokemonStadium2, [Raziel64] // (t0-0)*shade+shade, (cmb-0)*prim+0 { 0x84f1e3f0, cmb(cc_t0_mul_prim_mul_shade_add_prim_mul_shade) }, // Spiderman. Added by Gonetz // (1-0)*shade+shade { 0x84f684f6, cmb(cc_shade) }, // the "gekko" ( a monster in a room above the 3rd room of woodfall temple ) }, zelda 2 [Ogy]. Added by Gonetz // (t0-prim)*env+shade ** INC ** { 0x85318531, cmb(cc_t0_sub_prim_mul_env_add_shade) }, // clothes, zelda 2. Added by Gonetz // (t0-prim)*env+shade, (cmb-0)*shade+0 ** INC ** { 0x8531e4f0, cmb(cc_t0_mul_env_mul_shade) }, // Robotron 64, [scorpiove] // (env-shade)*env+shade ** INC ** { 0x85458545, cmb(cc_one_sub_env_mul_shade_add_env) }, // Enemy dying, quest64 // (1-shade)*env+shade **changed by Gonetz { 0x85468546, cmb(cc_one_sub_shade_mul_env_add_shade) }, // Sky, Beetle Adventure Racing ** INC ** //(t0-shade)*t0_a+shade, (env-cmb)*enva+cmb { 0x88410c05, cmb(cc_t0_sub_shade_mul_t0a_add_shade) }, // Mario's eyes, mario //z (t0-shade)*t0_a+shade { 0x88418841, cmb(cc_t0_sub_shade_mul_t0a_add_shade) }, //beetle adventure racing. Added by Gonetz // (prim-shade)*t1_a+shade, (t1-0)*cmb+0 **INC** { 0x8843e0f2, cmb(cc_t1_mul_shade) }, // blast corps [Ogy] // (prim-shade)*t1_a+shade { 0x89438943, cmb(cc_prim_sub_shade_mul_t1a_add_shade) }, //broken wall, beetle adventure racing. Added by Gonetz // (t0-shade)*prima+shade, (1-0)*0+cmb { 0x8a411ff6, cmb(cc_t0_sub_shade_mul_prima_add_shade) }, // menu, battle phoenix 64. Added by Gonetz // (t0-shade)*prima+shade { 0x8a418a41, cmb(cc_t0_add_shade) }, // intro, castlevania 2. Added by Gonetz // (prim-shade)*prim_a+shade { 0x8a438a43, cmb(cc_prim_sub_shade_mul_prima_add_shade) }, // ? // (1-shade)*shade_a+shade { 0x8b468b46, cmb(cc_one_sub_shade_mul_shadea_add_shade) }, // arena, Pokemon Stadium. Added by Gonetz // (t0-t1)*env_a+shade, (cmb-env)*prim+0 ** INC ** { 0x8c21e350, cmb(cc_t0_add_prim_mul_shade) }, //diddy kong racing background fill. Added by Gonetz ** Modified by Dave2001 // (env-shade)*env_a+shade, (cmb-0)*prim+0 { 0x8c458c45, cmb(cc_shade) }, // note: previous combiner used other_alpha; doesn't work //diddy kong racing. Added by Gonetz // (env-shade)*env_a+shade, (cmb-0)*prim+0 ** INC ** { 0x8c45e3f0, cmb(cc_prim_mul_shade) }, // sky, Pokemon Stadium, [Raziel64] // (t0-0)*env_a+shade, (cmb-env)*prim+0 ** INC ** { 0x8cf1e350, cmb(cc_t0_mul_prim_add_shade_sub_env_mul_prim) }, // zelda 2 [Ogy]. Added by Gonetz // (t0-prim)*primlod+shade, (prim-env)*cmb+env ** INC ** { 0x8e31a053, cmb(cc_prim_sub_env_mul__t0_sub_prim_mul_primlod_add_shade__add_env) }, // fallen leaves, Dobutsu no Mori. Added by Gonetz // (t0-shade)*primlod+shade, (prim-env)*cmb+env ** INC ** { 0x8e41a053, cmb(cc_prim_sub_env_mul__t0_sub_shade_mul_primlod_add_shade__add_env) }, // the icicle above the part just before the entrance to the mountain village, zelda 2 [Ogy]. Added by Gonetz // (t0-prim)*0+shade, (prim-env)*cmb+env ** INC ** ? { 0x9f31a053, cmb(cc_prim_sub_env_mul_shade_add_env) }, // background on level 3-1, kirby 64 [Raziel64]. Added by Gonetz // (0-env)*0+shade { 0x9f5f9f5f, cmb(cc_shade) }, // Spotlight, smash bros // (1-0)*0+shade { 0x9ff69ff6, cmb(cc_shade) }, // water, Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz // (0-0)*0+shade, (cmb-cmb)*cmb+cmb { 0x9fff0000, cmb(cc_shade) }, // menu, Dr.Mario. Added by Gonetz // (0-0)*0+shade, (prim-cmb)*env+cmb { 0x9fff0503, cmb(cc_prim_sub_shade_mul_env_add_shade) }, // pikachu, hey you pikachu. Added by Gonetz // (0-0)*0+shade, (env-cmb)*enva+cmb { 0x9fff0c05, cmb(cc_env_sub_shade_mul_enva_add_shade) }, // mega shock, paper mario //(0-0)*0+shade, (env-prim)*cmb+prim { 0x9fff6035, cmb(cc_env_sub_prim_mul_shade_add_prim) }, // Super Mario 64 logo background //z (k5-k5)*0+shade { 0x9fff9fff, cmb(cc_shade) }, // Zelda 2 final movie. Added by Gonetz // (0-0)*0+shade, (prim-0)*cmb+0 { 0x9fffe0f3, cmb(cc_prim_mul_shade) }, // tree shadow, Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz // (0-0)*0+shade, (env-0)*cmb+0 { 0x9fffe0f5, cmb(cc_env_mul_shade) }, // N64 logo, Aidyn Chronicles. Added by Gonetz // (0-0)*0+shade, (cmb-0)*prim+0 { 0x9fffe3f0, cmb(cc_prim_mul_shade) }, // Hand, smash bros // (0-0)*0+shade, (cmb-0)*env+0 { 0x9fffe5f0, cmb(cc_env_mul_shade) }, // Lave piranha atack, Paper Mario // (t1-t0)*t0+env, (cmb-t1)*t0+prim ** INC ** { 0xa1126120, cmb(cc__t0_mul_t1__mul_env_add_prim) }, // Kirby64 end [Raziel64]. Added by Gonetz // (prim-shade)*t0+env { 0xa143a143, cmb(cc_prim_sub_shade_mul_t0_add_env) }, // Superman [scorpiove]. Added by Gonetz // (t0-env)*t0+env { 0xa151a151, cmb(cc_t0_sub_env_mul_t0_add_env) }, // powder keg, zelda 2. Added by Gonetz // (prim-env)*t0+env, (0-0)*shade_a+cmb { 0xa1530bff, cmb(cc_prim_sub_env_mul_t0_add_env) }, // Kotake & koume defeated, going into sky, zelda // (prim-env)*t0+env, (prim-env)*0+cmb { 0xa1531f53, cmb(cc_prim_sub_env_mul_t0_add_env) }, // water, Dobutsu no Mori. Added by Gonetz // (prim-env)*t0+env, (cmb-0)*shade+t0 { 0xa15324f0, cmb(cc_t0_add_shade_mul_env) }, //broken wall, beetle adventure racing. Added by Gonetz // (prim-env)*t0+env, (cmb-shade)*t1+shade **INC** can't be done in one step { 0xa1538240, cmb(cc_prim_sub_env_mul__t0_mul_t1__add_shade) }, //couple's mask, zelda2. Added by Gonetz // (prim-env)*t0+env, (prim-cmb)*shade+shade **INC** can't be done in one step { 0xa1538403, cmb(cc_t0_mul_shade) }, // stadium, Pokemon Stadium 2. Added by Gonetz // (prim-env)*t0+env, (cmb-0)*shade+shade **INC** can't be done in one step { 0xa15384f0, cmb(cc_t0_mul_shade) }, //clothes on girl in inn, zelda2. Added by Gonetz // (prim-env)*t0+env, (cmb-prim)*env+shade **INC** can't be done in one step { 0xa1538530, cmb(cc_t0_mul_env_add_shade) }, // Getting light arrows for the first time, zelda // (prim-env)*t0+env, (prim-env)*cmb+env ** INC ** { 0xa153a053, cmb(cc_prim_sub_env_mul_t0_add_env) }, // Fire, starfox // (prim-env)*t0+env { 0xa153a153, cmb(cc_prim_sub_env_mul_t0_add_env) }, // a spell, Fushigi no Dungeon: Fuurai no Shiren 2 // (prim-env)*t0+env, (cmb-env)*enva+env { 0xa153ac50, cmb(cc_prim_sub_env_mul__t0_mul_enva__add_env) }, // wizrobe's attack, zelda 2. Added by Gonetz. // (prim-env)*t0+env, (cmb-0)*cmb+0 { 0xa153e0f0, cmb(cc_prim_sub_env_mul_t0_add_env) }, // dress, zelda 2. Added by Gonetz. // also for Great Farie's hair - changed to use texture mod by Dave2001. // (prim-env)*t0+env, (shade-0)*cmb+0 { 0xa153e0f4, cmb(cc__env_inter_prim_using_t0__mul_shade) }, // Start menu, paper mario // (prim-env)*t0+env, (cmb-0)*t0+0 { 0xa153e1f0, cmb(cc_prim_sub_env_mul_t0_add_env) }, // { 0xa153e0f4, cmb(cc_prim_sub_env_mul_t0_add_env) }, // Jellyfish tentacles in Jabu-Jabu's belly, zelda // (prim-env)*t0+env, (cmb-0)*prim+0 { 0xa153e3f0, cmb(cc__env_inter_prim_using_t0__mul_prim) }, // Dust, zelda //z (prim-env)*t0+env, (cmb-k5)*shade+cmb_a ** INC ** { 0xa153e4f0, cmb(cc__env_inter_prim_using_t0__mul_shade) }, //0xa153e4f0, cmb(cc_prim_sub_env_mul_t0_add_env) }, // roof, Kirby 64. Added by Gonetz // (prim-env)*t0+env, (cmb-0)*env+0 ** INC ** { 0xa153e5f0, cmb(cc_prim_sub_env_mul_t0_add_env) }, // Something weird in intro, monster truck madness // (prim-env)*t0+env, (cmb-0)*k5+0 { 0xa153eff0, cmb(cc__prim_sub_env_mul_t0_add_env__mul_k5) }, // clothes, kirby 64. Added by Gonetz // (shade-env)*t0+env { 0xa154a154, cmb(cc_shade_sub_env_mul_t0_add_env) }, // field, Derby Stallion // (shade-env)*t0+env, (cmb-0)*prim+0 ** INC ** { 0xa154e3f0, cmb(cc_shade_sub_env_mul_t0_mul_prim_add_prim_mul_env) }, // background, level 3-5, kirby 64, [Raziel64] // (shade-env)*t0+env, (cmb-0)*shade+0 ** INC ** { 0xa154e4f0, cmb(cc_shade_sub_env_mul_t0_add_env) }, // quake 2 intro // (prim-0)*t0+env, (prim-0)*primlod+cmb ** INC ** { 0xa1f30ef3, cmb(cc_t0_mul_prim_add_env) }, // Kotake or koume's hair, zelda // (prim-0)*t0+env { 0xa1f3a1f3, cmb(cc_t0_mul_prim_add_env) }, // track, ridge racer. Added by Gonetz // (t0-env)*t1+env, (cmb-0)*shade+0 ** INC ** { 0xa251e4f0, cmb(cc__t0_mul_t1__mul_shade) }, // lava, beetle adventure racing // (t0-env)*t1+env, (cmb-0)*enva+0 ** INC ** { 0xa251ecf0, cmb(cc__t0_mul_t1__mul_enva) }, // Ded Moroz, Paper Mario // (prim-env)*t1+env, (1-cmb)*t1+cmb ** INC ** { 0xa2530206, cmb(cc_prim_sub_env_mul_t1_add_env) }, // text, monster truck madness // (prim-env)*t1+env { 0xa253a253, cmb(cc_prim_sub_env_mul_t1_add_env) }, // car position, Top Gear Rally. Added by Gonetz // (prim-env)*t1+env, (cmb-t0)*t1+0 ** INC ** { 0xa253e210, cmb(cc_prim_sub_env_mul_t1_add_env_mul_t0) }, // text, Top Gear Rally. Added by Gonetz // (prim-env)*t1+env, (cmb-0)*t1+0 ** INC ** { 0xa253e2f0, cmb(cc_prim_sub_env_mul_t1_add_env_mul_t0) }, // 0xa253e2f0, cmb(cc_prim_sub_env_mul_t1_add_env) }, // a pole in the cut-scene that appears after you receive odolwa's mask, zelda 2 [Ogy]. Added by Gonetz // (prim-env)*t1+env, (cmb-0)*shade+0 ** INC ** { 0xa253e4f0, cmb(cc_t1_mul_prim_mul_shade) }, // Quake 2 intro. Added by Gonetz // (t0-0)*t1+env, (t0-0)*primlod+cmb ** INC ** { 0xa2f10ef1, cmb(cc__t0_mul_t1__add_env) }, // Quake64. Added by Gonetz // (t0-0)*t1+env { 0xa2f1a2f1, cmb(cc__t0_mul_t1__add_env) }, // Quake II. Added by Gonetz ** INC ** // (t0-0)*t1+env, (cmb-0)*prim+env { 0xa2f1a3f0, cmb(cc__t0_mul_t1__mul_prim_add_env) }, // Dr Mario [Ogy]. Added by Gonetz // (t0-env)*prim+env // 0xa351a351, cmb(cc_t0_mul_prim_add_env) }, { 0xa351a351, cmb(cc_t0_sub_env_mul_prim_add_env) }, // menu, Dr.Mario. Added by Gonetz // (prim-env)*prim+env { 0xa353a353, cmb(cc_prim_sub_env_mul_prim_add_env) }, // Razor sword, zelda 2. Added by Gonetz // (shade-env)*prim+env, (cmb-0)*shade+0 ** INC ** { 0xa354e4f0, cmb(cc_shade_sub_env_mul_prim_add_env) }, // bomberman 64-2 intro. Added by Gonetz // (1-env)*prim+env { 0xa356a356, cmb(cc_one_sub_env_mul_prim_add_env) }, // thing that escapes from the well, zelda // (noise-env)*prim+env { 0xa357a357, cmb(cc_prim_add_env) }, // Bongo Bongo, zelda // (noise-env)*prim+env, (cmb-0)*shade+0 { 0xa357e4f0, cmb(cc_env_mul_shade) }, // paper mario. Added by Gonetz // (t0-0)*prim+env { 0xa3f1a3f1, cmb(cc_t0_mul_prim_add_env) }, // paper mario. Added by Gonetz // (t0-0)*prim+env, (t0-env)*prim+0 { 0xa3f1e351, cmb(cc_t0_mul_prim_add_env) }, // paper mario. Added by Gonetz // (t0-0)*prim+env, (t0-0)*prim+0 { 0xa3f1e3f1, cmb(cc_t0_mul_prim) }, // squirt, paper mario. Added by Gonetz // (t1-0)*prim+env, (1-cmb)*t1+cmb { 0xa3f20206, cmb(cc_t1_mul_prim_add_env) }, // paper mario. Added by Gonetz // (shade-0)*prim+env { 0xa3f4a3f4, cmb(cc_prim_mul_shade_add_env) }, // Doraemon 2. Added by Gonetz // (1-0)*prim+env { 0xa3f6a3f6, cmb(cc_prim_add_env) }, // Pokemon Stadium 2, [Jeremy]. Added by Gonetz // (noise-0)*prim+env ** INC ** ? { 0xa3f7a3f7, cmb(cc_prim_add_env) }, // monsters, Pokemon Stadium. Added by Gonetz // (t0-t1)*shade+env, (cmb-0)*prim+0 ** INC ** { 0xa421e3f0, cmb(cc_t0_mul_prim_mul_shade_add_prim_mul_env) }, // background, pokemon stadium 2 // (t0-prim)*shade+env { 0xa431a431, cmb(cc_t0_mul_shade) }, // Buildings, pokemon stadium 2 // (t1-prim)*shade+env { 0xa432a432, cmb(cc_t1_mul_shade) }, // bomberman 64 [Ogy] // (t0-env)*shade+env { 0xa451a451, cmb(cc_t0_mul_shade_add_env) }, // kirby drill, kirby 64. Added by Gonetz // (prim-env)*shade+env { 0xa453a453, cmb(cc_prim_sub_env_mul_shade_add_env) }, // ball, ISS98 intro. Added by Gonetz // (t0-0)*shade+env { 0xa4f1a4f1, cmb(cc_t0_mul_shade_add_env) }, // score, ISS98 intro. Added by Gonetz // (prim-0)*shade+env { 0xa4f3a4f3, cmb(cc_prim_mul_shade_add_env) }, // magic fist, Rayman2. Added by Gonetz // (env-0)*shade+env { 0xa4f5a4f5, cmb(cc_env_mul_shade_add_env) }, // gunfire, Quake64. Added by Gonetz // (1-0)*shade+env { 0xa4f6a4f6, cmb(cc_env_add_shade) }, // Paper Mario. Added by Gonetz // (t0-center)*scale+env, (0-prim)*cmb+env { 0xa661a03f, cmb(cc_t0_add_env) }, // pink car, f-zero x // (t0-env)*t0_a+env, cmb*shade { 0xa851e4f0, cmb(cc__env_inter_t0_using_t0a__mul_shade) }, // PokemonStadium1, [Raziel64] // (prim-env)*t0_a+env, (cmb-cmb)*cmb+cmb { 0xa8530000, cmb(cc_prim_sub_env_mul_t0a_add_env) }, // N64 logo, Ogre Battle // (prim-env)*t0_a+env { 0xa853a853, cmb(cc_prim_sub_env_mul_t0a_add_env) }, // Mud Slap, Pokemon Stadium 2 [gokuss4]. Added by Gonetz // (prim-env)*t0_a+env, (cmb-0)*cmb+0 { 0xa853e0f0, cmb(cc_prim_sub_env_mul_t0a_add_env) }, // Tree background, mace // (prim-env)*t0_a+env, (cmb-0)*t0+0 { 0xa853e1f0, cmb(cc__env_inter_prim_using_t0a__mul_t0) }, // logo, Deadly Arts. Added by Gonetz // (prim-env)*t1_a+env { 0xa953a953, cmb(cc_prim_sub_env_mul_t1a_add_env) }, // Girl, PD intro. Added by Gonetz // (t0-env)*shade_alpha+env, (cmb-0)*shade+0 ** INC ** { 0xab51e4f0, cmb(cc_t0_mul_shade) }, // 0xab51e4f0, cmb(cc_t0_sub_env_mul_shade_mul_shadea_add_env) }, // Some gannon spell, zelda // (prim-env)*shade_alpha+env { 0xab53ab53, cmb(cc_prim_sub_env_mul_shadea_add_env) }, // Boxes, Taz express. Added by Gonetz // (t0-env)*env_a+env { 0xac51ac51, cmb(cc_t0_sub_env_mul_enva_add_env) }, // paper mario. Added by Gonetz // (t0-env)*env_a+env, (cmb-0)*shade+0 **INC** { 0xac51e4f0, cmb(cc_t0_mul_env_mul_shade) }, // goal, Monster Truck Madness 64 // (noise-0)*env_a+env, (cmb-0)*t1+0 **INC** { 0xacf7e2f0, cmb(cc_t1_mul_env) }, // sword on forge, zelda 2. Added by Gonetz // (t1-t1)*lodf+env, (t1-t0)*cmb+prim { 0xae226012, cmb(cc__t1_sub_t0__mul_env_add_prim) }, // menu background, Pokemon Stadium 2, [Raziel64] // (t0-prim)*lodf+env { 0xae31ae31, cmb(cc_t0_sub_prim_mul_primlod_add_env) }, // odd mushroom, zelda oot. Added by Gonetz // (t0-shade)*lodf+env, (prim-env)*cmb+env ** INC ** { 0xae41a053, cmb(cc__env_inter_prim_using__t0_sub_shade_mul_primlod_add_env) }, // 0xae41a053, cmb(cc_prim_sub_env_mul__t0_mul_shade__add_env) }, // Morning Sun, Pokemon Stadium 2 [gokuss4]. Added by Gonetz // (t0-env)*lodf+env, (cmb-0)*prim+0 { 0xae51e3f0, cmb(cc__env_inter_t0_using_primlod__mul_prim) }, //Spacestation Silicon Valley intro. Added by Gonetz // (prim-env)*lodf+env { 0xae53ae53, cmb(cc_env_inter_prim_using_primlod) }, // Doom, intro. Added by Gonetz // (t0-0)*lodf+env, (t0-0)*lodf+env { 0xaef1aef1, cmb(cc_t0_add_env) }, // Dobutsu no Mori. Added by Gonetz // (prim-0)*lodf+env { 0xaef3aef3, cmb(cc_prim_add_env) }, // light from window, Dobutsu no Mori. Added by Gonetz // (prim-0)*lodf+env, (t1-0)*cmb+0 { 0xaef3e0f2, cmb(cc_t1_mul__prim_add_env) }, // intro, Mission Impossible. Added by Gonetz // (k5-k5)*0+env, (0-0)*scale+env { 0xbfffa6ff, cmb(cc_env) }, // Something blocking the screen, waverace //z (k5-k5)*0+env { 0xbfffbfff, cmb(cc_env) }, // Derby Stallion . Added by Gonetz // (0-0)*0+env, (cmb-0)*prim+0 { 0xbfffe3f0, cmb(cc_prim_mul_env) }, // zelda 2 [Ogy]. Added by Gonetz // (k5-k5)*0+env, ((cmb-0)*shade+0 { 0xbfffe4f0, cmb(cc_env_mul_shade) }, // flame, paper mario. Added by Gonetz // (t0-t1)*t0+1, (0-prim)*cmb+env **INC** weird { 0xc121a03f, cmb(cc__t0_inter_t1_using_half__mul_prim_add_env) }, // tube near big monster on level 5, Kirby64 [Raziel64] // (prim-env)*t0+1, (cmb-0)*shade+0 ** INC ** { 0xc153e4f0, cmb(cc_prim_sub_env_mul_t0_mul_shade) }, // paper mario. Added by Gonetz // (0-env)*t0+1, (prim-cmb)*t0+prim **INC** { 0xc15f6103, cmb(cc_env_sub_prim_mul_t0_add_prim) }, // HAL, smash bros // (0-0)*0+1 { 0xdfffdfff, cmb(cc_one) }, // arena, Pokemon Stadium 1, [Raziel64] // (0-0)*0+1, (cmb-0)*prim+0 { 0xdfffe3f0, cmb(cc_prim) }, // skis, Spacestation Silicon Valley. Added by Gonetz // (shade-0)*cmb+0, (t1-t0)*primlod+t0 { 0xe0f42d12, cmb(cc_t0_inter_t1_using_primlod) }, // paper mario. Added by Gonetz // (1-t1)*t0+0, (env-prim)*cmb+prim ** INC ** { 0xe1266035, cmb(cc_env_sub_prim_mul__t0_mul_t1__add_prim) }, // ground, zelda 2. Added by Gonetz. // (t1-prim)*t0+0, (cmb-0)*shade+0 { 0xe132e4f0, cmb(cc__t1_sub_prim_mul_t0__mul_shade) }, // carmagedon // (shade-prim)*t0+0 { 0xe134e134, cmb(cc_shade_sub_prim_mul_t0) }, // skeleton, castlevania 2. Added by Gonetz // (1-prim)*t0+0, (cmb-0)*shade+0 { 0xe136e4f0, cmb(cc_t0_mul_1mprim_mul_shade) }, // Starshot logo. Added by Gonetz // (shade-env)*t0+0, (1-0)*cmb+cmb { 0xe15400f6, cmb(cc_shade_sub_env_mul_t0) }, // Kirby morfing, smash bros. Added by Gonetz // (shade-env)*t0+0 { 0xe154e154, cmb(cc_shade_sub_env_mul_t0) }, // menu, PGA euro tour. Added by Gonetz // (1-env)*t0+0 { 0xe156e156, cmb(cc_one_sub_env_mul_t0) }, // paper mario. Added by Gonetz // (t0-0)*t0+0, (1-cmb)*prim+cmb { 0xe1f10306, cmb(cc_one_sub_t0_mul_prim_add_t0) }, // F1 World Grand Prix. Added by Gonetz // (t0-0)*t0+0, (shade-prim)*cmb+prim { 0xe1f16034, cmb(cc_shade_sub_prim_mul_t0_add_prim) }, // paper mario. Added by Gonetz // (t0-0)*t0+0, (env-prim)*cmb+prim { 0xe1f16035, cmb(cc_env_sub_prim_mul_t0_add_prim) }, // sparkles, F1 World Grand Prix. Added by Gonetz // (t0-0)*t0+0, (1-prim)*cmb+prim { 0xe1f16036, cmb(cc_one_sub_prim_mul_t0_add_prim) }, // Tony Hawk's Pro Skater. Added by Gonetz // (t0-0)*t0+0, (cmb-0)*t0+0 { 0xe1f1e1f0, cmb(cc_t0) }, // something in upper left corner, mario tennis // (t0-0)*t0+0 { 0xe1f1e1f1, cmb(cc_t0) }, // zelda 2. Added by Gonetz // (t0-0)*t0+0, (cmb-0)*prim+0 { 0xe1f1e3f0, cmb(cc_t0_mul_prim) }, // zelda 2 final movie. Added by Gonetz // (t0-0)*t0+0, (cmb-0)*shade+0 { 0xe1f1e4f0, cmb(cc_t0_mul_shade) }, // paper mario. Added by Gonetz // (t0-t1)*t0+1, (env-cmb)*prima+cmb ** INC ** { 0xe1f20a05, cmb(cc_t1_mul_prima) }, // terrain, SCARS. Added by Gonetz // (t1-0)*t0+0, (env-prim)*cmb+prim { 0xe1f26035, cmb(cc_env_sub_prim_mul__t0_mul_t1__add_prim) }, // Trees, Zelda 2 // (t1-0)*t0+0, (cmb-0)*shade+prim { 0xe1f264f0, cmb(cc__t0_mul_t1__mul_shade_add_prim) }, // terrain, SCARS. Added by Gonetz // (t1-0)*t0+0, (env-shade)*cmb+shade { 0xe1f28045, cmb(cc_env_sub_shade_mul__t0_mul_t1__add_shade) }, // arena, Pokemon Stadium 2. Added by Gonetz // (t1-0)*t0+0, (cmb-prim)*shade+shade ** INC ** { 0xe1f28430, cmb(cc__t0_mul_t1__mul_shade) }, // Zelda 2, [Ogy]. Added by Gonetz // (t1-0)*t0+0, (cmb-prim)*env+shade ** INC ** { 0xe1f28530, cmb(cc__t0_mul_t1__mul_env_add_shade) }, // pokemon attack, Pokemon Stadium 2. Added by Gonetz // (t1-0)*t0+0, (prim-env)*cmb+env { 0xe1f2a053, cmb(cc_prim_sub_env_mul__t0_mul_t1__add_env) }, // paper mario. Added by Gonetz // (t1-0)*t0+0, (cmb-0)*prim+env { 0xe1f2a3f0, cmb(cc__t0_mul_t1__mul_prim_add_env) }, // Sand, pokemon stadium 2 // (t1-0)*t0+0, (cmb-prim)*shade+env ** INC ** { 0xe1f2a430, cmb(cc__t0_mul_t1__mul_shade) }, // grass, Mission Impossible. Added by Gonetz // (t1-0)*t0+0, (shade-0)*cmb+0 { 0xe1f2e0f4, cmb(cc__t0_mul_t1__mul_shade) }, // lighthouse's beam, zelda 2. Added by Gonetz // (t1-0)*t0+0, (cmb-0)*prim+0 { 0xe1f2e3f0, cmb(cc__t0_mul_t1__mul_prim) }, // Bottom of wings, pilotwings // (t1-0)*t0+0, (cmb-0)*shade+0 { 0xe1f2e4f0, cmb(cc__t0_mul_t1__mul_shade) }, // zelda 2. Added by Gonetz // (t1-0)*t0+0, (cmb-0)*prima+0 { 0xe1f2eaf0, cmb(cc__t0_mul_t1__mul_prima) }, // lava, Roadsters. Added by Gonetz // (prim-0)*t0+0, (1-prim)*t0+cmb { 0xe1f30136, cmb(cc_t0) }, // sky, Pokemon Stadium 2. Added by Gonetz // (prim-0)*t0+0, (cmb-0)*shadea+env { 0xe1f3abf0, cmb(cc_t0_mul_prim_mul_shadea_add_env) }, // cars, Indy Racing 2000. Added by Gonetz // (prim-0)*t0+0, (shade-0)*cmb+0 { 0xe1f3e0f4, cmb(cc_t0_mul_prim_mul_shade) }, // Sign shadows, zelda //z (prim-k5)*t0+cmb_a { 0xe1f3e1f3, cmb(cc_t0_mul_prim) }, // Table, mace // (prim-0)*t0+0, (cmb-0)*shade+0 { 0xe1f3e4f0, cmb(cc_t0_mul_prim_mul_shade) }, // Gauntlet Legends intro // (prim-0)*t0+0, (cmb-0)*prima+0 { 0xe1f3eaf0, cmb(cc_t0_mul_prim_mul_prima) }, // walls, beetle adventure racing. Added by Gonetz // (shade-0)*t0+0, (prim-0)*t0+cmb { 0xe1f401f3, cmb(cc_t0_mul_shade) }, // cars, ridge racer. Added by Gonetz // (shade-0)*t0+0, (prim-cmb)*cmb_a+cmb **INC** { 0xe1f40703, cmb(cc_t0_mul_shade) }, // water block, Paper Mario. Added by Gonetz // (shade-0)*t0+0, (prim-env)*cmb+env { 0xe1f4a053, cmb(cc_prim_sub_env_mul__t0_mul_shade__add_env) }, // a lot in TWINE. Added by Gonetz // (shade-0)*t0+0, (cmb-0)*prim+env { 0xe1f4a3f0, cmb(cc_t0_mul_prim_mul_shade_add_env) }, // Xena. Added by Gonetz // (shade-0)*t0+0, (env-0)*cmb+0 { 0xe1f4e0f5, cmb(cc_t0_mul_env_mul_shade) }, // Starshot logo. Added by Gonetz // (shade-0)*t0+0, (1-0)*cmb+0 { 0xe1f4e0f6, cmb(cc_t0_mul_shade) }, // Duck Dodgers intro. Added by Gonetz // (shade-0)*t0+0 { 0xe1f4e1f4, cmb(cc_t0_mul_shade) }, // shadow, Mission Impossible. Added by Gonetz // (shade-0)*t0+0, (cmb-0)*prim+0 { 0xe1f4e3f0, cmb(cc_t0_mul_prim_mul_shade) }, // Tony Hawk's Pro Skater 3. Added by Gonetz // (env-0)*t0+0, (t1-0)*shade+cmb ** INC ** { 0xe1f504f2, cmb(cc__t0_add_t1__mul_shade) }, // text, tonic trouble. Added by Gonetz // (env-0)*t0+0 { 0xe1f5e1f5, cmb(cc_t0_mul_env) }, // powder keg, zelda 2. Added by Gonetz // (env-0)*t0+0, (cmb-0)*shade+0 { 0xe1f5e4f0, cmb(cc_t0_mul_env_mul_shade) }, // water, Starshot. Added by Gonetz // (1-0)*t0+0, (1-0)*cmb+0 { 0xe1f6e0f6, cmb(cc_t0) }, // bomberman 64 [Ogy] // (1-0)*t0+0 { 0xe1f6e1f6, cmb(cc_t0) }, // Mermaid attack, Mystical Ninja // (noise-0)*t0+0 { 0xe1f7e1f7, cmb(cc_t0) }, // paper mario. Added by Gonetz * changed because of odd palette copy // (t0-0)*t1+0, (shade-env)*cmb+cmb **INC** ? { 0xe2f10054, cmb(cc_shade_sub_env_mul__t0_mul_t1__add__t0_mul_t1) }, // water, PGA European Tour // (t0-0)*t1+0, (env-cmb)*prim+cmb { 0xe2f10305, cmb(cc_one_sub_prim_mul__t0_mul_t1__add__prim_mul_env) }, // Grass, mario golf // (t0-0)*t1+0, (cmb-t0)*cmb_a+t0 { 0xe2f12710, cmb(cc_t0_mul_t1) }, // xg2, Added by Gonetz // (t0-0)*t1+0, (env-prim)*cmb+prim { 0xe2f16035, cmb(cc_env_sub_prim_mul__t0_mul_t1__add_prim) }, // poo, CBFD, Added by Gonetz // (t0-0)*t1+0, (cmb-env)*shade+prim ** INC ** { 0xe2f16450, cmb(cc__t0_mul_t1__mul_shade_add_prim) }, // sky, xg2, Added by Gonetz // (t0-0)*t1+0, (cmb-prim)*cmb_a+prim { 0xe2f16730, cmb(cc__t0_mul_t1__sub_prim_mul__t0t1a__add_prim ) }, // Sin and Punishment, [scorpiove], Added by Gonetz // (t0-0)*t1+0, (env-prim)*cmb_a+prim { 0xe2f16735, cmb(cc_env_sub_prim_mul__t0t1a__add_prim) }, // light, Ridge Racer. Added by Gonetz // (t0-0)*t1+0, (prim-env)*cmb+env { 0xe2f1a053, cmb(cc_prim_sub_env_mul__t0_mul_t1__add_env) }, // Waterfall, duck dodgers. Added by Gonetz // (t0-0)*t1+0, (shade-env)*cmb+env { 0xe2f1a054, cmb(cc_shade_sub_env_mul__t0_mul_t1__add_env) }, // bikes, xg2 // (t0-0)*t1+0, (shade-0)*cmb+0 { 0xe2f1e0f4, cmb(cc__t0_mul_t1__mul_shade) }, // Sky background, xg2 // (t0-0)*t1+0 { 0xe2f1e2f1, cmb(cc_t0_mul_t1) }, // statistics, Banjo 2. Added by Gonetz // (t0-0)*t1+0, (cmb-0)*prim+0 { 0xe2f1e3f0, cmb(cc__t0_mul_t1__mul_prim) }, // Water, pilotwings // (t0-0)*t1+0, (cmb-0)*shade+0 { 0xe2f1e4f0, cmb(cc__t0_mul_t1__mul_shade) }, //beetle adventure racing. A dded by Gonetz // (t0-0)*t1+0, (cmb-0)*env+0 { 0xe2f1e5f0, cmb(cc__t0_mul_t1__mul_env) }, //fall headwaters, zelda 2. Added by Gonetz // (t1-0)*t1+0, (cmb-0)*shade+0 { 0xe2f2e4f0, cmb(cc_t1_mul_shade) }, //text, Paper Mario // (prim-0)*t1+0 { 0xe2f3e2f3, cmb(cc_t1_mul_prim) }, //terrain, Beetle Adventure Racing. Added by Gonetz // (shade-0)*t1+0 { 0xe2f4e2f4, cmb(cc_t1_mul_shade) }, // lens of truth, zelda 2 [Ogy]. Added by Gonetz // (1-t0)*prim+0 { 0xe316e316, cmb(cc_one_sub_t0_mul_prim) }, // Magnitude, pokemon stadium 2 // (t0-0)*prim+0, (t0-0)*env+cmb { 0xe3f105f1, cmb(cc_t0_mul__prim_add_env) }, // night vision, jet force gemini // (t0-0)*prim+0, (noise-0)*env+cmb { 0xe3f105f7, cmb(cc_t0_mul_prim_add_env) }, // Smoke, diddy kong racing // (t0-0)*prim+0, (env-cmb)*env_alpha+cmb { 0xe3f10c05, cmb(cc_t0_mul_prim) }, // battle menu, Paper Mario. Added by Gonetz // (t0-0)*prim+0, (t0-env)*env_alpha+cmb ** INC ** { 0xe3f10c51, cmb(cc_t0_mul_prim) }, // stalactites, Beetle adventure Racing. Added by Gonetz // (t0-0)*prim+0, (cmb-shade)*t1_alpha+shade ** INC ** { 0xe3f18940, cmb(cc_t0_mul_prim_add_shade ) }, // ? in Jabu-Jabu's belly, submitted by gokuss4 // 0xe4f1a053, (t0-0)*prim+0, (prim-env)*cmb+env { 0xe3f1a053, cmb(cc_prim_sub_env_mul__t0_mul_prim__add_env) }, // kirby drill, kirby 64. Added by Gonetz // (t0-0)*prim+0, (cmb-env)*shade+env **INC** { 0xe3f1a450, cmb(cc_t0_mul_prim_mul_shade_add_env) }, // ? sign, zelda 2. Added by Gonetz // (t0-0)*prim+0, (cmb-0)*cmb+0 ** INC ** { 0xe3f1e0f0, cmb(cc_t0_mul_prim) }, // vehicle, Star Wars Ep.1 Racer, [Raziel64]. Added by Gonetz // (t0-0)*prim+0, (shade-0)*cmb+0 { 0xe3f1e0f4, cmb(cc_t0_mul_prim_mul_shade) }, // magic stuff, buck bumble. Added by Gonetz // (t0-0)*prim+0, (cmb-0)*prim+0 { 0xe3f1e3f0, cmb(cc_t0_mul_prim_mul_prim) }, // The mario face, mario //z (t0-k5)*prim+cmb_a { 0xe3f1e3f1, cmb(cc_t0_mul_prim) }, // Butterflies at Jabu-Jabu's lake, zelda // (t0-0)*prim+0, (cmb-0)*shade+0 { 0xe3f1e4f0, cmb(cc_t0_mul_prim_mul_shade) }, // Sprites, Ogre Battle. Added by Gonetz // (t1-0)*prim+0 { 0xe3f2e3f2, cmb(cc_t1_mul_prim) }, // F1 World Grand Prix. Added by Gonetz // (t1-0)*prim+0, (cmb-0)*shade+0 { 0xe3f2e4f0, cmb(cc_t1_mul_prim_mul_shade) }, // intro background, bio freaks. Added by Gonetz // (prim-0)*prim+0 { 0xe3f3e3f3, cmb(cc_prim_mul_prim) }, // player, Ohzumou2 // (shade-0)*prim+0, (env-cmb)*t0+cmb { 0xe3f40105, cmb(cc_env_sub_primshade_mul_t0_add_primshade) }, // floor in pyramides, beetle adventure racing. // (shade-0)*prim+0, (t1-0)*cmb+0 { 0xe3f4e0f2, cmb(cc_t1_mul_prim_mul_shade) }, // Slingshot string, zelda // (shade-0)*prim+0 { 0xe3f4e3f4, cmb(cc_prim_mul_shade) }, // ???, zelda // (env-0)*prim+0, (0-0)*0+cmb { 0xe3f5e3f5, cmb(cc_prim_mul_env) }, // Option selection, zelda //z (center-k5)*prim+cmb_a { 0xe3f6e3f6, cmb(cc_t0_mul_prim) }, // ranco monster, zelda 2. Added by Gonetz // (noise-0)*prim+0, (cmb-0)*prim_a+prim { 0xe3f76af0, cmb(cc_prim_mul_prima_add_prim) }, // zelda 2 [Ogy]. Added by Gonetz // (noise-0)*prim+0 { 0xe3f7e3f7, cmb(cc_prim) }, // Road rush. Added by Gonetz // (0-0)*prim+0 ** INC ** ? { 0xe3ffe3ff, cmb(cc_prim) }, // Letter to Kafei's mom, zelda 2. Added by Gonetz // (0-0)*prim+0, (cmb-0)*shade+0 { 0xe3ffe4f0, cmb(cc_prim_mul_shade) }, // Jabu-Jabu's Belly, zelda. Added by Gonetz // (1-t0)*shade+0, (cmb-0)*prim+0 { 0xe416e3f0, cmb(cc_one_sub_t0_mul_prim_mul_shade) }, // bomb mask, zelda 2. Added by Gonetz // (t0-env)*shade+0, (cmb-prim)*shade+shade ** INC ** { 0xe4518430, cmb(cc__t0_sub_env_mul_shade__sub_prim_mul_shade) }, // terrain, Top Gear Rally 2. Added by Gonetz // (t0-env)*shade+0 { 0xe451e451, cmb(cc_t0_sub_env_mul_shade) }, // closes, Nightmire Creatures // (1-env)*shade+0 { 0xe456e456, cmb(cc_one_sub_env_mul_shade) }, // water, Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz // (t0-0)*shade+0, (cmb-cmb)*cmb+cmb { 0xe4f10000, cmb(cc_t0_mul_shade) }, // Monster truck madness intro. Added by Gonetz // (t0-0)*shade+0, (1-0)*cmb+cmb ** INC ** { 0xe4f100f6, cmb(cc_t0_mul_shade) }, // terrain, SCARS. Added by Gonetz // (t0-0)*shade+0, (prim-cmb)*t0+cmb ** INC ** { 0xe4f10103, cmb(cc_t0_mul_shade) }, // Boomerang circle, zelda // (t0-0)*shade+0, (1-cmb)*t0+cmb { 0xe4f10106, cmb(cc_t0_mul_shade) }, // THPS3. // (t0-0)*shade+0, (1-0)*t0+cmb { 0xe4f101f6, cmb(cc_t0_mul_shade) }, // ???, WWF No Mercy [CpuMaster] // (t0-0)*shade+0, (env-cmb)*prim+cmb { 0xe4f10305, cmb(cc_t0_mul_one_sub_prim_mul_shade_add_prim_mul_env) }, // magic bubble, zelda2. Added by Gonetz // (t0-0)*shade+0, (t1-0)*shade+0 { 0xe4f104f2, cmb(cc_t0_mul_shade) }, // bike select, xg2. Added by Gonetz // (t0-0)*shade+0, (1-cmb)*env+cmb ** INC ** { 0xe4f10506, cmb(cc_t0_mul_shade) }, // a bugs life [Ogy] // (t0-0)*shade+0, (cmb-0)*env+cmb // 0xe4f105f0, cmb(cc_t0_mul_env_mul_shade) }, { 0xe4f105f0, cmb(cc_t0_mul_shade) }, // Wall, quest64 // (t0-0)*shade+0, (1-0)*env+cmb { 0xe4f105f6, cmb(cc_t0_mul_shade_add_env) }, //lava, beetle adventure racing. Added by Gonetz // (t0-0)*shade+0, (prim-cmb)*cmb_a+cmb **INC** { 0xe4f10703, cmb(cc_t0_mul_shade) }, // course map, Ridge Racer. Added by Gonetz // (t0-0)*shade+0, (prim-cmb)*prima+cmb **INC** { 0xe4f10a03, cmb(cc_t0_mul_shade) }, // arena, custom robo. Added by Gonetz // (t0-0)*shade+0, (noise-cmb)*prima+cmb **INC** { 0xe4f10a07, cmb(cc_t0_mul_shade) }, // arena, custom robo 2. Added by Gonetz // (t0-0)*shade+0, (0-cmb)*prima+cmb **INC** { 0xe4f10a0f, cmb(cc_t0_mul_shade) }, //floor in a cave, Paper mario. Added by Gonetz // (t0-0)*shade+0, (cmb-prim)*prima+cmb **INC** { 0xe4f10a30, cmb(cc_t0_mul_shade) }, //beetle adventure racing. Added by Gonetz // (t0-0)*shade+0, (t1-prim)*prima+cmb **INC** { 0xe4f10a32, cmb(cc_t0_mul_shade) }, // Monster truck madness intro. Added by Gonetz // (t0-0)*shade+0, (shade-cmb)*shade_a+cmb ** INC ** { 0xe4f10b04, cmb(cc_t0_mul_shade) }, // xg2 intro. Added by Gonetz // (t0-0)*shade+0, (1-cmb)*shade_a+cmb ** INC ** { 0xe4f10b06, cmb(cc__t0_mul_shade__inter_one_using_shadea) }, // Link's bomb, smash bros // (t0-0)*shade+0, (env-cmb)*env_a+cmb ** INC ** { 0xe4f10c05, cmb(cc__t0_mul_shade__inter_env_using_enva) }, // A Bugs Life, [Raziel64] // (t0-0)*shade+0, (cmb-0)*k5+cmb { 0xe4f10ff0, cmb(cc_t0_mul_shade) }, // car, Top Gear Rally. Added by Gonetz // (t0-0)*shade+0, (cmb-t0)*t0a+t0 **INC** { 0xe4f12810, cmb(cc_t0_mul_shade) }, // logo, SCARS. Added by Gonetz // (t0-0)*shade+0, (cmb-t0)*shadea+t0 **INC** { 0xe4f12b10, cmb(cc_t0_mul_shade) }, // ? sign, Spiderman. Added by Gonetz // (t0-0)*shade+0, (0-0)*0+t1 { 0xe4f15fff, cmb(cc_t0_mul_shade) }, // plants, CBFD. Added by Gonetz // (t0-0)*shade+0, (cmb-env)*shade+prim ** INC ** { 0xe4f16450, cmb(cc_t0_sub_env_mul_shade_add_prim) }, // Kirby64. Added by Gonetz // (t0-0)*shade+0, (cmb-prim)*prima+prim { 0xe4f16a30, cmb(cc_t0_mul_prima_mul_shade_add_prim_mul_one_sub_prima) }, // building shadow, Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz // (t0-0)*shade+0, (0-0)*0+prim { 0xe4f17fff, cmb(cc_prim) }, // tire trace, beetle adventure racing. Added by Gonetz // (t0-0)*shade+0, (env-cmb)*t1+shade **INC** { 0xe4f18205, cmb(cc_env_sub_shade_mul_t0_add_shade) }, // Gold Skulltula, zelda // (t0-0)*shade+0, (prim-env)*cmb+env { 0xe4f1a053, cmb(cc_prim_sub_env_mul_t0_mul_shade_add_env) }, // 0xe4f1a053, cmb(cc_t0_mul_prim_mul_shade) }, // fighters, GASP Fighters // (t0-0)*shade+0, (1-env)*cmb+env { 0xe4f1a056, cmb(cc_t0_mul_one_sub_env_mul_shade_add_env) }, // Brian, quest64 // (t0-0)*shade+0, (cmb-0)*prim+env { 0xe4f1a3f0, cmb(cc_t0_mul_prim_mul_shade_add_env) }, // Objects in arena, pokemon stadium 2 // (t0-0)*shade+0 // (cmb-prim)*shade+env { 0xe4f1a430, cmb(cc_t0_mul_shade) }, // Monster truck madness intro. Added by Gonetz // (t0-0)*shade+0, (cmb-env)*shadea+env **INC** // 0xe4f1ab50, cmb(cc_t0_mul_shade_add_env) }, { 0xe4f1ab50, cmb(cc__t0_mul_shade__sub_env_mul_shadea_add_env) }, // Taz express. Added by Gonetz // (t0-0)*shade+0, (cmb-env)*enva+env **INC** { 0xe4f1ac50, cmb(cc_t0_mul_shade_add_env) }, // sky in doom. Added by Gonetz // (t0-0)*shade+0, (cmb-0)*primlod+env **INC** { 0xe4f1aef0, cmb(cc_t0_mul_shade_add_env) }, // fighters, GASP Fighters // (t0-0)*shade+0, (1-env)*cmb+0 { 0xe4f1e056, cmb(cc_t0_mul_one_sub_env_mul_shade) }, // walls, beetle adventure racing. Added by Gonetz // (t0-0)*shade+0, (t0-0)*cmb+0 **INC** { 0xe4f1e0f1, cmb(cc_t0_mul_shade) }, // Link's face, zelda //z (t0-k5)*shade+cmb_a, (prim-k5)*cmb+cmb_a { 0xe4f1e0f3, cmb(cc_t0_mul_prim_mul_shade) }, // Link's suit, zelda //z (t0-k5)*shade+cmb_a, (env-k5)*cmb+cmb_a { 0xe4f1e0f5, cmb(cc_t0_mul_env_mul_shade) }, // Window, starfox //z (t0-k5)*shade+cmb_a, (cmb-k5)*prim+cmb_a { 0xe4f1e3f0, cmb(cc_t0_mul_prim_mul_shade) }, // crystal, Doraemon 2 //(t0-0)*shade+0, (t0-0)*prim+0 { 0xe4f1e3f1, cmb(cc_t0_mul_prim) }, // Characters, mace // (t0-0)*shade+0, (cmb-0)*shade+0 { 0xe4f1e4f0, cmb(cc_t0_mul_shade) }, // Super Mario 64 logo //z (t0-k5)*shade+cmb_a { 0xe4f1e4f1, cmb(cc_t0_mul_shade) }, // Kokiri's hat, zelda // (t0-0)*shade+0, (cmb-0)*env+0 { 0xe4f1e5f0, cmb(cc_t0_mul_env_mul_shade) }, // Gauntlet Legends intro // (t0-0)*shade+0, (cmb-0)*scale+0 { 0xe4f1e6f0, cmb(cc_t0_mul_shade) }, // Something on a tree, Paper Mario. Added by Gonetz // (t0-0)*shade+0, (cmb-0)*prima+0 { 0xe4f1eaf0, cmb(cc_t0_mul_prima_mul_shade) }, // Course map, Ridge Racer. Added by Gonetz // (t0-0)*shade+0, (cmb-0)*shadea+0 { 0xe4f1ebf0, cmb(cc_t0_mul_shade_mul_shadea) }, // Dodongo skull's eyes, zelda // (t0-0)*shade+0, (cmb-0)*env_alpha+0 { 0xe4f1ecf0, cmb(cc_t0_mul_enva_mul_shade) }, // lava, beetle adventure racing. Added by Gonetz // (t1-0)*shade+0, (cmb-prim)*cmb_a+prim **INC** { 0xe4f26730, cmb(cc_t1_mul_shade) }, // headlight, beetle adventure racing. Added by Gonetz // (t1-0)*shade+0, (env-cmb)*t0+shade **INC** { 0xe4f28105, cmb(cc_one_sub__t0_mul_t1__mul_shade) }, // water, Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz // (prim-0)*shade+0, (cmb-cmb)*cmb+cmb { 0xe4f30000, cmb(cc_prim_mul_shade) }, // lamp shadow, Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz // (prim-0)*shade+0, (cmb-cmb)*t0+cmb { 0xe4f30100, cmb(cc_prim_mul_shade) }, // Yoshi, mario golf // (prim-0)*shade+0, (env-cmb)*t0+cmb { 0xe4f30105, cmb(cc_env_sub_primshade_mul_t0_add_primshade) }, //Spacestation Silicon Valley intro. Added by Gonetz // (prim-0)*shade+0, (env-cmb)*t1+cmb { 0xe4f30205, cmb(cc_env_sub_primshade_mul_t1_add_primshade) }, // Tip of brian's hair, quest64 // (prim-0)*shade+0, (1-0)*env+cmb { 0xe4f305f6, cmb(cc_prim_mul_shade_add_env) }, // Background circle, xg2 // (prim-0)*shade+0, (1-cmb)*shade_a+cmb { 0xe4f30b06, cmb(cc_prim_mul_shade) }, // circle, waverace. Added by Gonetz // (prim-0)*shade+0, (t0-cmb)*enva+cmb { 0xe4f30c01, cmb(cc_t0_sub__prim_mul_shade__mul_enva_add__prim_mul_shade) }, // player, super bowling // (prim-0)*shade+0, (0-0)*k5+cmb { 0xe4f30fff, cmb(cc_prim_mul_shade) }, // walls, beetle adventure racing. Added by Gonetz // (prim-0)*shade+0, (cmb-shade)*t1+shade **INC** { 0xe4f38240, cmb(cc_prim_sub_shade_mul_t1_add_shade) }, // GASP fighters //(prim-0)*shade+0, (1-env)*cmb+0 { 0xe4f3e056, cmb(cc_prim_mul_one_sub_env_mul_shade) }, // Flag, mario kart //z (prim-k5)*shade+cmb_a { 0xe4f3e4f3, cmb(cc_prim_mul_shade) }, // Characters, smash bros // (prim-0)*shade+0, (cmb-0)*env+0 { 0xe4f3e5f0, cmb(cc_prim_mul_env_mul_shade) }, // N64 logo, ridge race. Added by Gonetz // (shade-0)*shade+0, (prim-cmb)*prima+cmb **INC** { 0xe4f40a03, cmb(cc_shade) }, // fighter, shield mode, bio freaks. Added by Gonetz // (shade-0)*shade+0 { 0xe4f4e4f4, cmb(cc_shade) }, // truck crush, Monster truck madness. Added by Gonetz // (env-0)*shade+0, (env-0)*shade+cmb { 0xe4f504f5, cmb(cc_env_mul_shade) }, // Course map, Ridge Racer. Added by Gonetz // (env-0)*shade+0 { 0xe4f5e4f5, cmb(cc_env_mul_shade) }, // lava, beetle adventure racing // (1-0)*shade+0, (prim-cmb)*cmb_a+cmb { 0xe4f60703, cmb(cc_prim_sub_shade_mul_shadea_add_shade) }, // the wings in the song of soaring cut-scene, zelda2 [Ogy]. Added by Gonetz // (1-0)*shade+0, (prim-0)*cmb+0 { 0xe4f6e0f3, cmb(cc_prim_mul_shade) }, // parts of vehicle, Star Wars Ep.I Racer. Added by Gonetz // (1-0)*shade+0, (cmb-0)*prim+0 { 0xe4f6e3f0, cmb(cc_prim_mul_shade) }, // Snowflakes??? (gokuss4) }, mario kart // (1-0)*shade+0, (1-0)*shade+0 { 0xe4f6e4f6, cmb(cc_shade) }, // ??? // (noise-0)*shade+0 { 0xe4f7e4f7, cmb(cc_shade) }, // quest64 [Ogy] // (prim-t0)*env+0, (0-0)*0+prim { 0xe5137fff, cmb(cc_prim) }, // field, Mike Piazza's Strike Zone // (t0-prim)*env+0 ** INC ** { 0xe531e531, cmb(cc_t0_mul_env) }, // Mike Piazza's Strike Zone // (shade-prim)*env+0 { 0xe534e534, cmb(cc_shade_sub_prim_mul_env) }, // rope, CBFD. Added by Gonetz // (t0-0)*env+0, (1-env)*prim+cmb { 0xe5f10356, cmb(cc_one_sub_env_mul_prim_add__t0_mul_env) }, // Bell, Pokemon Stadium 2. Added by Gonetz // (t0-0)*env+0, (shade-0)*prim+cmb { 0xe5f103f4, cmb(cc_t0_mul_env_add_prim_mul_shade) }, // aerofighter's assault [Ogy] // (t0-0)*env+0, (1-t0)*shade+cmb { 0xe5f10416, cmb(cc_t0_mul_env_add_1mt0_mul_shade) }, // foto, Armorines - Project S.W.A.R.M. Added by Gonetz // (t0-0)*env+0, (noise-0)*scale+cmb { 0xe5f106f7, cmb(cc_t0_mul_env) }, // Extreme G2, score. Added by Gonetz // (t0-0)*env+0, (1-cmb)*enva+cmb ** INC ** { 0xe5f10c06, cmb(cc_t0_mul_env) }, // many objects in Tonic Trouble // (t0-0)*env+0, (shade-0)*cmb+0 { 0xe5f1e0f4, cmb(cc_t0_mul_env_mul_shade) }, // Flying skull's eyes, zelda // (t0-0)*env+0, (cmb-0)*prim+0 { 0xe5f1e3f0, cmb(cc_t0_mul_prim_mul_env) }, // Rock spell, quest64 // (t0-0)*env+0, (cmb-0)*shade+0 { 0xe5f1e4f0, cmb(cc_t0_mul_env_mul_shade) }, // Text, mario //z (t0-k5)*env+cmb_a { 0xe5f1e5f1, cmb(cc_t0_mul_env) }, // kirby 64. Added by Gonetz // (prim-0)*env+0, (cmb-0)*shade+0 { 0xe5f3e4f0, cmb(cc_prim_mul_env_mul_shade) }, // wings, kirby 64. Added by Gonetz // (prim-0)*env+0 { 0xe5f3e5f3, cmb(cc_prim_mul_env) }, // Text, xg2 // (shade-0)*env+0, (1-cmb)*env_a+cmb { 0xe5f40c06, cmb(cc_env_mul_shade) }, // Text box, mario //z (shade-k5)*env+cmb_a { 0xe5f4e5f4, cmb(cc_env_mul_shade) }, // bomberman 64 [Ogy] // (1-0)*env+0 { 0xe5f6e5f6, cmb(cc_env) }, // Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz // (1-t0)*scale+0 { 0xe616e616, cmb(cc_zero) }, // Gauntlet Legends intro. Added by Gonetz // (t0-0)*scale+0, (cmb-0)*shade+0 { 0xe6f1e4f0, cmb(cc_t0_mul_shade) }, // shadows, Taz express. Added by Gonetz // (t0-0)*scale+0 { 0xe6f1e6f1, cmb(cc_t0) }, // shadows, Knockout Kings 2000. Added by Gonetz // (shade-0)*scale+0 { 0xe6f4e6f4, cmb(cc_shade) }, // bomberman 64 2 [Ogy]. Added by Gonetz // (1-0)*scale+0 **INC** what "scale" is ? { 0xe6f6e6f6, cmb(cc_one) }, // walls, beetle adventure racing. Added by Gonetz // (t1-0)*t0_a+0, (1-t1)*cmb+t1 **INC** { 0xe8f24026, cmb(cc_t1) }, // house on rancho, zelda2. Added by Gonetz // (t1-0)*t0_a+0, (cmb-0)*prim+0 { 0xe8f2e3f0, cmb(cc__t0a_mul_t1__mul_prim) }, // zelda2 [Ogy]. Added by Gonetz // (t1-0)*t0_a+0, (cmb-0)*shade+0 { 0xe8f2e4f0, cmb(cc__t0a_mul_t1__mul_shade) }, // logo, Deadly Arts. Added by Gonetz // (t0-0)*t1_a+0, (cmb-0)*shade+0 { 0xe9f1e4f0, cmb(cc__t0_mul_t1a__mul_shade) }, // car, Roadsters. Added by Gonetz // (prim-t0)*prim_a+0, (prim-cmb)*shade+0 ** INC ** { 0xea13e403, cmb(cc_prim_sub__prim_sub_t0_mul_prima__mul_shade) }, // arena, Pokemon Stadium 2. Added by Gonetz // (1-t0)*prim_a+0, (0-prim)*cmb+prim ** INC ** { 0xea16603f, cmb(cc_t0_mul_prim) }, // match start, Mario Tennis. Added by Gonetz // (t0-0)*prim_a+0, (1-t0)*cmb+t0 ** INC ** { 0xeaf12016, cmb(cc_one_sub_t0_mul_prima_add_t0) }, // blast corps [Ogy] // (t0-0)*prim_a+0 { 0xeaf1eaf1, cmb(cc_t0_mul_prima) }, // final battle, CBFD. Added by Gonetz // (prim-0)*prim_a+0 { 0xeaf3eaf3, cmb(cc_prim_mul_prima) }, // flower's stalk, Paper Mario. Added by Gonetz // (shade-0)*prim_a+0 { 0xeaf4eaf4, cmb(cc_shade_mul_prima) }, // blast corps [Ogy] // (noise-0)*prim_a+0, (t1-0)*shade+cmb ** INC ** { 0xeaf704f2, cmb(cc_t1_mul_shade) }, // F1 World Grand Prix. Added by Gonetz // (noise-0)*prim_a+0, (t1-0)*env_a+cmb ** INC ** { 0xeaf70cf2, cmb(cc_t1_mul_enva) }, // shadows, killer instinct gold // (0-0)*prim_a+0 { 0xeaffeaff, cmb(cc_zero) }, // Wreslters, WWF No Mercy, [CpUMasteR] // (t0-0)*shade_alpha+0, (env-cmb)*prim+cmb { 0xebf10305, cmb(cc_t0_mul_one_sub_prim_mul_shadea_add_prim_mul_env) }, // map, Pilot wings. Added by Gonetz // (t0-0)*shade_alpha+0, (1-cmb)*shade+cmb { 0xebf10406, cmb(cc_one_sub_shade_mul__t0_mul_shadea__add_shade) }, // Indy Racing 2000. Added by Gonetz // (t0-0)*shade_alpha+0, (1-0)*shade+cmb { 0xebf104f6, cmb(cc_t0_mul_shadea_add_shade) }, // logo, WCW-nWo Revenge // (t0-0)*shade_alpha+0, (cmb-0)*prim+0 { 0xebf1e3f0, cmb(cc_t0_mul_prim_mul_shadea) }, // Wrestlers in Game, WWF No mercy [CpUMasteR] // (t0-0)*shade_alpha+0 { 0xebf1ebf1, cmb(cc_t0_mul_shadea) }, // flag, top gear overdrive // (prim-0)*shade_alpha+0 { 0xebf3ebf3, cmb(cc_prim_mul_shadea) }, // Ropes, WWF games // (shade-0)*shade_alpha+0, (env-cmb)*prim+cmb { 0xebf40305, cmb(cc_shade_mul_shadea) }, // Ropes, WWF games // (shade-0)*shade_alpha+0 { 0xebf4ebf4, cmb(cc_shade_mul_shadea) }, // arena, custom robo 2 // (noise-0)*shade_alpha+0 { 0xebf7ebf7, cmb(cc_shadea) }, // Bell, Pokemon Stadium 2. Added by Gonetz // (t0-0)*enva+0, (shade-0)*prim+cmb { 0xecf103f4, cmb(cc_t0_mul_enva_add_prim_mul_shade) }, // blastcorps, unimp log. Added by Gonetz // (t0-0)*enva+0 { 0xecf1ecf1, cmb(cc_t0_mul_enva) }, // car, Top Gear Rally. Added by Gonetz // (env-0)*enva+0 { 0xecf5ecf5, cmb(cc_env_mul_enva) }, // Walls of well through lens of truth, zelda // (prim-t0)*primlod+0 ** INC ** { 0xee13ee13, cmb(cc_t0) }, // JUST t0 b/c the other combiner handles the subtraction // something on a flor in stone temple, zelda 2. Added by Gonetz // (t0-0)*primlod+0, (cmb-0)*prim+0 { 0xeef1e3f0, cmb(cc_t0_mul_primlod_mul_prim) }, // entrance to oceanside spider house, zelda 2. Added by Gonetz // (t0-0)*primlod+0, (cmb-0)*shade+0 { 0xeef1e4f0, cmb(cc_t0_mul_primlod_mul_shade) }, // Haze/(all powder status changers) }, Pokemon Stadium 2 [gokuss4]. Added by Gonetz // (noise-0)*primlod+0, (prim-env)*cmb+env ** INC ** { 0xeef7a053, cmb(cc_env) }, // pokemon attack, Pokemon Stadium 2. Added by Gonetz // (noise-0)*primlod+0, (prim-cmb)*cmb+0 ** INC ** { 0xeef7e003, cmb(cc_zero) }, // Night trees, Monster truck madness. Added by Gonetz // (t0-0)*k5+0 { 0xeff1eff1, cmb(cc_t0_mul_k5) }, // submitted by gokuss4 // (0-0)*0+0, (0-0)*0+prim { 0xfffd5fe6, cmb(cc_prim) }, // intro, Bettle Adventure Racing, [Raziel64] // (0-0)*0+0, (0-0)*0+t0 { 0xffff3fff, cmb(cc_t0) }, // Conker's face, CBFD // (0-0)*0+0, (shade-env)*k5+prim { 0xffff6f54, cmb(cc_shade_sub_env_mul_k5_add_prim) }, // Boost, Beetle Adventure Racing. Added by Gonetz // (0-0)*0+0, (0-0)*0+prim { 0xffff7fff, cmb(cc_prim) }, // headlight, beetle adventure racing. Added by Gonetz // (0-0)*0+0, (0-0)*0+shade { 0xffff9fff, cmb(cc_shade) }, // intro, Bettle Adventure Racing, [Raziel64] // (0-0)*0+0, (shade-env)*t1+env { 0xffffa254, cmb(cc_shade_sub_env_mul_t1_add_env) }, // Fly Swooping in, Pokemon Stadium 2 [gokuss4]. Added by Gonetz // (0-0)*0+0, (1-env)*cmb_a+env { 0xffffa756, cmb(cc_env) }, // Waterfall, Donkey Kong 64 // (0-0)*0+0, (t0-0)*t1+0 { 0xffffe1f2, cmb(cc_t0_mul_t1) }, // Screen clear, banjo kazooie // (0-0)*0+0 { 0xffffffff, cmb(cc_zero) }, // { #CCEND } }; static cmb_list_entry alpha_cmb_list[] = { // { #ACSTART } //Tony Hawk's Pro Skater. Added by Gonetz // (0-0)*0+0 { 0x01ff01ff, cmb(ac_zero) }, //terminal, Spacestation Silicon Valley. Added by Gonetz // (0-0)*0+0, (0-0)*0+prim { 0x01ff07ff, cmb(ac_prim) }, // kirby drill, kirby 64. Added by Gonetz // (0-0)*0+cmb, (0-0)*0+1 { 0x01ff0dff, cmb(ac_one) }, //chip in Spacestation Silicon Valley intro. Added by Gonetz // (0-0)*0+cmb, (prim-0)*shade+0 { 0x01ff0f3b, cmb(ac_prim_mul_shade) }, //Goldeneye, [Jeremy]. Added by Gonetz // (t0-t0)*lodf+t0, (cmb-0)*prim+0 { 0x02090ef8, cmb(ac_t0_mul_prim) }, // Indy Racing 2000. Added by Gonetz // (t1-t0)*lodf+t0, (env-cmb)*prim+cmb ** INC ** { 0x020a00c5, cmb(ac_t0_inter_t1_using_primlod) }, // water, Spacestation Silicon Valley. Added by Gonetz // (t1-t0)*lodf+t0, (0-shade)*0+cmb { 0x020a01e7, cmb(ac_t0_inter_t1_using_primlod) }, // Bridge, sf rush //z (t1-t0)*lodf+t0 { 0x020a020a, cmb(ac_t0_inter_t1_using_primlod) }, // explosion, body harvest. Added by Gonetz //(t1-t0)*lodf+t0, (0-0)*0+t0 { 0x020a03ff, cmb(ac_t0) }, // cars, PD intro. Added by Gonetz // (t1-t0)*lodf+t0, (cmb-0)*shade+prim { 0x020a0738, cmb(ac__t0_inter_t1_using_primlod__mul_shade_add_prim) }, // Rocket Robot in Wheels intro //(t1-t0)*lodf+t0, (0-0)*0+prim { 0x020a07ff, cmb(ac_prim) }, // Iguana background ground, turok // (t1-t0)*lodf+t0, (0-0)*0+shade { 0x020a09ff, cmb(ac_shade) }, // Ground, monster truck madness // (t1-t0)*lodf+t0, (0-0)*0+env { 0x020a0bff, cmb(ac_env) }, // Taz express. Added by Gonetz // (t1-t0)*lodf+t0, (0-0)*0+1 { 0x020a0dff, cmb(ac_one) }, // Mike Piazza's Strike Zone // (t1-t0)*lodf+t0, (cmb-0)*t0+0 { 0x020a0e78, cmb(ac_t0_inter_t1_using_primlod) }, // N64 logo, tetrisphere. Added by Gonetz // (t1-t0)*lodf+t0, (cmb-0)*prim+0 { 0x020a0ef8, cmb(ac__t0_inter_t1_using_primlod__mul_prim) }, // Ground, mace // (t1-t0)*lodf+t0, (cmb-0)*shade+0 // { 0x020a0f38, cmb(ac_t0_mul_shade) }, { 0x020a0f38, cmb(ac__t0_inter_t1_using_primlod__mul_shade) }, // blast corps [Ogy] // (t1-t0)*lodf+t0, (cmb-0)*env+0 { 0x020a0f78, cmb(ac__t0_inter_t1_using_primlod__mul_env) }, // blast corps [Ogy] // (t1-t0)*lodf+t0, (t0-0)*env+0 { 0x020a0f79, cmb(ac_t0_mul_env) }, // blast corps. Added by Gonetz // (t1-t0)*lodf+t0, (shade-0)*env+0 { 0x020a0f7c, cmb(ac_env_mul_shade) }, // field, Mike Piazza's Strike Zone // (t1-t0)*lodf+t0, (0-0)*0+0 { 0x020a0fff, cmb(ac_t0_inter_t1_using_primlod) }, // blast corps, unimp log. Added by Gonetz // (t1-t0)*t0+t0 { 0x024a024a, cmb(ac_t0_inter_t1_using_t0a) }, // zelda 2 [Ogy]. Added by Gonetz // (t1-t0)*t0+t0, (cmb-0)*prim+0 **INC** { 0x024a0ef8, cmb(ac__t0_inter_t1_using_t0a__mul_prim) }, // text in a menu, Twisted_Edge_Extreme_Snowboarding [Razeil64]. Added by Gonetz // (prim-t0)*t0+t0 **INC** { 0x024b024b, cmb(ac_t0) }, // enemy's shot, battle tanks 2 // (env-prim)*t0+t0 **INC** { 0x025d025d, cmb(ac_t0) }, //Bowser in final battle, Paper Mario. Added by Gonetz // (t1-env)*t0+t0, (cmb-env)*prim+0 ** INC ** { 0x026a0ee8, cmb(ac__t0_mul_t1__mul_prim) }, // paper mario. Added by Gonetz // (t1-env)*t0+t0, (cmb-0)*prim+0 ** INC ** { 0x026a0ef8, cmb(ac__t0_mul_t1__mul_prim) }, // THPS3. Added by Gonetz // (0-0)*t0+t0 { 0x027f027f, cmb(ac_t0) }, // zelda 2. Added by Gonetz // (0-0)*t0+t0, (cmb-0)*prim+0 { 0x027f0ef8, cmb(ac_t0_mul_prim) }, // teleportation, Spacestation Silicon Valley. Added by Gonetz // (t1-t0)*t1+t0 { 0x028a028a, cmb(ac_t0_inter_t1_using_t1a) }, // mega shock, paper mario. Added by Gonetz // (t1-t0)*t1+t0, (cmb-0)*prim+0 { 0x028a0ef8, cmb(ac__t0_inter_t1_using_t1a__mul_prim) }, // Magnitude, pokemon stadium 2 // (shade-t0)*t1+t0, (cmb-0)*shade+env { 0x028c0b38, cmb(ac__t0_mul_t1__mul_shade) }, // paper mario. Added by Gonetz // (1-t0)*t1+t0, (t1-0)*prim+0 ** INC ** { 0x028e0efa, cmb(ac__one_sub_t0_mul_t1_add_t0__mul_prim) }, // { 0x028e0efa, cmb(ac_t1_mul_prim) }, // paper mario. Added by Gonetz // (t1-env)*t1+t0, (cmb-0)*shade+0 { 0x02aa0f38, cmb(ac__t0_inter_t1_using_enva__mul_shade) }, // Scary dead boss thing, zelda // (env-1)*t1+t0, (cmb-0)*prim+0 * MAY need t1_inter_t0 instead... { 0x02b50ef8, cmb(ac__env_sub_one_mul_t1_add_t0__mul_prim) }, // first screen, castlevania. Added by Gonetz // (env-0)*t1+t0 **INC** { 0x02bd02bd, cmb(ac_t0) }, // enemy's shot, battle tanks 2 [Flash] // (1-0)*t1+t0, (0-0)*0+env { 0x02be0bff, cmb(ac_env) }, // battle tanks 2 [Ogy] // (1-0)*t1+t0, (0-0)*0+1 { 0x02be0dff, cmb(ac_one) }, // menu screen, Rayman2. Added by Gonetz // (1-0)*t1+t0, (cmb-0)*shade+0 { 0x02be0f38, cmb(ac__t0_add_t1__mul_shade) }, // Sky, zelda //z (t1-t0)*prim+t0 { 0x02ca02ca, cmb(ac_t0_inter_t1_using_prima) }, // F1 World Grand Prix. Added by Gonetz // (t1-t0)*prim+t0, (0-0)*0+1 { 0x02ca0dff, cmb(ac_t0_inter_t1_using_prima) }, // logo, PD. Added by Gonetz // (t1-t0)*prim+t0, (cmb-0)*shade+0 { 0x02ca0f38, cmb(ac__t0_inter_t1_using_prima__mul_shade) }, // battle tanks [Ogy] // (t1-t0)*prim+t0, (cmb-0)*env+0 { 0x02ca0f78, cmb(ac__t0_inter_t1_using_prima__mul_env) }, // logo, Deadly Arts. Added by Gonetz // (env-t0)*prim+t0 { 0x02cd02cd, cmb(ac_one_sub_prim_mul_t0_add__prim_mul_env) }, // intro, castlevania 2. Added by Gonetz // (1-t0)*prim+t0 { 0x02ce02ce, cmb(ac_one_sub_t0_mul_prim_add_t0) }, // intro, diddy kong racing. Added by Gonetz // (1-t0)*prim+t0, (cmb-0)*shade+0 **INC** { 0x02ce0f38, cmb(ac_t0_mul_shade) }, // submitted by Scorpiove, mario party 1 // (0-t0)*prim+t0 { 0x02cf02cf, cmb(ac_one_sub_prim_mul_t0) }, // Ground, pokemon stadium 2 // (t0-0)*prim+t0 { 0x02f902f9, cmb(ac_t0_mul_prim) }, // GASP Fighters // (t1-0)*prim+t0, ** INC ** { 0x02fa02fa, cmb(ac_t1_mul_prima_add_t0) }, // Earthquake pokemon attack, Pokemon Stadium 2 [gokuss4]. Added by Gonetz // (t1-0)*prim+t0, (cmb-0)*shade+0 { 0x02fa0f38, cmb(ac__t1_mul_prima_add_t0__mul_shade) }, // Paper Mario, fortune teller // (t1-0)*prim+t0, (cmb-0)*env+0 { 0x02fa0f78, cmb(ac__t1_mul_prima_add_t0__mul_env) }, // map, Ogre Battle 64. Added by Gonetz // (1-0)*prim+t0 { 0x02fe02fe, cmb(ac_t0_add_prim) }, // borders, Tony Hawk's Pro Skater 2. Added by Gonetz // (t1-t0)*shade+t0 ** INC ** { 0x030a030a, cmb(ac_t0_inter_t1_using_shadea) }, // Mickey USA // (t1-t0)*shade+t0, (cmb-0)*prim+0 ** INC ** { 0x030a0ef8, cmb(ac__t0_inter_t1_using_shadea__mul_prim) }, // Rocket Robot in Wheels intro // (t1-t0)*shade+t0, (cmb-0)*env+0 ** INC ** { 0x030a0f78, cmb(ac__t0_inter_t1_using_shadea__mul_env) }, // water, Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz // (1-t0)*shade+t0, (cmb-0)*shade+0 ** INC ** { 0x030e0f38, cmb(ac_t0_mul_shade) }, // sky, f-zero x // (0-t0)*shade+t0 { 0x030f030f, cmb(ac_one_sub_shade_mul_t0) }, // Deku tree from kokiri villiage, zelda //z (t1-t0)*env+t0, (t1-0)*primlod+cmb { 0x034a01ba, cmb(ac_t0_inter_t1_using_enva) }, // Hearts, zelda //z (t1-t0)*env+t0 { 0x034a034a, cmb(ac_t0_inter_t1_using_enva) }, // Faries, zelda //z (t1-t0)*env+t0, (cmb-0)*prim+0 { 0x034a0ef8, cmb(ac__t0_inter_t1_using_enva__mul_prim) }, // zelda, waterfall. Added by Gonetz //z (t1-t0)*env+t0, (cmb-0)*shade+0 { 0x034a0f38, cmb(ac__t0_inter_t1_using_enva__mul_shade) }, // pokemon stadium 1. Added by Gonetz //(t1-t0)*env+t0, (cmb-0)*primlod+0 { 0x034a0fb8, cmb(ac__t0_inter_t1_using_enva__mul_primlod) }, // fruits, Yoshi Story. Added by Gonetz //(prim-t0)*env+t0 { 0x034b034b, cmb(ac_prim_sub_t0_mul_env_add_t0) }, // window, Rayman2. Added by Gonetz //(1-t0)*env+t0 { 0x034e034e, cmb(ac_one_sub_t0_mul_env_add_t0) }, // menu, PokemonStadium1, [Raziel64] //(1-t0)*env+t0, (cmb-0)*shade+0 ** INC ** { 0x034e0f38, cmb(ac_t0_mul_shade) }, // Ganon's sword swinging, zelda // (t0-t1)*env+t0, (cmb-0)*prim+0 ** INC ** { 0x03510ef8, cmb(ac__t0_sub_t1_mul_enva_add_t0__mul_prim) }, // Lave piranha atack, Paper Mario // (t1-prim)*env+t0, (0-cmb)*t1+0 ** INC ** { 0x035a0e87, cmb(ac_t0_mul_t1) }, // Reflected fire at kotake & koume's, zelda // (t0-1)*env+t0, (cmb-0)*prim+0 ** INC ** { 0x03710ef8, cmb(ac__t0_sub_one_mul_enva_add_t0__mul_prim) }, // thing that escapes from the well, zelda // (t1-1)*env+t0 ** INC ** { 0x03720372, cmb(ac_t1_sub_one_mul_enva_add_t0) }, // Sword charge, zelda // (t1-1)*env+t0, (cmb-0)*prim+0 { 0x03720ef8, cmb(ac__t1_sub_one_mul_enva_add_t0__mul_prim) }, // Gannon hitting the ground, zelda // (t1-1)*env+t0, (cmb-0)*shade+0 ** INC ** { 0x03720f38, cmb(ac__t1_sub_one_mul_enva_add_t0__mul_shade) }, // Tony Hawk's Pro Skater 3. Added by Gonetz // (t0-0)*env+t0 { 0x03790379, cmb(ac_t0_mul_env) }, // paper mario. Added by Gonetz // (t0-0)*env+t0, (cmb-0)*prim+0 { 0x03790ef8, cmb(ac_t0_mul_prim) }, // pads, Pokemon Stadium 2. Added by Gonetz // (t1-0)*env+t0, (cmb-0)*prim+env ** INC ** { 0x037a0af8, cmb(ac__t0_inter_t1_using_enva__mul_prim_add_env) }, // Ice arrow gfx, zelda // (t1-0)*env+t0, (cmb-0)*prim+0 { 0x037a0ef8, cmb(ac__t1_mul_enva_add_t0__mul_prim) }, // Scary face move, pokemon stadium 2 // (t1-0)*env+t0, (cmb-prim)*shade+0 { 0x037a0f18, cmb(ac__t0_inter_t1_using_enva__mul_prim_mul_shade) }, // Saria's song, zelda // (t1-0)*env+t0, (cmb-0)*shade+0 { 0x037a0f38, cmb(ac__t1_mul_enva_add_t0__mul_shade) }, // eye drops bottle, zelda // (t0-t0)*prim_lodfrac+t0 { 0x03890389, cmb(ac_t0) }, // lighthouse's beam, zelda 2. Added by Gonetz // (t0-t0)*prim_lodfrac+t0, (cmb-0)*prim+0 { 0x03890ef8, cmb(ac_t0_mul_prim) }, // zelda 2. Added by Gonetz // (t1-t0)*primlod+t0, (cmb-0)*env+cmb ** INC ** { 0x038a0178, cmb(ac__t0_inter_t1_using_primlod__mul_env_add__t0_inter_t1_using_primlod) }, // Enter name letter background, zelda //z (t1-t0)*primlod+t0 { 0x038a038a, cmb(ac_t0_inter_t1_using_primlod) }, // Sunny Day, Pokemon Stadium 2 [gokuss4]. Added by Gonetz // (t1-t0)*primlod+t0, (cmb-0)*0+prim ** INC **? { 0x038a07f8, cmb(ac_t0_inter_t1_using_primlod) }, // blastcorps, unimp log. Added by Gonetz // (t1-t0)*primlod+t0, (0-0)*0+shade **INC**? { 0x038a09ff, cmb(ac_t0_inter_t1_using_primlod) }, // sky, PGA European Tour // (t1-t0)*primlod+t0, (0-0)*0+1 { 0x038a0dff, cmb(ac_one) }, // Ice surrounding enemy, zelda // (t1-t0)*primlod+t0, (env-0)*lodf+0 { 0x038a0e3d, cmb(ac__t0_inter_t1_using_primlod__mul_env) }, // the bridge out side the mountain smithy shop, zelda 2 [Ogy]. Added by Gonetz // (t1-t0)*primlod+t0, (cmb-0)*t0+0 { 0x038a0e78, cmb(ac_t0_inter_t1_using_primlod) }, // zelda 2, [Ogy]. Added by Gonetz // (t1-t0)*primlod+t0, (cmb-0)*t1+0 { 0x038a0eb8, cmb(ac_t0_inter_t1_using_primlod) }, // Kirby's pool, smash bros // (t1-t0)*primlod+t0, (cmb-0)*prim+0 { 0x038a0ef8, cmb(ac__t0_inter_t1_using_primlod__mul_prim) }, // Samus stage fire, smash bros // (t1-t0)*primlod+t0, (cmb-0)*shade+0 { 0x038a0f38, cmb(ac__t0_inter_t1_using_primlod__mul_shade) }, // something about ice, zelda // (t1-t0)*primlod+t0, (cmb-0)*env+0 { 0x038a0f78, cmb(ac__t0_inter_t1_using_primlod__mul_env) }, // Blast Corps. Added by Gonetz // (t1-t0)*primlod+t0, (shade-0)*env+0 { 0x038a0f7c, cmb(ac_env_mul_shade) }, // goals, J. League Tactics Soccer. Added by Gonetz // (prim-t0)*primlod+t0 ** INC ** { 0x038b038b, cmb(ac_t0) }, // zelda 2, [Ogy]. Added by Gonetz // (t0-t1)*primlod+t0, (cmb-0)*prim+0 { 0x03910ef8, cmb(ac__t0_sub_t1_mul_primlod_add_t0__mul_prim) }, // a plane in the entrance to the mountain village zelda 2, [Ogy]. Added by Gonetz // (t1-t1)*primlod+t0, (cmb-0)*prim+0 ** INC **? { 0x03920ef8, cmb(ac_t0_mul_prim) }, // zelda 2. Added by Gonetz // (t1-prim)*primlod+t0, (cmb-0)*prim+0 ** INC ** { 0x039a0ef8, cmb(ac__t1_sub_prim_mul_primlod_add_t0__mul_prim) }, // zelda 2. Added by Gonetz // (t1-shade)*primlod+t0, (cmb-0)*shade+0 ** INC ** { 0x03a20f38, cmb(ac__t1_sub_shade_mul_primlod_add_t0__mul_shade) }, // Candle flame in ganon's castle, zelda // (t1-1)*primlod+t0 ** INC ** { 0x03b203b2, cmb(ac_t1_sub_one_mul_primlod_add_t0) }, // Fire, zelda //z (t1-1)*primlod+t0, (cmb-0)*prim+0 ** INC ** { 0x03b20ef8, cmb(ac__t1_sub_one_mul_primlod_add_t0__mul_prim) }, // explosion, zelda 2. Added by Gonetz // (t1-1)*primlod+t0, (t0-0)*prim+0 ** INC ** { 0x03b20ef9, cmb(ac_t0_mul_prim) }, // Din's fire, zelda // (t1-1)*prim_lodfrac+t0, (cmb-0)*shade+0 ** INC ** { 0x03b20f38, cmb(ac__t1_sub_one_mul_primlod_add_t0__mul_shade) }, // Fire cloud, zelda // (t1-1)*prim_lodfrac+t0, (cmb-0)*env+0 ** INC ** { 0x03b20f78, cmb(ac__t1_sub_one_mul_primlod_add_t0__mul_env) }, // zelda 2 [Ogy]. Added by Gonetz // (prim-1)*prim_lodfrac+t0, (cmb-0)*env+0 ** INC ** { 0x03b30f78, cmb(ac__prim_sub_one_mul_primlod_add_t0__mul_env) }, // fairy's spirit, zelda oot // (t0-0)*primlod+t0 { 0x03b903b9, cmb(ac_t0_mul_primlod_add_t0) }, // Scary face, pokemon stadium 2 // (t0-0)*primlod+t0, (cmb-0)*prim+0 { 0x03b90ef8, cmb(ac_t0_mul_prim) }, // Leftovers Recovery, Pokemon Stadium 2 [gokuss4]. Added by Gonetz // (t1-0)*prim_lodfrac+t0, (cmb-env)*prim+0 ** INC ** { 0x03ba0ee8, cmb(ac__t1_mul_primlod_add_t0__sub_env_mul_prim) }, // zelda 2 [Ogy]. Added by Gonetz // (t1-0)*prim_lodfrac+t0, (cmb-0)*prim+0 { 0x03ba0ef8, cmb(ac__t1_mul_primlod_add_t0__mul_prim) }, // zelda 2 [Ogy]. Added by Gonetz // (t1-0)*prim_lodfrac+t0, (cmb-0)*shade+0 { 0x03ba0f38, cmb(ac__t1_mul_primlod_add_t0__mul_shade) }, // chuchu monsters, zelda 2 [Ogy]. Added by Gonetz // (t1-0)*prim_lodfrac+t0, (cmb-0)*env+0 { 0x03ba0f78, cmb(ac__t1_mul_primlod_add_t0__mul_env) }, // Scary face, pokemon stadium 2 // (env-0)*primlod+t0, (cmb-0)*prim+0 { 0x03bd0ef8, cmb(ac_t0_mul_prim) }, // ground, zelda 2. Added by Gonetz // (t1-t0)*0+t0, (cmb-0)*0+cmb { 0x03ca01f8, cmb(ac_t0) }, // zelda 2. Added by Gonetz // (t1-t0)*0+t0, (cmb-0)*prim+0 { 0x03ca0ef8, cmb(ac_t0_mul_prim) }, // smoke in a night, zelda 2. Added by Gonetz // (t1-t0)*0+t0, (cmb-0)*shade+0 { 0x03ca0f38, cmb(ac_t0_mul_shade) }, //the ice plane out side the mountain smithy shop, zelda 2 [Ogy]. Added by Gonetz //(t1-1)*0+t0, (cmb-0)*env+0 { 0x03f20f78, cmb(ac_t0_mul_env) }, //something on level 5, Kirby64 [Raziel64] //(t0-0)*0+t0 { 0x03f903f9, cmb(ac_t0) }, //spider house, zelda 2 [Ogy]. Added by Gonetz //(t0-0)*0+t0, (cmb-0)*prim+0 { 0x03f90ef8, cmb(ac_t0_mul_prim) }, //Darmani's fire spin, zelda 2 [Ogy]. Added by Gonetz //(t1-0)*0+t0, (cmb-0)*prim+0 { 0x03fa0ef8, cmb(ac_t0_mul_prim) }, // headlight, beetle adventure racing. Added by Gonetz //(1-0)*0+t0 { 0x03fe03fe, cmb(ac_t0) }, // player, super bowling // (0-0)*0+t0, { 0x03ff0000, cmb(ac_t0) }, // Ghost's lantern, zelda // (0-0)*0+t0, (t1-0)*prim_lod+cmb { 0x03ff01ba, cmb(ac_t1_mul_primlod_add_t0) }, // Hand cursor, mario //z (0-0)*0+t0 { 0x03ff03ff, cmb(ac_t0) }, // Taz express. Added by Gonetz // (0-0)*0+t0, (0-0)*0+t1 { 0x03ff05ff, cmb(ac_t0) }, // powder keg, zelda2. Added by Gonetz // (0-0)*0+t0, (0-0)*0+prim { 0x03ff07ff, cmb(ac_t0) }, // water, Spacestation Silicon Valley. Added by Gonetz // (0-0)*0+t0, (0-0)*0+shade { 0x03ff09ff, cmb(ac_t0) }, // Characters, Ogre Battle. Added by Gonetz. // (0-0)*0+t0, (cmb-0)*prim+env { 0x03ff0af8, cmb(ac_t0_mul_prim_add_env) }, // Monster truck madness intro. Added by Gonetz // (0-0)*0+t0, (0-0)*0+env { 0x03ff0bff, cmb(ac_t0) }, // Zoras, zelda // (0-0)*0+t0, (env-0)*lodf+0 { 0x03ff0e3d, cmb(ac_env) }, // logo, v-rally 99 // (0-0)*0+t0, (prim-0)*t0+0 { 0x03ff0e7b, cmb(ac_t0_mul_prim) }, // intro, WWF-War Zone // (0-0)*0+t0, (env-0)*t0+0 { 0x03ff0e7d, cmb(ac_t0_mul_env) }, // Window, starfox //z (0-0)*0+t0, (cmb-0)*prim+0 { 0x03ff0ef8, cmb(ac_t0_mul_prim) }, //beetle adventure racing. Added by Gonetz // (0-0)*0+t0, (cmb-0)*shade+0 { 0x03ff0f38, cmb(ac_t0_mul_shade) }, // Wonder Project J2 logo. Added by Gonetz // (0-0)*0+t0, (t0-0)*shade+0 { 0x03ff0f39, cmb(ac_t0_mul_shade) }, // Saria's suit, zelda // (0-0)*0+t0, (cmb-0)*env+0 { 0x03ff0f78, cmb(ac_t0_mul_env) }, // Pokemon Stadium 2, [Jeremy]. Added by Gonetz // (0-0)*0+t0, (cmb-0)*primlod+0 { 0x03ff0fb8, cmb(ac_t0_mul_primlod) }, // Tony Hawk's Pro Skater. Added by Gonetz // (0-0)*0+t0, (0-0)*0+0 { 0x03ff0fff, cmb(ac_zero) }, // Powered Star Beam, Paper Mario. Added by Gonetz // (t0-t1)*t0+t1, (cmb-0)*prim+0 **INC** { 0x04510ef8, cmb(ac__t1_inter_t0_using_t0a__mul_prim) }, // Deadly Arts logo. Added by Gonetz // (1-0)*t0+t1, (1-0)*prim+cmb { 0x047e00fe, cmb(ac__t0_add_t1__add_prim) }, // Spiderman. Added by Gonetz // (1-0)*t0+t1 { 0x047e047e, cmb(ac_t0_add_t1) }, // water, Dobutsu no Mori. Added by Gonetz // (1-0)*t0+t1, (cmb-0)*primlod+prim { 0x047e07b8, cmb(ac__t0_add_t1__mul_primlod_add_prim) }, // paper mario. Added by Gonetz // (1-t0)*t1+t1, (cmb-0)*t1+0 **INC** { 0x048e0eb8, cmb(ac_t0_mul_t1) }, // Pokemon Stadium 2. Added by Gonetz // (t0-prim)*t1+t1, (cmb-0)*shade+0 **INC** { 0x04990f38, cmb(ac_t1_mul_shade) }, // light, Dobutsu no Mori. Added by Gonetz // (t0-0)*t1+t1, (cmb-0)*primlod+0 ** INC ** { 0x04b90fb8, cmb(ac__t0_add_t1__mul_primlod) }, // lava, beetle adventure racing // (t1-0)*t1+t1, (cmb-0)*shade+0 ** INC ** { 0x04ba0f38, cmb(ac__t1_mul_t1_add_t1__mul_shade) }, // wheels, F1 World Grand Prix. Added by Gonetz // (t0-t1)*prim+t1 { 0x04d104d1, cmb(ac_t1_inter_t0_using_prima) }, // intro, castlevania 2. Added by Gonetz // (t0-t1)*prim+t1, (cmb-0)*shade+0 { 0x04d10f38, cmb(ac__t1_inter_t0_using_prima__mul_shade) }, // flame, castlevania 2. Added by Gonetz // (t0-t1)*prim+t1, (cmb-0)*env+0 { 0x04d10f78, cmb(ac__t1_inter_t0_using_prima__mul_env) }, // walls, beetle adventure racing. Added by Gonetz // (t0-0)*prim+t1 **INC** { 0x04f904f9, cmb(ac_t0_mul_prim) }, // Reflect pokemon attack, Pokemon Stadium 2 [gokuss4]. Added by Gonetz // (t0-0)*prim+t1, (cmb-0)*prim+env **INC** { 0x04f90af8, cmb(ac__t0_add_t1__mul_prim_add_env) }, // Psychic pokemon attack, Pokemon Stadium 2 [gokuss4]. Added by Gonetz // (t0-0)*prim+t1, (cmb-0)*shade+0 **INC** { 0x04f90f38, cmb(ac__t0_add_t1__mul_shade) }, // Rayman2. Added by Gonetz // (0-0)*shade+t1, (cmb-0)*env+0 { 0x053f0f78, cmb(ac_t1_mul_env) }, // Ground at kotake & koume, zelda // (t1-t0)*env+t1, (cmb-0)*prim+0 ** INC ** { 0x054a0ef8, cmb(ac__t1_sub_t0_mul_enva_add_t1__mul_prim) }, // Tony Hawk's Pro Skater. Added by Gonetz // (t0-t1)*env+t1 { 0x05510551, cmb(ac_t1_inter_t0_using_enva) }, // Shiek's disappearance, zelda // (t0-1)*env+t1 { 0x05710571, cmb(ac_t0_sub_one_mul_enva_add_t1) }, // Kotake or koume's magic poof, zelda // (t0-1)*env+t1, (cmb-0)*prim+0 ** INC ** { 0x05710ef8, cmb(ac__t0_sub_one_mul_enva_add_t1__mul_prim) }, // Gauntlet Legends intro // (t0-0)*env+t1, (cmb-0)*prim+0 ** INC ** { 0x05790ef8, cmb(ac__t0_add_t1__mul_prim) }, // Zelda opening door, zelda // (t0-0)*env+t1, (cmb-0)*shade+0 { 0x05790f38, cmb(ac_t1_mul_shade) }, // paper mario. Added by Gonetz // (t1-0)*env+t1, (cmb-0)*prim+0 ** INC ** { 0x057a0ef8, cmb(ac_t1_mul_prim) }, // Skulltula coin, zelda // (t0-1)*primlod+t1 ** INC ** { 0x05b105b1, cmb(ac_t0_mul_t1) }, // Bell, Pokemon Stadium 2. Added by Gonetz // (t0-0)*primlod+t1, (cmb-env)*prim ** INC ** { 0x05b90ee8, cmb(ac__t0_add_t1__mul_prim) }, // intro, Aidyn Chronicles. Added by Gonetz // (0-cmb)*0+t1, (t1-1)*0+cmb { 0x05c701f2, cmb(ac_t1) }, // zelda 2 [Ogy]. Added by Gonetz // (t1-t0)*0+t1, (cmb-0)*prim+0 { 0x05ca0ef8, cmb(ac_t1_mul_prim) }, // beaver's river, zelda 2. Added by Gonetz // (t1-0)*0+t1, (cmb-0)*prim+0 { 0x05fa0ef8, cmb(ac_t1_mul_prim) }, // Ogre Battle, unimp log. Added by Gonetz // (0-0)*0+t1, (0-0)*0+cmb { 0x05ff05ff, cmb(ac_t1) }, // lullaby, Paper Mario. Added by Gonetz // (0-0)*0+t1, (cmb-0)*prim+0 { 0x05ff0ef8, cmb(ac_t1_mul_prim) }, // aerofighter's assault [Ogy] // (0-0)*0+t1, (cmb-0)*shade+0 { 0x05ff0f38, cmb(ac_t1_mul_shade) }, // magic fist, Rayman2. Added by Gonetz // (0-0)*0+t1, (cmb-0)*env+0 { 0x05ff0f78, cmb(ac_t1_mul_env) }, // Pokemon selection background, Pokemon stadium 2 // (env-prim)*t0+prim { 0x065d065d, cmb(ac_env_sub_prim_mul_t0_add_prim) }, // text background, Ganbare Goemon - Mononoke Sugoroku // (1-prim)*t0+prim { 0x065e065e, cmb(ac_one_sub_prim_mul_t0_add_prim) }, // shadows, star wars: ep1 racer // (0-prim)*t0+prim { 0x065f065f, cmb(ac_zero_sub_prim_mul_t0_add_prim) }, // lava, beetle adventure racing // (0-1)*t0+prim, (cmb-0)*prim+0 ** INC ** { 0x06770ef8, cmb(ac_t0_mul_prim) }, // menu, Ganbare Goemon - Mononoke Sugoroku // (t0-0)*t0+prim { 0x06790679, cmb(ac_t0_add_prim) }, // Water, pokemon stadium 2 // (t1-0)*t0+prim { 0x067a067a, cmb(ac_t0_mul_t1_add_prim) }, // Smackdown Mall Menu, WWF No Mercy // (shade-0)*t0+prim { 0x067c067c, cmb(ac_t0_mul_shade_add_prim) }, // flag, Top Gear Rally 2. Added by Gonetz // (env-0)*t0+prim { 0x067d067d, cmb(ac_t0_mul_env_add_prim) }, // Mario Tennis. Added by Gonetz // (1-0)*t0+prim { 0x067e067e, cmb(ac_t0_add_prim) }, // sky, PGA European Tour // (t0-0)*t1+prim { 0x06b906b9, cmb(ac_t0_mul_t1_add_prim) }, // lava, beetle adventure racing // (t0-0)*t1+prim, (0-0)*0+1 **INC**? { 0x06b90dff, cmb(ac_one) }, // Pokemon Stadium 2, [Jeremy]. Added by Gonetz // (prim-0)*t1+prim { 0x06bb06bb, cmb(ac_t1_mul_prim_add_prim) }, // pokemon psyattack, Pokemon Stadium 2. Added by Gonetz // (1-0)*t1+prim, (cmb-0)*env+0 { 0x06be0f78, cmb(ac_t1_add_prim_mul_env) }, // Rush2 2. Added by Gonetz // (prim-prim)*prim+prim { 0x06db06db, cmb(ac_prim) }, //Spacestation Silicon Valley intro. Added by Gonetz // (t1-prim)*shade+prim // { 0x071a071a, cmb(ac_t1_mul_shade) }, { 0x071a071a, cmb(ac_t1_sub_prim_mul_shade_add_prim) }, //KI logos. Added by Gonetz // (env-prim)*shade+prim { 0x071d071d, cmb(ac_env_sub_prim_mul_shade_add_prim) }, // Deadly Arts, arena. Added by Gonetz // (1-0)*shade+prim { 0x073e073e, cmb(ac_prim_add_shade) }, // Phantom Gannon's portal, zelda // (t1-t0)*env+prim, (cmb-0)*shade+0 ** INC ** { 0x074a0f38, cmb(ac__t0_mul_t1__mul_prim_mul_shade) }, // Road rush. Added by Gonetz // (t0-0)*env+prim { 0x07790779, cmb(ac_t0_mul_env_add_prim) }, // telescope, zelda 2. Added by Gonetz // (1-t0)*primlod+prim { 0x078e078e, cmb(ac_one_sub_t0_mul_primlod_add_prim) }, // zelda 2 [Ogy]. Added by Gonetz // (t0-t1)*primlod+prim, (cmb-0)*t0+0 { 0x07910e78, cmb(ac_t0_inter_t1_using_primlod) }, // Dobutsu no Mori. Added by Gonetz // (t0-0)*primlod+prim { 0x07b907b9, cmb(ac_t0_mul_primlod_add_prim) }, // water, DK64 // (0-0)*0+0, (0-t1)*0+prim { 0x07d707d7, cmb(ac_prim) }, // Menu, megaman // (1-0)*0+prim { 0x07fe07fe, cmb(ac_prim) }, // super bowling //(0-0)*0+prim, { 0x07ff0000, cmb(ac_prim) }, // menu, Ganbare Goemon - Mononoke Sugoroku // (0-0)*0+prim, (0-0)*0+t0 { 0x07ff03ff, cmb(ac_t0) }, // Intro background, starfox //z (0-0)*0+prim { 0x07ff07ff, cmb(ac_prim) }, // gem, castlevania 2. Added by Gonetz // (0-0)*0+prim, (cmb-0)*t0+0 { 0x07ff0e78, cmb(ac_t0_mul_prim) }, // text, Tony Hawk's Pro Skater. Added by Gonetz // (0-0)*0+prim, (cmb-0)*t1+0 { 0x07ff0eb8, cmb(ac_t1_mul_prim) }, //weird, but implementing this makes text unreadable // zelda 2. Added by Gonetz // (0-0)*0+prim, (cmb-0)*prim+0 { 0x07ff0ef8, cmb(ac_prim_mul_prim) }, // explosion, Blast Corps. Added by Gonetz // (0-0)*0+prim, (t0-0)*prim+0 { 0x07ff0ef9, cmb(ac_t0_mul_prim) }, // zelda 2, [Ogy]. Added by Gonetz // (0-0)*0+prim, (cmb-0)*shade+0 { 0x07ff0f38, cmb(ac_prim_mul_shade) }, // Fox's ears and arms, smash bros // (0-0)*0+prim, (cmb-0)*env+0 { 0x07ff0f78, cmb(ac_prim_mul_env) }, // monsters, Pokemon Stadium. Added by Gonetz // (0-0)*0+prim, (cmb-0)*primlod+0 { 0x07ff0fb8, cmb(ac_prim_mul_primlod) }, // focus, Paper Mario. Added by Gonetz //(t0-shade)*t0+shade, (cmb-0)*prim+0 * INC ** { 0x08610ef8, cmb(ac_t0_mul_prim) }, // Mario's head, mario //Added by Gonetz //(prim-shade)*t0+shade { 0x08630863, cmb(ac_prim_sub_shade_mul_t0_add_shade) }, // Earthquake pokemon attack, Pokemon Stadium 2 [gokuss4]. Added by Gonetz //(t0-t1)*prim+shade, (cmb-0)*shade+0 ** INC ** { 0x08d10f38, cmb(ac_t0_mul_prim_mul_shade) }, // ? //(t0-shade)*prim+shade { 0x08e108e1, cmb(ac_t0_mul_prim_add_shade_mul_one_minus_prim) }, // Paper Mario // (t0-prim)*shade+shade, (cmb-0)*env+0 { 0x09190f78, cmb(ac__t0_sub_prim_mul_shade_add_shade__mul_env) }, // pads, Pokemon Stadium 2. Added by Gonetz // (0-t0)*env+shade, (cmb-0)*prim+0 ** INC ** { 0x094f0ef8, cmb(ac_one_sub_t0_mul_prim_mul_shade) }, // Huge turtle appearance, zelda 2. Added by Gonetz // (t1-0)*primlod+shade, (cmb-0)*shade+0 ** INC ** { 0x09ba0f38, cmb(ac_t1_mul_shade) }, // roof, Kirby 64. Added by Gonetz // (t0-0)*0+shade { 0x09f909f9, cmb(ac_shade) }, // water, Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz // (0-0)*0+shade, (cmb-cmb)*lodf+cmb { 0x09ff0000, cmb(ac_shade) }, // water temple, zelda 2. Added by Gonetz // (0-0)*0+shade, (cmb-0)*prim+cmb { 0x09ff00f8, cmb(ac_prim_mul_shade_add_shade) }, // damaged car, SCARS. Added by Gonetz // (0-0)*0+shade, (t0-t1)*primlod+prim ** INC ** { 0x09ff0791, cmb(ac_t0_mul_primlod_add_prim) }, // Hyrule castle gate, zelda //z (0-0)*0+shade, (0-0)*0+prim { 0x09ff07ff, cmb(ac_prim) }, // Super Mario 64 logo //z (0-0)*0+shade { 0x09ff09ff, cmb(ac_shade) }, // terrain, SCARS. Added by Gonetz // (0-0)*0+shade, (0-0)*0+1 { 0x09ff0dff, cmb(ac_one) }, // terrain, SCARS. Added by Gonetz // (0-0)*0+shade, (t0-0)*t1+0 { 0x09ff0eb9, cmb(ac_t0_mul_t1) }, // N64 logo, Aidyn Chronicles. Added by Gonetz // (0-0)*0+shade, (cmb-0)*prim+0 { 0x09ff0ef8, cmb(ac_prim_mul_shade) }, // birds?, custom robo. Added by Gonetz // (0-0)*0+shade, (cmb-0)*shade+0 { 0x09ff0f38, cmb(ac_shade) }, // sky, Glover, [Raziel64]. Added by Gonetz // (0-0)*0+shade, (t0-0)*shade+0 { 0x09ff0f39, cmb(ac_t0_mul_shade) }, // Hand, smash bros // (0-0)*0+shade, (cmb-0)*env+0 { 0x09ff0f78, cmb(ac_env_mul_shade) }, // Conker's helicopter tail, CBFD // (0-0)*0+shade, (shade-0)*env+0 { 0x09ff0f7c, cmb(ac_env_mul_shade) }, // menu, PokemonStadium1, [Raziel64] // (0-0)*0+shade, (cmb-0)*primlod+0 { 0x09ff0fb8, cmb(ac_primlod_mul_shade) }, // Link's sword slashing, smash bros // (prim-env)*t0+env { 0x0a6b0a6b, cmb(ac_prim_sub_env_mul_t0_add_env) }, // Reflected beam at kotake & koume's, zelda // (prim-env)*t0+env, (cmb-0)*prim+0 ** INC ** { 0x0a6b0ef8, cmb(ac_t0_mul_prim) }, // teleporter, Spacestation Silicon Valley. Added by Gonetz // (prim-env)*t0+env, (cmb-0)*shade+0 ** INC ** { 0x0a6b0f38, cmb(ac_t0_mul_shade) }, // Ridge Racer, unimp log. Added by Gonetz // (prim-env)*t0+env, (cmb-0)*primlod+0 { 0x0a6b0fb8, cmb(ac_prim_sub_env_mul_t0_add_env) }, // Kotake or koume's hair, zelda // (prim-0)*t0+env { 0x0a7b0a7b, cmb(ac_t0_mul_prim_add_env) }, // menu, doubut no mori // (1-0)*t0+env { 0x0a7e0a7e, cmb(ac_t0_add_env) }, // Grass, mario golf // (env-shade)*t1+env, (0-0)*0+1 { 0x0aa50dff, cmb(ac_one) }, // Ridge Racer, cars select. Added by Gonetz // (prim-env)*t1+env { 0x0aab0aab, cmb(ac_prim_sub_env_mul_t1_add_env) }, // text, monster truck madness // (prim-env)*t1+env, (cmb-0)*t1+0 { 0x0aab0eb8, cmb(ac_t1_mul_env) }, // zelda 2 [Ogy]. Added by Gonetz // (1-0)*t1+env, (0-0)*0+cmb { 0x0abe0abe, cmb(ac_one) }, // { 0x0abe0abe, cmb(ac_t1_add_env) }, // arena, Pokemon Stadium 2. Added by Gonetz // (1-t0)*prim+env, (cmb-0)*shade+0 { 0x0ace0f38, cmb(ac_one_sub_t0_mul_prim_mul_shade) }, // intro, Bomberman 64 - 2. Added by Gonetz // (t0-env)*prim+env { 0x0ae90ae9, cmb(ac_t0_sub_env_mul_prim_add_env) }, // N64 logo, Ogre Battle. Added by Gonetz // (t0-0)*prim+env { 0x0af90af9, cmb(ac_t0_mul_prim_add_env) }, // girls, PD intro. Added by Gonetz // (t0-env)*shade+env ** INC ** { 0x0b290b29, cmb(ac_t0_mul_shade_add_env) }, // shadows, Mario Tennis. Added by Gonetz // (prim-env)*shade+env, (0-cmb)*t1+cmb ** INC ** { 0x0b2b0087, cmb(ac_prim_sub_env_mul_shade_add_env_mul_t1) }, // lamppost?, Ridge Racer. Added by Gonetz // (prim-env)*shade+env, (0-0)*0+cmb { 0x0b2b0b2b, cmb(ac_prim_sub_env_mul_shade_add_env) }, // ground, zelda2. Added by Gonetz // (1-env)*shade+env, (t1-0)*prim+0 { 0x0b2e0efa, cmb(ac_t1_mul_prim) }, // GASP Fighters // (t0-0)*shade+env { 0x0b390b39, cmb(ac_t0_mul_shade_add_env) }, // destroying stuff, golden eye // (1-0)*shade+env { 0x0b3e0b3e, cmb(ac_env_add_shade) }, // Papeer Mario. Added by Gonetz // (t0-t1)*env+env, (0-0)*0+1 { 0x0b510dff, cmb(ac_one) }, // International Track and Field 2000. Added by Gonetz // (t0-0)*0+env { 0x0bf90bf9, cmb(ac_env) }, // TM, mario //z (0-0)*0+env { 0x0bff0bff, cmb(ac_env) }, // rancho monster, zelda2. Added by Gonetz // (0-0)*0+env, (cmb-0)*t1+0 { 0x0bff0eb8, cmb(ac_t1_mul_env) }, // Rocket Robot in Wheels intro // (0-0)*0+env, (cmb-0)*prim+0 { 0x0bff0ef8, cmb(ac_prim_mul_env) }, // Tony Hawk's Pro Skater. Added by Gonetz // (1-t0)*t1+1, (cmb-t1)*t1+t1 ** INC ** { 0x0c770c77, cmb(ac_t0_mul_t1) }, // flame, paper mario. Added by Gonetz // (1-t0)*t1+1, (cmb-t1)*t1+t1 { 0x0c8e0490, cmb(ac_t0_mul_t1) }, // Ring boundary, dual heroes // (0-1)*prim+1 { 0x0cf70cf7, cmb(ac_one_sub_prim) }, // Kirby64, level 6, [Raziel64] // (0-0)*prim+1 { 0x0cff0cff, cmb(ac_one) }, // Mystical Ninja // (0-1)*env+1 { 0x0d770d77, cmb(ac_one) }, // Deku shield in shop, zelda // (1-1)*primlod+1 { 0x0db60db6, cmb(ac_one) }, // water near gorons willage. Added by Gonetz // (t1-t0)*0+1, (cmb-0)*prim+0 { 0x0dca0ef8, cmb(ac_prim) }, // background, kirby 64. Added by Gonetz // (t0-0)*0+1 { 0x0df90df9, cmb(ac_one) }, // kirby 64. Added by Gonetz // (1-0)*0+1 { 0x0dfe0dfe, cmb(ac_one) }, // background on level 2-1, kirby 64 [Raziel64]. Added by Gonetz // (1-0)*0+1, (0-0)*0+1 { 0x0dfe0dff, cmb(ac_one) }, // duck dodgers intro. Added by Gonetz // (0-0)*0+1, (cmb-cmb)*primlod+cmb { 0x0dff0000, cmb(ac_one) }, // duck dodgers intro. Added by Gonetz // (0-0)*0+1, (0-0)*0+t1 **INC**? { 0x0dff05ff, cmb(ac_t1) }, // ? // (0-0)*0+1, (0-0)*0+prim { 0x0dff07ff, cmb(ac_prim) }, // arena, custom robo. Added by Gonetz // (0-0)*0+1, (0-0)*0+shade { 0x0dff09ff, cmb(ac_shade) }, // field, Mario Golf // (0-0)*0+1, (1-env)*shade+env { 0x0dff0b2e, cmb(ac_one_sub_env_mul_shade_add_env) }, // battle tanks 2 [Ogy] // (0-0)*0+1, (0-0)*0+env { 0x0dff0bff, cmb(ac_env) }, // helmet, F1 World Grand Prix. Added by Gonetz // (0-0)*0+1, (0-1)*0+1 { 0x0dff0df7, cmb(ac_one) }, // secret in level 3-4, Kirby64, [Raziel64] // (0-0)*0+1, (cmb-0)*0+1 { 0x0dff0df8, cmb(ac_one) }, // Menu options, starfox // (0-0)*0+1 { 0x0dff0dff, cmb(ac_one) }, // Water, zelda //z (0-0)*0+primlod, (cmb-0)*prim+0 { 0x0dff0ef8, cmb(ac_prim) }, // Desert ground, zelda // (0-0)*0+1, (cmb-0)*shade+0 { 0x0dff0f38, cmb(ac_shade) }, // Characters, smash bros // (0-0)*0+1, (cmb-0)*env+0 { 0x0dff0f78, cmb(ac_env) }, // end of level 3-4, Kirby64, [Raziel64] // (0-0)*0+1, (cmb-0)*0+0 { 0x0dff0ff8, cmb(ac_zero) }, // Kirby64 // (0-0)*0+1, (0-0)*0+0 { 0x0dff0fff, cmb(ac_zero) }, // floor, Spiderman [Raziel64]. Added by Gonetz // (env-t1)*t0+0 ** INC ** { 0x0e550e55, cmb(ac_t0_mul_env) }, // skeleton, castlevania 2. Added by Gonetz // (1-prim)*t0+0 { 0x0e5e0e5e, cmb(ac_one_sub_prim_mul_t0) }, // player select, Forsaken [Raziel64]. Added by Gonetz // (prim-shade)*t0+0 { 0x0e630e63, cmb(ac_prim_sub_shade_mul_t0) }, // castlevania 2 [Ogy]. Added by Gonetz // (1-shade)*t0+0 { 0x0e660e66, cmb(ac_one_sub_shade_mul_t0) }, // background, level3-4, Kirby64, [Raziel64] // (shade-env)*t0+0 { 0x0e6c0e6c, cmb(ac_shade_sub_env_mul_t0) }, // Goemon, mystical ninja. Added by Gonetz // (1-env)*t0+0 { 0x0e6e0e6e, cmb(ac_one_sub_env_mul_t0) }, // fist attack, Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz // (t0-0)*t0+0, (t1-cmb)*prim+cmb { 0x0e7900c2, cmb(ac_t0_inter_t1_using_prima) }, // Clay Fighter [Ogy]. Added by Gonetz // (t0-0)*t0+0 { 0x0e790e79, cmb(ac_t0_mul_t0) }, // Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz // (t0-0)*t0+0, (prim-0)*t1+0 { 0x0e790ebb, cmb(ac_t1_mul_prim) }, // zelda 2 [Ogy]. Added by Gonetz // (t0-0)*t0+0, (cmb-0)*prim+0 { 0x0e790ef8, cmb(ac_t0_mul_prim) }, // zelda 2. Added by Gonetz // (t0-0)*t0+0, (cmb-0)*shade+0 { 0x0e790f38, cmb(ac_t0_mul_shade) }, // zelda 2. Added by Gonetz // (t0-0)*t0+0, (cmb-0)*env+0 { 0x0e790f78, cmb(ac_t0_mul_env) }, // the ice plane just before the entrance to gorons village (where tingle is) }, zelda 2 [Ogy]. Added by Gonetz // (t1-0)*t0+0, (cmb-0)*0+cmb { 0x0e7a01f8, cmb(ac_t0_mul_t1) }, // paper mario. Added by Gonetz // (t1-0)*t0+0, (cmb-env)*prim+env ** INC ** { 0x0e7a0ae8, cmb(ac_t1_mul_prim) }, // Tony Hawk's Pro Skater. Added by Gonetz // (t1-0)*t0+0, (cmb-0)*t0+0 { 0x0e7a0e78, cmb(ac_t0_mul_t1) }, // bike trace, xg2. Added by Gonetz // (t1-0)*t0+0 { 0x0e7a0e7a, cmb(ac_t0_mul_t1) }, // Kotake & koume defeated, zelda // (t1-0)*t0+0, (cmb-0)*prim+0 { 0x0e7a0ef8, cmb(ac__t0_mul_t1__mul_prim) }, // Magnitude, pokemon stadium 2 // (t1-0)*t0+0, (cmb-env)*shade+0 { 0x0e7a0f28, cmb(ac__t0_mul_t1__mul_env_mul_shade) }, // Bongo Bongo, zelda // (t1-0)*t0+0, (cmb-0)*shade+0 { 0x0e7a0f38, cmb(ac__t0_mul_t1__mul_shade) }, // Back of doors, megaman // (prim-0)*t0+0, (cmb-0)*lodfrac+0 { 0x0e7b0e38, cmb(ac_t0_mul_prim) }, // Karts, mario kart //z (prim-0)*t0+0 { 0x0e7b0e7b, cmb(ac_t0_mul_prim) }, // paper mario. Added by Gonetz // (prim-0)*t0+0, (t0-0)*prim+0 { 0x0e7b0ef9, cmb(ac_t0_mul_prim) }, // Table, mace // (prim-0)*t0+0, (cmb-0)*shade+0 { 0x0e7b0f38, cmb(ac_t0_mul_prim_mul_shade) }, // lamp shadow, Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz // (shade-0)*t0+0, (cmb-cmb)*lodf+cmb { 0x0e7c0000, cmb(ac_t0_mul_shade) }, // Game logo, Aerofighters Assault [Raziel64] //(shade-0)*t0+0, (0-0)*0+1 { 0x0e7c0dff, cmb(ac_one) }, // Higher sky, waverace //z (shade-0)*t0+0 { 0x0e7c0e7c, cmb(ac_t0_mul_shade) }, // duck dodgers, intro. Added by Gonetz // (shade-0)*t0+0, (cmb-0)*prim+0 { 0x0e7c0ef8, cmb(ac_t0_mul_prim_mul_shade) }, // waterwheel in water temple, zelda 2. Added by Gonetz // (shade-0)*t0+0, (cmb-0)*env+0 { 0x0e7c0f78, cmb(ac_t0_mul_env_mul_shade) }, // Blowing up mine at bowser's, mario // (env-0)*t0+0 { 0x0e7d0e7d, cmb(ac_t0_mul_env) }, // castlevania 2, intro. Added by Gonetz // (1-0)*t0+0 { 0x0e7e0e7e, cmb(ac_t0) }, // moon, castlevania 2. Added by Gonetz // (1-0)*t0+0, (cmb-0)*prim+0 { 0x0e7e0ef8, cmb(ac_t0_mul_prim) }, //beetle adventure racing. Added by Gonetz // (1-0)*t0+0, (cmb-0)*shade+0 { 0x0e7e0f38, cmb(ac_t0_mul_shade) }, // lava, beetle adventure racing // (t0-prim)*t1+0, (0-0)*0+shade ** INC ** { 0x0e9909ff, cmb(ac_shade) }, // Rain Dance, Pokemon Stadium 2 [gokuss4]. Added by Gonetz // (t0-env)*t1+0, (cmb-0)*0+prim ** INC ** { 0x0ea90ef8, cmb(ac__t0_mul_t1__mul_prim) }, // airboarder 64 [Ogy] // (t0-0)*t1+0, (0-0)*0+prim { 0x0eb907ff, cmb(ac_prim) }, // explosion, body harvest. Added by Gonetz // (t0-0)*t1+0, (0-0)*0+shade { 0x0eb909ff, cmb(ac_shade) }, // Text off top, banjo kazooie // (t0-0)*t1+0 { 0x0eb90eb9, cmb(ac_t0_mul_t1) }, // smoke, daikatana. Added by Gonetz // (t0-0)*t1+0, (cmb-0)*prim+0 { 0x0eb90ef8, cmb(ac__t0_mul_t1__mul_prim) }, // Water, pilotwings // (t0-0)*t1+0, (cmb-0)*shade+0 { 0x0eb90f38, cmb(ac__t0_mul_t1__mul_shade) }, // Tony Hawk's Pro Skater. Added by Gonetz // (t0-0)*t1+0, (cmb-0)*env+0 { 0x0eb90f78, cmb(ac__t0_mul_t1__mul_env) }, // light from window, Dobutsu no Mori. Added by Gonetz // (t0-0)*t1+0, (cmb-0)*primlod+0 { 0x0eb90fb8, cmb(ac__t0_mul_t1__mul_primlod) }, // chandelier in spider house, zelda 2. Added by Gonetz // (t1-0)*t1+0, (cmb-0)*prim+0 { 0x0eba0ef8, cmb(ac_t1_mul_prim) }, // cars, ridge racer. Added by Gonetz // (prim-0)*t1+0, (0-0)*0+1 { 0x0ebb0dff, cmb(ac_t1_mul_prim) }, // aerofighter's assault [Ogy] // (prim-0)*t1+0 { 0x0ebb0ebb, cmb(ac_t1_mul_prim) }, // tire trace, beetle adventure racing. Added by Gonetz // (shade-0)*t1+0 { 0x0ebc0ebc, cmb(ac_t1_mul_shade) }, // smoke, Starshot. Added by Gonetz // (env-0)*t1+0 { 0x0ebd0ebd, cmb(ac_t1_mul_env) }, // lots of things, goldeneye // (1-0)*t1+0, (0-0)*0+shade { 0x0ebe09ff, cmb(ac_shade) }, // zelda 2 [Ogy]. Added by Gonetz // (1-0)*t1+0, (cmb-0)*prim+0 { 0x0ebe0ef8, cmb(ac_t1_mul_prim) }, // walls, perfect dark. Added by Gonetz // (1-0)*t1+0, (cmb-0)*shade+0 { 0x0ebe0f38, cmb(ac_t1_mul_shade) }, // sand, perfect dark. Added by Gonetz // (1-0)*t1+0, (cmb-0)*env+0 { 0x0ebe0f78, cmb(ac_t1_mul_env) }, // light, Ridge Racer. Added by Gonetz // (1-t0)*prim+0 { 0x0ece0ece, cmb(ac_one_sub_t0_mul_prim) }, // exaust, star wars ep1 racer // (1-t0)*prim+0, (cmb-0)*shade+0 { 0x0ece0f38, cmb(ac_one_sub_t0_mul_primshade) }, // iguana, Forsaken, [Raziel64]. Added by Gonetz // (t0-shade)*prim+0 ** INC ** { 0x0ee10ee1, cmb(ac_t0_sub_prim_mul_shade) }, // stands, NASCAR 2000 // (prim-shade)*prim+0 ** INC ** { 0x0ee30ee3, cmb(ac_prim) }, // arena, Pokemon Stadium 2. Added by Gonetz // (t0-env)*prim+0 ** INC ** { 0x0ee90ee9, cmb(ac_t0_mul_prim) }, // explosion, body harvest. Added by Gonetz // (t0-0)*prim+0, (t0-0)*env+cmb { 0x0ef90179, cmb(ac_prim_add_env_mul_t0) }, // frog's eyes, zelda // (t0-0)*prim+0, (1-1)*prim_lod+cmb { 0x0ef901b6, cmb(ac_t0_mul_prim) }, // Monster truck madness intro. Added by Gonetz // (t0-0)*prim+0, (cmb-0)*prim_lod+cmb ** INC ** { 0x0ef901b8, cmb(ac_t0_mul_prim) }, // Road, zelda //z (t0-0)*prim+0, (t1-0)*primlod+cmb { 0x0ef901ba, cmb(ac__t0_mul_prim__add__t1_mul_primlod) }, // Track, wipeout. Addded by Gonetz // (t0-0)*prim+0, (0-0)*0+prim { 0x0ef907ff, cmb(ac_t0_mul_prim) }, // magic stuff, buck bumble. Added by Gonetz // (t0-0)*prim+0, (cmb-0)*prim+0 { 0x0ef90ef8, cmb(ac_t0_mul_prim_mul_prim) }, // The mario face, mario //z (t0-0)*prim+0 { 0x0ef90ef9, cmb(ac_t0_mul_prim) }, // paper mario. Added by Gonetz // (t0-0)*prim+0, (cmb-0)*shade+0 { 0x0ef90f38, cmb(ac_t0_mul_prim_mul_shade) }, // Pik achu's mouth, smash bros // (t0-0)*prim+0, (cmb-0)*env+0 { 0x0ef90f78, cmb(ac_t0_mul_prim_mul_env) }, // bomb mask, zelda 2. Added by Gonetz // (t0-0)*prim+0, (1-0)*env+0 { 0x0ef90f7e, cmb(ac_t0_mul_prim) }, // Charmander's tail, pokemon stadium 2 // (t0-0)*prim+0, (cmb-0)*primlod+0 { 0x0ef90fb8, cmb(ac_t0_mul_prim_mul_primlod) }, // stalactites, Beetle adventure Racing. Added by Gonetz // (t1-0)*prim+0, (1-cmb)*shade+cmb { 0x0efa0106, cmb(ac_one_sub_shade_mul_t1_add_shade) }, // Sprites, Ogre Battle. Added by Gonetz // (t1-0)*prim+0, (0-0)*0+cmb { 0x0efa0efa, cmb(ac_t1_mul_prim) }, // Something about kotake & koume's combined attack, zelda // (t1-0)*prim+0, (cmb-0)*shade+0 { 0x0efa0f38, cmb(ac_t1_mul_prim_mul_shade) }, // intro background, bio freaks. Added by Gonetz // (prim-0)*prim+0 { 0x0efb0efb, cmb(ac_prim_mul_prim) }, // sky, xg2. Added by Gonetz // (shade-0)*prim+0, (0-0)*0+1 { 0x0efc0dff, cmb(ac_one) }, // Zelda, unimp log. Added by Gonetz // (shade-0)*prim+0 { 0x0efc0efc, cmb(ac_prim_mul_shade) }, // Baby mario's hat shadow, mario golf // (env-0)*prim+0 { 0x0efd0efd, cmb(ac_prim_mul_env) }, // Menu, doom // (1-0)*prim+0 { 0x0efe0efe, cmb(ac_prim) }, // Conker's shadow, CBFD. Added by Gonetz // (1-t0)*shade+0 { 0x0f0e0f0e, cmb(ac_one_sub_t0_mul_shade) }, // Rock smash, pokemon stadium 2 // (1-t0)*shade+0 { 0x0f0f0ee8, cmb(ac_one_sub_t0_mul_shade) }, //waterfall, Paper Mario // (t0-t1)*shade+0 { 0x0f110f11, cmb(ac__t0_sub_t1__mul_shade) }, // Boomerang circle, zelda // (t0-0)*shade+0, (1-cmb)*t0+cmb { 0x0f390046, cmb(ac_t0_mul_shade) }, // THPS3 // (t0-0)*shade+0, (1-0)*t0+cmb { 0x0f39007e, cmb(ac_t0_mul_shade) }, // ??? // (t0-0)*shade+0, (env-0)*t1+cmb { 0x0f3900bd, cmb(ac_t0_mul_shade) }, // Forest temple doorway, zelda // (t0-0)*shade+0, (t1-0)*primlod+cmb { 0x0f3901ba, cmb(ac_t0_mul_shade) }, // skis, Spacestation Silicon Valley. Added by Gonetz // (t0-0)*shade+0, (0-0)*0+t0 { 0x0f3903ff, cmb(ac_t0) }, // paper mario. Added by Gonetz // (t0-0)*shade+0, (cmb-t0)*prim+0 { 0x0f390ec8, cmb(ac_t0_mul_prim_mul_shade) }, // House windows, zelda intro //z (t0-0)*shade+0, (cmb-0)*prim+0 { 0x0f390ef8, cmb(ac_t0_mul_prim_mul_shade) }, // Characters, mace // (t0-0)*shade+0, (cmb-0)*shade+0 { 0x0f390f38, cmb(ac_t0_mul_shade) }, // Shadows, mario //z (t0-0)*shade+0 { 0x0f390f39, cmb(ac_t0_mul_shade) }, // Clear screen intro, banjo kazooie // (t0-0)*shade+0, (cmb-0)*env+0 { 0x0f390f78, cmb(ac_t0_mul_env_mul_shade) }, // ridge racer, unimp log. Added by Gonetz // (t0-0)*shade+0, (cmb-0)*primlod+0 **INC**? { 0x0f390fb8, cmb(ac_t0_mul_shade) }, // Reflecting combined attack at kotake & koume's, zelda // (t1-0)*shade+0, (cmb-0)*prim+0 { 0x0f3a0ef8, cmb(ac_t1_mul_prim_mul_shade) }, // aerofighter's assault [Ogy] // (t1-0)*shade+0 { 0x0f3a0f3a, cmb(ac_t1_mul_shade) }, //beetle adventure racing. Added by Gonetz //(t1-0)*shade+0, (cmb-0)*env+0 { 0x0f3a0f78, cmb(ac_t1_mul_env_mul_shade) }, // building shadow, Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz // (prim-0)*shade+0, (cmb-cmb)*lodf+cmb { 0x0f3b0000, cmb(ac_prim_mul_shade) }, //chip in Spacestation Silicon Valley intro. Added by Gonetz // (prim-0)*shade+0, (env-cmb)*t1+cmb { 0x0f3b0085, cmb(ac_env_sub_primshade_mul_t1_add_primshade) }, // N64 logo, tetrisphere. Added by Gonetz // (prim-0)*shade+0, (prim-0)*shade+0 { 0x0f3b0f3b, cmb(ac_prim_mul_shade) }, // rays, Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz // (shade-0)*shade+0, (cmb-0)*prim+0 { 0x0f3c0ef8, cmb(ac_prim_mul_shade) }, // light, dracula resurrection, castlevania 2. Added by Gonetz // (env-0)*shade+0 { 0x0f3d0f3d, cmb(ac_env_mul_shade) }, // zelda 2 [Ogy]. Added by Gonetz // (1-0)*shade+0 { 0x0f3e0f3e, cmb(ac_shade) }, // surf pokemon attack, Pokemon Stadium 2 [gokuss4]. Added by Gonetz // (1-t0)*env+0, (1-cmb)*shade+0 ** INC ** { 0x0f4e0f06, cmb(ac_t0_mul_shade) }, //beetle adventure racing. Added by Gonetz //(t0-0)*env+0, (1-t0)*prim+cmb { 0x0f7900ce, cmb(ac_t0_mul_env) }, //this one looks better // { 0x0f7900ce, cmb(ac_env_sub_prim_mul_t0_add_prim) }, //Zelda, logo ? Added by Gonetz //(t0-0)*env+0, (t1-0)*primlod+0 **INC** changed to mul_env for gannon's organ disappearing [Dave2001] { 0x0f7901ba, cmb(ac__t0_inter_t1_using_primlod__mul_env) }, // Skeleton guy's eyes, zelda // (t0-0)*env+0, (cmb-0)*prim+0 { 0x0f790ef8, cmb(ac_t0_mul_prim_mul_env) }, // Dust from rock spell, quest64 // (t0-0)*env+0, (cmb-0)*shade+0 { 0x0f790f38, cmb(ac_t0_mul_env_mul_shade) }, // eyes of poe, zelda // (t0-0)*env+0, (cmb-0)*env+0 { 0x0f790f78, cmb(ac_t0_mul_env) }, // Text, mario //z (t0-0)*env+0 { 0x0f790f79, cmb(ac_t0_mul_env) }, // Shadows, pokemon stadeom 2 // (t0-0)*env+0, (cmb-0)*primlod+0 { 0x0f790fb8, cmb(ac_t0_mul_env_mul_primlod) }, //gauge, PGA // (t1-0)*env+0, (cmb-0)*t1+0 ** INC ** { 0x0f7a0eb8, cmb(ac_t1_mul_env) }, //text and shadows, Rayman2. Added by Gonetz // (t1-0)*env+0, (cmb-0)*shade+0 { 0x0f7a0f38, cmb(ac_t1_mul_env_mul_shade) }, // shadows, tom and jerry. Added by Gonetz // (t1-0)*env+0 { 0x0f7a0f7a, cmb(ac_t1_mul_env) }, // Bomberman64-2 intro. Added by Gonetz // (prim-0)*env+0 { 0x0f7b0f7b, cmb(ac_prim_mul_env) }, // Text box, mario //z (shade-0)*env+0 { 0x0f7c0f7c, cmb(ac_env_mul_shade) }, // Ogre battle 64 // (env-0)*env+0 { 0x0f7d0f7d, cmb(ac_env) }, //Goldeneye, [Jeremy]. Added by Gonetz // (1-0)*env+0, (cmb-0)*shade+0 { 0x0f7e0f38, cmb(ac_env_mul_shade) }, // Status items, megaman // (1-0)*env+0 { 0x0f7e0f7e, cmb(ac_env) }, // gun fire, Beast_Wars_Transmetal [Raziel64] // (0-0)*env+0 { 0x0f7f0f7f, cmb(ac_zero) }, // Shadow Ball, Pokemon Stadium 2 [gokuss4]. Added by Gonetz // (t1-t0)*primlod+0, (t1-cmb)*prim+0 ** INC ** { 0x0f8a0ec2, cmb(ac_t0_mul_prim) }, // Walls of well through lens of truth, zelda // (prim-t0)*primlod+0 { 0x0f8b0f8b, cmb(ac_prim_sub_t0) }, // N64 logo, ridge racer. Added by Gonetz // (1-prim)*primlod+0 **INC** { 0x0f9e0f9e, cmb(ac_zero) }, // Vines that covers a door in the third room of woodfall temple, zelda 2 [Ogy]. Added by Gonetz // (t0-0)*primlod+0, (cmb-0)*prim+0 { 0x0fb90ef8, cmb(ac_t0_mul_primlod_mul_prim) }, // zelda 2. Added by Gonetz // (t0-0)*primlod+0 { 0x0fb90fb9, cmb(ac_t0_mul_primlod) }, // NFL Blitz logo. Added by Gonetz // (t1-0)*primlod+0 { 0x0fba0fba, cmb(ac_t1_mul_primlod) }, //causes issues // fallen stars at star summit, Paper Mario. Added by Gonetz // (shade-0)*primlod+0 { 0x0fbc0fbc, cmb(ac_primlod_mul_shade) }, // expansion pack, Jeremy McGrath Supercross 2000. Added by Gonetz // (1-0)*primlod+0 { 0x0fbe0fbe, cmb(ac_primlod) }, // intro, Aidyn Chronicles. Added by Gonetz // (0-0)*primlod+0, (prim-env)*t0+prim **INC** { 0x0fbf066b, cmb(ac_t0_mul_prim) }, // sky, Rayman2. Added by Gonetz // (0-shade)*0+0 { 0x0fe70fe7, cmb(ac_zero) }, // flame, PokemonStadium1 [Raziel64] // (t0-0)*0+0 { 0x0ff90ff9, cmb(ac_zero) }, // Screen clear, banjo kazooie // (0-0)*0+0 { 0x0fff0fff, cmb(ac_zero) }, // { #ACEND } }; // CountCombine - count the # of entries in the combine lists void CountCombine () { int size = sizeof(color_cmb_list) >> 3; int i=0, index=0, a, b; do { a = color_cmb_list[index].key >> 24; for (; i<=a; i++) cc_lookup[i] = index; while (index < size) { b = color_cmb_list[index].key >> 24; if (b != a) break; index ++; } } while (index < size); for (; i<257; i++) cc_lookup[i] = index; size = sizeof(alpha_cmb_list) >> 3; i=0, index=0; do { a = (alpha_cmb_list[index].key >> 20) & 0xFF; for (; i<=a; i++) ac_lookup[i] = index; while (index < size) { b = (alpha_cmb_list[index].key >> 20) & 0xFF; if (b != a) break; index ++; } } while (index < size); for (; i<257; i++) ac_lookup[i] = index; //color_cmb_list_count = sizeof(color_cmb_list) >> 3; // #bytes/4/2 //alpha_cmb_list_count = sizeof(alpha_cmb_list) >> 3; } //**************************************************************** // Main Combine //**************************************************************** void Combine () { FRDP (" | |- color combine: %08lx, #1: (%s-%s)*%s+%s, #2: (%s-%s)*%s+%s\n", ((rdp.cycle1 & 0xFFFF) << 16) | (rdp.cycle2 & 0xFFFF), Mode0[rdp.cycle1&0xF], Mode1[(rdp.cycle1>>4)&0xF], Mode2[(rdp.cycle1>>8)&0x1F], Mode3[(rdp.cycle1>>13)&7], Mode0[rdp.cycle2&0xF], Mode1[(rdp.cycle2>>4)&0xF], Mode2[(rdp.cycle2>>8)&0x1F], Mode3[(rdp.cycle2>>13)&7]); FRDP (" | |- alpha combine: %08lx, #1: (%s-%s)*%s+%s, #2: (%s-%s)*%s+%s\n", (rdp.cycle1 & 0x0FFF0000) | ((rdp.cycle2 & 0x0FFF0000) >> 16), Alpha0[(rdp.cycle1>>16)&7], Alpha1[(rdp.cycle1>>19)&7], Alpha2[(rdp.cycle1>>22)&7], Alpha3[(rdp.cycle1>>25)&7], Alpha0[(rdp.cycle2>>16)&7], Alpha1[(rdp.cycle2>>19)&7], Alpha2[(rdp.cycle2>>22)&7], Alpha3[(rdp.cycle2>>25)&7]); if (settings.lodmode == 0 || rdp.cur_tile == rdp.mipmap_level) lod_frac = rdp.prim_lodfrac; else lod_frac = 10; rdp.noise = noise_none; DWORD found = TRUE; rdp.col[0] = rdp.col[1] = rdp.col[2] = rdp.col[3] = rdp.coladd[0] = rdp.coladd[1] = rdp.coladd[2] = rdp.coladd[3] = 1.0f; rdp.cmb_flags = rdp.cmb_flags_2 = 0; rdp.uncombined = 0; cmb.tex = 0; cmb.tmu0_func = cmb.tmu1_func = cmb.tmu0_a_func = cmb.tmu1_a_func = GR_COMBINE_FUNCTION_ZERO; cmb.tmu0_fac = cmb.tmu1_fac = cmb.tmu0_a_fac = cmb.tmu1_a_fac = GR_COMBINE_FACTOR_NONE; cmb.tmu0_invert = cmb.tmu0_a_invert = cmb.tmu1_invert = cmb.tmu1_a_invert = FXFALSE; cmb.dc0_detailmax = cmb.dc1_detailmax = 0; cmb.mod_0 = cmb.mod_1 = 0; // remove all modifications cmb.modcolor_0 = cmb.modcolor1_0 = cmb.modcolor2_0 = cmb.modcolor_1 = cmb.modcolor1_1 = cmb.modcolor2_1 = cmb.modfactor_0 = cmb.modfactor_1 = 0; cmb.ccolor = cmb.tex_ccolor = 0; if (cmb.cmb_ext_use || cmb.tex_cmb_ext_use) { //have to draw something to allow use of standard combine functions if (fullscreen) { VERTEX v; memset(&v,0,sizeof(v)); grDrawPoint(&v); } cmb.cmb_ext_use = 0; cmb.tex_cmb_ext_use = 0; } DWORD cmb_mode_c = (rdp.cycle1 << 16) | (rdp.cycle2 & 0xFFFF); DWORD cmb_mode_a = (rdp.cycle1 & 0x0FFF0000) | ((rdp.cycle2 >> 16) & 0x00000FFF); cmb.abf1 = GR_BLEND_SRC_ALPHA; cmb.abf2 = GR_BLEND_ONE_MINUS_SRC_ALPHA; #ifdef FASTSEARCH // Fast, ordered search int current=0x7FFFFFFF, last; DWORD actual_combine, current_combine = 0x7fffffff, color_combine, alpha_combine; int left, right; actual_combine = cmb_mode_c; color_combine = actual_combine; if ((rdp.cycle2 & 0xFFFF) == 0x1FFF) actual_combine = (rdp.cycle1 << 16) | (rdp.cycle1 & 0xFFFF); left = cc_lookup[actual_combine>>24]; right = cc_lookup[(actual_combine>>24)+1]; while (1) { last = current; current = left + ((right-left) >> 1); if (current == last) break; // can't be found! current_combine = color_cmb_list[current].key; if (current_combine < actual_combine) left = current; else if (current_combine > actual_combine) right = current; else break; // found it! } // Check if we didn't find it if (actual_combine != current_combine) { rdp.uncombined |= 1; #ifdef UNIMP_LOG if (settings.log_unk) { sprintf (out_buf, "COLOR combine not found: %08x, #1: (%s-%s)*%s+%s, #2: (%s-%s)*%s+%s\n", actual_combine, Mode0[rdp.cycle1&0xF], Mode1[(rdp.cycle1>>4)&0xF], Mode2[(rdp.cycle1>>8)&0x1F], Mode3[(rdp.cycle1>>13)&7], Mode0[rdp.cycle2&0xF], Mode1[(rdp.cycle2>>4)&0xF], Mode2[(rdp.cycle2>>8)&0x1F], Mode3[(rdp.cycle2>>13)&7]); UNIMPMODE(); } #endif found = FALSE; //tex |= 3; // use t0 as default cc_t0 (); } else (color_cmb_list[current].func)(); RDP (" | |- Color done\n"); // Now again for alpha current = 0x7FFFFFFF; actual_combine = cmb_mode_a; alpha_combine = actual_combine; if ((rdp.cycle2 & 0x0FFF0000) == 0x01FF0000) actual_combine = (rdp.cycle1 & 0x0FFF0000) | ((rdp.cycle1 >> 16) & 0x00000FFF); if ((rdp.cycle1 & 0x0FFF0000) == 0x0FFF0000) actual_combine = (rdp.cycle2 & 0x0FFF0000) | ((rdp.cycle2 >> 16) & 0x00000FFF); left = ac_lookup[(actual_combine>>20)&0xFF]; right = ac_lookup[((actual_combine>>20)&0xFF)+1]; while (1) { last = current; current = left + ((right-left) >> 1); if (current == last) break; // can't be found! current_combine = alpha_cmb_list[current].key; if (current_combine < actual_combine) left = current; else if (current_combine > actual_combine) right = current; else break; // found it! } // Check if we didn't find it if (actual_combine != current_combine || !found) { if (actual_combine != current_combine) { rdp.uncombined |= 2; #ifdef UNIMP_LOG if (settings.log_unk) { sprintf (out_buf, "ALPHA combine not found: %08x, #1: (%s-%s)*%s+%s, #2: (%s-%s)*%s+%s\n", actual_combine, Alpha0[(rdp.cycle1>>16)&7], Alpha1[(rdp.cycle1>>19)&7], Alpha2[(rdp.cycle1>>22)&7], Alpha3[(rdp.cycle1>>25)&7], Alpha0[(rdp.cycle2>>16)&7], Alpha1[(rdp.cycle2>>19)&7], Alpha2[(rdp.cycle2>>22)&7], Alpha3[(rdp.cycle2>>25)&7]); UNIMPMODE(); } #endif } if (settings.unk_as_red) { BrightRed (); } else { // use full alpha as default ac_t0 (); } //tex |= 3; } else (alpha_cmb_list[current].func)(); if (color_combine == 0x69351fff) //text, PD, need to change texture alpha { A_USE_T1(); } else if ((color_combine == 0x3fff1fff) && (alpha_combine == 0x03ff03ff) && (rdp.last_tile > rdp.cur_tile))//Dr. Mario { cc_t0(); ac_t1(); } else if (color_combine == 0x613522f0 && settings.PM) //Paper Mario fortune teller spheres { ac_t0(); } RDP (" | |- Alpha done\n"); #endif // FASTSEARCH CombineBlender (); //* // Update textures? // if (tex == 2 && rdp.texrecting && (cmb.tmu1_func != GR_COMBINE_FUNCTION_ZERO) && (rdp.last_tile_size == 0)) if (cmb.tex == 2 && rdp.texrecting && (rdp.cur_tile == rdp.last_tile_size)) { cmb.tex = 0; USE_T0(); A_USE_T0(); } //*/ rdp.tex = cmb.tex; if (cmb.tex && rdp.hires_tex && settings.fb_read_alpha) { if (settings.PM && rdp.hires_tex->width == rdp.ci_width) ; else { grChromakeyValue(0); grChromakeyMode(GR_CHROMAKEY_ENABLE); } } else if (settings.invaders && (rdp.geom_mode == 0x0205)) { grChromakeyValue(0); grChromakeyMode(GR_CHROMAKEY_ENABLE); } else grChromakeyMode(GR_CHROMAKEY_DISABLE); RDP (" | + Combine end\n"); } void CombineBlender () { // Check force-blending if ((rdp.othermode_l & 0x4000) && (rdp.cycle_mode < 2)) { switch (rdp.othermode_l >> 16) { // Mace objects case 0x0382: case 0x0091: // 1080 sky case 0x0c08: // Mario kart player select // clr_in * 0 + clr_in * 1 // - or just clr_in, no matter what alpha case 0x0f0a: //DK64 blue prints case 0x0302: A_BLEND (GR_BLEND_ONE, GR_BLEND_ZERO); break; // LOT in Zelda: MM case 0xaf50: case 0x0f5a: //clr_in * 0 + clr_mem * 1 A_BLEND (GR_BLEND_ZERO, GR_BLEND_ONE); break; case 0x5f50: //clr_mem * 0 + clr_mem * (1-a) A_BLEND (GR_BLEND_ZERO, GR_BLEND_ONE_MINUS_SRC_ALPHA); break; case 0xf550: //clr_fog * a_fog + clr_mem * (1-a) A_BLEND (GR_BLEND_SRC_ALPHA, GR_BLEND_ONE_MINUS_SRC_ALPHA); rdp.col[0] *= (float)((rdp.fog_color & 0xFF000000) >> 24) / 255.0f; rdp.col[1] *= (float)((rdp.fog_color & 0x00FF0000) >> 16) / 255.0f; rdp.col[2] *= (float)((rdp.fog_color & 0x0000FF00) >> 8) / 255.0f; rdp.col[3] *= (float)(rdp.fog_color & 0xFF) / 255.0f; rdp.cmb_flags = CMB_SET | CMB_A_SET; break; // Super Smash Bros, faked fog for flashing characters case 0xc411: { MOD_0 (TMOD_TEX_INTER_COLOR_USING_FACTOR); MOD_0_COL (rdp.fog_color & 0x00FFFFFF); MOD_0_FAC (rdp.fog_color >> 24); INTERSHADE_2 (rdp.fog_color & 0x00FFFFFF, rdp.fog_color >> 24); float percent = (rdp.fog_color >> 24) / 255.0f; cmb.ccolor = (cmb.ccolor & 0xFF000000) | ((DWORD)(((cmb.ccolor >> 16) & 0xFF) * (1.0f-percent) + ((rdp.fog_color>>16) & 0xFF) * percent) << 16) | ((DWORD)(((cmb.ccolor >> 8) & 0xFF) * (1.0f-percent) + ((rdp.fog_color>>8) & 0xFF) * percent) << 8) | (DWORD)((cmb.ccolor & 0xFF) * (1.0f-percent) + (rdp.fog_color & 0xFF) * percent); rdp.col[0] = rdp.col[0] * (1.0f-percent) + ((rdp.fog_color>>16) & 0xFF) / 255.0f * percent; rdp.col[1] = rdp.col[1] * (1.0f-percent) + ((rdp.fog_color>>8) & 0xFF) / 255.0f * percent; rdp.col[2] = rdp.col[2] * (1.0f-percent) + (rdp.fog_color & 0xFF) / 255.0f * percent; } break; default: A_BLEND (GR_BLEND_SRC_ALPHA, GR_BLEND_ONE_MINUS_SRC_ALPHA); } } else A_BLEND (GR_BLEND_ONE, GR_BLEND_ZERO); // ALPHA_CVG_SEL means full alpha // The reason it wasn't working before was because I wasn't handling rdp:setothermode // if (rdp.othermode_l & 0x2000) if ((rdp.othermode_l & 0x2000) && ((rdp.othermode_l & 0x7000) != 0x7000)) { if (settings.PM && ((rdp.othermode_l >> 16) == 0x5055)) { A_BLEND (GR_BLEND_ZERO, GR_BLEND_ONE); } else { A_BLEND (GR_BLEND_ONE, GR_BLEND_ZERO); } } //hack //* if (settings.ISS64) { if ((rdp.othermode_l >> 16) == 0xc302) { A_BLEND (GR_BLEND_ONE, GR_BLEND_ZERO); } else if (rdp.othermode_l == 0xff5a6379) { A_BLEND (GR_BLEND_ZERO, GR_BLEND_SRC_ALPHA); } else if (rdp.othermode_l == 0x00504dd9) { A_BLEND (GR_BLEND_ZERO, GR_BLEND_ONE); } } else if (settings.TGR) { if (rdp.othermode_l == 0x0f0a0235) { A_BLEND (GR_BLEND_SRC_ALPHA, GR_BLEND_ONE_MINUS_SRC_ALPHA); } } //*/ } void InitCombine () { LOG ("InitCombine() "); memset(&cmb, 0, sizeof(cmb)); const char *extensions = grGetString (GR_EXTENSION); const char *extstr = strstr(extensions, "COMBINE"); if (extstr) { if (!strncmp(extstr, "COMBINE", 7)) { LOG ("extensions "); cmb.grColorCombineExt = (GRCOLORCOMBINEEXT) grGetProcAddress("grColorCombineExt"); cmb.grAlphaCombineExt = (GRCOLORCOMBINEEXT) grGetProcAddress("grAlphaCombineExt"); cmb.grTexColorCombineExt = (GRTEXCOLORCOMBINEEXT) grGetProcAddress("grTexColorCombineExt"); cmb.grTexAlphaCombineExt = (GRTEXCOLORCOMBINEEXT) grGetProcAddress("grTexAlphaCombineExt"); cmb.grConstantColorValueExt = (GRCONSTANTCOLORVALUEEXT) grGetProcAddress("grConstantColorValueExt"); if (cmb.grColorCombineExt && cmb.grAlphaCombineExt && cmb.grTexColorCombineExt && cmb.grTexAlphaCombineExt) { cmb.combine_ext = TRUE; LOG ("initialized."); } else { cmb.combine_ext = FALSE; } } } cmb.dc0_lodbias = cmb.dc1_lodbias = 31; cmb.dc0_detailscale = cmb.dc1_detailscale = 7; cmb.lodbias0 = cmb.lodbias1 = 1.0f; LOG ("\n"); } void ColorCombinerToExtension () { DWORD ext_local, ext_local_a, ext_other, ext_other_a; switch (cmb.c_loc) { case GR_COMBINE_LOCAL_ITERATED: ext_local = GR_CMBX_ITRGB; ext_local_a = GR_CMBX_ITALPHA; break; case GR_COMBINE_LOCAL_CONSTANT: ext_local = GR_CMBX_CONSTANT_COLOR; ext_local_a = GR_CMBX_CONSTANT_ALPHA; break; default: ext_local = 0; ext_local_a = 0; break; }; switch (cmb.c_oth) { case GR_COMBINE_OTHER_ITERATED: ext_other = GR_CMBX_ITRGB; ext_other_a = GR_CMBX_ITALPHA; break; case GR_COMBINE_OTHER_TEXTURE: ext_other = GR_CMBX_TEXTURE_RGB; ext_other_a = GR_CMBX_TEXTURE_ALPHA; break; case GR_COMBINE_OTHER_CONSTANT: ext_other = GR_CMBX_CONSTANT_COLOR; ext_other_a = GR_CMBX_CONSTANT_ALPHA; break; default: ext_other = 0; ext_other_a = 0; break; }; switch (cmb.c_fac) { case GR_COMBINE_FACTOR_ZERO: cmb.c_ext_c = GR_CMBX_ZERO; cmb.c_ext_c_invert = 0; break; case GR_COMBINE_FACTOR_ONE: cmb.c_ext_c = GR_CMBX_ZERO; cmb.c_ext_c_invert = 1; break; case GR_COMBINE_FACTOR_LOCAL: cmb.c_ext_c = ext_local; cmb.c_ext_c_invert = 0; break; case GR_COMBINE_FACTOR_LOCAL_ALPHA: cmb.c_ext_c = ext_local_a; cmb.c_ext_c_invert = 0; break; case GR_COMBINE_FACTOR_OTHER_ALPHA: cmb.c_ext_c = ext_other_a; cmb.c_ext_c_invert = 0; break; case GR_COMBINE_FACTOR_TEXTURE_RGB: cmb.c_ext_c = GR_CMBX_TEXTURE_RGB; cmb.c_ext_c_invert = 0; break; case GR_COMBINE_FACTOR_TEXTURE_ALPHA: cmb.c_ext_c = GR_CMBX_TEXTURE_ALPHA; cmb.c_ext_c_invert = 0; break; case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL: cmb.c_ext_c = ext_local; cmb.c_ext_c_invert = 1; break; case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA: cmb.c_ext_c = ext_local_a; cmb.c_ext_c_invert = 1; break; case GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA: cmb.c_ext_c = ext_other_a; cmb.c_ext_c_invert = 1; break; case GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA: cmb.c_ext_c = GR_CMBX_TEXTURE_ALPHA; cmb.c_ext_c_invert = 1; break; } switch (cmb.c_fnc) { case GR_COMBINE_FUNCTION_ZERO: cmb.c_ext_a = GR_CMBX_ZERO; cmb.c_ext_a_mode = GR_FUNC_MODE_X; cmb.c_ext_b = GR_CMBX_ZERO; cmb.c_ext_b_mode = GR_FUNC_MODE_X; cmb.c_ext_c = GR_CMBX_ZERO; cmb.c_ext_c_invert = 0; cmb.c_ext_d = GR_CMBX_ZERO; cmb.c_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_LOCAL: cmb.c_ext_a = ext_local; cmb.c_ext_a_mode = GR_FUNC_MODE_X; cmb.c_ext_b = GR_CMBX_ZERO; cmb.c_ext_b_mode = GR_FUNC_MODE_X; cmb.c_ext_c = GR_CMBX_ZERO; cmb.c_ext_c_invert = 1; cmb.c_ext_d = GR_CMBX_ZERO; cmb.c_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_LOCAL_ALPHA: cmb.c_ext_a = ext_local_a; cmb.c_ext_a_mode = GR_FUNC_MODE_X; cmb.c_ext_b = GR_CMBX_ZERO; cmb.c_ext_b_mode = GR_FUNC_MODE_X; cmb.c_ext_c = GR_CMBX_ZERO; cmb.c_ext_c_invert = 1; cmb.c_ext_d = GR_CMBX_ZERO; cmb.c_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_OTHER: cmb.c_ext_a = ext_other; cmb.c_ext_a_mode = GR_FUNC_MODE_X; cmb.c_ext_b = GR_CMBX_ZERO; cmb.c_ext_b_mode = GR_FUNC_MODE_ZERO; cmb.c_ext_d = GR_CMBX_ZERO; cmb.c_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL: cmb.c_ext_a = ext_other; cmb.c_ext_a_mode = GR_FUNC_MODE_X; cmb.c_ext_b = ext_local; cmb.c_ext_b_mode = GR_FUNC_MODE_ZERO; cmb.c_ext_d = GR_CMBX_B; cmb.c_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA: cmb.c_ext_a = ext_other; cmb.c_ext_a_mode = GR_FUNC_MODE_X; cmb.c_ext_b = ext_local_a; cmb.c_ext_b_mode = GR_FUNC_MODE_ZERO; cmb.c_ext_d = GR_CMBX_B; cmb.c_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL: cmb.c_ext_a = ext_other; cmb.c_ext_a_mode = GR_FUNC_MODE_X; cmb.c_ext_b = ext_local; cmb.c_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X; cmb.c_ext_d = GR_CMBX_ZERO; cmb.c_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL: cmb.c_ext_a = ext_other; cmb.c_ext_a_mode = GR_FUNC_MODE_X; cmb.c_ext_b = ext_local; cmb.c_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X; cmb.c_ext_d = GR_CMBX_B; cmb.c_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA: cmb.c_ext_a = ext_other; cmb.c_ext_a_mode = GR_FUNC_MODE_X; cmb.c_ext_b = ext_local; cmb.c_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X; cmb.c_ext_d = GR_CMBX_ALOCAL; cmb.c_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL: cmb.c_ext_a = GR_CMBX_ZERO; cmb.c_ext_a_mode = GR_FUNC_MODE_ZERO; cmb.c_ext_b = ext_local; cmb.c_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X; cmb.c_ext_d = GR_CMBX_B; cmb.c_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA: cmb.c_ext_a = GR_CMBX_ZERO; cmb.c_ext_a_mode = GR_FUNC_MODE_ZERO; cmb.c_ext_b = ext_local; cmb.c_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X; cmb.c_ext_d = GR_CMBX_ALOCAL; cmb.c_ext_d_invert = 0; break; } } void AlphaCombinerToExtension () { DWORD ext_local, ext_other; switch (cmb.a_loc) { case GR_COMBINE_LOCAL_ITERATED: ext_local = GR_CMBX_ITALPHA; break; case GR_COMBINE_LOCAL_CONSTANT: ext_local = GR_CMBX_CONSTANT_ALPHA; break; default: ext_local = GR_CMBX_ZERO; }; switch (cmb.a_oth) { case GR_COMBINE_OTHER_ITERATED: ext_other = GR_CMBX_ITALPHA; break; case GR_COMBINE_OTHER_TEXTURE: ext_other = GR_CMBX_TEXTURE_ALPHA; break; case GR_COMBINE_OTHER_CONSTANT: ext_other = GR_CMBX_CONSTANT_ALPHA; break; default: ext_other = GR_CMBX_ZERO; }; switch (cmb.a_fac) { case GR_COMBINE_FACTOR_ZERO: cmb.a_ext_c = GR_CMBX_ZERO; cmb.a_ext_c_invert = 0; break; case GR_COMBINE_FACTOR_ONE: cmb.a_ext_c = GR_CMBX_ZERO; cmb.a_ext_c_invert = 1; break; case GR_COMBINE_FACTOR_LOCAL: case GR_COMBINE_FACTOR_LOCAL_ALPHA: cmb.a_ext_c = ext_local; cmb.a_ext_c_invert = 0; break; case GR_COMBINE_FACTOR_OTHER_ALPHA: cmb.a_ext_c = ext_other; cmb.a_ext_c_invert = 0; break; case GR_COMBINE_FACTOR_TEXTURE_ALPHA: cmb.a_ext_c = GR_CMBX_TEXTURE_ALPHA; cmb.a_ext_c_invert = 0; break; case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL: case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA: cmb.a_ext_c = ext_local; cmb.a_ext_c_invert = 1; break; case GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA: cmb.a_ext_c = ext_other; cmb.a_ext_c_invert = 1; break; case GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA: cmb.a_ext_c = GR_CMBX_TEXTURE_ALPHA; cmb.a_ext_c_invert = 1; break; default: cmb.a_ext_c = GR_CMBX_ZERO; cmb.a_ext_c_invert = 0; } switch (cmb.a_fnc) { case GR_COMBINE_FUNCTION_ZERO: cmb.a_ext_a = GR_CMBX_ZERO; cmb.a_ext_a_mode = GR_FUNC_MODE_X; cmb.a_ext_b = GR_CMBX_ZERO; cmb.a_ext_b_mode = GR_FUNC_MODE_X; cmb.a_ext_c = GR_CMBX_ZERO; cmb.a_ext_c_invert = 0; cmb.a_ext_d = GR_CMBX_ZERO; cmb.a_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_LOCAL: case GR_COMBINE_FUNCTION_LOCAL_ALPHA: cmb.a_ext_a = GR_CMBX_ZERO; cmb.a_ext_a_mode = GR_FUNC_MODE_ZERO; cmb.a_ext_b = ext_local; cmb.a_ext_b_mode = GR_FUNC_MODE_X; cmb.a_ext_c = GR_CMBX_ZERO; cmb.a_ext_c_invert = 1; cmb.a_ext_d = GR_CMBX_ZERO; cmb.a_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_OTHER: cmb.a_ext_a = ext_other; cmb.a_ext_a_mode = GR_FUNC_MODE_X; cmb.a_ext_b = GR_CMBX_ZERO; cmb.a_ext_b_mode = GR_FUNC_MODE_ZERO; cmb.a_ext_d = GR_CMBX_ZERO; cmb.a_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL: case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA: cmb.a_ext_a = ext_other; cmb.a_ext_a_mode = GR_FUNC_MODE_X; cmb.a_ext_b = ext_local; cmb.a_ext_b_mode = GR_FUNC_MODE_ZERO; cmb.a_ext_d = GR_CMBX_B; cmb.a_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL: cmb.a_ext_a = ext_other; cmb.a_ext_a_mode = GR_FUNC_MODE_X; cmb.a_ext_b = ext_local; cmb.a_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X; cmb.a_ext_d = GR_CMBX_ZERO; cmb.a_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL: case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA: cmb.a_ext_a = ext_other; cmb.a_ext_a_mode = GR_FUNC_MODE_X; cmb.a_ext_b = ext_local; cmb.a_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X; cmb.a_ext_d = GR_CMBX_B; cmb.a_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL: case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA: cmb.a_ext_a = GR_CMBX_ZERO; cmb.a_ext_a_mode = GR_FUNC_MODE_ZERO; cmb.a_ext_b = ext_local; cmb.a_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X; cmb.a_ext_d = GR_CMBX_B; cmb.a_ext_d_invert = 0; break; } } void TexColorCombinerToExtension (GrChipID_t tmu) { DWORD tc_ext_a, tc_ext_a_mode, tc_ext_b, tc_ext_b_mode, tc_ext_c, tc_ext_d; BOOL tc_ext_c_invert, tc_ext_d_invert; DWORD tmu_func, tmu_fac; if (tmu == GR_TMU0) { tmu_func = cmb.tmu0_func; tmu_fac = cmb.tmu0_fac; } else { tmu_func = cmb.tmu1_func; tmu_fac = cmb.tmu1_fac; } switch (tmu_fac) { case GR_COMBINE_FACTOR_ZERO: tc_ext_c = GR_CMBX_ZERO; tc_ext_c_invert = 0; break; case GR_COMBINE_FACTOR_LOCAL: tc_ext_c = GR_CMBX_LOCAL_TEXTURE_RGB; tc_ext_c_invert = 0; break; case GR_COMBINE_FACTOR_LOCAL_ALPHA: tc_ext_c = GR_CMBX_LOCAL_TEXTURE_ALPHA; tc_ext_c_invert = 0; break; case GR_COMBINE_FACTOR_OTHER_ALPHA: tc_ext_c = GR_CMBX_OTHER_TEXTURE_ALPHA; tc_ext_c_invert = 0; break; case GR_COMBINE_FACTOR_DETAIL_FACTOR: tc_ext_c = GR_CMBX_DETAIL_FACTOR; tc_ext_c_invert = 0; break; case GR_COMBINE_FACTOR_ONE: tc_ext_c = GR_CMBX_ZERO; tc_ext_c_invert = 1; break; case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL: tc_ext_c = GR_CMBX_LOCAL_TEXTURE_RGB; tc_ext_c_invert = 1; break; case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA: tc_ext_c = GR_CMBX_LOCAL_TEXTURE_ALPHA; tc_ext_c_invert = 1; break; case GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA: tc_ext_c = GR_CMBX_OTHER_TEXTURE_ALPHA; tc_ext_c_invert = 1; break; case GR_COMBINE_FACTOR_ONE_MINUS_DETAIL_FACTOR: tc_ext_c = GR_CMBX_DETAIL_FACTOR; tc_ext_c_invert = 1; break; default: tc_ext_c = 0; tc_ext_c_invert = 0; break; } switch (tmu_func) { case GR_COMBINE_FUNCTION_ZERO: tc_ext_a = GR_CMBX_LOCAL_TEXTURE_RGB; tc_ext_a_mode = GR_FUNC_MODE_ZERO; tc_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB; tc_ext_b_mode = GR_FUNC_MODE_ZERO; tc_ext_c = GR_CMBX_ZERO; tc_ext_c_invert = 0; tc_ext_d = GR_CMBX_ZERO; tc_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_LOCAL: tc_ext_a = GR_CMBX_LOCAL_TEXTURE_RGB; tc_ext_a_mode = GR_FUNC_MODE_X; tc_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB; tc_ext_b_mode = GR_FUNC_MODE_ZERO; tc_ext_c = GR_CMBX_ZERO; tc_ext_c_invert = 1; tc_ext_d = GR_CMBX_ZERO; tc_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_LOCAL_ALPHA: tc_ext_a = GR_CMBX_LOCAL_TEXTURE_ALPHA; tc_ext_a_mode = GR_FUNC_MODE_X; tc_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB; tc_ext_b_mode = GR_FUNC_MODE_ZERO; tc_ext_c = GR_CMBX_ZERO; tc_ext_c_invert = 1; tc_ext_d = GR_CMBX_ZERO; tc_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_OTHER: tc_ext_a = GR_CMBX_OTHER_TEXTURE_RGB; tc_ext_a_mode = GR_FUNC_MODE_X; tc_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB; tc_ext_b_mode = GR_FUNC_MODE_ZERO; tc_ext_d = GR_CMBX_ZERO; tc_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL: tc_ext_a = GR_CMBX_OTHER_TEXTURE_RGB; tc_ext_a_mode = GR_FUNC_MODE_X; tc_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB; tc_ext_b_mode = GR_FUNC_MODE_ZERO; tc_ext_d = GR_CMBX_B; tc_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA: tc_ext_a = GR_CMBX_OTHER_TEXTURE_RGB; tc_ext_a_mode = GR_FUNC_MODE_X; tc_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA; tc_ext_b_mode = GR_FUNC_MODE_ZERO; tc_ext_d = GR_CMBX_B; tc_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL: tc_ext_a = GR_CMBX_OTHER_TEXTURE_RGB; tc_ext_a_mode = GR_FUNC_MODE_X; tc_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB; tc_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X; tc_ext_d = GR_CMBX_ZERO; tc_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL: tc_ext_a = GR_CMBX_OTHER_TEXTURE_RGB; tc_ext_a_mode = GR_FUNC_MODE_X; tc_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB; tc_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X; tc_ext_d = GR_CMBX_B; tc_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA: tc_ext_a = GR_CMBX_OTHER_TEXTURE_RGB; tc_ext_a_mode = GR_FUNC_MODE_X; tc_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB; tc_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X; tc_ext_d = GR_CMBX_LOCAL_TEXTURE_ALPHA; tc_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL: tc_ext_a = GR_CMBX_LOCAL_TEXTURE_RGB; tc_ext_a_mode = GR_FUNC_MODE_ZERO; tc_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB; tc_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X; tc_ext_d = GR_CMBX_B; tc_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA: tc_ext_a = GR_CMBX_LOCAL_TEXTURE_RGB; tc_ext_a_mode = GR_FUNC_MODE_ZERO; tc_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB; tc_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X; tc_ext_d = GR_CMBX_LOCAL_TEXTURE_ALPHA; tc_ext_d_invert = 0; break; default: tc_ext_a = 0; tc_ext_a_mode = 0; tc_ext_b = 0; tc_ext_b_mode = 0; tc_ext_d = 0; tc_ext_d_invert = 0; break; } if (tmu == GR_TMU0) { cmb.t0c_ext_a = tc_ext_a; cmb.t0c_ext_a_mode = tc_ext_a_mode; cmb.t0c_ext_b = tc_ext_b; cmb.t0c_ext_b_mode = tc_ext_b_mode; cmb.t0c_ext_c = tc_ext_c; cmb.t0c_ext_c_invert = tc_ext_c_invert; cmb.t0c_ext_d = tc_ext_d; cmb.t0c_ext_d_invert = tc_ext_d_invert; } else { cmb.t1c_ext_a = tc_ext_a; cmb.t1c_ext_a_mode = tc_ext_a_mode; cmb.t1c_ext_b = tc_ext_b; cmb.t1c_ext_b_mode = tc_ext_b_mode; cmb.t1c_ext_c = tc_ext_c; cmb.t1c_ext_c_invert = tc_ext_c_invert; cmb.t1c_ext_d = tc_ext_d; cmb.t1c_ext_d_invert = tc_ext_d_invert; } } void TexAlphaCombinerToExtension (GrChipID_t tmu) { DWORD ta_ext_a, ta_ext_a_mode, ta_ext_b, ta_ext_b_mode, ta_ext_c, ta_ext_d; BOOL ta_ext_c_invert, ta_ext_d_invert; DWORD tmu_a_func, tmu_a_fac; if (tmu == GR_TMU0) { tmu_a_func = cmb.tmu0_a_func; tmu_a_fac = cmb.tmu0_a_fac; } else { tmu_a_func = cmb.tmu1_a_func; tmu_a_fac = cmb.tmu1_a_fac; } switch (tmu_a_fac) { case GR_COMBINE_FACTOR_ZERO: ta_ext_c = GR_CMBX_ZERO; ta_ext_c_invert = 0; break; case GR_COMBINE_FACTOR_LOCAL: case GR_COMBINE_FACTOR_LOCAL_ALPHA: ta_ext_c = GR_CMBX_LOCAL_TEXTURE_ALPHA; ta_ext_c_invert = 0; break; case GR_COMBINE_FACTOR_OTHER_ALPHA: ta_ext_c = GR_CMBX_OTHER_TEXTURE_ALPHA; ta_ext_c_invert = 0; break; case GR_COMBINE_FACTOR_DETAIL_FACTOR: ta_ext_c = GR_CMBX_DETAIL_FACTOR; ta_ext_c_invert = 0; break; case GR_COMBINE_FACTOR_ONE: ta_ext_c = GR_CMBX_ZERO; ta_ext_c_invert = 1; break; case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL: case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA: ta_ext_c = GR_CMBX_LOCAL_TEXTURE_ALPHA; ta_ext_c_invert = 1; break; case GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA: ta_ext_c = GR_CMBX_OTHER_TEXTURE_ALPHA; ta_ext_c_invert = 1; break; case GR_COMBINE_FACTOR_ONE_MINUS_DETAIL_FACTOR: ta_ext_c = GR_CMBX_DETAIL_FACTOR; ta_ext_c_invert = 1; break; default: ta_ext_c = 0; ta_ext_c_invert = 0; break; } switch (tmu_a_func) { case GR_COMBINE_FUNCTION_ZERO: ta_ext_a = GR_CMBX_LOCAL_TEXTURE_ALPHA; ta_ext_a_mode = GR_FUNC_MODE_ZERO; ta_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA; ta_ext_b_mode = GR_FUNC_MODE_ZERO; ta_ext_c = GR_CMBX_ZERO; ta_ext_c_invert = 0; ta_ext_d = GR_CMBX_ZERO; ta_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_LOCAL: case GR_COMBINE_FUNCTION_LOCAL_ALPHA: ta_ext_a = GR_CMBX_LOCAL_TEXTURE_ALPHA; ta_ext_a_mode = GR_FUNC_MODE_X; ta_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA; ta_ext_b_mode = GR_FUNC_MODE_ZERO; ta_ext_c = GR_CMBX_ZERO; ta_ext_c_invert = 1; ta_ext_d = GR_CMBX_ZERO; ta_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_OTHER: ta_ext_a = GR_CMBX_OTHER_TEXTURE_ALPHA; ta_ext_a_mode = GR_FUNC_MODE_X; ta_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA; ta_ext_b_mode = GR_FUNC_MODE_ZERO; ta_ext_d = GR_CMBX_ZERO; ta_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL: case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA: ta_ext_a = GR_CMBX_OTHER_TEXTURE_ALPHA; ta_ext_a_mode = GR_FUNC_MODE_X; ta_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA; ta_ext_b_mode = GR_FUNC_MODE_ZERO; ta_ext_d = GR_CMBX_B; ta_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL: ta_ext_a = GR_CMBX_OTHER_TEXTURE_ALPHA; ta_ext_a_mode = GR_FUNC_MODE_X; ta_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA; ta_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X; ta_ext_d = GR_CMBX_ZERO; ta_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL: case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA: ta_ext_a = GR_CMBX_OTHER_TEXTURE_ALPHA; ta_ext_a_mode = GR_FUNC_MODE_X; ta_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA; ta_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X; ta_ext_d = GR_CMBX_B; ta_ext_d_invert = 0; break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL: case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA: ta_ext_a = GR_CMBX_LOCAL_TEXTURE_ALPHA; ta_ext_a_mode = GR_FUNC_MODE_ZERO; ta_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA; ta_ext_b_mode = GR_FUNC_MODE_NEGATIVE_X; ta_ext_d = GR_CMBX_B; ta_ext_d_invert = 0; break; default: ta_ext_a = 0; ta_ext_a_mode = 0; ta_ext_b = 0; ta_ext_b_mode = 0; ta_ext_d = 0; ta_ext_d_invert = 0; break; } if (tmu == GR_TMU0) { cmb.t0a_ext_a = ta_ext_a; cmb.t0a_ext_a_mode = ta_ext_a_mode; cmb.t0a_ext_b = ta_ext_b; cmb.t0a_ext_b_mode = ta_ext_b_mode; cmb.t0a_ext_c = ta_ext_c; cmb.t0a_ext_c_invert = ta_ext_c_invert; cmb.t0a_ext_d = ta_ext_d; cmb.t0a_ext_d_invert = ta_ext_d_invert; } else { cmb.t1a_ext_a = ta_ext_a; cmb.t1a_ext_a_mode = ta_ext_a_mode; cmb.t1a_ext_b = ta_ext_b; cmb.t1a_ext_b_mode = ta_ext_b_mode; cmb.t1a_ext_c = ta_ext_c; cmb.t1a_ext_c_invert = ta_ext_c_invert; cmb.t1a_ext_d = ta_ext_d; cmb.t1a_ext_d_invert = ta_ext_d_invert; } } mupen64plus-video-glide64-src-2.6.0/src/Combine.h000066400000000000000000000117451464507525600214100ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** #ifndef COMBINE_H #define COMBINE_H #include "Gfx1.3.h" // texture MOD types #define TMOD_TEX_INTER_COLOR_USING_FACTOR 1 #define TMOD_TEX_INTER_COL_USING_COL1 2 #define TMOD_FULL_COLOR_SUB_TEX 3 #define TMOD_COL_INTER_COL1_USING_TEX 4 #define TMOD_COL_INTER_COL1_USING_TEXA 5 #define TMOD_COL_INTER_COL1_USING_TEXA__MUL_TEX 6 #define TMOD_COL_INTER_TEX_USING_TEXA 7 #define TMOD_COL2_INTER__COL_INTER_COL1_USING_TEX__USING_TEXA 8 #define TMOD_TEX_SCALE_FAC_ADD_FAC 9 #define TMOD_TEX_SUB_COL_MUL_FAC_ADD_TEX 10 #define TMOD_TEX_SCALE_COL_ADD_COL 11 #define TMOD_TEX_ADD_COL 12 #define TMOD_TEX_SUB_COL 13 #define TMOD_TEX_SUB_COL_MUL_FAC 14 #define TMOD_COL_INTER_TEX_USING_COL1 15 #define TMOD_COL_MUL_TEXA_ADD_TEX 16 #define TMOD_COL_INTER_TEX_USING_TEX 17 #define TMOD_TEX_INTER_NOISE_USING_COL 18 #define TMOD_TEX_INTER_COL_USING_TEXA 19 #define TMOD_TEX_MUL_COL 20 #define TMOD_TEX_SCALE_FAC_ADD_COL 21 #define COMBINE_EXT_COLOR 1 #define COMBINE_EXT_ALPHA 2 #define TEX_COMBINE_EXT_COLOR 1 #define TEX_COMBINE_EXT_ALPHA 2 typedef struct { DWORD ccolor; // constant color to set at the end, color and alpha DWORD c_fnc, c_fac, c_loc, c_oth; // grColorCombine flags DWORD a_fnc, a_fac, a_loc, a_oth; // grAlphaCombine flags DWORD tex, tmu0_func, tmu0_fac, tmu0_invert, tmu1_func, tmu1_fac, tmu1_invert; DWORD tmu0_a_func, tmu0_a_fac, tmu0_a_invert, tmu1_a_func, tmu1_a_fac, tmu1_a_invert; int dc0_lodbias, dc1_lodbias; BYTE dc0_detailscale, dc1_detailscale; float dc0_detailmax, dc1_detailmax; float lodbias0, lodbias1; DWORD abf1, abf2; DWORD mod_0, modcolor_0, modcolor1_0, modcolor2_0, modfactor_0; DWORD mod_1, modcolor_1, modcolor1_1, modcolor2_1, modfactor_1; //combine extensions DWORD c_ext_a, c_ext_a_mode, c_ext_b, c_ext_b_mode, c_ext_c, c_ext_d; BOOL c_ext_c_invert, c_ext_d_invert; DWORD a_ext_a, a_ext_a_mode, a_ext_b, a_ext_b_mode, a_ext_c, a_ext_d; BOOL a_ext_c_invert, a_ext_d_invert; DWORD t0c_ext_a, t0c_ext_a_mode, t0c_ext_b, t0c_ext_b_mode, t0c_ext_c, t0c_ext_d; BOOL t0c_ext_c_invert, t0c_ext_d_invert; DWORD t0a_ext_a, t0a_ext_a_mode, t0a_ext_b, t0a_ext_b_mode, t0a_ext_c, t0a_ext_d; BOOL t0a_ext_c_invert, t0a_ext_d_invert; DWORD t1c_ext_a, t1c_ext_a_mode, t1c_ext_b, t1c_ext_b_mode, t1c_ext_c, t1c_ext_d; BOOL t1c_ext_c_invert, t1c_ext_d_invert; DWORD t1a_ext_a, t1a_ext_a_mode, t1a_ext_b, t1a_ext_b_mode, t1a_ext_c, t1a_ext_d; BOOL t1a_ext_c_invert, t1a_ext_d_invert; GRCOLORCOMBINEEXT grColorCombineExt; GRCOLORCOMBINEEXT grAlphaCombineExt; GRTEXCOLORCOMBINEEXT grTexColorCombineExt; GRTEXCOLORCOMBINEEXT grTexAlphaCombineExt; GRCONSTANTCOLORVALUEEXT grConstantColorValueExt; DWORD tex_ccolor; BOOL combine_ext; BYTE cmb_ext_use; BYTE tex_cmb_ext_use; } COMBINE; extern COMBINE cmb; void Combine (); void CombineBlender (); void CountCombine (); void InitCombine (); void ColorCombinerToExtension (); void AlphaCombinerToExtension (); void TexColorCombinerToExtension (GrChipID_t tmu); void TexAlphaCombinerToExtension (GrChipID_t tmu); #endif //COMBINE _H mupen64plus-video-glide64-src-2.6.0/src/Config.cpp000066400000000000000000000047371464507525600215770ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2010 Jon Ring * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ #include "Config.h" #include "m64p.h" static m64p_handle video_general_section; static m64p_handle video_glide64_section; BOOL Config_Open() { if (ConfigOpenSection("Video-General", &video_general_section) != M64ERR_SUCCESS || ConfigOpenSection("Video-Glide64", &video_glide64_section) != M64ERR_SUCCESS) { WriteLog(M64MSG_ERROR, "Could not open configuration"); return FALSE; } ConfigSetDefaultBool(video_general_section, "Fullscreen", false, "Use fullscreen mode if True, or windowed mode if False"); ConfigSetDefaultInt(video_general_section, "ScreenWidth", 640, "Width of output window or fullscreen width"); ConfigSetDefaultInt(video_general_section, "ScreenHeight", 480, "Height of output window or fullscreen height"); return TRUE; } PackedScreenResolution Config_ReadScreenSettings() { PackedScreenResolution packedResolution; packedResolution.width = ConfigGetParamInt(video_general_section, "ScreenWidth"); packedResolution.height = ConfigGetParamInt(video_general_section, "ScreenHeight"); packedResolution.fullscreen = ConfigGetParamBool(video_general_section, "Fullscreen"); return packedResolution; } int Config_ReadInt(const char *itemname, const char *desc, int def_value, BOOL create, BOOL isBoolean) { WriteLog(M64MSG_VERBOSE, "Getting value %s", itemname); if (isBoolean) { ConfigSetDefaultBool(video_glide64_section, itemname, def_value, desc); return ConfigGetParamBool(video_glide64_section, itemname); } else { ConfigSetDefaultInt(video_glide64_section, itemname, def_value, desc); return ConfigGetParamInt(video_glide64_section, itemname); } } mupen64plus-video-glide64-src-2.6.0/src/Config.h000066400000000000000000000021241464507525600212300ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2010 Jon Ring * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ #ifndef CONFIG_H #define CONFIG_H #include "winlnxdefs.h" #include "m64p.h" BOOL Config_Open(); PackedScreenResolution Config_ReadScreenSettings(); int Config_ReadInt(const char *itemname, const char *desc, int def_value, BOOL create=TRUE, BOOL isBoolean=TRUE); #endif /* CONFIG_H */ mupen64plus-video-glide64-src-2.6.0/src/Debugger.cpp000066400000000000000000001045141464507525600221100ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** #define M64P_PLUGIN_PROTOTYPES 1 #include "m64p_types.h" #include "m64p_plugin.h" #include "m64p_config.h" #include "m64p_vidext.h" #include "Util.h" #include "Debugger.h" #include #include "Gfx1.3.h" #ifndef _WIN32 #include #include #endif // _WIN32 DEBUGGER debug; const char *FBLa[] = { "G_BL_CLR_IN", "G_BL_CLR_MEM", "G_BL_CLR_BL", "G_BL_CLR_FOG" }; const char *FBLb[] = { "G_BL_A_IN", "G_BL_A_FOG", "G_BL_A_SHADE", "G_BL_0" }; const char *FBLc[] = { "G_BL_CLR_IN", "G_BL_CLR_MEM", "G_BL_CLR_BL", "G_BL_CLR_FOG"}; const char *FBLd[] = { "G_BL_1MA", "G_BL_A_MEM", "G_BL_1", "G_BL_0" }; const char *str_lod[] = { "1", "2", "4", "8", "16", "32", "64", "128", "256" }; const char *str_aspect[] = { "1x8", "1x4", "1x2", "1x1", "2x1", "4x1", "8x1" }; #define SX(x) ((x)*rdp.scale_1024) #define SY(x) ((x)*rdp.scale_768) #ifdef COLORED_DEBUGGER #define COL_CATEGORY() grConstantColorValue(0xD288F400) #define COL_UCC() grConstantColorValue(0xFF000000) #define COL_CC() grConstantColorValue(0x88C3F400) #define COL_UAC() grConstantColorValue(0xFF808000) #define COL_AC() grConstantColorValue(0x3CEE5E00) #define COL_TEXT() grConstantColorValue(0xFFFFFF00) #define COL_SEL(x) grConstantColorValue((x)?0x00FF00FF:0x800000FF) #else #define COL_CATEGORY() #define COL_UCC() #define COL_CC() #define COL_UAC() #define COL_AC() #define COL_TEXT() #define COL_SEL(x) #endif #define COL_GRID 0xFFFFFF80 BOOL grid = 0; // // debug_init - initialize the debugger // void debug_init () { debug.capture = 0; debug.selected = SELECTED_TRI; debug.screen = NULL; debug.tri_list = NULL; debug.tri_last = NULL; debug.tri_sel = NULL; debug.tmu = 0; debug.tex_scroll = 0; debug.tex_sel = 0; debug.draw_mode = 0; } // // debug_cacheviewer - views the debugger's cache // void debug_cacheviewer () { grCullMode (GR_CULL_DISABLE); int i; for (i=0; i<2; i++) { grTexFilterMode (i, (settings.filter_cache)?GR_TEXTUREFILTER_BILINEAR:GR_TEXTUREFILTER_POINT_SAMPLED, (settings.filter_cache)?GR_TEXTUREFILTER_BILINEAR:GR_TEXTUREFILTER_POINT_SAMPLED); grTexClampMode (i, GR_TEXTURECLAMP_CLAMP, GR_TEXTURECLAMP_CLAMP); } switch (debug.draw_mode) { case 0: grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); break; case 1: grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE, FXFALSE); grConstantColorValue (0xFFFFFFFF); break; case 2: grColorCombine (GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE, FXFALSE); grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); grConstantColorValue (0xFFFFFFFF); } if (debug.tmu == 1) { grTexCombine (GR_TMU1, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE); grTexCombine (GR_TMU0, GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, FXFALSE, FXFALSE); } else { grTexCombine (GR_TMU0, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE); } grAlphaBlendFunction (GR_BLEND_SRC_ALPHA, GR_BLEND_ONE_MINUS_SRC_ALPHA, GR_BLEND_ONE, GR_BLEND_ZERO); // Draw texture memory for (i=0; i<4; i++) { for (DWORD x=0; x<16; x++) { DWORD y = i+debug.tex_scroll; if (x+y*16 >= (DWORD)rdp.n_cached[debug.tmu]) break; VERTEX v[4] = { { SX(x*64.0f), SY(512+64.0f*i), 1, 1, 0, 0, 0, 0, {0, 0, 0, 0} }, { SX(x*64.0f+64.0f*rdp.cache[debug.tmu][x+y*16].scale_x), SY(512+64.0f*i), 1, 1, 255*rdp.cache[debug.tmu][x+y*16].scale_x, 0, 0, 0, {0, 0, 0, 0} }, { SX(x*64.0f), SY(512+64.0f*i+64.0f*rdp.cache[debug.tmu][x+y*16].scale_y), 1, 1, 0, 255*rdp.cache[debug.tmu][x+y*16].scale_y, 0, 0, {0, 0, 0, 0} }, { SX(x*64.0f+64.0f*rdp.cache[debug.tmu][x+y*16].scale_x), SY(512+64.0f*i+64.0f*rdp.cache[debug.tmu][x+y*16].scale_y), 1, 1, 255*rdp.cache[debug.tmu][x+y*16].scale_x, 255*rdp.cache[debug.tmu][x+y*16].scale_y, 0, 0, {0, 0, 0, 0} } }; for (int i=0; i<4; i++) { v[i].u1 = v[i].u0; v[i].v1 = v[i].v0; } ConvertCoordsConvert (v, 4); grTexSource(debug.tmu, grTexMinAddress(debug.tmu) + rdp.cache[debug.tmu][x+y*16].tmem_addr, GR_MIPMAPLEVELMASK_BOTH, &rdp.cache[debug.tmu][x+y*16].t_info); grDrawTriangle (&v[2], &v[1], &v[0]); grDrawTriangle (&v[2], &v[3], &v[1]); } } /* for (i=0; i<4; i++) { for (DWORD x=0; x<16; x++) { DWORD y = i+debug.tex_scroll; if (x+y*16 >= (DWORD)rdp.n_cached[debug.tmu]) break; VERTEX v[4] = { { SX(x*64.0f), SY(768-64.0f*i), 1, 1, 0, 0, 0, 0, 0, 0, 0 }, { SX(x*64.0f+64.0f), SY(768-64.0f*i), 1, 1, 255, 0, 0, 0, 0, 0, 0 }, { SX(x*64.0f), SY(768-64.0f*i-64.0f), 1, 1, 0, 255, 0, 0, 0, 0, 0 }, { SX(x*64.0f+64.0f), SY(768-64.0f*i-64.0f), 1, 1, 255, 255, 0, 0, 0, 0, 0 } }; for (int i=0; i<4; i++) { v[i].u1 = v[i].u0; v[i].v1 = v[i].v0; } ConvertCoordsConvert (v, 4); grTexSource(debug.tmu, grTexMinAddress(debug.tmu) + rdp.cache[debug.tmu][x+y*16].tmem_addr, GR_MIPMAPLEVELMASK_BOTH, &rdp.cache[debug.tmu][x+y*16].t_info); grDrawTriangle (&v[2], &v[1], &v[0]); grDrawTriangle (&v[2], &v[3], &v[1]); } }*/ } // // debug_capture - does a frame capture event (for debugging) // #ifdef _WIN32 void debug_capture () { DWORD i,j; if (debug.tri_list == NULL) goto END; debug.tri_sel = debug.tri_list; debug.selected = SELECTED_TRI; // Connect the list debug.tri_last->pNext = debug.tri_list; while (!(GetAsyncKeyState(VK_INSERT) & 0x0001)) { // Check for clicks if (GetAsyncKeyState(GetSystemMetrics(SM_SWAPBUTTON)?VK_RBUTTON:VK_LBUTTON) & 0x0001) { POINT pt; GetCursorPos (&pt); //int diff = settings.scr_res_y-settings.res_y; if (pt.y <= (int)settings.res_y) { int x = pt.x; int y = pt.y;//settings.res_y - (pt.y - diff); TRI_INFO *start; TRI_INFO *tri; if (debug.tri_sel == NULL) tri = debug.tri_list, start = debug.tri_list; else tri = debug.tri_sel->pNext, start = debug.tri_sel; // Select a triangle (start from the currently selected one) do { if (tri->v[0].x == tri->v[1].x && tri->v[0].y == tri->v[1].y) { tri = tri->pNext; continue; } for (i=0; inv; i++) { j=i+1; if (j==tri->nv) j=0; if ((y-tri->v[i].y)*(tri->v[j].x-tri->v[i].x) - (x-tri->v[i].x)*(tri->v[j].y-tri->v[i].y) < 0) break; // It's outside } if (i==tri->nv) // all lines passed { debug.tri_sel = tri; break; } for (i=0; inv; i++) { j=i+1; if (j==tri->nv) j=0; if ((y-tri->v[i].y)*(tri->v[j].x-tri->v[i].x) - (x-tri->v[i].x)*(tri->v[j].y-tri->v[i].y) > 0) break; // It's outside } if (i==tri->nv) // all lines passed { debug.tri_sel = tri; break; } tri = tri->pNext; } while (tri != start); } else { // on a texture debug.tex_sel = (((DWORD)((pt.y-SY(512))/SY(64))+debug.tex_scroll)*16) + (DWORD)(pt.x/SX(64)); } } debug_keys (); grBufferClear (0, 0, 0xFFFF); // Copy the screen capture back to the screen: // Lock the backbuffer GrLfbInfo_t info; while (!grLfbLock (GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER, GR_LFBWRITEMODE_565, GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)); DWORD offset_src=0/*(settings.scr_res_y-settings.res_y)*info.strideInBytes*/, offset_dst=0; // Copy the screen for (DWORD y=0; ynv; i++) { j=i+1; if (j>=debug.tri_sel->nv) j=0; grDrawLine (&debug.tri_sel->v[i], &debug.tri_sel->v[j]); v[i] = &debug.tri_sel->v[i]; } } // and the selected texture DWORD t_y = ((debug.tex_sel & 0xFFFFFFF0) >> 4) - debug.tex_scroll; DWORD t_x = debug.tex_sel & 0xF; VERTEX vt[4] = { { SX(t_x*64.0f), SY(512+64.0f*t_y), 1, 1 }, { SX(t_x*64.0f+64.0f), SY(512+64.0f*t_y), 1, 1 }, { SX(t_x*64.0f), SY(512+64.0f*t_y+64.0f), 1, 1 }, { SX(t_x*64.0f+64.0f), SY(512+64.0f*t_y+64.0f), 1, 1 } }; if (t_y < 4) { grDrawLine (&vt[0], &vt[1]); grDrawLine (&vt[1], &vt[3]); grDrawLine (&vt[3], &vt[2]); grDrawLine (&vt[2], &vt[0]); } grConstantColorValue (0xFF000020); if (t_y < 4) { grDrawTriangle (&vt[2], &vt[1], &vt[0]); grDrawTriangle (&vt[2], &vt[3], &vt[1]); } if (debug.tri_sel) grDrawVertexArray (GR_TRIANGLE_FAN, debug.tri_sel->nv, &v); // Draw the outline of the cacheviewer if (debug.page == PAGE_TEX_INFO) { /*grConstantColorValue (0xFF0000FF); float scx = rdp.cache[debug.tmu][debug.tex_sel].scale_x; float scy = rdp.cache[debug.tmu][debug.tex_sel].scale_y; VERTEX v[4] = { { SX(704.0f), SY(271.0f), 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { SX(704.0f+256.0f*scx), SY(271.0f), 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { SX(704.0f), SY(271.0f-256.0f*scy), 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { SX(704.0f+256.0f*scx), SY(271.0f-256.0f*scy), 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; VERTEX *varr[5] = { &v[0], &v[1], &v[3], &v[2], &v[0] }; grDrawVertexArray (GR_LINE_STRIP, 5, varr);*/ float scx = rdp.cache[debug.tmu][debug.tex_sel].scale_x; float scy = rdp.cache[debug.tmu][debug.tex_sel].scale_y; // And the grid if (grid) { grConstantColorValue (COL_GRID); float scale_y = (256.0f * scy) / (float)rdp.cache[debug.tmu][debug.tex_sel].height; for (int y=0; y<=(int)rdp.cache[debug.tmu][debug.tex_sel].height; y++) { float y_val = SY(221.0f+y*scale_y); VERTEX vh[2] = { { SX(704.0f), y_val, 1, 1 }, { SX(704.0f+255.0f*scx), y_val, 1, 1 } }; grDrawLine (&vh[0], &vh[1]); } float scale_x = (256.0f * scx) / (float)rdp.cache[debug.tmu][debug.tex_sel].width; for (int x=0; x<=(int)rdp.cache[debug.tmu][debug.tex_sel].width; x++) { float x_val = SX(704.0f+x*scale_x); VERTEX vv[2] = { { x_val, SX(221.0f), 1, 1 }, { x_val, SX(221.0f+256.0f*scy), 1, 1 } }; grDrawLine (&vv[0], &vv[1]); } } } grTexCombine (GR_TMU0, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE); grColorCombine (GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE, FXFALSE); grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); grConstantColorValue (0xFFFFFF00); // Output the information about the selected triangle grTexSource(GR_TMU0, // Text grTexMinAddress(debug.tmu)+ offset_font, GR_MIPMAPLEVELMASK_BOTH, &fontTex); static char *cycle_mode_s[4] = { "1 cycle (0)", "2 cycle (1)", "copy (2)", "fill (3)" }; #define OUTPUT(fmt,other) output(642,(float)i,1,fmt,other); i-=16; #define OUTPUT1(fmt,other,other1) output(642,(float)i,1,fmt,other,other1); i-=16; #define OUTPUT_(fmt,cc) COL_SEL(cc); x=642; output(x,(float)i,1,fmt,0); x+=8*(strlen(fmt)+1) #define _OUTPUT(fmt,cc) COL_SEL(cc); output(x,(float)i,1,fmt,0); x+=8*(strlen(fmt)+1) i = 740; float x; if (debug.page == PAGE_GENERAL && debug.tri_sel) { COL_CATEGORY(); OUTPUT ("GENERAL (page 1):",0); COL_TEXT(); OUTPUT ("tri #%d", debug.tri_sel->tri_n); OUTPUT ("type: %s", tri_type[debug.tri_sel->type]); OUTPUT ("geom: 0x%08lx", debug.tri_sel->geom_mode); OUTPUT ("othermode_h: 0x%08lx", debug.tri_sel->othermode_h); OUTPUT ("othermode_l: 0x%08lx", debug.tri_sel->othermode_l); OUTPUT ("flags: 0x%08lx", debug.tri_sel->flags); OUTPUT ("",0); COL_CATEGORY(); OUTPUT ("COMBINE:",0); COL_TEXT(); OUTPUT ("cycle_mode: %s", cycle_mode_s[debug.tri_sel->cycle_mode]); OUTPUT ("cycle1: 0x%08lx", debug.tri_sel->cycle1); OUTPUT ("cycle2: 0x%08lx", debug.tri_sel->cycle2); if (debug.tri_sel->uncombined & 1) COL_UCC(); else COL_CC(); OUTPUT ("a0: %s", Mode0[(debug.tri_sel->cycle1)&0x0000000F]); OUTPUT ("b0: %s", Mode1[(debug.tri_sel->cycle1>>4)&0x0000000F]); OUTPUT ("c0: %s", Mode2[(debug.tri_sel->cycle1>>8)&0x0000001F]); OUTPUT ("d0: %s", Mode3[(debug.tri_sel->cycle1>>13)&0x00000007]); if (debug.tri_sel->uncombined & 2) COL_UAC(); else COL_AC(); OUTPUT ("Aa0: %s", Alpha0[(debug.tri_sel->cycle1>>16)&0x00000007]); OUTPUT ("Ab0: %s", Alpha1[(debug.tri_sel->cycle1>>19)&0x00000007]); OUTPUT ("Ac0: %s", Alpha2[(debug.tri_sel->cycle1>>22)&0x00000007]); OUTPUT ("Ad0: %s", Alpha3[(debug.tri_sel->cycle1>>25)&0x00000007]); if (debug.tri_sel->uncombined & 1) COL_UCC(); else COL_CC(); OUTPUT ("a1: %s", Mode0[(debug.tri_sel->cycle2)&0x0000000F]); OUTPUT ("b1: %s", Mode1[(debug.tri_sel->cycle2>>4)&0x0000000F]); OUTPUT ("c1: %s", Mode2[(debug.tri_sel->cycle2>>8)&0x0000001F]); OUTPUT ("d1: %s", Mode3[(debug.tri_sel->cycle2>>13)&0x00000007]); if (debug.tri_sel->uncombined & 2) COL_UAC(); else COL_AC(); OUTPUT ("Aa1: %s", Alpha0[(debug.tri_sel->cycle2>>16)&0x00000007]); OUTPUT ("Ab1: %s", Alpha1[(debug.tri_sel->cycle2>>19)&0x00000007]); OUTPUT ("Ac1: %s", Alpha2[(debug.tri_sel->cycle2>>22)&0x00000007]); OUTPUT ("Ad1: %s", Alpha3[(debug.tri_sel->cycle2>>25)&0x00000007]); } if ((debug.page == PAGE_TEX1 || debug.page == PAGE_TEX2) && debug.tri_sel) { COL_CATEGORY (); OUTPUT1 ("TEXTURE %d (page %d):", debug.page-PAGE_TEX1, 2+debug.page-PAGE_TEX1); COL_TEXT(); int tmu = debug.page - PAGE_TEX1; OUTPUT1 ("cur cache: %d,%d", debug.tri_sel->t[tmu].cur_cache[tmu]&0x0F, debug.tri_sel->t[tmu].cur_cache[tmu]>>4); OUTPUT ("tex_size: %d", debug.tri_sel->t[tmu].size); OUTPUT ("tex_format: %d", debug.tri_sel->t[tmu].format); OUTPUT ("width: %d", debug.tri_sel->t[tmu].width); OUTPUT ("height: %d", debug.tri_sel->t[tmu].height); OUTPUT ("palette: %d", debug.tri_sel->t[tmu].palette); OUTPUT ("clamp_s: %d", debug.tri_sel->t[tmu].clamp_s); OUTPUT ("clamp_t: %d", debug.tri_sel->t[tmu].clamp_t); OUTPUT ("mirror_s: %d", debug.tri_sel->t[tmu].mirror_s); OUTPUT ("mirror_t: %d", debug.tri_sel->t[tmu].mirror_t); OUTPUT ("mask_s: %d", debug.tri_sel->t[tmu].mask_s); OUTPUT ("mask_t: %d", debug.tri_sel->t[tmu].mask_t); OUTPUT ("shift_s: %d", debug.tri_sel->t[tmu].shift_s); OUTPUT ("shift_t: %d", debug.tri_sel->t[tmu].shift_t); OUTPUT ("ul_s: %d", debug.tri_sel->t[tmu].ul_s); OUTPUT ("ul_t: %d", debug.tri_sel->t[tmu].ul_t); OUTPUT ("lr_s: %d", debug.tri_sel->t[tmu].lr_s); OUTPUT ("lr_t: %d", debug.tri_sel->t[tmu].lr_t); OUTPUT ("t_ul_s: %d", debug.tri_sel->t[tmu].t_ul_s); OUTPUT ("t_ul_t: %d", debug.tri_sel->t[tmu].t_ul_t); OUTPUT ("t_lr_s: %d", debug.tri_sel->t[tmu].t_lr_s); OUTPUT ("t_lr_t: %d", debug.tri_sel->t[tmu].t_lr_t); OUTPUT ("scale_s: %f", debug.tri_sel->t[tmu].scale_s); OUTPUT ("scale_t: %f", debug.tri_sel->t[tmu].scale_t); OUTPUT ("s_mode: %s", str_cm[((debug.tri_sel->t[tmu].clamp_s << 1) | debug.tri_sel->t[tmu].mirror_s)&3]); OUTPUT ("t_mode: %s", str_cm[((debug.tri_sel->t[tmu].clamp_t << 1) | debug.tri_sel->t[tmu].mirror_t)&3]); } if (debug.page == PAGE_COLORS && debug.tri_sel) { COL_CATEGORY(); OUTPUT ("COLORS (page 4)", 0); COL_TEXT(); OUTPUT ("fill: %08lx", debug.tri_sel->fill_color); OUTPUT ("prim: %08lx", debug.tri_sel->prim_color); OUTPUT ("blend: %08lx", debug.tri_sel->blend_color); OUTPUT ("env: %08lx", debug.tri_sel->env_color); OUTPUT ("fog: %08lx", debug.tri_sel->fog_color); OUTPUT ("prim_lodmin: %d", debug.tri_sel->prim_lodmin); OUTPUT ("prim_lodfrac: %d", debug.tri_sel->prim_lodfrac); } if (debug.page == PAGE_FBL && debug.tri_sel) { COL_CATEGORY(); OUTPUT ("BLENDER", 0); COL_TEXT(); OUTPUT ("fbl_a0: %s", FBLa[(debug.tri_sel->othermode_l>>30)&0x3]); OUTPUT ("fbl_b0: %s", FBLb[(debug.tri_sel->othermode_l>>26)&0x3]); OUTPUT ("fbl_c0: %s", FBLc[(debug.tri_sel->othermode_l>>22)&0x3]); OUTPUT ("fbl_d0: %s", FBLd[(debug.tri_sel->othermode_l>>18)&0x3]); OUTPUT ("fbl_a1: %s", FBLa[(debug.tri_sel->othermode_l>>28)&0x3]); OUTPUT ("fbl_b1: %s", FBLb[(debug.tri_sel->othermode_l>>24)&0x3]); OUTPUT ("fbl_c1: %s", FBLc[(debug.tri_sel->othermode_l>>20)&0x3]); OUTPUT ("fbl_d1: %s", FBLd[(debug.tri_sel->othermode_l>>16)&0x3]); OUTPUT ("", 0); OUTPUT ("fbl: %08lx", debug.tri_sel->othermode_l&0xFFFF0000); OUTPUT ("fbl #1: %08lx", debug.tri_sel->othermode_l&0xCCCC0000); OUTPUT ("fbl #2: %08lx", debug.tri_sel->othermode_l&0x33330000); } if (debug.page == PAGE_OTHERMODE_L && debug.tri_sel) { DWORD othermode_l = debug.tri_sel->othermode_l; COL_CATEGORY (); OUTPUT ("OTHERMODE_L: %08lx", othermode_l); OUTPUT_ ("AC_NONE", (othermode_l & 3) == 0); _OUTPUT ("AC_THRESHOLD", (othermode_l & 3) == 1); _OUTPUT ("AC_DITHER", (othermode_l & 3) == 3); i -= 16; OUTPUT_ ("ZS_PIXEL", !(othermode_l & 4)); _OUTPUT ("ZS_PRIM", (othermode_l & 4)); i -= 32; COL_CATEGORY (); OUTPUT ("RENDERMODE: %08lx", othermode_l); OUTPUT_ ("AA_EN", othermode_l & 0x08); i -= 16; OUTPUT_ ("Z_CMP", othermode_l & 0x10); i -= 16; OUTPUT_ ("Z_UPD", othermode_l & 0x20); i -= 16; OUTPUT_ ("IM_RD", othermode_l & 0x40); i -= 16; OUTPUT_ ("CLR_ON_CVG", othermode_l & 0x80); i -= 16; OUTPUT_ ("CVG_DST_CLAMP", (othermode_l & 0x300) == 0x000); _OUTPUT ("CVG_DST_WRAP", (othermode_l & 0x300) == 0x100); _OUTPUT (".._FULL", (othermode_l & 0x300) == 0x200); _OUTPUT (".._SAVE", (othermode_l & 0x300) == 0x300); i -= 16; OUTPUT_ ("ZM_OPA", (othermode_l & 0xC00) == 0x000); _OUTPUT ("ZM_INTER", (othermode_l & 0xC00) == 0x400); _OUTPUT ("ZM_XLU", (othermode_l & 0xC00) == 0x800); _OUTPUT ("ZM_DEC", (othermode_l & 0xC00) == 0xC00); i -= 16; OUTPUT_ ("CVG_X_ALPHA", othermode_l & 0x1000); i -= 16; OUTPUT_ ("ALPHA_CVG_SEL", othermode_l & 0x2000); i -= 16; OUTPUT_ ("FORCE_BL", othermode_l & 0x4000); } if (debug.page == PAGE_OTHERMODE_H && debug.tri_sel) { DWORD othermode_h = debug.tri_sel->othermode_h; COL_CATEGORY (); OUTPUT ("OTHERMODE_H: %08lx", othermode_h); OUTPUT_ ("CK_NONE", (othermode_h & 0x100) == 0); _OUTPUT ("CK_KEY", (othermode_h & 0x100) == 1); i -= 16; OUTPUT_ ("TC_CONV", (othermode_h & 0xE00) == 0x200); _OUTPUT ("TC_FILTCONV", (othermode_h & 0xE00) == 0xA00); _OUTPUT ("TC_FILT", (othermode_h & 0xE00) == 0xC00); i -= 16; OUTPUT_ ("TF_POINT", (othermode_h & 0x3000) == 0x0000); _OUTPUT ("TF_AVERAGE", (othermode_h & 0x3000) == 0x3000); _OUTPUT ("TF_BILERP", (othermode_h & 0x3000) == 0x2000); i -= 16; OUTPUT_ ("TT_NONE", (othermode_h & 0xC000) == 0x0000); _OUTPUT ("TT_RGBA16", (othermode_h & 0xC000) == 0x8000); _OUTPUT ("TT_IA16", (othermode_h & 0xC000) == 0xC000); i -= 16; OUTPUT_ ("TL_TILE", (othermode_h & 0x10000) == 0x00000); _OUTPUT ("TL_LOD", (othermode_h & 0x10000) == 0x10000); i -= 16; OUTPUT_ ("TD_CLAMP", (othermode_h & 0x60000) == 0x00000); _OUTPUT ("TD_SHARPEN", (othermode_h & 0x60000) == 0x20000); _OUTPUT ("TD_DETAIL", (othermode_h & 0x60000) == 0x40000); i -= 16; OUTPUT_ ("TP_NONE", (othermode_h & 0x80000) == 0x00000); _OUTPUT ("TP_PERSP", (othermode_h & 0x80000) == 0x80000); i -= 16; OUTPUT_ ("1CYCLE", (othermode_h & 0x300000) == 0x000000); _OUTPUT ("2CYCLE", (othermode_h & 0x300000) == 0x100000); _OUTPUT ("COPY", (othermode_h & 0x300000) == 0x200000); _OUTPUT ("FILL", (othermode_h & 0x300000) == 0x300000); i -= 16; OUTPUT_ ("PM_1PRIM", (othermode_h & 0x400000) == 0x000000); _OUTPUT ("PM_NPRIM", (othermode_h & 0x400000) == 0x400000); } if (debug.page == PAGE_TEXELS && debug.tri_sel) { // change these to output whatever you need, ou for triangles, or u0 for texrects COL_TEXT(); OUTPUT ("n: %d", debug.tri_sel->nv); OUTPUT ("",0); for (j=0; jnv; j++) { OUTPUT1 ("v[%d].s0: %f", j, debug.tri_sel->v[j].ou); OUTPUT1 ("v[%d].t0: %f", j, debug.tri_sel->v[j].ov); } OUTPUT ("",0); for (j=0; jnv; j++) { OUTPUT1 ("v[%d].s1: %f", j, debug.tri_sel->v[j].u0); OUTPUT1 ("v[%d].t1: %f", j, debug.tri_sel->v[j].v0); } } if (debug.page == PAGE_COORDS && debug.tri_sel) { COL_TEXT(); OUTPUT ("n: %d", debug.tri_sel->nv); for (j=0; jnv; j++) { OUTPUT1 ("v[%d].x: %f", j, debug.tri_sel->v[j].x); OUTPUT1 ("v[%d].y: %f", j, debug.tri_sel->v[j].y); OUTPUT1 ("v[%d].z: %f", j, debug.tri_sel->v[j].z); OUTPUT1 ("v[%d].w: %f", j, debug.tri_sel->v[j].w); OUTPUT1 ("v[%d].f: %f", j, 1.0f/debug.tri_sel->v[j].f); OUTPUT1 ("v[%d].r: %d", j, debug.tri_sel->v[j].r); OUTPUT1 ("v[%d].g: %d", j, debug.tri_sel->v[j].g); OUTPUT1 ("v[%d].b: %d", j, debug.tri_sel->v[j].b); OUTPUT1 ("v[%d].a: %d", j, debug.tri_sel->v[j].a); } } if (debug.page == PAGE_TEX_INFO && debug.tex_sel < (DWORD)rdp.n_cached[debug.tmu]) { COL_CATEGORY(); OUTPUT ("CACHE (page 0)", 0); COL_TEXT(); //OUTPUT ("t_mem: %08lx", rdp.cache[0][debug.tex_sel].t_mem); //OUTPUT ("crc: %08lx", rdp.cache[0][debug.tex_sel].crc); OUTPUT ("addr: %08lx", rdp.cache[debug.tmu][debug.tex_sel].addr); OUTPUT ("scale_x: %f", rdp.cache[debug.tmu][debug.tex_sel].scale_x); OUTPUT ("scale_y: %f", rdp.cache[debug.tmu][debug.tex_sel].scale_y); OUTPUT ("tmem_addr: %08lx", rdp.cache[debug.tmu][debug.tex_sel].tmem_addr); OUTPUT ("palette: %08lx", rdp.cache[debug.tmu][debug.tex_sel].palette); OUTPUT ("set_by: %08lx", rdp.cache[debug.tmu][debug.tex_sel].set_by); OUTPUT ("texrecting: %d", rdp.cache[debug.tmu][debug.tex_sel].texrecting); OUTPUT ("mod: %08lx", rdp.cache[debug.tmu][debug.tex_sel].mod); OUTPUT ("mod_col: %08lx", rdp.cache[debug.tmu][debug.tex_sel].mod_color); OUTPUT ("mod_col1: %08lx", rdp.cache[debug.tmu][debug.tex_sel].mod_color1); i=740; output(800,(float)i,1,"width: %d", rdp.cache[debug.tmu][debug.tex_sel].width); i-=16; output(800,(float)i,1,"height: %d", rdp.cache[debug.tmu][debug.tex_sel].height); i-=16; output(800,(float)i,1,"format: %d", rdp.cache[debug.tmu][debug.tex_sel].format); i-=16; output(800,(float)i,1,"size: %d", rdp.cache[debug.tmu][debug.tex_sel].size); i-=16; output(800,(float)i,1,"crc: %08lx", rdp.cache[debug.tmu][debug.tex_sel].crc); i-=16; output(800,(float)i,1,"line: %d", rdp.cache[debug.tmu][debug.tex_sel].line); i-=16; output(800,(float)i,1,"mod_factor: %08lx", rdp.cache[debug.tmu][debug.tex_sel].mod_factor); i-=32; output(800,(float)i,1,"lod: %s", str_lod[rdp.cache[debug.tmu][debug.tex_sel].lod]); i-=16; output(800,(float)i,1,"aspect: %s", str_aspect[rdp.cache[debug.tmu][debug.tex_sel].aspect + 3]); // debug_texture(debug.tmu, rdp.cache[debug.tmu][debug.tex_sel].addr, debug.tex_sel); } // Draw the vertex numbers if (debug.tri_sel) { for (i=0; inv; i++) { grConstantColorValue (0x000000FF); output (debug.tri_sel->v[i].x+1, settings.scr_res_y-debug.tri_sel->v[i].y+1, 1, "%d", i); grConstantColorValue (0xFFFFFFFF); output (debug.tri_sel->v[i].x, settings.scr_res_y-debug.tri_sel->v[i].y, 1, "%d", i); } } // Draw the cursor debug_mouse (); grBufferSwap (1); } END: // Release all data delete [] debug.screen; TRI_INFO *tri; for (tri=debug.tri_list; tri != debug.tri_last;) { TRI_INFO *tmp = tri; tri = tri->pNext; delete [] tmp->v; delete tmp; } delete [] tri->v; delete tri; // Reset all values debug.capture = 0; debug.selected = SELECTED_TRI; debug.screen = NULL; debug.tri_list = NULL; debug.tri_last = NULL; debug.tri_sel = NULL; debug.tex_sel = 0; } // // debug_mouse - draws the debugger mouse // void debug_mouse () { grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); // Draw the cursor POINT pt; GetCursorPos (&pt); float cx = (float)pt.x; float cy = (float)pt.y; VERTEX v[4] = { { cx, cy, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, { cx+32, cy, 1, 1, 255, 0, 0, 0, 0, 0, 0 }, { cx, cy+32, 1, 1, 0, 255, 0, 0, 0, 0, 0 }, { cx+32, cy+32, 1, 1, 255, 255, 0, 0, 0, 0, 0 } }; ConvertCoordsKeep (v, 4); grTexSource(GR_TMU0, grTexMinAddress(GR_TMU0) + offset_cursor, GR_MIPMAPLEVELMASK_BOTH, &cursorTex); if (num_tmu >= 3) grTexCombine (GR_TMU2, GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE); if (num_tmu >= 2) grTexCombine (GR_TMU1, GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE); grTexCombine (GR_TMU0, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE); grDrawTriangle (&v[0], &v[1], &v[2]); grDrawTriangle (&v[1], &v[3], &v[2]); } // // debug_keys - receives debugger key input // void debug_keys () { if ((GetAsyncKeyState (VK_RIGHT) & 0x0001) && debug.tri_sel) { TRI_INFO *start = debug.tri_sel; while (debug.tri_sel->pNext != start) debug.tri_sel = debug.tri_sel->pNext; } if ((GetAsyncKeyState (VK_LEFT) & 0x0001) && debug.tri_sel) debug.tri_sel = debug.tri_sel->pNext; // Check for page changes if (GetAsyncKeyState ('1') & 0x0001) debug.page = PAGE_GENERAL; if (GetAsyncKeyState ('2') & 0x0001) debug.page = PAGE_TEX1; if (GetAsyncKeyState ('3') & 0x0001) debug.page = PAGE_TEX2; if (GetAsyncKeyState ('4') & 0x0001) debug.page = PAGE_COLORS; if (GetAsyncKeyState ('5') & 0x0001) debug.page = PAGE_FBL; if (GetAsyncKeyState ('6') & 0x0001) debug.page = PAGE_OTHERMODE_L; if (GetAsyncKeyState ('7') & 0x0001) debug.page = PAGE_OTHERMODE_H; if (GetAsyncKeyState ('8') & 0x0001) debug.page = PAGE_TEXELS; if (GetAsyncKeyState ('9') & 0x0001) debug.page = PAGE_COORDS; if (GetAsyncKeyState ('0') & 0x0001) debug.page = PAGE_TEX_INFO; if (GetAsyncKeyState ('Q') & 0x0001) debug.tmu = 0; if (GetAsyncKeyState ('W') & 0x0001) debug.tmu = 1; if (GetAsyncKeyState ('G') & 0x0001) grid = !grid; // Go to texture if (GetAsyncKeyState (VK_SPACE) & 0x0001) { int tile = -1; if (debug.page == PAGE_TEX2) tile = 1; else tile = 0; if (tile != -1) { debug.tmu = debug.tri_sel->t[tile].tmu; debug.tex_sel = debug.tri_sel->t[tile].cur_cache[debug.tmu]; debug.tex_scroll = (debug.tri_sel->t[tile].cur_cache[debug.tmu] >> 4) - 1; } } // Go to triangle if (GetAsyncKeyState (VK_LCONTROL) & 0x0001) { int count = rdp.debug_n - rdp.cache[debug.tmu][debug.tex_sel].uses - 1; if (rdp.cache[debug.tmu][debug.tex_sel].last_used == frame_count) { TRI_INFO *t = debug.tri_list; while (count && t) { t = t->pNext; count --; } debug.tri_sel = t; } else debug.tri_sel = NULL; } if (GetAsyncKeyState ('A') & 0x0001) debug.draw_mode = 0; // texture & texture alpha if (GetAsyncKeyState ('S') & 0x0001) debug.draw_mode = 1; // texture if (GetAsyncKeyState ('D') & 0x0001) debug.draw_mode = 2; // texture alpha // Check for texture scrolling if (GetAsyncKeyState (VK_DOWN) & 0x0001) debug.tex_scroll ++; if (GetAsyncKeyState (VK_UP) & 0x0001) debug.tex_scroll --; } #endif // _WIN32 // // output - output debugger text // void output (float x, float y, BOOL scale, const char *fmt, ...) { va_list ap; va_start(ap,fmt); vsprintf(out_buf, fmt, ap); va_end(ap); BYTE c,r; for (DWORD i=0; i> 5) * 16;//<< 4; VERTEX v[4] = { { SX(x), SY(768-y), 1, 1, (float)c, r+16.0f, 0, 0, {0, 0, 0, 0} }, { SX(x+8), SY(768-y), 1, 1, c+8.0f, r+16.0f, 0, 0, {0, 0, 0, 0} }, { SX(x), SY(768-y-16), 1, 1, (float)c, (float)r, 0, 0, {0, 0, 0, 0} }, { SX(x+8), SY(768-y-16), 1, 1, c+8.0f, (float)r, 0, 0, {0, 0, 0, 0} } }; if (!scale) { v[0].x = x; v[0].y = y; v[1].x = x+8; v[1].y = y; v[2].x = x; v[2].y = y-16; v[3].x = x+8; v[3].y = y-16; } ConvertCoordsKeep (v, 4); grDrawTriangle (&v[0], &v[1], &v[2]); grDrawTriangle (&v[1], &v[3], &v[2]); x+=8; } } mupen64plus-video-glide64-src-2.6.0/src/Debugger.h000066400000000000000000000101451464507525600215510ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** #define SELECTED_NONE 0x00000000 #define SELECTED_TRI 0x00000001 #define SELECTED_TEX 0x00000002 typedef struct TEX_INFO_t { DWORD cur_cache[2]; // Current cache # BYTE format; BYTE size; DWORD width, height; WORD line, wid; BYTE palette; BYTE clamp_s, clamp_t; BYTE mirror_s, mirror_t; BYTE mask_s, mask_t; BYTE shift_s, shift_t; WORD ul_s, ul_t, lr_s, lr_t; WORD t_ul_s, t_ul_t, t_lr_s, t_lr_t; float scale_s, scale_t; int tmu; } TEX_INFO; typedef struct TRI_INFO_t { DWORD nv; // Number of vertices VERTEX *v; // Vertices (2d screen coords) of the triangle, used to outline DWORD cycle1, cycle2, cycle_mode; // Combine mode at the time of rendering BYTE uncombined; // which is uncombined: 0x01=color 0x02=alpha 0x03=both DWORD geom_mode; // geometry mode flags DWORD othermode_h; // setothermode_h flags DWORD othermode_l; // setothermode_l flags DWORD tri_n; // Triangle number DWORD flags; int type; // 0-normal, 1-texrect, 2-fillrect // texture info TEX_INFO t[2]; // colors DWORD fog_color; DWORD fill_color; DWORD prim_color; DWORD blend_color; DWORD env_color; DWORD prim_lodmin, prim_lodfrac; TRI_INFO_t *pNext; } TRI_INFO; typedef struct { BOOL capture; // Capture moment for debugging? DWORD selected; // Selected object (see flags above) TRI_INFO *tri_sel; DWORD tex_scroll; // texture scrolling DWORD tex_sel; // CAPTURE INFORMATION BYTE *screen; // Screen capture TRI_INFO *tri_list; // Triangle information list TRI_INFO *tri_last; // Last in the list (first in) DWORD tmu; // tmu # DWORD draw_mode; // Page number int page; } DEBUGGER; #define PAGE_GENERAL 0 #define PAGE_TEX1 1 #define PAGE_TEX2 2 #define PAGE_COLORS 3 #define PAGE_FBL 4 #define PAGE_OTHERMODE_L 5 #define PAGE_OTHERMODE_H 6 #define PAGE_TEXELS 7 #define PAGE_COORDS 8 #define PAGE_TEX_INFO 9 #define TRI_TRIANGLE 0 #define TRI_TEXRECT 1 #define TRI_FILLRECT 2 #define TRI_BACKGROUND 3 #ifdef _WIN32 static char *tri_type[4] = { "TRIANGLE", "TEXRECT", "FILLRECT", "BACKGROUND" }; #endif // _WIN32 extern DEBUGGER debug; void debug_init (); void debug_capture (); void debug_cacheviewer (); void debug_mouse (); void debug_keys (); void output (float x, float y, BOOL scale, const char *fmt, ...); mupen64plus-video-glide64-src-2.6.0/src/DepthBufferRender.cpp000066400000000000000000000231031464507525600237140ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * Copyright (c) 2008 Günther * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // //**************************************************************** // // Software rendering into N64 depth buffer // Idea and N64 depth value format by Orkin // Polygon rasterization algorithm is taken from FATMAP2 engine by Mats Byggmastar, mri@penti.sit.fi // // Created by Gonetz, Dec 2004 // //**************************************************************** #include "Gfx1.3.h" #include "rdp.h" #include "DepthBufferRender.h" WORD * zLUT = 0; void ZLUT_init() { if (zLUT) return; zLUT = new WORD[0x40000]; for(int i=0; i<0x40000; i++) { DWORD exponent = 0; DWORD testbit = 1 << 17; while((i & testbit) && (exponent < 7)) { exponent++; testbit = 1 << (17 - exponent); } DWORD mantissa = (i >> (6 - (6 < exponent ? 6 : exponent))) & 0x7ff; zLUT[i] = (WORD)(((exponent << 11) | mantissa) << 2); } /* for(i=0; i<0x40000; i++) { int j = i + 1; WORD z = zLUT[i]; while (zLUT[i] == zLUT[j]) j++; int w = (j - i) >> 2; if (w > 0) { int k; for (k = 1; k < 4; k++) for (int t = 0; t < w; t++) zLUT[i+k*w+t] = z + k; i = j - 1; } } */ } void ZLUT_release() { delete[] zLUT; zLUT = 0; } static vertexi * max_vtx; // Max y vertex (ending vertex) static vertexi * start_vtx, * end_vtx; // First and last vertex in array static vertexi * right_vtx, * left_vtx; // Current right and left vertex static int right_height, left_height; static int right_x, right_dxdy, left_x, left_dxdy; static int left_z, left_dzdy; __inline int iceil(int x) { x += 0xffff; return (x >> 16); } __inline int imul16(int x, int y) // (x * y) >> 16 { return (((long long)x) * ((long long)y)) >> 16; } __inline int imul14(int x, int y) // (x * y) >> 14 { return (((long long)x) * ((long long)y)) >> 14; } __inline int idiv16(int x, int y) // (x << 16) / y { //x = (((long long)x) << 16) / ((long long)y); /* eax = x; ebx = y; edx = x; (x << 16) | () */ #if !defined(__GNUC__) && !defined(NO_ASM) __asm { mov eax, x mov ebx, y mov edx,eax sar edx,16 shl eax,16 idiv ebx mov x, eax } #elif !defined(NO_ASM) int reminder; asm ("idivl %[divisor]" : "=a" (x), "=d" (reminder) : [divisor] "g" (y), "d" (x >> 16), "a" (x << 16)); #else x = (((long long)x) << 16) / ((long long)y); #endif return x; } static void RightSection(void) { // Walk backwards trough the vertex array vertexi * v2, * v1 = right_vtx; if(right_vtx > start_vtx) v2 = right_vtx-1; else v2 = end_vtx; // Wrap to end of array right_vtx = v2; // v1 = top vertex // v2 = bottom vertex // Calculate number of scanlines in this section right_height = iceil(v2->y) - iceil(v1->y); if(right_height <= 0) return; // Guard against possible div overflows if(right_height > 1) { // OK, no worries, we have a section that is at least // one pixel high. Calculate slope as usual. int height = v2->y - v1->y; right_dxdy = idiv16(v2->x - v1->x, height); } else { // Height is less or equal to one pixel. // Calculate slope = width * 1/height // using 18:14 bit precision to avoid overflows. int inv_height = (0x10000 << 14) / (v2->y - v1->y); right_dxdy = imul14(v2->x - v1->x, inv_height); } // Prestep initial values int prestep = (iceil(v1->y) << 16) - v1->y; right_x = v1->x + imul16(prestep, right_dxdy); } static void LeftSection(void) { // Walk forward trough the vertex array vertexi * v2, * v1 = left_vtx; if(left_vtx < end_vtx) v2 = left_vtx+1; else v2 = start_vtx; // Wrap to start of array left_vtx = v2; // v1 = top vertex // v2 = bottom vertex // Calculate number of scanlines in this section left_height = iceil(v2->y) - iceil(v1->y); if(left_height <= 0) return; // Guard against possible div overflows if(left_height > 1) { // OK, no worries, we have a section that is at least // one pixel high. Calculate slope as usual. int height = v2->y - v1->y; left_dxdy = idiv16(v2->x - v1->x, height); left_dzdy = idiv16(v2->z - v1->z, height); } else { // Height is less or equal to one pixel. // Calculate slope = width * 1/height // using 18:14 bit precision to avoid overflows. int inv_height = (0x10000 << 14) / (v2->y - v1->y); left_dxdy = imul14(v2->x - v1->x, inv_height); left_dzdy = imul14(v2->z - v1->z, inv_height); } // Prestep initial values int prestep = (iceil(v1->y) << 16) - v1->y; left_x = v1->x + imul16(prestep, left_dxdy); left_z = v1->z + imul16(prestep, left_dzdy); } void Rasterize(vertexi * vtx, int vertices, int dzdx) { start_vtx = vtx; // First vertex in array // Search trough the vtx array to find min y, max y // and the location of these structures. vertexi * min_vtx = vtx; max_vtx = vtx; int min_y = vtx->y; int max_y = vtx->y; vtx++; for(int n=1; ny < min_y) { min_y = vtx->y; min_vtx = vtx; } else if(vtx->y > max_y) { max_y = vtx->y; max_vtx = vtx; } vtx++; } // OK, now we know where in the array we should start and // where to end while scanning the edges of the polygon left_vtx = min_vtx; // Left side starting vertex right_vtx = min_vtx; // Right side starting vertex end_vtx = vtx-1; // Last vertex in array // Search for the first usable right section do { if(right_vtx == max_vtx) return; RightSection(); } while(right_height <= 0); // Search for the first usable left section do { if(left_vtx == max_vtx) return; LeftSection(); } while(left_height <= 0); WORD * destptr = (WORD*)(gfx.RDRAM+rdp.zimg); int y1 = iceil(min_y); int shift; //destptr += iceil(min_y) * rdp.zi_width; for(;;) { int x1 = iceil(left_x); int width = iceil(right_x) - x1; if(width > 0) { // Prestep initial color intensity i if (y1 >= rdp.zi_lry) return; //if (x1+width > rdp.zi_lrx) width = rdp.zi_lrx-x1; int prestep = (x1 << 16) - left_x; int z = left_z + imul16(prestep, dzdx); // if (y1 > max_y) return; // FRDP("Depth render. x1: %d, y1: %d, width: %d\n", x1, y1, width); shift = x1 + y1*rdp.zi_width; // if (shift + width > rdp.zi_nb_pixels) // return; //draw to depth buffer int trueZ; int idx; WORD encodedZ; for (int x = 0; x < width; x++) { trueZ = z/8192; if (trueZ < 0) trueZ = 0; else if (trueZ > 0x3FFFF) trueZ = 0x3FFFF; encodedZ = zLUT[trueZ]; idx = (shift+x)^1; if(encodedZ < destptr[idx]) destptr[idx] = encodedZ; z += dzdx; } } //destptr += rdp.zi_width; y1++; // Scan the right side if(--right_height <= 0) { // End of this section? do { if(right_vtx == max_vtx) return; RightSection(); } while(right_height <= 0); } else right_x += right_dxdy; // Scan the left side if(--left_height <= 0) { // End of this section? do { if(left_vtx == max_vtx) return; LeftSection(); } while(left_height <= 0); } else { left_x += left_dxdy; left_z += left_dzdy; } } } mupen64plus-video-glide64-src-2.6.0/src/DepthBufferRender.h000066400000000000000000000037721464507525600233730ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // //**************************************************************** // // Created by Gonetz, Dec 2004 // //**************************************************************** #ifndef DEPTH_BUFFER_RENDER_H #define DEPTH_BUFFER_RENDER_H struct vertexi { long x,y; // Screen position in 16:16 bit fixed point long z; // z value in 16:16 bit fixed point }; extern WORD * zLUT; void ZLUT_init(); void ZLUT_release(); void Rasterize(vertexi * vtx, int vertices, int dzdx); #endif //DEPTH_BUFFER_RENDER_H mupen64plus-video-glide64-src-2.6.0/src/Gfx1.3.h000066400000000000000000000660771464507525600210120ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** // ** NOTE: this file has been modified from it's original version, which can be // downloaded along with Project64 ** /********************************************************************************** Common gfx plugin spec, version #1.3 maintained by zilmar (zilmar@emulation64.com) All questions or suggestions should go through the mailing list. http://www.egroups.com/group/Plugin64-Dev *********************************************************************************** Notes: ------ Setting the approprate bits in the MI_INTR_REG and calling CheckInterrupts which are both passed to the DLL in InitiateGFX will generate an Interrupt from with in the plugin. The Setting of the RSP flags and generating an SP interrupt should not be done in the plugin **********************************************************************************/ // THIS FILE IS A PRECOMPILED HEADER TO DECREASE BUILD TIME. INCLUDE ALL STANDARD // .H FILES HERE #ifndef _GFX_H_INCLUDED__ #define _GFX_H_INCLUDED__ #include "m64p.h" #if defined(WIN32) && defined(GCC) // ZIGGY ARRRRGG what a pain in the #$@$ //# include "Gfx #1.3-mangling.h" #ifdef GCC #include //#define printf(...) #endif #endif #define _WIN32_WINNT 0x0400 #ifdef _WIN32 #include #else // _WIN32 #include "winlnxdefs.h" #endif // _WIN32 #include #include #include #include // offsetof #ifndef _WIN32 #include #endif #ifdef _WIN32 #include #include #include #include #endif // _WIN32 #include #include #include #include "rdp.h" #if defined(__cplusplus) extern "C" { #endif // tooltips have an error on debug mode, this can be overcome by clicking ignore, // but I'd rather just disable tooltips altogether since nobody else should // have the debug version anyway. #ifndef _DEBUG //#ifndef __INTEL_COMPILER // tooltips don't work with intel compiler #define USE_TOOLTIPS //#endif #endif #ifndef VPDEBUG # define _FINAL_RELEASE_ #endif // #ifdef WIN32 // # define _FINAL_RELEASE_ // #else // //# define _FINAL_RELEASE_ // #endif //******** // Logging // ******************************** // ** TAKE OUT BEFORE RELEASE!!! ** //#define LOGGING // log of spec functions called //#define LOG_KEY // says "Key!!!" in the log when space bar is pressed //#define LOG_UCODE //#define ALTTAB_FIX //#define EXTREME_LOGGING // lots of logging // note that some of these things are inserted/removed // from within the code & may not be changed by this define. //#define TLUT_LOGGING // log every entry of the TLUT? // ******************************** #define FPS // fps counter able? (not enabled necessarily) #define LOGNOTKEY // Log if not pressing: #ifdef WIN32 #define LOGKEY VK_LCONTROL // this key #else #include #define LOGKEY KMOD_LCTRL inline int GetAsyncKeyState(int key) { return (SDL_GetModState() & key) != 0; } #endif #define LOG_COMMANDS // log the whole 64-bit command as (0x........, 0x........) #define CATCH_EXCEPTIONS // catch exceptions so it doesn't freeze and will report // "The gfx plugin has caused an exception" instead. #define FLUSH // flush the file buffer. slower logging, but makes sure // the command is logged before continuing (in case of // crash or exception, the log will not be cut short) #ifndef _FINAL_RELEASE_ #define RDP_LOGGING // Allow logging (will not log unless checked, but allows the option) // Logging functions will not be compiled if this is not present. //#define RDP_ERROR_LOG #endif #define FPS_FRAMES 10 // Number of frames in which to make an FPS count //#define SHOW_FULL_TEXVIEWER // shows the entire contents of the texture in the cache viewer, // usually used to debug clamping issues. // Usually enabled #define LARGE_TEXTURE_HANDLING // allow large-textured objects to be split? #ifdef ALTTAB_FIX extern HHOOK hhkLowLevelKybd; extern LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam); #endif // Simulations //#define SIMULATE_VOODOO1 //#define SIMULATE_BANSHEE //******** #ifdef EXT_LOGGING extern std::ofstream extlog; #define EXT(x) extlog.open("ext.txt",ios::app); extlog << x; extlog.close(); #else #define EXT(x) #endif #ifndef _FINAL_RELEASE_ #define UNIMP_LOG // Keep enabled, option in dialog #define BRIGHT_RED // Keep enabled, option in dialog #endif #define COLORED_DEBUGGER // ;) pretty colors #ifdef FPS extern LARGE_INTEGER perf_freq; extern LARGE_INTEGER fps_last; extern LARGE_INTEGER fps_next; extern float fps; extern DWORD fps_count; #endif // rdram mask at 0x400000 bytes (bah, not right for majora's mask) //#define BMASK 0x7FFFFF extern unsigned long BMASK; #define WMASK 0x3FFFFF #define DMASK 0x1FFFFF extern int num_tmu; extern int max_tex_size; extern long sup_mirroring; extern BOOL sup_32bit_tex; extern DWORD update_screen_count; extern DWORD resolutions[0x18][2]; //#define PERFORMANCE #ifdef PERFORMANCE extern __int64 perf_cur; extern __int64 perf_next; #endif #ifdef LOGGING extern std::ofstream loga; #define LOG(x) loga.open("log.txt",ios::app); loga << x; loga.flush(); loga.close(); #else #define LOG(x) WriteLog(M64MSG_VERBOSE, "%s", x); #endif #ifdef RDP_LOGGING extern int dumping; extern BOOL log_open; extern std::ofstream rdp_log; //#define rdp_log std::cerr; #define OPEN_RDP_LOG() EXT("OPEN_RDP_LOG ()\n"); if (settings.logging && !log_open) { /*rdp_log.open ("rdp.txt");*/ log_open=TRUE; } #define CLOSE_RDP_LOG() EXT("CLOSE_RDP_LOG ()\n"); if (settings.logging && log_open) { /*rdp_log.close ();*/ log_open=FALSE; } #ifdef LOGNOTKEY #define RDP(x) EXT("RDP (...)\n"); if (dumping && settings.logging && log_open) { if (!(GetAsyncKeyState(LOGKEY)&0x8000)) { fprintf(stderr, x);/*rdp_log << x; rdp_log.flush();*/ } } #else #define RDP(x) EXT("RDP (...)\n"); if (dumping && settings.logging && log_open) { fprintf(stderr, x);/*rdp_log << x; rdp_log.flush();*/ } #endif #else #define OPEN_RDP_LOG() #define CLOSE_RDP_LOG() #define RDP(x) #endif #ifdef RDP_ERROR_LOG extern BOOL elog_open; extern std::ofstream rdp_err; //#define rdp_err std::cerr #define OPEN_RDP_E_LOG() EXT("OPEN_RDP_E_LOG ()\n"); if (settings.elogging && !elog_open) { /*rdp_err.open ("rdp_e.txt");*/ elog_open=TRUE; } #define CLOSE_RDP_E_LOG() EXT("CLOSE_RDP_LOG ()\n"); if (settings.elogging && elog_open) { /*rdp_err.close (); */elog_open=FALSE; } #define RDP_E(x) if (dumping && settings.elogging) { FRDP_E (x); } #else #define OPEN_RDP_E_LOG() #define CLOSE_RDP_E_LOG() #define RDP_E(x) #endif #ifdef RDP_LOGGING __inline void FRDP (const char *fmt, ...) { #ifdef RDP_LOGGING if (!dumping || !settings.logging || !log_open) return; #ifdef LOGNOTKEY if (GetAsyncKeyState(LOGKEY)&0x8000) return; #endif va_list ap; va_start(ap, fmt); vsprintf(out_buf, fmt, ap); RDP (out_buf); va_end(ap); #endif } __inline void FRDP_E (const char *fmt, ...) { #ifdef RDP_ERROR_LOG if (!dumping || !settings.elogging || !elog_open) return; #ifdef LOGNOTKEY if (GetAsyncKeyState(LOGKEY)&0x8000) return; #endif sprintf (out_buf, "%08x: (%08x, %08x) ", rdp.pc[rdp.pc_i]-8, rdp.cmd0, rdp.cmd1); rdp_err << out_buf; va_list ap2; va_start(ap2, fmt); vsprintf(out_buf, fmt, ap2); // rdp_err << out_buf; // rdp_err.flush(); fprintf(stderr, out_buf); va_end(ap2); #endif } #else #ifndef GCC #define FRDP(...) #define FRDP_E(...) #else // _WIN32 inline void FRDP (const char *fmt, ...) {} inline void FRDP_E (const char *fmt, ...) {} #endif // _WIN32 #endif extern BOOL fullscreen; extern BOOL romopen; extern BOOL to_fullscreen; extern BOOL debugging; extern HINSTANCE hInstance; extern BOOL evoodoo; extern BOOL ev_fullscreen; extern BOOL exception; extern PROPSHEETHEADER m_PropSheet; extern PROPSHEETPAGE m_psp[3]; BOOL InitGfx (BOOL); void ReleaseGfx (); void DrawFrameBuffer (); // The highest 8 bits are the segment # (1-16), and the lower 24 bits are the offset to // add to it. __inline DWORD segoffset (DWORD so) { return (rdp.segment[(so>>24)&0x0f] + (so&BMASK))&BMASK; } /* Plugin types */ #define PLUGIN_TYPE_GFX 2 //TODO: remove //#define EXPORT __declspec(dllexport) //#define CALL _cdecl /***** Structures *****/ typedef struct { WORD Version; /* Set to 0x0103 */ WORD Type; /* Set to PLUGIN_TYPE_GFX */ char Name[100]; /* Name of the DLL */ /* If DLL supports memory these memory options then set them to TRUE or FALSE if it does not support it */ BOOL NormalMemory; /* a normal BYTE array */ BOOL MemoryBswaped; /* a normal BYTE array where the memory has been pre bswap on a dword (32 bits) boundry */ } PLUGIN_INFO; #if 0 //TODO: remove typedef struct { HWND hWnd; /* Render window */ HWND hStatusBar; /* if render window does not have a status bar then this is NULL */ BOOL MemoryBswaped; // If this is set to TRUE, then the memory has been pre // bswap on a dword (32 bits) boundry // eg. the first 8 bytes are stored like this: // 4 3 2 1 8 7 6 5 BYTE * HEADER; // This is the rom header (first 40h bytes of the rom // This will be in the same memory format as the rest of the memory. BYTE * RDRAM; BYTE * DMEM; BYTE * IMEM; DWORD * MI_INTR_REG; DWORD * DPC_START_REG; DWORD * DPC_END_REG; DWORD * DPC_CURRENT_REG; DWORD * DPC_STATUS_REG; DWORD * DPC_CLOCK_REG; DWORD * DPC_BUFBUSY_REG; DWORD * DPC_PIPEBUSY_REG; DWORD * DPC_TMEM_REG; DWORD * VI_STATUS_REG; DWORD * VI_ORIGIN_REG; DWORD * VI_WIDTH_REG; DWORD * VI_INTR_REG; DWORD * VI_V_CURRENT_LINE_REG; DWORD * VI_TIMING_REG; DWORD * VI_V_SYNC_REG; DWORD * VI_H_SYNC_REG; DWORD * VI_LEAP_REG; DWORD * VI_H_START_REG; DWORD * VI_V_START_REG; DWORD * VI_V_BURST_REG; DWORD * VI_X_SCALE_REG; DWORD * VI_Y_SCALE_REG; void (*CheckInterrupts)( void ); } GFX_INFO; #endif extern GFX_INFO gfx; extern BOOL no_dlist; typedef GrContext_t (FX_CALL *GRWINOPENEXT)( FxU32 hWnd, GrScreenResolution_t resolution, GrScreenRefresh_t refresh, GrColorFormat_t format, GrOriginLocation_t origin, GrPixelFormat_t pixelformat, int nColBuffers, int nAuxBuffers) ; typedef void (FX_CALL *GRTEXBUFFEREXT)( GrChipID_t tmu, FxU32 startAddress, GrLOD_t lodmin, GrLOD_t lodmax, GrAspectRatio_t aspect, GrTextureFormat_t fmt, FxU32 evenOdd) ; typedef void (FX_CALL *GRAUXBUFFEREXT)( GrBuffer_t buffer ) ; typedef void (FX_CALL *GRCOLORCOMBINEEXT) (GrCCUColor_t a, GrCombineMode_t a_mode, GrCCUColor_t b, GrCombineMode_t b_mode, GrCCUColor_t c, FxBool c_invert, GrCCUColor_t d, FxBool d_invert, FxU32 shift, FxBool invert) ; typedef void (FX_CALL *GRTEXCOLORCOMBINEEXT) (GrChipID_t tmu, GrTCCUColor_t a, GrCombineMode_t a_mode, GrTCCUColor_t b, GrCombineMode_t b_mode, GrTCCUColor_t c, FxBool c_invert, GrTCCUColor_t d, FxBool d_invert, FxU32 shift, FxBool invert); typedef void (FX_CALL *GRCONSTANTCOLORVALUEEXT) (GrChipID_t tmu, GrColor_t value); typedef void (FX_CALL *GRSTIPPLE)( FxI32 mode) ; typedef void (FX_CALL *GRCONFIGWRAPPEREXT)(HINSTANCE instance, HWND hwnd); typedef GrScreenResolution_t (FX_CALL *GRWRAPPERFULLSCREENRESOLUTIONEXT)(); // ZIGGY framebuffer copy extension // allow to copy the depth or color buffer from back/front to front/back // (GL has separate back and front depth buffer, unlike glide, so this extension // makes sense only in a wrapper) #define GR_FBCOPY_MODE_DEPTH 0 #define GR_FBCOPY_MODE_COLOR 1 #define GR_FBCOPY_BUFFER_BACK 0 #define GR_FBCOPY_BUFFER_FRONT 1 typedef void (FX_CALL *GRFRAMEBUFFERCOPYEXT)(int x, int y, int w, int h, int buffer_from, int buffer_to, int mode); extern GRFRAMEBUFFERCOPYEXT grFramebufferCopyExt; extern GRTEXBUFFEREXT grTextureBufferExt; extern GRTEXBUFFEREXT grTextureAuxBufferExt; extern GRAUXBUFFEREXT grAuxBufferExt; extern GRSTIPPLE grStippleModeExt; extern GRSTIPPLE grStipplePatternExt; #ifndef GR_STIPPLE_DISABLE #define GR_STIPPLE_DISABLE 0x0 #define GR_STIPPLE_PATTERN 0x1 #define GR_STIPPLE_ROTATE 0x2 #endif void ReadSettings (); void ReadSpecialSettings (const char name[21]); void WriteSettings (); #if 0 //TODO: remove /****************************************************************** Function: CaptureScreen Purpose: This function dumps the current frame to a file input: pointer to the directory to save the file to output: none *******************************************************************/ EXPORT void CALL CaptureScreen ( char * Directory ); /****************************************************************** Function: ChangeWindow Purpose: to change the window between fullscreen and window mode. If the window was in fullscreen this should change the screen to window mode and vice vesa. input: none output: none *******************************************************************/ EXPORT void CALL ChangeWindow (void); /****************************************************************** Function: CloseDLL Purpose: This function is called when the emulator is closing down allowing the dll to de-initialise. input: none output: none *******************************************************************/ EXPORT void CALL CloseDLL (void); /****************************************************************** Function: DllAbout Purpose: This function is optional function that is provided to give further information about the DLL. input: a handle to the window that calls this function output: none *******************************************************************/ EXPORT void CALL DllAbout ( HWND hParent ); /****************************************************************** Function: DllConfig Purpose: This function is optional function that is provided to allow the user to configure the dll input: a handle to the window that calls this function output: none *******************************************************************/ EXPORT void CALL DllConfig ( HWND hParent ); /****************************************************************** Function: DllTest Purpose: This function is optional function that is provided to allow the user to test the dll input: a handle to the window that calls this function output: none *******************************************************************/ EXPORT void CALL DllTest ( HWND hParent ); EXPORT void CALL ReadScreen(void **dest, int *width, int *height); /****************************************************************** Function: DrawScreen Purpose: This function is called when the emulator receives a WM_PAINT message. This allows the gfx to fit in when it is being used in the desktop. input: none output: none *******************************************************************/ EXPORT void CALL DrawScreen (void); /****************************************************************** Function: GetDllInfo Purpose: This function allows the emulator to gather information about the dll by filling in the PluginInfo structure. input: a pointer to a PLUGIN_INFO stucture that needs to be filled by the function. (see def above) output: none *******************************************************************/ EXPORT void CALL GetDllInfo ( PLUGIN_INFO * PluginInfo ); /****************************************************************** Function: InitiateGFX Purpose: This function is called when the DLL is started to give information from the emulator that the n64 graphics uses. This is not called from the emulation thread. Input: Gfx_Info is passed to this function which is defined above. Output: TRUE on success FALSE on failure to initialise ** note on interrupts **: To generate an interrupt set the appropriate bit in MI_INTR_REG and then call the function CheckInterrupts to tell the emulator that there is a waiting interrupt. *******************************************************************/ EXPORT BOOL CALL InitiateGFX (GFX_INFO Gfx_Info); /****************************************************************** Function: MoveScreen Purpose: This function is called in response to the emulator receiving a WM_MOVE passing the xpos and ypos passed from that message. input: xpos - the x-coordinate of the upper-left corner of the client area of the window. ypos - y-coordinate of the upper-left corner of the client area of the window. output: none *******************************************************************/ EXPORT void CALL MoveScreen (int xpos, int ypos); /****************************************************************** Function: ProcessDList Purpose: This function is called when there is a Dlist to be processed. (High level GFX list) input: none output: none *******************************************************************/ EXPORT void CALL ProcessDList(void); /****************************************************************** Function: ProcessRDPList Purpose: This function is called when there is a Dlist to be processed. (Low level GFX list) input: none output: none *******************************************************************/ EXPORT void CALL ProcessRDPList(void); /****************************************************************** Function: RomClosed Purpose: This function is called when a rom is closed. input: none output: none *******************************************************************/ EXPORT void CALL RomClosed (void); /****************************************************************** Function: RomOpen Purpose: This function is called when a rom is open. (from the emulation thread) input: none output: none *******************************************************************/ EXPORT void CALL RomOpen (void); /****************************************************************** Function: ShowCFB Purpose: Useally once Dlists are started being displayed, cfb is ignored. This function tells the dll to start displaying them again. input: none output: none *******************************************************************/ EXPORT void CALL ShowCFB (void); /****************************************************************** Function: UpdateScreen Purpose: This function is called in response to a vsync of the screen were the VI bit in MI_INTR_REG has already been set input: none output: none *******************************************************************/ EXPORT void CALL UpdateScreen (void); /****************************************************************** Function: ViStatusChanged Purpose: This function is called to notify the dll that the ViStatus registers value has been changed. input: none output: none *******************************************************************/ EXPORT void CALL ViStatusChanged (void); /****************************************************************** Function: ViWidthChanged Purpose: This function is called to notify the dll that the ViWidth registers value has been changed. input: none output: none *******************************************************************/ EXPORT void CALL ViWidthChanged (void); /****************************************************************** Function: FrameBufferWrite Purpose: This function is called to notify the dll that the frame buffer has been modified by CPU at the given address. input: addr rdram address val val size 1 = BYTE, 2 = WORD, 4 = DWORD output: none *******************************************************************/ EXPORT void CALL FBWrite(DWORD, DWORD); typedef struct { DWORD addr; DWORD val; DWORD size; // 1 = BYTE, 2 = WORD, 4=DWORD } FrameBufferModifyEntry; /****************************************************************** Function: FrameBufferWriteList Purpose: This function is called to notify the dll that the frame buffer has been modified by CPU at the given address. input: FrameBufferModifyEntry *plist size = size of the plist, max = 1024 output: none *******************************************************************/ EXPORT void CALL FBWList(FrameBufferModifyEntry *plist, DWORD size); /****************************************************************** Function: FrameBufferRead Purpose: This function is called to notify the dll that the frame buffer memory is beening read at the given address. DLL should copy content from its render buffer to the frame buffer in N64 RDRAM DLL is responsible to maintain its own frame buffer memory addr list DLL should copy 4KB block content back to RDRAM frame buffer. Emulator should not call this function again if other memory is read within the same 4KB range input: addr rdram address val val size 1 = BYTE, 2 = WORD, 4 = DWORD output: none *******************************************************************/ EXPORT void CALL FBRead(DWORD addr); /************************************************************************ Function: FBGetFrameBufferInfo Purpose: This function is called by the emulator core to retrieve depth buffer information from the video plugin in order to be able to notify the video plugin about CPU depth buffer read/write operations size: = 1 byte = 2 word (16 bit) <-- this is N64 default depth buffer format = 4 dword (32 bit) when depth buffer information is not available yet, set all values in the FrameBufferInfo structure to 0 input: FrameBufferInfo *pinfo pinfo is pointed to a FrameBufferInfo structure which to be filled in by this function output: Values are return in the FrameBufferInfo structure ************************************************************************/ EXPORT void CALL FBGetFrameBufferInfo(void *pinfo); /****************************************************************** NOTE: THIS HAS BEEN ADDED FOR MUPEN64PLUS AND IS NOT PART OF THE ORIGINAL SPEC Function: SetConfigDir Purpose: To pass the location where config files should be read/ written to. input: path to config directory output: none *******************************************************************/ EXPORT void CALL SetConfigDir( char *configDir ); /****************************************************************** NOTE: THIS HAS BEEN ADDED FOR MUPEN64PLUS AND IS NOT PART OF THE ORIGINAL SPEC Function: SetRenderingCallback Purpose: Allows emulator to register a callback function that will be called by the graphics plugin just before the the frame buffers are swapped. This was added as a way for the emulator to draw emulator- specific things to the screen, e.g. On-screen display. input: pointer to callback function. The function expects to receive the current window width and height. output: none *******************************************************************/ EXPORT void CALL SetRenderingCallback(void (*callback)()); #endif #if defined(__cplusplus) } #endif #endif //_GFX_H_INCLUDED__ mupen64plus-video-glide64-src-2.6.0/src/INSTALL000066400000000000000000000002671464507525600207110ustar00rootroot00000000000000For Linux : Just type "make" and install the Glide64.so file that should be hopefully produced into the plugins directory of the emulator. For FreeBSD : Instead, use "gmake", also mupen64plus-video-glide64-src-2.6.0/src/Ini.cpp000066400000000000000000000315061464507525600211030ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** // INI code v1.1 #define M64P_PLUGIN_PROTOTYPES 1 #include "m64p_types.h" #include "m64p_plugin.h" #include "m64p_config.h" #include "m64p_vidext.h" #include "Ini.h" #include "Gfx1.3.h" #include #ifndef _WIN32 #include #include #include #include #endif // _WIN32 #include #ifndef _WIN32 #include #endif #ifdef _WIN32 #define PATH_MAX _MAX_PATH #endif /* PATH_MAX only may be defined by limits.h */ #ifndef PATH_MAX #define PATH_MAX 4096 #endif FILE *ini; int sectionstart; int last_line; // last good line int last_line_ret; // last line ended in return? WORD cr = 0x0A0D; static char configdir[PATH_MAX] = {0}; BOOL INI_Open () { // Get the path of the dll, ex: C:\Games\Project64\Plugin\Glide64.dll char path[PATH_MAX]; if(strlen(configdir) > 0) { strncpy(path, configdir, PATH_MAX); // make sure there's a trailing '/' //if(path[strlen(path)-1] != '/') // strncat(path, "/", PATH_MAX - strlen(path)); } else { #ifdef _WIN32 GetModuleFileName (hInstance, path, PATH_MAX); #else // _WIN32 # ifdef __FreeBSD__ int n = readlink("/proc/curproc/files", path, PATH_MAX); #else int n = readlink("/proc/self/exe", path, PATH_MAX); #endif if (n == -1) strcpy(path, "./"); else { char path2[PATH_MAX]; int i; path[n] = '\0'; strcpy(path2, path); for (i=strlen(path2)-1; i>0; i--) { if(path2[i] == '/') break; } if(i == 0) strcpy(path, "./"); else { DIR *dir; struct dirent *entry; int gooddir = 0; path2[i+1] = '\0'; dir = opendir(path2); while((entry = readdir(dir)) != NULL) { if(!strcmp(entry->d_name, "plugins")) gooddir = 1; } closedir(dir); if(!gooddir) strcpy(path, "./"); } } #endif // _WIN32 // Find the previous backslash int i; for (i=strlen(path)-1; i>0; i--) { #ifdef _WIN32 if (path[i] == '\\') #else // _WIN32 if (path[i] == '/') #endif // _WIN32 break; } if (i == 0) return FALSE; path[i+1] = 0; #ifndef _WIN32 strcat(path, "plugins/"); #endif // _WIN32 } //strncat (path, "Glide64.ini", PATH_MAX - strlen(path)); WriteLog(M64MSG_INFO, "opening %s\n", path); // Open the file ini = fopen (path, "rb"); if (ini == NULL) { WriteLog(M64MSG_ERROR, "Could not find Glide64.ini!"); return FALSE; /* ini = fopen (path, "w+b"); if (ini == NULL) { return FALSE; } */ } sectionstart = 0; last_line = 0; last_line_ret = 1; return TRUE; } void INI_Close () { //if (ini) // fclose(ini); } void INI_InsertSpace(int space) { // Since there is no good way to normally insert to or delete from a certain location in // a file, this function was added. It will insert (or delete) space bytes at the // current location. // note: negative count means delete char chunk[2048]; int len, file, start_pos, cur_pos; #ifdef _WIN32 file = _fileno(ini); #else // _WIN32 file = fileno(ini); #endif // _WIN32 start_pos = ftell(ini); fseek(ini,0,SEEK_END); // if adding, extend the file if (space > 0) #ifdef _WIN32 _chsize (file, _filelength(file)+space); #else // _WIN32 { int t1 = ftell(ini); fseek(ini, 0L, SEEK_END); int t2 = ftell(ini); fseek(ini, t1, SEEK_SET); ftruncate(file, t2+space); } #endif // _WIN32 while (1) { cur_pos = ftell(ini); len = cur_pos - start_pos; if (len == 0) break; if (len > 2048) len = 2048; fseek (ini,-len,SEEK_CUR); fread (chunk,1,len,ini); fseek (ini,-len+space,SEEK_CUR); fwrite (chunk,1,len,ini); fseek (ini,-len-space,SEEK_CUR); } // if deleted, make the file shorter if (space < 0) #ifdef _WIN32 _chsize (file, _filelength(file)+space); #else // _WIN32 { int t1 = ftell(ini); fseek(ini, 0L, SEEK_END); int t2 = ftell(ini); fseek(ini, t1, SEEK_SET); ftruncate(file, t2+space); } #endif // _WIN32 } BOOL INI_FindSection (const char *sectionname, BOOL create) { if (ini == NULL) return FALSE; char line[256], section[64]; char *p; int i, sectionfound, ret; rewind (ini); last_line = 0; sectionfound = 0; while(!feof(ini)) { ret = 0; *line=0; fgets(line,255,ini); // remove enter i=strlen(line); // ZIGGY there was a bug here if EOL was unix like on a short line (i.e. a line // with just EOL), it would write into line[-1] if(i>=1 && line[i-1]==0xa) { ret=1; line[i-1]=0; if (i>=2 && line[i-2]==0xd) line[i-2]=0; } // remove comments p=line; while(*p) { if (p[0]=='/' && p[1]=='/') { p[0]=0; break; } p++; } // skip starting space p=line; while(*p<=' ' && *p) p++; // empty line if(!*p) continue; last_line=ftell(ini); // where to add if not found last_line_ret = ret; if(*p!='[') continue; p++; for (i=0;i<63;i++) { if(*p==']' || !*p) break; section[i]=*p++; } section[i]=0; #ifdef _WIN32 if(!stricmp(section,sectionname)) #else // _WIN32 if (!strcasecmp(section,sectionname)) #endif // _WIN32 { sectionstart=ftell(ini); sectionfound=1; return TRUE; } } if (!sectionfound && create) { // create the section fseek(ini,last_line,SEEK_SET); INI_InsertSpace ((!last_line_ret) * 2 + 6 + strlen(sectionname)); if (!last_line_ret) fwrite (&cr, 1, 2, ini); fwrite (&cr, 1, 2, ini); sprintf (section, "[%s]", sectionname); fwrite (section, 1, strlen(section), ini); fwrite (&cr, 1, 2, ini); sectionstart = ftell(ini); last_line = sectionstart; last_line_ret = 1; return TRUE; } return FALSE; } // Reads the value of item 'itemname' as a string. const char *INI_ReadString (const char *itemname, char *value, const char *def_value, BOOL create) { char line[256], name[64]; char *p, *n; int ret, i; *value = 0; fseek(ini,sectionstart,SEEK_SET); while(!feof(ini)) { ret = 0; *line=0; fgets(line,255,ini); // remove enter i=strlen(line); // ZIGGY there was a bug here if EOL was unix like on a short line (i.e. a line // with just EOL), it would write into line[-1] // OLD CODE : if(line[i-1]=='\n') ret=1, line[i-2]=0; if(i>=1 && line[i-1]==0xa) { ret=1; line[i-1]=0; if (i>=2 && line[i-2]==0xd) line[i-2]=0; } // remove comments p=line; while(*p) { if (p[0]==';') { p[0]=0; break; } p++; } // skip starting space p=line; while(*p<=' ' && *p) p++; // empty line if(!*p) continue; // new section if(*p=='[') break; last_line=ftell(ini); // where to add if not found last_line_ret = ret; // read name n = name; while(*p && *p!='=' && *p>' ') *n++ = *p++; *n = 0; #ifdef _WIN32 if(!stricmp(name,itemname)) #else // _WIN32 if(!strcasecmp(name,itemname)) #endif // _WIN32 { // skip spaces/equal sign while(*p<=' ' || *p=='=') p++; // read value n = value; while(*p) *n++ = *p++; // remove trailing spaces while (*(n-1) == ' ') n--; *n=0; return value; } } // uh-oh, not found. we need to create if (create) { fseek(ini,last_line,SEEK_SET); INI_InsertSpace ((!last_line_ret) * 2 + strlen(itemname) + strlen(def_value) + 5); if (!last_line_ret) fwrite (&cr, 1, 2, ini); sprintf (line, "%s = %s", itemname, def_value); fwrite (line, 1, strlen(line), ini); fwrite (&cr, 1, 2, ini); last_line = ftell(ini); last_line_ret = 1; } strcpy (value, def_value); return value; } // Reads the value of item 'itemname' as a string. void INI_WriteString (const char *itemname, const char *value) { char line[256], name[64]; char *p, *n; int ret, i; fseek(ini,sectionstart,SEEK_SET); while(!feof(ini)) { ret = 0; *line=0; fgets(line,255,ini); // remove enter i=strlen(line); // ZIGGY there was a bug here if EOL was unix like on a short line (i.e. a line // with just EOL), it would write into line[-1] // OLD CODE : if(line[i-1]=='\n') ret=1, line[i-2]=0; if(i>=1 && line[i-1]==0xa) { ret=1; line[i-1]=0; if (i>=2 && line[i-2]==0xd) line[i-2]=0; } // remove comments p=line; while(*p) { if (p[0]=='/' && p[1]=='/') { p[0]=0; break; } p++; } // skip starting space p=line; while(*p<=' ' && *p) p++; // empty line if(!*p) continue; // new section if(*p=='[') break; last_line=ftell(ini); // where to add if not found last_line_ret = ret; // read name n = name; while(*p && *p!='=' && *p>' ') *n++ = *p++; *n = 0; #ifdef _WIN32 if(!stricmp(name,itemname)) #else // _WIN32 if(!strcasecmp(name,itemname)) #endif // _WIN32 { INI_InsertSpace (-i + (strlen(itemname) + strlen(value) + 5)); sprintf (line, "%s = %s", itemname, value); fseek (ini, -i, SEEK_CUR); fwrite (line, 1, strlen(line), ini); fwrite (&cr, 1, 2, ini); last_line = ftell(ini); last_line_ret = 1; return; } } // uh-oh, not found. we need to create fseek(ini,last_line,SEEK_SET); INI_InsertSpace ((!last_line_ret) * 2 + strlen(itemname) + strlen(value) + 5); if (!last_line_ret) fwrite (&cr, 1, 2, ini); sprintf (line, "%s = %s", itemname, value); fwrite (line, 1, strlen(line), ini); fwrite (&cr, 1, 2, ini); last_line = ftell(ini); last_line_ret = 1; return; } int INI_ReadInt (const char *itemname, int def_value, BOOL create) { if (ini == NULL) return def_value; char value[64], def[64]; #ifdef _WIN32 _itoa (def_value, def, 10); #else // _WIN32 sprintf(def, "%d", def_value); #endif // _WIN32 INI_ReadString (itemname, value, def, create); return atoi (value); } void INI_WriteInt (const char *itemname, int value) { char valstr[64]; #ifdef _WIN32 _itoa (value, valstr, 10); #else // _WIN32 sprintf(valstr, "%d", value); #endif // _WIN32 INI_WriteString (itemname, valstr); } void SetConfigDir( const char *configDir ) { strncpy(configdir, configDir, PATH_MAX); } mupen64plus-video-glide64-src-2.6.0/src/Ini.h000066400000000000000000000042331464507525600205450ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** #include #include "winlnxdefs.h" BOOL INI_Open (); void INI_Close (); void INI_InsertSpace(int space); BOOL INI_FindSection (const char *sectionname, BOOL create=TRUE); const char *INI_ReadString (const char *itemname, const char *value, const char *def_value, BOOL create=TRUE); void INI_WriteString (const char *itemname, const char *value); int INI_ReadInt (const char *itemname, int def_value, BOOL create=TRUE); void INI_WriteInt (const char *itemname, int value); void SetConfigDir( const char *configDir ); mupen64plus-video-glide64-src-2.6.0/src/LICENSES000066400000000000000000000017561464507525600210140ustar00rootroot00000000000000The included data files: cursor.tex font.tex are Copyright (C) 2002 by Dave2001. These files are licensed under the GNU General Public License, version 2 or later. Please see the gpl.txt file for full license details. * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA mupen64plus-video-glide64-src-2.6.0/src/Main.cpp000066400000000000000000001633501464507525600212530ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** #include "Util.h" #include "3dmath.h" #include "Debugger.h" #include "Combine.h" #include "Ini.h" #include "Config.h" #include "TexCache.h" #include "CRC.h" #include "DepthBufferRender.h" #include #include #ifndef _WIN32 #include #endif #include "osal_dynamiclib.h" #define G64_VERSION "Mupen64Plus" #define RELTIME "Date: " __DATE__ " Time: " __TIME__ #ifdef EXT_LOGGING std::ofstream extlog; #endif #ifdef LOGGING std::ofstream loga; #endif #ifdef RDP_LOGGING BOOL log_open = FALSE; std::ofstream rdp_log; #endif #ifdef RDP_ERROR_LOG BOOL elog_open = FALSE; std::ofstream rdp_err; #endif GFX_INFO gfx; /* definitions of pointers to Core config functions */ ptr_ConfigOpenSection ConfigOpenSection = NULL; ptr_ConfigSetParameter ConfigSetParameter = NULL; ptr_ConfigGetParameter ConfigGetParameter = NULL; ptr_ConfigGetParameterHelp ConfigGetParameterHelp = NULL; ptr_ConfigSetDefaultInt ConfigSetDefaultInt = NULL; ptr_ConfigSetDefaultFloat ConfigSetDefaultFloat = NULL; ptr_ConfigSetDefaultBool ConfigSetDefaultBool = NULL; ptr_ConfigSetDefaultString ConfigSetDefaultString = NULL; ptr_ConfigGetParamInt ConfigGetParamInt = NULL; ptr_ConfigGetParamFloat ConfigGetParamFloat = NULL; ptr_ConfigGetParamBool ConfigGetParamBool = NULL; ptr_ConfigGetParamString ConfigGetParamString = NULL; ptr_ConfigGetSharedDataFilepath ConfigGetSharedDataFilepath = NULL; ptr_ConfigGetUserConfigPath ConfigGetUserConfigPath = NULL; ptr_ConfigGetUserDataPath ConfigGetUserDataPath = NULL; ptr_ConfigGetUserCachePath ConfigGetUserCachePath = NULL; /* definitions of pointers to Core video extension functions */ ptr_VidExt_Init CoreVideo_Init = NULL; ptr_VidExt_Quit CoreVideo_Quit = NULL; ptr_VidExt_ListFullscreenModes CoreVideo_ListFullscreenModes = NULL; ptr_VidExt_SetVideoMode CoreVideo_SetVideoMode = NULL; ptr_VidExt_SetCaption CoreVideo_SetCaption = NULL; ptr_VidExt_ToggleFullScreen CoreVideo_ToggleFullScreen = NULL; ptr_VidExt_ResizeWindow CoreVideo_ResizeWindow = NULL; ptr_VidExt_GL_GetProcAddress CoreVideo_GL_GetProcAddress = NULL; ptr_VidExt_GL_SetAttribute CoreVideo_GL_SetAttribute = NULL; ptr_VidExt_GL_SwapBuffers CoreVideo_GL_SwapBuffers = NULL; BOOL to_fullscreen = FALSE; BOOL fullscreen = FALSE; BOOL romopen = FALSE; GrContext_t gfx_context = 0; BOOL debugging = FALSE; HINSTANCE hInstance = NULL; BOOL exception = FALSE; BOOL evoodoo = 0; BOOL ev_fullscreen = 0; int num_tmu; int max_tex_size; long sup_mirroring; BOOL sup_32bit_tex = FALSE; #ifdef ALTTAB_FIX HHOOK hhkLowLevelKybd = NULL; LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam); #endif #ifdef PERFORMANCE __int64 perf_cur; __int64 perf_next; #endif #ifdef FPS LARGE_INTEGER perf_freq; LARGE_INTEGER fps_last; LARGE_INTEGER fps_next; float fps = 0.0f; DWORD fps_count = 0; DWORD vi_count = 0; float vi = 0.0f; DWORD region = 0; float ntsc_percent = 0.0f; float pal_percent = 0.0f; #endif // Resolutions, MUST be in the correct order (SST1VID.H) DWORD resolutions[0x18][2] = { { 320, 200 }, { 320, 240 }, { 400, 256 }, { 512, 384 }, { 640, 200 }, { 640, 350 }, { 640, 400 }, { 640, 480 }, { 800, 600 }, { 960, 720 }, { 856, 480 }, { 512, 256 }, { 1024, 768 }, { 1280, 1024 }, { 1600, 1200 }, { 400, 300 }, // 0x10 { 1152, 864 }, { 1280, 960 }, { 1600, 1024 }, { 1792, 1344 }, { 1856, 1392 }, { 1920, 1440 }, { 2048, 1536 }, { 2048, 2048 } }; // ref rate // 60=0x0, 70=0x1, 72=0x2, 75=0x3, 80=0x4, 90=0x5, 100=0x6, 85=0x7, 120=0x8, none=0xff unsigned long BMASK = 0x7FFFFF; // Reality display processor structure RDP rdp; SETTINGS settings = { FALSE, 640, 480, GR_RESOLUTION_640x480, 0 }; HOTKEY_INFO hotkey_info; GrTexInfo fontTex; GrTexInfo cursorTex; DWORD offset_font = 0; DWORD offset_cursor = 0; DWORD offset_textures = 0; DWORD offset_texbuf1 = 0; BOOL capture_screen = 0; char capture_path[256]; void (*renderCallback)(int) = NULL; static void (*l_DebugCallback)(void *, int, const char *) = NULL; static void *l_DebugCallContext = NULL; void WriteLog(m64p_msg_level level, const char *msg, ...) { char buf[1024]; va_list args; va_start(args, msg); vsnprintf(buf, 1023, msg, args); buf[1023]='\0'; va_end(args); if (l_DebugCallback) { l_DebugCallback(l_DebugCallContext, level, buf); } } void ChangeSize () { float res_scl_x = (float)settings.res_x / 320.0f; float res_scl_y = (float)settings.res_y / 240.0f; DWORD scale_x = *gfx.VI_X_SCALE_REG & 0xFFF; if (!scale_x) return; DWORD scale_y = *gfx.VI_Y_SCALE_REG & 0xFFF; if (!scale_y) return; float fscale_x = (float)scale_x / 1024.0f; float fscale_y = (float)scale_y / 1024.0f; DWORD dwHStartReg = *gfx.VI_H_START_REG; DWORD dwVStartReg = *gfx.VI_V_START_REG; DWORD hstart = dwHStartReg >> 16; DWORD hend = dwHStartReg & 0xFFFF; // dunno... but sometimes this happens if (hend == hstart) hend = (int)(*gfx.VI_WIDTH_REG / fscale_x); DWORD vstart = dwVStartReg >> 16; DWORD vend = dwVStartReg & 0xFFFF; sprintf (out_buf, "hstart: %d, hend: %d, vstart: %d, vend: %d\n", hstart, hend, vstart, vend); LOG (out_buf); rdp.vi_width = (hend - hstart) * fscale_x; rdp.vi_height = (vend - vstart)/2 * fscale_y; sprintf (out_buf, "size: %d x %d\n", (int)rdp.vi_width, (int)rdp.vi_height); LOG (out_buf); if (region == 0) { if (*gfx.VI_WIDTH_REG == 0x500) // 1280x960 is different... needs height * 2 { rdp.scale_x = res_scl_x * (320.0f / rdp.vi_width); rdp.scale_y = res_scl_y * (120.0f / rdp.vi_height); } else { rdp.scale_x = res_scl_x * (320.0f / rdp.vi_width); rdp.scale_y = res_scl_y * (240.0f / rdp.vi_height); } } else { // odd... but pal games seem to want 230 as height... if (*gfx.VI_WIDTH_REG == 0x500) // 1280x960 is different... needs height * 2 { // NOT SURE ABOUT PAL HERE, DON'T HAVE PAL MEGAMAN TO TRY rdp.scale_x = res_scl_x * (320.0f / rdp.vi_width); // VP changed to 120 rdp.scale_y = res_scl_y * (120.0f / rdp.vi_height); //rdp.scale_y = res_scl_y * (115.0f / rdp.vi_height); } else { rdp.scale_x = res_scl_x * (320.0f / rdp.vi_width); // VP changed to 240 rdp.scale_y = res_scl_y * (240.0f / rdp.vi_height); //rdp.scale_y = res_scl_y * (230.0f / rdp.vi_height); } } rdp.offset_x = settings.offset_x * res_scl_x; rdp.offset_y = settings.offset_y * res_scl_y; if (settings.scale_x != 0) rdp.scale_x *= (settings.scale_x / 100000.0f); if (settings.scale_y != 0) rdp.scale_y *= (settings.scale_y / 100000.0f); rdp.scale_1024 = settings.scr_res_x / 1024.0f; rdp.scale_768 = settings.scr_res_y / 768.0f; rdp.scissor_o.ul_x = 0; rdp.scissor_o.ul_y = 0; rdp.scissor_o.lr_x = (DWORD)rdp.vi_width; rdp.scissor_o.lr_y = (DWORD)rdp.vi_height; rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR; } void ReadSettings () { // LOG("ReadSettings\n"); if (!Config_Open()) { WriteLog(M64MSG_ERROR, "Could not open configuration!"); return; } settings.card_id = (BYTE)Config_ReadInt ("card_id", "Card ID", 0, TRUE, FALSE); settings.depth_bias = -Config_ReadInt ("depth_bias", "Depth bias level", 0, TRUE, FALSE); PackedScreenResolution packedResolution = Config_ReadScreenSettings(); settings.res_data = (DWORD) packedResolution.resolution; settings.scr_res_x = settings.res_x = packedResolution.width; settings.scr_res_y = settings.res_y = packedResolution.height; settings.autodetect_ucode = (BOOL)Config_ReadInt ("autodetect_ucode", "Auto-detect microcode", 1); settings.ucode = (DWORD)Config_ReadInt ("ucode", "Force microcode", 2, TRUE, FALSE); settings.wireframe = (BOOL)Config_ReadInt ("wireframe", "Wireframe display", 0); settings.wfmode = (int)Config_ReadInt ("wfmode", "Wireframe mode: 0=Normal colors, 1=Vertex colors, 2=Red only", 1, TRUE, FALSE); settings.filtering = (BYTE)Config_ReadInt ("filtering", "Filtering mode: 0=None, 1=Force bilinear, 2=Force point-sampled", 1, TRUE, FALSE); settings.fog = (BOOL)Config_ReadInt ("fog", "Fog enabled", 1); settings.buff_clear = (BOOL)Config_ReadInt ("buff_clear", "Buffer clear on every frame", 1); settings.vsync = (BOOL)Config_ReadInt ("vsync", "Vertical sync", 0); settings.fast_crc = (BOOL)Config_ReadInt ("fast_crc", "Fast CRC", 0); settings.swapmode = (BYTE)Config_ReadInt ("swapmode", "Buffer swapping method: 0=Old, 1=New, 2=Hybrid", 1, TRUE, FALSE); settings.lodmode = (BYTE)Config_ReadInt ("lodmode", "LOD calculation: 0=Off, 1=Fast, 2=Precise", 0, TRUE, FALSE); settings.logging = (BOOL)Config_ReadInt ("logging", "Logging", 0); settings.log_clear = (BOOL)Config_ReadInt ("log_clear", "", 0); settings.elogging = (BOOL)Config_ReadInt ("elogging", "", 0); settings.filter_cache = (BOOL)Config_ReadInt ("filter_cache", "Filter cache", 0); settings.cpu_write_hack = (BOOL)Config_ReadInt ("detect_cpu_write", "Detect CPU writes", 0); settings.unk_as_red = (BOOL)Config_ReadInt ("unk_as_red", "Display unknown combines as red", 0); settings.log_unk = (BOOL)Config_ReadInt ("log_unk", "Log unknown combines", 0); settings.unk_clear = (BOOL)Config_ReadInt ("unk_clear", "", 0); settings.wrap_big_tex = (BOOL)Config_ReadInt ("wrap_big_tex", "Wrap textures too big for tmem", 0); settings.flame_corona = (BOOL)Config_ReadInt ("flame_corona", "Zelda corona fix", 0); // settings.RE2_native_video = (BOOL)INI_ReadInt ("RE2_native_video", 0); settings.show_fps = (BYTE)Config_ReadInt ("show_fps", "Display performance stats (add together desired flags): 1=FPS counter, 2=VI/s counter, 4=% speed, 8=FPS transparent", 0, TRUE, FALSE); settings.clock = (BOOL)Config_ReadInt ("clock", "Clock enabled", 0); settings.clock_24_hr = (BOOL)Config_ReadInt ("clock_24_hr", "Clock is 24-hour", 0); settings.fb_read_always = (BOOL)Config_ReadInt ("fb_read_always", "Framebuffer read every frame", 0); settings.fb_read_alpha = (BOOL)Config_ReadInt ("fb_read_alpha", "Framebuffer read alpha", 0); settings.fb_smart = (BOOL)Config_ReadInt ("fb_smart", "Smart framebuffer", 0); settings.fb_motionblur = (BOOL)Config_ReadInt ("motionblur", "Motion blur", 0); settings.fb_hires = (BOOL)Config_ReadInt ("fb_hires", "Hi-res framebuffer", 1); settings.fb_get_info = (BOOL)Config_ReadInt ("fb_get_info", "Get framebuffer info", 0); settings.fb_depth_clear = (BOOL)Config_ReadInt ("fb_clear", "Clear framebuffer", 0); settings.fb_depth_render = (BOOL)Config_ReadInt ("fb_render", "Depth buffer render", 0); if (settings.fb_depth_render) settings.fb_depth_clear = TRUE; settings.custom_ini = (BOOL)Config_ReadInt ("custom_ini", "Use custom INI settings", 0); settings.hotkeys = 0; settings.full_res = 0; settings.tex_filter = (DWORD)Config_ReadInt ("tex_filter", "Texture filter: 0=None, 1=Blur edges, 2=Super 2xSai, 3=Hq2x, 4=Hq4x", 0, TRUE, FALSE); settings.noditheredalpha = (BOOL)Config_ReadInt ("noditheredalpha", "Disable dithered alpha", 1); settings.noglsl = (BOOL)Config_ReadInt ("noglsl", "Disable GLSL combiners", 1); settings.FBO = (BOOL)Config_ReadInt ("fbo", "Use framebuffer objects", 0); settings.disable_auxbuf = (BOOL)Config_ReadInt ("disable_auxbuf", "Disable aux buffer", 0); } void ReadSpecialSettings (const char name[21]) { // char buf [256]; // sprintf(buf, "ReadSpecialSettings. Name: %s\n", name); // LOG(buf); settings.zelda = FALSE; //zeldas hacks settings.bomberman64 = FALSE; //bomberman64 hacks settings.diddy = FALSE; //diddy kong racing settings.tonic = FALSE; //tonic trouble settings.PPL = FALSE; //pokemon puzzle league requires many special fixes settings.ASB = FALSE; //All-Star Baseball games settings.doraemon2 = FALSE;//Doraemon 2 settings.invaders = FALSE; //Space Invaders settings.BAR = FALSE; //Beetle Adventure Racing settings.ISS64 = FALSE; //International Superstar Soccer 64 settings.RE2 = FALSE; //Resident Evil 2 settings.nitro = FALSE; //WCW Nitro settings.chopper = FALSE; //Chopper Attack settings.yoshi = FALSE; // Yoshi Story settings.fzero = FALSE; // F-Zero settings.PM = FALSE; //Paper Mario settings.TGR = FALSE; //Top Gear Rally settings.TGR2 = FALSE; //Top Gear Rally 2 settings.KI = FALSE; //Killer Instinct settings.lego = FALSE; //LEGO Racers //detect games which require special hacks if (strstr(name, (const char *)"ZELDA") || strstr(name, (const char *)"MASK")) settings.zelda = TRUE; else if (strstr(name, (const char *)"ROADSTERS TROPHY")) settings.zelda = TRUE; else if (strstr(name, (const char *)"Diddy Kong Racing")) settings.diddy = TRUE; else if (strstr(name, (const char *)"BOMBERMAN64")) settings.bomberman64 = TRUE; else if (strstr(name, (const char *)"BAKU-BOMBERMAN")) settings.bomberman64 = TRUE; else if (strstr(name, (const char *)"Tonic Trouble")) settings.tonic = TRUE; else if (strstr(name, (const char *)"All") && strstr(name, (const char *)"Star") && strstr(name, (const char *)"Baseball")) settings.ASB = TRUE; else if (strstr(name, (const char *)"\xbf\xef\xef\xbd\xbd\xbf\xb4\xd7\xbf\xef\xef\xbd\xbd\xbf\x20\x32\xb6\xcb\xbf\xef\xc9\xbd\xef\xbc\xbd\xbf\xbf\xef\xef\xbd\xbd\xbf\xbf\xef\x0a\xbd")) settings.doraemon2 = TRUE; else if (strstr(name, (const char *)"SPACE INVADERS")) settings.invaders = TRUE; else if (strstr(name, (const char *)"Beetle") || strstr(name, (const char *)"BEETLE") || strstr(name, (const char *)"HSV")) settings.BAR = TRUE; else if (strstr(name, (const char *)"I S S 64") || strstr(name, (const char *)"PERFECT STRIKER")) settings.ISS64 = TRUE; else if (strstr(name, (const char *)"NITRO64")) settings.nitro = TRUE; else if (strstr(name, (const char *)"CHOPPER_ATTACK")) settings.chopper = TRUE; else if (strstr(name, (const char *)"Resident Evil II") || strstr(name, (const char *)"BioHazard II")) { settings.RE2 = TRUE; ZLUT_init(); } else if (strstr(name, (const char *)"YOSHI STORY")) settings.yoshi= TRUE; else if (strstr(name, (const char *)"F-Zero X") || strstr(name, (const char *)"F-ZERO X")) settings.fzero = TRUE; else if (strstr(name, (const char *)"PAPER MARIO") || strstr(name, (const char *)"MARIO STORY")) settings.PM = TRUE; else if (strstr(name, (const char *)"TOP GEAR RALLY 2")) settings.TGR2 = TRUE; else if (strstr(name, (const char *)"TOP GEAR RALLY")) settings.TGR = TRUE; else if (strstr(name, (const char *)"Killer Instinct Gold") || strstr(name, (const char *)"KILLER INSTINCT GOLD")) settings.KI = TRUE; else if (strstr(name, (const char *)"LEGORacers")) settings.lego = TRUE; INI_Open (); if (INI_FindSection (name,FALSE) == FALSE) { INI_Close (); return; } int offset_x = INI_ReadInt ("offset_x", -1, 0); int offset_y = INI_ReadInt ("offset_y", -1, 0); int scale_x = INI_ReadInt ("scale_x", -1, 0); int scale_y = INI_ReadInt ("scale_y", -1, 0); int alt_tex_size = INI_ReadInt ("alt_tex_size", -1, 0); int use_sts1_only = INI_ReadInt ("use_sts1_only", -1, 0); int ppl = INI_ReadInt ("PPL", -1, 0); // int texrect_zbuf = INI_ReadInt ("force_texrect_zbuf", -1, 0); int optimize_texrect = INI_ReadInt ("optimize_texrect", -1, 0); int optimize_write = INI_ReadInt ("optimize_write", -1, 0); int ignore_aux_copy = INI_ReadInt ("ignore_aux_copy", -1, 0); int ignore_previous = INI_ReadInt ("ignore_previous", -1, 0); int hires_buf_clear = INI_ReadInt ("hires_buf_clear", -1, 0); int wrap_big_tex = INI_ReadInt ("wrap_big_tex", -1, 0); int tex_fix = INI_ReadInt ("fix_tex_coord", -1, 0); int soft_depth_compare = INI_ReadInt ("soft_depth_compare", -1, 0); int force_depth_compare = INI_ReadInt ("force_depth_compare", -1, 0); int fillcolor_fix = INI_ReadInt ("fillcolor_fix", -1, 0); int depth_bias = INI_ReadInt ("depth_bias", -1, 0); int increase_texrect_edge = INI_ReadInt ("increase_texrect_edge", -1, 0); int decrease_fillrect_edge = INI_ReadInt ("decrease_fillrect_edge", -1, 0); int increase_primdepth = INI_ReadInt ("increase_primdepth", -1, 0); int stipple_mode = INI_ReadInt ("stipple_mode", -1, 0); int stipple_pattern = INI_ReadInt ("stipple_pattern", -1, 0); int force_microcheck = INI_ReadInt ("force_microcheck", -1, 0); int info_disable = INI_ReadInt ("fb_info_disable", -1, 0); int hires_disable = INI_ReadInt ("fb_hires_disable", -1, 0); if (offset_x != -1) settings.offset_x = offset_x; if (offset_y != -1) settings.offset_y = offset_y; if (scale_x != -1) settings.scale_x = scale_x; if (scale_y != -1) settings.scale_y = scale_y; if (alt_tex_size != -1) settings.alt_tex_size = alt_tex_size; if (use_sts1_only != -1) settings.use_sts1_only = use_sts1_only; if (ppl != -1) settings.PPL = ppl; // if (texrect_zbuf != -1) settings.force_texrect_zbuf = texrect_zbuf; if (optimize_texrect != -1) settings.fb_optimize_texrect = optimize_texrect; if (optimize_write != -1) settings.fb_optimize_write = optimize_write; if (ignore_aux_copy != -1) settings.fb_ignore_aux_copy = ignore_aux_copy; if (hires_buf_clear != -1) settings.fb_hires_buf_clear = hires_buf_clear; if (wrap_big_tex != -1) settings.wrap_big_tex = wrap_big_tex; if (tex_fix != -1) settings.fix_tex_coord = tex_fix; if (soft_depth_compare != -1) settings.soft_depth_compare = soft_depth_compare; if (force_depth_compare != -1) settings.force_depth_compare = force_depth_compare; if (fillcolor_fix != -1) settings.fillcolor_fix = fillcolor_fix; if (depth_bias != -1) settings.depth_bias = -depth_bias; if (increase_texrect_edge != -1) settings.increase_texrect_edge = increase_texrect_edge; if (decrease_fillrect_edge != -1) settings.decrease_fillrect_edge = decrease_fillrect_edge; if (increase_primdepth != -1) settings.increase_primdepth = increase_primdepth; if (stipple_mode != -1) settings.stipple_mode = stipple_mode; if (stipple_pattern != -1) settings.stipple_pattern = (DWORD)stipple_pattern; if (force_microcheck != -1) settings.force_microcheck = force_microcheck; if (ignore_previous != -1) settings.fb_ignore_previous = ignore_previous; if (info_disable == 1) settings.fb_get_info = 0; if (hires_disable == 1) settings.fb_hires = 0; if (settings.lodmode == 0) { int lodmode = INI_ReadInt ("lodmode", -1, 0); if (lodmode > 0) settings.lodmode = lodmode; } if (settings.custom_ini) { int filtering = INI_ReadInt ("filtering", -1, 0); int fog = INI_ReadInt ("fog", -1, 0); int buff_clear = INI_ReadInt ("buff_clear", -1, 0); int swapmode = INI_ReadInt ("swapmode", -1, 0); int smart_read = INI_ReadInt ("fb_smart", -1, 0); int read_alpha = INI_ReadInt ("fb_read_alpha", -1, 0); int depth_clear = INI_ReadInt ("fb_clear", -1, 0); //FIXME unused int depth_render = INI_ReadInt ("fb_render", -1, 0); //int resolution = (INT)INI_ReadInt ("resolution", -1, 0); int cpu_write_hack = (INT)INI_ReadInt ("detect_cpu_write", -1, 0); if (filtering != -1) settings.filtering = filtering; if (fog != -1) settings.fog = fog; if (buff_clear != -1) settings.buff_clear = buff_clear; if (swapmode != -1) settings.swapmode= swapmode; // settings.swapmode = 2; if (smart_read != -1) settings.fb_smart = smart_read; if (read_alpha != -1) settings.fb_read_alpha= read_alpha; if (depth_clear != -1) settings.fb_depth_clear = depth_clear; if (cpu_write_hack != -1) settings.cpu_write_hack = cpu_write_hack; /* if (resolution != -1) { settings.res_data = (DWORD) resolution; if (settings.res_data >= 0x18) settings.res_data = 12; settings.scr_res_x = settings.res_x = resolutions[settings.res_data][0]; settings.scr_res_y = settings.res_y = resolutions[settings.res_data][1]; } */ } if (settings.fb_depth_render) settings.fb_depth_clear = TRUE; INI_Close (); } #include "font.h" #include "cursor.h" GRFRAMEBUFFERCOPYEXT grFramebufferCopyExt = NULL; GRTEXBUFFEREXT grTextureBufferExt = NULL; GRTEXBUFFEREXT grTextureAuxBufferExt = NULL; GRAUXBUFFEREXT grAuxBufferExt = NULL; GRSTIPPLE grStippleModeExt = NULL; GRSTIPPLE grStipplePatternExt = NULL; BOOL combineext = FALSE; BOOL depthbuffersave = FALSE; // guLoadTextures - used to load the cursor and font textures void guLoadTextures () { if (grTextureBufferExt) { int tbuf_size = 0; if (max_tex_size <= 256) { grTextureBufferExt( GR_TMU1, grTexMinAddress(GR_TMU1), GR_LOD_LOG2_256, GR_LOD_LOG2_256, GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH ); tbuf_size = 8 * grTexCalcMemRequired(GR_LOD_LOG2_256, GR_LOD_LOG2_256, GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565); } else if (settings.scr_res_x <= 1024) { grTextureBufferExt( GR_TMU1, grTexMinAddress(GR_TMU1), GR_LOD_LOG2_1024, GR_LOD_LOG2_1024, GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH ); tbuf_size = grTexCalcMemRequired(GR_LOD_LOG2_1024, GR_LOD_LOG2_1024, GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565); } else { grTextureBufferExt( GR_TMU1, grTexMinAddress(GR_TMU1), GR_LOD_LOG2_2048, GR_LOD_LOG2_2048, GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH ); tbuf_size = grTexCalcMemRequired(GR_LOD_LOG2_2048, GR_LOD_LOG2_2048, GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565); } //tbuf_size *= 2; WriteLog(M64MSG_INFO, "tbuf_size %gMb\n", tbuf_size/1024.0f/1024); rdp.texbufs[0].tmu = GR_TMU0; rdp.texbufs[0].begin = grTexMinAddress(GR_TMU0); rdp.texbufs[0].end = rdp.texbufs[0].begin+tbuf_size; rdp.texbufs[0].count = 0; rdp.texbufs[0].clear_allowed = TRUE; if (num_tmu > 1) { rdp.texbufs[1].tmu = GR_TMU1; rdp.texbufs[1].begin = grTexMinAddress(GR_TMU1); rdp.texbufs[1].end = rdp.texbufs[1].begin+tbuf_size; rdp.texbufs[1].count = 0; rdp.texbufs[1].clear_allowed = TRUE; offset_texbuf1 = tbuf_size; } offset_font = tbuf_size; } else offset_font = 0; DWORD *data = (DWORD*)font; DWORD cur; // ** Font texture ** BYTE *tex8 = (BYTE*)malloc(256*64); fontTex.smallLodLog2 = fontTex.largeLodLog2 = GR_LOD_LOG2_256; fontTex.aspectRatioLog2 = GR_ASPECT_LOG2_4x1; fontTex.format = GR_TEXFMT_ALPHA_8; fontTex.data = tex8; // Decompression: [1-bit inverse alpha --> 8-bit alpha] DWORD i,b; for (i=0; i<0x200; i++) { // cur = ~*(data++), byteswapped cur = bswap32(~*(data++)); for (b=0x80000000; b!=0; b>>=1) { if (cur&b) *tex8 = 0xFF; else *tex8 = 0x00; tex8 ++; } } grTexDownloadMipMap (GR_TMU0, grTexMinAddress(GR_TMU0) + offset_font, GR_MIPMAPLEVELMASK_BOTH, &fontTex); offset_cursor = offset_font + grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, &fontTex); free (fontTex.data); // ** Cursor texture ** data = (DWORD*)cursor; WORD *tex16 = (WORD*)malloc(32*32*2); cursorTex.smallLodLog2 = cursorTex.largeLodLog2 = GR_LOD_LOG2_32; cursorTex.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; cursorTex.format = GR_TEXFMT_ARGB_1555; cursorTex.data = tex16; // Conversion: [16-bit 1555 (swapped) --> 16-bit 1555] for (i=0; i<0x200; i++) { cur = *(data++); *(tex16++) = (WORD)(((cur&0x000000FF)<<8)|((cur&0x0000FF00)>>8)); *(tex16++) = (WORD)(((cur&0x00FF0000)>>8)|((cur&0xFF000000)>>24)); } grTexDownloadMipMap (GR_TMU0, grTexMinAddress(GR_TMU0) + offset_cursor, GR_MIPMAPLEVELMASK_BOTH, &cursorTex); // Round to higher 16 offset_textures = ((offset_cursor + grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, &cursorTex)) & 0xFFFFFFF0) + 16; free (cursorTex.data); } BOOL InitGfx (BOOL evoodoo_using_window) { if (fullscreen) { ReleaseGfx (); } OPEN_RDP_LOG (); // doesn't matter if opens again; it will check for it OPEN_RDP_E_LOG (); LOG ("InitGfx ()\n"); debugging = FALSE; // Initialize Glide grGlideInit (); // Select the Glide device grSstSelect (settings.card_id); gfx_context = 0; // Select the window if (settings.fb_hires) { WriteLog(M64MSG_INFO, "fb_hires\n"); GRWINOPENEXT grSstWinOpenExt = (GRWINOPENEXT)grGetProcAddress("grSstWinOpenExt"); if (grSstWinOpenExt) gfx_context = grSstWinOpenExt ((uintptr_t)NULL, settings.res_data, GR_REFRESH_60Hz, GR_COLORFORMAT_RGBA, GR_ORIGIN_UPPER_LEFT, GR_PIXFMT_RGB_565, 2, // Double-buffering 1); // 1 auxillary buffer } if (!gfx_context) gfx_context = grSstWinOpen ((uintptr_t)NULL, settings.res_data, GR_REFRESH_60Hz, GR_COLORFORMAT_RGBA, GR_ORIGIN_UPPER_LEFT, 2, // Double-buffering 1); // 1 auxillary buffer if (!gfx_context) { WriteLog(M64MSG_ERROR, "Error setting display mode"); grSstWinClose (gfx_context); grGlideShutdown (); return FALSE; } // get the # of TMUs available grGet (GR_NUM_TMU, 4, (FxI32 *) &num_tmu); WriteLog(M64MSG_INFO, "num_tmu %d\n", num_tmu); // get maximal texture size grGet (GR_MAX_TEXTURE_SIZE, 4, (FxI32 *) &max_tex_size); //num_tmu = 1; // Is mirroring allowed? const char *extensions = grGetString (GR_EXTENSION); if (strstr (extensions, "TEXMIRROR")) sup_mirroring = 1; else sup_mirroring = 0; if (strstr (extensions, "TEXFMT")) //VSA100 texture format extension sup_32bit_tex = TRUE; else sup_32bit_tex = FALSE; if (settings.fb_hires) { const char * extstr = strstr(extensions, "TEXTUREBUFFER"); if (extstr) { if (!strncmp(extstr, "TEXTUREBUFFER", 13)) { grTextureBufferExt = (GRTEXBUFFEREXT) grGetProcAddress("grTextureBufferExt"); grTextureAuxBufferExt = (GRTEXBUFFEREXT) grGetProcAddress("grTextureAuxBufferExt"); grAuxBufferExt = (GRAUXBUFFEREXT) grGetProcAddress("grAuxBufferExt"); } } else settings.fb_hires = 0; } else grTextureBufferExt = 0; grFramebufferCopyExt = (GRFRAMEBUFFERCOPYEXT) grGetProcAddress("grFramebufferCopyExt"); grStippleModeExt = (GRSTIPPLE) grStippleMode; grStipplePatternExt = (GRSTIPPLE) grStipplePattern; if (grStipplePatternExt) grStipplePatternExt(settings.stipple_pattern); InitCombine(); #ifdef SIMULATE_VOODOO1 num_tmu = 1; sup_mirroring = 0; #endif #ifdef SIMULATE_BANSHEE num_tmu = 1; sup_mirroring = 1; #endif fullscreen = TRUE; if (evoodoo_using_window) ev_fullscreen = FALSE; else ev_fullscreen = TRUE; grCoordinateSpace (GR_WINDOW_COORDS); grVertexLayout (GR_PARAM_XY, offsetof(VERTEX,x), GR_PARAM_ENABLE); grVertexLayout (GR_PARAM_Q, offsetof(VERTEX,q), GR_PARAM_ENABLE); grVertexLayout (GR_PARAM_Z, offsetof(VERTEX,z), GR_PARAM_ENABLE); grVertexLayout (GR_PARAM_ST0, offsetof(VERTEX,coord[0]), GR_PARAM_ENABLE); grVertexLayout (GR_PARAM_ST1, offsetof(VERTEX,coord[2]), GR_PARAM_ENABLE); grVertexLayout (GR_PARAM_PARGB, offsetof(VERTEX,b), GR_PARAM_ENABLE); grCullMode(GR_CULL_NEGATIVE); if (settings.fog) //"FOGCOORD" extension { if (strstr (extensions, "FOGCOORD")) { GrFog_t fog_t[64]; guFogGenerateLinear (fog_t, 0.0f, 255.0f);//(float)rdp.fog_multiplier + (float)rdp.fog_offset);//256.0f); for (int i = 63; i > 0; i--) { if (fog_t[i] - fog_t[i-1] > 63) { fog_t[i-1] = fog_t[i] - 63; } } fog_t[0] = 0; // for (int f = 0; f < 64; f++) // { // FRDP("fog[%d]=%d->%f\n", f, fog_t[f], guFogTableIndexToW(f)); // } grFogTable (fog_t); grVertexLayout (GR_PARAM_FOG_EXT, offsetof(VERTEX,f), GR_PARAM_ENABLE); } else //not supported settings.fog = FALSE; } //grDepthBufferMode (GR_DEPTHBUFFER_WBUFFER); grDepthBufferMode (GR_DEPTHBUFFER_ZBUFFER); grDepthBufferFunction(GR_CMP_LESS); grDepthMask(FXTRUE); settings.res_x = settings.scr_res_x; settings.res_y = settings.scr_res_y; ChangeSize (); guLoadTextures (); grRenderBuffer(GR_BUFFER_BACKBUFFER); rdp_reset (); ClearCache (); rdp.update |= UPDATE_SCISSOR; return TRUE; } void ReleaseGfx () { // Release graphics grSstWinClose (gfx_context); // Shutdown glide grGlideShutdown(); fullscreen = FALSE; rdp.window_changed = TRUE; } #ifdef __cplusplus extern "C" { #endif EXPORT void CALL ReadScreen2(void *dest, int *width, int *height, int front) { *width = settings.res_x; *height = settings.res_y; if (dest) { BYTE * line = (BYTE*)dest; if (!fullscreen) { for (DWORD y=0; yVersion = 0x0103; // Set to 0x0103 PluginInfo->Type = PLUGIN_TYPE_GFX; // Set to PLUGIN_TYPE_GFX sprintf (PluginInfo->Name, "Glide64 " G64_VERSION); // Name of the DLL // If DLL supports memory these memory options then set them to TRUE or FALSE // if it does not support it PluginInfo->NormalMemory = TRUE; // a normal BYTE array PluginInfo->MemoryBswaped = TRUE; // a normal BYTE array where the memory has been pre // bswap on a dword (32 bits) boundry } #ifndef WIN32 BOOL WINAPI QueryPerformanceCounter(PLARGE_INTEGER counter) { struct timeval tv; /* generic routine */ gettimeofday( &tv, NULL ); counter->QuadPart = (LONGLONG)tv.tv_usec + (LONGLONG)tv.tv_sec * 1000000; return TRUE; } BOOL WINAPI QueryPerformanceFrequency(PLARGE_INTEGER frequency) { frequency->s.LowPart= 1000000; frequency->s.HighPart= 0; return TRUE; } #endif /****************************************************************** Function: InitiateGFX Purpose: This function is called when the DLL is started to give information from the emulator that the n64 graphics uses. This is not called from the emulation thread. Input: Gfx_Info is passed to this function which is defined above. Output: TRUE on success FALSE on failure to initialise ** note on interrupts **: To generate an interrupt set the appropriate bit in MI_INTR_REG and then call the function CheckInterrupts to tell the emulator that there is a waiting interrupt. *******************************************************************/ EXPORT BOOL CALL InitiateGFX (GFX_INFO Gfx_Info) { LOG ("InitiateGFX (*)\n"); // Do *NOT* put this in rdp_reset or it could be set after the screen is initialized num_tmu = 2; // Assume scale of 1 for debug purposes rdp.scale_x = 1.0f; rdp.scale_y = 1.0f; memset (&settings, 0, sizeof(SETTINGS)); ReadSettings (); #ifdef FPS QueryPerformanceFrequency (&perf_freq); QueryPerformanceCounter (&fps_last); #endif debug_init (); // Initialize debugger gfx = Gfx_Info; /* char name[21]; // get the name of the ROM for (int i=0; i<20; i++) name[i] = gfx.HEADER[(32+i)^3]; name[20] = 0; // remove all trailing spaces while (name[strlen(name)-1] == ' ') name[strlen(name)-1] = 0; ReadSpecialSettings (name); */ #ifdef WINPROC_OVERRIDE if (!oldWndProc) { myWndProc = (WNDPROC)WndProc; oldWndProc = (WNDPROC)SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)myWndProc); } #endif util_init (); math_init (); TexCacheInit (); CRC_BuildTable(); CountCombine(); if (settings.fb_depth_render) ZLUT_init(); return TRUE; } /****************************************************************** Function: MoveScreen Purpose: This function is called in response to the emulator receiving a WM_MOVE passing the xpos and ypos passed from that message. input: xpos - the x-coordinate of the upper-left corner of the client area of the window. ypos - y-coordinate of the upper-left corner of the client area of the window. output: none *******************************************************************/ EXPORT void CALL MoveScreen (int xpos, int ypos) { LOG ("MoveScreen"); } /****************************************************************** Function: ProcessRDPList Purpose: This function is called when there is a Dlist to be processed. (Low level GFX list) input: none output: none *******************************************************************/ #if 0 EXPORT void CALL ProcessRDPList(void) { if (settings.KI) { *gfx.MI_INTR_REG |= 0x20; gfx.CheckInterrupts(); } LOG ("ProcessRDPList ()\n"); printf("ProcessRPDList %x %x %x\n", *gfx.DPC_START_REG, *gfx.DPC_END_REG, *gfx.DPC_CURRENT_REG); //*gfx.DPC_STATUS_REG = 0xffffffff; // &= ~0x0002; //*gfx.DPC_START_REG = *gfx.DPC_END_REG; *gfx.DPC_CURRENT_REG = *gfx.DPC_END_REG; } #endif /****************************************************************** Function: ResizeVideoOutput Purpose: This function is called to force us to resize our output OpenGL window. This is currently unsupported, and should never be called because we do not pass the RESIZABLE flag to VidExt_SetVideoMode when initializing. input: new width and height output: none *******************************************************************/ EXPORT void CALL ResizeVideoOutput(int Width, int Height) { } /****************************************************************** Function: RomClosed Purpose: This function is called when a rom is closed. input: none output: none *******************************************************************/ EXPORT void CALL RomClosed (void) { LOG ("RomClosed ()\n"); CLOSE_RDP_LOG (); CLOSE_RDP_E_LOG (); rdp.window_changed = TRUE; romopen = FALSE; if (fullscreen && evoodoo) ReleaseGfx (); CoreVideo_Quit(); } BOOL no_dlist = TRUE; /****************************************************************** Function: RomOpen Purpose: This function is called when a rom is open. (from the emulation thread) input: none output: none *******************************************************************/ EXPORT int CALL RomOpen (void) { LOG ("RomOpen ()\n"); if (CoreVideo_Init() != M64ERR_SUCCESS) { WriteLog(M64MSG_ERROR, "Could not initialize video!"); return false; } no_dlist = TRUE; romopen = TRUE; ucode_error_report = TRUE; // allowed to report ucode errors // Get the country code & translate to NTSC(0) or PAL(1) WORD code = ((WORD*)gfx.HEADER)[0x1F^1]; if (code == 0x4400) region = 1; // Germany (PAL) if (code == 0x4500) region = 0; // USA (NTSC) if (code == 0x4A00) region = 0; // Japan (NTSC) if (code == 0x5000) region = 1; // Europe (PAL) if (code == 0x5500) region = 0; // Australia (NTSC) char name[21] = "DEFAULT"; ReadSpecialSettings (name); // get the name of the ROM for (int i=0; i<20; i++) name[i] = gfx.HEADER[(32+i)^3]; name[20] = 0; // remove all trailing spaces while (name[strlen(name)-1] == ' ') name[strlen(name)-1] = 0; ReadSpecialSettings (name); WriteLog(M64MSG_INFO, "fb_clear %d fb_smart %d\n", settings.fb_depth_clear, settings.fb_smart); rdp_reset (); ClearCache (); OPEN_RDP_LOG (); OPEN_RDP_E_LOG (); // ** EVOODOO EXTENSIONS ** if (!fullscreen) { grGlideInit (); grSstSelect (0); } const char *extensions = grGetString (GR_EXTENSION); WriteLog(M64MSG_INFO, "extensions '%s'\n", extensions); if (!fullscreen) { grGlideShutdown (); if (strstr (extensions, "EVOODOO")) evoodoo = 1; else evoodoo = 0; if (evoodoo) InitGfx (TRUE); } if (strstr (extensions, "ROMNAME")) { void (__stdcall *grSetRomName)(char*); grSetRomName = (void (__stdcall *)(char*))grGetProcAddress ("grSetRomName"); grSetRomName (name); } // ** return true; } /****************************************************************** Function: ShowCFB Purpose: Useally once Dlists are started being displayed, cfb is ignored. This function tells the dll to start displaying them again. input: none output: none *******************************************************************/ EXPORT void CALL ShowCFB (void) { no_dlist = TRUE; LOG ("ShowCFB ()\n"); } EXPORT void CALL SetRenderingCallback(void (*callback)(int)) { renderCallback = callback; } /****************************************************************** Function: UpdateScreen Purpose: This function is called in response to a vsync of the screen were the VI bit in MI_INTR_REG has already been set input: none output: none *******************************************************************/ DWORD update_screen_count = 0; EXPORT void CALL UpdateScreen (void) { #ifdef LOG_KEY if (GetAsyncKeyState (VK_SPACE) & 0x0001) { LOG ("KEY!!!\n"); } #endif char out_buf[512]; sprintf (out_buf, "UpdateScreen (). distance: %d\n", (int)(*gfx.VI_ORIGIN_REG) - (int)((*gfx.VI_WIDTH_REG) << 2)); LOG (out_buf); // LOG ("UpdateScreen ()\n"); DWORD width = (*gfx.VI_WIDTH_REG) << 1; if (fullscreen && (*gfx.VI_ORIGIN_REG > width)) update_screen_count++; // vertical interrupt has occured, increment counter vi_count ++; #ifdef FPS // Check frames per second LARGE_INTEGER difference; QueryPerformanceCounter (&fps_next); difference.QuadPart = fps_next.QuadPart - fps_last.QuadPart; float diff_secs = (float)((double)difference.QuadPart / (double)perf_freq.QuadPart); if (diff_secs > 0.5f) { fps = (float)fps_count / diff_secs; vi = (float)vi_count / diff_secs; ntsc_percent = vi / 0.6f; pal_percent = vi / 0.5f; fps_last = fps_next; fps_count = 0; vi_count = 0; } #endif //* DWORD limit = settings.lego ? 15 : 50; if (settings.cpu_write_hack && (update_screen_count > limit) && (rdp.last_bg == 0)) { RDP("DirectCPUWrite hack!\n"); update_screen_count = 0; no_dlist = TRUE; ClearCache (); UpdateScreen(); return; } //*/ //* if( no_dlist ) { if( *gfx.VI_ORIGIN_REG > width ) { ChangeSize (); RDP("ChangeSize done\n"); DrawFrameBuffer(); RDP("DrawFrameBuffer done\n"); rdp.updatescreen = 1; newSwapBuffers (); } return; } //*/ if (settings.swapmode == 0) { newSwapBuffers (); } } /****************************************************************** Function: ViStatusChanged Purpose: This function is called to notify the dll that the ViStatus registers value has been changed. input: none output: none *******************************************************************/ EXPORT void CALL ViStatusChanged (void) { } /****************************************************************** Function: ViWidthChanged Purpose: This function is called to notify the dll that the ViWidth registers value has been changed. input: none output: none *******************************************************************/ EXPORT void CALL ViWidthChanged (void) { } #ifdef __cplusplus } #endif void drawViRegBG(); void drawNoFullscreenMessage(); void DrawFrameBuffer () { if (!fullscreen) { drawNoFullscreenMessage(); } if (to_fullscreen) { to_fullscreen = FALSE; if (!InitGfx (FALSE)) { LOG ("FAILED!!!\n"); return; } fullscreen = TRUE; } if (fullscreen) { grDepthMask (FXTRUE); grColorMask (FXTRUE, FXTRUE); grBufferClear (0, 0, 0xFFFF); drawViRegBG(); } } DWORD curframe = 0; void newSwapBuffers() { if (rdp.updatescreen) { rdp.updatescreen = 0; RDP ("swapped\n"); // Allow access to the whole screen if (fullscreen) { grClipWindow (0, 0, settings.scr_res_x, settings.scr_res_y); grDepthBufferFunction (GR_CMP_ALWAYS); grDepthMask (FXFALSE); grCullMode (GR_CULL_DISABLE); if ((settings.show_fps & 0xF) || settings.clock) set_message_combiner (); #ifdef FPS float y = (float)settings.res_y; if (settings.show_fps & 0x0F) { if (settings.show_fps & 4) { if (region) // PAL output (0, y, 0, "%d%% ", (int)pal_percent); else output (0, y, 0, "%d%% ", (int)ntsc_percent); y -= 16; } if (settings.show_fps & 2) { output (0, y, 0, "VI/s: %.02f ", vi); y -= 16; } if (settings.show_fps & 1) output (0, y, 0, "FPS: %.02f ", fps); } #endif if (settings.clock) { if (settings.clock_24_hr) { time_t ltime; time (<ime); tm *cur_time = localtime (<ime); sprintf (out_buf, "%.2d:%.2d:%.2d", cur_time->tm_hour, cur_time->tm_min, cur_time->tm_sec); } else { char ampm[] = "AM"; time_t ltime; time (<ime); tm *cur_time = localtime (<ime); if (cur_time->tm_hour >= 12) { strcpy (ampm, "PM"); if (cur_time->tm_hour != 12) cur_time->tm_hour -= 12; } if (cur_time->tm_hour == 0) cur_time->tm_hour = 12; if (cur_time->tm_hour >= 10) sprintf (out_buf, "%.5s %s", asctime(cur_time) + 11, ampm); else sprintf (out_buf, " %.4s %s", asctime(cur_time) + 12, ampm); } output ((float)(settings.res_x - 68), y, 0, out_buf, 0); } } // Capture the screen if debug capture is set if (debug.capture) { // Allocate the screen debug.screen = new BYTE [(settings.res_x*settings.res_y) << 1]; // Lock the backbuffer (already rendered) GrLfbInfo_t info; info.size = sizeof(GrLfbInfo_t); while (!grLfbLock (GR_LFB_READ_ONLY, GR_BUFFER_BACKBUFFER, GR_LFBWRITEMODE_565, GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)); DWORD offset_src=0/*(settings.scr_res_y-settings.res_y)*info.strideInBytes*/, offset_dst=0; // Copy the screen for (DWORD y=0; yvkCode == 162) k_ctl = 0; if (p->vkCode == 164) k_alt = 0; if (p->vkCode == 46) k_del = 0; goto do_it; case WM_KEYDOWN: case WM_SYSKEYDOWN: p = (PKBDLLHOOKSTRUCT) lParam; if (p->vkCode == 162) k_ctl = 1; if (p->vkCode == 164) k_alt = 1; if (p->vkCode == 46) k_del = 1; goto do_it; do_it: TabKey = ((p->vkCode == VK_TAB) && ((p->flags & LLKHF_ALTDOWN) != 0)) || ((p->vkCode == VK_ESCAPE) && ((p->flags & LLKHF_ALTDOWN) != 0)) || ((p->vkCode == VK_ESCAPE) && ((GetKeyState(VK_CONTROL) & 0x8000) != 0)) || (k_ctl && k_alt && k_del); break; } } if (TabKey) { k_ctl = 0; k_alt = 0; k_del = 0; ReleaseGfx (); } return CallNextHookEx(NULL, nCode, wParam, lParam); } #endif mupen64plus-video-glide64-src-2.6.0/src/MiClWr16b.h000066400000000000000000000156461464507525600215060ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski * * 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 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators // Project started on December 29th, 2001 // // Authors: // Dave2001, original author, founded the project in 2001, left it in 2002 // Gugaman, joined the project in 2002, left it in 2002 // Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002 // Hiroshi 'KoolSmoky' Morii, joined the project in 2007 // //**************************************************************** // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // //**************************************************************** static inline void mirror16bS(uint8_t *tex, uint8_t *start, int width, int height, int mask, int line, int full, int count) { uint16_t *v8; int v9; int v10; v8 = (uint16_t *)start; v9 = height; do { v10 = 0; do { if ( width & (v10 + width) ) { *v8 = *(uint16_t *)(&tex[mask] - (mask & 2 * v10)); ++v8; } else { *v8 = *(uint16_t *)&tex[mask & 2 * v10]; ++v8; } ++v10; } while ( v10 != count ); v8 = (uint16_t *)((char *)v8 + line); tex += full; --v9; } while ( v9 ); } static inline void wrap16bS(uint8_t *tex, uint8_t *start, int height, int mask, int line, int full, int count) { uint32_t *v7; int v8; int v9; v7 = (uint32_t *)start; v8 = height; do { v9 = 0; do { *v7 = *(uint32_t *)&tex[4 * (mask & v9)]; ++v7; ++v9; } while ( v9 != count ); v7 = (uint32_t *)((char *)v7 + line); tex += full; --v8; } while ( v8 ); } static inline void clamp16bS(uint8_t *tex, uint8_t *constant, int height, int line, int full, int count) { uint16_t *v6; uint16_t *v7; int v8; uint16_t v9; int v10; v6 = (uint16_t *)constant; v7 = (uint16_t *)tex; v8 = height; do { v9 = *v6; v10 = count; do { *v7 = v9; ++v7; --v10; } while ( v10 ); v6 = (uint16_t *)((char *)v6 + full); v7 = (uint16_t *)((char *)v7 + line); --v8; } while ( v8 ); } //**************************************************************** // 16-bit Horizontal Mirror #include #include typedef uint32_t uint32_t; void Mirror16bS (unsigned char * tex, uint32_t mask, uint32_t max_width, uint32_t real_width, uint32_t height) { if (mask == 0) return; uint32_t mask_width = (1 << mask); uint32_t mask_mask = (mask_width-1) << 1; if (mask_width >= max_width) return; int count = max_width - mask_width; if (count <= 0) return; int line_full = real_width << 1; int line = line_full - (count << 1); if (line < 0) return; unsigned char *start = tex + (mask_width << 1); mirror16bS (tex, start, mask_width, height, mask_mask, line, line_full, count); } //**************************************************************** // 16-bit Horizontal Wrap (like mirror) void Wrap16bS (unsigned char * tex, uint32_t mask, uint32_t max_width, uint32_t real_width, uint32_t height) { if (mask == 0) return; uint32_t mask_width = (1 << mask); uint32_t mask_mask = (mask_width-1) >> 1; if (mask_width >= max_width) return; int count = (max_width - mask_width) >> 1; if (count <= 0) return; int line_full = real_width << 1; int line = line_full - (count << 2); if (line < 0) return; unsigned char * start = tex + (mask_width << 1); wrap16bS (tex, start, height, mask_mask, line, line_full, count); } //**************************************************************** // 16-bit Horizontal Clamp void Clamp16bS (unsigned char * tex, uint32_t width, uint32_t clamp_to, uint32_t real_width, uint32_t real_height) { if (real_width <= width) return; unsigned char * dest = tex + (width << 1); unsigned char * constant = dest-2; int count = clamp_to - width; int line_full = real_width << 1; int line = width << 1; clamp16bS (dest, constant, real_height, line, line_full, count); } //**************************************************************** // 16-bit Vertical Mirror void Mirror16bT (unsigned char * tex, uint32_t mask, uint32_t max_height, uint32_t real_width) { if (mask == 0) return; uint32_t mask_height = (1 << mask); uint32_t mask_mask = mask_height-1; if (max_height <= mask_height) return; int line_full = real_width << 1; unsigned char * dst = tex + mask_height * line_full; for (uint32_t y=mask_height; y= max_width) return; int count = max_width - mask_width; if (count <= 0) return; int line_full = real_width; int line = line_full - (count); if (line < 0) return; unsigned char * start = tex + (mask_width); mirror8bS (tex, start, mask_width, height, mask_mask, line, line_full, count); } //**************************************************************** // 8-bit Horizontal Wrap (like mirror) ** UNTESTED ** void Wrap8bS (unsigned char * tex, uint32_t mask, uint32_t max_width, uint32_t real_width, uint32_t height) { if (mask == 0) return; uint32_t mask_width = (1 << mask); uint32_t mask_mask = (mask_width-1) >> 2; if (mask_width >= max_width) return; int count = (max_width - mask_width) >> 2; if (count <= 0) return; int line_full = real_width; int line = line_full - (count << 2); if (line < 0) return; unsigned char * start = tex + (mask_width); wrap8bS (tex, start, height, mask_mask, line, line_full, count); } //**************************************************************** // 8-bit Horizontal Clamp void Clamp8bS (unsigned char * tex, uint32_t width, uint32_t clamp_to, uint32_t real_width, uint32_t real_height) { if (real_width <= width) return; unsigned char * dest = tex + (width); unsigned char * constant = dest-1; int count = clamp_to - width; int line_full = real_width; int line = width; clamp8bS (dest, constant, real_height, line, line_full, count); } //**************************************************************** // 8-bit Vertical Mirror void Mirror8bT (unsigned char * tex, uint32_t mask, uint32_t max_height, uint32_t real_width) { if (mask == 0) return; uint32_t mask_height = (1 << mask); uint32_t mask_mask = mask_height-1; if (max_height <= mask_height) return; int line_full = real_width; unsigned char * dst = tex + mask_height * line_full; for (uint32_t y=mask_height; y #endif // _WIN32 static HIRES_COLOR_IMAGE * AllocateTextureBuffer(COLOR_IMAGE & cimage) { HIRES_COLOR_IMAGE texbuf; texbuf.addr = cimage.addr; texbuf.end_addr = cimage.addr + cimage.width*cimage.height*cimage.size; texbuf.width = cimage.width; texbuf.height = cimage.height; texbuf.format = (WORD)cimage.format; texbuf.scr_width = std::min(cimage.width * rdp.scale_x, (float) settings.scr_res_x); float height = std::min(rdp.vi_height, (float) cimage.height); if (cimage.status == ci_copy_self || (cimage.status == ci_copy && cimage.width == rdp.frame_buffers[rdp.main_ci_index].width)) height = rdp.vi_height; texbuf.scr_height = height * rdp.scale_y; WORD max_size = std::max((WORD)texbuf.scr_width, (WORD)texbuf.scr_height); if (max_size > max_tex_size) //texture size is too large return 0; DWORD tex_size; //calculate LOD switch ((max_size-1) >> 6) { case 0: // ZIGGY : fixed (was GR_LOD_LOG2_128) texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_64; tex_size = 64; break; case 1: texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_128; tex_size = 128; break; case 2: case 3: texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_256; tex_size = 256; break; case 4: case 5: case 6: case 7: texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_512; tex_size = 512; break; case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_1024; tex_size = 1024; break; default: texbuf.info.smallLodLog2 = texbuf.info.largeLodLog2 = GR_LOD_LOG2_2048; tex_size = 2048; } //calculate aspect if (texbuf.scr_width >= texbuf.scr_height) { if ((texbuf.scr_width/texbuf.scr_height) >= 2) { texbuf.info.aspectRatioLog2 = GR_ASPECT_LOG2_2x1; texbuf.tex_width = tex_size; texbuf.tex_height = tex_size >> 1; } else { texbuf.info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; texbuf.tex_width = texbuf.tex_height = tex_size; } } else { if ((texbuf.scr_height/texbuf.scr_width) >= 2) { texbuf.info.aspectRatioLog2 = GR_ASPECT_LOG2_1x2; texbuf.tex_width = tex_size >> 1; texbuf.tex_height = tex_size; } else { texbuf.info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; texbuf.tex_width = texbuf.tex_height = tex_size; } } if ((cimage.format != 0))// && (cimage.width <= 64)) texbuf.info.format = GR_TEXFMT_ALPHA_INTENSITY_88; else texbuf.info.format = GR_TEXFMT_RGB_565; float lr_u = 256.0f * texbuf.scr_width / (float)tex_size;// + 1.0f; float lr_v = 256.0f * texbuf.scr_height / (float)tex_size;// + 1.0f; texbuf.tile = 0; texbuf.tile_uls = 0; texbuf.tile_ult = 0; texbuf.u_shift = 0; texbuf.v_shift = 0; texbuf.drawn = FALSE; texbuf.clear = FALSE; texbuf.info.data = NULL; texbuf.u_scale = lr_u / (float)(texbuf.width); texbuf.v_scale = lr_v / (float)(texbuf.height); FRDP("\nAllocateTextureBuffer. width: %d, height: %d, scr_width: %f, scr_height: %f, vi_width: %f, vi_height:%f, scale_x: %f, scale_y: %f, lr_u: %f, lr_v: %f, u_scale: %f, v_scale: %f\n", texbuf.width, texbuf.height, texbuf.scr_width, texbuf.scr_height, rdp.vi_width, rdp.vi_height, rdp.scale_x, rdp.scale_y, lr_u, lr_v, texbuf.u_scale, texbuf.v_scale); DWORD required = grTexCalcMemRequired(texbuf.info.smallLodLog2, texbuf.info.largeLodLog2, texbuf.info.aspectRatioLog2, texbuf.info.format); //find free space for (int i = 0; i < num_tmu; i++) { DWORD available = 0; DWORD top = 0; if (rdp.texbufs[i].count) { HIRES_COLOR_IMAGE & t = rdp.texbufs[i].images[rdp.texbufs[i].count - 1]; if (rdp.read_whole_frame) { if ((cimage.status == ci_aux) && (rdp.cur_tex_buf == i)) { top = /*rdp.texbufs[i].begin + */t.tex_addr + t.tex_width * (int)(t.scr_height+1) * 2; if (rdp.texbufs[i].end - top < required) return 0; } else top = rdp.texbufs[i].end; } else top = /*rdp.texbufs[i].begin + */t.tex_addr + t.tex_width * t.tex_height * 2; available = rdp.texbufs[i].end - top; } else { available = rdp.texbufs[i].end - rdp.texbufs[i].begin; top = rdp.texbufs[i].begin; } //printf("i %d count %d end %gMb avail %gMb req %gMb\n", i, rdp.texbufs[i].count, rdp.texbufs[i].end/1024.0f/1024, available/1024.0f/1024, required/1024.0f/1024); if (available >= required) { rdp.texbufs[i].count++; rdp.texbufs[i].clear_allowed = FALSE; texbuf.tex_addr = top; rdp.cur_tex_buf = i; // ZIGGY strange fix texbuf.tmu = rdp.texbufs[i].tmu; rdp.texbufs[i].images[rdp.texbufs[i].count - 1] = texbuf; return &(rdp.texbufs[i].images[rdp.texbufs[i].count - 1]); } } //not found. keep recently accessed bank, clear second one if (!rdp.texbufs[rdp.cur_tex_buf^1].clear_allowed) { //can't clear => can't allocate WriteLog(M64MSG_WARNING, "Can't allocate texture buffer\n"); return 0; } rdp.cur_tex_buf ^= 1; rdp.texbufs[rdp.cur_tex_buf].count = 1; rdp.texbufs[rdp.cur_tex_buf].clear_allowed = FALSE; // ZIGGY strange fix texbuf.tmu = rdp.texbufs[rdp.cur_tex_buf].tmu; texbuf.tex_addr = rdp.texbufs[rdp.cur_tex_buf].begin; rdp.texbufs[rdp.cur_tex_buf].images[0] = texbuf; return &(rdp.texbufs[rdp.cur_tex_buf].images[0]); } BOOL OpenTextureBuffer(COLOR_IMAGE & cimage) { FRDP("OpenTextureBuffer. cur_tex_buf: %d, addr: %08lx, width: %d, height: %d", rdp.cur_tex_buf, cimage.addr, cimage.width, cimage.height); if (!fullscreen) return FALSE; BOOL found = FALSE, search = TRUE; HIRES_COLOR_IMAGE *texbuf = 0; DWORD addr = cimage.addr; DWORD end_addr = addr + cimage.width*cimage.height*cimage.size; if (rdp.motionblur) { if (cimage.format != 0) return FALSE; search = FALSE; } if (rdp.read_whole_frame) { if (settings.PM) //motion blur effects in Paper Mario { rdp.cur_tex_buf = rdp.acc_tex_buf; FRDP("read_whole_frame. last allocated bank: %d\n", rdp.acc_tex_buf); } else { if (!rdp.texbufs[0].clear_allowed || !rdp.texbufs[1].clear_allowed) { if (cimage.status == ci_main) { texbuf = &(rdp.texbufs[rdp.cur_tex_buf].images[0]); found = TRUE; } else { for (int t = 0; (t < rdp.texbufs[rdp.cur_tex_buf].count) && !found; t++) { texbuf = &(rdp.texbufs[rdp.cur_tex_buf].images[t]); if (addr == texbuf->addr && cimage.width == texbuf->width) { texbuf->drawn = FALSE; found = TRUE; } } } } search = FALSE; } } if (search) { for (int i = 0; (i < num_tmu) && !found; i++) { for (int j = 0; (j < rdp.texbufs[i].count) && !found; j++) { texbuf = &(rdp.texbufs[i].images[j]); if (addr == texbuf->addr && cimage.width == texbuf->width) { //texbuf->height = cimage.height; //texbuf->end_addr = end_addr; texbuf->drawn = FALSE; texbuf->format = (WORD)cimage.format; if ((cimage.format != 0)) texbuf->info.format = GR_TEXFMT_ALPHA_INTENSITY_88; else texbuf->info.format = GR_TEXFMT_RGB_565; found = TRUE; rdp.cur_tex_buf = i; rdp.texbufs[i].clear_allowed = FALSE; } else //check intersection { if (!((end_addr <= texbuf->addr) || (addr >= texbuf->end_addr))) //intersected, remove { grTextureBufferExt( texbuf->tmu, texbuf->tex_addr, texbuf->info.smallLodLog2, texbuf->info.largeLodLog2, texbuf->info.aspectRatioLog2, texbuf->info.format, GR_MIPMAPLEVELMASK_BOTH ); grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT ); grDepthMask (FXFALSE); grBufferClear (0, 0, 0xFFFF); grDepthMask (FXTRUE); grRenderBuffer( GR_BUFFER_BACKBUFFER ); rdp.texbufs[i].count--; if (j < rdp.texbufs[i].count) memmove(&(rdp.texbufs[i].images[j]), &(rdp.texbufs[i].images[j+1]), sizeof(HIRES_COLOR_IMAGE)*(rdp.texbufs[i].count-j)); } } } } } if (!found) { RDP (" not found"); texbuf = AllocateTextureBuffer(cimage); } else { RDP (" found"); } if (!texbuf) { RDP(" KO\n"); return FALSE; } rdp.acc_tex_buf = rdp.cur_tex_buf; rdp.cur_image = texbuf; grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT ); //printf("texadr %gMb\n", rdp.cur_image->tex_addr/1024.0f/1024); grTextureBufferExt( rdp.cur_image->tmu, rdp.cur_image->tex_addr, rdp.cur_image->info.smallLodLog2, rdp.cur_image->info.largeLodLog2, rdp.cur_image->info.aspectRatioLog2, rdp.cur_image->info.format, GR_MIPMAPLEVELMASK_BOTH ); ///* if (rdp.cur_image->clear && settings.fb_hires_buf_clear && cimage.changed) { rdp.cur_image->clear = FALSE; grDepthMask (FXFALSE); grBufferClear (0, 0, 0xFFFF); grDepthMask (FXTRUE); } //*/ // memset(gfx.RDRAM+cimage.addr, 0, cimage.width*cimage.height*cimage.size); FRDP(" texaddr: %08lx, tex_width: %d, tex_height: %d, cur_tex_buf: %d, texformat: %d, motionblur: %d\n", rdp.cur_image->tex_addr, rdp.cur_image->tex_width, rdp.cur_image->tex_height, rdp.cur_tex_buf, rdp.cur_image->info.format, rdp.motionblur); return TRUE; } static GrTextureFormat_t TexBufSetupCombiner(BOOL force_rgb = FALSE) { grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); grAlphaBlendFunction (GR_BLEND_ONE, // use alpha compare, but not T0 alpha GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO); grClipWindow (0, 0, settings.scr_res_x, settings.scr_res_y); grDepthBufferFunction (GR_CMP_ALWAYS); grDepthMask (FXFALSE); grCullMode (GR_CULL_DISABLE); grFogMode (GR_FOG_DISABLE); GrTextureFormat_t buf_format = (rdp.hires_tex) ? rdp.hires_tex->info.format : GR_TEXFMT_RGB_565; GrCombineFunction_t color_source = GR_COMBINE_FUNCTION_LOCAL; if (!force_rgb && rdp.black_ci_index > 0 && rdp.black_ci_index <= rdp.copy_ci_index) { color_source = GR_COMBINE_FUNCTION_LOCAL_ALPHA; buf_format = GR_TEXFMT_ALPHA_INTENSITY_88; } if (rdp.hires_tex->tmu == GR_TMU0) { grTexCombine( GR_TMU1, GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE ); grTexCombine( GR_TMU0, color_source, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_NONE, FXFALSE, FXTRUE ); } else { grTexCombine( GR_TMU1, color_source, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_NONE, FXFALSE, FXTRUE ); grTexCombine( GR_TMU0, GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, FXFALSE, FXFALSE ); } return buf_format; } BOOL CloseTextureBuffer(BOOL draw) { if (!fullscreen || !rdp.cur_image) { RDP("CloseTextureBuffer KO\n"); return FALSE; } grRenderBuffer( GR_BUFFER_BACKBUFFER ); if (!draw) { RDP("CloseTextureBuffer no draw, OK\n"); rdp.cur_image = 0; return TRUE; } rdp.hires_tex = rdp.cur_image; rdp.cur_image = 0; GrTextureFormat_t buf_format = rdp.hires_tex->info.format; rdp.hires_tex->info.format = TexBufSetupCombiner(); float ul_x = 0.0f; float ul_y = 0.0f; float ul_u = 0.0f; float ul_v = 0.0f; float lr_x = (float)rdp.hires_tex->scr_width; float lr_y = (float)rdp.hires_tex->scr_height; float lr_u = rdp.hires_tex->u_scale * (float)(rdp.hires_tex->width);//255.0f - (1024 - settings.res_x)*0.25f; float lr_v = rdp.hires_tex->v_scale * (float)(rdp.hires_tex->height);//255.0f - (1024 - settings.res_y)*0.25f; FRDP("lr_x: %f, lr_y: %f, lr_u: %f, lr_v: %f\n", lr_x, lr_y, lr_u, lr_v); // Make the vertices VERTEX v[4] = { { ul_x, ul_y, 1, 1, ul_u, ul_v, ul_u, ul_v }, { lr_x, ul_y, 1, 1, lr_u, ul_v, lr_u, ul_v }, { ul_x, lr_y, 1, 1, ul_u, lr_v, ul_u, lr_v }, { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v } }; ConvertCoordsConvert (v, 4); grTexSource( rdp.hires_tex->tmu, rdp.hires_tex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(rdp.hires_tex->info) ); grDrawTriangle (&v[0], &v[2], &v[1]); grDrawTriangle (&v[2], &v[3], &v[1]); rdp.hires_tex->info.format = buf_format; rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_TEXTURE | UPDATE_ALPHA_COMPARE; if (settings.fog && (rdp.flags & FOG_ENABLED)) { grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT); } RDP("CloseTextureBuffer draw, OK\n"); rdp.hires_tex = 0; return TRUE; } BOOL CopyTextureBuffer(COLOR_IMAGE & fb_from, COLOR_IMAGE & fb_to) { if (!fullscreen) return FALSE; RDP("CopyTextureBuffer. "); if (rdp.cur_image) { if (rdp.cur_image->addr == fb_to.addr) return CloseTextureBuffer(TRUE); rdp.hires_tex = rdp.cur_image; } else if (!FindTextureBuffer(fb_from.addr, (WORD)fb_from.width)) { RDP("Can't find 'from' buffer.\n"); return FALSE; } if (!OpenTextureBuffer(fb_to)) { RDP("Can't open new buffer.\n"); return CloseTextureBuffer(TRUE); } GrTextureFormat_t buf_format = rdp.hires_tex->info.format; rdp.hires_tex->info.format = GR_TEXFMT_RGB_565; TexBufSetupCombiner(TRUE); float ul_x = 0.0f; float ul_y = 0.0f; float lr_x = (float)rdp.hires_tex->scr_width; float lr_y = (float)rdp.hires_tex->scr_height; float lr_u = rdp.hires_tex->u_scale * (float)(rdp.hires_tex->width);//255.0f - (1024 - settings.res_x)*0.25f; float lr_v = rdp.hires_tex->v_scale * (float)(rdp.hires_tex->height);//255.0f - (1024 - settings.res_y)*0.25f; FRDP("lr_x: %f, lr_y: %f\n", lr_x, lr_y); // Make the vertices VERTEX v[4] = { { ul_x, ul_y, 1, 1, 0, 0, 0, 0 }, { lr_x, ul_y, 1, 1, lr_u, 0, lr_u, 0}, { ul_x, lr_y, 1, 1, 0, lr_v, 0, lr_v}, { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v} }; ConvertCoordsConvert (v, 4); grTexSource( rdp.hires_tex->tmu, rdp.hires_tex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(rdp.hires_tex->info) ); grDrawTriangle (&v[0], &v[2], &v[1]); grDrawTriangle (&v[2], &v[3], &v[1]); grRenderBuffer( GR_BUFFER_BACKBUFFER ); grDrawTriangle (&v[0], &v[2], &v[1]); grDrawTriangle (&v[2], &v[3], &v[1]); rdp.hires_tex->info.format = buf_format; rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_TEXTURE | UPDATE_ALPHA_COMPARE; if (settings.fog && (rdp.flags & FOG_ENABLED)) grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT); RDP("CopyTextureBuffer draw, OK\n"); rdp.hires_tex = 0; rdp.cur_image = 0; return TRUE; } BOOL SwapTextureBuffer() { if (!fullscreen || !rdp.hires_tex) return FALSE; RDP("SwapTextureBuffer."); HIRES_COLOR_IMAGE * texbuf = AllocateTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); if (!texbuf) { RDP(" failed!\n"); return FALSE; } TexBufSetupCombiner(); float ul_x = 0.0f; float ul_y = 0.0f; float lr_x = (float)rdp.hires_tex->scr_width; float lr_y = (float)rdp.hires_tex->scr_height; float lr_u = rdp.hires_tex->u_scale * (float)(rdp.hires_tex->width);//255.0f - (1024 - settings.res_x)*0.25f; float lr_v = rdp.hires_tex->v_scale * (float)(rdp.hires_tex->height);//255.0f - (1024 - settings.res_y)*0.25f; // Make the vertices VERTEX v[4] = { { ul_x, ul_y, 1, 1, 0, 0, 0, 0 }, { lr_x, ul_y, 1, 1, lr_u, 0, lr_u, 0}, { ul_x, lr_y, 1, 1, 0, lr_v, 0, lr_v}, { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v} }; int tex = rdp.tex; rdp.tex = 1; ConvertCoordsConvert (v, 4); rdp.tex = tex; grTexSource( rdp.hires_tex->tmu, rdp.hires_tex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(rdp.hires_tex->info) ); texbuf->tile_uls = rdp.hires_tex->tile_uls; texbuf->tile_ult = rdp.hires_tex->tile_ult; texbuf->v_shift = rdp.hires_tex->v_shift; rdp.cur_image = texbuf; grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT ); grSstOrigin(GR_ORIGIN_UPPER_LEFT); grTextureBufferExt( rdp.cur_image->tmu, rdp.cur_image->tex_addr, rdp.cur_image->info.smallLodLog2, rdp.cur_image->info.largeLodLog2, rdp.cur_image->info.aspectRatioLog2, rdp.cur_image->info.format, GR_MIPMAPLEVELMASK_BOTH ); grDrawTriangle (&v[0], &v[2], &v[1]); grDrawTriangle (&v[2], &v[3], &v[1]); rdp.texbufs[rdp.hires_tex->tmu].clear_allowed = TRUE; rdp.texbufs[rdp.hires_tex->tmu].count = 0; rdp.hires_tex = rdp.cur_image; rdp.cur_image = 0; grRenderBuffer( GR_BUFFER_BACKBUFFER ); rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_TEXTURE | UPDATE_ALPHA_COMPARE; if (settings.fog && (rdp.flags & FOG_ENABLED)) { grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT); } RDP("SwapTextureBuffer draw, OK\n"); return TRUE; } BOOL FindTextureBuffer(DWORD addr, WORD width) { if (rdp.skip_drawing) return FALSE; FRDP("FindTextureBuffer. addr: %08lx, width: %d, scale_x: %f\n", addr, width, rdp.scale_x); BOOL found = FALSE; DWORD shift = 0; for (int i = 0; i < num_tmu && !found; i++) { BYTE index = rdp.cur_tex_buf^i; for (int j = 0; j < rdp.texbufs[index].count && !found; j++) { rdp.hires_tex = &(rdp.texbufs[index].images[j]); if(addr >= rdp.hires_tex->addr && addr < rdp.hires_tex->end_addr)// && rdp.timg.format == 0) { if (width == 1 || rdp.hires_tex->width == width) { shift = addr - rdp.hires_tex->addr; if (!rdp.motionblur) rdp.cur_tex_buf = index; found = TRUE; // FRDP("FindTextureBuffer, found in TMU%d buffer: %d\n", rdp.hires_tex->tmu, j); } else //new texture is loaded into this place, texture buffer is not valid anymore { rdp.texbufs[index].count--; if (j < rdp.texbufs[index].count) memmove(&(rdp.texbufs[index].images[j]), &(rdp.texbufs[index].images[j+1]), sizeof(HIRES_COLOR_IMAGE)*(rdp.texbufs[index].count-j)); } } } } if (found) { rdp.hires_tex->tile_uls = 0; rdp.hires_tex->tile_ult = 0; if (shift > 0) { shift >>= 1; rdp.hires_tex->v_shift = shift / rdp.hires_tex->width; rdp.hires_tex->u_shift = shift % rdp.hires_tex->width; } else { rdp.hires_tex->v_shift = 0; rdp.hires_tex->u_shift = 0; } /* if (rdp.timg.format == 0) //RGB rdp.hires_tex->info.format = GR_TEXFMT_RGB_565; else //IA rdp.hires_tex->info.format = GR_TEXFMT_ALPHA_INTENSITY_88; */ FRDP("FindTextureBuffer, found, v_shift: %d, format: %d\n", rdp.hires_tex->v_shift, rdp.hires_tex->info.format); return TRUE; } rdp.hires_tex = 0; RDP("FindTextureBuffer, not found\n"); return FALSE; } mupen64plus-video-glide64-src-2.6.0/src/TexBuffer.h000066400000000000000000000037331464507525600217240ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // //**************************************************************** // // Dec 2003 created by Gonetz // //**************************************************************** #ifndef TEXBUFFER_H #define TEXBUFFER_H #include "winlnxdefs.h" #include "rdp.h" BOOL OpenTextureBuffer(COLOR_IMAGE & cimage); BOOL CloseTextureBuffer(BOOL draw = FALSE); BOOL CopyTextureBuffer(COLOR_IMAGE & fb_from, COLOR_IMAGE & fb_to); BOOL SwapTextureBuffer(); BOOL FindTextureBuffer(DWORD addr, WORD width); #endif // ifndef TEXBUFFER mupen64plus-video-glide64-src-2.6.0/src/TexCache.cpp000066400000000000000000001315731464507525600220550ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * Copyright (c) 2008 Günther * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** #define M64P_PLUGIN_PROTOTYPES 1 #include "m64p_types.h" #include "m64p_plugin.h" #include "m64p_config.h" #include "m64p_vidext.h" #include "TexCache.h" #include "Combine.h" #include "Util.h" void LoadTex (int id, int tmu); BYTE tex1[512*512*4]; // temporary texture BYTE tex2[512*512*4]; BYTE *texture; #include "TexLoad.h" // texture loading functions, ONLY INCLUDE IN THIS FILE!!! #include "MiClWr16b.h" // Mirror/Clamp/Wrap functions, ONLY INCLUDE IN THIS FILE!!! #include "MiClWr8b.h" // Mirror/Clamp/Wrap functions, ONLY INCLUDE IN THIS FILE!!! #include "TexConv.h" // texture conversions, ONLY INCLUDE IN THIS FILE!!! #include "TexMod.h" #include "TexModCI.h" #include "CRC.h" #ifndef _WIN32 #include #endif // _WIN32 typedef struct TEXINFO_t { int real_image_width, real_image_height; // FOR ALIGNMENT PURPOSES ONLY!!! int tile_width, tile_height; int mask_width, mask_height; int width, height; int wid_64, line; DWORD crc; DWORD flags; int splits, splitheight; } TEXINFO; TEXINFO texinfo[2]; int tex_found[2][MAX_TMU]; //**************************************************************** // List functions typedef struct NODE_t { DWORD crc; CACHE_LUT* data; int tmu; int number; NODE_t *pNext; } NODE; NODE *cachelut[256]; void AddToList (NODE **list, DWORD crc, CACHE_LUT* data, int tmu, int number) { NODE *node = new NODE; node->crc = crc; node->data = data; node->tmu = tmu; node->number = number; node->pNext = *list; *list = node; } void DeleteList (NODE **list) { while (*list) { NODE *next = (*list)->pNext; delete (*list); *list = next; } } void TexCacheInit () { for (int i=0; i<256; i++) { cachelut[i] = NULL; } } //**************************************************************** uint32_t textureCRC(uint8_t *addr, int width, int height, int line) { uint32_t crc = 0; uint32_t *pixelpos; unsigned int i; uint64_t twopixel_crc; pixelpos = (uint32_t*)addr; for (; height; height--) { for (i = width; i; --i) { twopixel_crc = i * (uint64_t)(pixelpos[1] + pixelpos[0] + crc); crc = (uint32_t) ((twopixel_crc >> 32) + twopixel_crc); pixelpos += 2; } crc = ((unsigned int)height * (uint64_t)crc >> 32) + height * crc; pixelpos = (uint32_t *)((char *)pixelpos + line); } return crc; } //**************************************************************** // GetTexInfo - gets information for either t0 or t1, checks if in cache & fills tex_found void GetTexInfo (int id, int tile) { FRDP (" | |-+ GetTexInfo (id: %d, tile: %d)\n", id, tile); TEXINFO *info = &texinfo[id]; int tile_width, tile_height; int mask_width, mask_height; int width, height; int wid_64, line, bpl; // Get width and height tile_width = rdp.tiles[tile].lr_s - rdp.tiles[tile].ul_s + 1; tile_height = rdp.tiles[tile].lr_t - rdp.tiles[tile].ul_t + 1; mask_width = (rdp.tiles[tile].mask_s==0)?(tile_width):(1 << rdp.tiles[tile].mask_s); mask_height = (rdp.tiles[tile].mask_t==0)?(tile_height):(1 << rdp.tiles[tile].mask_t); if (settings.alt_tex_size) { // ** ALTERNATE TEXTURE SIZE METHOD ** // Helps speed in some games that loaded weird-sized textures, but could break other // textures. // Get the width/height to load if ((rdp.tiles[tile].clamp_s && tile_width <= 256) || (mask_width > 256)) { // loading width width = std::min(mask_width, tile_width); // actual width rdp.tiles[tile].width = tile_width; } else { // wrap all the way width = std::min(mask_width, tile_width); // changed from mask_width only rdp.tiles[tile].width = width; } if ((rdp.tiles[tile].clamp_t && tile_height <= 256) || (mask_height > 256)) { // loading height height = std::min(mask_height, tile_height); // actual height rdp.tiles[tile].height = tile_height; } else { // wrap all the way height = std::min(mask_height, tile_height); rdp.tiles[tile].height = height; } } else { // ** NORMAL TEXTURE SIZE METHOD ** // This is the 'correct' method for determining texture size, but may cause certain // textures to load too large & make the whole game go slow. // Get the width/height to load if ((rdp.tiles[tile].clamp_s && tile_width <= 256) || (mask_width > 256)) { // loading width width = std::min(mask_width, tile_width); // actual width rdp.tiles[tile].width = tile_width; } else { // wrap all the way width = mask_width; rdp.tiles[tile].width = mask_width; } if ((rdp.tiles[tile].clamp_t && tile_height <= 256) || (mask_height > 256)) { // loading height height = std::min(mask_height, tile_height); // actual height rdp.tiles[tile].height = tile_height; } else { // wrap all the way height = mask_height; rdp.tiles[tile].height = mask_height; } } // without any large texture fixing-up; for alignment int real_image_width = rdp.tiles[tile].width; int real_image_height = rdp.tiles[tile].height; bpl = width << rdp.tiles[tile].size >> 1; // ** COMMENT THIS TO DISABLE LARGE TEXTURES #ifdef LARGE_TEXTURE_HANDLING if (width > 256) { info->splits = ((width-1)>>8)+1; info->splitheight = rdp.tiles[tile].height; rdp.tiles[tile].height *= info->splits; rdp.tiles[tile].width = 256; width = 256; } else #endif // ** { info->splits = 1; } RDP (" | | |-+ Texture approved:\n"); FRDP (" | | | |- tmem: %08lx\n", rdp.tiles[tile].t_mem); FRDP (" | | | |- load width: %d\n", width); FRDP (" | | | |- load height: %d\n", height); FRDP (" | | | |- actual width: %d\n", rdp.tiles[tile].width); FRDP (" | | | |- actual height: %d\n", rdp.tiles[tile].height); FRDP (" | | | |- size: %d\n", rdp.tiles[tile].size); FRDP (" | | | +- format: %d\n", rdp.tiles[tile].format); RDP (" | | |- Calculating CRC... "); // ** CRC CHECK wid_64 = width << (rdp.tiles[tile].size) >> 1; if (rdp.tiles[tile].size == 3) { if (wid_64 & 15) wid_64 += 16; wid_64 &= 0xFFFFFFF0; } else { if (wid_64 & 7) wid_64 += 8; // round up } wid_64 = wid_64>>3; // Texture too big for tmem & needs to wrap? (trees in mm) if (settings.wrap_big_tex && (rdp.tiles[tile].t_mem + std::min(height, tile_height) * (rdp.tiles[tile].line<<3) > 4096)) { RDP ("TEXTURE WRAPS TMEM!!! "); // calculate the y value that intersects at 4096 bytes int y = (4096 - rdp.tiles[tile].t_mem) / (rdp.tiles[tile].line<<3); rdp.tiles[tile].clamp_t = 0; rdp.tiles[tile].lr_t = rdp.tiles[tile].ul_t + y - 1; // calc mask int shift; for (shift=0; (1< 0) crc = textureCRC(addr, wid_64, height, line); } else { crc = 0xFFFFFFFF; // unsigned __int64 * addr = (unsigned __int64 *)&rdp.tmem[rdp.tiles[tile].t_mem]; BYTE * addr = rdp.tmem + (rdp.tiles[tile].t_mem<<3); DWORD line2 = std::max(line,1); line2 <<= 3; for (int y = 0; y < height; y++) { crc = CRC_Calculate( crc, (void*)addr, bpl ); addr += line2; } line = (line - wid_64) << 3; if (wid_64 < 1) wid_64 = 1; } if ((rdp.tiles[tile].size < 2) && (rdp.tlut_mode != 0)) { if (rdp.tiles[tile].size == 0) crc += rdp.pal_8_crc[rdp.tiles[tile].palette]; else crc += rdp.pal_256_crc; } FRDP ("Done. CRC is: %08lx.\n", crc); DWORD flags = (rdp.tiles[tile].clamp_s << 23) | (rdp.tiles[tile].mirror_s << 22) | (rdp.tiles[tile].mask_s << 18) | (rdp.tiles[tile].clamp_t << 17) | (rdp.tiles[tile].mirror_t << 16) | (rdp.tiles[tile].mask_t << 12); info->real_image_width = real_image_width; info->real_image_height = real_image_height; info->tile_width = tile_width; info->tile_height = tile_height; info->mask_width = mask_width; info->mask_height = mask_height; info->width = width; info->height = height; info->wid_64 = wid_64; info->line = line; info->crc = crc; info->flags = flags; // Search the texture cache for this texture RDP (" | | |-+ Checking cache...\n"); int t; CACHE_LUT *cache; // this is the OLD cache searching, searches ALL textures /* for (t=0; tcrc && //rdp.timg.addr == cache->addr && // not totally correct, but will help //rdp.addr[rdp.tiles[tile].t_mem] == cache->addr && // more correct rdp.tiles[tile].width == cache->width && rdp.tiles[tile].height == cache->height && rdp.tiles[tile].format == cache->format && rdp.tiles[tile].size == cache->size && rdp.tiles[tile].palette == cache->palette && pal_crc == cache->pal_crc && flags == cache->flags) { FRDP (" | | | |- Texture found in cache (tmu=%d).\n", t); tex_found[id][t] = i; break; } } } for (; t>24]; DWORD mod_mask = (rdp.tiles[tile].format == 2)?0xFFFFFFFF:0xF0F0F0F0; while (node) { if (node->crc == crc) { cache = (CACHE_LUT*)node->data; if (tex_found[id][node->tmu] == -1 && rdp.tiles[tile].width == cache->width && rdp.tiles[tile].height == cache->height && rdp.tiles[tile].format == cache->format && rdp.tiles[tile].size == cache->size && rdp.tiles[tile].palette == cache->palette && flags == cache->flags) { if (cache->mod == mod && (cache->mod_color&mod_mask) == (modcolor&mod_mask) && (cache->mod_color1&mod_mask) == (modcolor1&mod_mask) && (cache->mod_color2&mod_mask) == (modcolor2&mod_mask) && abs(static_cast(cache->mod_factor - modfactor)) < 8) { FRDP (" | | | |- Texture found in cache (tmu=%d).\n", node->tmu); tex_found[id][node->tmu] = node->number; // if (rdp.addr[rdp.tiles[tile].t_mem] == cache->addr) // return; } } } node = node->pNext; } RDP (" | | | +- Done.\n | | +- GetTexInfo end\n"); } //**************************************************************** // ChooseBestTmu - chooses the best TMU to load to (the one with the most memory) int ChooseBestTmu (int tmu1, int tmu2) { if (!fullscreen) return tmu1; if (tmu1 >= num_tmu) return tmu2; if (tmu2 >= num_tmu) return tmu1; if (grTexMaxAddress(tmu1)-rdp.tmem_ptr[tmu1] > grTexMaxAddress(tmu2)-rdp.tmem_ptr[tmu2]) return tmu1; else return tmu2; } //**************************************************************** // SelectHiresTex - select texture from texture buffer static void SelectHiresTex() { FRDP ("SelectHiresTex: tex: %d, tmu: %d, tile: %d\n", rdp.tex, rdp.hires_tex->tmu, rdp.hires_tex->tile); grTexSource( rdp.hires_tex->tmu, rdp.hires_tex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(rdp.hires_tex->info) ); if (rdp.tex == 3 && rdp.hires_tex->tmu == rdp.hires_tex->tile) return; GrCombineFunction_t color_source = (rdp.hires_tex->info.format == GR_TEXFMT_RGB_565) ? GR_COMBINE_FUNCTION_LOCAL : GR_COMBINE_FUNCTION_LOCAL_ALPHA; if (rdp.hires_tex->tmu == GR_TMU0) { grTexCombine( GR_TMU1, GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE ); grTexCombine( GR_TMU0, color_source, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE); } else { grTexCombine( GR_TMU1, color_source, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE); grTexCombine( GR_TMU0, GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, FXFALSE, FXFALSE ); } } //**************************************************************** // TexCache - does texture loading after combiner is set void TexCache () { RDP (" |-+ TexCache called\n"); if (rdp.tex & 1) GetTexInfo (0, rdp.cur_tile); if (rdp.tex & 2) GetTexInfo (1, rdp.cur_tile+1); #define TMUMODE_NORMAL 0 #define TMUMODE_PASSTHRU 1 #define TMUMODE_NONE 2 int tmu_0, tmu_1; int tmu_0_mode=0, tmu_1_mode=0; // Select the best TMUs to use (removed 3 tmu support, unnecessary) if (rdp.tex == 3) // T0 and T1 { tmu_0 = 0; tmu_1 = 1; } else if (rdp.tex == 2) // T1 { if (tex_found[1][0] != -1) // T1 found in tmu 0 tmu_1 = 0; else if (tex_found[1][1] != -1) // T1 found in tmu 1 tmu_1 = 1; else // T1 not found tmu_1 = ChooseBestTmu (0, 1); tmu_0 = !tmu_1; tmu_0_mode = (tmu_0==1)?TMUMODE_NONE:TMUMODE_PASSTHRU; } else if (rdp.tex == 1) // T0 { if (tex_found[0][0] != -1) // T0 found in tmu 0 tmu_0 = 0; else if (tex_found[0][1] != -1) // T0 found in tmu 1 tmu_0 = 1; else // T0 not found tmu_0 = ChooseBestTmu (0, 1); tmu_1 = !tmu_0; tmu_1_mode = (tmu_1==1)?TMUMODE_NONE:TMUMODE_PASSTHRU; } else // no texture { tmu_0 = 0; tmu_0_mode = TMUMODE_NONE; tmu_1 = 0; tmu_1_mode = TMUMODE_NONE; } FRDP (" | |-+ Modes set:\n | | |- tmu_0 = %d\n | | |- tmu_1 = %d\n", tmu_0, tmu_1); FRDP (" | | |- tmu_0_mode = %d\n | | |- tmu_1_mode = %d\n", tmu_0_mode, tmu_1_mode); if (tmu_0_mode == TMUMODE_PASSTHRU) { cmb.tmu0_func = cmb.tmu0_a_func = GR_COMBINE_FUNCTION_SCALE_OTHER; cmb.tmu0_fac = cmb.tmu0_a_fac = GR_COMBINE_FACTOR_ONE; if (cmb.tex_cmb_ext_use) { cmb.t0c_ext_a = GR_CMBX_OTHER_TEXTURE_RGB; cmb.t0c_ext_a_mode = GR_FUNC_MODE_X; cmb.t0c_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB; cmb.t0c_ext_b_mode = GR_FUNC_MODE_ZERO; cmb.t0c_ext_c = GR_CMBX_ZERO; cmb.t0c_ext_c_invert = 1; cmb.t0c_ext_d = GR_CMBX_ZERO; cmb.t0c_ext_d_invert = 0; cmb.t0a_ext_a = GR_CMBX_OTHER_TEXTURE_ALPHA; cmb.t0a_ext_a_mode = GR_FUNC_MODE_X; cmb.t0a_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA; cmb.t0a_ext_b_mode = GR_FUNC_MODE_ZERO; cmb.t0a_ext_c = GR_CMBX_ZERO; cmb.t0a_ext_c_invert = 1; cmb.t0a_ext_d = GR_CMBX_ZERO; cmb.t0a_ext_d_invert = 0; } } else if (tmu_0_mode == TMUMODE_NONE) { cmb.tmu0_func = cmb.tmu0_a_func = GR_COMBINE_FUNCTION_NONE; cmb.tmu0_fac = cmb.tmu0_a_fac = GR_COMBINE_FACTOR_NONE; if (cmb.tex_cmb_ext_use) { cmb.t0c_ext_a = GR_CMBX_LOCAL_TEXTURE_RGB; cmb.t0c_ext_a_mode = GR_FUNC_MODE_ZERO; cmb.t0c_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB; cmb.t0c_ext_b_mode = GR_FUNC_MODE_ZERO; cmb.t0c_ext_c = GR_CMBX_ZERO; cmb.t0c_ext_c_invert = 0; cmb.t0c_ext_d = GR_CMBX_ZERO; cmb.t0c_ext_d_invert = 0; cmb.t0a_ext_a = GR_CMBX_LOCAL_TEXTURE_ALPHA; cmb.t0a_ext_a_mode = GR_FUNC_MODE_ZERO; cmb.t0a_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA; cmb.t0a_ext_b_mode = GR_FUNC_MODE_ZERO; cmb.t0a_ext_c = GR_CMBX_ZERO; cmb.t0a_ext_c_invert = 0; cmb.t0a_ext_d = GR_CMBX_ZERO; cmb.t0a_ext_d_invert = 0; } } if (tmu_1_mode == TMUMODE_PASSTHRU) { cmb.tmu1_func = cmb.tmu1_a_func = GR_COMBINE_FUNCTION_SCALE_OTHER; cmb.tmu1_fac = cmb.tmu1_a_fac = GR_COMBINE_FACTOR_ONE; if (cmb.tex_cmb_ext_use) { cmb.t1c_ext_a = GR_CMBX_OTHER_TEXTURE_RGB; cmb.t1c_ext_a_mode = GR_FUNC_MODE_X; cmb.t1c_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB; cmb.t1c_ext_b_mode = GR_FUNC_MODE_ZERO; cmb.t1c_ext_c = GR_CMBX_ZERO; cmb.t1c_ext_c_invert = 1; cmb.t1c_ext_d = GR_CMBX_ZERO; cmb.t1c_ext_d_invert = 0; cmb.t1a_ext_a = GR_CMBX_OTHER_TEXTURE_ALPHA; cmb.t1a_ext_a_mode = GR_FUNC_MODE_X; cmb.t1a_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA; cmb.t1a_ext_b_mode = GR_FUNC_MODE_ZERO; cmb.t1a_ext_c = GR_CMBX_ZERO; cmb.t1a_ext_c_invert = 1; cmb.t1a_ext_d = GR_CMBX_ZERO; cmb.t1a_ext_d_invert = 0; } } else if (tmu_1_mode == TMUMODE_NONE) { cmb.tmu1_func = cmb.tmu1_a_func = GR_COMBINE_FUNCTION_NONE; cmb.tmu1_fac = cmb.tmu1_a_fac = GR_COMBINE_FACTOR_NONE; if (cmb.tex_cmb_ext_use) { cmb.t1c_ext_a = GR_CMBX_LOCAL_TEXTURE_RGB; cmb.t1c_ext_a_mode = GR_FUNC_MODE_ZERO; cmb.t1c_ext_b = GR_CMBX_LOCAL_TEXTURE_RGB; cmb.t1c_ext_b_mode = GR_FUNC_MODE_ZERO; cmb.t1c_ext_c = GR_CMBX_ZERO; cmb.t1c_ext_c_invert = 0; cmb.t1c_ext_d = GR_CMBX_ZERO; cmb.t1c_ext_d_invert = 0; cmb.t1a_ext_a = GR_CMBX_LOCAL_TEXTURE_ALPHA; cmb.t1a_ext_a_mode = GR_FUNC_MODE_ZERO; cmb.t1a_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA; cmb.t1a_ext_b_mode = GR_FUNC_MODE_ZERO; cmb.t1a_ext_c = GR_CMBX_ZERO; cmb.t1a_ext_c_invert = 0; cmb.t1a_ext_d = GR_CMBX_ZERO; cmb.t1a_ext_d_invert = 0; } } // little change to make single-tmu cards look better, use first texture no matter what if (num_tmu == 1) { if (rdp.best_tex == 0) { cmb.tmu0_func = cmb.tmu0_a_func = GR_COMBINE_FUNCTION_LOCAL; cmb.tmu0_fac = cmb.tmu0_a_fac = GR_COMBINE_FACTOR_NONE; tmu_0 = 0; tmu_1 = 1; } else { cmb.tmu1_func = cmb.tmu1_a_func = GR_COMBINE_FUNCTION_LOCAL; cmb.tmu1_fac = cmb.tmu1_a_fac = GR_COMBINE_FACTOR_NONE; tmu_1 = 0; tmu_0 = 1; } } rdp.t0 = tmu_0; rdp.t1 = tmu_1; // SET the combiner if (fullscreen) { if (rdp.allow_combine) { // Now actually combine if (cmb.cmb_ext_use) { RDP (" | | | |- combiner extension\n"); if (!(cmb.cmb_ext_use & COMBINE_EXT_COLOR)) ColorCombinerToExtension (); if (!(cmb.cmb_ext_use & COMBINE_EXT_ALPHA)) AlphaCombinerToExtension (); cmb.grColorCombineExt(cmb.c_ext_a, cmb.c_ext_a_mode, cmb.c_ext_b, cmb.c_ext_b_mode, cmb.c_ext_c, cmb.c_ext_c_invert, cmb.c_ext_d, cmb.c_ext_d_invert, 0, 0); cmb.grAlphaCombineExt(cmb.a_ext_a, cmb.a_ext_a_mode, cmb.a_ext_b, cmb.a_ext_b_mode, cmb.a_ext_c, cmb.a_ext_c_invert, cmb.a_ext_d, cmb.a_ext_d_invert, 0, 0); } else { grColorCombine (cmb.c_fnc, cmb.c_fac, cmb.c_loc, cmb.c_oth, FXFALSE); grAlphaCombine (cmb.a_fnc, cmb.a_fac, cmb.a_loc, cmb.a_oth, FXFALSE); } grConstantColorValue (cmb.ccolor); grAlphaBlendFunction (cmb.abf1, cmb.abf2, GR_BLEND_ZERO, GR_BLEND_ZERO); } if (tmu_1 < num_tmu) { if (cmb.tex_cmb_ext_use) { RDP (" | | | |- combiner extension tmu1\n"); if (!(cmb.tex_cmb_ext_use & TEX_COMBINE_EXT_COLOR)) TexColorCombinerToExtension (GR_TMU1); if (!(cmb.tex_cmb_ext_use & TEX_COMBINE_EXT_ALPHA)) TexAlphaCombinerToExtension (GR_TMU1); cmb.grTexColorCombineExt(tmu_1, cmb.t1c_ext_a, cmb.t1c_ext_a_mode, cmb.t1c_ext_b, cmb.t1c_ext_b_mode, cmb.t1c_ext_c, cmb.t1c_ext_c_invert, cmb.t1c_ext_d, cmb.t1c_ext_d_invert, 0, 0); cmb.grTexAlphaCombineExt(tmu_1, cmb.t1a_ext_a, cmb.t1a_ext_a_mode, cmb.t1a_ext_b, cmb.t1a_ext_b_mode, cmb.t1a_ext_c, cmb.t1a_ext_c_invert, cmb.t1a_ext_d, cmb.t1a_ext_d_invert, 0, 0); cmb.grConstantColorValueExt(tmu_1, cmb.tex_ccolor); } else { grTexCombine (tmu_1, cmb.tmu1_func, cmb.tmu1_fac, cmb.tmu1_a_func, cmb.tmu1_a_fac, cmb.tmu1_invert, cmb.tmu1_a_invert); if (cmb.combine_ext) cmb.grConstantColorValueExt(tmu_1, 0); } grTexDetailControl (tmu_1, cmb.dc1_lodbias, cmb.dc1_detailscale, cmb.dc1_detailmax); grTexLodBiasValue (tmu_1, cmb.lodbias1); } if (tmu_0 < num_tmu) { if (cmb.tex_cmb_ext_use) { RDP (" | | | |- combiner extension tmu0\n"); if (!(cmb.tex_cmb_ext_use & TEX_COMBINE_EXT_COLOR)) TexColorCombinerToExtension (GR_TMU0); if (!(cmb.tex_cmb_ext_use & TEX_COMBINE_EXT_ALPHA)) TexAlphaCombinerToExtension (GR_TMU0); cmb.grTexColorCombineExt(tmu_0, cmb.t0c_ext_a, cmb.t0c_ext_a_mode, cmb.t0c_ext_b, cmb.t0c_ext_b_mode, cmb.t0c_ext_c, cmb.t0c_ext_c_invert, cmb.t0c_ext_d, cmb.t0c_ext_d_invert, 0, 0); cmb.grTexAlphaCombineExt(tmu_0, cmb.t0a_ext_a, cmb.t0a_ext_a_mode, cmb.t0a_ext_b, cmb.t0a_ext_b_mode, cmb.t0a_ext_c, cmb.t0a_ext_c_invert, cmb.t0a_ext_d, cmb.t0a_ext_d_invert, 0, 0); cmb.grConstantColorValueExt(tmu_0, cmb.tex_ccolor); } else { grTexCombine (tmu_0, cmb.tmu0_func, cmb.tmu0_fac, cmb.tmu0_a_func, cmb.tmu0_a_fac, cmb.tmu0_invert, cmb.tmu0_a_invert); if (cmb.combine_ext) cmb.grConstantColorValueExt(tmu_0, 0); } grTexDetailControl (tmu_0, cmb.dc0_lodbias, cmb.dc0_detailscale, cmb.dc0_detailmax); grTexLodBiasValue (tmu_0, cmb.lodbias0); } } if ((rdp.tex & 1) && tmu_0 < num_tmu) { if (tex_found[0][tmu_0] != -1) { RDP (" | |- T0 found in cache.\n"); if (fullscreen) { CACHE_LUT *cache = &rdp.cache[tmu_0][tex_found[0][tmu_0]]; rdp.cur_cache_n[0] = tex_found[0][tmu_0]; rdp.cur_cache[0] = cache; rdp.cur_cache[0]->last_used = frame_count; rdp.cur_cache[0]->uses = rdp.debug_n; grTexSource (tmu_0, (grTexMinAddress(tmu_0) + cache->tmem_addr), GR_MIPMAPLEVELMASK_BOTH, &cache->t_info); } } else LoadTex (0, tmu_0); } if ((rdp.tex & 2) && tmu_1 < num_tmu) { if (tex_found[1][tmu_1] != -1) { if (fullscreen) { CACHE_LUT *cache = &rdp.cache[tmu_1][tex_found[1][tmu_1]]; rdp.cur_cache_n[1] = tex_found[1][tmu_1]; rdp.cur_cache[1] = cache; rdp.cur_cache[1]->last_used = frame_count; rdp.cur_cache[1]->uses = rdp.debug_n; grTexSource (tmu_1, (grTexMinAddress(tmu_1) + cache->tmem_addr), GR_MIPMAPLEVELMASK_BOTH, &cache->t_info); } } else LoadTex (1, tmu_1); } if (fullscreen) { for (int i=0; i<2; i++) { int tmu; if (i==0) tmu=tmu_0; else tmu=tmu_1; if (tmu >= num_tmu) continue; int tile = rdp.cur_tile + i; if (settings.filtering == 0) { int filter = (rdp.filter_mode!=2)?GR_TEXTUREFILTER_POINT_SAMPLED:GR_TEXTUREFILTER_BILINEAR; grTexFilterMode (tmu, filter, filter); } else { int filter = (settings.filtering==1)?GR_TEXTUREFILTER_BILINEAR:GR_TEXTUREFILTER_POINT_SAMPLED; grTexFilterMode (tmu, filter, filter); } DWORD mode_s, mode_t; if ((rdp.tiles[tile].clamp_s || rdp.tiles[tile].mask_s == 0) && rdp.tiles[tile].lr_s-rdp.tiles[tile].ul_s < 256) mode_s = GR_TEXTURECLAMP_CLAMP; else { if (rdp.tiles[tile].mirror_s && sup_mirroring) mode_s = GR_TEXTURECLAMP_MIRROR_EXT; else mode_s = GR_TEXTURECLAMP_WRAP; } if ((rdp.tiles[tile].clamp_t || rdp.tiles[tile].mask_t == 0) && rdp.tiles[tile].lr_t-rdp.tiles[tile].ul_t < 256) mode_t = GR_TEXTURECLAMP_CLAMP; else { if (rdp.tiles[tile].mirror_t && sup_mirroring) mode_t = GR_TEXTURECLAMP_MIRROR_EXT; else mode_t = GR_TEXTURECLAMP_WRAP; } grTexClampMode (tmu, mode_s, mode_t); } if (rdp.hires_tex) SelectHiresTex(); } RDP (" | +- TexCache End\n"); } //**************************************************************** // ClearCache - clear the texture cache for BOTH tmus void ClearCache () { rdp.tmem_ptr[0] = offset_textures; rdp.n_cached[0] = 0; rdp.tmem_ptr[1] = offset_texbuf1; rdp.n_cached[1] = 0; for (int i=0; i<256; i++) { DeleteList (&cachelut[i]); } } //**************************************************************** // LoadTex - does the actual texture loading after everything is prepared void LoadTex (int id, int tmu) { FRDP (" | |-+ LoadTex (id: %d, tmu: %d)\n", id, tmu); int td = rdp.cur_tile + id; int lod, aspect; CACHE_LUT *cache; if (texinfo[id].width < 0 || texinfo[id].height < 0) return; // Clear the cache if it's full if (rdp.n_cached[tmu] >= MAX_CACHE) { RDP ("Cache count reached, clearing...\n"); ClearCache (); if (id == 1 && rdp.tex == 3) LoadTex (0, rdp.t0); } // Get this cache object cache = &rdp.cache[tmu][rdp.n_cached[tmu]]; rdp.cur_cache[id] = cache; rdp.cur_cache_n[id] = rdp.n_cached[tmu]; // Set the data cache->line = rdp.tiles[td].line; cache->addr = rdp.addr[rdp.tiles[td].t_mem]; cache->crc = texinfo[id].crc; cache->palette = rdp.tiles[td].palette; cache->width = rdp.tiles[td].width; cache->height = rdp.tiles[td].height; cache->format = rdp.tiles[td].format; cache->size = rdp.tiles[td].size; cache->tmem_addr = rdp.tmem_ptr[tmu]; cache->set_by = rdp.timg.set_by; cache->texrecting = rdp.texrecting; cache->last_used = frame_count; cache->uses = rdp.debug_n; cache->flags = texinfo[id].flags; // Add this cache to the list AddToList (&cachelut[cache->crc>>24], cache->crc, cache, tmu, rdp.n_cached[tmu]); rdp.n_cached[tmu] ++; // temporary cache->t_info.format = GR_TEXFMT_ARGB_1555; // Calculate lod and aspect DWORD size_x = rdp.tiles[td].width; DWORD size_y = rdp.tiles[td].height; // make size_x and size_y both powers of two if (size_x > 256) size_x = 256; if (size_y > 256) size_y = 256; int shift; for (shift=0; (1<scale = 256.0f; break; case 2: lod = GR_LOD_LOG2_2; cache->scale = 128.0f; break; case 4: lod = GR_LOD_LOG2_4; cache->scale = 64.0f; break; case 8: lod = GR_LOD_LOG2_8; cache->scale = 32.0f; break; case 16: lod = GR_LOD_LOG2_16; cache->scale = 16.0f; break; case 32: lod = GR_LOD_LOG2_32; cache->scale = 8.0f; break; case 64: lod = GR_LOD_LOG2_64; cache->scale = 4.0f; break; case 128: lod = GR_LOD_LOG2_128; cache->scale = 2.0f; break; //case 256: default: lod = GR_LOD_LOG2_256; cache->scale = 1.0f; break; // No default here, can't be a non-power of two, see above } // Calculate the aspect ratio if (size_x >= size_y) { int ratio = size_x / size_y; switch (ratio) { case 1: aspect = GR_ASPECT_LOG2_1x1; cache->scale_x = 1.0f; cache->scale_y = 1.0f; break; case 2: aspect = GR_ASPECT_LOG2_2x1; cache->scale_x = 1.0f; cache->scale_y = 0.5f; real_y >>= 1; break; case 4: aspect = GR_ASPECT_LOG2_4x1; cache->scale_x = 1.0f; cache->scale_y = 0.25f; real_y >>= 2; break; //case 8: default: aspect = GR_ASPECT_LOG2_8x1; cache->scale_x = 1.0f; cache->scale_y = 0.125f; real_y >>= 3; break; } } else { int ratio = size_y / size_x; switch (ratio) { case 2: aspect = GR_ASPECT_LOG2_1x2; cache->scale_x = 0.5f; cache->scale_y = 1.0f; real_x >>= 1; break; case 4: aspect = GR_ASPECT_LOG2_1x4; cache->scale_x = 0.25f; cache->scale_y = 1.0f; real_x >>= 2; break; //case 8: default: aspect = GR_ASPECT_LOG2_1x8; cache->scale_x = 0.125f; cache->scale_y = 1.0f; real_x >>= 3; break; } } if (real_x != cache->width || real_y != cache->height) { cache->scale_x *= (float)cache->width / (float)real_x; cache->scale_y *= (float)cache->height / (float)real_y; } int splits = texinfo[id].splits; cache->splits = texinfo[id].splits; cache->splitheight = real_y / cache->splits; if (cache->splitheight < texinfo[id].splitheight) cache->splitheight = texinfo[id].splitheight; // ** Calculate alignment values int wid = cache->width; int hei = cache->height; if (splits > 1) { wid = texinfo[id].real_image_width; hei = texinfo[id].real_image_height; } float center_off = cache->scale / 2.0f; float c_lr_x = (float)real_x*cache->scale - center_off; float c_lr_y = (float)real_y*cache->scale - center_off; float c_scl_x; if (real_x != 1) c_scl_x = (c_lr_x - center_off) / (real_x-1); else c_scl_x = 0.0f; float c_scl_y; if (real_y != 1) c_scl_y = (c_lr_y - center_off) / (real_y-1); else c_scl_y = 0.0f; c_lr_x = center_off + c_scl_x * (wid-1); c_lr_y = center_off + c_scl_y * (hei-1); cache->c_off = center_off; if (wid != 1) cache->c_scl_x = (c_lr_x - center_off) / (float)(wid-1); else cache->c_scl_x = 0.0f; if (hei != 1) cache->c_scl_y = (c_lr_y - center_off) / (float)(hei-1); else cache->c_scl_y = 0.0f; // ** DWORD mod, modcolor, modcolor1, modcolor2, modfactor; if (id == 0) { mod = cmb.mod_0; modcolor = cmb.modcolor_0; modcolor1 = cmb.modcolor1_0; modcolor2 = cmb.modcolor2_0; modfactor = cmb.modfactor_0; } else { mod = cmb.mod_1; modcolor = cmb.modcolor_1; modcolor1 = cmb.modcolor1_1; modcolor2 = cmb.modcolor2_1; modfactor = cmb.modfactor_1; } WORD tmp_pal[256]; BOOL modifyPalette = (mod && (cache->format == 2) && (rdp.tlut_mode == 2)); if (modifyPalette) { memcpy(tmp_pal, rdp.pal_8, 512); ModifyPalette(mod, modcolor, modcolor1, modfactor); } cache->mod = mod; cache->mod_color = modcolor; cache->mod_color1 = modcolor1; cache->mod_factor = modfactor; if (rdp.hires_tex && rdp.hires_tex->tile == id) //texture buffer will be used instead of frame buffer texture { RDP("hires_tex selected\n"); return; } DWORD result = 0; // keep =0 so it doesn't mess up on the first split texture = tex1; // ** handle texture splitting ** if (splits > 1) { cache->scale_y = 0.125f; int i; for (i=0; isplitheight * 256; // start lower start_dst <<= HIWORD(result); // 1st time, result is set to 0, but start_dst is 0 anyway so it doesn't matter int start_src = i * 256; // start 256 more to the right start_src = start_src << (rdp.tiles[td].size) >> 1; result = load_table[rdp.tiles[td].size][rdp.tiles[td].format] (texture+start_dst, rdp.tmem+(rdp.tiles[td].t_mem<<3)+start_src, texinfo[id].wid_64, texinfo[id].height, texinfo[id].line, real_x, td); DWORD size = HIWORD(result); // clamp so that it looks somewhat ok when wrapping if (size == 1) Clamp16bT (texture+start_dst, texinfo[id].height, real_x, cache->splitheight); else Clamp8bT (texture+start_dst, texinfo[id].height, real_x, cache->splitheight); } } // ** end texture splitting ** else { result = load_table[rdp.tiles[td].size][rdp.tiles[td].format] (texture, rdp.tmem+(rdp.tiles[td].t_mem<<3), texinfo[id].wid_64, texinfo[id].height, texinfo[id].line, real_x, td); DWORD size = HIWORD(result); int min_x, min_y; if (rdp.tiles[td].mask_s != 0) min_x = std::min((int)real_x, 1< texinfo[id].width) { if (size == 1) Clamp16bS (texture, texinfo[id].width, min_x, real_x, texinfo[id].height); else Clamp8bS (texture, texinfo[id].width, min_x, real_x, texinfo[id].height); } if (texinfo[id].width < (int)real_x) { if (rdp.tiles[td].mirror_s) { if (size == 1) Mirror16bS (texture, rdp.tiles[td].mask_s, real_x, real_x, texinfo[id].height); else Mirror8bS (texture, rdp.tiles[td].mask_s, real_x, real_x, texinfo[id].height); } else { if (size == 1) Wrap16bS (texture, rdp.tiles[td].mask_s, real_x, real_x, texinfo[id].height); else Wrap8bS (texture, rdp.tiles[td].mask_s, real_x, real_x, texinfo[id].height); } } if (min_y > texinfo[id].height) { if (size == 1) Clamp16bT (texture, texinfo[id].height, real_x, min_y); else Clamp8bT (texture, texinfo[id].height, real_x, min_y); } if (texinfo[id].height < (int)real_y) { if (rdp.tiles[td].mirror_t) { if (size == 1) Mirror16bT (texture, rdp.tiles[td].mask_t, real_y, real_x); else Mirror8bT (texture, rdp.tiles[td].mask_t, real_y, real_x); } else { if (size == 1) Wrap16bT (texture, rdp.tiles[td].mask_t, real_y, real_x); else Wrap8bT (texture, rdp.tiles[td].mask_t, real_y, real_x); } } } if (modifyPalette) { memcpy(rdp.pal_8, tmp_pal, 512); } if (mod && !modifyPalette) { // Convert the texture to ARGB 4444 if (LOWORD(result) == GR_TEXFMT_ARGB_1555) TexConv_ARGB1555_ARGB4444 (tex1, tex2, real_x, real_y); if (LOWORD(result) == GR_TEXFMT_ALPHA_INTENSITY_88) TexConv_AI88_ARGB4444 (tex1, tex2, real_x, real_y); if (LOWORD(result) == GR_TEXFMT_ALPHA_INTENSITY_44) TexConv_AI44_ARGB4444 (tex1, tex2, real_x, real_y); if (LOWORD(result) == GR_TEXFMT_ALPHA_8) TexConv_A8_ARGB4444 (tex1, tex2, real_x, real_y); if (LOWORD(result) == GR_TEXFMT_ARGB_4444) memcpy (tex2, tex1, (real_x*real_y) << 1); texture = tex2; result = (1 << 16) | GR_TEXFMT_ARGB_4444; // Now convert the color to the same modcolor = ((modcolor & 0xF0000000) >> 16) | ((modcolor & 0x00F00000) >> 12) | ((modcolor & 0x0000F000) >> 8) | ((modcolor & 0x000000F0) >> 4); modcolor1 = ((modcolor1 & 0xF0000000) >> 16) | ((modcolor1 & 0x00F00000) >> 12) | ((modcolor1 & 0x0000F000) >> 8) | ((modcolor1 & 0x000000F0) >> 4); modcolor2 = ((modcolor2 & 0xF0000000) >> 16) | ((modcolor2 & 0x00F00000) >> 12) | ((modcolor2 & 0x0000F000) >> 8) | ((modcolor2 & 0x000000F0) >> 4); int size = (real_x * real_y) << 1; switch (mod) { case TMOD_TEX_INTER_COLOR_USING_FACTOR: mod_tex_inter_color_using_factor ((WORD*)tex2, size, modcolor, modfactor); break; case TMOD_TEX_INTER_COL_USING_COL1: mod_tex_inter_col_using_col1 ((WORD*)tex2, size, modcolor, modcolor1); break; case TMOD_FULL_COLOR_SUB_TEX: mod_full_color_sub_tex ((WORD*)tex2, size, modcolor); break; case TMOD_COL_INTER_COL1_USING_TEX: mod_col_inter_col1_using_tex ((WORD*)tex2, size, modcolor, modcolor1); break; case TMOD_COL_INTER_COL1_USING_TEXA: mod_col_inter_col1_using_texa ((WORD*)tex2, size, modcolor, modcolor1); break; case TMOD_COL_INTER_COL1_USING_TEXA__MUL_TEX: mod_col_inter_col1_using_texa__mul_tex ((WORD*)tex2, size, modcolor, modcolor1); break; case TMOD_COL_INTER_TEX_USING_TEXA: mod_col_inter_tex_using_texa ((WORD*)tex2, size, modcolor); break; case TMOD_COL2_INTER__COL_INTER_COL1_USING_TEX__USING_TEXA: mod_col2_inter__col_inter_col1_using_tex__using_texa ((WORD*)tex2, size, modcolor, modcolor1, modcolor2); break; case TMOD_TEX_SCALE_FAC_ADD_FAC: mod_tex_scale_fac_add_fac ((WORD*)tex2, size, modfactor); break; case TMOD_TEX_SUB_COL_MUL_FAC_ADD_TEX: mod_tex_sub_col_mul_fac_add_tex ((WORD*)tex2, size, modcolor, modfactor); break; case TMOD_TEX_SCALE_COL_ADD_COL: mod_tex_scale_col_add_col ((WORD*)tex2, size, modcolor, modfactor); break; case TMOD_TEX_ADD_COL: mod_tex_add_col ((WORD*)tex2, size, modcolor); break; case TMOD_TEX_SUB_COL: mod_tex_sub_col ((WORD*)tex2, size, modcolor); break; case TMOD_TEX_SUB_COL_MUL_FAC: mod_tex_sub_col_mul_fac ((WORD*)tex2, size, modcolor, modfactor); break; case TMOD_COL_INTER_TEX_USING_COL1: mod_col_inter_tex_using_col1 ((WORD*)tex2, size, modcolor, modcolor1); break; case TMOD_COL_MUL_TEXA_ADD_TEX: mod_col_mul_texa_add_tex((WORD*)tex2, size, modcolor); break; case TMOD_COL_INTER_TEX_USING_TEX: mod_col_inter_tex_using_tex ((WORD*)tex2, size, modcolor); break; case TMOD_TEX_INTER_NOISE_USING_COL: mod_tex_inter_noise_using_col ((WORD*)tex2, size, modcolor); break; case TMOD_TEX_INTER_COL_USING_TEXA: mod_tex_inter_col_using_texa ((WORD*)tex2, size, modcolor); break; case TMOD_TEX_MUL_COL: mod_tex_mul_col ((WORD*)tex2, size, modcolor); break; case TMOD_TEX_SCALE_FAC_ADD_COL: mod_tex_scale_fac_add_col ((WORD*)tex2, size, modcolor, modfactor); break; default: ; } } cache->t_info.format = LOWORD(result); cache->realwidth = real_x; cache->realheight = real_y; cache->lod = lod; cache->aspect = aspect; if (fullscreen) { // Load the texture into texture memory GrTexInfo *t_info = &cache->t_info; t_info->data = texture; t_info->smallLodLog2 = lod; t_info->largeLodLog2 = lod; t_info->aspectRatioLog2 = aspect; DWORD texture_size = grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, t_info); // Check for 2mb boundary if ((rdp.tmem_ptr[tmu] < TEXMEM_2MB_EDGE) && (rdp.tmem_ptr[tmu]+texture_size > TEXMEM_2MB_EDGE)) { rdp.tmem_ptr[tmu] = TEXMEM_2MB_EDGE; cache->tmem_addr = rdp.tmem_ptr[tmu]; } // Check for end of memory (too many textures to fit, clear cache) if (rdp.tmem_ptr[tmu]+texture_size >= grTexMaxAddress(tmu)) { RDP ("Cache size reached, clearing...\n"); ClearCache (); if (id == 1 && rdp.tex == 3) LoadTex (0, rdp.t0); LoadTex (id, tmu); return; // DON'T CONTINUE (already done) } grTexDownloadMipMap (tmu, grTexMinAddress(tmu) + rdp.tmem_ptr[tmu], GR_MIPMAPLEVELMASK_BOTH, t_info); grTexSource (tmu, grTexMinAddress(tmu) + rdp.tmem_ptr[tmu], GR_MIPMAPLEVELMASK_BOTH, t_info); rdp.tmem_ptr[tmu] += texture_size; } RDP (" | | +- LoadTex end\n"); } mupen64plus-video-glide64-src-2.6.0/src/TexCache.h000066400000000000000000000034071464507525600215140ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** #ifndef TEXCACHE_H #define TEXCACHE_H void TexCacheInit (); void TexCache (); void ClearCache (); #endif //TEXCACHE_H mupen64plus-video-glide64-src-2.6.0/src/TexConv.h000066400000000000000000000127641464507525600214240ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski * * 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 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators // Project started on December 29th, 2001 // // Authors: // Dave2001, original author, founded the project in 2001, left it in 2002 // Gugaman, joined the project in 2002, left it in 2002 // Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002 // Hiroshi 'KoolSmoky' Morii, joined the project in 2007 // //**************************************************************** // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // //**************************************************************** static inline void texConv_ARGB1555_ARGB4444(uint8_t *src, uint8_t *dst, int size) { uint32_t *v3; uint32_t *v4; int v5; uint32_t v6; uint32_t v7; v3 = (uint32_t *)src; v4 = (uint32_t *)dst; v5 = size; do { v6 = *v3; ++v3; v7 = v6; *v4 = ((v7 & 0x1E001E) >> 1) | ((v6 & 0x3C003C0) >> 2) | ((v6 & 0x78007800) >> 3) | ((v6 & 0x80008000) >> 3) | ((v6 & 0x80008000) >> 2) | ((v6 & 0x80008000) >> 1) | (v6 & 0x80008000); ++v4; --v5; } while ( v5 ); } static inline void texConv_AI88_ARGB4444(uint8_t *src, uint8_t *dst, int size) { uint32_t *v3; uint32_t *v4; int v5; uint32_t v6; uint32_t v7; v3 = (uint32_t *)src; v4 = (uint32_t *)dst; v5 = size; do { v6 = *v3; ++v3; v7 = v6; *v4 = (16 * (v7 & 0xF000F0) >> 8) | (v7 & 0xF000F0) | (16 * (v7 & 0xF000F0)) | (v6 & 0xF000F000); ++v4; --v5; } while ( v5 ); } static inline void texConv_AI44_ARGB4444(uint8_t *src, uint8_t *dst, int size) { uint32_t *v3; uint32_t *v4; int v5; uint32_t v6; uint32_t *v7; v3 = (uint32_t *)src; v4 = (uint32_t *)dst; v5 = size; do { v6 = *v3; ++v3; *v4 = ((((uint16_t)v6 << 8) & 0xFF00 & 0xF00u) >> 8) | ((((uint16_t)v6 << 8) & 0xFF00 & 0xF00u) >> 4) | (uint16_t)(((uint16_t)v6 << 8) & 0xFF00) | (((v6 << 16) & 0xF000000) >> 8) | (((v6 << 16) & 0xF000000) >> 4) | ((v6 << 16) & 0xFF000000); v7 = v4 + 1; *v7 = (((v6 >> 8) & 0xF00) >> 8) | (((v6 >> 8) & 0xF00) >> 4) | ((v6 >> 8) & 0xFF00) | ((v6 & 0xF000000) >> 8) | ((v6 & 0xF000000) >> 4) | (v6 & 0xFF000000); v4 = v7 + 1; --v5; } while ( v5 ); } static inline void texConv_A8_ARGB4444(uint8_t *src, uint8_t *dst, int size) { uint32_t *v3; uint32_t *v4; int v5; uint32_t v6; uint32_t v7; uint32_t *v8; v3 = (uint32_t *)src; v4 = (uint32_t *)dst; v5 = size; do { v6 = *v3; ++v3; v7 = v6; *v4 = ((v6 & 0xF0) << 8 >> 12) | (uint8_t)(v6 & 0xF0) | (16 * (uint8_t)(v6 & 0xF0) & 0xFFFFFFF) | ((uint8_t)(v6 & 0xF0) << 8) | (16 * (uint16_t)(v6 & 0xF000) & 0xFFFFF) | (((uint16_t)(v6 & 0xF000) << 8) & 0xFFFFFF) | (((uint16_t)(v6 & 0xF000) << 12) & 0xFFFFFFF) | ((uint16_t)(v6 & 0xF000) << 16); v8 = v4 + 1; *v8 = ((v7 & 0xF00000) >> 20) | ((v7 & 0xF00000) >> 16) | ((v7 & 0xF00000) >> 12) | ((v7 & 0xF00000) >> 8) | ((v6 & 0xF0000000) >> 12) | ((v6 & 0xF0000000) >> 8) | ((v6 & 0xF0000000) >> 4) | (v6 & 0xF0000000); v4 = v8 + 1; --v5; } while ( v5 ); } void TexConv_ARGB1555_ARGB4444 (unsigned char * src, unsigned char * dst, int width, int height) { int size = (width * height) >> 1; // Hiroshi Morii // 2 pixels are converted in one loop // NOTE: width * height must be a multiple of 2 texConv_ARGB1555_ARGB4444(src, dst, size); } void TexConv_AI88_ARGB4444 (unsigned char * src, unsigned char * dst, int width, int height) { int size = (width * height) >> 1; // Hiroshi Morii // 2 pixels are converted in one loop // NOTE: width * height must be a multiple of 2 texConv_AI88_ARGB4444(src, dst, size); } void TexConv_AI44_ARGB4444 (unsigned char * src, unsigned char * dst, int width, int height) { int size = (width * height) >> 2; // Hiroshi Morii // 4 pixels are converted in one loop // NOTE: width * height must be a multiple of 4 texConv_AI44_ARGB4444(src, dst, size); } void TexConv_A8_ARGB4444 (unsigned char * src, unsigned char * dst, int width, int height) { int size = (width * height) >> 2; // Hiroshi Morii // 4 pixels are converted in one loop // NOTE: width * height must be a multiple of 4 texConv_A8_ARGB4444(src, dst, size); } mupen64plus-video-glide64-src-2.6.0/src/TexLoad.h000066400000000000000000000045021464507525600213650ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** #include "TexLoad4b.h" #include "TexLoad8b.h" #include "TexLoad16b.h" #include "TexLoad32b.h" #ifndef _WIN32 #include #endif // _WIN32 uint32_t LoadNone (unsigned char * dst, unsigned char * src, int wid_64, int height, int line, int real_width, int tile) { return GR_TEXFMT_ARGB_1555; } typedef uint32_t (*texfunc)(unsigned char *, unsigned char *, int, int, int, int, int); texfunc load_table [4][5] = { // [size][format] { Load4bSelect, LoadNone, Load4bCI, Load4bIA, Load4bI}, { Load8bCI, LoadNone, Load8bCI, Load8bIA, Load8bI}, { Load16bRGBA, LoadNone, LoadNone, Load16bIA, LoadNone}, { Load32bRGBA, LoadNone, LoadNone, LoadNone, LoadNone} }; mupen64plus-video-glide64-src-2.6.0/src/TexLoad16b.h000066400000000000000000000155471464507525600217110ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski * * 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 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators // Project started on December 29th, 2001 // // Authors: // Dave2001, original author, founded the project in 2001, left it in 2002 // Gugaman, joined the project in 2002, left it in 2002 // Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002 // Hiroshi 'KoolSmoky' Morii, joined the project in 2007 // //**************************************************************** // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // //**************************************************************** static inline void load16bRGBA(uint8_t *src, uint8_t *dst, int wid_64, int height, int line, int ext) { uint32_t *v6; uint32_t *v7; int v8; int v9; uint32_t v10; uint32_t v11; uint32_t *v12; uint32_t *v13; int v14; uint32_t v15; uint32_t v16; int v17; int v18; v6 = (uint32_t *)src; v7 = (uint32_t *)dst; v8 = height; do { v17 = v8; v9 = wid_64; do { v10 = bswap32(*v6); v11 = bswap32(v6[1]); ALOWORD(v10) = __ROR__((uint16_t)v10, 1); ALOWORD(v11) = __ROR__((uint16_t)v11, 1); v10 = __ROR__(v10, 16); v11 = __ROR__(v11, 16); ALOWORD(v10) = __ROR__((uint16_t)v10, 1); ALOWORD(v11) = __ROR__((uint16_t)v11, 1); *v7 = v10; v7[1] = v11; v6 += 2; v7 += 2; --v9; } while ( v9 ); if ( v17 == 1 ) break; v18 = v17 - 1; v12 = (uint32_t *)&src[(line + (uintptr_t)v6 - (uintptr_t)src) & 0xFFF]; v13 = (uint32_t *)((char *)v7 + ext); v14 = wid_64; do { v15 = bswap32(v12[1]); v16 = bswap32(*v12); ALOWORD(v15) = __ROR__((uint16_t)v15, 1); ALOWORD(v16) = __ROR__((uint16_t)v16, 1); v15 = __ROR__(v15, 16); v16 = __ROR__(v16, 16); ALOWORD(v15) = __ROR__((uint16_t)v15, 1); ALOWORD(v16) = __ROR__((uint16_t)v16, 1); *v13 = v15; v13[1] = v16; v12 += 2; v13 += 2; --v14; } while ( v14 ); v6 = (uint32_t *)&src[(line + (uintptr_t)v12 - (uintptr_t)src) & 0xFFF]; v7 = (uint32_t *)((char *)v13 + ext); v8 = v18 - 1; } while ( v18 != 1 ); } static inline void load16bIA(uint8_t *src, uint8_t *dst, int wid_64, int height, int line, int ext) { uint32_t *v6; uint32_t *v7; int v8; int v9; uint32_t v10; uint32_t *v11; uint32_t *v12; int v13; uint32_t v14; int v15; int v16; v6 = (uint32_t *)src; v7 = (uint32_t *)dst; v8 = height; do { v15 = v8; v9 = wid_64; do { v10 = v6[1]; *v7 = *v6; v7[1] = v10; v6 += 2; v7 += 2; --v9; } while ( v9 ); if ( v15 == 1 ) break; v16 = v15 - 1; v11 = (uint32_t *)((char *)v6 + line); v12 = (uint32_t *)((char *)v7 + ext); v13 = wid_64; do { v14 = *v11; *v12 = v11[1]; v12[1] = v14; v11 += 2; v12 += 2; --v13; } while ( v13 ); v6 = (uint32_t *)((char *)v11 + line); v7 = (uint32_t *)((char *)v12 + ext); v8 = v16 - 1; } while ( v16 != 1 ); } //**************************************************************** // Size: 2, Format: 0 // uint32_t Load16bRGBA (uint8_t *dst, uint8_t *src, int wid_64, int height, int line, int real_width, int tile) { if (wid_64 < 1) wid_64 = 1; if (height < 1) height = 1; int ext = (real_width - (wid_64 << 2)) << 1; if (ext < 0) return 0; load16bRGBA(src, dst, wid_64, height, line, ext); return (1 << 16) | GR_TEXFMT_ARGB_1555; } //**************************************************************** // Size: 2, Format: 3 // // ** by Gugaman/Dave2001 ** uint32_t Load16bIA (uint8_t *dst, uint8_t *src, int wid_64, int height, int line, int real_width, int tile) { if (wid_64 < 1) wid_64 = 1; if (height < 1) height = 1; int ext = (real_width - (wid_64 << 2)) << 1; if (ext < 0) return 0; load16bIA(src, dst, wid_64, height, line, ext); return (1 << 16) | GR_TEXFMT_ALPHA_INTENSITY_88; } //**************************************************************** // Size: 2, Format: 1 // uint16_t yuv_to_rgb565(uint8_t y, uint8_t u, uint8_t v) { //* float r = y + (1.370705f * (v-128)); float g = y - (0.698001f * (v-128)) - (0.337633f * (u-128)); float b = y + (1.732446f * (u-128)); r *= 0.125f; g *= 0.25f; b *= 0.125f; //clipping the result if (r > 31) r = 31; if (g > 63) g = 63; if (b > 31) b = 31; if (r < 0) r = 0; if (g < 0) g = 0; if (b < 0) b = 0; uint16_t c = (uint16_t)(((uint16_t)(r) << 11) | ((uint16_t)(g) << 5) | (uint16_t)(b) ); return c; //*/ /* const uint32_t c = y - 16; const uint32_t d = u - 128; const uint32_t e = v - 128; uint32_t r = (298 * c + 409 * e + 128) & 0xf800; uint32_t g = ((298 * c - 100 * d - 208 * e + 128) >> 5) & 0x7e0; uint32_t b = ((298 * c + 516 * d + 128) >> 11) & 0x1f; WORD texel = (WORD)(r | g | b); return texel; */ } //**************************************************************** // Size: 2, Format: 1 // uint32_t Load16bYUV (uint8_t *dst, uint8_t *src, int wid_64, int height, int line, int real_width, int tile) { uint32_t * mb = (uint32_t*)(gfx.RDRAM+rdp.addr[rdp.tiles[tile].t_mem]); //pointer to the macro block uint16_t * tex = (uint16_t*)dst; uint16_t i; for (i = 0; i < 128; i++) { uint32_t t = mb[i]; //each uint32_t contains 2 pixels uint8_t y1 = (uint8_t)t&0xFF; uint8_t v = (uint8_t)(t>>8)&0xFF; uint8_t y0 = (uint8_t)(t>>16)&0xFF; uint8_t u = (uint8_t)(t>>24)&0xFF; uint16_t c = yuv_to_rgb565(y0, u, v); *(tex++) = c; c = yuv_to_rgb565(y1, u, v); *(tex++) = c; } return (1 << 16) | GR_TEXFMT_RGB_565; } mupen64plus-video-glide64-src-2.6.0/src/TexLoad32b.h000066400000000000000000000110101464507525600216640ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * Copyright (c) 2008 Günther * * 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 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** //**************************************************************** // Size: 2, Format: 0 uint32_t Load32bRGBA (unsigned char * dst, unsigned char * src, int wid_64, int height, int line, int real_width, int tile) { uint32_t *input_pos; uint32_t *output_pos; uint32_t inval; uint32_t doublergba; uint32_t t; int x, y; if (wid_64 < 1) wid_64 = 1; if (height < 1) height = 1; int ext = (real_width - (wid_64 << 1)) << 1; wid_64 >>= 1; // re-shift it, load twice as many quadwords input_pos = (uint32_t *)src; output_pos = (uint32_t *)dst; for (y = 0; y < height; y += 2) { for (x = 0; x < wid_64; x++) { inval = bswap32(input_pos[0]); doublergba = ((inval >> 20) & 0xF00) | ((inval >> 16) & 0xF0) | ((inval >> 12) & 0xF) | ((inval << 8) & 0xF000); inval = bswap32(input_pos[1]); doublergba = (inval & 0xF00000) | ((inval << 24) & 0xF0000000) | doublergba; t = __ROL__(inval, 4); output_pos[0] = ((t << 24) & 0xF000000) | (t & 0xF0000) | doublergba; inval = bswap32(input_pos[2]); doublergba = ((inval >> 20) & 0xF00) | ((inval >> 16) & 0xF0) | ((inval >> 12) & 0xF) | ((inval << 8) & 0xF000); inval = bswap32(input_pos[3]); doublergba = (inval & 0xF00000) | ((inval << 24) & 0xF0000000) | doublergba; t = __ROL__(inval, 4); output_pos[1] = ((t << 24) & 0xF000000) | (t & 0xF0000) | doublergba; input_pos += 4; output_pos += 2; } if ((y + 1) >= height) break; input_pos = (uint32_t *)((uint8_t *)input_pos + line); output_pos = (uint32_t *)((uint8_t *)output_pos + ext); for (x = 0; x < wid_64; x++) { inval = bswap32(input_pos[2]); doublergba = ((inval >> 20) & 0xF00) | ((inval >> 16) & 0xF0) | ((inval >> 12) & 0xF) | ((inval << 8) & 0xF000); inval = bswap32(input_pos[3]); doublergba = (inval & 0xF00000) | ((inval << 24) & 0xF0000000) | doublergba; t = __ROL__(inval, 4); output_pos[0] = ((t << 24) & 0xF000000) | (t & 0xF0000) | doublergba; inval = bswap32(input_pos[0]); doublergba = ((inval >> 20) & 0xF00) | ((inval >> 16) & 0xF0) | ((inval >> 12) & 0xF) | ((inval << 8) & 0xF000); inval = bswap32(input_pos[1]); doublergba = (inval & 0xF00000) | ((inval << 24) & 0xF0000000) | doublergba; t = __ROL__(inval, 4); output_pos[1] = ((t << 24) & 0xF000000) | (t & 0xF0000) | doublergba; input_pos += 4; output_pos += 2; } input_pos = (uint32_t *)((uint8_t *)input_pos + line); output_pos = (uint32_t *)((uint8_t *)output_pos + ext); } return (1 << 16) | GR_TEXFMT_ARGB_4444; } mupen64plus-video-glide64-src-2.6.0/src/TexLoad4b.h000066400000000000000000000613021464507525600216140ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski * * 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 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators // Project started on December 29th, 2001 // // Authors: // Dave2001, original author, founded the project in 2001, left it in 2002 // Gugaman, joined the project in 2002, left it in 2002 // Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002 // Hiroshi 'KoolSmoky' Morii, joined the project in 2007 // //**************************************************************** // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // //**************************************************************** #include static inline void load4bCI(uint8_t *src, uint8_t *dst, int wid_64, int height, uint16_t line, int ext, uint16_t *pal) { uint8_t *v7; uint8_t *v8; int v9; int v10; int v11; uint32_t v12; uint8_t *v13; uint32_t v14; uint32_t *v15; uint32_t v16; uint8_t *v17; uint32_t *v18; int v19; int v20; uint32_t v21; uint32_t v22; uint32_t *v23; uint32_t v24; int v25; int v26; v7 = src; v8 = dst; v9 = height; do { v25 = v9; v10 = wid_64; do { v11 = v10; v12 = bswap32(*(uint32_t *)v7); v13 = v7 + 4; ALOWORD(v10) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 23) & 0x1E)), 1); v14 = v10 << 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 27) & 0x1E)), 1); *(uint32_t *)v8 = v14; v15 = (uint32_t *)(v8 + 4); ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 15) & 0x1E)), 1); v14 <<= 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 19) & 0x1E)), 1); *v15 = v14; ++v15; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 7) & 0x1E)), 1); v14 <<= 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 11) & 0x1E)), 1); *v15 = v14; ++v15; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint8_t)v12 & 0x1E)), 1); v14 <<= 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 3) & 0x1E)), 1); *v15 = v14; ++v15; v16 = bswap32(*(uint32_t *)v13); v7 = v13 + 4; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 23) & 0x1E)), 1); v14 <<= 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 27) & 0x1E)), 1); *v15 = v14; ++v15; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 15) & 0x1E)), 1); v14 <<= 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 19) & 0x1E)), 1); *v15 = v14; ++v15; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 7) & 0x1E)), 1); v14 <<= 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 11) & 0x1E)), 1); *v15 = v14; ++v15; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint8_t)v16 & 0x1E)), 1); v14 <<= 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 3) & 0x1E)), 1); *v15 = v14; v8 = (uint8_t *)(v15 + 1); v10 = v11 - 1; } while ( v11 != 1 ); if ( v25 == 1 ) break; v26 = v25 - 1; v17 = &src[(line + (uintptr_t)v7 - (uintptr_t)src) & 0x7FF]; v18 = (uint32_t *)&v8[ext]; v19 = wid_64; do { v20 = v19; v21 = bswap32(*((uint32_t *)v17 + 1)); ALOWORD(v19) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 23) & 0x1E)), 1); v22 = v19 << 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 27) & 0x1E)), 1); *v18 = v22; v23 = v18 + 1; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 15) & 0x1E)), 1); v22 <<= 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 19) & 0x1E)), 1); *v23 = v22; ++v23; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 7) & 0x1E)), 1); v22 <<= 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 11) & 0x1E)), 1); *v23 = v22; ++v23; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint8_t)v21 & 0x1E)), 1); v22 <<= 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 3) & 0x1E)), 1); *v23 = v22; ++v23; v24 = bswap32(*(uint32_t *)v17); v17 = &src[((uintptr_t)v17 + 8 - (uintptr_t)src) & 0x7FF]; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 23) & 0x1E)), 1); v22 <<= 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 27) & 0x1E)), 1); *v23 = v22; ++v23; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 15) & 0x1E)), 1); v22 <<= 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 19) & 0x1E)), 1); *v23 = v22; ++v23; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 7) & 0x1E)), 1); v22 <<= 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 11) & 0x1E)), 1); *v23 = v22; ++v23; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint8_t)v24 & 0x1E)), 1); v22 <<= 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 3) & 0x1E)), 1); *v23 = v22; v18 = v23 + 1; v19 = v20 - 1; } while ( v20 != 1 ); v7 = &src[(line + (uintptr_t)v17 - (uintptr_t)src) & 0x7FF]; v8 = (uint8_t *)((char *)v18 + ext); v9 = v26 - 1; } while ( v26 != 1 ); } static inline void load4bIAPal(uint8_t *src, uint8_t *dst, int wid_64, int height, int line, int ext, uint16_t *pal) { uint8_t *v7; uint32_t *v8; int v9; int v10; int v11; uint32_t v12; uint32_t *v13; uint32_t v14; uint32_t *v15; uint32_t v16; uint8_t *v17; uint32_t *v18; int v19; int v20; uint32_t v21; uint32_t v22; uint32_t *v23; uint32_t v24; int v25; int v26; v7 = src; v8 = (uint32_t *)dst; v9 = height; do { v25 = v9; v10 = wid_64; do { v11 = v10; v12 = bswap32(*(uint32_t *)v7); v13 = (uint32_t *)(v7 + 4); ALOWORD(v10) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 23) & 0x1E)), 8); v14 = v10 << 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 27) & 0x1E)), 8); *v8 = v14; v15 = v8 + 1; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 15) & 0x1E)), 8); v14 <<= 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 19) & 0x1E)), 8); *v15 = v14; ++v15; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 7) & 0x1E)), 8); v14 <<= 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 11) & 0x1E)), 8); *v15 = v14; ++v15; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint8_t)v12 & 0x1E)), 8); v14 <<= 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 3) & 0x1E)), 8); *v15 = v14; ++v15; v16 = bswap32(*v13); v7 = (uint8_t *)(v13 + 1); ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 23) & 0x1E)), 8); v14 <<= 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 27) & 0x1E)), 8); *v15 = v14; ++v15; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 15) & 0x1E)), 8); v14 <<= 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 19) & 0x1E)), 8); *v15 = v14; ++v15; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 7) & 0x1E)), 8); v14 <<= 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 11) & 0x1E)), 8); *v15 = v14; ++v15; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint8_t)v16 & 0x1E)), 8); v14 <<= 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 3) & 0x1E)), 8); *v15 = v14; v8 = v15 + 1; v10 = v11 - 1; } while ( v11 != 1 ); if ( v25 == 1 ) break; v26 = v25 - 1; v17 = &src[(line + (uintptr_t)v7 - (uintptr_t)src) & 0x7FF]; v18 = (uint32_t *)((char *)v8 + ext); v19 = wid_64; do { v20 = v19; v21 = bswap32(*((uint32_t *)v17 + 1)); ALOWORD(v19) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 23) & 0x1E)), 8); v22 = v19 << 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 27) & 0x1E)), 8); *v18 = v22; v23 = v18 + 1; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 15) & 0x1E)), 8); v22 <<= 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 19) & 0x1E)), 8); *v23 = v22; ++v23; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 7) & 0x1E)), 8); v22 <<= 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 11) & 0x1E)), 8); *v23 = v22; ++v23; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint8_t)v21 & 0x1E)), 8); v22 <<= 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 3) & 0x1E)), 8); *v23 = v22; ++v23; v24 = bswap32(*(uint32_t *)v17); v17 = &src[((uintptr_t)v17 + 8 - (uintptr_t)src) & 0x7FF]; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 23) & 0x1E)), 8); v22 <<= 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 27) & 0x1E)), 8); *v23 = v22; ++v23; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 15) & 0x1E)), 8); v22 <<= 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 19) & 0x1E)), 8); *v23 = v22; ++v23; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 7) & 0x1E)), 8); v22 <<= 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 11) & 0x1E)), 8); *v23 = v22; ++v23; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint8_t)v24 & 0x1E)), 8); v22 <<= 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 3) & 0x1E)), 8); *v23 = v22; v18 = v23 + 1; v19 = v20 - 1; } while ( v20 != 1 ); v7 = &src[(line + (uintptr_t)v17 - (uintptr_t)src) & 0x7FF]; v8 = (uint32_t *)((char *)v18 + ext); v9 = v26 - 1; } while ( v26 != 1 ); } static inline void load4bIA(uint8_t *src, uint8_t *dst, int wid_64, int height, int line, int ext) { uint32_t *v6; uint32_t *v7; int v8; int v9; int v10; uint32_t v11; uint32_t *v12; uint32_t v13; uint32_t v14; uint32_t v15; uint32_t *v16; uint32_t v17; uint32_t v18; uint32_t v19; uint32_t v20; uint32_t v21; uint32_t v22; uint32_t v23; uint32_t v24; uint32_t v25; uint32_t v26; uint32_t v27; uint32_t v28; uint32_t v29; uint32_t v30; uint32_t v31; uint32_t v32; uint32_t *v33; uint32_t *v34; int v35; int v36; uint32_t v37; uint32_t v38; uint32_t v39; uint32_t *v40; uint32_t v41; uint32_t v42; uint32_t v43; uint32_t v44; uint32_t v45; uint32_t v46; uint32_t v47; uint32_t v48; uint32_t v49; uint32_t v50; uint32_t v51; uint32_t v52; uint32_t v53; uint32_t v54; uint32_t v55; uint32_t v56; int v57; int v58; v6 = (uint32_t *)src; v7 = (uint32_t *)dst; v8 = height; do { v57 = v8; v9 = wid_64; do { v10 = v9; v11 = bswap32(*v6); v12 = v6 + 1; v13 = v11; v14 = (8 * (v11 & 0x100000)) | (4 * (v11 & 0x100000)) | (2 * (v11 & 0x100000)) | (v11 & 0x100000) | ((((v11 >> 16) & 0xE00) >> 3) & 0x100) | ((v11 >> 16) & 0xE00) | (8 * ((v11 >> 12) & 0x1000)) | (4 * ((v11 >> 12) & 0x1000)) | (2 * ((v11 >> 12) & 0x1000)) | ((v11 >> 12) & 0x1000) | ((((v11 >> 28) & 0xE) >> 3)) | ((v11 >> 28) & 0xE) | (8 * ((v11 >> 24) & 0x10)) | (4 * ((v11 >> 24) & 0x10)) | (2 * ((v11 >> 24) & 0x10)) | ((v11 >> 24) & 0x10); v11 >>= 4; v11 &= 0xE0000u; v15 = v11 | v14; v11 >>= 3; *v7 = ((((v13 << 8) & 0xE000000) >> 3) & 0x1000000) | ((v13 << 8) & 0xE000000) | (8 * ((v13 << 12) & 0x10000000)) | (4 * ((v13 << 12) & 0x10000000)) | (2 * ((v13 << 12) & 0x10000000)) | ((v13 << 12) & 0x10000000) | (v11 & 0x10000) | v15; v16 = v7 + 1; v17 = 16 * (uint16_t)v13 & 0x1000; v18 = (((v13 & 0xE00) >> 3) & 0x100) | (v13 & 0xE00) | (8 * v17) | (4 * v17) | (2 * v17) | (v17) | ((((v13 >> 12) & 0xE) >> 3)) | ((v13 >> 12) & 0xE) | (8 * ((v13 >> 8) & 0x10)) | (4 * ((v13 >> 8) & 0x10)) | (2 * ((v13 >> 8) & 0x10)) | ((v13 >> 8) & 0x10); v19 = v13 << 16; v20 = (8 * (v19 & 0x100000)) | (4 * (v19 & 0x100000)) | (2 * (v19 & 0x100000)) | (v19 & 0x100000) | v18; v21 = v13 << 12; v21 &= 0xE0000u; v22 = v21 | v20; v21 >>= 3; *v16 = ((((v13 << 24) & 0xE000000) >> 3) & 0x1000000) | ((v13 << 24) & 0xE000000) | (8 * ((v13 << 28) & 0x10000000)) | (4 * ((v13 << 28) & 0x10000000)) | (2 * ((v13 << 28) & 0x10000000)) | ((v13 << 28) & 0x10000000) | (v21 & 0x10000) | v22; ++v16; v23 = bswap32(*v12); v6 = v12 + 1; v24 = v23; v25 = (8 * (v23 & 0x100000)) | (4 * (v23 & 0x100000)) | (2 * (v23 & 0x100000)) | (v23 & 0x100000) | ((((v23 >> 16) & 0xE00) >> 3) & 0x100) | ((v23 >> 16) & 0xE00) | (8 * ((v23 >> 12) & 0x1000)) | (4 * ((v23 >> 12) & 0x1000)) | (2 * ((v23 >> 12) & 0x1000)) | ((v23 >> 12) & 0x1000) | (((v23 >> 28) & 0xE) >> 3) | ((v23 >> 28) & 0xE) | (8 * ((v23 >> 24) & 0x10)) | (4 * ((v23 >> 24) & 0x10)) | (2 * ((v23 >> 24) & 0x10)) | ((v23 >> 24) & 0x10); v23 >>= 4; v23 &= 0xE0000u; v26 = v23 | v25; v23 >>= 3; *v16 = ((((v24 << 8) & 0xE000000) >> 3) & 0x1000000) | ((v24 << 8) & 0xE000000) | (8 * ((v24 << 12) & 0x10000000)) | (4 * ((v24 << 12) & 0x10000000)) | (2 * ((v24 << 12) & 0x10000000)) | ((v24 << 12) & 0x10000000) | (v23 & 0x10000) | (v26); ++v16; v27 = 16 * (uint16_t)v24 & 0x1000; v28 = (((v24 & 0xE00) >> 3) & 0x100) | (v24 & 0xE00) | (8 * v27) | (4 * v27) | (2 * v27) | (v27) | ((((v24 >> 12) & 0xE) >> 3)) | ((v24 >> 12) & 0xE) | (8 * ((v24 >> 8) & 0x10)) | (4 * ((v24 >> 8) & 0x10)) | (2 * ((v24 >> 8) & 0x10)) | ((v24 >> 8) & 0x10); v29 = v24 << 16; v30 = (8 * (v29 & 0x100000)) | (4 * (v29 & 0x100000)) | (2 * (v29 & 0x100000)) | (v29 & 0x100000) | v28; v31 = v24 << 12; v31 &= 0xE0000u; v32 = v31 | v30; v31 >>= 3; *v16 = ((((v24 << 24) & 0xE000000) >> 3) & 0x1000000) | ((v24 << 24) & 0xE000000) | (8 * ((v24 << 28) & 0x10000000)) | (4 * ((v24 << 28) & 0x10000000)) | (2 * ((v24 << 28) & 0x10000000)) | ((v24 << 28) & 0x10000000) | (v31 & 0x10000) | v32; v7 = v16 + 1; v9 = v10 - 1; } while ( v10 != 1 ); if ( v57 == 1 ) break; v58 = v57 - 1; v33 = (uint32_t *)((char *)v6 + line); v34 = (uint32_t *)((char *)v7 + ext); v35 = wid_64; do { v36 = v35; v37 = bswap32(v33[1]); v38 = v37 >> 4; v38 &= 0xE0000u; v39 = v38 | (8 * (v37 & 0x100000)) | (4 * (v37 & 0x100000)) | (2 * (v37 & 0x100000)) | (v37 & 0x100000) | ((((v37 >> 16) & 0xE00) >> 3) & 0x100) | ((v37 >> 16) & 0xE00) | (8 * ((v37 >> 12) & 0x1000)) | (4 * ((v37 >> 12) & 0x1000)) | (2 * ((v37 >> 12) & 0x1000)) | ((v37 >> 12) & 0x1000) | (((v37 >> 28) & 0xE) >> 3) | ((v37 >> 28) & 0xE) | (8 * ((v37 >> 24) & 0x10)) | (4 * ((v37 >> 24) & 0x10)) | (2 * ((v37 >> 24) & 0x10)) | ((v37 >> 24) & 0x10); v38 >>= 3; *v34 = ((((v37 << 8) & 0xE000000) >> 3) & 0x1000000) | ((v37 << 8) & 0xE000000) | (8 * ((v37 << 12) & 0x10000000)) | (4 * ((v37 << 12) & 0x10000000)) | (2 * ((v37 << 12) & 0x10000000)) | ((v37 << 12) & 0x10000000) | (v38 & 0x10000) | v39; v40 = v34 + 1; v41 = 16 * (uint16_t)v37 & 0x1000; v42 = (((v37 & 0xE00) >> 3) & 0x100) | (v37 & 0xE00) | (8 * v41) | (4 * v41) | (2 * v41) | v41 | (((v37 >> 12) & 0xE) >> 3) | ((v37 >> 12) & 0xE) | (8 * ((v37 >> 8) & 0x10)) | (4 * ((v37 >> 8) & 0x10)) | (2 * ((v37 >> 8) & 0x10)) | ((v37 >> 8) & 0x10); v43 = v37 << 16; v44 = (8 * (v43 & 0x100000)) | (4 * (v43 & 0x100000)) | (2 * (v43 & 0x100000)) | (v43 & 0x100000) | v42; v45 = v37 << 12; v45 &= 0xE0000u; v46 = v45 | v44; v45 >>= 3; *v40 = ((((v37 << 24) & 0xE000000) >> 3) & 0x1000000) | ((v37 << 24) & 0xE000000) | (8 * ((v37 << 28) & 0x10000000)) | (4 * ((v37 << 28) & 0x10000000)) | (2 * ((v37 << 28) & 0x10000000)) | ((v37 << 28) & 0x10000000) | (v45 & 0x10000) | v46; ++v40; v47 = bswap32(*v33); v33 += 2; v48 = v47; v49 = (8 * (v47 & 0x100000)) | (4 * (v47 & 0x100000)) | (2 * (v47 & 0x100000)) | (v47 & 0x100000) | ((((v47 >> 16) & 0xE00) >> 3) & 0x100) | ((v47 >> 16) & 0xE00) | (8 * ((v47 >> 12) & 0x1000)) | (4 * ((v47 >> 12) & 0x1000)) | (2 * ((v47 >> 12) & 0x1000)) | ((v47 >> 12) & 0x1000) | (((v47 >> 28) & 0xE) >> 3) | ((v47 >> 28) & 0xE) | (8 * ((v47 >> 24) & 0x10)) | (4 * ((v47 >> 24) & 0x10)) | (2 * ((v47 >> 24) & 0x10)) | ((v47 >> 24) & 0x10); v47 >>= 4; v47 &= 0xE0000u; v50 = v47 | v49; v47 >>= 3; *v40 = ((((v48 << 8) & 0xE000000) >> 3) & 0x1000000) | ((v48 << 8) & 0xE000000) | (8 * ((v48 << 12) & 0x10000000)) | (4 * ((v48 << 12) & 0x10000000)) | (2 * ((v48 << 12) & 0x10000000)) | ((v48 << 12) & 0x10000000) | (v47 & 0x10000) | v50; ++v40; v51 = 16 * (uint16_t)v48 & 0x1000; v52 = (((v48 & 0xE00) >> 3) & 0x100) | (v48 & 0xE00) | (8 * v51) | (4 * v51) | (2 * v51) | v51 | (((v48 >> 12) & 0xE) >> 3) | ((v48 >> 12) & 0xE) | (8 * ((v48 >> 8) & 0x10)) | (4 * ((v48 >> 8) & 0x10)) | (2 * ((v48 >> 8) & 0x10)) | ((v48 >> 8) & 0x10); v53 = v48 << 16; v54 = (8 * (v53 & 0x100000)) | (4 * (v53 & 0x100000)) | (2 * (v53 & 0x100000)) | (v53 & 0x100000) | v52; v55 = v48 << 12; v55 &= 0xE0000u; v56 = v55 | v54; v55 >>= 3; *v40 = ((((v48 << 24) & 0xE000000) >> 3) & 0x1000000) | ((v48 << 24) & 0xE000000) | (8 * ((v48 << 28) & 0x10000000)) | (4 * ((v48 << 28) & 0x10000000)) | (2 * ((v48 << 28) & 0x10000000)) | ((v48 << 28) & 0x10000000) | (v55 & 0x10000) | v56; v34 = v40 + 1; v35 = v36 - 1; } while ( v36 != 1 ); v6 = (uint32_t *)((char *)v33 + line); v7 = (uint32_t *)((char *)v34 + ext); v8 = v58 - 1; } while ( v58 != 1 ); } static inline void load4bI(uint8_t *src, uint8_t *dst, int wid_64, int height, int line, int ext) { uint32_t *v6; uint32_t *v7; int v8; int v9; int v10; uint32_t v11; uint32_t *v12; uint32_t v13; uint32_t v14; uint32_t *v15; uint32_t v16; unsigned int v17; unsigned int v18; uint32_t v19; uint32_t v20; uint32_t *v21; uint32_t *v22; int v23; int v24; uint32_t v25; uint32_t v26; uint32_t *v27; uint32_t v28; uint32_t v29; uint32_t v30; uint32_t v31; uint32_t v32; int v33; int v34; v6 = (uint32_t *)src; v7 = (uint32_t *)dst; v8 = height; do { v33 = v8; v9 = wid_64; do { v10 = v9; v11 = bswap32(*v6); v12 = v6 + 1; v13 = v11; v14 = (16 * ((v11 >> 16) & 0xF00)) | ((v11 >> 16) & 0xF00) | (16 * (v11 >> 28)) | (v11 >> 28); v11 >>= 4; *v7 = (16 * ((v13 << 8) & 0xF000000)) | ((v13 << 8) & 0xF000000) | (16 * (v11 & 0xF0000)) | (v11 & 0xF0000) | v14; v15 = v7 + 1; v16 = v13 << 12; *v15 = (16 * ((v13 << 24) & 0xF000000)) | ((v13 << 24) & 0xF000000) | (16 * (v16 & 0xF0000)) | (v16 & 0xF0000) | (16 * (v13 & 0xF00)) | (v13 & 0xF00) | (16 * ((uint16_t)v13 >> 12)) | ((uint16_t)v13 >> 12); ++v15; v17 = bswap32(*v12); v6 = v12 + 1; v18 = v17; v19 = (16 * ((v17 >> 16) & 0xF00)) | ((v17 >> 16) & 0xF00) | (16 * (v17 >> 28)) | (v17 >> 28); v17 >>= 4; *v15 = (16 * ((v18 << 8) & 0xF000000)) | ((v18 << 8) & 0xF000000) | (16 * (v17 & 0xF0000)) | (v17 & 0xF0000) | v19; ++v15; v20 = v18 << 12; *v15 = (16 * ((v18 << 24) & 0xF000000)) | ((v18 << 24) & 0xF000000) | (16 * (v20 & 0xF0000)) | (v20 & 0xF0000) | (16 * (v18 & 0xF00)) | (v18 & 0xF00) | (16 * ((uint16_t)v18 >> 12)) | ((uint16_t)v18 >> 12); v7 = v15 + 1; v9 = v10 - 1; } while ( v10 != 1 ); if ( v33 == 1 ) break; v34 = v33 - 1; v21 = (uint32_t *)((char *)v6 + line); v22 = (uint32_t *)((char *)v7 + ext); v23 = wid_64; do { v24 = v23; v25 = bswap32(v21[1]); v26 = v25 >> 4; *v22 = (16 * ((v25 << 8) & 0xF000000)) | ((v25 << 8) & 0xF000000) | (16 * (v26 & 0xF0000)) | (v26 & 0xF0000) | (16 * ((v25 >> 16) & 0xF00)) | ((v25 >> 16) & 0xF00) | (16 * (v25 >> 28)) | (v25 >> 28); v27 = v22 + 1; v28 = v25 << 12; *v27 = (16 * ((v25 << 24) & 0xF000000)) | ((v25 << 24) & 0xF000000) | (16 * (v28 & 0xF0000)) | (v28 & 0xF0000) | (16 * (v25 & 0xF00)) | (v25 & 0xF00) | (16 * ((uint16_t)v25 >> 12)) | ((uint16_t)v25 >> 12); ++v27; v29 = bswap32(*v21); v21 += 2; v30 = v29; v31 = (16 * ((v29 >> 16) & 0xF00)) | ((v29 >> 16) & 0xF00) | (16 * (v29 >> 28)) | (v29 >> 28); v29 >>= 4; *v27 = (16 * ((v30 << 8) & 0xF000000)) | ((v30 << 8) & 0xF000000) | (16 * (v29 & 0xF0000)) | (v29 & 0xF0000) | v31; ++v27; v32 = v30 << 12; *v27 = (16 * ((v30 << 24) & 0xF000000)) | ((v30 << 24) & 0xF000000) | (16 * (v32 & 0xF0000)) | (v32 & 0xF0000) | (16 * (v30 & 0xF00)) | (v30 & 0xF00) | (16 * ((uint16_t)v30 >> 12)) | ((uint16_t)v30 >> 12); v22 = v27 + 1; v23 = v24 - 1; } while ( v24 != 1 ); v6 = (uint32_t *)((char *)v21 + line); v7 = (uint32_t *)((char *)v22 + ext); v8 = v34 - 1; } while ( v34 != 1 ); } //**************************************************************** // Size: 0, Format: 2 uint32_t Load4bCI (uint8_t *dst, uint8_t *src, int wid_64, int height, int line, int real_width, int tile) { if (wid_64 < 1) wid_64 = 1; if (height < 1) height = 1; int ext = (real_width - (wid_64 << 4)) << 1; if (ext < 0) return 0; if (rdp.tlut_mode == 0) { //in tlut DISABLE mode load CI texture as plain intensity texture instead of palette dereference. //Thanks to angrylion for the advice load4bI (src, dst, wid_64, height, line, ext); return /*(0 << 16) | */GR_TEXFMT_ALPHA_INTENSITY_44; } uintptr_t pal = (uintptr_t)(rdp.pal_8 + (rdp.tiles[tile].palette << 4)); if (rdp.tlut_mode == 2) { load4bCI (src, dst, wid_64, height, line, ext, (uint16_t *)pal); return (1 << 16) | GR_TEXFMT_ARGB_1555; } load4bIAPal (src, dst, wid_64, height, line, ext, (uint16_t *)pal); return (1 << 16) | GR_TEXFMT_ALPHA_INTENSITY_88; } //**************************************************************** // Size: 0, Format: 3 // // ** BY GUGAMAN ** uint32_t Load4bIA (unsigned char * dst, unsigned char * src, int wid_64, int height, int line, int real_width, int tile) { if (rdp.tlut_mode != 0) return Load4bCI (dst, src, wid_64, height, line, real_width, tile); if (wid_64 < 1) wid_64 = 1; if (height < 1) height = 1; int ext = (real_width - (wid_64 << 4)); if (ext < 0) return 0; load4bIA (src, dst, wid_64, height, line, ext); return /*(0 << 16) | */GR_TEXFMT_ALPHA_INTENSITY_44; } //**************************************************************** // Size: 0, Format: 4 uint32_t Load4bI (unsigned char * dst, unsigned char * src, int wid_64, int height, int line, int real_width, int tile) { if (rdp.tlut_mode != 0) return Load4bCI (dst, src, wid_64, height, line, real_width, tile); if (wid_64 < 1) wid_64 = 1; if (height < 1) height = 1; int ext = (real_width - (wid_64 << 4)); if (ext < 0) return 0; load4bI (src, dst, wid_64, height, line, ext); return /*(0 << 16) | */GR_TEXFMT_ALPHA_INTENSITY_44; } //**************************************************************** // Size: 0, Format: 0 uint32_t Load4bSelect (unsigned char * dst, unsigned char * src, int wid_64, int height, int line, int real_width, int tile) { if (rdp.tlut_mode == 0) return Load4bI (dst, src, wid_64, height, line, real_width, tile); return Load4bCI (dst, src, wid_64, height, line, real_width, tile); } mupen64plus-video-glide64-src-2.6.0/src/TexLoad8b.h000066400000000000000000000301711464507525600216200ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski * * 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 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators // Project started on December 29th, 2001 // // Authors: // Dave2001, original author, founded the project in 2001, left it in 2002 // Gugaman, joined the project in 2002, left it in 2002 // Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002 // Hiroshi 'KoolSmoky' Morii, joined the project in 2007 // //**************************************************************** // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // //**************************************************************** #include static inline void load8bCI(uint8_t *src, uint8_t *dst, int wid_64, int height, int line, int ext, uint16_t *pal) { uint8_t *v7; uint32_t *v8; int v9; int v10; int v11; uint32_t v12; uint32_t *v13; uint32_t v14; uint32_t *v15; uint32_t v16; uint32_t *v17; uint32_t *v18; int v19; int v20; uint32_t v21; uint32_t v22; uint32_t *v23; uint32_t v24; int v25; int v26; v7 = src; v8 = (uint32_t *)dst; v9 = height; do { v25 = v9; v10 = wid_64; do { v11 = v10; v12 = bswap32(*(uint32_t *)v7); v13 = (uint32_t *)(v7 + 4); ALOWORD(v10) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 15) & 0x1FE)), 1); v14 = v10 << 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 23) & 0x1FE)), 1); *v8 = v14; v15 = v8 + 1; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint16_t)v12 & 0x1FE)), 1); v14 <<= 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 7) & 0x1FE)), 1); *v15 = v14; ++v15; v16 = bswap32(*v13); v7 = (uint8_t *)(v13 + 1); ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 15) & 0x1FE)), 1); v14 <<= 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 23) & 0x1FE)), 1); *v15 = v14; ++v15; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint16_t)v16 & 0x1FE)), 1); v14 <<= 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 7) & 0x1FE)), 1); *v15 = v14; v8 = v15 + 1; v10 = v11 - 1; } while ( v11 != 1 ); if ( v25 == 1 ) break; v26 = v25 - 1; v17 = (uint32_t *)&src[(line + (uintptr_t)v7 - (uintptr_t)src) & 0x7FF]; v18 = (uint32_t *)((char *)v8 + ext); v19 = wid_64; do { v20 = v19; v21 = bswap32(v17[1]); ALOWORD(v19) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 15) & 0x1FE)), 1); v22 = v19 << 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 23) & 0x1FE)), 1); *v18 = v22; v23 = v18 + 1; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint16_t)v21 & 0x1FE)), 1); v22 <<= 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 7) & 0x1FE)), 1); *v23 = v22; ++v23; v24 = bswap32(*v17); v17 = (uint32_t *)&src[((uintptr_t)v17 + 8 - (uintptr_t)src) & 0x7FF]; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 15) & 0x1FE)), 1); v22 <<= 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 23) & 0x1FE)), 1); *v23 = v22; ++v23; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint16_t)v24 & 0x1FE)), 1); v22 <<= 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 7) & 0x1FE)), 1); *v23 = v22; v18 = v23 + 1; v19 = v20 - 1; } while ( v20 != 1 ); v7 = &src[(line + (uintptr_t)v17 - (uintptr_t)src) & 0x7FF]; v8 = (uint32_t *)((char *)v18 + ext); v9 = v26 - 1; } while ( v26 != 1 ); } static inline void load8bIA8(uint8_t *src, uint8_t *dst, int wid_64, int height, int line, int ext, uint16_t *pal) { uint32_t *v7; uint32_t *v8; int v9; int v10; int v11; uint32_t v12; uint32_t *v13; uint32_t v14; uint32_t *v15; uint32_t v16; uint32_t *v17; uint32_t *v18; int v19; int v20; uint32_t v21; uint32_t v22; uint32_t *v23; uint32_t v24; int v25; int v26; v7 = (uint32_t *)src; v8 = (uint32_t *)dst; v9 = height; do { v25 = v9; v10 = wid_64; do { v11 = v10; v12 = bswap32(*v7); v13 = v7 + 1; ALOWORD(v10) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 15) & 0x1FE)), 8); v14 = v10 << 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 23) & 0x1FE)), 8); *v8 = v14; v15 = v8 + 1; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint16_t)v12 & 0x1FE)), 8); v14 <<= 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 7) & 0x1FE)), 8); *v15 = v14; ++v15; v16 = bswap32(*v13); v7 = v13 + 1; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 15) & 0x1FE)), 8); v14 <<= 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 23) & 0x1FE)), 8); *v15 = v14; ++v15; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint16_t)v16 & 0x1FE)), 8); v14 <<= 16; ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 7) & 0x1FE)), 8); *v15 = v14; v8 = v15 + 1; v10 = v11 - 1; } while ( v11 != 1 ); if ( v25 == 1 ) break; v26 = v25 - 1; v17 = (uint32_t *)((char *)v7 + line); v18 = (uint32_t *)((char *)v8 + ext); v19 = wid_64; do { v20 = v19; v21 = bswap32(v17[1]); ALOWORD(v19) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 15) & 0x1FE)), 8); v22 = v19 << 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 23) & 0x1FE)), 8); *v18 = v22; v23 = v18 + 1; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint16_t)v21 & 0x1FE)), 8); v22 <<= 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 7) & 0x1FE)), 8); *v23 = v22; ++v23; v24 = bswap32(*v17); v17 += 2; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 15) & 0x1FE)), 8); v22 <<= 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 23) & 0x1FE)), 8); *v23 = v22; ++v23; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint16_t)v24 & 0x1FE)), 8); v22 <<= 16; ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 7) & 0x1FE)), 8); *v23 = v22; v18 = v23 + 1; v19 = v20 - 1; } while ( v20 != 1 ); v7 = (uint32_t *)((char *)v17 + line); v8 = (uint32_t *)((char *)v18 + ext); v9 = v26 - 1; } while ( v26 != 1 ); } static inline void load8bIA4(uint8_t *src, uint8_t *dst, int wid_64, int height, int line, int ext) { uint32_t *v6; uint32_t *v7; int v8; int v9; uint32_t v10; uint32_t v11; uint32_t *v12; uint32_t *v13; uint32_t v14; uint32_t v15; uint32_t *v16; uint32_t *v17; int v18; uint32_t *v19; uint32_t v20; int v21; int v22; v6 = (uint32_t *)src; v7 = (uint32_t *)dst; v8 = height; do { v21 = v8; v9 = wid_64; do { v10 = *v6; v11 = (*v6 >> 4) & 0xF0F0F0F; v12 = v6 + 1; *v7 = (16 * v10 & 0xF0F0F0F0) | v11; v13 = v7 + 1; v14 = (*v12 >> 4) & 0xF0F0F0F; v15 = 16 * *v12 & 0xF0F0F0F0; v6 = v12 + 1; *v13 = v15 | v14; v7 = v13 + 1; --v9; } while ( v9 ); if ( v21 == 1 ) break; v22 = v21 - 1; v16 = (uint32_t *)((char *)v6 + line); v17 = (uint32_t *)((char *)v7 + ext); v18 = wid_64; do { *v17 = (16 * v16[1] & 0xF0F0F0F0) | ((v16[1] >> 4) & 0xF0F0F0F); v19 = v17 + 1; v20 = *v16; v16 += 2; *v19 = (16 * v20 & 0xF0F0F0F0) | ((v20 >> 4) & 0xF0F0F0F); v17 = v19 + 1; --v18; } while ( v18 ); v6 = (uint32_t *)((char *)v16 + line); v7 = (uint32_t *)((char *)v17 + ext); v8 = v22 - 1; } while ( v22 != 1 ); } static inline void load8bI(uint8_t *src, uint8_t *dst, int wid_64, int height, int line, int ext) { uint32_t *v6; uint32_t *v7; int v8; int v9; uint32_t v10; uint32_t *v11; uint32_t *v12; uint32_t v13; uint32_t *v14; uint32_t *v15; int v16; uint32_t *v17; uint32_t v18; int v19; int v20; v6 = (uint32_t *)src; v7 = (uint32_t *)dst; v8 = height; do { v19 = v8; v9 = wid_64; do { v10 = *v6; v11 = v6 + 1; *v7 = v10; v12 = v7 + 1; v13 = *v11; v6 = v11 + 1; *v12 = v13; v7 = v12 + 1; --v9; } while ( v9 ); if ( v19 == 1 ) break; v20 = v19 - 1; v14 = (uint32_t *)((char *)v6 + line); v15 = (uint32_t *)((char *)v7 + ext); v16 = wid_64; do { *v15 = v14[1]; v17 = v15 + 1; v18 = *v14; v14 += 2; *v17 = v18; v15 = v17 + 1; --v16; } while ( v16 ); v6 = (uint32_t *)((char *)v14 + line); v7 = (uint32_t *)((char *)v15 + ext); v8 = v20 - 1; } while ( v20 != 1 ); } //**************************************************************** // Size: 1, Format: 2 // uint32_t Load8bCI (uint8_t *dst, uint8_t *src, int wid_64, int height, int line, int real_width, int tile) { if (wid_64 < 1) wid_64 = 1; if (height < 1) height = 1; unsigned short * pal = rdp.pal_8; int ext = (real_width - (wid_64 << 3)); if (ext < 0) return 0; switch (rdp.tlut_mode) { case 0: //palette is not used //in tlut DISABLE mode load CI texture as plain intensity texture instead of palette dereference. //Thanks to angrylion for the advice load8bI (src, dst, wid_64, height, line, ext); return /*(0 << 16) | */GR_TEXFMT_ALPHA_8; case 2: //color palette ext <<= 1; load8bCI (src, dst, wid_64, height, line, ext, pal); return (1 << 16) | GR_TEXFMT_ARGB_1555; default: //IA palette ext <<= 1; load8bIA8 (src, dst, wid_64, height, line, ext, pal); return (1 << 16) | GR_TEXFMT_ALPHA_INTENSITY_88; } } //**************************************************************** // Size: 1, Format: 3 // // ** by Gugaman ** uint32_t Load8bIA (uint8_t *dst, uint8_t *src, int wid_64, int height, int line, int real_width, int tile) { if (rdp.tlut_mode != 0) return Load8bCI (dst, src, wid_64, height, line, real_width, tile); if (wid_64 < 1) wid_64 = 1; if (height < 1) height = 1; int ext = (real_width - (wid_64 << 3)); if (ext < 0) return 0; load8bIA4 (src, dst, wid_64, height, line, ext); return /*(0 << 16) | */GR_TEXFMT_ALPHA_INTENSITY_44; } //**************************************************************** // Size: 1, Format: 4 // // ** by Gugaman ** uint32_t Load8bI (uint8_t *dst, uint8_t *src, int wid_64, int height, int line, int real_width, int tile) { if (rdp.tlut_mode != 0) return Load8bCI (dst, src, wid_64, height, line, real_width, tile); if (wid_64 < 1) wid_64 = 1; if (height < 1) height = 1; int ext = (real_width - (wid_64 << 3)); if (ext < 0) return 0; load8bI (src, dst, wid_64, height, line, ext); return /*(0 << 16) | */GR_TEXFMT_ALPHA_8; } mupen64plus-video-glide64-src-2.6.0/src/TexMod.h000066400000000000000000000414041464507525600212270ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** #ifndef _WIN32 #include #endif static void mod_tex_inter_color_using_factor (WORD *dst, int size, DWORD color, DWORD factor) { float percent = factor / 255.0f; float percent_i = 1 - percent; DWORD cr, cg, cb; WORD col, a; BYTE r, g, b; cr = (color >> 12) & 0xF; cg = (color >> 8) & 0xF; cb = (color >> 4) & 0xF; for (int i=0; i> 8) & 0xF) + percent * cr); g = (BYTE)(percent_i * ((col >> 4) & 0xF) + percent * cg); b = (BYTE)(percent_i * (col & 0xF) + percent * cb); *(dst++) = a | (r << 8) | (g << 4) | b; } } static void mod_tex_inter_col_using_col1 (WORD *dst, int size, DWORD color0, DWORD color1) { DWORD cr, cg, cb; WORD col, a; BYTE r, g, b; float percent_r = ((color1 >> 12) & 0xF) / 15.0f; float percent_g = ((color1 >> 8) & 0xF) / 15.0f; float percent_b = ((color1 >> 4) & 0xF) / 15.0f; float percent_r_i = 1.0f - percent_r; float percent_g_i = 1.0f - percent_g; float percent_b_i = 1.0f - percent_b; cr = (color0 >> 12) & 0xF; cg = (color0 >> 8) & 0xF; cb = (color0 >> 4) & 0xF; for (int i=0; i> 8) & 0xF) + percent_r * cr); g = (BYTE)(percent_g_i * ((col >> 4) & 0xF) + percent_g * cg); b = (BYTE)(percent_b_i * (col & 0xF) + percent_b * cb); *(dst++) = a | (r << 8) | (g << 4) | b; } } static void mod_full_color_sub_tex (WORD *dst, int size, DWORD color) { DWORD cr, cg, cb, ca; WORD col; BYTE a, r, g, b; cr = (color >> 12) & 0xF; cg = (color >> 8) & 0xF; cb = (color >> 4) & 0xF; ca = color & 0xF; for (int i=0; i> 12) & 0xF)); r = (BYTE)(cr - ((col >> 8) & 0xF)); g = (BYTE)(cg - ((col >> 4) & 0xF)); b = (BYTE)(cb - (col & 0xF)); *(dst++) = (a << 12) | (r << 8) | (g << 4) | b; } } static void mod_col_inter_col1_using_tex (WORD *dst, int size, DWORD color0, DWORD color1) { DWORD cr0, cg0, cb0, cr1, cg1, cb1; WORD col; BYTE r, g, b; WORD a; float percent_r, percent_g, percent_b; cr0 = (color0 >> 12) & 0xF; cg0 = (color0 >> 8) & 0xF; cb0 = (color0 >> 4) & 0xF; cr1 = (color1 >> 12) & 0xF; cg1 = (color1 >> 8) & 0xF; cb1 = (color1 >> 4) & 0xF; for (int i=0; i> 8) & 0xF) / 15.0f; percent_g = ((col >> 4) & 0xF) / 15.0f; percent_b = (col & 0xF) / 15.0f; r = std::min((BYTE)15, (BYTE)((1.0f-percent_r) * cr0 + percent_r * cr1)); g = std::min((BYTE)15, (BYTE)((1.0f-percent_g) * cg0 + percent_g * cg1)); b = std::min((BYTE)15, (BYTE)((1.0f-percent_b) * cb0 + percent_b * cb1)); *(dst++) = a | (r << 8) | (g << 4) | b; } } static void mod_col_inter_col1_using_texa (WORD *dst, int size, DWORD color0, DWORD color1) { DWORD cr0, cg0, cb0, cr1, cg1, cb1; WORD col; BYTE r, g, b; WORD a; float percent, percent_i; cr0 = (color0 >> 12) & 0xF; cg0 = (color0 >> 8) & 0xF; cb0 = (color0 >> 4) & 0xF; cr1 = (color1 >> 12) & 0xF; cg1 = (color1 >> 8) & 0xF; cb1 = (color1 >> 4) & 0xF; for (int i=0; i> 12) / 15.0f; percent_i = 1.0f - percent; r = (BYTE)(percent_i * cr0 + percent * cr1); g = (BYTE)(percent_i * cg0 + percent * cg1); b = (BYTE)(percent_i * cb0 + percent * cb1); *(dst++) = a | (r << 8) | (g << 4) | b; } } static void mod_col_inter_col1_using_texa__mul_tex (WORD *dst, int size, DWORD color0, DWORD color1) { DWORD cr0, cg0, cb0, cr1, cg1, cb1; WORD col; BYTE r, g, b; WORD a; float percent, percent_i; cr0 = (color0 >> 12) & 0xF; cg0 = (color0 >> 8) & 0xF; cb0 = (color0 >> 4) & 0xF; cr1 = (color1 >> 12) & 0xF; cg1 = (color1 >> 8) & 0xF; cb1 = (color1 >> 4) & 0xF; for (int i=0; i> 12) / 15.0f; percent_i = 1.0f - percent; r = (BYTE)(((percent_i * cr0 + percent * cr1) / 15.0f) * (((col & 0x0F00) >> 8) / 15.0f) * 15.0f); g = (BYTE)(((percent_i * cg0 + percent * cg1) / 15.0f) * (((col & 0x00F0) >> 4) / 15.0f) * 15.0f); b = (BYTE)(((percent_i * cb0 + percent * cb1) / 15.0f) * ((col & 0x000F) / 15.0f) * 15.0f); *(dst++) = a | (r << 8) | (g << 4) | b; } } static void mod_col_inter_tex_using_tex (WORD *dst, int size, DWORD color) { DWORD cr, cg, cb; WORD col; BYTE r, g, b; WORD a; float percent_r, percent_g, percent_b; cr = (color >> 12) & 0xF; cg = (color >> 8) & 0xF; cb = (color >> 4) & 0xF; for (int i=0; i> 8) & 0xF) / 15.0f; percent_g = ((col >> 4) & 0xF) / 15.0f; percent_b = (col & 0xF) / 15.0f; r = (BYTE)((1.0f-percent_r) * cr + percent_r * ((col & 0x0F00) >> 8)); g = (BYTE)((1.0f-percent_g) * cg + percent_g * ((col & 0x00F0) >> 4)); b = (BYTE)((1.0f-percent_b) * cb + percent_b * (col & 0x000F)); *(dst++) = a | (r << 8) | (g << 4) | b; } } static void mod_col_inter_tex_using_texa (WORD *dst, int size, DWORD color) { DWORD cr, cg, cb; WORD col; BYTE r, g, b; WORD a; float percent, percent_i; cr = (color >> 12) & 0xF; cg = (color >> 8) & 0xF; cb = (color >> 4) & 0xF; for (int i=0; i> 12) / 15.0f; percent_i = 1.0f - percent; r = (BYTE)(percent_i * cr + percent * ((col & 0x0F00) >> 8)); g = (BYTE)(percent_i * cg + percent * ((col & 0x00F0) >> 4)); b = (BYTE)(percent_i * cb + percent * (col & 0x000F)); *(dst++) = a | (r << 8) | (g << 4) | b; } } static void mod_col2_inter__col_inter_col1_using_tex__using_texa (WORD *dst, int size, DWORD color0, DWORD color1, DWORD color2) { DWORD cr0, cg0, cb0, cr1, cg1, cb1, cr2, cg2, cb2; WORD col; BYTE r, g, b; WORD a; float percent_r, percent_g, percent_b, percent_a; cr0 = (color0 >> 12) & 0xF; cg0 = (color0 >> 8) & 0xF; cb0 = (color0 >> 4) & 0xF; cr1 = (color1 >> 12) & 0xF; cg1 = (color1 >> 8) & 0xF; cb1 = (color1 >> 4) & 0xF; cr2 = (color2 >> 12) & 0xF; cg2 = (color2 >> 8) & 0xF; cb2 = (color2 >> 4) & 0xF; for (int i=0; i> 12) / 15.0f; percent_r = ((col >> 8) & 0xF) / 15.0f; percent_g = ((col >> 4) & 0xF) / 15.0f; percent_b = (col & 0xF) / 15.0f; r = (BYTE)(((1.0f-percent_r) * cr0 + percent_r * cr1) * percent_a + cr2 * (1.0f-percent_a)); g = (BYTE)(((1.0f-percent_g) * cg0 + percent_g * cg1) * percent_a + cg2 * (1.0f-percent_a)); b = (BYTE)(((1.0f-percent_b) * cb0 + percent_b * cb1) * percent_a + cb2 * (1.0f-percent_a)); *(dst++) = a | (r << 8) | (g << 4) | b; } } static void mod_tex_scale_fac_add_fac (WORD *dst, int size, DWORD factor) { float percent = factor / 255.0f; WORD col; BYTE a; float base_a = (1.0f - percent) * 15.0f; for (int i=0; i>12)); *(dst++) = (a<<12) | (col & 0x0FFF); } } static void mod_tex_sub_col_mul_fac_add_tex (WORD *dst, int size, DWORD color, DWORD factor) { float percent = factor / 255.0f; DWORD cr, cg, cb; WORD col, a; float r, g, b; cr = (color >> 12) & 0xF; cg = (color >> 8) & 0xF; cb = (color >> 4) & 0xF; for (int i=0; i> 8) & 0xF); r = /*max(*/(r - cr) * percent/*, 0.0f)*/ + r; if (r > 15.0f) r = 15.0f; if (r < 0.0f) r = 0.0f; g = (float)((col >> 4) & 0xF); g = /*max(*/(g - cg) * percent/*, 0.0f)*/ + g; if (g > 15.0f) g = 15.0f; if (g < 0.0f) g = 0.0f; b = (float)(col & 0xF); b = /*max(*/(b - cb) * percent/*, 0.0f)*/ + b; if (b > 15.0f) b = 15.0f; if (b < 0.0f) b = 0.0f; *(dst++) = a | ((WORD)r << 8) | ((WORD)g << 4) | (WORD)b; } } static void mod_tex_scale_col_add_col (WORD *dst, int size, DWORD color, DWORD factor) { float percent = factor / 255.0f; float percent_r = (1.0f - ((color>>12)&0xF) / 15.0f) * percent; float percent_g = (1.0f - ((color>>8)&0xF) / 15.0f) * percent; float percent_b = (1.0f - ((color>>4)&0xF) / 15.0f) * percent; WORD col; float base = (1.0f - percent) * 15.0f; float r, g, b; for (int i=0; i>8)&0xF); g = base + percent_g * (float)((col>>4)&0xF); b = base + percent_b * (float)(col&0xF); *(dst++) = (col&0xF000) | ((BYTE)r << 8) | ((BYTE)g << 4) | (BYTE)b; } } static void mod_tex_add_col (WORD *dst, int size, DWORD color) { DWORD cr, cg, cb; WORD col; BYTE a, r, g, b; cr = (color >> 12) & 0xF; cg = (color >> 8) & 0xF; cb = (color >> 4) & 0xF; for (int i=0; i> 12) & 0xF); // a = col & 0xF000; r = (BYTE)(cr + ((col >> 8) & 0xF))&0xF; g = (BYTE)(cg + ((col >> 4) & 0xF))&0xF; b = (BYTE)(cb + (col & 0xF))&0xF; *(dst++) = (a << 12) | (r << 8) | (g << 4) | b; } } static void mod_col_mul_texa_add_tex (WORD *dst, int size, DWORD color) { DWORD cr, cg, cb; WORD col; BYTE r, g, b; WORD a; float factor; cr = (color >> 12) & 0xF; cg = (color >> 8) & 0xF; cb = (color >> 4) & 0xF; for (int i=0; i> 12) / 15.0f; r = (BYTE)(cr*factor + ((col >> 8) & 0xF))&0xF; g = (BYTE)(cg*factor + ((col >> 4) & 0xF))&0xF; b = (BYTE)(cb*factor + (col & 0xF))&0xF; *(dst++) = a | (r << 8) | (g << 4) | b; } } static void mod_tex_sub_col (WORD *dst, int size, DWORD color) { DWORD cr, cg, cb, ca; WORD col; BYTE a, r, g, b; cr = (color >> 12) & 0xF; cg = (color >> 8) & 0xF; cb = (color >> 4) & 0xF; ca = color & 0xF; for (int i=0; i> 12) & 0xF) - ca); r = (BYTE)(((col >> 8) & 0xF) - cr); g = (BYTE)(((col >> 4) & 0xF) - cg); b = (BYTE)((col & 0xF) - cb); *(dst++) = (a << 12) | (r << 8) | (g << 4) | b; } } static void mod_tex_sub_col_mul_fac (WORD *dst, int size, DWORD color, DWORD factor) { float percent = factor / 255.0f; DWORD cr, cg, cb; WORD col, a; float r, g, b; cr = (color >> 12) & 0xF; cg = (color >> 8) & 0xF; cb = (color >> 4) & 0xF; for (int i=0; i> 12) & 0xF); r = (float)((col >> 8) & 0xF); r = (r - cr) * percent; if (r > 15.0f) r = 15.0f; if (r < 0.0f) r = 0.0f; g = (float)((col >> 4) & 0xF); g = (g - cg) * percent; if (g > 15.0f) g = 15.0f; if (g < 0.0f) g = 0.0f; b = (float)(col & 0xF); b = (b - cb) * percent; if (b > 15.0f) b = 15.0f; if (b < 0.0f) b = 0.0f; *(dst++) = (a << 12) | ((WORD)r << 8) | ((WORD)g << 4) | (WORD)b; } } static void mod_col_inter_tex_using_col1 (WORD *dst, int size, DWORD color0, DWORD color1) { DWORD cr, cg, cb; WORD col, a; BYTE r, g, b; float percent_r = ((color1 >> 12) & 0xF) / 15.0f; float percent_g = ((color1 >> 8) & 0xF) / 15.0f; float percent_b = ((color1 >> 4) & 0xF) / 15.0f; float percent_r_i = 1.0f - percent_r; float percent_g_i = 1.0f - percent_g; float percent_b_i = 1.0f - percent_b; cr = (color0 >> 12) & 0xF; cg = (color0 >> 8) & 0xF; cb = (color0 >> 4) & 0xF; for (int i=0; i> 12) & 0xF); r = (BYTE)(percent_r * ((col >> 8) & 0xF) + percent_r_i * cr); g = (BYTE)(percent_g * ((col >> 4) & 0xF) + percent_g_i * cg); b = (BYTE)(percent_b * (col & 0xF) + percent_b_i * cb); *(dst++) = (a << 12) | (r << 8) | (g << 4) | b; } } static void mod_tex_inter_noise_using_col (WORD *dst, int size, DWORD color) { WORD col, a; BYTE r, g, b, noise; float percent_r = ((color >> 12) & 0xF) / 15.0f; float percent_g = ((color >> 8) & 0xF) / 15.0f; float percent_b = ((color >> 4) & 0xF) / 15.0f; float percent_r_i = 1.0f - percent_r; float percent_g_i = 1.0f - percent_g; float percent_b_i = 1.0f - percent_b; for (int i=0; i> 8) & 0xF) + percent_r * noise); g = (BYTE)(percent_g_i * ((col >> 4) & 0xF) + percent_g * noise); b = (BYTE)(percent_b_i * (col & 0xF) + percent_b * noise); *(dst++) = a | (r << 8) | (g << 4) | b; } } static void mod_tex_inter_col_using_texa (WORD *dst, int size, DWORD color) { DWORD cr, cg, cb; WORD col; BYTE r, g, b; WORD a; float percent, percent_i; cr = (color >> 12) & 0xF; cg = (color >> 8) & 0xF; cb = (color >> 4) & 0xF; for (int i=0; i> 12) / 15.0f; percent_i = 1.0f - percent; r = (BYTE)(percent * cr + percent_i * ((col & 0x0F00) >> 8)); g = (BYTE)(percent * cg + percent_i * ((col & 0x00F0) >> 4)); b = (BYTE)(percent * cb + percent_i * (col & 0x000F)); *(dst++) = a | (r << 8) | (g << 4) | b; } } static void mod_tex_mul_col (WORD *dst, int size, DWORD color) { float cr, cg, cb; WORD col; BYTE r, g, b; WORD a; cr = (float)((color >> 12) & 0xF)/16.0f; cg = (float)((color >> 8) & 0xF)/16.0f; cb = (float)((color >> 4) & 0xF)/16.0f; for (int i=0; i> 8)); g = (BYTE)(cg * ((col & 0x00F0) >> 4)); b = (BYTE)(cb * (col & 0x000F)); *(dst++) = a | (r << 8) | (g << 4) | b; } } static void mod_tex_scale_fac_add_col (WORD *dst, int size, DWORD color, DWORD factor) { float percent = factor / 255.0f; DWORD cr, cg, cb; WORD col; float r, g, b; cr = (color >> 12) & 0xF; cg = (color >> 8) & 0xF; cb = (color >> 4) & 0xF; for (int i=0; i>8)&0xF); g = cg + percent * (float)((col>>4)&0xF); b = cb + percent * (float)(col&0xF); *(dst++) = (col&0xF000) | ((BYTE)r << 8) | ((BYTE)g << 4) | (BYTE)b; } } mupen64plus-video-glide64-src-2.6.0/src/TexModCI.h000066400000000000000000000345741464507525600214550ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** static void mod_tex_inter_color_using_factor_CI (DWORD color, DWORD factor) { float percent = factor / 255.0f; float percent_i = 1 - percent; BYTE cr, cg, cb; WORD col; BYTE a, r, g, b; cr = (BYTE)((color >> 24) & 0xFF); cg = (BYTE)((color >> 16) & 0xFF); cb = (BYTE)((color >> 8) & 0xFF); for (int i=0; i<256; i++) { col = rdp.pal_8[i]; a = (BYTE)(col&0x0001);; r = (BYTE)((float)((col&0xF800) >> 11) / 31.0f * 255.0f); g = (BYTE)((float)((col&0x07C0) >> 6) / 31.0f * 255.0f); b = (BYTE)((float)((col&0x003E) >> 1) / 31.0f * 255.0f); r = (BYTE)(std::min(255.0f, percent_i * r + percent * cr)); g = (BYTE)(std::min(255.0f, percent_i * g + percent * cg)); b = (BYTE)(std::min(255.0f, percent_i * b + percent * cb)); rdp.pal_8[i] = (WORD)(((WORD)(r >> 3) << 11) | ((WORD)(g >> 3) << 6) | ((WORD)(b >> 3) << 1) | ((WORD)(a ) << 0)); } } static void mod_tex_inter_col_using_col1_CI (DWORD color0, DWORD color1) { BYTE cr, cg, cb; WORD col; BYTE a, r, g, b; float percent_r = ((color1 >> 24) & 0xFF) / 255.0f; float percent_g = ((color1 >> 16) & 0xFF) / 255.0f; float percent_b = ((color1 >> 8) & 0xFF) / 255.0f; float percent_r_i = 1.0f - percent_r; float percent_g_i = 1.0f - percent_g; float percent_b_i = 1.0f - percent_b; cr = (BYTE)((color0 >> 24) & 0xFF); cg = (BYTE)((color0 >> 16) & 0xFF); cb = (BYTE)((color0 >> 8) & 0xFF); for (int i=0; i<256; i++) { col = rdp.pal_8[i]; a = (BYTE)(col&0x0001);; r = (BYTE)((float)((col&0xF800) >> 11) / 31.0f * 255.0f); g = (BYTE)((float)((col&0x07C0) >> 6) / 31.0f * 255.0f); b = (BYTE)((float)((col&0x003E) >> 1) / 31.0f * 255.0f); r = (BYTE)(std::min(255.0f, percent_r_i * r + percent_r * cr)); g = (BYTE)(std::min(255.0f, percent_g_i * g + percent_g * cg)); b = (BYTE)(std::min(255.0f, percent_b_i * b + percent_b * cb)); rdp.pal_8[i] = (WORD)(((WORD)(r >> 3) << 11) | ((WORD)(g >> 3) << 6) | ((WORD)(b >> 3) << 1) | ((WORD)(a ) << 0)); } } static void mod_full_color_sub_tex_CI (DWORD color) { BYTE cr, cg, cb, ca; WORD col; BYTE a, r, g, b; cr = (BYTE)((color >> 24) & 0xFF); cg = (BYTE)((color >> 16) & 0xFF); cb = (BYTE)((color >> 8) & 0xFF); ca = (BYTE)(color & 0xFF); for (int i=0; i<256; i++) { col = rdp.pal_8[i]; a = (BYTE)(col&0x0001);; r = (BYTE)((float)((col&0xF800) >> 11) / 31.0f * 255.0f); g = (BYTE)((float)((col&0x07C0) >> 6) / 31.0f * 255.0f); b = (BYTE)((float)((col&0x003E) >> 1) / 31.0f * 255.0f); a = std::max(0, ca - a); r = std::max(0, cr - r); g = std::max(0, cg - g); b = std::max(0, cb - b); rdp.pal_8[i] = (WORD)(((WORD)(r >> 3) << 11) | ((WORD)(g >> 3) << 6) | ((WORD)(b >> 3) << 1) | ((WORD)(a ) << 0)); } } static void mod_col_inter_col1_using_tex_CI (DWORD color0, DWORD color1) { DWORD cr0, cg0, cb0, cr1, cg1, cb1; WORD col; BYTE a, r, g, b; float percent_r, percent_g, percent_b; cr0 = (BYTE)((color0 >> 24) & 0xFF); cg0 = (BYTE)((color0 >> 16) & 0xFF); cb0 = (BYTE)((color0 >> 8) & 0xFF); cr1 = (BYTE)((color1 >> 24) & 0xFF); cg1 = (BYTE)((color1 >> 16) & 0xFF); cb1 = (BYTE)((color1 >> 8) & 0xFF); for (int i=0; i<256; i++) { col = rdp.pal_8[i]; a = (BYTE)(col&0x0001);; percent_r = ((col&0xF800) >> 11) / 31.0f; percent_g = ((col&0x07C0) >> 6) / 31.0f; percent_b = ((col&0x003E) >> 1) / 31.0f; r = (BYTE)(std::min((1.0f-percent_r) * cr0 + percent_r * cr1, 255.0f)); g = (BYTE)(std::min((1.0f-percent_g) * cg0 + percent_g * cg1, 255.0f)); b = (BYTE)(std::min((1.0f-percent_b) * cb0 + percent_b * cb1, 255.0f)); rdp.pal_8[i] = (WORD)(((WORD)(r >> 3) << 11) | ((WORD)(g >> 3) << 6) | ((WORD)(b >> 3) << 1) | ((WORD)(a ) << 0)); } } static void mod_tex_sub_col_mul_fac_add_tex_CI (DWORD color, DWORD factor) { float percent = factor / 255.0f; BYTE cr, cg, cb, a; WORD col; float r, g, b; cr = (BYTE)((color >> 24) & 0xFF); cg = (BYTE)((color >> 16) & 0xFF); cb = (BYTE)((color >> 8) & 0xFF); for (int i=0; i<256; i++) { col = rdp.pal_8[i]; a = (BYTE)(col&0x0001);; r = (BYTE)((float)((col&0xF800) >> 11) / 31.0f * 255.0f); g = (BYTE)((float)((col&0x07C0) >> 6) / 31.0f * 255.0f); b = (BYTE)((float)((col&0x003E) >> 1) / 31.0f * 255.0f); r = (r - cr) * percent + r; if (r > 255.0f) r = 255.0f; if (r < 0.0f) r = 0.0f; g = (g - cg) * percent + g; if (g > 255.0f) g = 255.0f; if (g < 0.0f) g = 0.0f; b = (b - cb) * percent + b; if (b > 255.0f) g = 255.0f; if (b < 0.0f) b = 0.0f; rdp.pal_8[i] = (WORD)(((WORD)((BYTE)(r) >> 3) << 11) | ((WORD)((BYTE)(g) >> 3) << 6) | ((WORD)((BYTE)(b) >> 3) << 1) | (WORD)(a) ); } } static void mod_tex_scale_col_add_col_CI (DWORD color, DWORD factor) { float percent = factor / 255.0f; float percent_r = (1.0f - ((color >> 24) & 0xFF) / 255.0f) * percent; float percent_g = (1.0f - ((color >> 16) & 0xFF) / 255.0f) * percent; float percent_b = (1.0f - ((color >> 8) & 0xFF) / 255.0f) * percent; WORD col; float base = (1.0f - percent) * 255.0f; BYTE a, r, g, b; for (int i=0; i<256; i++) { col = rdp.pal_8[i]; a = (BYTE)(col&0x0001);; r = (BYTE)((float)((col&0xF800) >> 11) / 31.0f * 255.0f); g = (BYTE)((float)((col&0x07C0) >> 6) / 31.0f * 255.0f); b = (BYTE)((float)((col&0x003E) >> 1) / 31.0f * 255.0f); r = (BYTE)(std::min(base + percent_r * r, 255.0f)); g = (BYTE)(std::min(base + percent_g * g, 255.0f)); b = (BYTE)(std::min(base + percent_b * b, 255.0f)); rdp.pal_8[i] = (WORD)(((WORD)(r >> 3) << 11) | ((WORD)(g >> 3) << 6) | ((WORD)(b >> 3) << 1) | (WORD)(a) ); } } static void mod_tex_add_col_CI (DWORD color) { BYTE cr, cg, cb; WORD col; BYTE a, r, g, b; cr = (BYTE)((color >> 24) & 0xFF); cg = (BYTE)((color >> 16) & 0xFF); cb = (BYTE)((color >> 8) & 0xFF); for (int i=0; i<256; i++) { col = rdp.pal_8[i]; a = (BYTE)(col&0x0001);; r = (BYTE)((float)((col&0xF800) >> 11) / 31.0f * 255.0f); g = (BYTE)((float)((col&0x07C0) >> 6) / 31.0f * 255.0f); b = (BYTE)((float)((col&0x003E) >> 1) / 31.0f * 255.0f); r = std::min(cr + r, 255); g = std::min(cg + g, 255); b = std::min(cb + b, 255); rdp.pal_8[i] = (WORD)(((WORD)(r >> 3) << 11) | ((WORD)(g >> 3) << 6) | ((WORD)(b >> 3) << 1) | ((WORD)(a ) << 0)); } } static void mod_tex_sub_col_CI (DWORD color) { BYTE cr, cg, cb; WORD col; BYTE a, r, g, b; cr = (BYTE)((color >> 24) & 0xFF); cg = (BYTE)((color >> 16) & 0xFF); cb = (BYTE)((color >> 8) & 0xFF); for (int i=0; i<256; i++) { col = rdp.pal_8[i]; a = (BYTE)(col&0x0001);; r = (BYTE)((float)((col&0xF800) >> 11) / 31.0f * 255.0f); g = (BYTE)((float)((col&0x07C0) >> 6) / 31.0f * 255.0f); b = (BYTE)((float)((col&0x003E) >> 1) / 31.0f * 255.0f); r = std::max(r - cr, 0); g = std::max(g - cg, 0); b = std::max(b - cb, 0); rdp.pal_8[i] = (WORD)(((WORD)(r >> 3) << 11) | ((WORD)(g >> 3) << 6) | ((WORD)(b >> 3) << 1) | ((WORD)(a ) << 0)); } } static void mod_tex_sub_col_mul_fac_CI (DWORD color, DWORD factor) { float percent = factor / 255.0f; BYTE cr, cg, cb; WORD col; BYTE a; float r, g, b; cr = (BYTE)((color >> 24) & 0xFF); cg = (BYTE)((color >> 16) & 0xFF); cb = (BYTE)((color >> 8) & 0xFF); for (int i=0; i<256; i++) { col = rdp.pal_8[i]; a = (BYTE)(col&0x0001); r = (float)((col&0xF800) >> 11) / 31.0f * 255.0f; g = (float)((col&0x07C0) >> 6) / 31.0f * 255.0f; b = (float)((col&0x003E) >> 1) / 31.0f * 255.0f; r = (r - cr) * percent; if (r > 255.0f) r = 255.0f; if (r < 0.0f) r = 0.0f; g = (g - cg) * percent; if (g > 255.0f) g = 255.0f; if (g < 0.0f) g = 0.0f; b = (b - cb) * percent; if (b > 255.0f) g = 255.0f; if (b < 0.0f) b = 0.0f; rdp.pal_8[i] = (WORD)(((WORD)((BYTE)(r) >> 3) << 11) | ((WORD)((BYTE)(g) >> 3) << 6) | ((WORD)((BYTE)(b) >> 3) << 1) | (WORD)(a) ); } } static void mod_col_inter_tex_using_col1_CI (DWORD color0, DWORD color1) { BYTE cr, cg, cb; WORD col; BYTE a, r, g, b; float percent_r = ((color1 >> 24) & 0xFF) / 255.0f; float percent_g = ((color1 >> 16) & 0xFF) / 255.0f; float percent_b = ((color1 >> 8) & 0xFF) / 255.0f; float percent_r_i = 1.0f - percent_r; float percent_g_i = 1.0f - percent_g; float percent_b_i = 1.0f - percent_b; cr = (BYTE)((color0 >> 24) & 0xFF); cg = (BYTE)((color0 >> 16) & 0xFF); cb = (BYTE)((color0 >> 8) & 0xFF); for (int i=0; i<256; i++) { col = rdp.pal_8[i]; a = (BYTE)(col&0x0001);; r = (BYTE)((float)((col&0xF800) >> 11) / 31.0f * 255.0f); g = (BYTE)((float)((col&0x07C0) >> 6) / 31.0f * 255.0f); b = (BYTE)((float)((col&0x003E) >> 1) / 31.0f * 255.0f); r = (BYTE)(std::min(255.0f, percent_r * r + percent_r_i * cr)); g = (BYTE)(std::min(255.0f, percent_g * g + percent_g_i * cg)); b = (BYTE)(std::min(255.0f, percent_b * b + percent_b_i * cb)); rdp.pal_8[i] = (WORD)(((WORD)(r >> 3) << 11) | ((WORD)(g >> 3) << 6) | ((WORD)(b >> 3) << 1) | ((WORD)(a ) << 0)); } } static void mod_tex_inter_col_using_texa_CI (DWORD color) { BYTE a, r, g, b; r = (BYTE)((float)((color >> 24) & 0xFF) / 255.0f * 31.0f); g = (BYTE)((float)((color >> 16) & 0xFF) / 255.0f * 31.0f); b = (BYTE)((float)((color >> 8) & 0xFF) / 255.0f * 31.0f); a = (color&0xFF) ? 1 : 0; WORD col16 = (WORD)((r<<11)|(g<<6)|(b<<1)|a); for (int i=0; i<256; i++) { if (rdp.pal_8[i]&1) rdp.pal_8[i] = col16; } } static void mod_tex_mul_col_CI (DWORD color) { BYTE a, r, g, b; WORD col; float cr, cg, cb; cr = (float)((color >> 24) & 0xFF) / 255.0f; cg = (float)((color >> 16) & 0xFF) / 255.0f; cb = (float)((color >> 8) & 0xFF) / 255.0f; for (int i=0; i<256; i++) { col = rdp.pal_8[i]; a = (BYTE)(col&0x0001);; r = (BYTE)((float)((col&0xF800) >> 11) * cr); g = (BYTE)((float)((col&0x07C0) >> 6) * cg); b = (BYTE)((float)((col&0x003E) >> 1) * cb); rdp.pal_8[i] = (WORD)(((WORD)(r >> 3) << 11) | ((WORD)(g >> 3) << 6) | ((WORD)(b >> 3) << 1) | ((WORD)(a ) << 0)); } } static void ModifyPalette(DWORD mod, DWORD modcolor, DWORD modcolor1, DWORD modfactor) { switch (mod) { case TMOD_TEX_INTER_COLOR_USING_FACTOR: mod_tex_inter_color_using_factor_CI (modcolor, modfactor); break; case TMOD_TEX_INTER_COL_USING_COL1: mod_tex_inter_col_using_col1_CI (modcolor, modcolor1); break; case TMOD_FULL_COLOR_SUB_TEX: mod_full_color_sub_tex_CI (modcolor); break; case TMOD_COL_INTER_COL1_USING_TEX: mod_col_inter_col1_using_tex_CI (modcolor, modcolor1); break; case TMOD_TEX_SUB_COL_MUL_FAC_ADD_TEX: mod_tex_sub_col_mul_fac_add_tex_CI (modcolor, modfactor); break; case TMOD_TEX_SCALE_COL_ADD_COL: mod_tex_scale_col_add_col_CI (modcolor, modfactor); break; case TMOD_TEX_ADD_COL: mod_tex_add_col_CI (modcolor); break; case TMOD_TEX_SUB_COL: mod_tex_sub_col_CI (modcolor); break; case TMOD_TEX_SUB_COL_MUL_FAC: mod_tex_sub_col_mul_fac_CI (modcolor, modfactor); break; case TMOD_COL_INTER_TEX_USING_COL1: mod_col_inter_tex_using_col1_CI (modcolor, modcolor1); break; case TMOD_TEX_INTER_COL_USING_TEXA: mod_tex_inter_col_using_texa_CI (modcolor); break; case TMOD_TEX_MUL_COL: mod_tex_mul_col_CI (modcolor); break; default: ; } } mupen64plus-video-glide64-src-2.6.0/src/Tmem.h000066400000000000000000000035311464507525600207300ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** #if !defined(WIN32) && defined(GCC) #define SwapBlock32 _SwapBlock32 #define SwapBlock64 _SwapBlock64 #endif extern "C" void CopyBlock (); extern "C" void SwapBlock32 (); extern "C" void SwapBlock64 (); mupen64plus-video-glide64-src-2.6.0/src/Ucode00.h000066400000000000000000000662331464507525600212350ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** #include #ifdef GCC #include #define __int32 int32_t #endif static void uc0_enddl(); // ** Definitions ** // // matrix functions ***** SWITCH TO POINTERS LATER ****** // void modelview_load (float m[4][4]) { memcpy (rdp.model, m, 64); // 4*4*4(float) rdp.update |= UPDATE_MULT_MAT | UPDATE_LIGHTS; } void modelview_mul (float m[4][4]) { __declspec( align(16) ) float m_src[4][4]; memcpy (m_src, rdp.model, 64); MulMatrices(m, m_src, rdp.model); rdp.update |= UPDATE_MULT_MAT | UPDATE_LIGHTS; } void modelview_push () { if (rdp.model_i == rdp.model_stack_size) { RDP_E ("** Model matrix stack overflow ** too many pushes\n"); RDP ("** Model matrix stack overflow ** too many pushes\n"); return; } memcpy (rdp.model_stack[rdp.model_i], rdp.model, 64); rdp.model_i ++; } void modelview_pop (int num = 1) { if (rdp.model_i > num - 1) { rdp.model_i -= num; } else { RDP_E ("** Model matrix stack error ** too many pops\n"); RDP ("** Model matrix stack error ** too many pops\n"); return; } memcpy (rdp.model, rdp.model_stack[rdp.model_i], 64); rdp.update |= UPDATE_MULT_MAT | UPDATE_LIGHTS; } void modelview_load_push (float m[4][4]) { modelview_push (); modelview_load (m); } void modelview_mul_push (float m[4][4]) { modelview_push (); modelview_mul (m); } void projection_load (float m[4][4]) { memcpy (rdp.proj, m, 64); // 4*4*4(float) rdp.update |= UPDATE_MULT_MAT; } void projection_mul (float m[4][4]) { __declspec( align(16) ) float m_src[4][4]; memcpy (m_src, rdp.proj, 64); MulMatrices(m, m_src, rdp.proj); rdp.update |= UPDATE_MULT_MAT; } // // uc0:matrix - performs matrix operations // static void uc0_matrix() { RDP("uc0:matrix "); // Use segment offset to get the address DWORD addr = segoffset(rdp.cmd1) & 0x00FFFFFF; BYTE command = (BYTE)((rdp.cmd0 >> 16) & 0xFF); __declspec( align(16) ) float m[4][4]; int x,y; // matrix index addr >>= 1; for (x=0; x<16; x+=4) { // Adding 4 instead of one, just to remove mult. later for (y=0; y<4; y++) { m[x>>2][y] = (float)( (((__int32)((WORD*)gfx.RDRAM)[(addr+x+y)^1]) << 16) | ((WORD*)gfx.RDRAM)[(addr+x+y+16)^1] ) / 65536.0f; } } switch (command) { case 0: // modelview mul nopush RDP ("modelview mul\n"); modelview_mul (m); break; case 1: // projection mul nopush case 5: // projection mul push, can't push projection RDP ("projection mul\n"); projection_mul (m); break; case 2: // modelview load nopush RDP ("modelview load\n"); modelview_load (m); break; case 3: // projection load nopush case 7: // projection load push, can't push projection RDP ("projection load\n"); projection_load (m); break; case 4: // modelview mul push RDP ("modelview mul push\n"); modelview_mul_push (m); break; case 6: // modelview load push RDP ("modelview load push\n"); modelview_load_push (m); break; default: FRDP_E ("Unknown matrix command, %02lx", command); FRDP ("Unknown matrix command, %02lx", command); } #ifdef EXTREME_LOGGING FRDP ("{%f,%f,%f,%f}\n", m[0][0], m[0][1], m[0][2], m[0][3]); FRDP ("{%f,%f,%f,%f}\n", m[1][0], m[1][1], m[1][2], m[1][3]); FRDP ("{%f,%f,%f,%f}\n", m[2][0], m[2][1], m[2][2], m[2][3]); FRDP ("{%f,%f,%f,%f}\n", m[3][0], m[3][1], m[3][2], m[3][3]); FRDP ("\nmodel\n{%f,%f,%f,%f}\n", rdp.model[0][0], rdp.model[0][1], rdp.model[0][2], rdp.model[0][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.model[1][0], rdp.model[1][1], rdp.model[1][2], rdp.model[1][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.model[2][0], rdp.model[2][1], rdp.model[2][2], rdp.model[2][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.model[3][0], rdp.model[3][1], rdp.model[3][2], rdp.model[3][3]); FRDP ("\nproj\n{%f,%f,%f,%f}\n", rdp.proj[0][0], rdp.proj[0][1], rdp.proj[0][2], rdp.proj[0][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.proj[1][0], rdp.proj[1][1], rdp.proj[1][2], rdp.proj[1][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.proj[2][0], rdp.proj[2][1], rdp.proj[2][2], rdp.proj[2][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.proj[3][0], rdp.proj[3][1], rdp.proj[3][2], rdp.proj[3][3]); #endif } // // uc0:movemem - loads a structure with data // static void uc0_movemem() { RDP("uc0:movemem "); DWORD i,a; // Check the command switch ((rdp.cmd0 >> 16) & 0xFF) { case 0x80: { a = (segoffset(rdp.cmd1) & 0xFFFFFF) >> 1; short scale_x = ((short*)gfx.RDRAM)[(a+0)^1] / 4; short scale_y = ((short*)gfx.RDRAM)[(a+1)^1] / 4; short scale_z = ((short*)gfx.RDRAM)[(a+2)^1]; short trans_x = ((short*)gfx.RDRAM)[(a+4)^1] / 4; short trans_y = ((short*)gfx.RDRAM)[(a+5)^1] / 4; short trans_z = ((short*)gfx.RDRAM)[(a+6)^1]; rdp.view_scale[0] = scale_x * rdp.scale_x; rdp.view_scale[1] = -scale_y * rdp.scale_y; rdp.view_scale[2] = 32.0f * scale_z; rdp.view_trans[0] = trans_x * rdp.scale_x + rdp.offset_x; rdp.view_trans[1] = trans_y * rdp.scale_y + rdp.offset_y; rdp.view_trans[2] = 32.0f * trans_z; // there are other values than x and y, but I don't know what they do rdp.update |= UPDATE_VIEWPORT; FRDP ("viewport scale(%d, %d, %d), trans(%d, %d, %d), from:%08lx\n", scale_x, scale_y, scale_z, trans_x, trans_y, trans_z, rdp.cmd1); } break; case 0x82: { a = segoffset(rdp.cmd1) & 0x00ffffff; char dir_x = ((char*)gfx.RDRAM)[(a+8)^3]; rdp.lookat[1][0] = (float)(dir_x) / 127.0f; char dir_y = ((char*)gfx.RDRAM)[(a+9)^3]; rdp.lookat[1][1] = (float)(dir_y) / 127.0f; char dir_z = ((char*)gfx.RDRAM)[(a+10)^3]; rdp.lookat[1][2] = (float)(dir_z) / 127.0f; if (!dir_x && !dir_y) rdp.use_lookat = FALSE; else rdp.use_lookat = TRUE; FRDP("lookat_y (%f, %f, %f)\n", rdp.lookat[1][0], rdp.lookat[1][1], rdp.lookat[1][2]); } break; case 0x84: a = segoffset(rdp.cmd1) & 0x00ffffff; rdp.lookat[0][0] = (float)(((char*)gfx.RDRAM)[(a+8)^3]) / 127.0f; rdp.lookat[0][1] = (float)(((char*)gfx.RDRAM)[(a+9)^3]) / 127.0f; rdp.lookat[0][2] = (float)(((char*)gfx.RDRAM)[(a+10)^3]) / 127.0f; rdp.use_lookat = TRUE; FRDP("lookat_x (%f, %f, %f)\n", rdp.lookat[1][0], rdp.lookat[1][1], rdp.lookat[1][2]); break; case 0x86: case 0x88: case 0x8a: case 0x8c: case 0x8e: case 0x90: case 0x92: case 0x94: // Get the light # i = (((rdp.cmd0 >> 16) & 0xff) - 0x86) >> 1; a = segoffset(rdp.cmd1) & 0x00ffffff; // Get the data rdp.light[i].r = (float)(((BYTE*)gfx.RDRAM)[(a+0)^3]) / 255.0f; rdp.light[i].g = (float)(((BYTE*)gfx.RDRAM)[(a+1)^3]) / 255.0f; rdp.light[i].b = (float)(((BYTE*)gfx.RDRAM)[(a+2)^3]) / 255.0f; rdp.light[i].a = 1.0f; // ** Thanks to Icepir8 for pointing this out ** // Lighting must be signed byte instead of byte rdp.light[i].dir_x = (float)(((char*)gfx.RDRAM)[(a+8)^3]) / 127.0f; rdp.light[i].dir_y = (float)(((char*)gfx.RDRAM)[(a+9)^3]) / 127.0f; rdp.light[i].dir_z = (float)(((char*)gfx.RDRAM)[(a+10)^3]) / 127.0f; // ** //rdp.update |= UPDATE_LIGHTS; FRDP ("light: n: %d, r: %.3f, g: %.3f, b: %.3f, x: %.3f, y: %.3f, z: %.3f\n", i, rdp.light[i].r, rdp.light[i].g, rdp.light[i].b, rdp.light_vector[i][0], rdp.light_vector[i][1], rdp.light_vector[i][2]); break; case 0x9E: //gSPForceMatrix command. Modification of uc2_movemem:matrix. Gonetz. { // do not update the combined matrix! rdp.update &= ~UPDATE_MULT_MAT; int x,y; DWORD addr = segoffset(rdp.cmd1) & 0x00FFFFFF; FRDP ("matrix addr: %08lx\n", addr); addr >>= 1; DWORD a = rdp.pc[rdp.pc_i] & BMASK; rdp.pc[rdp.pc_i] = (a+24) & BMASK; //skip next 3 command, b/c they all are part of gSPForceMatrix for (x=0; x<16; x+=4) { // Adding 4 instead of one, just to remove mult. later for (y=0; y<4; y++) { rdp.combined[x>>2][y] = (float)( (((__int32)((WORD*)gfx.RDRAM)[(addr+x+y)^1]) << 16) | ((WORD*)gfx.RDRAM)[(addr+x+y+16)^1] ) / 65536.0f; } } #ifdef EXTREME_LOGGING FRDP ("{%f,%f,%f,%f}\n", rdp.combined[0][0], rdp.combined[0][1], rdp.combined[0][2], rdp.combined[0][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.combined[1][0], rdp.combined[1][1], rdp.combined[1][2], rdp.combined[1][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.combined[2][0], rdp.combined[2][1], rdp.combined[2][2], rdp.combined[2][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.combined[3][0], rdp.combined[3][1], rdp.combined[3][2], rdp.combined[3][3]); #endif } break; //next 3 command should never appear since they will be skipped in previous command case 0x98: RDP_E ("uc0:movemem matrix 0 - ERROR!\n"); RDP ("matrix 0 - IGNORED\n"); break; case 0x9A: RDP_E ("uc0:movemem matrix 1 - ERROR!\n"); RDP ("matrix 1 - IGNORED\n"); break; case 0x9C: RDP_E ("uc0:movemem matrix 2 - ERROR!\n"); RDP ("matrix 2 - IGNORED\n"); break; default: FRDP_E ("uc0:movemem unknown (index: 0x%08lx)\n", (rdp.cmd0 >> 16) & 0xFF); FRDP ("unknown (index: 0x%08lx)\n", (rdp.cmd0 >> 16) & 0xFF); } } // // uc0:vertex - loads vertices // static void uc0_vertex() { DWORD addr = segoffset(rdp.cmd1) & 0x00FFFFFF; int v0, i, n; float x, y, z; rdp.v0 = v0 = (rdp.cmd0 >> 16) & 0xF; // Current vertex rdp.vn = n = ((rdp.cmd0 >> 20) & 0xF) + 1; // Number of vertices to copy FRDP("uc0:vertex: v0: %d, n: %d\n", v0, n); // This is special, not handled in update(), but here // * Matrix Pre-multiplication idea by Gonetz (Gonetz@ngs.ru) if (rdp.update & UPDATE_MULT_MAT) { rdp.update ^= UPDATE_MULT_MAT; MulMatrices(rdp.model, rdp.proj, rdp.combined); } // * // This is special, not handled in update() if (rdp.update & UPDATE_LIGHTS) { rdp.update ^= UPDATE_LIGHTS; // Calculate light vectors for (DWORD l=0; l>4)]; x = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 0)^1]; y = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 1)^1]; z = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 2)^1]; v->flags = ((WORD*)gfx.RDRAM)[(((addr+i) >> 1) + 3)^1]; v->ou = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 4)^1] * rdp.tiles[rdp.cur_tile].s_scale; v->ov = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 5)^1] * rdp.tiles[rdp.cur_tile].t_scale; v->a = ((BYTE*)gfx.RDRAM)[(addr+i + 15)^3]; v->x = x*rdp.combined[0][0] + y*rdp.combined[1][0] + z*rdp.combined[2][0] + rdp.combined[3][0]; v->y = x*rdp.combined[0][1] + y*rdp.combined[1][1] + z*rdp.combined[2][1] + rdp.combined[3][1]; v->z = x*rdp.combined[0][2] + y*rdp.combined[1][2] + z*rdp.combined[2][2] + rdp.combined[3][2]; v->w = x*rdp.combined[0][3] + y*rdp.combined[1][3] + z*rdp.combined[2][3] + rdp.combined[3][3]; #ifdef EXTREME_LOGGING FRDP ("v%d - x: %f, y: %f, z: %f, u: %f, v: %f\n", i>>4, v->x, v->y, v->z, v->ou, v->ov); #endif v->oow = 1.0f / v->w; v->x_w = v->x * v->oow; v->y_w = v->y * v->oow; v->z_w = v->z * v->oow; CalculateFog (v); v->uv_calculated = 0xFFFFFFFF; v->screen_translated = 0; v->shade_mods_allowed = 1; v->scr_off = 0; if (v->x < -v->w) v->scr_off |= 1; if (v->x > v->w) v->scr_off |= 2; if (v->y < -v->w) v->scr_off |= 4; if (v->y > v->w) v->scr_off |= 8; if (v->w < 0.1f) v->scr_off |= 16; if (rdp.geom_mode & 0x00020000) { v->vec[0] = ((char*)gfx.RDRAM)[(addr+i + 12)^3]; v->vec[1] = ((char*)gfx.RDRAM)[(addr+i + 13)^3]; v->vec[2] = ((char*)gfx.RDRAM)[(addr+i + 14)^3]; if (rdp.geom_mode & 0x80000) calc_linear (v); else if (rdp.geom_mode & 0x40000) calc_sphere (v); NormalizeVector (v->vec); calc_light (v); } else { v->r = ((BYTE*)gfx.RDRAM)[(addr+i + 12)^3]; v->g = ((BYTE*)gfx.RDRAM)[(addr+i + 13)^3]; v->b = ((BYTE*)gfx.RDRAM)[(addr+i + 14)^3]; } } } // // uc0:displaylist - makes a call to another section of code // static void uc0_displaylist() { DWORD addr = segoffset(rdp.cmd1) & 0x00FFFFFF; // This fixes partially Gauntlet: Legends if (addr == rdp.pc[rdp.pc_i] - 8) { RDP ("display list not executed!\n"); return; } DWORD push = (rdp.cmd0 >> 16) & 0xFF; // push the old location? FRDP("uc0:displaylist: %08lx, push:%s", addr, push?"no":"yes"); FRDP(" (seg %d, offset %08lx)\n", (rdp.cmd1>>24)&0x0F, rdp.cmd1&0x00FFFFFF); switch (push) { case 0: // push if (rdp.pc_i >= 9) { RDP_E ("** DL stack overflow **"); RDP ("** DL stack overflow **\n"); return; } rdp.pc_i ++; // go to the next PC in the stack rdp.pc[rdp.pc_i] = addr; // jump to the address break; case 1: // no push rdp.pc[rdp.pc_i] = addr; // just jump to the address break; default: RDP_E("Unknown displaylist operation\n"); RDP ("Unknown displaylist operation\n"); } } // // tri1 - renders a triangle // static void uc0_tri1() { FRDP("uc0:tri1 #%d - %d, %d, %d\n", rdp.tri_n, ((rdp.cmd1>>16) & 0xFF) / 10, ((rdp.cmd1>>8) & 0xFF) / 10, (rdp.cmd1 & 0xFF) / 10); VERTEX *v[3] = { &rdp.vtx[((rdp.cmd1 >> 16) & 0xFF) / 10], &rdp.vtx[((rdp.cmd1 >> 8) & 0xFF) / 10], &rdp.vtx[(rdp.cmd1 & 0xFF) / 10] }; if (cull_tri(v)) rdp.tri_n ++; else { update (); DrawTri (v); rdp.tri_n ++; } } static void uc0_culldl() { BYTE vStart = (BYTE)((rdp.cmd0 & 0x00FFFFFF) / 40) & 0xF; BYTE vEnd = (BYTE)(rdp.cmd1 / 40) & 0x0F; DWORD cond = 0; VERTEX *v; FRDP("uc0:culldl start: %d, end: %d\n", vStart, vEnd); if (vEnd < vStart) return; for (WORD i=vStart; i<=vEnd; i++) { v = &rdp.vtx[i]; // Check if completely off the screen (quick frustrum clipping for 90 FOV) if (v->x >= -v->w) cond |= 0x01; if (v->x <= v->w) cond |= 0x02; if (v->y >= -v->w) cond |= 0x04; if (v->y <= v->w) cond |= 0x08; if (v->w >= 0.1f) cond |= 0x10; if (cond == 0x1F) return; } RDP (" - "); // specify that the enddl is not a real command uc0_enddl (); } static void uc0_popmatrix() { RDP("uc0:popmatrix\n"); DWORD param = rdp.cmd1; switch (param) { case 0: // modelview modelview_pop (); break; case 1: // projection, can't break; default: FRDP_E ("Unknown uc0:popmatrix command: 0x%08lx\n", param); FRDP ("Unknown uc0:popmatrix command: 0x%08lx\n", param); } } void uc6_obj_sprite (); static void uc0_modifyvtx(BYTE where, WORD vtx, DWORD val) { VERTEX *v = &rdp.vtx[vtx]; switch (where) { case 0: uc6_obj_sprite (); break; case 0x10: // RGBA v->r = (BYTE)(val >> 24); v->g = (BYTE)((val >> 16) & 0xFF); v->b = (BYTE)((val >> 8) & 0xFF); v->a = (BYTE)(val & 0xFF); v->shade_mods_allowed = 1; FRDP ("RGBA: %d, %d, %d, %d\n", v->r, v->g, v->b, v->a); break; case 0x14: // ST v->ou = (float)((short)(val>>16)) / 32.0f; v->ov = (float)((short)(val&0xFFFF)) / 32.0f; v->uv_calculated = 0xFFFFFFFF; v->uv_fixed = 0; FRDP ("u/v: (%04lx, %04lx), (%f, %f)\n", (short)(val>>16), (short)(val&0xFFFF), v->ou, v->ov); break; case 0x18: // XY screen { float scr_x = (float)((short)(val>>16)) / 4.0f; float scr_y = (float)((short)(val&0xFFFF)) / 4.0f; v->screen_translated = 1; v->sx = scr_x * rdp.scale_x; v->sy = scr_y * rdp.scale_y; if (v->w < 0.01f) { v->w = 1.0f; v->oow = 1.0f; v->z_w = 1.0f; } v->sz = rdp.view_trans[2] + v->z_w * rdp.view_scale[2]; v->scr_off = 0; if (scr_x < 0) v->scr_off |= 1; if (scr_x > rdp.vi_width) v->scr_off |= 2; if (scr_y < 0) v->scr_off |= 4; if (scr_y > rdp.vi_height) v->scr_off |= 8; if (v->w < 0.1f) v->scr_off |= 16; FRDP ("x/y: (%f, %f)\n", scr_x, scr_y); } break; case 0x1C: // Z screen { float scr_z = (float)((short)(val>>16)); v->z_w = (scr_z - rdp.view_trans[2]) / rdp.view_scale[2]; v->z = v->z_w * v->w; FRDP ("z: %f\n", scr_z); } break; default: RDP("UNKNOWN\n"); break; } } // // uc0:moveword - moves a word to someplace, like the segment pointers // static void uc0_moveword() { RDP("uc0:moveword "); // Find which command this is (lowest byte of cmd0) switch (rdp.cmd0 & 0xFF) { case 0x00: RDP_E ("uc0:moveword matrix - IGNORED\n"); RDP ("matrix - IGNORED\n"); break; case 0x02: rdp.num_lights = ((rdp.cmd1 - 0x80000000) >> 5) - 1; // inverse of equation if (rdp.num_lights > 8) rdp.num_lights = 0; rdp.update |= UPDATE_LIGHTS; FRDP ("numlights: %d\n", rdp.num_lights); break; case 0x04: FRDP ("clip %08lx, %08lx\n", rdp.cmd0, rdp.cmd1); break; case 0x06: // segment FRDP ("segment: %08lx -> seg%d\n", rdp.cmd1, (rdp.cmd0 >> 10) & 0x0F); if ((rdp.cmd1&BMASK)> 10) & 0x0F] = rdp.cmd1; break; case 0x08: { rdp.fog_multiplier = (short)(rdp.cmd1 >> 16); rdp.fog_offset = (short)(rdp.cmd1 & 0x0000FFFF); FRDP ("fog: multiplier: %f, offset: %f\n", rdp.fog_multiplier, rdp.fog_offset); } break; case 0x0a: // moveword LIGHTCOL { int n = (rdp.cmd0&0xE000) >> 13; FRDP ("lightcol light:%d, %08lx\n", n, rdp.cmd1); rdp.light[n].r = (float)((rdp.cmd1 >> 24) & 0xFF) / 255.0f; rdp.light[n].g = (float)((rdp.cmd1 >> 16) & 0xFF) / 255.0f; rdp.light[n].b = (float)((rdp.cmd1 >> 8) & 0xFF) / 255.0f; rdp.light[n].a = 255; } break; case 0x0c: { WORD val = (WORD)((rdp.cmd0 >> 8) & 0xFFFF); WORD vtx = val / 40; BYTE where = val%40; uc0_modifyvtx(where, vtx, rdp.cmd1); FRDP ("uc0:modifyvtx: vtx: %d, where: 0x%02lx, val: %08lx - ", vtx, where, rdp.cmd1); } break; case 0x0e: RDP ("perspnorm - IGNORED\n"); break; default: FRDP_E ("uc0:moveword unknown (index: 0x%08lx)\n", rdp.cmd0 & 0xFF); FRDP ("unknown (index: 0x%08lx)\n", rdp.cmd0 & 0xFF); } } static void uc0_texture() { int tile = (rdp.cmd0 >> 8) & 0x07; rdp.mipmap_level = (rdp.cmd0 >> 11) & 0x07; DWORD on = (rdp.cmd0 & 0xFF); if (on) { rdp.cur_tile = tile; WORD s = (WORD)((rdp.cmd1 >> 16) & 0xFFFF); WORD t = (WORD)(rdp.cmd1 & 0xFFFF); TILE *tmp_tile = &rdp.tiles[tile]; tmp_tile->on = (BYTE)on; tmp_tile->org_s_scale = s; tmp_tile->org_t_scale = t; tmp_tile->s_scale = (float)(s+1)/65536.0f; tmp_tile->t_scale = (float)(t+1)/65536.0f; tmp_tile->s_scale /= 32.0f; tmp_tile->t_scale /= 32.0f; rdp.update |= UPDATE_TEXTURE; FRDP("uc0:texture: tile: %d, mipmap_lvl: %d, on: %d, s_scale: %f, t_scale: %f\n", tile, rdp.mipmap_level, on, tmp_tile->s_scale, tmp_tile->t_scale); } else { RDP("uc0:texture skipped b/c of off\n"); } } static void uc0_setothermode_h() { RDP ("uc0:setothermode_h: "); int shift, len; if ((settings.ucode == 2) || (settings.ucode == 8)) { len = (rdp.cmd0 & 0xFF) + 1; shift = 32 - ((rdp.cmd0 >> 8) & 0xFF) - len; } else { shift = (rdp.cmd0 >> 8) & 0xFF; len = rdp.cmd0 & 0xFF; } DWORD mask = 0; int i = len; for (; i; i--) mask = (mask << 1) | 1; mask <<= shift; rdp.cmd1 &= mask; rdp.othermode_h &= ~mask; rdp.othermode_h |= rdp.cmd1; if (mask & 0x00003000) // filter mode { rdp.filter_mode = (int)((rdp.othermode_h & 0x00003000) >> 12); rdp.update |= UPDATE_TEXTURE; FRDP ("filter mode: %s\n", str_filter[rdp.filter_mode]); } if (mask & 0x0000C000) // tlut mode { rdp.tlut_mode = (BYTE)((rdp.othermode_h & 0x0000C000) >> 14); FRDP ("tlut mode: %s\n", str_tlut[rdp.tlut_mode]); } if (mask & 0x00300000) // cycle type { rdp.cycle_mode = (BYTE)((rdp.othermode_h & 0x00300000) >> 20); FRDP ("cycletype: %d\n", rdp.cycle_mode); } if (mask & 0x00010000) // LOD enable { rdp.LOD_en = (rdp.othermode_h & 0x00010000) ? TRUE : FALSE; FRDP ("LOD_en: %d\n", rdp.LOD_en); } DWORD unk = mask & 0xFFCF0FFF; if (unk) // unknown portions, LARGE { FRDP ("UNKNOWN PORTIONS: shift: %d, len: %d, unknowns: %08lx\n", shift, len, unk); } } static void uc0_setothermode_l() { RDP("uc0:setothermode_l "); int shift, len; if ((settings.ucode == 2) || (settings.ucode == 8)) { len = (rdp.cmd0 & 0xFF) + 1; shift = 32 - ((rdp.cmd0 >> 8) & 0xFF) - len; } else { len = rdp.cmd0 & 0xFF; shift = (rdp.cmd0 >> 8) & 0xFF; } DWORD mask = 0; int i = len; for (; i; i--) mask = (mask << 1) | 1; mask <<= shift; rdp.cmd1 &= mask; rdp.othermode_l &= ~mask; rdp.othermode_l |= rdp.cmd1; if (mask & 0x00000003) // alpha compare { rdp.acmp = rdp.othermode_l & 0x00000003; FRDP ("alpha compare %s\n", ACmp[rdp.acmp]); rdp.update |= UPDATE_ALPHA_COMPARE; } if (mask & 0x00000004) // z-src selection { rdp.zsrc = (rdp.othermode_l & 0x00000004) >> 2; FRDP ("z-src sel: %s\n", str_zs[rdp.zsrc]); FRDP ("z-src sel: %08lx\n", rdp.zsrc); } if (mask & 0xFFFFFFF8) // rendermode / blender bits { rdp.update |= UPDATE_FOG_ENABLED; //if blender has no fog bits, fog must be set off rdp.render_mode_changed |= rdp.rm ^ rdp.othermode_l; rdp.rm = rdp.othermode_l; if (settings.flame_corona && (rdp.rm == 0x00504341)) //hack for flame's corona rdp.othermode_l |= /*0x00000020 |*/ 0x00000010; FRDP ("rendermode: %08lx\n", rdp.othermode_l); // just output whole othermode_l } // there is not one setothermode_l that's not handled :) } // // uc0:enddl - ends a call made by uc0:displaylist // static void uc0_enddl() { RDP("uc0:enddl\n"); if (rdp.pc_i == 0) { RDP ("RDP end\n"); // Halt execution here rdp.halt = 1; } rdp.pc_i --; } static void uc0_setgeometrymode() { FRDP("uc0:setgeometrymode %08lx\n", rdp.cmd1); rdp.geom_mode |= rdp.cmd1; if (rdp.cmd1 & 0x00000001) // Z-Buffer enable { if (!(rdp.flags & ZBUF_ENABLED)) { rdp.flags |= ZBUF_ENABLED; rdp.update |= UPDATE_ZBUF_ENABLED; } } if (rdp.cmd1 & 0x00001000) // Front culling { if (!(rdp.flags & CULL_FRONT)) { rdp.flags |= CULL_FRONT; rdp.update |= UPDATE_CULL_MODE; } } if (rdp.cmd1 & 0x00002000) // Back culling { if (!(rdp.flags & CULL_BACK)) { rdp.flags |= CULL_BACK; rdp.update |= UPDATE_CULL_MODE; } } //Added by Gonetz if (rdp.cmd1 & 0x00010000) // Fog enable { if (!(rdp.flags & FOG_ENABLED)) { rdp.flags |= FOG_ENABLED; rdp.update |= UPDATE_FOG_ENABLED; } } } static void uc0_cleargeometrymode() { FRDP("uc0:cleargeometrymode %08lx\n", rdp.cmd1); rdp.geom_mode &= (~rdp.cmd1); if (rdp.cmd1 & 0x00000001) // Z-Buffer enable { if (rdp.flags & ZBUF_ENABLED) { rdp.flags ^= ZBUF_ENABLED; rdp.update |= UPDATE_ZBUF_ENABLED; } } if (rdp.cmd1 & 0x00001000) // Front culling { if (rdp.flags & CULL_FRONT) { rdp.flags ^= CULL_FRONT; rdp.update |= UPDATE_CULL_MODE; } } if (rdp.cmd1 & 0x00002000) // Back culling { if (rdp.flags & CULL_BACK) { rdp.flags ^= CULL_BACK; rdp.update |= UPDATE_CULL_MODE; } } //Added by Gonetz if (rdp.cmd1 & 0x00010000) // Fog enable { if (rdp.flags & FOG_ENABLED) { rdp.flags ^= FOG_ENABLED; rdp.update |= UPDATE_FOG_ENABLED; } } } static void uc0_quad3d() { // Actually line3d, not supported I think int v0 = ((rdp.cmd1 >> 16) & 0xff) / 10; int v1 = ((rdp.cmd1 >> 8) & 0xff) / 10; int f = (rdp.cmd1 >> 24) & 0xff; FRDP("uc0:line3d v0:%d, v1:%d, f:%02lx - IGNORED\n", v0, v1, f); } static void uc0_rdphalf_1() { RDP_E("uc0:rdphalf_1 - IGNORED\n"); RDP ("uc0:rdphalf_1 - IGNORED\n"); } static void uc0_rdphalf_2() { RDP_E("uc0:rdphalf_2 - IGNORED\n"); RDP ("uc0:rdphalf_2 - IGNORED\n"); } static void uc0_rdphalf_cont() { RDP_E("uc0:rdphalf_cont - IGNORED\n"); RDP ("uc0:rdphalf_cont - IGNORED\n"); } static void uc0_tri4 () { // c0: 0000 0123, c1: 456789ab // becomes: 405 617 829 a3b RDP ("uc0:tri4"); FRDP(" #%d, #%d, #%d, #%d - %d, %d, %d - %d, %d, %d - %d, %d, %d - %d, %d, %d\n", rdp.tri_n, rdp.tri_n+1, rdp.tri_n+2, rdp.tri_n+3, (rdp.cmd1 >> 28) & 0xF, (rdp.cmd0 >> 12) & 0xF, (rdp.cmd1 >> 24) & 0xF, (rdp.cmd1 >> 20) & 0xF, (rdp.cmd0 >> 8) & 0xF, (rdp.cmd1 >> 16) & 0xF, (rdp.cmd1 >> 12) & 0xF, (rdp.cmd0 >> 4) & 0xF, (rdp.cmd1 >> 8) & 0xF, (rdp.cmd1 >> 4) & 0xF, (rdp.cmd0 >> 0) & 0xF, (rdp.cmd1 >> 0) & 0xF); VERTEX *v[12] = { &rdp.vtx[(rdp.cmd1 >> 28) & 0xF], &rdp.vtx[(rdp.cmd0 >> 12) & 0xF], &rdp.vtx[(rdp.cmd1 >> 24) & 0xF], &rdp.vtx[(rdp.cmd1 >> 20) & 0xF], &rdp.vtx[(rdp.cmd0 >> 8) & 0xF], &rdp.vtx[(rdp.cmd1 >> 16) & 0xF], &rdp.vtx[(rdp.cmd1 >> 12) & 0xF], &rdp.vtx[(rdp.cmd0 >> 4) & 0xF], &rdp.vtx[(rdp.cmd1 >> 8) & 0xF], &rdp.vtx[(rdp.cmd1 >> 4) & 0xF], &rdp.vtx[(rdp.cmd0 >> 0) & 0xF], &rdp.vtx[(rdp.cmd1 >> 0) & 0xF], }; BOOL updated = 0; if (cull_tri(v)) rdp.tri_n ++; else { updated = 1; update (); DrawTri (v); rdp.tri_n ++; } if (cull_tri(v+3)) rdp.tri_n ++; else { if (!updated) { updated = 1; update (); } DrawTri (v+3); rdp.tri_n ++; } if (cull_tri(v+6)) rdp.tri_n ++; else { if (!updated) { updated = 1; update (); } DrawTri (v+6); rdp.tri_n ++; } if (cull_tri(v+9)) rdp.tri_n ++; else { if (!updated) { updated = 1; update (); } DrawTri (v+9); rdp.tri_n ++; } } mupen64plus-video-glide64-src-2.6.0/src/UcodeFB.h000066400000000000000000002003401464507525600212720ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** // // Creation 13 August 2003 Gonetz // //**************************************************************** #ifndef _WIN32 #include #endif static void fb_uc0_moveword() { if ((rdp.cmd0 & 0xFF) == 0x06) // segment { rdp.segment[(rdp.cmd0 >> 10) & 0x0F] = rdp.cmd1; } } static void fb_uc2_moveword() { if (((rdp.cmd0 >> 16) & 0xFF) == 0x06) // segment { rdp.segment[((rdp.cmd0 & 0xFFFF) >> 2)&0xF] = rdp.cmd1; } } static void fb_bg_copy () { if (rdp.main_ci == 0) return; CI_STATUS status = rdp.frame_buffers[rdp.ci_count-1].status; if (status == ci_copy) return; DWORD addr = segoffset(rdp.cmd1) >> 1; BYTE imageFmt = ((BYTE *)gfx.RDRAM)[(((addr+11)<<1)+0)^3]; BYTE imageSiz = ((BYTE *)gfx.RDRAM)[(((addr+11)<<1)+1)^3]; DWORD imagePtr = segoffset(((DWORD*)gfx.RDRAM)[(addr+8)>>1]); FRDP ("fb_bg_copy. fmt: %d, size: %d, imagePtr %08lx, main_ci: %08lx, cur_ci: %08lx \n", imageFmt, imageSiz, imagePtr, rdp.main_ci, rdp.frame_buffers[rdp.ci_count-1].addr); if (status == ci_main) { WORD frameW = ((WORD *)gfx.RDRAM)[(addr+3)^1] >> 2; WORD frameH = ((WORD *)gfx.RDRAM)[(addr+7)^1] >> 2; if ( (frameW == rdp.frame_buffers[rdp.ci_count-1].width) && (frameH == rdp.frame_buffers[rdp.ci_count-1].height) ) rdp.main_ci_bg = imagePtr; } else if (imagePtr >= rdp.main_ci && imagePtr < rdp.main_ci_end) //addr within main frame buffer { rdp.copy_ci_index = rdp.ci_count-1; rdp.frame_buffers[rdp.copy_ci_index].status = ci_copy; FRDP("rdp.frame_buffers[%d].status = ci_copy\n", rdp.copy_ci_index); if (rdp.frame_buffers[rdp.copy_ci_index].addr != rdp.main_ci_bg) { rdp.scale_x = 1.0f; rdp.scale_y = 1.0f; } else { RDP("motion blur!\n"); rdp.motionblur = TRUE; } FRDP ("Detect FB usage. texture addr is inside framebuffer: %08lx - %08lx \n", imagePtr, rdp.main_ci); } else if (imagePtr == rdp.zimg) { printf("toto !\n"); if (status == ci_unknown) { rdp.frame_buffers[rdp.ci_count-1].status = ci_zimg; rdp.tmpzimg = rdp.frame_buffers[rdp.ci_count-1].addr; FRDP("rdp.frame_buffers[%d].status = ci_zimg\n", rdp.copy_ci_index); } } } static void fb_setscissor() { rdp.scissor_o.lr_y = (((rdp.cmd1 & 0x00000FFF) >> 2)); if (rdp.ci_count) { rdp.scissor_o.ul_x = (((rdp.cmd0 & 0x00FFF000) >> 14)); rdp.scissor_o.lr_x = (((rdp.cmd1 & 0x00FFF000) >> 14)); COLOR_IMAGE & cur_fb = rdp.frame_buffers[rdp.ci_count-1]; if (rdp.scissor_o.lr_x - rdp.scissor_o.ul_x > (cur_fb.width >> 1)) { if (cur_fb.height == 0 || (cur_fb.width >= rdp.scissor_o.lr_x-1 && cur_fb.width <= rdp.scissor_o.lr_x+1)) cur_fb.height = rdp.scissor_o.lr_y; } FRDP("fb_setscissor. lr_x = %d, lr_y = %d, fb_width = %d, fb_height = %d\n", rdp.scissor_o.lr_x, rdp.scissor_o.lr_y, cur_fb.width, cur_fb.height); } } static void fb_rect() { if (rdp.frame_buffers[rdp.ci_count-1].width == 32) return; int ul_x = ((rdp.cmd1 & 0x00FFF000) >> 14); int lr_x = ((rdp.cmd0 & 0x00FFF000) >> 14); int width = lr_x-ul_x; DWORD lr_y = ((rdp.cmd0 & 0x00000FFF) >> 2); int diff = abs((int)rdp.frame_buffers[rdp.ci_count-1].width - width); if (diff < 4) if (rdp.frame_buffers[rdp.ci_count-1].height < lr_y) { FRDP("fb_rect. ul_x: %d, lr_x: %d, fb_height: %d -> %d\n", ul_x, lr_x, rdp.frame_buffers[rdp.ci_count-1].height, lr_y); rdp.frame_buffers[rdp.ci_count-1].height = lr_y; } } static void fb_settextureimage() { if (rdp.main_ci == 0) return; COLOR_IMAGE & cur_fb = rdp.frame_buffers[rdp.ci_count-1]; if ( cur_fb.status >= ci_copy ) return; if (((rdp.cmd0 >> 19) & 0x03) >= 2) //check that texture is 16/32bit { int tex_format = ((rdp.cmd0 >> 21) & 0x07); DWORD addr = segoffset(rdp.cmd1); if ( tex_format == 0 ) { FRDP ("fb_settextureimage. fmt: %d, size: %d, imagePtr %08lx, main_ci: %08lx, cur_ci: %08lx \n", ((rdp.cmd0 >> 21) & 0x07), ((rdp.cmd0 >> 19) & 0x03), addr, rdp.main_ci, rdp.frame_buffers[rdp.ci_count-1].addr); if (cur_fb.status == ci_main) { rdp.main_ci_last_tex_addr = addr; if (cur_fb.height == 0) { cur_fb.height = rdp.scissor_o.lr_y; rdp.main_ci_end = cur_fb.addr + ((cur_fb.width * cur_fb.height) << cur_fb.size >> 1); } } if ((addr >= rdp.main_ci) && (addr < rdp.main_ci_end)) //addr within main frame buffer { if (cur_fb.status == ci_main) { rdp.copy_ci_index = rdp.ci_count-1; cur_fb.status = ci_copy_self; rdp.scale_x = rdp.scale_x_bak; rdp.scale_y = rdp.scale_y_bak; FRDP("rdp.frame_buffers[%d].status = ci_copy_self\n", rdp.ci_count-1); } else { if (cur_fb.width == rdp.frame_buffers[rdp.main_ci_index].width) { rdp.copy_ci_index = rdp.ci_count-1; cur_fb.status = ci_copy; FRDP("rdp.frame_buffers[%d].status = ci_copy\n", rdp.copy_ci_index); if ((rdp.main_ci_last_tex_addr >= cur_fb.addr) && (rdp.main_ci_last_tex_addr < (cur_fb.addr + cur_fb.width*cur_fb.height*cur_fb.size))) { RDP("motion blur!\n"); rdp.motionblur = TRUE; } else { rdp.scale_x = 1.0f; rdp.scale_y = 1.0f; } } else if (!settings.fb_ignore_aux_copy && cur_fb.width < rdp.frame_buffers[rdp.main_ci_index].width) { rdp.copy_ci_index = rdp.ci_count-1; cur_fb.status = ci_aux_copy; FRDP("rdp.frame_buffers[%d].status = ci_aux_copy\n", rdp.copy_ci_index); rdp.scale_x = 1.0f; rdp.scale_y = 1.0f; } else { cur_fb.status = ci_aux; FRDP("rdp.frame_buffers[%d].status = ci_aux\n", rdp.copy_ci_index); } } FRDP ("Detect FB usage. texture addr is inside framebuffer: %08lx - %08lx \n", addr, rdp.main_ci); } ///* else if ((cur_fb.status != ci_main) && (addr >= rdp.zimg && addr < rdp.zimg_end)) { cur_fb.status = ci_zcopy; FRDP("fb_settextureimage. rdp.frame_buffers[%d].status = ci_zcopy\n", rdp.ci_count-1); } //*/ else if ((addr >= rdp.maincimg[0].addr) && (addr < (rdp.maincimg[0].addr + rdp.maincimg[0].width*rdp.maincimg[0].height*2))) { if (cur_fb.status != ci_main) { cur_fb.status = ci_old_copy; FRDP("rdp.frame_buffers[%d].status = ci_old_copy 1, addr:%08lx\n", rdp.ci_count-1, rdp.last_drawn_ci_addr); } rdp.read_previous_ci = TRUE; RDP("read_previous_ci = TRUE\n"); } else if ((addr >= rdp.last_drawn_ci_addr) && (addr < (rdp.last_drawn_ci_addr + rdp.maincimg[0].width*rdp.maincimg[0].height*2))) { if (cur_fb.status != ci_main) { cur_fb.status = ci_old_copy; FRDP("rdp.frame_buffers[%d].status = ci_old_copy 2, addr:%08lx\n", rdp.ci_count-1, rdp.last_drawn_ci_addr); } rdp.read_previous_ci = TRUE; RDP("read_previous_ci = TRUE\n"); } } else if (settings.fb_hires && (cur_fb.status == ci_main)) { if ((addr >= rdp.main_ci) && (addr < rdp.main_ci_end)) //addr within main frame buffer { rdp.copy_ci_index = rdp.ci_count-1; rdp.black_ci_index = rdp.ci_count-1; cur_fb.status = ci_copy_self; FRDP("rdp.frame_buffers[%d].status = ci_copy_self\n", rdp.ci_count-1); } } } if (cur_fb.status == ci_unknown) { cur_fb.status = ci_aux; FRDP("fb_settextureimage. rdp.frame_buffers[%d].status = ci_aux\n", rdp.ci_count-1); } } static void fb_loadtxtr() { if (rdp.frame_buffers[rdp.ci_count-1].status == ci_unknown) { rdp.frame_buffers[rdp.ci_count-1].status = ci_aux; FRDP("rdp.frame_buffers[%d].status = ci_aux\n", rdp.ci_count-1); } } static void fb_setdepthimage() { rdp.zimg = segoffset(rdp.cmd1) & BMASK; rdp.zimg_end = rdp.zimg + rdp.ci_width*rdp.ci_height*2; FRDP ("fb_setdepthimage. addr %08lx - %08lx\n", rdp.zimg, rdp.zimg_end); if (rdp.zimg == rdp.main_ci) //strange, but can happen { rdp.frame_buffers[rdp.main_ci_index].status = ci_unknown; if (rdp.main_ci_index < rdp.ci_count) { rdp.frame_buffers[rdp.main_ci_index].status = ci_zimg; FRDP("rdp.frame_buffers[%d].status = ci_zimg\n", rdp.main_ci_index); rdp.main_ci_index++; rdp.frame_buffers[rdp.main_ci_index].status = ci_main; FRDP("rdp.frame_buffers[%d].status = ci_main\n", rdp.main_ci_index); rdp.main_ci = rdp.frame_buffers[rdp.main_ci_index].addr; rdp.main_ci_end = rdp.main_ci + (rdp.frame_buffers[rdp.main_ci_index].width * rdp.frame_buffers[rdp.main_ci_index].height * rdp.frame_buffers[rdp.main_ci_index].size); } else { rdp.main_ci = 0; } } for (int i = 0; i < rdp.ci_count; i++) { COLOR_IMAGE & fb = rdp.frame_buffers[i]; if ((fb.addr == rdp.zimg) && (fb.status == ci_aux || fb.status == ci_useless)) { fb.status = ci_zimg; FRDP("rdp.frame_buffers[%d].status = ci_zimg\n", i); } } } static void fb_setcolorimage() { rdp.ocimg = rdp.cimg; rdp.cimg = segoffset(rdp.cmd1) & BMASK; COLOR_IMAGE & cur_fb = rdp.frame_buffers[rdp.ci_count]; cur_fb.width = (rdp.cmd0 & 0xFFF) + 1; if (cur_fb.width == 32 ) cur_fb.height = 32; else if (cur_fb.width == 16 ) cur_fb.height = 16; else if (rdp.ci_count > 0) cur_fb.height = rdp.scissor_o.lr_y; else cur_fb.height = 0; cur_fb.format = (rdp.cmd0 >> 21) & 0x7; cur_fb.size = (rdp.cmd0 >> 19) & 0x3; cur_fb.addr = rdp.cimg; cur_fb.changed = 1; /* if (rdp.ci_count > 0) if (rdp.frame_buffers[0].addr == rdp.cimg) rdp.frame_buffers[0].height = rdp.scissor_o.lr_y; */ FRDP ("fb_setcolorimage. width: %d, height: %d, fmt: %d, size: %d, addr %08lx\n", cur_fb.width, cur_fb.height, cur_fb.format, cur_fb.size, cur_fb.addr); if ((rdp.cimg == rdp.zimg) || (rdp.cimg == rdp.tmpzimg)) { cur_fb.status = ci_zimg; if (rdp.zimg_end == rdp.zimg) rdp.zimg_end = rdp.zimg + cur_fb.width*rdp.scissor_o.lr_y*2; FRDP("rdp.frame_buffers[%d].status = ci_zimg\n", rdp.ci_count); } else if (rdp.main_ci != 0) { if (rdp.cimg == rdp.main_ci) //switched to main fb again { cur_fb.height = std::max(cur_fb.height, rdp.frame_buffers[rdp.main_ci_index].height); rdp.main_ci_index = rdp.ci_count; rdp.main_ci_end = rdp.cimg + ((cur_fb.width * cur_fb.height) << cur_fb.size >> 1); cur_fb.status = ci_main; FRDP("rdp.frame_buffers[%d].status = ci_main\n", rdp.ci_count); } else // status is not known yet { cur_fb.status = ci_unknown; } } else { if ((rdp.zimg != rdp.cimg))//&& (rdp.ocimg != rdp.cimg)) { rdp.main_ci = rdp.cimg; rdp.main_ci_end = rdp.cimg + ((cur_fb.width * cur_fb.height) << cur_fb.size >> 1); rdp.main_ci_index = rdp.ci_count; cur_fb.status = ci_main; FRDP("rdp.frame_buffers[%d].status = ci_main\n", rdp.ci_count); } else { cur_fb.status = ci_unknown; } } if (rdp.frame_buffers[rdp.ci_count-1].status == ci_unknown) //status of previous fb was not changed - it is useless { if (settings.fb_hires && !settings.PM) { rdp.frame_buffers[rdp.ci_count-1].status = ci_aux; rdp.frame_buffers[rdp.ci_count-1].changed = 0; FRDP("rdp.frame_buffers[%d].status = ci_aux\n", rdp.ci_count-1); } else { rdp.frame_buffers[rdp.ci_count-1].status = ci_useless; /* DWORD addr = rdp.frame_buffers[rdp.ci_count-1].addr; for (int i = 0; i < rdp.ci_count - 1; i++) { if (rdp.frame_buffers[i].addr == addr) { rdp.frame_buffers[rdp.ci_count-1].status = rdp.frame_buffers[i].status; break; } } //*/ FRDP("rdp.frame_buffers[%d].status = %s\n", rdp.ci_count-1, CIStatus[rdp.frame_buffers[rdp.ci_count-1].status]); } } if (cur_fb.status == ci_main) { BOOL viSwapOK = ((settings.swapmode == 2) && (rdp.vi_org_reg == *gfx.VI_ORIGIN_REG)) ? FALSE : TRUE; if ((rdp.maincimg[0].addr != cur_fb.addr) && SwapOK && viSwapOK) { SwapOK = FALSE; rdp.swap_ci_index = rdp.ci_count; } } rdp.ci_count++; if (rdp.ci_count > NUMTEXBUF) //overflow rdp.halt = 1; } // RDP graphic instructions pointer table used in DetectFrameBufferUsage static rdp_instr gfx_instruction_lite[9][256] = { { // uCode 0 - RSP SW 2.0X // 00-3f // games: Super Mario 64, Tetrisphere, Demos 0, 0, 0, 0, 0, 0, uc0_displaylist, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40-7f: Unused 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80-bf: Immediate commands 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, uc0_enddl, 0, 0, 0, fb_uc0_moveword, 0, uc0_culldl, 0, // c0-ff: RDP commands 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, fb_rect, fb_rect, 0, 0, 0, 0, 0, 0, 0, fb_setscissor, 0, 0, 0, 0, 0, 0, 0, 0, fb_rect, 0, 0, 0, 0, 0, 0, fb_settextureimage, fb_setdepthimage, fb_setcolorimage }, // uCode 1 - F3DEX 1.XX // 00-3f // games: Mario Kart, Star Fox { 0, 0, 0, 0, 0, 0, uc0_displaylist, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40-7f: unused 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80-bf: Immediate commands 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, uc6_loaducode, uc1_branch_z, 0, 0, 0, uc1_rdphalf_1, 0, 0, 0, uc0_enddl, 0, 0, 0, fb_uc0_moveword, 0, uc2_culldl, 0, // c0-ff: RDP commands 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, fb_rect, fb_rect, 0, 0, 0, 0, 0, 0, 0, fb_setscissor, 0, 0, 0, 0, 0, 0, 0, 0, fb_rect, 0, 0, 0, 0, 0, 0, fb_settextureimage, fb_setdepthimage, fb_setcolorimage }, // uCode 2 - F3DEX 2.XX // games: Zelda 64 { // 00-3f 0, 0, 0, uc2_culldl, uc1_branch_z, 0, 0, 0, 0, fb_bg_copy, fb_bg_copy, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40-7f: unused 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80-bf: unused 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // c0-ff: RDP commands mixed with uc2 commands 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, uc2_dlist_cnt, 0, 0, 0, 0, 0, fb_uc2_moveword, 0/*fb_uc2_movemem*/, uc2_load_ucode, uc0_displaylist, uc0_enddl, 0, uc1_rdphalf_1, 0, 0, fb_rect, fb_rect, 0, 0, 0, 0, 0, 0, 0, fb_setscissor, 0, 0, 0, 0, 0, 0, 0, 0, fb_rect, 0, 0, 0, 0, 0, 0, fb_settextureimage, fb_setdepthimage, fb_setcolorimage }, // uCode 3 - "RSP SW 2.0D", but not really // 00-3f // games: Wave Race // ** Added by Gonetz ** { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40-7f: unused 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80-bf: Immediate commands 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, uc0_enddl, 0, 0, 0, fb_uc0_moveword, 0, uc0_culldl, 0, // c0-ff: RDP commands 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, fb_rect, fb_rect, 0, 0, 0, 0, 0, 0, 0, fb_setscissor, 0, 0, 0, 0, 0, 0, 0, 0, fb_rect, 0, 0, 0, 0, 0, 0, fb_settextureimage, fb_setdepthimage, fb_setcolorimage }, { // uCode 4 - RSP SW 2.0D EXT // 00-3f // games: Star Wars: Shadows of the Empire 0, 0, 0, 0, 0, 0, uc0_displaylist, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40-7f: Unused 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80-bf: Immediate commands 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, uc0_enddl, 0, 0, 0, fb_uc0_moveword, 0, uc0_culldl, 0, // c0-ff: RDP commands rdp_noop, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, fb_rect, fb_rect, 0, 0, 0, 0, 0, 0, 0, fb_setscissor, 0, 0, 0, 0, 0, 0, 0, 0, fb_rect, 0, 0, 0, 0, 0, 0, fb_settextureimage, fb_setdepthimage, fb_setcolorimage }, { // uCode 5 - RSP SW 2.0 Diddy // 00-3f // games: Diddy Kong Racing 0, 0, 0, 0, 0, 0, uc0_displaylist, uc5_dl_in_mem, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40-7f: Unused 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80-bf: Immediate commands 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, uc0_enddl, 0, 0, 0, fb_uc0_moveword, 0, uc0_culldl, 0, // c0-ff: RDP commands 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, fb_rect, fb_rect, 0, 0, 0, 0, 0, 0, 0, fb_setscissor, 0, 0, 0, 0, 0, 0, 0, 0, fb_rect, 0, 0, 0, 0, 0, 0, fb_settextureimage, fb_setdepthimage, fb_setcolorimage }, // uCode 6 - S2DEX 1.XX // games: Yoshi's Story { 0, 0, 0, 0, 0, 0, uc0_displaylist, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40-7f: unused 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80-bf: Immediate commands 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, uc6_loaducode, uc6_select_dl, 0, 0, 0, 0, 0, 0, 0, uc0_enddl, 0, 0, 0, fb_uc0_moveword, 0, uc2_culldl, 0, // c0-ff: RDP commands 0, fb_loadtxtr, fb_loadtxtr, fb_loadtxtr, fb_loadtxtr, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, fb_rect, fb_rect, 0, 0, 0, 0, 0, 0, 0, fb_setscissor, 0, 0, 0, 0, 0, 0, 0, 0, fb_rect, 0, 0, 0, 0, 0, 0, fb_settextureimage, fb_setdepthimage, fb_setcolorimage }, { 0, 0, 0, 0, 0, 0, uc0_displaylist, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40-7f: unused 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80-bf: Immediate commands 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, uc0_enddl, 0, 0, 0, fb_uc0_moveword, 0, uc0_culldl, 0, // c0-ff: RDP commands 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, fb_rect, fb_rect, 0, 0, 0, 0, 0, 0, 0, fb_setscissor, 0, 0, 0, 0, 0, 0, 0, 0, fb_rect, 0, 0, 0, 0, 0, 0, fb_settextureimage, fb_setdepthimage, fb_setcolorimage }, { // 00-3f 0, 0, 0, uc2_culldl, uc1_branch_z, 0, 0, 0, 0, fb_bg_copy, fb_bg_copy, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40-7f: unused 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80-bf: unused 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // c0-ff: RDP commands mixed with uc2 commands 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, uc2_dlist_cnt, 0, 0, 0, 0, 0, fb_uc2_moveword, 0, uc2_load_ucode, uc0_displaylist, uc0_enddl, 0, uc1_rdphalf_1, 0, 0, fb_rect, fb_rect, 0, 0, 0, 0, 0, 0, 0, fb_setscissor, 0, 0, 0, 0, 0, 0, 0, 0, fb_rect, 0, 0, 0, 0, 0, 0, fb_settextureimage, fb_setdepthimage, fb_setcolorimage } }; mupen64plus-video-glide64-src-2.6.0/src/Util.cpp000066400000000000000000002157051464507525600213060ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** #define M64P_PLUGIN_PROTOTYPES 1 #include "m64p_types.h" #include "m64p_plugin.h" #include "m64p_config.h" #include "m64p_vidext.h" #include "Util.h" #include "Combine.h" #include "3dmath.h" #include "Debugger.h" #include "TexCache.h" #include "DepthBufferRender.h" #ifndef _WIN32 #include #include #endif // _WIN32 #define Vj rdp.vtxbuf2[j] #define Vi rdp.vtxbuf2[i] VERTEX *vtx_list1[32]; // vertex indexing VERTEX *vtx_list2[32]; // // util_init - initialize data for the functions in this file // void util_init () { for (int i=0; i<32; i++) { vtx_list1[i] = &rdp.vtx1[i]; vtx_list2[i] = &rdp.vtx2[i]; } } //software backface culling. Gonetz // mega modifications by Dave2001 BOOL cull_tri(VERTEX **v) // type changed to VERTEX** [Dave2001] { int i; if (v[0]->scr_off & v[1]->scr_off & v[2]->scr_off) { RDP (" clipped\n"); return TRUE; } // Triangle can't be culled, if it need clipping BOOL draw = FALSE; //fix for sun in zeldas BOOL fix_i_uv = FALSE; if (settings.zelda && rdp.rm == 0x0c184241 && rdp.tiles[rdp.cur_tile].format == 4) fix_i_uv = TRUE; for (i=0; i<3; i++) { if (!v[i]->screen_translated) { v[i]->sx = rdp.view_trans[0] + v[i]->x_w * rdp.view_scale[0]; v[i]->sy = rdp.view_trans[1] + v[i]->y_w * rdp.view_scale[1]; v[i]->sz = rdp.view_trans[2] + v[i]->z_w * rdp.view_scale[2]; if ((fix_i_uv) && (v[i]->uv_fixed == 0)) { v[i]->uv_fixed = 1; v[i]->ou *= 0.5f; v[i]->ov *= 0.5f; } v[i]->screen_translated = 1; } if (v[i]->w < 0.01f) //need clip_z. can't be culled now draw = 1; } if (settings.fix_tex_coord) fix_tex_coord (v); if (draw) return FALSE; // z-clipping, can't be culled by software #define SW_CULLING #ifdef SW_CULLING //now we need to check, if triangle's vertices are in clockwise order // Use precalculated x/z and y/z coordinates. float x1 = v[0]->sx - v[1]->sx; float y1 = v[0]->sy - v[1]->sy; float x2 = v[2]->sx - v[1]->sx; float y2 = v[2]->sy - v[1]->sy; DWORD mode = (rdp.flags & CULLMASK) >> CULLSHIFT; switch (mode) { case 1: // cull front // if ((x1*y2 - y1*x2) < 0.0f) //counter-clockwise, positive if ((y1*x2-x1*y2) < 0.0f) //counter-clockwise, positive { RDP (" culled!\n"); return TRUE; } return FALSE; case 2: // cull back // if ((x1*y2 - y1*x2) >= 0.0f) //clockwise, negative if ((y1*x2-x1*y2) >= 0.0f) //clockwise, negative { RDP (" culled!\n"); return TRUE; } return FALSE; } #endif return FALSE; } void apply_shade_mods (VERTEX *v) { float col[4]; DWORD cmb; memcpy (col, rdp.col, 16); if (rdp.cmb_flags) { cmb = rdp.cmb_flags; if (cmb & CMB_SET) { if (col[0] > 1.0f) col[0] = 1.0f; if (col[1] > 1.0f) col[1] = 1.0f; if (col[2] > 1.0f) col[2] = 1.0f; if (col[0] < 0.0f) col[0] = 0.0f; if (col[1] < 0.0f) col[1] = 0.0f; if (col[2] < 0.0f) col[2] = 0.0f; v->r = (BYTE)(255.0f * col[0]); v->g = (BYTE)(255.0f * col[1]); v->b = (BYTE)(255.0f * col[2]); } if (cmb & CMB_A_SET) { if (col[3] > 1.0f) col[3] = 1.0f; if (col[3] < 0.0f) col[3] = 0.0f; v->a = (BYTE)(255.0f * col[3]); } if (cmb & CMB_SETSHADE_SHADEALPHA) { v->r = v->g = v->b = v->a; } if (cmb & CMB_SUB) { int r = v->r - (int)(255.0f * rdp.coladd[0]); int g = v->g - (int)(255.0f * rdp.coladd[1]); int b = v->b - (int)(255.0f * rdp.coladd[2]); if (r < 0) r = 0; if (g < 0) g = 0; if (b < 0) b = 0; v->r = (BYTE)r; v->g = (BYTE)g; v->b = (BYTE)b; } if (cmb & CMB_A_SUB) { int a = v->a - (int)(255.0f * rdp.coladd[3]); if (a < 0) a = 0; v->a = (BYTE)a; } if (cmb & CMB_ADD) { int r = v->r + (int)(255.0f * rdp.coladd[0]); int g = v->g + (int)(255.0f * rdp.coladd[1]); int b = v->b + (int)(255.0f * rdp.coladd[2]); if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255; v->r = (BYTE)r; v->g = (BYTE)g; v->b = (BYTE)b; } if (cmb & CMB_A_ADD) { int a = v->a + (int)(255.0f * rdp.coladd[3]); if (a > 255) a = 255; v->a = (BYTE)a; } if (cmb & CMB_COL_SUB_OWN) { int r = (BYTE)(255.0f * rdp.coladd[0]) - v->r; int g = (BYTE)(255.0f * rdp.coladd[1]) - v->g; int b = (BYTE)(255.0f * rdp.coladd[2]) - v->b; if (r < 0) r = 0; if (g < 0) g = 0; if (b < 0) b = 0; v->r = (BYTE)r; v->g = (BYTE)g; v->b = (BYTE)b; } if (cmb & CMB_MULT) { if (col[0] > 1.0f) col[0] = 1.0f; if (col[1] > 1.0f) col[1] = 1.0f; if (col[2] > 1.0f) col[2] = 1.0f; if (col[0] < 0.0f) col[0] = 0.0f; if (col[1] < 0.0f) col[1] = 0.0f; if (col[2] < 0.0f) col[2] = 0.0f; v->r = (BYTE)(v->r * col[0]); v->g = (BYTE)(v->g * col[1]); v->b = (BYTE)(v->b * col[2]); } if (cmb & CMB_A_MULT) { if (col[3] > 1.0f) col[3] = 1.0f; if (col[3] < 0.0f) col[3] = 0.0f; v->a = (BYTE)(v->a * col[3]); } if (cmb & CMB_MULT_OWN_ALPHA) { float percent = v->a / 255.0f; v->r = (BYTE)(v->r * percent); v->g = (BYTE)(v->g * percent); v->b = (BYTE)(v->b * percent); } v->shade_mods_allowed = 0; } cmb = rdp.cmb_flags_2; if (cmb & CMB_INTER) { v->r = (BYTE)(rdp.col_2[0] * rdp.shade_factor * 255.0f + v->r * (1.0f - rdp.shade_factor)); v->g = (BYTE)(rdp.col_2[1] * rdp.shade_factor * 255.0f + v->g * (1.0f - rdp.shade_factor)); v->b = (BYTE)(rdp.col_2[2] * rdp.shade_factor * 255.0f + v->b * (1.0f - rdp.shade_factor)); v->shade_mods_allowed = 0; } } static long dzdx = 0; void DrawTri (VERTEX **vtx, WORD linew) { if (settings.fb_depth_render && linew == 0) { float X0 = vtx[0]->sx / rdp.scale_x; float Y0 = vtx[0]->sy / rdp.scale_y; float X1 = vtx[1]->sx / rdp.scale_x; float Y1 = vtx[1]->sy / rdp.scale_y; float X2 = vtx[2]->sx / rdp.scale_x; float Y2 = vtx[2]->sy / rdp.scale_y; float diff12 = Y1 - Y2; float diff02 = Y0 - Y2; double denom = ((X0 - X2) * diff12 - (X1 - X2) * diff02); if(denom*denom > 0.0) { dzdx = (long)(((vtx[0]->sz - vtx[2]->sz) * diff12 - (vtx[1]->sz - vtx[2]->sz) * diff02) / denom * 65536.0); } else dzdx = 0; } else dzdx = 0; for (int i=0; i<3; i++) { VERTEX *v = vtx[i]; if (v->uv_calculated != rdp.tex_ctr) { #ifdef EXTREME_LOGGING FRDP(" * CALCULATING VERTEX U/V: %d\n", v->number); #endif v->uv_calculated = rdp.tex_ctr; if (!(rdp.geom_mode & 0x00020000)) { if (!(rdp.geom_mode & 0x00000200)) { if (rdp.geom_mode & 0x00000004) // flat shading { #ifdef EXTREME_LOGGING RDP(" * Flat shaded\n"); #endif v->a = vtx[0]->a; v->b = vtx[0]->b; v->g = vtx[0]->g; v->r = vtx[0]->r; } else // prim color { #ifdef EXTREME_LOGGING FRDP(" * Prim shaded %08lx\n", rdp.prim_color); #endif v->a = (BYTE)(rdp.prim_color & 0xFF); v->b = (BYTE)((rdp.prim_color >> 8) & 0xFF); v->g = (BYTE)((rdp.prim_color >> 16) & 0xFF); v->r = (BYTE)((rdp.prim_color >> 24) & 0xFF); } } } // Fix texture coordinates v->u1 = v->u0 = v->ou; v->v1 = v->v0 = v->ov; if (rdp.tex >= 1 && rdp.cur_cache[0]) { if (rdp.hires_tex && rdp.hires_tex->tile == 0) { v->u0 += rdp.hires_tex->u_shift + rdp.hires_tex->tile_uls; v->v0 += rdp.hires_tex->v_shift + rdp.hires_tex->tile_ult; } if (rdp.tiles[rdp.cur_tile].shift_s) { if (rdp.tiles[rdp.cur_tile].shift_s > 10) v->u0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_s)); else v->u0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_s); } if (rdp.tiles[rdp.cur_tile].shift_t) { if (rdp.tiles[rdp.cur_tile].shift_t > 10) v->v0 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_t)); else v->v0 /= (float)(1 << rdp.tiles[rdp.cur_tile].shift_t); } if (rdp.hires_tex && rdp.hires_tex->tile == 0) { if (rdp.hires_tex->tile_uls != (int)rdp.tiles[rdp.cur_tile].f_ul_s) v->u0 -= rdp.tiles[rdp.cur_tile].f_ul_s; v->u0 *= rdp.hires_tex->u_scale; v->v0 *= rdp.hires_tex->u_scale; v->u0 -= 0.45f; v->v0 -= 0.45f; FRDP("hires_tex t0: (%f, %f)->(%f, %f)\n", v->ou, v->ov, v->u0, v->v0); } else { v->u0 -= rdp.tiles[rdp.cur_tile].f_ul_s; v->v0 -= rdp.tiles[rdp.cur_tile].f_ul_t; v->u0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_x * v->u0; v->v0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_y * v->v0; } v->u0_w = v->u0 / v->w; v->v0_w = v->v0 / v->w; } if (rdp.tex >= 2 && rdp.cur_cache[1]) { if (rdp.hires_tex && rdp.hires_tex->tile == 1) { v->u1 += rdp.hires_tex->u_shift + rdp.hires_tex->tile_uls; v->v1 += rdp.hires_tex->v_shift + rdp.hires_tex->tile_ult; } if (rdp.tiles[rdp.cur_tile+1].shift_s) { if (rdp.tiles[rdp.cur_tile+1].shift_s > 10) v->u1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_s)); else v->u1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_s); } if (rdp.tiles[rdp.cur_tile+1].shift_t) { if (rdp.tiles[rdp.cur_tile+1].shift_t > 10) v->v1 *= (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_t)); else v->v1 /= (float)(1 << rdp.tiles[rdp.cur_tile+1].shift_t); } if (rdp.hires_tex && rdp.hires_tex->tile == 1) { if (rdp.hires_tex->tile_uls != (int)rdp.tiles[rdp.cur_tile].f_ul_s) v->u1 -= rdp.tiles[rdp.cur_tile].f_ul_s; v->u1 *= rdp.hires_tex->u_scale; v->v1 *= rdp.hires_tex->u_scale; v->u1 -= 0.45f; v->v1 -= 0.45f; FRDP("hires_tex t1: (%f, %f)->(%f, %f)\n", v->ou, v->ov, v->u0, v->v0); } else { v->u1 -= rdp.tiles[rdp.cur_tile+1].f_ul_s; v->v1 -= rdp.tiles[rdp.cur_tile+1].f_ul_t; v->u1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_x * v->u1; v->v1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_y * v->v1; } v->u1_w = v->u1 / v->w; v->v1_w = v->v1 / v->w; } // FRDP(" * CALCULATING VERTEX U/V: %d u0: %f, v0: %f, u1: %f, v1: %f\n", v->number, v->u0, v->v0, v->u1, v->v1); } if (v->shade_mods_allowed) apply_shade_mods (v); } //for rdp.clip = 0; if ((vtx[0]->scr_off & 16) || (vtx[1]->scr_off & 16) || (vtx[2]->scr_off & 16)) rdp.clip |= CLIP_ZMIN; vtx[0]->not_zclipped = vtx[1]->not_zclipped = vtx[2]->not_zclipped = 1; if (rdp.cur_cache[0] && (rdp.tex & 1) && (rdp.cur_cache[0]->splits > 1) && !rdp.hires_tex && !rdp.clip) { int index,i,j, min_256,max_256, cur_256,left_256,right_256; float percent; min_256 = std::min((int)vtx[0]->u0,(int)vtx[1]->u0); // bah, don't put two mins on one line min_256 = std::min(min_256,(int)vtx[2]->u0) >> 8; // or it will be calculated twice max_256 = std::max((int)vtx[0]->u0,(int)vtx[1]->u0); // not like it makes much difference max_256 = std::max(max_256,(int)vtx[2]->u0) >> 8; // anyway :P for (cur_256=min_256; cur_256<=max_256; cur_256++) { left_256 = cur_256 << 8; right_256 = (cur_256+1) << 8; // Set vertex buffers rdp.vtxbuf = rdp.vtx1; // copy from v to rdp.vtx1 rdp.vtxbuf2 = rdp.vtx2; rdp.vtx_buffer = 0; rdp.n_global = 3; index = 0; // ** Left plane ** for (i=0; i<3; i++) { j = i+1; if (j == 3) j = 0; VERTEX *v1 = vtx[i]; VERTEX *v2 = vtx[j]; if (v1->u0 >= left_256) { if (v2->u0 >= left_256) // Both are in, save the last one { rdp.vtxbuf[index] = *v2; rdp.vtxbuf[index].u0 -= left_256; rdp.vtxbuf[index++].v0 += rdp.cur_cache[0]->c_scl_y * (cur_256 * rdp.cur_cache[0]->splitheight); } else // First is in, second is out, save intersection { percent = (left_256 - v1->u0) / (v2->u0 - v1->u0); rdp.vtxbuf[index].x = v1->x + (v2->x - v1->x) * percent; rdp.vtxbuf[index].y = v1->y + (v2->y - v1->y) * percent; rdp.vtxbuf[index].z = v1->z + (v2->z - v1->z) * percent; rdp.vtxbuf[index].w = v1->w + (v2->w - v1->w) * percent; rdp.vtxbuf[index].f = v1->f + (v2->f - v1->f) * percent; rdp.vtxbuf[index].u0 = 0.5f; rdp.vtxbuf[index].v0 = v1->v0 + (v2->v0 - v1->v0) * percent + rdp.cur_cache[0]->c_scl_y * cur_256 * rdp.cur_cache[0]->splitheight; rdp.vtxbuf[index].u1 = v1->u1 + (v2->u1 - v1->u1) * percent; rdp.vtxbuf[index].v1 = v1->v1 + (v2->v1 - v1->v1) * percent; rdp.vtxbuf[index].b = (BYTE)(v1->b + (v2->b - v1->b) * percent); rdp.vtxbuf[index].g = (BYTE)(v1->g + (v2->g - v1->g) * percent); rdp.vtxbuf[index].r = (BYTE)(v1->r + (v2->r - v1->r) * percent); rdp.vtxbuf[index++].a = (BYTE)(v1->a + (v2->a - v1->a) * percent); } } else { //if (v2->u0 < left_256) // Both are out, save nothing if (v2->u0 >= left_256) // First is out, second is in, save intersection & in point { percent = (left_256 - v2->u0) / (v1->u0 - v2->u0); rdp.vtxbuf[index].x = v2->x + (v1->x - v2->x) * percent; rdp.vtxbuf[index].y = v2->y + (v1->y - v2->y) * percent; rdp.vtxbuf[index].z = v2->z + (v1->z - v2->z) * percent; rdp.vtxbuf[index].w = v2->w + (v1->w - v2->w) * percent; rdp.vtxbuf[index].f = v2->f + (v1->f - v2->f) * percent; rdp.vtxbuf[index].u0 = 0.5f; rdp.vtxbuf[index].v0 = v2->v0 + (v1->v0 - v2->v0) * percent + rdp.cur_cache[0]->c_scl_y * cur_256 * rdp.cur_cache[0]->splitheight; rdp.vtxbuf[index].u1 = v2->u1 + (v1->u1 - v2->u1) * percent; rdp.vtxbuf[index].v1 = v2->v1 + (v1->v1 - v2->v1) * percent; rdp.vtxbuf[index].b = (BYTE)(v2->b + (v1->b - v2->b) * percent); rdp.vtxbuf[index].g = (BYTE)(v2->g + (v1->g - v2->g) * percent); rdp.vtxbuf[index].r = (BYTE)(v2->r + (v1->r - v2->r) * percent); rdp.vtxbuf[index++].a = (BYTE)(v2->a + (v1->a - v2->a) * percent); // Save the in point rdp.vtxbuf[index] = *v2; rdp.vtxbuf[index].u0 -= left_256; rdp.vtxbuf[index++].v0 += rdp.cur_cache[0]->c_scl_y * (cur_256 * rdp.cur_cache[0]->splitheight); } } } rdp.n_global = index; rdp.vtxbuf = rdp.vtx2; // now vtx1 holds the value, & vtx2 is the destination rdp.vtxbuf2 = rdp.vtx1; rdp.vtx_buffer ^= 1; index = 0; for (i=0; iu0 <= 256.0f) { if (v2->u0 <= 256.0f) // Both are in, save the last one { rdp.vtxbuf[index] = *v2; rdp.vtxbuf[index++].not_zclipped = 0; } else // First is in, second is out, save intersection { percent = (right_256 - v1->u0) / (v2->u0 - v1->u0); rdp.vtxbuf[index].x = v1->x + (v2->x - v1->x) * percent; rdp.vtxbuf[index].y = v1->y + (v2->y - v1->y) * percent; rdp.vtxbuf[index].z = v1->z + (v2->z - v1->z) * percent; rdp.vtxbuf[index].w = v1->w + (v2->w - v1->w) * percent; rdp.vtxbuf[index].f = v1->f + (v2->f - v1->f) * percent; rdp.vtxbuf[index].u0 = 255.5f; rdp.vtxbuf[index].v0 = v1->v0 + (v2->v0 - v1->v0) * percent; rdp.vtxbuf[index].u1 = v1->u1 + (v2->u1 - v1->u1) * percent; rdp.vtxbuf[index].v1 = v1->v1 + (v2->v1 - v1->v1) * percent; rdp.vtxbuf[index].b = (BYTE)(v1->b + (v2->b - v1->b) * percent); rdp.vtxbuf[index].g = (BYTE)(v1->g + (v2->g - v1->g) * percent); rdp.vtxbuf[index].r = (BYTE)(v1->r + (v2->r - v1->r) * percent); rdp.vtxbuf[index].a = (BYTE)(v1->a + (v2->a - v1->a) * percent); rdp.vtxbuf[index++].not_zclipped = 0; } } else { //if (v2->u0 > 256.0f) // Both are out, save nothing if (v2->u0 <= 256.0f) // First is out, second is in, save intersection & in point { percent = (right_256 - v2->u0) / (v1->u0 - v2->u0); rdp.vtxbuf[index].x = v2->x + (v1->x - v2->x) * percent; rdp.vtxbuf[index].y = v2->y + (v1->y - v2->y) * percent; rdp.vtxbuf[index].z = v2->z + (v1->z - v2->z) * percent; rdp.vtxbuf[index].w = v2->w + (v1->w - v2->w) * percent; rdp.vtxbuf[index].f = v2->f + (v1->f - v2->f) * percent; rdp.vtxbuf[index].u0 = 255.5f; rdp.vtxbuf[index].v0 = v2->v0 + (v1->v0 - v2->v0) * percent; rdp.vtxbuf[index].u1 = v2->u1 + (v1->u1 - v2->u1) * percent; rdp.vtxbuf[index].v1 = v2->v1 + (v1->v1 - v2->v1) * percent; rdp.vtxbuf[index].b = (BYTE)(v2->b + (v1->b - v2->b) * percent); rdp.vtxbuf[index].g = (BYTE)(v2->g + (v1->g - v2->g) * percent); rdp.vtxbuf[index].r = (BYTE)(v2->r + (v1->r - v2->r) * percent); rdp.vtxbuf[index].a = (BYTE)(v2->a + (v1->a - v2->a) * percent); rdp.vtxbuf[index++].not_zclipped = 0; // Save the in point rdp.vtxbuf[index] = *v2; rdp.vtxbuf[index++].not_zclipped = 0; } } } rdp.n_global = index; do_triangle_stuff (linew); } } else { // Set vertex buffers rdp.vtxbuf = rdp.vtx1; // copy from v to rdp.vtx1 rdp.vtxbuf2 = rdp.vtx2; rdp.vtx_buffer = 0; rdp.n_global = 3; rdp.vtxbuf[0] = *vtx[0]; rdp.vtxbuf[1] = *vtx[1]; rdp.vtxbuf[2] = *vtx[2]; do_triangle_stuff (linew); } } void do_triangle_stuff (WORD linew) // what else?? do the triangle stuff :P (to keep from writing code twice) { int i; // if (rdp.zsrc != 1) clip_z (); for (i=0; i= 1) { rdp.vtxbuf[i].u0 *= rdp.vtxbuf[i].q; rdp.vtxbuf[i].v0 *= rdp.vtxbuf[i].q; } if (rdp.tex >= 2) { rdp.vtxbuf[i].u1 *= rdp.vtxbuf[i].q; rdp.vtxbuf[i].v1 *= rdp.vtxbuf[i].q; } } if (rdp.zsrc == 1) rdp.vtxbuf[i].z = rdp.prim_depth; // Don't remove clipping, or it will freeze if (rdp.vtxbuf[i].x > rdp.scissor.lr_x) rdp.clip |= CLIP_XMAX; if (rdp.vtxbuf[i].x < rdp.scissor.ul_x) rdp.clip |= CLIP_XMIN; if (rdp.vtxbuf[i].y > rdp.scissor.lr_y) rdp.clip |= CLIP_YMAX; if (rdp.vtxbuf[i].y < rdp.scissor.ul_y) rdp.clip |= CLIP_YMIN; } clip_tri (linew); } void do_triangle_stuff_2 (WORD linew) { rdp.clip = 0; for (int i=0; i rdp.scissor.lr_x) rdp.clip |= CLIP_XMAX; if (rdp.vtxbuf[i].x < rdp.scissor.ul_x) rdp.clip |= CLIP_XMIN; if (rdp.vtxbuf[i].y > rdp.scissor.lr_y) rdp.clip |= CLIP_YMAX; if (rdp.vtxbuf[i].y < rdp.scissor.ul_y) rdp.clip |= CLIP_YMIN; } clip_tri (linew); } // // clip_z - clips along the z-axis, also copies the vertex buffer for clip_tri // * ALWAYS * processes it, even if it does not need z-clipping. It needs // to copy the buffer anyway. // void clip_z () { int i,j,index,n=rdp.n_global; float percent; if (rdp.clip & CLIP_ZMIN) { // Swap vertex buffers VERTEX *tmp = rdp.vtxbuf2; rdp.vtxbuf2 = rdp.vtxbuf; rdp.vtxbuf = tmp; rdp.vtx_buffer ^= 1; index = 0; // Check the vertices for clipping for (i=0; i= 0.01f) { if (Vj.w >= 0.01f) // Both are in, save the last one { rdp.vtxbuf[index] = Vj; rdp.vtxbuf[index++].not_zclipped = 1; } else // First is in, second is out, save intersection { percent = (-Vi.w) / (Vj.w - Vi.w); rdp.vtxbuf[index].not_zclipped = 0; rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent; rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent; rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent; rdp.vtxbuf[index].f = Vi.f + (Vj.f - Vi.f) * percent; rdp.vtxbuf[index].w = 0.01f; rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent; rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent; rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent; rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent; rdp.vtxbuf[index].b = (BYTE)(Vi.b + (Vj.b - Vi.b) * percent); rdp.vtxbuf[index].g = (BYTE)(Vi.g + (Vj.g - Vi.g) * percent); rdp.vtxbuf[index].r = (BYTE)(Vi.r + (Vj.r - Vi.r) * percent); rdp.vtxbuf[index++].a = (BYTE)(Vi.a + (Vj.a - Vi.a) * percent); } } else { //if (Vj.w < 0.01f) // Both are out, save nothing if (Vj.w >= 0.01f) // First is out, second is in, save intersection & in point { percent = (-Vj.w) / (Vi.w - Vj.w); rdp.vtxbuf[index].not_zclipped = 0; rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent; rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent; rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent; rdp.vtxbuf[index].f = Vj.f + (Vi.f - Vj.f) * percent; rdp.vtxbuf[index].w = 0.01f; rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent; rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent; rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent; rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent; rdp.vtxbuf[index].b = (BYTE)(Vj.b + (Vi.b - Vj.b) * percent); rdp.vtxbuf[index].g = (BYTE)(Vj.g + (Vi.g - Vj.g) * percent); rdp.vtxbuf[index].r = (BYTE)(Vj.r + (Vi.r - Vj.r) * percent); rdp.vtxbuf[index++].a = (BYTE)(Vj.a + (Vi.a - Vj.a) * percent); // Save the in point rdp.vtxbuf[index] = Vj; rdp.vtxbuf[index++].not_zclipped = 1; } } } rdp.n_global = index; } } static void CalculateLOD(VERTEX **v, int n) { //rdp.update |= UPDATE_TEXTURE; /* if (rdp.lod_calculated) { float detailmax; if (dc0_detailmax < 0.5) detailmax = rdp.lod_fraction; else detailmax = 1.0f - rdp.lod_fraction; grTexDetailControl (GR_TMU0, dc0_lodbias, dc0_detailscale, detailmax); if (num_tmu == 2) grTexDetailControl (GR_TMU1, dc1_lodbias, dc1_detailscale, detailmax); return; } */ float deltaS, deltaT; float deltaX, deltaY; double deltaTexels, deltaPixels, lodFactor = 0; double intptr; float s_scale = rdp.tiles[rdp.cur_tile].width / 255.0f; float t_scale = rdp.tiles[rdp.cur_tile].height / 255.0f; if (settings.lodmode == 1) { deltaS = (v[1]->u0/v[1]->q - v[0]->u0/v[0]->q) * s_scale; deltaT = (v[1]->v0/v[1]->q - v[0]->v0/v[0]->q) * t_scale; deltaTexels = sqrt( deltaS * deltaS + deltaT * deltaT ); deltaX = (v[1]->x - v[0]->x)/rdp.scale_x; deltaY = (v[1]->y - v[0]->y)/rdp.scale_y; deltaPixels = sqrt( deltaX * deltaX + deltaY * deltaY ); lodFactor = deltaTexels / deltaPixels; } else { int i, j; for (i = 0; i < n; i++) { j = (i < n-1) ? i + 1 : 0; deltaS = (v[j]->u0/v[j]->q - v[i]->u0/v[i]->q) * s_scale; deltaT = (v[j]->v0/v[j]->q - v[i]->v0/v[i]->q) * t_scale; // deltaS = v[j]->ou - v[i]->ou; // deltaT = v[j]->ov - v[i]->ov; deltaTexels = sqrt( deltaS * deltaS + deltaT * deltaT ); deltaX = (v[j]->x - v[i]->x)/rdp.scale_x; deltaY = (v[j]->y - v[i]->y)/rdp.scale_y; deltaPixels = sqrt( deltaX * deltaX + deltaY * deltaY ); lodFactor += deltaTexels / deltaPixels; } // Divide by n (n edges) to find average lodFactor = lodFactor / n; } long ilod = (long)lodFactor; int lod_tile = std::min((int)(log((double)ilod)/log(2.0)), rdp.cur_tile + rdp.mipmap_level); float lod_fraction = 1.0f; if (lod_tile < rdp.cur_tile + rdp.mipmap_level) { lod_fraction = std::max((float)modf(lodFactor / pow(2.0f,lod_tile),&intptr), rdp.prim_lodmin / 255.0f); } float detailmax; if (cmb.dc0_detailmax < 0.5f) detailmax = lod_fraction; else detailmax = 1.0f - lod_fraction; grTexDetailControl (GR_TMU0, cmb.dc0_lodbias, cmb.dc0_detailscale, detailmax); if (num_tmu == 2) grTexDetailControl (GR_TMU1, cmb.dc1_lodbias, cmb.dc1_detailscale, detailmax); FRDP("CalculateLOD factor: %f, tile: %d, lod_fraction: %f\n", (float)lodFactor, lod_tile, lod_fraction); } static void DepthBuffer(VERTEX ** vtx, int n) { if (settings.RE2) { for(int i=0; iz*8.0f+0.5f); if (fz < 0) fz = 0; else if (fz >= 0x40000) fz = 0x40000 - 1; vtx[i]->z = (float)zLUT[fz]; } return; } if (settings.fb_depth_render && dzdx && (rdp.flags & ZBUF_UPDATE)) { vertexi v[12]; for(int i=0; ix / rdp.scale_x * 65536.0); v[i].y = (long)(vtx[i]->y / rdp.scale_y * 65536.0); v[i].z = (long)(vtx[i]->z * 65536.0); } Rasterize(v, n, dzdx); } for(int i=0; iz = ScaleZ(vtx[i]->z); } void clip_tri (WORD linew) { int i,j,index,n=rdp.n_global; float percent; // rdp.vtxbuf and rdp.vtxbuf2 were set by clip_z // Check which clipping is needed if (rdp.clip & CLIP_XMAX) // right of the screen { // Swap vertex buffers VERTEX *tmp = rdp.vtxbuf2; rdp.vtxbuf2 = rdp.vtxbuf; rdp.vtxbuf = tmp; rdp.vtx_buffer ^= 1; index = 0; // Check the vertices for clipping for (i=0; i rdp.scissor.lr_x) // Both are out, save nothing if (Vj.x <= rdp.scissor.lr_x) // First is out, second is in, save intersection & in point { percent = (rdp.scissor.lr_x - Vj.x) / (Vi.x - Vj.x); rdp.vtxbuf[index].x = (float)rdp.scissor.lr_x + 0.001f; rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent; rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent; rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent; rdp.vtxbuf[index].f = Vj.f + (Vi.f - Vj.f) * percent; rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent; rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent; rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent; rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent; rdp.vtxbuf[index].b = (BYTE)(Vj.b + (Vi.b - Vj.b) * percent); rdp.vtxbuf[index].g = (BYTE)(Vj.g + (Vi.g - Vj.g) * percent); rdp.vtxbuf[index].r = (BYTE)(Vj.r + (Vi.r - Vj.r) * percent); rdp.vtxbuf[index++].a = (BYTE)(Vj.a + (Vi.a - Vj.a) * percent); // Save the in point rdp.vtxbuf[index++] = Vj; } } } n = index; } if (rdp.clip & CLIP_XMIN) // left of the screen { // Swap vertex buffers VERTEX *tmp = rdp.vtxbuf2; rdp.vtxbuf2 = rdp.vtxbuf; rdp.vtxbuf = tmp; rdp.vtx_buffer ^= 1; index = 0; // Check the vertices for clipping for (i=0; i= rdp.scissor.ul_x) { if (Vj.x >= rdp.scissor.ul_x) // Both are in, save the last one { rdp.vtxbuf[index++] = Vj; } else // First is in, second is out, save intersection { percent = (rdp.scissor.ul_x - Vi.x) / (Vj.x - Vi.x); rdp.vtxbuf[index].x = (float)rdp.scissor.ul_x + 0.001f; rdp.vtxbuf[index].y = Vi.y + (Vj.y - Vi.y) * percent; rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent; rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent; rdp.vtxbuf[index].f = Vi.f + (Vj.f - Vi.f) * percent; rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent; rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent; rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent; rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent; rdp.vtxbuf[index].b = (BYTE)(Vi.b + (Vj.b - Vi.b) * percent); rdp.vtxbuf[index].g = (BYTE)(Vi.g + (Vj.g - Vi.g) * percent); rdp.vtxbuf[index].r = (BYTE)(Vi.r + (Vj.r - Vi.r) * percent); rdp.vtxbuf[index++].a = (BYTE)(Vi.a + (Vj.a - Vi.a) * percent); } } else { //if (Vj.x < rdp.scissor.ul_x) // Both are out, save nothing if (Vj.x >= rdp.scissor.ul_x) // First is out, second is in, save intersection & in point { percent = (rdp.scissor.ul_x - Vj.x) / (Vi.x - Vj.x); rdp.vtxbuf[index].x = (float)rdp.scissor.ul_x + 0.001f; rdp.vtxbuf[index].y = Vj.y + (Vi.y - Vj.y) * percent; rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent; rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent; rdp.vtxbuf[index].f = Vj.f + (Vi.f - Vj.f) * percent; rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent; rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent; rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent; rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent; rdp.vtxbuf[index].b = (BYTE)(Vj.b + (Vi.b - Vj.b) * percent); rdp.vtxbuf[index].g = (BYTE)(Vj.g + (Vi.g - Vj.g) * percent); rdp.vtxbuf[index].r = (BYTE)(Vj.r + (Vi.r - Vj.r) * percent); rdp.vtxbuf[index++].a = (BYTE)(Vj.a + (Vi.a - Vj.a) * percent); // Save the in point rdp.vtxbuf[index++] = Vj; } } } n = index; } if (rdp.clip & CLIP_YMAX) // top of the screen { // Swap vertex buffers VERTEX *tmp = rdp.vtxbuf2; rdp.vtxbuf2 = rdp.vtxbuf; rdp.vtxbuf = tmp; rdp.vtx_buffer ^= 1; index = 0; // Check the vertices for clipping for (i=0; i rdp.scissor.lr_y) // Both are out, save nothing if (Vj.y <= rdp.scissor.lr_y) // First is out, second is in, save intersection & in point { percent = (rdp.scissor.lr_y - Vj.y) / (Vi.y - Vj.y); rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent; rdp.vtxbuf[index].y = (float)rdp.scissor.lr_y + 0.001f; rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent; rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent; rdp.vtxbuf[index].f = Vj.f + (Vi.f - Vj.f) * percent; rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent; rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent; rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent; rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent; rdp.vtxbuf[index].b = (BYTE)(Vj.b + (Vi.b - Vj.b) * percent); rdp.vtxbuf[index].g = (BYTE)(Vj.g + (Vi.g - Vj.g) * percent); rdp.vtxbuf[index].r = (BYTE)(Vj.r + (Vi.r - Vj.r) * percent); rdp.vtxbuf[index++].a = (BYTE)(Vj.a + (Vi.a - Vj.a) * percent); // Save the in point rdp.vtxbuf[index++] = Vj; } } } n = index; } if (rdp.clip & CLIP_YMIN) // bottom of the screen { // Swap vertex buffers VERTEX *tmp = rdp.vtxbuf2; rdp.vtxbuf2 = rdp.vtxbuf; rdp.vtxbuf = tmp; rdp.vtx_buffer ^= 1; index = 0; // Check the vertices for clipping for (i=0; i= rdp.scissor.ul_y) { if (Vj.y >= rdp.scissor.ul_y) // Both are in, save the last one { rdp.vtxbuf[index++] = Vj; } else // First is in, second is out, save intersection { percent = (rdp.scissor.ul_y - Vi.y) / (Vj.y - Vi.y); rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent; rdp.vtxbuf[index].y = (float)rdp.scissor.ul_y + 0.001f; rdp.vtxbuf[index].z = Vi.z + (Vj.z - Vi.z) * percent; rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * percent; rdp.vtxbuf[index].f = Vi.f + (Vj.f - Vi.f) * percent; rdp.vtxbuf[index].u0 = Vi.u0 + (Vj.u0 - Vi.u0) * percent; rdp.vtxbuf[index].v0 = Vi.v0 + (Vj.v0 - Vi.v0) * percent; rdp.vtxbuf[index].u1 = Vi.u1 + (Vj.u1 - Vi.u1) * percent; rdp.vtxbuf[index].v1 = Vi.v1 + (Vj.v1 - Vi.v1) * percent; rdp.vtxbuf[index].b = (BYTE)(Vi.b + (Vj.b - Vi.b) * percent); rdp.vtxbuf[index].g = (BYTE)(Vi.g + (Vj.g - Vi.g) * percent); rdp.vtxbuf[index].r = (BYTE)(Vi.r + (Vj.r - Vi.r) * percent); rdp.vtxbuf[index++].a = (BYTE)(Vi.a + (Vj.a - Vi.a) * percent); } } else { //if (Vj.y < rdp.scissor.ul_y) // Both are out, save nothing if (Vj.y >= rdp.scissor.ul_y) // First is out, second is in, save intersection & in point { percent = (rdp.scissor.ul_y - Vj.y) / (Vi.y - Vj.y); rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent; rdp.vtxbuf[index].y = (float)rdp.scissor.ul_y + 0.001f; rdp.vtxbuf[index].z = Vj.z + (Vi.z - Vj.z) * percent; rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * percent; rdp.vtxbuf[index].f = Vj.f + (Vi.f - Vj.f) * percent; rdp.vtxbuf[index].u0 = Vj.u0 + (Vi.u0 - Vj.u0) * percent; rdp.vtxbuf[index].v0 = Vj.v0 + (Vi.v0 - Vj.v0) * percent; rdp.vtxbuf[index].u1 = Vj.u1 + (Vi.u1 - Vj.u1) * percent; rdp.vtxbuf[index].v1 = Vj.v1 + (Vi.v1 - Vj.v1) * percent; rdp.vtxbuf[index].b = (BYTE)(Vj.b + (Vi.b - Vj.b) * percent); rdp.vtxbuf[index].g = (BYTE)(Vj.g + (Vi.g - Vj.g) * percent); rdp.vtxbuf[index].r = (BYTE)(Vj.r + (Vi.r - Vj.r) * percent); rdp.vtxbuf[index++].a = (BYTE)(Vj.a + (Vi.a - Vj.a) * percent); // Save the in point rdp.vtxbuf[index++] = Vj; } } } n = index; } if (n < 3) { FRDP (" * clip_tri: n < 3\n"); return; } ConvertCoordsConvert (rdp.vtxbuf, n); if (rdp.fog_coord_enabled) { for (i = 0; i < n; i++) { rdp.vtxbuf[i].f = 1.0f/std::max(16.0f,rdp.vtxbuf[i].f); } } if (settings.lodmode > 0 && rdp.cur_tile < rdp.mipmap_level) CalculateLOD(rdp.vtx_buffer?(vtx_list2):(vtx_list1), n); cmb.cmb_ext_use = cmb.tex_cmb_ext_use = 0; /* if (rdp.hires_tex) { for (int k = 0; k < 3; k++) { FRDP("v%d %f->%f, width: %d. height: %d, tex_width: %d, tex_height: %d, lr_u: %f, lr_v: %f\n", k, vv0[k], pv[k]->v1, rdp.hires_tex->width, rdp.hires_tex->height, rdp.hires_tex->tex_width, rdp.hires_tex->tex_height, rdp.hires_tex->lr_u, rdp.hires_tex->lr_v); } } */ if (fullscreen) { if (settings.wireframe) { SetWireframeCol (); for (i=0; ix, pv[k]->y, pv[k]->z, pv[k]->coord[rdp.t0<<1], pv[k]->coord[(rdp.t0<<1)+1]); // pv[k]->y = settings.res_y - pv[k]->y; if (linew > 0) { if (linew == 1) { for (i=0; inv = n; info->v = new VERTEX [n]; memcpy (info->v, v, sizeof(VERTEX)*n); info->cycle_mode = rdp.cycle_mode; info->cycle1 = rdp.cycle1; info->cycle2 = rdp.cycle2; info->uncombined = rdp.uncombined; info->geom_mode = rdp.geom_mode; info->othermode_h = rdp.othermode_h; info->othermode_l = rdp.othermode_l; info->tri_n = rdp.tri_n; info->type = type; for (int i=0; i<2; i++) { int j = rdp.cur_tile+i; if (i == 0) info->t[i].tmu = rdp.t0; else info->t[i].tmu = rdp.t1; info->t[i].cur_cache[0] = rdp.cur_cache_n[rdp.t0]; info->t[i].cur_cache[1] = rdp.cur_cache_n[rdp.t1]; info->t[i].format = rdp.tiles[j].format; info->t[i].size = rdp.tiles[j].size; info->t[i].width = rdp.tiles[j].width; info->t[i].height = rdp.tiles[j].height; info->t[i].line = rdp.tiles[j].line; info->t[i].palette = rdp.tiles[j].palette; info->t[i].clamp_s = rdp.tiles[j].clamp_s; info->t[i].clamp_t = rdp.tiles[j].clamp_t; info->t[i].mirror_s = rdp.tiles[j].mirror_s; info->t[i].mirror_t = rdp.tiles[j].mirror_t; info->t[i].shift_s = rdp.tiles[j].shift_s; info->t[i].shift_t = rdp.tiles[j].shift_t; info->t[i].mask_s = rdp.tiles[j].mask_s; info->t[i].mask_t = rdp.tiles[j].mask_t; info->t[i].ul_s = rdp.tiles[j].ul_s; info->t[i].ul_t = rdp.tiles[j].ul_t; info->t[i].lr_s = rdp.tiles[j].lr_s; info->t[i].lr_t = rdp.tiles[j].lr_t; info->t[i].t_ul_s = rdp.tiles[7].t_ul_s; info->t[i].t_ul_t = rdp.tiles[7].t_ul_t; info->t[i].t_lr_s = rdp.tiles[7].t_lr_s; info->t[i].t_lr_t = rdp.tiles[7].t_lr_t; info->t[i].scale_s = rdp.tiles[j].s_scale; info->t[i].scale_t = rdp.tiles[j].t_scale; } info->fog_color = rdp.fog_color; info->fill_color = rdp.fill_color; info->prim_color = rdp.prim_color; info->blend_color = rdp.blend_color; info->env_color = rdp.env_color; info->prim_lodmin = rdp.prim_lodmin; info->prim_lodfrac = rdp.prim_lodfrac; info->pNext = debug.tri_list; debug.tri_list = info; if (debug.tri_last == NULL) debug.tri_last = debug.tri_list; } } void update_scissor () { if (rdp.update & UPDATE_SCISSOR) { rdp.update ^= UPDATE_SCISSOR; // KILL the floating point error with 0.01f rdp.scissor.ul_x = (DWORD) std::max(std::min((rdp.scissor_o.ul_x * rdp.scale_x + rdp.offset_x + 0.01f), (float) settings.res_x),0.0f); rdp.scissor.lr_x = (DWORD) std::max(std::min((rdp.scissor_o.lr_x * rdp.scale_x + rdp.offset_x + 0.01f), (float) settings.res_x),0.0f); rdp.scissor.ul_y = (DWORD) std::max(std::min((rdp.scissor_o.ul_y * rdp.scale_y + rdp.offset_y + 0.01f), (float) settings.res_y),0.0f); rdp.scissor.lr_y = (DWORD) std::max(std::min((rdp.scissor_o.lr_y * rdp.scale_y + rdp.offset_y + 0.01f), (float) settings.res_y),0.0f); FRDP (" |- scissor - (%d, %d) -> (%d, %d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y); } } // // update - update states if they need it // typedef struct { unsigned int c2_m2b:2; unsigned int c1_m2b:2; unsigned int c2_m2a:2; unsigned int c1_m2a:2; unsigned int c2_m1b:2; unsigned int c1_m1b:2; unsigned int c2_m1a:2; unsigned int c1_m1a:2; } rdp_blender_setting; void update () { RDP ("-+ update called\n"); // Check for rendermode changes // Z buffer if (rdp.render_mode_changed & 0x00000C30) { FRDP (" |- render_mode_changed zbuf - decal: %s, update: %s, compare: %s\n", str_yn[(rdp.othermode_l&0x00000C00) == 0x00000C00], str_yn[(rdp.othermode_l&0x00000020)?1:0], str_yn[(rdp.othermode_l&0x00000010)?1:0]); rdp.render_mode_changed &= ~0x00000C30; rdp.update |= UPDATE_ZBUF_ENABLED; // Decal? // if ((rdp.othermode_l & 0x00000C00) == 0x00000C00) if (rdp.othermode_l & 0x00000800) rdp.flags |= ZBUF_DECAL; else rdp.flags &= ~ZBUF_DECAL; // Update? if ((rdp.othermode_l & 0x00000020)) rdp.flags |= ZBUF_UPDATE; else rdp.flags &= ~ZBUF_UPDATE; // Compare? if (rdp.othermode_l & 0x00000010) rdp.flags |= ZBUF_COMPARE; else rdp.flags &= ~ZBUF_COMPARE; } // Alpha compare if (rdp.render_mode_changed & 0x00001000) { FRDP (" |- render_mode_changed alpha compare - on: %s\n", str_yn[(rdp.othermode_l&0x00001000)?1:0]); rdp.render_mode_changed &= ~0x00001000; rdp.update |= UPDATE_ALPHA_COMPARE; if (rdp.othermode_l & 0x00001000) rdp.flags |= ALPHA_COMPARE; else rdp.flags &= ~ALPHA_COMPARE; } if (rdp.render_mode_changed & 0x00002000) // alpha cvg sel { FRDP (" |- render_mode_changed alpha cvg sel - on: %s\n", str_yn[(rdp.othermode_l&0x00002000)?1:0]); rdp.render_mode_changed &= ~0x00002000; rdp.update |= UPDATE_COMBINE; } // Force blend if (rdp.render_mode_changed & 0xFFFF0000) { FRDP (" |- render_mode_changed force_blend - %08lx\n", rdp.othermode_l&0xFFFF0000); rdp.render_mode_changed &= 0x0000FFFF; rdp.fbl_a0 = (BYTE)((rdp.othermode_l>>30)&0x3); rdp.fbl_b0 = (BYTE)((rdp.othermode_l>>26)&0x3); rdp.fbl_c0 = (BYTE)((rdp.othermode_l>>22)&0x3); rdp.fbl_d0 = (BYTE)((rdp.othermode_l>>18)&0x3); rdp.fbl_a1 = (BYTE)((rdp.othermode_l>>28)&0x3); rdp.fbl_b1 = (BYTE)((rdp.othermode_l>>24)&0x3); rdp.fbl_c1 = (BYTE)((rdp.othermode_l>>20)&0x3); rdp.fbl_d1 = (BYTE)((rdp.othermode_l>>16)&0x3); rdp.update |= UPDATE_COMBINE; } //if (fullscreen) //{ // Combine MUST go before texture if ((rdp.update & UPDATE_COMBINE) && rdp.allow_combine) { RDP (" |-+ update_combine\n"); Combine (); } if (rdp.update & UPDATE_TEXTURE) // note: UPDATE_TEXTURE and UPDATE_COMBINE are the same { rdp.tex_ctr ++; if (rdp.tex_ctr == 0xFFFFFFFF) rdp.tex_ctr = 0; TexCache (); if (rdp.noise == noise_none) rdp.update ^= UPDATE_TEXTURE; } if (fullscreen) { // Z buffer if (rdp.update & UPDATE_ZBUF_ENABLED) { // already logged above rdp.update ^= UPDATE_ZBUF_ENABLED; if (rdp.flags & ZBUF_DECAL) { if ((rdp.othermode_l & 0x00000C00) == 0x00000C00) { grDepthBiasLevel (settings.depth_bias);//(-32); FRDP("depth bias: %d\n", settings.depth_bias); } else { // VP changed that to -1 (was -4) grDepthBiasLevel (-4);//-16); RDP("depth bias: -4"); } } else { grDepthBiasLevel (0); } if ((rdp.flags & ZBUF_ENABLED) || (settings.force_depth_compare && rdp.zsrc == 1)) { if ((rdp.flags & ZBUF_COMPARE)) { if (settings.soft_depth_compare) { grDepthBufferFunction (GR_CMP_LEQUAL); } else { grDepthBufferFunction (GR_CMP_LESS); } } else { grDepthBufferFunction (GR_CMP_ALWAYS); } if ((rdp.flags & ZBUF_UPDATE) // || (rdp.flags & ZBUF_DECAL) // FOR DEBUGGING ONLY ) { grDepthMask (FXTRUE); } else { grDepthMask (FXFALSE); } } else { grDepthBufferFunction (GR_CMP_ALWAYS); grDepthMask (FXFALSE); } } // Alpha compare if (rdp.update & UPDATE_ALPHA_COMPARE) { // already logged above rdp.update ^= UPDATE_ALPHA_COMPARE; // if (rdp.acmp == 1 && !(rdp.othermode_l & 0x00002000) && !force_full_alpha) // if (rdp.acmp == 1 && !(rdp.othermode_l & 0x00002000) && (rdp.blend_color&0xFF)) if (rdp.acmp == 1 && !(rdp.othermode_l & 0x00002000) && (!(rdp.othermode_l & 0x00004000) || (rdp.blend_color&0xFF))) { BYTE reference = (BYTE)(rdp.blend_color&0xFF); if (reference) grAlphaTestFunction (GR_CMP_GEQUAL); else grAlphaTestFunction (GR_CMP_GREATER); grAlphaTestReferenceValue (reference); FRDP (" |- alpha compare: blend: %02lx\n", reference); } else { if (rdp.flags & ALPHA_COMPARE) { if ((rdp.othermode_l & 0x5000) != 0x5000) { grAlphaTestFunction (GR_CMP_GEQUAL); grAlphaTestReferenceValue (0x20);//0xA0); RDP (" |- alpha compare: 0x20\n"); } else { grAlphaTestFunction (GR_CMP_GREATER); if (rdp.acmp == 3) { grAlphaTestReferenceValue ((BYTE)(rdp.blend_color&0xFF)); FRDP (" |- alpha compare: blend: %02lx\n", rdp.blend_color&0xFF); } else { grAlphaTestReferenceValue (0x00); RDP (" |- alpha compare: 0x00\n"); } } } else { grAlphaTestFunction (GR_CMP_ALWAYS); RDP (" |- alpha compare: none\n"); } } if (rdp.acmp == 3) { if (grStippleModeExt) { RDP (" |- alpha compare: dither\n"); grStippleModeExt(settings.stipple_mode); // grStippleModeExt(GR_STIPPLE_PATTERN); } } else { if (grStippleModeExt) { //RDP (" |- alpha compare: dither disabled\n"); grStippleModeExt(GR_STIPPLE_DISABLE); } } } // Cull mode (leave this in for z-clipped triangles) if (rdp.update & UPDATE_CULL_MODE) { rdp.update ^= UPDATE_CULL_MODE; DWORD mode = (rdp.flags & CULLMASK) >> CULLSHIFT; FRDP (" |- cull_mode - mode: %s\n", str_cull[mode]); switch (mode) { case 0: // cull none case 3: // cull both grCullMode(GR_CULL_DISABLE); break; case 1: // cull front // grCullMode(GR_CULL_POSITIVE); grCullMode(GR_CULL_NEGATIVE); break; case 2: // cull back // grCullMode (GR_CULL_NEGATIVE); grCullMode (GR_CULL_POSITIVE); break; } } //Added by Gonetz. if (settings.fog && (rdp.update & UPDATE_FOG_ENABLED)) { rdp.update ^= UPDATE_FOG_ENABLED; if (rdp.flags & FOG_ENABLED) { typedef union { WORD *w; rdp_blender_setting *b; } BLEND; WORD blword = (WORD) (rdp.othermode_l >> 16); BLEND bl; bl.w = &blword; if((rdp.fog_multiplier > 0) && (bl.b->c1_m1a==3 || bl.b->c1_m2a == 3 || bl.b->c2_m1a == 3 || bl.b->c2_m2a == 3)) { grFogColorValue(rdp.fog_color); grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT); rdp.fog_coord_enabled = TRUE; RDP("fog enabled \n"); } else { RDP("fog disabled in blender\n"); rdp.fog_coord_enabled = FALSE; grFogMode (GR_FOG_DISABLE); } } else { RDP("fog disabled\n"); rdp.fog_coord_enabled = FALSE; grFogMode (GR_FOG_DISABLE); } } } if (rdp.update & UPDATE_VIEWPORT) { rdp.update ^= UPDATE_VIEWPORT; if (fullscreen) { if (settings.RE2) { grClipWindow (0, 0, settings.res_x-1, settings.res_y-1); } else { float scale_x = (float)fabs(rdp.view_scale[0]); float scale_y = (float)fabs(rdp.view_scale[1]); //printf("scale_y %g\n", scale_y); DWORD min_x = (DWORD) std::max(rdp.view_trans[0] - scale_x, 0.0f); DWORD min_y = (DWORD) std::max(rdp.view_trans[1] - scale_y, 0.0f); DWORD max_x = (DWORD) std::min(rdp.view_trans[0] + scale_x + 1, (float) settings.res_x); DWORD max_y = (DWORD) std::min(rdp.view_trans[1] + scale_y + 1, (float) settings.res_y); FRDP (" |- viewport - (%d, %d, %d, %d)\n", min_x, min_y, max_x, max_y); grClipWindow (min_x, min_y, max_x, max_y); //printf("viewport %d %d %d %d\n", min_x, min_y, max_x, max_y); } } } if (rdp.update & UPDATE_SCISSOR) update_scissor (); RDP (" + update end\n"); } void set_message_combiner () { grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); if (settings.buff_clear && (settings.show_fps & 0x08)) grAlphaBlendFunction (GR_BLEND_SRC_ALPHA, GR_BLEND_ONE_MINUS_SRC_ALPHA, GR_BLEND_ZERO, GR_BLEND_ZERO); else grAlphaBlendFunction (GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ZERO, GR_BLEND_ZERO); grAlphaTestFunction (GR_CMP_ALWAYS); if (grStippleModeExt) { grStippleModeExt(GR_STIPPLE_DISABLE); } grTexCombine (GR_TMU1, GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE); grTexCombine (GR_TMU0, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE); grTexSource(GR_TMU0, grTexMinAddress(GR_TMU0) + offset_font, GR_MIPMAPLEVELMASK_BOTH, &fontTex); grFogMode (GR_FOG_DISABLE); } /* 1 bit: common 2 bit: I textures, V-Rally 99 3 bit: South Park, Polaris 4 bit: Mace 5 bit: CyberTiger 6 bit: Yoshi Story */ void fix_tex_coord (VERTEX **v) { BOOL fix = FALSE; if (settings.fix_tex_coord & 449) { // if ( (rdp.tiles[rdp.last_tile_size].format == 2) || // ( (rdp.tiles[rdp.last_tile_size].size != 2)) ) if (rdp.tiles[rdp.last_tile_size].size != 2) { if (settings.fix_tex_coord & 128) { if (v[0]->sz != v[1]->sz || v[0]->sz != v[2]->sz) return; } if (settings.fix_tex_coord & 256) //dr.mario { if ((rdp.tiles[rdp.last_tile_size].format == 2) && (rdp.tiles[rdp.last_tile_size].size == 0)) return; } // int lu = (rdp.tiles[rdp.last_tile_size].ul_s)<<1; int ru = (rdp.tiles[rdp.last_tile_size].lr_s+1)<<1; int rv = (rdp.tiles[rdp.last_tile_size].lr_t+1)<<1; int diff = (settings.fix_tex_coord & 64) ? 5 : 3; for (int t = 0; t < 3; t++) { if (v[t]->uv_fixed == 0) //&& (((short)v[t]->ou > 0) || ((short)v[t]->ov > 0))) { if ( (abs((short)v[t]->ou - ru) < diff) || (abs((short)v[t]->ov - rv) < diff) ) // if ( ((short)v[t]->ou == lu) || (abs((short)v[t]->ou - ru) < 3) ) { fix = TRUE; break; } } else { fix = TRUE; break; } } if (fix) { for (int t = 0; t < 3; t++) { if (v[t]->uv_fixed == 0) { v[t]->uv_fixed = 1; FRDP("v[%d] uv_fixed (%f, %f)->(%f,%f)\n",t, v[t]->ou, v[t]->ov, v[t]->ou*0.5f, v[t]->ov*0.5f); v[t]->ou *= 0.5f; v[t]->ov *= 0.5f; } } return; } } } if (settings.fix_tex_coord & 2) { if (rdp.tiles[rdp.last_tile_size].format == 4) { for (int t = 0; t < 3; t++) { if (v[t]->uv_fixed == 0) { v[t]->uv_fixed = 1; v[t]->ou *= 0.5f; v[t]->ov *= 0.5f; } } return; } } if (settings.fix_tex_coord & 4) { TILE & last_tile = rdp.tiles[rdp.last_tile_size]; if ((last_tile.format == 2) && (last_tile.size == 0) && (last_tile.line%2 == 0) && (last_tile.lr_s >= last_tile.lr_t)) { int ru = (rdp.tiles[rdp.last_tile_size].lr_s+1); int rv = (rdp.tiles[rdp.last_tile_size].lr_t+1); int t; for (t = 0; t < 3; t++) { if (v[t]->uv_fixed == 0) { if ( (abs((short)v[t]->ou - ru) < 3) || (abs((short)v[t]->ov - rv) < 3) ) return; } } for (t = 0; t < 3; t++) { if (v[t]->uv_fixed == 0) { v[t]->uv_fixed = 1; v[t]->ou *= 0.5f; v[t]->ov *= 0.5f; } } return; } } if (settings.fix_tex_coord & 8) { if (rdp.tiles[rdp.last_tile_size].format == 3 && rdp.tiles[rdp.last_tile_size].size == 1) { short width = (rdp.tiles[rdp.last_tile_size].ul_s<<1)+1 ; for (int t = 0; t < 3; t++) { if (v[t]->uv_fixed == 0) { if (short(v[t]->ou) == width) { fix = TRUE; break; } } else { fix = TRUE; break; } } if (fix) { RDP("texcoord fixed!\n"); for (int t = 0; t < 3; t++) { if (v[t]->uv_fixed == 0) { v[t]->uv_fixed = 1; v[t]->ou *= 0.5f; v[t]->ov *= 0.5f; } } return; } } } if (settings.fix_tex_coord & 16) { if ((rdp.tiles[rdp.last_tile_size].format == 2) && (rdp.tiles[rdp.last_tile_size].size == 0)) { short width = rdp.tiles[rdp.last_tile_size].lr_s + 1; short height = rdp.tiles[rdp.last_tile_size].lr_t + 1; for (int t = 0; t < 3; t++) { if (v[t]->uv_fixed == 0) { if ((short(v[t]->ou) > width) || (short(v[t]->ov) > height)) { fix = TRUE; break; } } else { fix = TRUE; break; } } if (fix) { for (int t = 0; t < 3; t++) { if (v[t]->uv_fixed == 0) { v[t]->uv_fixed = 1; v[t]->ou *= 0.5f; v[t]->ov *= 0.5f; } } RDP("texcoord fixed!\n"); return; } } } if (settings.fix_tex_coord & 32) { if (!rdp.vtx[rdp.v0].uv_fixed && (rdp.tiles[rdp.last_tile_size].format == 2) && (rdp.tiles[rdp.last_tile_size].size == 1) && (rdp.tiles[rdp.last_tile_size].lr_s >= 31) && (rdp.tiles[rdp.last_tile_size].lr_t >= 31)) { int ru = (rdp.tiles[rdp.last_tile_size].lr_s+1)<<1; int rv = (rdp.tiles[rdp.last_tile_size].lr_t+1)<<1; int top = rdp.v0 + rdp.vn; for (int t = rdp.v0; t < top; t++) { if ( (abs((short)rdp.vtx[t].ou - ru) < 2) || (abs((short)rdp.vtx[t].ov - rv) < 2) ) { fix = TRUE; break; } } if (fix) { for (int t = rdp.v0; t < top; t++) { rdp.vtx[t].uv_fixed = 1; rdp.vtx[t].ou *= 0.5f; rdp.vtx[t].ov *= 0.5f; } RDP("texcoord fixed!\n"); return; } } } } mupen64plus-video-glide64-src-2.6.0/src/Util.h000066400000000000000000000076221464507525600207500ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** #ifndef Util_H #define Util_H #include #include "winlnxdefs.h" #include "rdp.h" #define NOT_TMU0 0x00 #define NOT_TMU1 0x01 #define NOT_TMU2 0x02 void util_init (); void clip_z (); void clip_tri (WORD linew = 0); BOOL cull_tri (VERTEX **v); void DrawTri (VERTEX **v, WORD linew = 0); void do_triangle_stuff (WORD linew = 0); void do_triangle_stuff_2 (WORD linew = 0); void add_tri (VERTEX *v, int n, int type); void apply_shade_mods (VERTEX *v); void update (); void update_scissor (); void set_message_combiner (); void fix_tex_coord (VERTEX **v); // positional and texel coordinate clipping #define CCLIP(ux,lx,ut,lt,uc,lc) \ if (ux > lx || lx < uc || ux > lc) { rdp.tri_n += 2; return; } \ if (ux < uc) { \ float p = (uc-ux)/(lx-ux); \ ut = p*(lt-ut)+ut; \ ux = uc; \ } \ if (lx > lc) { \ float p = (lc-ux)/(lx-ux); \ lt = p*(lt-ut)+ut; \ lx = lc; \ } #define CCLIP2(ux,lx,ut,lt,un,ln,uc,lc) \ if (ux > lx || lx < uc || ux > lc) { rdp.tri_n += 2; return; } \ if (ux < uc) { \ float p = (uc-ux)/(lx-ux); \ ut = p*(lt-ut)+ut; \ un = p*(ln-un)+un; \ ux = uc; \ } \ if (lx > lc) { \ float p = (lc-ux)/(lx-ux); \ lt = p*(lt-ut)+ut; \ ln = p*(ln-un)+un; \ lx = lc; \ } #if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) #include #define bswap32(x) _byteswap_ulong(x) #else static inline uint32_t bswap32(uint32_t val) { return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); } #endif #define ALOWORD(x) (*((uint16_t*)&(x))) // low word template static inline T __ROR__(T value, unsigned int count) { const unsigned int nbits = sizeof(T) * 8; count %= nbits; T low = value << (nbits - count); value >>= count; value |= low; return value; } // rotate left template static T __ROL__(T value, unsigned int count) { const unsigned int nbits = sizeof(T) * 8; count %= nbits; T high = value >> (nbits - count); value <<= count; value |= high; return value; } #endif // ifndef Util_H mupen64plus-video-glide64-src-2.6.0/src/compiletex.c000066400000000000000000000022201464507525600221640ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ #include int main(int argc, char **argv) { FILE *src, *dest; unsigned char a; src = fopen(argv[1], "rb"); dest = fopen(argv[2], "wb"); fprintf(dest, "unsigned char %s[] = {", argv[3]); while(fread(&a, 1, 1, src)) { fprintf(dest, "%d,\n", a); } fprintf(dest, "0};\n"); fclose(src); fclose(dest); return 0; } mupen64plus-video-glide64-src-2.6.0/src/cursor.h000066400000000000000000000236101464507525600213430ustar00rootroot00000000000000unsigned char cursor[] = {127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 128, 0, 128, 0, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 128, 0, 160, 31, 128, 0, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 128, 0, 160, 31, 160, 31, 128, 0, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 128, 0, 130, 31, 160, 31, 160, 31, 128, 0, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 128, 0, 130, 31, 160, 31, 160, 31, 160, 31, 128, 0, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 128, 0, 130, 31, 130, 31, 160, 31, 160, 31, 160, 31, 128, 0, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 128, 0, 130, 31, 130, 31, 160, 31, 160, 31, 160, 31, 160, 31, 128, 0, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 128, 0, 130, 31, 130, 31, 130, 31, 160, 31, 160, 31, 160, 31, 160, 31, 128, 0, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 128, 0, 130, 31, 130, 31, 130, 31, 160, 31, 160, 31, 160, 31, 160, 31, 160, 31, 128, 0, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 128, 0, 130, 31, 130, 31, 130, 31, 130, 31, 160, 31, 128, 0, 128, 0, 128, 0, 128, 0, 128, 0, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 128, 0, 130, 31, 130, 31, 128, 0, 130, 31, 160, 31, 128, 0, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 128, 0, 130, 31, 128, 0, 127, 255, 128, 0, 130, 31, 160, 31, 128, 0, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 128, 0, 128, 0, 127, 255, 127, 255, 128, 0, 130, 31, 160, 31, 128, 0, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 128, 0, 127, 255, 127, 255, 127, 255, 127, 255, 128, 0, 130, 31, 160, 31, 128, 0, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 128, 0, 130, 31, 160, 31, 128, 0, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 128, 0, 130, 31, 160, 31, 128, 0, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 128, 0, 130, 31, 160, 31, 128, 0, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 128, 0, 128, 0, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 127, 255, 0}; mupen64plus-video-glide64-src-2.6.0/src/cursor.tex000066400000000000000000000040001464507525600217040ustar00rootroot00000000000000ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ €ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€  €ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€‚  €ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€‚   €ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€‚‚   €ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€‚‚    €ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€‚‚‚    €ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€‚‚‚     €ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€‚‚‚‚ €€€€€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€‚‚€‚ €ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€‚€ÿ€‚ €ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€€ÿÿ€‚ €ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿÿÿÿ€‚ €ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€‚ €ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€‚ €ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€‚ €ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿmupen64plus-video-glide64-src-2.6.0/src/font.h000066400000000000000000000240201464507525600207700ustar00rootroot00000000000000unsigned char font[] = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 231, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 231, 143, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 231, 153, 201, 195, 39, 199, 231, 243, 207, 255, 255, 255, 255, 255, 249, 225, 243, 195, 195, 207, 129, 227, 129, 195, 195, 255, 255, 249, 255, 159, 195, 255, 195, 153, 201, 153, 37, 147, 231, 231, 231, 255, 255, 255, 255, 255, 249, 204, 227, 153, 153, 207, 159, 231, 249, 153, 153, 255, 255, 243, 255, 207, 153, 255, 195, 153, 128, 159, 137, 147, 231, 231, 231, 201, 231, 255, 255, 255, 243, 200, 131, 153, 153, 201, 159, 207, 243, 153, 153, 227, 227, 231, 255, 231, 153, 255, 195, 255, 201, 207, 243, 199, 255, 207, 243, 227, 231, 255, 255, 255, 243, 200, 243, 249, 249, 201, 159, 131, 243, 137, 153, 227, 227, 207, 129, 243, 243, 255, 231, 255, 201, 231, 231, 159, 255, 207, 243, 128, 129, 255, 129, 255, 231, 204, 243, 243, 227, 201, 131, 153, 231, 195, 153, 255, 255, 159, 255, 249, 231, 255, 231, 255, 201, 243, 207, 144, 255, 207, 243, 227, 231, 255, 255, 255, 231, 196, 243, 231, 249, 153, 249, 153, 231, 145, 193, 255, 255, 207, 129, 243, 231, 255, 255, 255, 128, 249, 145, 153, 255, 207, 243, 201, 231, 255, 255, 255, 207, 196, 243, 207, 153, 128, 249, 153, 207, 153, 243, 255, 255, 231, 255, 231, 255, 255, 231, 255, 201, 153, 164, 153, 255, 207, 243, 255, 255, 227, 255, 227, 207, 204, 243, 159, 153, 249, 243, 153, 207, 153, 231, 227, 227, 243, 255, 207, 231, 255, 231, 255, 201, 195, 228, 196, 255, 231, 231, 255, 255, 227, 255, 227, 159, 225, 243, 129, 195, 249, 135, 195, 207, 195, 199, 227, 227, 249, 255, 159, 231, 255, 255, 255, 255, 231, 241, 255, 255, 231, 231, 255, 255, 243, 255, 255, 159, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 243, 255, 255, 255, 255, 255, 255, 255, 255, 231, 255, 255, 255, 243, 207, 255, 255, 231, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 231, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 231, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 195, 255, 129, 231, 131, 195, 135, 129, 129, 195, 153, 195, 249, 153, 159, 156, 156, 195, 131, 195, 131, 195, 129, 153, 153, 156, 153, 153, 129, 195, 159, 195, 153, 255, 60, 195, 153, 153, 147, 159, 159, 153, 153, 231, 249, 153, 159, 156, 156, 153, 153, 153, 153, 153, 231, 153, 153, 156, 153, 153, 249, 207, 159, 243, 255, 255, 60, 153, 153, 153, 153, 159, 159, 153, 153, 231, 249, 147, 159, 136, 140, 153, 153, 153, 153, 159, 231, 153, 153, 156, 203, 153, 249, 207, 207, 243, 255, 255, 48, 153, 153, 159, 153, 159, 159, 159, 153, 231, 249, 147, 159, 148, 132, 153, 153, 153, 153, 207, 231, 153, 153, 148, 231, 153, 243, 207, 207, 243, 255, 255, 36, 153, 131, 159, 153, 131, 131, 159, 129, 231, 249, 135, 159, 148, 144, 153, 131, 153, 131, 231, 231, 153, 153, 148, 231, 195, 231, 207, 231, 243, 255, 255, 36, 129, 153, 159, 153, 159, 159, 145, 153, 231, 249, 147, 159, 148, 152, 153, 159, 153, 147, 243, 231, 153, 153, 148, 211, 231, 207, 207, 231, 243, 255, 255, 48, 153, 153, 153, 153, 159, 159, 153, 153, 231, 153, 147, 159, 156, 156, 153, 159, 153, 153, 249, 231, 153, 153, 201, 153, 231, 159, 207, 243, 243, 255, 255, 63, 153, 153, 153, 147, 159, 159, 153, 153, 231, 153, 153, 159, 156, 156, 153, 159, 153, 153, 153, 231, 153, 195, 201, 153, 231, 159, 207, 243, 243, 255, 255, 128, 153, 131, 195, 135, 129, 159, 193, 153, 195, 195, 153, 129, 156, 156, 195, 159, 195, 153, 195, 231, 195, 231, 201, 153, 231, 129, 207, 249, 243, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 243, 255, 255, 255, 255, 255, 255, 255, 255, 255, 207, 249, 243, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 249, 255, 255, 255, 255, 255, 255, 255, 255, 255, 207, 255, 243, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 195, 255, 195, 255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 199, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 231, 255, 255, 255, 255, 255, 255, 255, 255, 231, 243, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 243, 255, 159, 255, 249, 255, 225, 255, 159, 231, 243, 159, 135, 255, 255, 255, 255, 255, 255, 255, 207, 255, 255, 255, 255, 255, 255, 243, 231, 207, 255, 255, 255, 255, 159, 255, 249, 255, 207, 255, 159, 255, 255, 159, 231, 255, 255, 255, 255, 255, 255, 255, 207, 255, 255, 255, 255, 255, 255, 231, 231, 231, 255, 255, 255, 195, 131, 195, 193, 195, 207, 193, 131, 135, 195, 153, 231, 129, 131, 195, 131, 193, 153, 193, 129, 153, 153, 156, 153, 153, 129, 231, 231, 231, 255, 255, 255, 249, 153, 153, 153, 153, 207, 153, 153, 231, 243, 153, 231, 148, 153, 153, 153, 153, 145, 159, 207, 153, 153, 148, 153, 153, 249, 231, 231, 231, 255, 255, 255, 249, 153, 159, 153, 153, 129, 153, 153, 231, 243, 147, 231, 148, 153, 153, 153, 153, 143, 159, 207, 153, 153, 148, 195, 153, 243, 207, 231, 243, 255, 255, 255, 193, 153, 159, 153, 129, 207, 153, 153, 231, 243, 135, 231, 148, 153, 153, 153, 153, 159, 195, 207, 153, 153, 148, 231, 153, 231, 159, 231, 249, 255, 255, 255, 153, 153, 159, 153, 159, 207, 153, 153, 231, 243, 147, 231, 148, 153, 153, 153, 153, 159, 249, 207, 153, 153, 148, 195, 153, 207, 207, 231, 243, 255, 255, 255, 153, 153, 153, 153, 159, 207, 153, 153, 231, 243, 153, 231, 148, 153, 153, 153, 153, 159, 249, 207, 153, 195, 201, 153, 153, 159, 231, 231, 231, 255, 255, 255, 193, 131, 195, 193, 195, 207, 193, 153, 129, 243, 153, 129, 156, 153, 195, 131, 193, 159, 131, 225, 193, 231, 201, 153, 195, 129, 231, 231, 231, 255, 255, 255, 255, 255, 255, 255, 255, 255, 249, 255, 255, 243, 255, 255, 255, 255, 255, 159, 249, 255, 255, 255, 255, 255, 255, 255, 243, 255, 231, 231, 231, 255, 255, 255, 255, 255, 255, 255, 255, 255, 249, 255, 255, 243, 255, 255, 255, 255, 255, 159, 249, 255, 255, 255, 255, 255, 255, 255, 231, 255, 243, 231, 207, 255, 255, 255, 255, 255, 255, 255, 255, 255, 131, 255, 255, 135, 255, 255, 255, 255, 255, 159, 249, 255, 255, 255, 255, 255, 255, 255, 15, 255, 255, 231, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0}; mupen64plus-video-glide64-src-2.6.0/src/font.tex000066400000000000000000000040001464507525600213350ustar00rootroot00000000000000ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿçÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿçÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿç™ÉÃ'ÇçóÏÿÿÿÿÿùáóÃÃÏãÃÃÿÿùÿŸÃÿÙə%“çççÿÿÿÿÿùÌ㙙ϟçù™™ÿÿóÿÏ™ÿÙ€Ÿ‰“çççÉçÿÿÿóȃ™™ÉŸÏó™™ããçÿç™ÿÃÿÉÏóÇÿÏóãçÿÿÿóÈóùùÉŸƒó‰™ããÏóóÿçÿÉççŸÿÏó€ÿÿçÌóóãɃ™çÙÿÿŸÿùçÿçÿÉóÏÿÏóãçÿÿÿçÄóçù™ù™ç‘ÁÿÿÏóçÿÿÿ€ù‘™ÿÏóÉçÿÿÿÏÄóÏ™€ù™Ï™óÿÿçÿçÿÿçÿÉ™¤™ÿÏóÿÿãÿãÏÌóŸ™ùó™Ï™çããóÿÏçÿçÿÉÃäÄÿççÿÿãÿãŸáóÃù‡ÃÏÃÇããùÿŸçÿÿÿÿçñÿÿççÿÿóÿÿŸÿÿÿÿÿÿÿÿÿÿÿóÿÿÿÿÿÿÿÿçÿÿÿóÏÿÿçÿÿÿÿÿÿÿÿÿÿÿÿÿÿçÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿçÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÃÿçƒÃ‡Ã™Ãù™ŸœœÃƒÃƒÃ™™œ™™ÃŸÃ™ÿ<Ù™“ŸŸ™™çù™Ÿœœ™™™™™ç™™œ™™ùÏŸóÿÿ<™™™™ŸŸ™™çù“ŸˆŒ™™™™Ÿç™™œË™ùÏÏóÿÿ0™™Ÿ™ŸŸŸ™çù“Ÿ”„™™™™Ïç™™”ç™óÏÏóÿÿ$™ƒŸ™ƒƒŸçù‡Ÿ”™ƒ™ƒçç™™”çÃçÏçóÿÿ$™Ÿ™ŸŸ‘™çù“Ÿ”˜™Ÿ™“óç™™”ÓçÏÏçóÿÿ0™™™™ŸŸ™™ç™“Ÿœœ™Ÿ™™ù癙əçŸÏóóÿÿ?™™™“ŸŸ™™ç™™Ÿœœ™Ÿ™™™ç™ÃÉ™çŸÏóóÿÿ€™ƒÃ‡ŸÁ™ÃÙœœÃŸÃ™ÃçÃçÉ™çÏùóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóÿÿÿÿÿÿÿÿÿÏùóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùÿÿÿÿÿÿÿÿÿÏÿóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÃÿÃÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÇÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿçÿÿÿÿÿÿÿÿçóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóÿŸÿùÿáÿŸçóŸ‡ÿÿÿÿÿÿÿÏÿÿÿÿÿÿóçÏÿÿÿÿŸÿùÿÏÿŸÿÿŸçÿÿÿÿÿÿÿÏÿÿÿÿÿÿçççÿÿÿÃÃÁÃÏÁƒ‡Ã™çƒÃƒÁ™Á™™œ™™çççÿÿÿù™™™™Ï™™çó™ç”™™™™‘ŸÏ™™”™™ùçççÿÿÿù™Ÿ™™™™çó“ç”™™™™ŸÏ™™”ÙóÏçóÿÿÿÁ™Ÿ™Ï™™çó‡ç”™™™™ŸÃÏ™™”ç™çŸçùÿÿÿ™™Ÿ™ŸÏ™™çó“ç”™™™™ŸùÏ™™”ÙÏÏçóÿÿÿ™™™™ŸÏ™™çó™ç”™™™™ŸùÏ™ÃÉ™™ŸçççÿÿÿÁƒÃÁÃÏÁ™ó™œ™ÃƒÁŸƒáÁçÉ™ÃçççÿÿÿÿÿÿÿÿÿùÿÿóÿÿÿÿÿŸùÿÿÿÿÿÿÿóÿçççÿÿÿÿÿÿÿÿÿùÿÿóÿÿÿÿÿŸùÿÿÿÿÿÿÿçÿóçÏÿÿÿÿÿÿÿÿÿƒÿÿ‡ÿÿÿÿÿŸùÿÿÿÿÿÿÿÿÿçÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿmupen64plus-video-glide64-src-2.6.0/src/gpl.txt000066400000000000000000000432061464507525600212030ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) 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 this service 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 make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. 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. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), 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 distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the 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 a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE 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. 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 convey 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 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision 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, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This 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 Library General Public License instead of this License. mupen64plus-video-glide64-src-2.6.0/src/m64p.h000066400000000000000000000070211464507525600206120ustar00rootroot00000000000000/****************************************************************************** * Glide64 - Glide video plugin for Nintendo 64 emulators. * https://github.com/mupen64plus/mupen64plus-video-glide64/ * * Copyright (C) 2010 Jon Ring * * 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 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *****************************************************************************/ #ifndef M64P_H #define M64P_H #define M64P_PLUGIN_PROTOTYPES 1 #include "m64p_types.h" #include "m64p_common.h" #include "m64p_plugin.h" #include "m64p_config.h" #include "m64p_vidext.h" #include #define PLUGIN_NAME "Glide64 Video Plugin" #define PLUGIN_VERSION 0x020600 #define VIDEO_PLUGIN_API_VERSION 0x020200 #define CONFIG_API_VERSION 0x020000 #define VIDEXT_API_VERSION 0x030000 #define VERSION_PRINTF_SPLIT(x) (((x) >> 16) & 0xffff), (((x) >> 8) & 0xff), ((x) & 0xff) void WriteLog(m64p_msg_level level, const char *msg, ...); //The Glide API originally used an integer to pick an enumerated resolution. //To accomodate arbitrary resolutions, pack it into a 32-bit struct //so we don't have to change function signatures union PackedScreenResolution { struct { int width : 16; int height : 15; int fullscreen : 1; }; int resolution; }; /* definitions of pointers to Core config functions */ extern ptr_ConfigOpenSection ConfigOpenSection; extern ptr_ConfigSetParameter ConfigSetParameter; extern ptr_ConfigGetParameter ConfigGetParameter; extern ptr_ConfigGetParameterHelp ConfigGetParameterHelp; extern ptr_ConfigSetDefaultInt ConfigSetDefaultInt; extern ptr_ConfigSetDefaultFloat ConfigSetDefaultFloat; extern ptr_ConfigSetDefaultBool ConfigSetDefaultBool; extern ptr_ConfigSetDefaultString ConfigSetDefaultString; extern ptr_ConfigGetParamInt ConfigGetParamInt; extern ptr_ConfigGetParamFloat ConfigGetParamFloat; extern ptr_ConfigGetParamBool ConfigGetParamBool; extern ptr_ConfigGetParamString ConfigGetParamString; extern ptr_ConfigGetSharedDataFilepath ConfigGetSharedDataFilepath; extern ptr_ConfigGetUserConfigPath ConfigGetUserConfigPath; extern ptr_ConfigGetUserDataPath ConfigGetUserDataPath; extern ptr_ConfigGetUserCachePath ConfigGetUserCachePath; extern ptr_VidExt_Init CoreVideo_Init; extern ptr_VidExt_Quit CoreVideo_Quit; extern ptr_VidExt_ListFullscreenModes CoreVideo_ListFullscreenModes; extern ptr_VidExt_SetVideoMode CoreVideo_SetVideoMode; extern ptr_VidExt_SetCaption CoreVideo_SetCaption; extern ptr_VidExt_ToggleFullScreen CoreVideo_ToggleFullScreen; extern ptr_VidExt_ResizeWindow CoreVideo_ResizeWindow; extern ptr_VidExt_GL_GetProcAddress CoreVideo_GL_GetProcAddress; extern ptr_VidExt_GL_SetAttribute CoreVideo_GL_SetAttribute; extern ptr_VidExt_GL_SwapBuffers CoreVideo_GL_SwapBuffers; #endif mupen64plus-video-glide64-src-2.6.0/src/osal_dynamiclib.h000066400000000000000000000034441464507525600231620ustar00rootroot00000000000000/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-core - osal/dynamiclib.h * * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2009 Richard Goedeken * * * * 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 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #if !defined(OSAL_DYNAMICLIB_H) #define OSAL_DYNAMICLIB_H #ifdef __cplusplus extern "C" { #endif #include "m64p_types.h" void * osal_dynlib_getproc(m64p_dynlib_handle LibHandle, const char *pccProcedureName); #ifdef __cplusplus } #endif #endif /* #define OSAL_DYNAMICLIB_H */ mupen64plus-video-glide64-src-2.6.0/src/osal_dynamiclib_unix.c000066400000000000000000000034731464507525600242220ustar00rootroot00000000000000/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-core - osal/dynamiclib_unix.c * * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2009 Richard Goedeken * * * * 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 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include "m64p_types.h" #include "osal_dynamiclib.h" void * osal_dynlib_getproc(m64p_dynlib_handle LibHandle, const char *pccProcedureName) { if (pccProcedureName == NULL) return NULL; return dlsym(LibHandle, pccProcedureName); } mupen64plus-video-glide64-src-2.6.0/src/osal_dynamiclib_win32.c000066400000000000000000000060551464507525600242000ustar00rootroot00000000000000/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus-ui-console - osal_dynamiclib_win32.c * * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2009 Richard Goedeken * * * * 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 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include "m64p_types.h" #include "osal_dynamiclib.h" m64p_error osal_dynlib_open(m64p_dynlib_handle *pLibHandle, const char *pccLibraryPath) { if (pLibHandle == NULL || pccLibraryPath == NULL) return M64ERR_INPUT_ASSERT; *pLibHandle = LoadLibrary(pccLibraryPath); if (*pLibHandle == NULL) { char *pchErrMsg; DWORD dwErr = GetLastError(); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &pchErrMsg, 0, NULL); fprintf(stderr, "LoadLibrary('%s') error: %s\n", pccLibraryPath, pchErrMsg); LocalFree(pchErrMsg); return M64ERR_INPUT_NOT_FOUND; } return M64ERR_SUCCESS; } void * osal_dynlib_getproc(m64p_dynlib_handle LibHandle, const char *pccProcedureName) { if (pccProcedureName == NULL) return NULL; return GetProcAddress(LibHandle, pccProcedureName); } m64p_error osal_dynlib_close(m64p_dynlib_handle LibHandle) { int rval = FreeLibrary(LibHandle); if (rval == 0) { char *pchErrMsg; DWORD dwErr = GetLastError(); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &pchErrMsg, 0, NULL); fprintf(stderr, "FreeLibrary() error: %s\n", pchErrMsg); LocalFree(pchErrMsg); return M64ERR_INTERNAL; } return M64ERR_SUCCESS; } mupen64plus-video-glide64-src-2.6.0/src/rdp.cpp000066400000000000000000003432611464507525600211550ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * Copyright (c) 2008 Günther * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** #define M64P_PLUGIN_PROTOTYPES 1 #include "m64p_types.h" #include "m64p_plugin.h" #include "m64p_config.h" #include "m64p_vidext.h" #include "3dmath.h" #include "Util.h" #include "Debugger.h" #include "Combine.h" #include "Util.h" #include "Ini.h" #include "Config.h" #include "Tmem.h" #include "TexCache.h" #include "TexCache.h" #include "TexBuffer.h" #include "CRC.h" #include "rdp.h" #ifndef _WIN32 #include #endif // _WIN32 char out_buf[2048]; DWORD frame_count; // frame counter BOOL ucode_error_report = TRUE; int wrong_tile = -1; int drawFlag = 1; // draw flag for rendering callback // global strings const char *ACmp[4] = { "NONE", "THRESHOLD", "UNKNOWN", "DITHER" }; const char *Mode0[16] = { "COMBINED", "TEXEL0", "TEXEL1", "PRIMITIVE", "SHADE", "ENVIORNMENT", "1", "NOISE", "0", "0", "0", "0", "0", "0", "0", "0" }; const char *Mode1[16] = { "COMBINED", "TEXEL0", "TEXEL1", "PRIMITIVE", "SHADE", "ENVIORNMENT", "CENTER", "K4", "0", "0", "0", "0", "0", "0", "0", "0" }; const char *Mode2[32] = { "COMBINED", "TEXEL0", "TEXEL1", "PRIMITIVE", "SHADE", "ENVIORNMENT", "SCALE", "COMBINED_ALPHA", "T0_ALPHA", "T1_ALPHA", "PRIM_ALPHA", "SHADE_ALPHA", "ENV_ALPHA", "LOD_FRACTION", "PRIM_LODFRAC", "K5", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0" }; const char *Mode3[8] = { "COMBINED", "TEXEL0", "TEXEL1", "PRIMITIVE", "SHADE", "ENVIORNMENT", "1", "0" }; const char *Alpha0[8] = { "COMBINED", "TEXEL0", "TEXEL1", "PRIMITIVE", "SHADE", "ENVIORNMENT", "1", "0" }; const char *Alpha2[8] = { "LOD_FRACTION", "TEXEL0", "TEXEL1", "PRIMITIVE", "SHADE", "ENVIORNMENT", "PRIM_LODFRAC", "0" }; //FIXME:unused? //const char *FBLa[] = { "G_BL_CLR_IN", "G_BL_CLR_MEM", "G_BL_CLR_BL", "G_BL_CLR_FOG" }; //const char *FBLb[] = { "G_BL_A_IN", "G_BL_A_FOG", "G_BL_A_SHADE", "G_BL_0" }; //const char *FBLc[] = { "G_BL_CLR_IN", "G_BL_CLR_MEM", "G_BL_CLR_BL", "G_BL_CLR_FOG"}; //const char *FBLd[] = { "G_BL_1MA", "G_BL_A_MEM", "G_BL_1", "G_BL_0" }; const char *str_zs[2] = { "G_ZS_PIXEL", "G_ZS_PRIM" }; const char *str_yn[2] = { "NO", "YES" }; const char *str_offon[2] = { "OFF", "ON" }; const char *str_cull[4] = { "DISABLE", "FRONT", "BACK", "BOTH" }; // I=intensity probably const char *str_format[8] = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" }; const char *str_size[4] = { "4bit", "8bit", "16bit", "32bit" }; const char *str_cm[4] = { "WRAP/NO CLAMP", "MIRROR/NO CLAMP", "WRAP/CLAMP", "MIRROR/CLAMP" }; //const char *str_lod[] = { "1", "2", "4", "8", "16", "32", "64", "128", "256" }; //const char *str_aspect[] = { "1x8", "1x4", "1x2", "1x1", "2x1", "4x1", "8x1" }; const char *str_filter[3] = { "Point Sampled", "Average (box)", "Bilinear" }; const char *str_tlut[4] = { "TT_NONE", "TT_UNKNOWN", "TT_RGBA_16", "TT_IA_16" }; const char *CIStatus[10] = { "ci_main", "ci_zimg", "ci_unknown", "ci_useless", "ci_old_copy", "ci_copy", "ci_copy_self", "ci_zcopy", "ci_aux", "ci_aux_copy" }; // ZIGGY // depth save/restore variables // 0 : normal mode // 1 : writing in normal depth buffer // 2 : writing in alternate depth buffer static int render_depth_mode; // ** RDP graphics functions ** static void undef(); static void spnoop(); static void rdp_noop(); static void rdp_texrect(); //static void rdp_texrectflip(); static void rdp_loadsync(); static void rdp_pipesync(); static void rdp_tilesync(); static void rdp_fullsync(); static void rdp_setkeygb(); static void rdp_setkeyr(); static void rdp_setconvert(); static void rdp_setscissor(); static void rdp_setprimdepth(); static void rdp_setothermode(); static void rdp_loadtlut(); static void rdp_settilesize(); static void rdp_loadblock(); static void rdp_loadtile(); static void rdp_settile(); static void rdp_fillrect(); static void rdp_setfillcolor(); static void rdp_setfogcolor(); static void rdp_setblendcolor(); static void rdp_setprimcolor(); static void rdp_setenvcolor(); static void rdp_setcombine(); static void rdp_settextureimage(); static void rdp_setdepthimage(); static void rdp_setcolorimage(); static void rdp_trifill(); static void rdp_trishade(); static void rdp_tritxtr(); static void rdp_trishadetxtr(); static void rdp_trifillz(); static void rdp_trishadez(); static void rdp_tritxtrz(); static void rdp_trishadetxtrz(); static void rsp_reserved0(); static void rsp_reserved1(); static void rsp_reserved2(); static void rsp_reserved3(); static void ys_memrect(); BYTE microcode[4096]; DWORD uc_crc; void microcheck (); // ** UCODE FUNCTIONS ** #include "Ucode00.h" #include "ucode01.h" #include "ucode02.h" #include "ucode03.h" #include "ucode04.h" #include "ucode05.h" #include "ucode06.h" #include "ucode07.h" #include "ucode08.h" #include "ucode.h" static BOOL reset = 0; static int old_ucode = -1; // rdp_reset - resets the RDP_E void rdp_reset () { reset = 1; rdp.model_i = 0; rdp.n_cached[0] = 0; rdp.n_cached[1] = 0; rdp.cur_cache[0] = NULL; rdp.cur_cache[1] = NULL; /* rdp.tmem_ptr[0] = offset_textures; rdp.tmem_ptr[1] = offset_textures; if (grTextureBufferExt) rdp.tmem_ptr[1] = TEXMEM_2MB_EDGE * 2; */ rdp.c_a0 = 0; rdp.c_b0 = 0; rdp.c_c0 = 0; rdp.c_d0 = 0; rdp.c_Aa0 = 0; rdp.c_Ab0 = 0; rdp.c_Ac0 = 0; rdp.c_Ad0 = 0; rdp.c_a1 = 0; rdp.c_b1 = 0; rdp.c_c1 = 0; rdp.c_d1 = 0; rdp.c_Aa1 = 0; rdp.c_Ab1 = 0; rdp.c_Ac1 = 0; rdp.c_Ad1 = 0; // Clear the palette CRC int i; for (i=0; i<16; i++) rdp.pal_8_crc[i] = 0; // Clear the palettes for (i=0; i<256; i++) rdp.pal_8[i] = 0; rdp.tlut_mode = 0; // Clear all segments ** VERY IMPORTANT FOR ZELDA ** for (i=0; i<16; i++) rdp.segment[i] = 0; for (i=0; i<512; i++) rdp.addr[i] = 0; // set all vertex numbers for (i=0; i>2; i++) { uc_crc += ((DWORD*)microcode)[i]; } FRDP_E ("crc: %08lx\n", uc_crc); #ifdef LOG_UCODE std::ofstream ucf; ucf.open ("ucode.txt", ios::out | ios::binary); char d; for (i=0; i<0x400000; i++) { d = ((char*)gfx.RDRAM)[i^3]; ucf.write (&d, 1); } ucf.close (); #endif char str[9]; sprintf (str, "%08lx", (unsigned long)uc_crc); INI_Open (); INI_FindSection ("UCODE"); FRDP("ucode = %s\n", str); int uc = INI_ReadInt (str, -2, 0); WriteLog(M64MSG_INFO, "ucode = %d\n", uc); if (uc == -2 && ucode_error_report) { Config_Open(); settings.ucode = Config_ReadInt ("ucode", "Force microcode", 0, FALSE, FALSE); ReleaseGfx (); WriteLog(M64MSG_ERROR, "Error: uCode crc not found in INI, using currently selected uCode\n\n%08lx", (unsigned long)uc_crc); ucode_error_report = FALSE; // don't report any more ucode errors from this game } else if (uc == -1 && ucode_error_report) { Config_Open(); settings.ucode = Config_ReadInt ("ucode", "Force microcode", 0, FALSE, FALSE); ReleaseGfx (); WriteLog(M64MSG_ERROR, "Error: Unsupported uCode!\n\ncrc: %08lx", (unsigned long)uc_crc); ucode_error_report = FALSE; // don't report any more ucode errors from this game } else { old_ucode = settings.ucode; settings.ucode = uc; FRDP("microcheck: old ucode: %d, new ucode: %d\n", old_ucode, uc); } } void drawNoFullscreenMessage() { LOG ("drawNoFullscreenMessage ()\n"); } static WORD yuv_to_rgb(BYTE y, BYTE u, BYTE v) { float r = y + (1.370705f * (v-128)); float g = y - (0.698001f * (v-128)) - (0.337633f * (u-128)); float b = y + (1.732446f * (u-128)); r *= 0.125f; g *= 0.125f; b *= 0.125f; //clipping the result if (r > 32) r = 32; if (g > 32) g = 32; if (b > 32) b = 32; if (r < 0) r = 0; if (g < 0) g = 0; if (b < 0) b = 0; WORD c = (WORD)(((WORD)(r) << 11) | ((WORD)(g) << 6) | ((WORD)(b) << 1) | 1); return c; } static void DrawYUVImageToFrameBuffer() { WORD width = (WORD)(rdp.yuv_lr_x - rdp.yuv_ul_x); WORD height = (WORD)(rdp.yuv_lr_y - rdp.yuv_ul_y); DWORD * mb = (DWORD*)(gfx.RDRAM+rdp.yuv_im_begin); //pointer to the first macro block WORD * cimg = (WORD*)(gfx.RDRAM+rdp.cimg); //yuv macro block contains 16x16 texture. we need to put it in the proper place inside cimg for (WORD y = 0; y < height; y+=16) { for (WORD x = 0; x < width; x+=16) { WORD *dst = cimg + x + y * rdp.ci_width; for (WORD h = 0; h < 16; h++) { for (WORD w = 0; w < 8; w++) { DWORD t = *(mb++); //each DWORD contains 2 pixels if ((x < rdp.ci_width) && (y < rdp.ci_height)) //clipping. texture image may be larger than color image { BYTE y0 = (BYTE)t&0xFF; BYTE v = (BYTE)(t>>8)&0xFF; BYTE y1 = (BYTE)(t>>16)&0xFF; BYTE u = (BYTE)(t>>24)&0xFF; *(dst++) = yuv_to_rgb(y0, u, v); *(dst++) = yuv_to_rgb(y1, u, v); } } dst += rdp.ci_width - 16; } mb += 64; //macro block is 768 bytes long, last 256 bytes are useless } } } static DWORD d_ul_x, d_ul_y, d_lr_x, d_lr_y; typedef struct { int ul_x, ul_y, lr_x, lr_y; } FB_PART; static void DrawPart(int scr_ul_x, int scr_ul_y, int prt_ul_x, int prt_ul_y, int width, int height, float scale_x, float scale_y) { WORD * dst = new WORD[width*height]; DWORD shift = ((d_ul_y+prt_ul_y) * rdp.ci_width + d_ul_x + prt_ul_x) << 1; WORD * src = (WORD*)(gfx.RDRAM+rdp.cimg+shift); WORD c; for (int y=0; y < height; y++) { for (int x=0; x < width; x++) { c = src[(int(x*scale_x)+int(y*scale_y)*rdp.ci_width)^1]; dst[x+y*width] = c?((c >> 1) | 0x8000):0; } } grLfbWriteRegion(GR_BUFFER_BACKBUFFER, scr_ul_x, scr_ul_y, GR_LFB_SRC_FMT_1555, width, height, FXTRUE, width<<1, dst); delete[] dst; } static void DrawFrameBufferToScreen() { FRDP("DrawFrameBufferToScreen. cimg: %08lx, ul_x: %d, uly: %d, lr_x: %d, lr_y: %d\n", rdp.cimg, d_ul_x, d_ul_y, d_lr_x, d_lr_y); if (!fullscreen) return; grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); grConstantColorValue (0xFFFFFFFF); grAlphaBlendFunction( GR_BLEND_SRC_ALPHA, GR_BLEND_ONE_MINUS_SRC_ALPHA, GR_BLEND_ONE, GR_BLEND_ZERO); rdp.update |= UPDATE_COMBINE; float scale_x_dst = (float)settings.scr_res_x / rdp.vi_width;//(float)std::max(rdp.frame_buffers[rdp.main_ci_index].width, rdp.ci_width); float scale_y_dst = (float)settings.scr_res_y / rdp.vi_height;//(float)std::max(rdp.frame_buffers[rdp.main_ci_index].height, rdp.ci_lower_bound); float scale_x_src = (float)rdp.vi_width / (float)settings.scr_res_x;//(float)std::max(rdp.frame_buffers[rdp.main_ci_index].width, rdp.ci_width); float scale_y_src = (float)rdp.vi_height / (float)settings.scr_res_y;//(float)std::max(rdp.frame_buffers[rdp.main_ci_index].height, rdp.ci_lower_bound); int src_width = d_lr_x - d_ul_x + 1; int src_height = d_lr_y - d_ul_y + 1; int dst_width, dst_height, ul_x, ul_y; if (!settings.fb_optimize_write || ((src_width < 33) && (src_height < 33))) { dst_width = int(src_width*scale_x_dst); dst_height = int(src_height*scale_y_dst); ul_x = int(d_ul_x*scale_x_dst); ul_y = int(d_ul_y*scale_y_dst); DrawPart(ul_x, ul_y, 0, 0, dst_width, dst_height, scale_x_src, scale_y_src); memset(gfx.RDRAM+rdp.cimg, 0, rdp.ci_width*rdp.ci_height*rdp.ci_size); return; } FB_PART parts[8]; int p; for (p = 0; p < 8; p++) { parts[p].lr_x = parts[p].lr_y = 0; parts[p].ul_x = parts[p].ul_y = 0xFFFF; } int num_of_parts = 0; int cur_part = 0; int most_left = d_ul_x; int most_right = d_lr_x; DWORD shift = (d_ul_y * rdp.ci_width + d_ul_x) << 1; WORD * src = (WORD*)(gfx.RDRAM+rdp.cimg+shift); for (int h = 0; h < src_height; h++) { cur_part = 0; int w = 0; while (w < src_width) { while (w < src_width) { if (src[(w+h*rdp.ci_width)^1] == 0) w++; else break; } if (w == src_width) break; if (num_of_parts == 0) //first part { parts[0].ul_x = w; most_left = w; parts[0].ul_y = h; cur_part = 0; } else if (w < most_left - 2) //new part { parts[num_of_parts].ul_x = w; most_left = w; parts[num_of_parts].ul_y = h; cur_part = num_of_parts; num_of_parts++; } else if (w > most_right + 2) //new part { parts[num_of_parts].ul_x = w; most_right = w; parts[num_of_parts].ul_y = h; cur_part = num_of_parts; num_of_parts++; } else { for (p = 0; p < num_of_parts; p++) { if ((w > parts[p].ul_x - 2) && (w < parts[p].lr_x+2)) { if (w < parts[p].ul_x) parts[p].ul_x = w; break; } } cur_part = p; } while (w < src_width) { if (src[(w+h*rdp.ci_width)^1] != 0) w++; else break; } if (num_of_parts == 0) //first part { parts[0].lr_x = w; most_right = w; num_of_parts++; } else { if (parts[cur_part].lr_x < w) parts[cur_part].lr_x = w; if (most_right < w) most_right = w; parts[cur_part].lr_y = h; } } } /* for (p = 0; p < num_of_parts; p++) { FRDP("part#%d ul_x: %d, ul_y: %d, lr_x: %d, lr_y: %d\n", p, parts[p].ul_x, parts[p].ul_y, parts[p].lr_x, parts[p].lr_y); } */ for (p = 0; p < num_of_parts; p++) { dst_width = int((parts[p].lr_x-parts[p].ul_x + 1)*scale_x_dst); dst_height = int((parts[p].lr_y-parts[p].ul_y + 1)*scale_y_dst); ul_x = int((d_ul_x+parts[p].ul_x)*scale_x_dst); ul_y = int((d_ul_y+parts[p].ul_y)*scale_y_dst); DrawPart(ul_x, ul_y, parts[p].ul_x, parts[p].ul_y, dst_width, dst_height, scale_x_src, scale_y_src); } memset(gfx.RDRAM+rdp.cimg, 0, rdp.ci_width*rdp.ci_height*rdp.ci_size); } #define RGBA16TO32(color) \ ((color&1)?0xFF:0) | \ ((DWORD)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) | \ ((DWORD)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) | \ ((DWORD)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8) static void CopyFrameBuffer (GrBuffer_t buffer = GR_BUFFER_BACKBUFFER) { if (!fullscreen) return; FRDP ("CopyFrameBuffer: %08lx... ", rdp.cimg); // don't bother to write the stuff in asm... the slow part is the read from video card, // not the copy. int width = rdp.ci_width;//*gfx.VI_WIDTH_REG; int height; if (settings.fb_smart && !settings.PPL) { int ind = (rdp.ci_count > 0)?rdp.ci_count-1:0; height = rdp.frame_buffers[ind].height; } else { height = rdp.ci_lower_bound; if (settings.PPL) height -= rdp.ci_upper_bound; } FRDP ("width: %d, height: %d... ", width, height); if (rdp.scale_x < 1.1f) { WORD * ptr_src = new WORD[width*height]; if (grLfbReadRegion(buffer, 0, 0,//rdp.ci_upper_bound, width, height, width<<1, ptr_src)) { WORD *ptr_dst = (WORD*)(gfx.RDRAM+rdp.cimg); DWORD *ptr_dst32 = (DWORD*)(gfx.RDRAM+rdp.cimg); WORD c; for (int y=0; y 0) c = (c&0xFFC0) | ((c&0x001F) << 1) | 1; } else { c = (c&0xFFC0) | ((c&0x001F) << 1) | 1; } if (rdp.ci_size == 2) ptr_dst[(x + y * width)^1] = c; else ptr_dst32[x + y * width] = RGBA16TO32(c); } } /* } else //8bit I or CI { BYTE *ptr_dst = (BYTE*)(gfx.RDRAM+rdp.cimg); WORD c; for (int y=0; y>5)&0x3F)/63.0f*85.0f); BYTE r = (BYTE)((float)((c>>11)&0x1F)/31.0f*85.0f); c = (c&0xFFC0) | ((c&0x001F) << 1) | 1; // FRDP("src: %08lx, dst: %d\n",c,(BYTE)(r+g+b)); ptr_dst[(x + y * width)^1] = (BYTE)(r+g+b); // ptr_dst[(x + y * width)^1] = (BYTE)((c>>8)&0xFF); } } } */ RDP ("ReadRegion. Framebuffer copy complete.\n"); } else { RDP ("Framebuffer copy failed.\n"); } delete[] ptr_src; } else { if (rdp.motionblur && settings.fb_hires) { return; } else { float scale_x = (float)settings.scr_res_x / rdp.vi_width;//(float)std::max(rdp.frame_buffers[rdp.main_ci_index].width, rdp.ci_width); float scale_y = (float)settings.scr_res_y / rdp.vi_height;//(float)std::max(rdp.frame_buffers[rdp.main_ci_index].height, rdp.ci_lower_bound); FRDP("width: %d, height: %d, ul_y: %d, lr_y: %d, scale_x: %f, scale_y: %f, ci_width: %d, ci_height: %d\n",width, height, rdp.ci_upper_bound, rdp.ci_lower_bound, scale_x, scale_y, rdp.ci_width, rdp.ci_height); GrLfbInfo_t info; info.size = sizeof(GrLfbInfo_t); // VP 888 disconnected for now if (1||rdp.ci_size <= 2) { if (grLfbLock (GR_LFB_READ_ONLY, buffer, GR_LFBWRITEMODE_565, GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)) { WORD *ptr_src = (WORD*)info.lfbPtr; WORD *ptr_dst = (WORD*)(gfx.RDRAM+rdp.cimg); DWORD *ptr_dst32 = (DWORD*)(gfx.RDRAM+rdp.cimg); WORD c; DWORD stride = info.strideInBytes>>1; BOOL read_alpha = settings.fb_read_alpha; if (settings.PM && rdp.frame_buffers[rdp.ci_count-1].status != ci_aux) read_alpha = FALSE; for (int y=0; y>1; for (int y=0; y 0) SwapOK = TRUE; rdp.updatescreen = 1; rdp.tri_n = 0; // 0 triangles so far this frame rdp.debug_n = 0; rdp.model_i = 0; // 0 matrices so far in stack //stack_size can be less then 32! Important for Silicon Vally. Thanks Orkin! rdp.model_stack_size = std::min((DWORD) 32, (*(DWORD*)(gfx.DMEM+0x0FE4))>>6); if (rdp.model_stack_size == 0) rdp.model_stack_size = 32; rdp.fb_drawn = rdp.fb_drawn_front = FALSE; rdp.update = 0x7FFFFFFF; // All but clear cache rdp.geom_mode = 0; rdp.acmp = 0; rdp.maincimg[1] = rdp.maincimg[0]; rdp.skip_drawing = FALSE; rdp.s2dex_tex_loaded = FALSE; fbreads_front = fbreads_back = 0; rdp.fog_multiplier = rdp.fog_offset = 0; rdp.zsrc = 0; if (cpu_fb_write == TRUE) DrawFrameBufferToScreen(); cpu_fb_write = FALSE; cpu_fb_read_called = FALSE; cpu_fb_write_called = FALSE; cpu_fb_ignore = FALSE; d_ul_x = 0xffff; d_ul_y = 0xffff; d_lr_x = 0; d_lr_y = 0; //analize possible frame buffer usage if (settings.fb_smart) DetectFrameBufferUsage(); if (!settings.lego || rdp.num_of_ci > 1) rdp.last_bg = 0; //* End of set states *// // Get the start of the display list and the length of it DWORD dlist_start = *(DWORD*)(gfx.DMEM+0xFF0); DWORD dlist_length = *(DWORD*)(gfx.DMEM+0xFF4); FRDP("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx, fbuf_width: %d, dlist start: %08lx, dlist_lenght: %d\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG, *gfx.VI_WIDTH_REG, dlist_start, dlist_length); FRDP_E("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG); if (settings.tonic && dlist_length < 16) { rdp_fullsync(); FRDP_E("DLIST is too short!\n"); return; } // Start executing at the start of the display list rdp.pc_i = 0; rdp.pc[rdp.pc_i] = dlist_start; rdp.dl_count = -1; rdp.halt = 0; DWORD a; // catches exceptions so that it doesn't freeze #ifdef CATCH_EXCEPTIONS try { #endif // MAIN PROCESSING LOOP do { // Get the address of the next command a = rdp.pc[rdp.pc_i] & BMASK; // Load the next command and its input rdp.cmd0 = ((DWORD*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit rdp.cmd1 = ((DWORD*)gfx.RDRAM)[(a>>2)+1]; // / // cmd2 and cmd3 are filled only when needed, by the function that needs them // Output the address before the command #ifdef LOG_COMMANDS FRDP ("%08lx (c0:%08lx, c1:%08lx): ", a, rdp.cmd0, rdp.cmd1); #else FRDP ("%08lx: ", a); #endif // Go to the next instruction rdp.pc[rdp.pc_i] = (a+8) & BMASK; #ifdef PERFORMANCE QueryPerformanceCounter ((LARGE_INTEGER*)&perf_cur); #endif // Process this instruction gfx_instruction[settings.ucode][rdp.cmd0>>24] (); // check DL counter if (rdp.dl_count != -1) { rdp.dl_count --; if (rdp.dl_count == 0) { rdp.dl_count = -1; RDP ("End of DL\n"); rdp.pc_i --; } } #ifdef PERFORMANCE QueryPerformanceCounter ((LARGE_INTEGER*)&perf_next); __int64 t = perf_next-perf_cur; sprintf (out_buf, "perf %08lx: %016I64d\n", a-8, t); rdp_log << out_buf; #endif } while (!rdp.halt); #ifdef CATCH_EXCEPTIONS } catch (...) { if (fullscreen) ReleaseGfx (); WriteLog(M64MSG_ERROR, "The GFX plugin caused an exception and has been disabled."); exception = TRUE; } #endif if (settings.fb_smart) { rdp.scale_x = rdp.scale_x_bak; rdp.scale_y = rdp.scale_y_bak; } if (settings.fb_read_always) { CopyFrameBuffer (); } if (rdp.yuv_image) { DrawYUVImageToFrameBuffer(); rdp.yuv_image = FALSE; // FRDP("yuv image draw. ul_x: %f, ul_y: %f, lr_x: %f, lr_y: %f, begin: %08lx\n", // rdp.yuv_ul_x, rdp.yuv_ul_y, rdp.yuv_lr_x, rdp.yuv_lr_y, rdp.yuv_im_begin); rdp.yuv_ul_x = rdp.yuv_ul_y = rdp.yuv_lr_x = rdp.yuv_lr_y = 0; rdp.yuv_im_begin = 0x00FFFFFF; } if (rdp.cur_image) CloseTextureBuffer(rdp.read_whole_frame && (settings.PM || rdp.swap_ci_index >= 0)); if (settings.TGR2 && rdp.vi_org_reg != *gfx.VI_ORIGIN_REG && CI_SET) { newSwapBuffers (); CI_SET = FALSE; } RDP("ProcessDList end\n"); } #ifdef __cplusplus } #endif // undef - undefined instruction, always ignore static void undef() { FRDP_E("** undefined ** (%08lx)\n", rdp.cmd0); FRDP("** undefined ** (%08lx) - IGNORED\n", rdp.cmd0); #ifdef _FINAL_RELEASE_ *gfx.MI_INTR_REG |= 0x20; gfx.CheckInterrupts(); rdp.halt = 1; #endif } // spnoop - no operation, always ignore static void spnoop() { RDP("spnoop\n"); } // noop - no operation, always ignore static void rdp_noop() { RDP("noop\n"); } static void ys_memrect () { DWORD tile = (WORD)((rdp.cmd1 & 0x07000000) >> 24); DWORD lr_x = (WORD)((rdp.cmd0 & 0x00FFF000) >> 14); DWORD lr_y = (WORD)((rdp.cmd0 & 0x00000FFF) >> 2); DWORD ul_x = (WORD)((rdp.cmd1 & 0x00FFF000) >> 14); DWORD ul_y = (WORD)((rdp.cmd1 & 0x00000FFF) >> 2); rdp.pc[rdp.pc_i] += 16; // texrect is 196-bit if (lr_y > rdp.scissor_o.lr_y) lr_y = rdp.scissor_o.lr_y; FRDP ("memrect (%d, %d, %d, %d), ci_width: %d\n", ul_x, ul_y, lr_x, lr_y, rdp.ci_width); DWORD y, width = lr_x - ul_x; DWORD texaddr = rdp.addr[rdp.tiles[tile].t_mem]; DWORD tex_width = rdp.tiles[tile].line << 3; for (y = ul_y; y < lr_y; y++) { BYTE *src = gfx.RDRAM + texaddr + (y - ul_y) * tex_width; BYTE *dst = gfx.RDRAM + rdp.cimg + ul_x + y * rdp.ci_width; memcpy (dst, src, width); } } static void pm_palette_mod () { BYTE envr = (BYTE)((float)((rdp.env_color >> 24)&0xFF)/255.0f*31.0f); BYTE envg = (BYTE)((float)((rdp.env_color >> 16)&0xFF)/255.0f*31.0f); BYTE envb = (BYTE)((float)((rdp.env_color >> 8)&0xFF)/255.0f*31.0f); WORD env16 = (WORD)((envr<<11)|(envg<<6)|(envb<<1)|1); BYTE prmr = (BYTE)((float)((rdp.prim_color >> 24)&0xFF)/255.0f*31.0f); BYTE prmg = (BYTE)((float)((rdp.prim_color >> 16)&0xFF)/255.0f*31.0f); BYTE prmb = (BYTE)((float)((rdp.prim_color >> 8)&0xFF)/255.0f*31.0f); WORD prim16 = (WORD)((prmr<<11)|(prmg<<6)|(prmb<<1)|1); WORD * dst = (WORD*)(gfx.RDRAM+rdp.cimg); for (int i = 0; i < 16; i++) { dst[i^1] = (rdp.pal_8[i]&1) ? prim16 : env16; } RDP("Texrect palette modification\n"); } static void rdp_texrect() { DWORD a = rdp.pc[rdp.pc_i]; rdp.cmd2 = ((DWORD*)gfx.RDRAM)[(a>>2)+1]; rdp.cmd3 = ((DWORD*)gfx.RDRAM)[(a>>2)+3]; if (settings.ASB) //modified Rice's hack for All-Star Baseball games { DWORD dwHalf1 = (((DWORD*)gfx.RDRAM)[(a>>2)+0]) >> 24; if ((dwHalf1 != 0xF1) && (dwHalf1 != 0xb3)) { rdp.pc[rdp.pc_i] += 16; } else { rdp.pc[rdp.pc_i] += 8; rdp.cmd3 = rdp.cmd2; rdp.cmd2 = 0; } } else if (settings.yoshi && settings.ucode == 6) { ys_memrect(); return; } else { rdp.pc[rdp.pc_i] += 16; // texrect is 196-bit } if (rdp.skip_drawing || (!settings.fb_smart && (rdp.cimg == rdp.zimg))) { if (settings.PM && rdp.ci_status == ci_useless) { pm_palette_mod (); } else { RDP("Texrect skipped\n"); } return; } if ((settings.ucode == 8) && rdp.cur_image && rdp.cur_image->format) { //FRDP("Wrong Texrect. texaddr: %08lx, cimg: %08lx, cimg_end: %08lx\n", rdp.timg.addr, rdp.maincimg[1].addr, rdp.maincimg[1].addr+rdp.ci_width*rdp.ci_height*rdp.ci_size); RDP("Shadow texrect is skipped.\n"); rdp.tri_n += 2; return; } WORD ul_x = (WORD)((rdp.cmd1 & 0x00FFF000) >> 14); WORD ul_y = (WORD)((rdp.cmd1 & 0x00000FFF) >> 2); WORD lr_x = (WORD)((rdp.cmd0 & 0x00FFF000) >> 14); WORD lr_y = (WORD)((rdp.cmd0 & 0x00000FFF) >> 2); if (ul_x >= lr_x) return; if (rdp.cycle_mode > 1 || settings.increase_texrect_edge) { lr_x++; lr_y++; } if (ul_y == lr_y) { lr_y ++; } //* if (rdp.hires_tex && settings.fb_optimize_texrect) { if (!rdp.hires_tex->drawn) { DRAWIMAGE d; d.imageX = 0; d.imageW = (WORD)rdp.hires_tex->width; d.frameX = ul_x; d.frameW = (WORD)(rdp.hires_tex->width);//(WORD)(ul_x + rdp.hires_tex->width);//lr_x; d.imageY = 0; d.imageH = (WORD)rdp.hires_tex->height; d.frameY = ul_y; d.frameH = (WORD)(rdp.hires_tex->height);//(ul_y + rdp.hires_tex->height); FRDP("texrect. ul_x: %d, ul_y: %d, lr_x: %d, lr_y: %d, width: %d, height: %d\n", ul_x, ul_y, lr_x, lr_y, rdp.hires_tex->width, rdp.hires_tex->height); d.scaleX = 1.0f; d.scaleY = 1.0f; DrawHiresImage(&d, rdp.hires_tex->width == rdp.ci_width); rdp.hires_tex->drawn = TRUE; } return; } //*/ // framebuffer workaround for Zelda: MM LOT if ((rdp.othermode_l & 0xFFFF0000) == 0x0f5a0000) return; /*Gonetz*/ //hack for Zelda MM. it removes black texrects which cover all geometry in "Link meets Zelda" cut scene if (settings.zelda && rdp.timg.addr >= rdp.cimg && rdp.timg.addr < rdp.ci_end) { FRDP("Wrong Texrect. texaddr: %08lx, cimg: %08lx, cimg_end: %08lx\n", rdp.cur_cache[0]->addr, rdp.cimg, rdp.cimg+rdp.ci_width*rdp.ci_height*2); rdp.tri_n += 2; return; } //* //hack for Banjo2. it removes black texrects under Banjo if (!settings.fb_hires && ((rdp.cycle1 << 16) | (rdp.cycle2 & 0xFFFF)) == 0xFFFFFFFF && (rdp.othermode_l & 0xFFFF0000) == 0x00500000) { rdp.tri_n += 2; return; } //*/ //* //remove motion blur in night vision if ((settings.ucode == 7) && (rdp.maincimg[1].addr != rdp.maincimg[0].addr) && (rdp.timg.addr >= rdp.maincimg[1].addr) && (rdp.timg.addr < (rdp.maincimg[1].addr+rdp.ci_width*rdp.ci_height*rdp.ci_size))) { if (settings.fb_smart) if (rdp.frame_buffers[rdp.ci_count-1].status == ci_copy_self || !settings.fb_motionblur) { // FRDP("Wrong Texrect. texaddr: %08lx, cimg: %08lx, cimg_end: %08lx\n", rdp.timg.addr, rdp.maincimg[1], rdp.maincimg[1]+rdp.ci_width*rdp.ci_height*rdp.ci_size); RDP("Wrong Texrect.\n"); rdp.tri_n += 2; return; } } //*/ int i; DWORD tile = (WORD)((rdp.cmd1 & 0x07000000) >> 24); // update MUST be at the beginning, b/c of update_scissor if (rdp.cycle_mode == 2) { rdp.tex = 1; rdp.allow_combine = 0; cmb.tmu1_func = cmb.tmu0_func = GR_COMBINE_FUNCTION_LOCAL; cmb.tmu1_fac = cmb.tmu0_fac = GR_COMBINE_FACTOR_NONE; cmb.tmu1_a_func = cmb.tmu0_a_func = GR_COMBINE_FUNCTION_LOCAL; cmb.tmu1_a_fac = cmb.tmu0_a_fac = GR_COMBINE_FACTOR_NONE; cmb.tmu1_invert = cmb.tmu0_invert = FXFALSE; cmb.tmu1_a_invert = cmb.tmu0_a_invert = FXFALSE; } rdp.texrecting = 1; DWORD prev_tile = rdp.cur_tile; rdp.cur_tile = tile; rdp.update |= UPDATE_COMBINE; update (); rdp.texrecting = 0; rdp.allow_combine = 1; if (!rdp.cur_cache[0]) { rdp.cur_tile = prev_tile; rdp.tri_n += 2; return; } // **** // ** Texrect offset by Gugaman ** float off_x = (float)((short)((rdp.cmd2 & 0xFFFF0000) >> 16)) / 32.0f; if ((int(off_x) == 512) && (rdp.timg.width < 512)) off_x = 0.0f; float off_y = (float)((short)(rdp.cmd2 & 0x0000FFFF)) / 32.0f; float dsdx = (float)((short)((rdp.cmd3 & 0xFFFF0000) >> 16)) / 1024.0f; float dtdy = (float)((short)(rdp.cmd3 & 0x0000FFFF)) / 1024.0f; if (rdp.cycle_mode == 2) dsdx /= 4.0f; float s_ul_x = ul_x * rdp.scale_x + rdp.offset_x; float s_lr_x = lr_x * rdp.scale_x + rdp.offset_x; float s_ul_y = ul_y * rdp.scale_y + rdp.offset_y; float s_lr_y = lr_y * rdp.scale_y + rdp.offset_y; FRDP("texrect (%d, %d, %d, %d), tile: %d, #%d, #%d\n", ul_x, ul_y, lr_x, lr_y, tile, rdp.tri_n, rdp.tri_n+1); FRDP ("(%f, %f) -> (%f, %f), s: (%d, %d) -> (%d, %d)\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y, rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y); FRDP("\toff_x: %f, off_y: %f, dsdx: %f, dtdy: %f\n", off_x, off_y, dsdx, dtdy); float off_size_x; float off_size_y; if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip { off_size_x = (float)((lr_y - ul_y - 1) * dsdx); off_size_y = (float)((lr_x - ul_x - 1) * dtdy); } else { off_size_x = (float)((lr_x - ul_x - 1) * dsdx); off_size_y = (float)((lr_y - ul_y - 1) * dtdy); } float lr_u0, lr_v0, ul_u0, ul_v0, lr_u1, lr_v1, ul_u1, ul_v1; if (rdp.cur_cache[0] && (rdp.tex & 1)) { float sx=1, sy=1; if (rdp.tiles[rdp.cur_tile].shift_s) { if (rdp.tiles[rdp.cur_tile].shift_s > 10) sx = (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_s)); else sx = (float)1.0f/(1 << rdp.tiles[rdp.cur_tile].shift_s); } if (rdp.tiles[rdp.cur_tile].shift_t) { if (rdp.tiles[rdp.cur_tile].shift_t > 10) sy = (float)(1 << (16 - rdp.tiles[rdp.cur_tile].shift_t)); else sy = (float)1.0f/(1 << rdp.tiles[rdp.cur_tile].shift_t); } if (rdp.hires_tex && rdp.hires_tex->tile == 0) { off_x += rdp.hires_tex->u_shift;// + rdp.tiles[0].ul_s; //commented for Paper Mario motion blur off_y += rdp.hires_tex->v_shift;// + rdp.tiles[0].ul_t; FRDP("hires_tex ul_s: %d, ul_t: %d, off_x: %f, off_y: %f\n", rdp.tiles[0].ul_s, rdp.tiles[0].ul_t, off_x, off_y); ul_u0 = off_x * sx; ul_v0 = off_y * sy; lr_u0 = ul_u0 + off_size_x * sx; lr_v0 = ul_v0 + off_size_y * sy; ul_u0 *= rdp.hires_tex->u_scale; ul_v0 *= rdp.hires_tex->v_scale; lr_u0 *= rdp.hires_tex->u_scale; lr_v0 *= rdp.hires_tex->v_scale; FRDP("hires_tex ul_u0: %f, ul_v0: %f, lr_u0: %f, lr_v0: %f\n", ul_u0, ul_v0, lr_u0, lr_v0); } else { ul_u0 = off_x * sx; ul_v0 = off_y * sy; ul_u0 -= rdp.tiles[rdp.cur_tile].f_ul_s; ul_v0 -= rdp.tiles[rdp.cur_tile].f_ul_t; lr_u0 = ul_u0 + off_size_x * sx; lr_v0 = ul_v0 + off_size_y * sy; ul_u0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_x * ul_u0; lr_u0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_x * lr_u0; ul_v0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_y * ul_v0; lr_v0 = rdp.cur_cache[0]->c_off + rdp.cur_cache[0]->c_scl_y * lr_v0; } } else { ul_u0 = ul_v0 = lr_u0 = lr_v0 = 0; } if (rdp.cur_cache[1] && (rdp.tex & 2)) { float sx=1, sy=1; if (rdp.tiles[rdp.cur_tile+1].shift_s) { if (rdp.tiles[rdp.cur_tile+1].shift_s > 10) sx = (float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_s)); else sx = (float)1.0f/(1 << rdp.tiles[rdp.cur_tile+1].shift_s); } if (rdp.tiles[rdp.cur_tile+1].shift_t) { if (rdp.tiles[rdp.cur_tile+1].shift_t > 10) sy = 1;//(float)(1 << (16 - rdp.tiles[rdp.cur_tile+1].shift_t)); else sy = (float)1.0f/(1 << rdp.tiles[rdp.cur_tile+1].shift_t); } if (rdp.hires_tex && rdp.hires_tex->tile == 1) { off_x += rdp.hires_tex->u_shift;// + rdp.tiles[0].ul_s; //commented for Paper Mario motion blur off_y += rdp.hires_tex->v_shift;// + rdp.tiles[0].ul_t; FRDP("hires_tex ul_s: %d, ul_t: %d, off_x: %f, off_y: %f\n", rdp.tiles[0].ul_s, rdp.tiles[0].ul_t, off_x, off_y); ul_u1 = off_x * sx; ul_v1 = off_y * sy; lr_u1 = ul_u1 + off_size_x * sx; lr_v1 = ul_v1 + off_size_y * sy; ul_u1 *= rdp.hires_tex->u_scale; ul_v1 *= rdp.hires_tex->v_scale; lr_u1 *= rdp.hires_tex->u_scale; lr_v1 *= rdp.hires_tex->v_scale; FRDP("hires_tex ul_u1: %f, ul_v1: %f, lr_u1: %f, lr_v1: %f\n", ul_u0, ul_v0, lr_u0, lr_v0); } else { ul_u1 = off_x * sx; ul_v1 = off_y * sy; ul_u1 -= rdp.tiles[rdp.cur_tile+1].f_ul_s; ul_v1 -= rdp.tiles[rdp.cur_tile+1].f_ul_t; lr_u1 = ul_u1 + off_size_x * sx; lr_v1 = ul_v1 + off_size_y * sy; ul_u1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_x * ul_u1; lr_u1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_x * lr_u1; ul_v1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_y * ul_v1; lr_v1 = rdp.cur_cache[1]->c_off + rdp.cur_cache[1]->c_scl_y * lr_v1; } } else { ul_u1 = ul_v1 = lr_u1 = lr_v1 = 0; } rdp.cur_tile = prev_tile; // **** FRDP (" scissor: (%d, %d) -> (%d, %d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y); CCLIP2 (s_ul_x, s_lr_x, ul_u0, lr_u0, ul_u1, lr_u1, (float)rdp.scissor.ul_x, (float)rdp.scissor.lr_x); CCLIP2 (s_ul_y, s_lr_y, ul_v0, lr_v0, ul_v1, lr_v1, (float)rdp.scissor.ul_y, (float)rdp.scissor.lr_y); // CCLIP2 (s_lr_y, s_ul_y, lr_v0, ul_v0, lr_v1, ul_v1, (float)rdp.scissor.ul_y, (float)rdp.scissor.lr_y); FRDP (" draw at: (%f, %f) -> (%f, %f)\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y); // DO NOT SET CLAMP MODE HERE float Z = 1.0f; if (rdp.zsrc == 1 && (rdp.othermode_l & 0x00000030)) // othermode check makes sure it // USES the z-buffer. Otherwise it returns bad (unset) values for lot and telescope //in zelda:mm. { FRDP ("prim_depth = %d\n", rdp.prim_depth); Z = rdp.prim_depth; if (settings.increase_primdepth) Z += 8.0f; Z = ScaleZ(Z); grDepthBufferFunction (GR_CMP_LEQUAL); rdp.update |= UPDATE_ZBUF_ENABLED; } else { RDP ("no prim_depth used, using 1.0\n"); } VERTEX vstd[4] = { { s_ul_x, s_ul_y, Z, 1.0f, ul_u0, ul_v0, ul_u1, ul_v1, { 0, 0, 0, 0}, 255 }, { s_lr_x, s_ul_y, Z, 1.0f, lr_u0, ul_v0, lr_u1, ul_v1, { 0, 0, 0, 0}, 255 }, { s_ul_x, s_lr_y, Z, 1.0f, ul_u0, lr_v0, ul_u1, lr_v1, { 0, 0, 0, 0}, 255 }, { s_lr_x, s_lr_y, Z, 1.0f, lr_u0, lr_v0, lr_u1, lr_v1, { 0, 0, 0, 0}, 255 } }; if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip { vstd[1].u0 = ul_u0; vstd[1].v0 = lr_v0; vstd[1].u1 = ul_u1; vstd[1].v1 = lr_v1; vstd[2].u0 = lr_u0; vstd[2].v0 = ul_v0; vstd[2].u1 = lr_u1; vstd[2].v1 = ul_v1; } VERTEX *vptr = vstd; int n_vertices = 4; VERTEX *vnew = 0; // for (int j =0; j < 4; j++) // FRDP("v[%d] u0: %f, v0: %f, u1: %f, v1: %f\n", j, vstd[j].u0, vstd[j].v0, vstd[j].u1, vstd[j].v1); if (!rdp.hires_tex && rdp.cur_cache[0]->splits != 1) { // ** LARGE TEXTURE HANDLING ** // *VERY* simple algebra for texrects float min_u, min_x, max_u, max_x; if (vstd[0].u0 < vstd[1].u0) { min_u = vstd[0].u0; min_x = vstd[0].x; max_u = vstd[1].u0; max_x = vstd[1].x; } else { min_u = vstd[1].u0; min_x = vstd[1].x; max_u = vstd[0].u0; max_x = vstd[0].x; } int start_u_256, end_u_256; if (settings.ucode == 7) { start_u_256 = 0; end_u_256 = (lr_x - ul_x - 1)>>8; } else { start_u_256 = (int)min_u >> 8; end_u_256 = (int)max_u >> 8; } //FRDP(" min_u: %f, max_u: %f start: %d, end: %d\n", min_u, max_u, start_u_256, end_u_256); int splitheight = rdp.cur_cache[0]->splitheight; int num_verts_line = 2 + ((end_u_256-start_u_256)<<1); vnew = new VERTEX [num_verts_line << 1]; n_vertices = num_verts_line << 1; vptr = vnew; vnew[0] = vstd[0]; vnew[0].u0 -= 256.0f * start_u_256; vnew[0].v0 += splitheight * start_u_256; vnew[0].u1 -= 256.0f * start_u_256; vnew[0].v1 += splitheight * start_u_256; vnew[1] = vstd[2]; vnew[1].u0 -= 256.0f * start_u_256; vnew[1].v0 += splitheight * start_u_256; vnew[1].u1 -= 256.0f * start_u_256; vnew[1].v1 += splitheight * start_u_256; vnew[n_vertices-2] = vstd[1]; vnew[n_vertices-2].u0 -= 256.0f * end_u_256; vnew[n_vertices-2].v0 += splitheight * end_u_256; vnew[n_vertices-2].u1 -= 256.0f * end_u_256; vnew[n_vertices-2].v1 += splitheight * end_u_256; vnew[n_vertices-1] = vstd[3]; vnew[n_vertices-1].u0 -= 256.0f * end_u_256; vnew[n_vertices-1].v0 += splitheight * end_u_256; vnew[n_vertices-1].u1 -= 256.0f * end_u_256; vnew[n_vertices-1].v1 += splitheight * end_u_256; // find the equation of the line of u,x float m = (max_x - min_x) / (max_u - min_u); // m = delta x / delta u float b = min_x - m * min_u; // b = y - m * x for (i=start_u_256; iu0 *= z->q; z->v0 *= z->q; z->u1 *= z->q; z->v1 *= z->q; apply_shade_mods (z); } if (fullscreen) { grFogMode (GR_FOG_DISABLE); grClipWindow (0, 0, settings.res_x, settings.res_y); grCullMode (GR_CULL_DISABLE); if (rdp.cycle_mode == 2) { grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); grAlphaBlendFunction (GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ZERO, GR_BLEND_ZERO); if (rdp.othermode_l & 1) { grAlphaTestFunction (GR_CMP_GEQUAL); grAlphaTestReferenceValue (0x80); } else grAlphaTestFunction (GR_CMP_ALWAYS); rdp.update |= UPDATE_ALPHA_COMPARE | UPDATE_COMBINE; } ConvertCoordsConvert (vptr, n_vertices); if (settings.wireframe) { SetWireframeCol (); grDrawLine (&vstd[0], &vstd[2]); grDrawLine (&vstd[2], &vstd[1]); grDrawLine (&vstd[1], &vstd[0]); grDrawLine (&vstd[2], &vstd[3]); grDrawLine (&vstd[3], &vstd[1]); } else { grDrawVertexArrayContiguous (GR_TRIANGLE_STRIP, n_vertices, vptr, sizeof(VERTEX)); } if (debug.capture) { VERTEX vl[3]; vl[0] = vstd[0]; vl[1] = vstd[2]; vl[2] = vstd[1]; add_tri (vl, 3, TRI_TEXRECT); rdp.tri_n ++; vl[0] = vstd[2]; vl[1] = vstd[3]; vl[2] = vstd[1]; add_tri (vl, 3, TRI_TEXRECT); rdp.tri_n ++; } else rdp.tri_n += 2; if (settings.fog && (rdp.flags & FOG_ENABLED)) { grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT); } rdp.update |= UPDATE_CULL_MODE | UPDATE_VIEWPORT; } else { rdp.tri_n += 2; } delete[] vnew; } static void rdp_loadsync() { RDP("loadsync - ignored\n"); } static void rdp_pipesync() { RDP("pipesync - ignored\n"); } static void rdp_tilesync() { RDP("tilesync - ignored\n"); } static void rdp_fullsync() { // Set an interrupt to allow the game to continue *gfx.MI_INTR_REG |= 0x20; gfx.CheckInterrupts(); RDP("fullsync\n"); } static void rdp_setkeygb() { RDP_E("setkeygb - IGNORED\n"); RDP("setkeygb - IGNORED\n"); } static void rdp_setkeyr() { RDP_E("setkeyr - IGNORED\n"); RDP("setkeyr - IGNORED\n"); } static void rdp_setconvert() { /* rdp.YUV_C0 = 1.1647f ; rdp.YUV_C1 = 0.79931f ; rdp.YUV_C2 = -0.1964f ; rdp.YUV_C3 = -0.40651f; rdp.YUV_C4 = 1.014f ; */ rdp.K5 = (BYTE)(rdp.cmd1&0x1FF); RDP_E("setconvert - IGNORED\n"); RDP("setconvert - IGNORED\n"); } // // setscissor - sets the screen clipping rectangle // static void rdp_setscissor() { // clipper resolution is 320x240, scale based on computer resolution rdp.scissor_o.ul_x = /*min(*/(DWORD)(((rdp.cmd0 & 0x00FFF000) >> 14))/*, 320)*/; rdp.scissor_o.ul_y = /*min(*/(DWORD)(((rdp.cmd0 & 0x00000FFF) >> 2))/*, 240)*/; rdp.scissor_o.lr_x = /*min(*/(DWORD)(((rdp.cmd1 & 0x00FFF000) >> 14))/*, 320)*/; rdp.scissor_o.lr_y = /*min(*/(DWORD)(((rdp.cmd1 & 0x00000FFF) >> 2))/*, 240)*/; rdp.ci_upper_bound = rdp.scissor_o.ul_y; rdp.ci_lower_bound = rdp.scissor_o.lr_y; FRDP("setscissor: (%d,%d) -> (%d,%d)\n", rdp.scissor_o.ul_x, rdp.scissor_o.ul_y, rdp.scissor_o.lr_x, rdp.scissor_o.lr_y); rdp.update |= UPDATE_SCISSOR; } static void rdp_setprimdepth() { rdp.prim_depth = (WORD)((rdp.cmd1 >> 16) & 0x7FFF); FRDP("setprimdepth: %d\n", rdp.prim_depth); } static void rdp_setothermode() { #define F3DEX2_SETOTHERMODE(cmd,sft,len,data) { \ rdp.cmd0 = (cmd<<24) | ((32-(sft)-(len))<<8) | (((len)-1)); \ rdp.cmd1 = data; \ gfx_instruction[settings.ucode][cmd] (); \ } #define SETOTHERMODE(cmd,sft,len,data) { \ rdp.cmd0 = (cmd<<24) | ((sft)<<8) | (len); \ rdp.cmd1 = data; \ gfx_instruction[settings.ucode][cmd] (); \ } RDP("rdp_setothermode\n"); if ((settings.ucode == 2) || (settings.ucode == 8)) { int cmd0 = rdp.cmd0; F3DEX2_SETOTHERMODE(0xE2, 0, 32, rdp.cmd1); // SETOTHERMODE_L F3DEX2_SETOTHERMODE(0xE3, 0, 32, cmd0 & 0x00FFFFFF); // SETOTHERMODE_H } else { int cmd0 = rdp.cmd0; SETOTHERMODE(0xB9, 0, 32, rdp.cmd1); // SETOTHERMODE_L SETOTHERMODE(0xBA, 0, 32, cmd0 & 0x00FFFFFF); // SETOTHERMODE_H } } void load_palette (DWORD addr, WORD start, WORD count) { RDP ("Loading palette... "); WORD *dpal = rdp.pal_8 + start; WORD end = start+count; // WORD *spal = (WORD*)(gfx.RDRAM + (addr & BMASK)); for (WORD i=start; i>= 4; end = start + (count >> 4); for (WORD p = start; p < end; p++) { rdp.pal_8_crc[p] = CRC_Calculate( 0xFFFFFFFF, &rdp.pal_8[(p << 4)], 32 ); } rdp.pal_256_crc = CRC_Calculate( 0xFFFFFFFF, rdp.pal_8_crc, 64 ); RDP ("Done.\n"); } static void rdp_loadtlut() { DWORD tile = (rdp.cmd1 >> 24) & 0x07; WORD start = rdp.tiles[tile].t_mem - 256; // starting location in the palettes // WORD start = ((WORD)(rdp.cmd1 >> 2) & 0x3FF) + 1; WORD count = ((WORD)(rdp.cmd1 >> 14) & 0x3FF) + 1; // number to copy if (rdp.timg.addr + (count<<1) > BMASK) count = (WORD)((BMASK - rdp.timg.addr) >> 1); if (start+count > 256) count = 256-start; FRDP("loadtlut: tile: %d, start: %d, count: %d, from: %08lx\n", tile, start, count, rdp.timg.addr); load_palette (rdp.timg.addr, start, count); rdp.timg.addr += count << 1; } BOOL tile_set = 0; static void rdp_settilesize() { DWORD tile = (rdp.cmd1 >> 24) & 0x07; rdp.last_tile_size = tile; rdp.tiles[tile].f_ul_s = (float)((rdp.cmd0 >> 12) & 0xFFF) / 4.0f; rdp.tiles[tile].f_ul_t = (float)(rdp.cmd0 & 0xFFF) / 4.0f; int ul_s = (((WORD)(rdp.cmd0 >> 14)) & 0x03ff); int ul_t = (((WORD)(rdp.cmd0 >> 2 )) & 0x03ff); int lr_s = (((WORD)(rdp.cmd1 >> 14)) & 0x03ff); int lr_t = (((WORD)(rdp.cmd1 >> 2 )) & 0x03ff); if (lr_s == 0 && ul_s == 0) //pokemon puzzle league set such tile size wrong_tile = tile; else if (wrong_tile == (int)tile) wrong_tile = -1; if (settings.use_sts1_only) { // ** USE FIRST SETTILESIZE ONLY ** // This option helps certain textures while using the 'Alternate texture size method', // but may break others. (should help more than break) if (tile_set) { // coords in 10.2 format rdp.tiles[tile].ul_s = ul_s; rdp.tiles[tile].ul_t = ul_t; rdp.tiles[tile].lr_s = lr_s; rdp.tiles[tile].lr_t = lr_t; tile_set = 0; } } else { // coords in 10.2 format rdp.tiles[tile].ul_s = ul_s; rdp.tiles[tile].ul_t = ul_t; rdp.tiles[tile].lr_s = lr_s; rdp.tiles[tile].lr_t = lr_t; } // handle wrapping if (rdp.tiles[tile].lr_s < rdp.tiles[tile].ul_s) rdp.tiles[tile].lr_s += 0x400; if (rdp.tiles[tile].lr_t < rdp.tiles[tile].ul_t) rdp.tiles[tile].lr_t += 0x400; rdp.update |= UPDATE_TEXTURE; rdp.first = 1; if (tile == 0 && rdp.hires_tex) //if ((rdp.tiles[tile].size != 2) || ((rdp.timg.width == 1) && (rdp.hires_tex->width != (DWORD)(lr_s+1)))) if (((rdp.tiles[tile].format == 0) && (rdp.tiles[tile].size != 2)) || ((rdp.timg.width == 1) && (rdp.hires_tex->width != (DWORD)(lr_s+1)))) rdp.hires_tex = 0; if (rdp.hires_tex) { if (rdp.tiles[tile].format == 0 && rdp.hires_tex->format == 0) { if (tile == 1 && (DWORD)rdp.hires_tex->tmu != tile) SwapTextureBuffer(); rdp.hires_tex->tile = tile; rdp.hires_tex->info.format = GR_TEXFMT_RGB_565; FRDP ("hires_tex: tile: %d\n", tile); } else if (tile == 0) { rdp.hires_tex->info.format = GR_TEXFMT_ALPHA_INTENSITY_88; } } FRDP ("settilesize: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, lr_t: %d\n", tile, ul_s, ul_t, lr_s, lr_t); } static void CopyswapBlock(int *pDst, unsigned int cnt, unsigned int SrcOffs) { // copy and byteswap a block of 8-byte dwords int rem = SrcOffs & 3; if (rem == 0) { int *pSrc = (int *) ((uintptr_t) gfx.RDRAM + SrcOffs); for (unsigned int x = 0; x < cnt; x++) { int s1 = bswap32(*pSrc++); int s2 = bswap32(*pSrc++); *pDst++ = s1; *pDst++ = s2; } } else { // set source pointer to 4-byte aligned RDRAM location before the start int *pSrc = (int *) ((uintptr_t) gfx.RDRAM + (SrcOffs & 0xfffffffc)); // do the first partial 32-bit word int s0 = bswap32(*pSrc++); for (int x = 0; x < rem; x++) s0 >>= 8; for (int x = 4; x > rem; x--) { *((char *) pDst) = s0 & 0xff; pDst = (int *) ((char *) pDst + 1); s0 >>= 8; } // do one full 32-bit word s0 = bswap32(*pSrc++); *pDst++ = s0; // do 'cnt-1' 64-bit dwords for (unsigned int x = 0; x < cnt-1; x++) { int s1 = bswap32(*pSrc++); int s2 = bswap32(*pSrc++); *pDst++ = s1; *pDst++ = s2; } // do last partial 32-bit word s0 = bswap32(*pSrc++); for (; rem > 0; rem--) { *((char *) pDst) = s0 & 0xff; pDst = (int *) ((char *) pDst + 1); s0 >>= 8; } } } static void WordswapBlock(int *pDst, unsigned int cnt, unsigned int TileSize) { // Since it's not loading 32-bit textures as the N64 would, 32-bit textures need to // be swapped by 64-bits, not 32. if (TileSize == 3) { // swapblock64 dst, cnt for (unsigned int x = 0; x < cnt / 2; x++, pDst += 4) { long long s1 = ((long long *) pDst)[0]; long long s2 = ((long long *) pDst)[1]; ((long long *) pDst)[0] = s2; ((long long *) pDst)[1] = s1; } } else { // swapblock32 dst, cnt for (unsigned int x = 0; x < cnt; x++, pDst += 2) { int s1 = pDst[0]; int s2 = pDst[1]; pDst[0] = s2; pDst[1] = s1; } } } static void rdp_loadblock() { if (rdp.skip_drawing) { RDP("loadblock skipped\n"); return; } DWORD tile = (DWORD)((rdp.cmd1 >> 24) & 0x07); DWORD dxt = (DWORD)(rdp.cmd1 & 0x0FFF); rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr; // ** DXT is used for swapping every other line /* double fdxt = (double)0x8000000F/(double)((DWORD)(2047/(dxt-1))); // F for error DWORD _dxt = (DWORD)fdxt;*/ // 0x00000800 -> 0x80000000 (so we can check the sign bit instead of the 11th bit) DWORD _dxt = dxt << 20; DWORD addr = segoffset(rdp.timg.addr) & BMASK; // lr_s specifies number of 64-bit words to copy // 10.2 format WORD ul_s = (WORD)(rdp.cmd0 >> 14) & 0x3FF; WORD ul_t = (WORD)(rdp.cmd0 >> 2) & 0x3FF; WORD lr_s = (WORD)(rdp.cmd1 >> 14) & 0x3FF; rdp.tiles[tile].ul_s = ul_s; rdp.tiles[tile].ul_t = ul_t; rdp.tiles[tile].lr_s = lr_s; rdp.timg.set_by = 0; // load block // do a quick boundary check before copying to eliminate the possibility for exception if (ul_s >= 512) { lr_s = 1; // 1 so that it doesn't die on memcpy ul_s = 511; } if (ul_s+lr_s > 512) lr_s = 512-ul_s; if (addr+(lr_s<<3) > BMASK+1) lr_s = (WORD)((BMASK-addr)>>3); DWORD offs = rdp.timg.addr; DWORD cnt = lr_s+1; if (rdp.tiles[tile].size == 3) cnt <<= 1; //FIXME: unused? DWORD start_line = 0; // if (lr_s > 0) rdp.timg.addr += cnt << 3; int * pDst = (int *) ((uintptr_t)rdp.tmem+(rdp.tiles[tile].t_mem<<3)); // Load the block from RDRAM and byteswap it as it loads CopyswapBlock(pDst, cnt, offs); // now do 32-bit or 64-bit word swapping on every other row of data int dxt_accum = 0; while (cnt > 0) { // skip over unswapped blocks do { pDst += 2; if (--cnt == 0) break; dxt_accum += _dxt; } while (!(dxt_accum & 0x80000000)); // count number of blocks to swap if (cnt == 0) break; int swapcnt = 0; do { swapcnt++; if (--cnt == 0) break; dxt_accum += _dxt; } while (dxt_accum & 0x80000000); // do 32-bit or 64-bit swap operation on this block WordswapBlock(pDst, swapcnt, rdp.tiles[tile].size); pDst += swapcnt * 2; } rdp.update |= UPDATE_TEXTURE; FRDP ("loadblock: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, dxt: %08lx -> %08lx\n", tile, ul_s, ul_t, lr_s, dxt, _dxt); } static void rdp_loadtile() { if (rdp.skip_drawing) return; rdp.timg.set_by = 1; // load tile DWORD tile = (DWORD)((rdp.cmd1 >> 24) & 0x07); if (rdp.tiles[tile].format == 1) { rdp.yuv_image = TRUE; if (rdp.timg.addr < rdp.yuv_im_begin) rdp.yuv_im_begin = rdp.timg.addr; return; } rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr; WORD ul_s = (WORD)((rdp.cmd0 >> 14) & 0x03FF); WORD ul_t = (WORD)((rdp.cmd0 >> 2 ) & 0x03FF); WORD lr_s = (WORD)((rdp.cmd1 >> 14) & 0x03FF); WORD lr_t = (WORD)((rdp.cmd1 >> 2 ) & 0x03FF); if (lr_s < ul_s || lr_t < ul_t) return; if (wrong_tile >= 0) //there was a tile with zero length { rdp.tiles[wrong_tile].lr_s = lr_s; if (rdp.tiles[tile].size > rdp.tiles[wrong_tile].size) rdp.tiles[wrong_tile].lr_s <<= (rdp.tiles[tile].size - rdp.tiles[wrong_tile].size); else if (rdp.tiles[tile].size < rdp.tiles[wrong_tile].size) rdp.tiles[wrong_tile].lr_s >>= (rdp.tiles[wrong_tile].size - rdp.tiles[tile].size); rdp.tiles[wrong_tile].lr_t = lr_t; // wrong_tile = -1; } if (rdp.hires_tex)// && (rdp.tiles[tile].format == 0)) { FRDP("loadtile: hires_tex ul_s: %d, ul_t:%d\n", ul_s, ul_t); rdp.hires_tex->tile_uls = ul_s; rdp.hires_tex->tile_ult = ul_t; } if (settings.tonic && tile == 7) { rdp.tiles[0].ul_s = ul_s; rdp.tiles[0].ul_t = ul_t; rdp.tiles[0].lr_s = lr_s; rdp.tiles[0].lr_t = lr_t; } DWORD height = lr_t - ul_t + 1; // get height DWORD width = lr_s - ul_s + 1; DWORD wid_64 = rdp.tiles[tile].line; // CHEAT: it's very unlikely that it loads more than 1 32-bit texture in one command, // so i don't bother to write in two different places at once. Just load once with // twice as much data. if (rdp.tiles[tile].size == 3) wid_64 <<= 1; int line_n = rdp.timg.width; if (rdp.tiles[tile].size == 0) line_n >>= 1; else line_n <<= (rdp.tiles[tile].size-1); int offs = ul_t * line_n; offs += ul_s << rdp.tiles[tile].size >> 1; offs += rdp.timg.addr; if ((unsigned int) offs >= BMASK) return; // check if points to bad location DWORD size = width * height; if (rdp.tiles[tile].size == 0) size >>= 1; else size <<= (rdp.tiles[tile].size-1); if (offs + line_n*height > BMASK) height = (BMASK - offs) / line_n; int * pDst = (int *) ((uintptr_t)rdp.tmem+(rdp.tiles[tile].t_mem<<3)); int * pEnd = (int *) ((uintptr_t)rdp.tmem+4096 - (wid_64<<3)); for (unsigned int y = 0; y < height; y++) { if (pDst > pEnd) break; CopyswapBlock(pDst, wid_64, offs); if (y & 1) { WordswapBlock(pDst, wid_64, rdp.tiles[tile].size); } pDst += wid_64 * 2; offs += line_n; } FRDP("loadtile: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, lr_t: %d\n", tile, ul_s, ul_t, lr_s, lr_t); } static void rdp_settile() { tile_set = 1; // used to check if we only load the first settilesize rdp.first = 0; //rdp.cur_tile_n = (DWORD)((rdp.cmd1 >> 24) & 0x07); //rdp.cur_tile = &rdp.tiles[rdp.cur_tile_n]; rdp.last_tile = (DWORD)((rdp.cmd1 >> 24) & 0x07); TILE *tile = &rdp.tiles[rdp.last_tile]; tile->format = (BYTE)((rdp.cmd0 >> 21) & 0x07); tile->size = (BYTE)((rdp.cmd0 >> 19) & 0x03); tile->line = (WORD)((rdp.cmd0 >> 9) & 0x01FF); tile->t_mem = (WORD)(rdp.cmd0 & 0x1FF); tile->palette = (BYTE)((rdp.cmd1 >> 20) & 0x0F); tile->clamp_t = (BYTE)((rdp.cmd1 >> 19) & 0x01); tile->mirror_t = (BYTE)((rdp.cmd1 >> 18) & 0x01); tile->mask_t = (BYTE)((rdp.cmd1 >> 14) & 0x0F); tile->shift_t = (BYTE)((rdp.cmd1 >> 10) & 0x0F); tile->clamp_s = (BYTE)((rdp.cmd1 >> 9) & 0x01); tile->mirror_s = (BYTE)((rdp.cmd1 >> 8) & 0x01); tile->mask_s = (BYTE)((rdp.cmd1 >> 4) & 0x0F); tile->shift_s = (BYTE)(rdp.cmd1 & 0x0F); rdp.update |= UPDATE_TEXTURE; FRDP ("settile: tile: %d, format: %s, size: %s, line: %d, " "t_mem: %08lx, palette: %d, clamp_t/mirror_t: %s, mask_t: %d, " "shift_t: %d, clamp_s/mirror_s: %s, mask_s: %d, shift_s: %d\n", rdp.last_tile, str_format[tile->format], str_size[tile->size], tile->line, tile->t_mem, tile->palette, str_cm[(tile->clamp_t<<1)|tile->mirror_t], tile->mask_t, tile->shift_t, str_cm[(tile->clamp_s<<1)|tile->mirror_s], tile->mask_s, tile->shift_s); } // // fillrect - fills a rectangle // static void rdp_fillrect() { DWORD ul_x = ((rdp.cmd1 & 0x00FFF000) >> 14); DWORD ul_y = (rdp.cmd1 & 0x00000FFF) >> 2; DWORD lr_x = ((rdp.cmd0 & 0x00FFF000) >> 14) + 1; DWORD lr_y = ((rdp.cmd0 & 0x00000FFF) >> 2) + 1; if ((rdp.cimg == rdp.zimg) || (settings.fb_smart && rdp.frame_buffers[rdp.ci_count-1].status == ci_zimg)) { RDP ("Fillrect - cleared the depth buffer\n"); if (fullscreen) { grDepthMask (FXTRUE); grColorMask (FXFALSE, FXFALSE); grBufferClear (0, 0, 0xFFFF); grColorMask (FXTRUE, FXTRUE); rdp.update |= UPDATE_ZBUF_ENABLED; if (settings.fb_depth_clear) { ul_x = std::min(std::max(ul_x, rdp.scissor_o.ul_x), rdp.scissor_o.lr_x); lr_x = std::min(std::max(lr_x, rdp.scissor_o.ul_x), rdp.scissor_o.lr_x); ul_y = std::min(std::max(ul_y, rdp.scissor_o.ul_y), rdp.scissor_o.lr_y); lr_y = std::min(std::max(lr_y, rdp.scissor_o.ul_y), rdp.scissor_o.lr_y); //FIXME:unused? DWORD zi_height = lr_y - ul_y - 1; // rdp.zi_nb_pixels = rdp.zi_width * zi_height; rdp.zi_lry = lr_y - 1; rdp.zi_lrx = lr_x - 1; // FRDP ("zi_width: %d, zi_height: %d\n", rdp.zi_width, zi_height); DWORD fillrect_width_in_dwords = (lr_x-ul_x) >> 1; DWORD zi_width_in_dwords = rdp.zi_width >> 1; ul_x >>= 1; DWORD * dst = (DWORD*)(gfx.RDRAM+rdp.cimg); dst += ul_y * zi_width_in_dwords; for (DWORD y = ul_y; y < lr_y; y++) { for (DWORD x = ul_x; x < fillrect_width_in_dwords; x++) { dst[x] = rdp.fill_color; } dst += zi_width_in_dwords; } } } return; } if (rdp.skip_drawing) { RDP("Fillrect skipped\n"); return; } // Update scissor update_scissor (); if ((ul_x > lr_x) || (ul_y > lr_y)) return; if (settings.bomberman64 && (lr_x == rdp.ci_width) && (rdp.cimg == rdp.ocimg)) //bomberman64 hack return; if (rdp.cur_image && (rdp.cur_image->format != 0) && (rdp.cycle_mode == 3) && (rdp.cur_image->width == lr_x)) { DWORD color = rdp.fill_color; color = ((color&1)?0xFF:0) | ((DWORD)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) | ((DWORD)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) | ((DWORD)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8); grDepthMask (FXFALSE); grBufferClear (color, 0, 0xFFFF); grDepthMask (FXTRUE); rdp.update |= UPDATE_ZBUF_ENABLED; return; } if (settings.decrease_fillrect_edge && rdp.cycle_mode == 0) { lr_x--; lr_y--; } FRDP("fillrect (%d,%d) -> (%d,%d), cycle mode: %d, #%d, #%d\n", ul_x, ul_y, lr_x, lr_y, rdp.cycle_mode, rdp.tri_n, rdp.tri_n+1); FRDP("scissor (%d,%d) -> (%d,%d)\n", rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y); // KILL the floating point error with 0.01f DWORD s_ul_x = std::min(std::max((DWORD) (ul_x * rdp.scale_x + rdp.offset_x + 0.01f), rdp.scissor.ul_x), rdp.scissor.lr_x); DWORD s_lr_x = std::min(std::max((DWORD) (lr_x * rdp.scale_x + rdp.offset_x + 0.01f), rdp.scissor.ul_x), rdp.scissor.lr_x); DWORD s_ul_y = std::min(std::max((DWORD) (ul_y * rdp.scale_y + rdp.offset_y + 0.01f), rdp.scissor.ul_y), rdp.scissor.lr_y); DWORD s_lr_y = std::min(std::max((DWORD) (lr_y * rdp.scale_y + rdp.offset_y + 0.01f), rdp.scissor.ul_y), rdp.scissor.lr_y); if (s_lr_x < 0.0f) s_lr_x = 0; if (s_lr_y < 0.0f) s_lr_y = 0; if (s_ul_x > (float)settings.res_x) s_ul_x = settings.res_x; if (s_ul_y > (float)settings.res_y) s_ul_y = settings.res_y; FRDP (" - %d, %d, %d, %d\n", s_ul_x, s_ul_y, s_lr_x, s_lr_y); if (fullscreen) { grFogMode (GR_FOG_DISABLE); grClipWindow (0, 0, settings.res_x, settings.res_y); float Z = 1.0f; if (rdp.zsrc == 1 && (rdp.othermode_l & 0x00000030)) { Z = ScaleZ(rdp.prim_depth); grDepthBufferFunction (GR_CMP_LEQUAL); // grDepthMask (FXTRUE); FRDP ("prim_depth = %d\n", rdp.prim_depth); } else { grDepthBufferFunction (GR_CMP_ALWAYS); grDepthMask (FXFALSE); RDP ("no prim_depth used, using 1.0\n"); } // Draw the rectangle VERTEX v[4] = { { (float)s_ul_x, (float)s_ul_y, Z, 1.0f, 0,0,0,0, { 0,0,0,0 }, 0,0, 0,0,0,0 }, { (float)s_lr_x, (float)s_ul_y, Z, 1.0f, 0,0,0,0, { 0,0,0,0 }, 0,0, 0,0,0,0 }, { (float)s_ul_x, (float)s_lr_y, Z, 1.0f, 0,0,0,0, { 0,0,0,0 }, 0,0, 0,0,0,0 }, { (float)s_lr_x, (float)s_lr_y, Z, 1.0f, 0,0,0,0, { 0,0,0,0 }, 0,0, 0,0,0,0 } }; if (rdp.cycle_mode == 3) { DWORD color = (settings.fillcolor_fix) ? rdp.fill_color : (rdp.fill_color >> 16); if (settings.PM && rdp.frame_buffers[rdp.ci_count-1].status == ci_aux) { //background of auxilary frame buffers must have zero alpha. //make it black, set 0 alpha to plack pixels on frame buffer read color = 0; } else { color = ((color&1)?0xFF:0) | ((DWORD)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) | ((DWORD)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) | ((DWORD)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8); } grConstantColorValue (color); grColorCombine (GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE, FXFALSE); grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE, FXFALSE); grAlphaBlendFunction (GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO); rdp.update |= UPDATE_COMBINE; } else { Combine (); TexCache (); // (to update combiner) DWORD cmb_mode_c = (rdp.cycle1 << 16) | (rdp.cycle2 & 0xFFFF); DWORD cmb_mode_a = (rdp.cycle1 & 0x0FFF0000) | ((rdp.cycle2 >> 16) & 0x00000FFF); if (cmb_mode_c == 0x9fff9fff || cmb_mode_a == 0x09ff09ff) //shade { AllowShadeMods (v, 4); for (int k = 0; k < 4; k++) apply_shade_mods (&v[k]); } } grAlphaTestFunction (GR_CMP_ALWAYS); if (grStippleModeExt) grStippleModeExt(GR_STIPPLE_DISABLE); grCullMode(GR_CULL_DISABLE); if (settings.wireframe) { SetWireframeCol (); grDrawLine (&v[0], &v[2]); grDrawLine (&v[2], &v[1]); grDrawLine (&v[1], &v[0]); grDrawLine (&v[2], &v[3]); grDrawLine (&v[3], &v[1]); //grDrawLine (&v[1], &v[2]); } else { grDrawTriangle (&v[0], &v[2], &v[1]); grDrawTriangle (&v[2], &v[3], &v[1]); } if (debug.capture) { VERTEX v1[3]; v1[0] = v[0]; v1[1] = v[2]; v1[2] = v[1]; add_tri (v1, 3, TRI_FILLRECT); rdp.tri_n ++; v1[0] = v[2]; v1[1] = v[3]; add_tri (v1, 3, TRI_FILLRECT); rdp.tri_n ++; } else rdp.tri_n += 2; if (settings.fog && (rdp.flags & FOG_ENABLED)) { grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT); } rdp.update |= UPDATE_CULL_MODE | UPDATE_ALPHA_COMPARE | UPDATE_ZBUF_ENABLED; } else { rdp.tri_n += 2; } } // // setfillcolor - sets the filling color // static void rdp_setfillcolor() { rdp.fill_color = rdp.cmd1; rdp.update |= UPDATE_ALPHA_COMPARE | UPDATE_COMBINE; FRDP("setfillcolor: %08lx\n", rdp.cmd1); } static void rdp_setfogcolor() { rdp.fog_color = rdp.cmd1; rdp.update |= UPDATE_COMBINE | UPDATE_FOG_ENABLED; FRDP("setfogcolor - %08lx\n", rdp.cmd1); } static void rdp_setblendcolor() { rdp.blend_color = rdp.cmd1; rdp.update |= UPDATE_COMBINE; FRDP("setblendcolor: %08lx\n", rdp.cmd1); } static void rdp_setprimcolor() { rdp.prim_color = rdp.cmd1; rdp.prim_lodmin = (rdp.cmd0 >> 8) & 0xFF; rdp.prim_lodfrac = std::max(rdp.cmd0 & 0xFF, rdp.prim_lodmin); rdp.update |= UPDATE_COMBINE; FRDP("setprimcolor: %08lx, lodmin: %d, lodfrac: %d\n", rdp.cmd1, rdp.prim_lodmin, rdp.prim_lodfrac); } static void rdp_setenvcolor() { rdp.env_color = rdp.cmd1; rdp.update |= UPDATE_COMBINE; FRDP("setenvcolor: %08lx\n", rdp.cmd1); } static void rdp_setcombine() { rdp.c_a0 = (BYTE)((rdp.cmd0 >> 20) & 0xF); rdp.c_b0 = (BYTE)((rdp.cmd1 >> 28) & 0xF); rdp.c_c0 = (BYTE)((rdp.cmd0 >> 15) & 0x1F); rdp.c_d0 = (BYTE)((rdp.cmd1 >> 15) & 0x7); rdp.c_Aa0 = (BYTE)((rdp.cmd0 >> 12) & 0x7); rdp.c_Ab0 = (BYTE)((rdp.cmd1 >> 12) & 0x7); rdp.c_Ac0 = (BYTE)((rdp.cmd0 >> 9) & 0x7); rdp.c_Ad0 = (BYTE)((rdp.cmd1 >> 9) & 0x7); rdp.c_a1 = (BYTE)((rdp.cmd0 >> 5) & 0xF); rdp.c_b1 = (BYTE)((rdp.cmd1 >> 24) & 0xF); rdp.c_c1 = (BYTE)((rdp.cmd0 >> 0) & 0x1F); rdp.c_d1 = (BYTE)((rdp.cmd1 >> 6) & 0x7); rdp.c_Aa1 = (BYTE)((rdp.cmd1 >> 21) & 0x7); rdp.c_Ab1 = (BYTE)((rdp.cmd1 >> 3) & 0x7); rdp.c_Ac1 = (BYTE)((rdp.cmd1 >> 18) & 0x7); rdp.c_Ad1 = (BYTE)((rdp.cmd1 >> 0) & 0x7); rdp.cycle1 = (rdp.c_a0<<0) | (rdp.c_b0<<4) | (rdp.c_c0<<8) | (rdp.c_d0<<13)| (rdp.c_Aa0<<16)| (rdp.c_Ab0<<19)| (rdp.c_Ac0<<22)| (rdp.c_Ad0<<25); rdp.cycle2 = (rdp.c_a1<<0) | (rdp.c_b1<<4) | (rdp.c_c1<<8) | (rdp.c_d1<<13)| (rdp.c_Aa1<<16)| (rdp.c_Ab1<<19)| (rdp.c_Ac1<<22)| (rdp.c_Ad1<<25); rdp.update |= UPDATE_COMBINE; FRDP("setcombine\na0=%s b0=%s c0=%s d0=%s\nAa0=%s Ab0=%s Ac0=%s Ad0=%s\na1=%s b1=%s c1=%s d1=%s\nAa1=%s Ab1=%s Ac1=%s Ad1=%s\n", Mode0[rdp.c_a0], Mode1[rdp.c_b0], Mode2[rdp.c_c0], Mode3[rdp.c_d0], Alpha0[rdp.c_Aa0], Alpha1[rdp.c_Ab0], Alpha2[rdp.c_Ac0], Alpha3[rdp.c_Ad0], Mode0[rdp.c_a1], Mode1[rdp.c_b1], Mode2[rdp.c_c1], Mode3[rdp.c_d1], Alpha0[rdp.c_Aa1], Alpha1[rdp.c_Ab1], Alpha2[rdp.c_Ac1], Alpha3[rdp.c_Ad1]); } // // settextureimage - sets the source for an image copy // static void rdp_settextureimage() { static const char *format[] = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" }; static const char *size[] = { "4bit", "8bit", "16bit", "32bit" }; rdp.timg.format = (BYTE)((rdp.cmd0 >> 21) & 0x07); rdp.timg.size = (BYTE)((rdp.cmd0 >> 19) & 0x03); rdp.timg.width = (WORD)(1 + (rdp.cmd0 & 0x00000FFF)); rdp.timg.addr = segoffset(rdp.cmd1); rdp.s2dex_tex_loaded = TRUE; rdp.update |= UPDATE_TEXTURE; if (rdp.frame_buffers[rdp.ci_count-1].status == ci_copy_self && (rdp.timg.addr >= rdp.cimg) && (rdp.timg.addr < rdp.ci_end)) { if (!rdp.fb_drawn) { if (!rdp.cur_image) CopyFrameBuffer(); else if (rdp.frame_buffers[rdp.ci_count].status != ci_copy) CloseTextureBuffer(TRUE); rdp.fb_drawn = TRUE; } } if (settings.fb_hires) //search this texture among drawn texture buffers { if (settings.zelda) { if (rdp.timg.size == 2) FindTextureBuffer(rdp.timg.addr, rdp.timg.width); } else FindTextureBuffer(rdp.timg.addr, rdp.timg.width); } FRDP("settextureimage: format: %s, size: %s, width: %d, addr: %08lx\n", format[rdp.timg.format], size[rdp.timg.size], rdp.timg.width, rdp.timg.addr); } static void rdp_setdepthimage() { rdp.zimg = segoffset(rdp.cmd1) & BMASK; rdp.zi_width = rdp.ci_width; FRDP("setdepthimage - %08lx\n", rdp.zimg); } BOOL SwapOK = TRUE; static void RestoreScale() { FRDP("Return to original scale: x = %f, y = %f\n", rdp.scale_x_bak, rdp.scale_y_bak); rdp.scale_x = rdp.scale_x_bak; rdp.scale_y = rdp.scale_y_bak; // update_scissor(); rdp.view_scale[0] *= rdp.scale_x; rdp.view_scale[1] *= rdp.scale_y; rdp.view_trans[0] *= rdp.scale_x; rdp.view_trans[1] *= rdp.scale_y; rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR; //* if (fullscreen) { grDepthMask (FXFALSE); grBufferClear (0, 0, 0xFFFF); grDepthMask (FXTRUE); } //*/ } static DWORD swapped_addr = 0; static void rdp_setcolorimage() { render_depth_mode = 0; if (settings.fb_smart && (rdp.num_of_ci < NUMTEXBUF)) { COLOR_IMAGE & cur_fb = rdp.frame_buffers[rdp.ci_count]; COLOR_IMAGE & prev_fb = rdp.frame_buffers[rdp.ci_count-1]; COLOR_IMAGE & next_fb = rdp.frame_buffers[rdp.ci_count+1]; switch (cur_fb.status) { case ci_main: { if (rdp.ci_count == 0) { if (rdp.ci_status == ci_aux) //for PPL { float sx = rdp.scale_x; float sy = rdp.scale_y; rdp.scale_x = 1.0f; rdp.scale_y = 1.0f; CopyFrameBuffer (); rdp.scale_x = sx; rdp.scale_y = sy; } if (!settings.fb_hires) { if ((rdp.num_of_ci > 1) && (next_fb.status == ci_aux) && (next_fb.width >= cur_fb.width)) { rdp.scale_x = 1.0f; rdp.scale_y = 1.0f; } } else if (rdp.copy_ci_index && settings.PM) //tidal wave OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); } else if (!rdp.motionblur && settings.fb_hires && !SwapOK && (rdp.ci_count <= rdp.copy_ci_index)) { if (next_fb.status == ci_aux_copy) OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); else OpenTextureBuffer(rdp.frame_buffers[rdp.copy_ci_index]); } else if (settings.fb_hires && rdp.read_whole_frame && prev_fb.status == ci_aux) { OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); } //else if (rdp.ci_status == ci_aux && !rdp.copy_ci_index) // CloseTextureBuffer(); rdp.skip_drawing = FALSE; } break; case ci_copy: { if (!rdp.motionblur || settings.fb_motionblur) { if (cur_fb.width == rdp.ci_width) { if (CopyTextureBuffer(prev_fb, cur_fb)) // if (CloseTextureBuffer(TRUE)) ; else { if (!rdp.fb_drawn || prev_fb.status == ci_copy_self) { CopyFrameBuffer (); rdp.fb_drawn = TRUE; } memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.cimg, (cur_fb.width*cur_fb.height)<>1); } } else { CloseTextureBuffer(TRUE); } } else { memset(gfx.RDRAM+cur_fb.addr, 0, cur_fb.width*cur_fb.height*rdp.ci_size); } rdp.skip_drawing = TRUE; } break; case ci_aux_copy: { rdp.skip_drawing = FALSE; if (CloseTextureBuffer(prev_fb.status != ci_aux_copy)) ; else if (!rdp.fb_drawn) { CopyFrameBuffer (); rdp.fb_drawn = TRUE; } if (settings.fb_hires) OpenTextureBuffer(cur_fb); } break; case ci_old_copy: { if (!rdp.motionblur || settings.fb_motionblur) { if (cur_fb.width == rdp.ci_width) { memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.maincimg[1].addr, (cur_fb.width*cur_fb.height)<>1); } //rdp.skip_drawing = TRUE; } else { memset(gfx.RDRAM+cur_fb.addr, 0, (cur_fb.width*cur_fb.height)<>1); } } break; /* else if (rdp.frame_buffers[rdp.ci_count].status == ci_main_i) { // CopyFrameBuffer (); rdp.scale_x = rdp.scale_x_bak; rdp.scale_y = rdp.scale_y_bak; rdp.skip_drawing = FALSE; } */ case ci_aux: { if (!settings.fb_hires && cur_fb.format != 0) rdp.skip_drawing = TRUE; else { rdp.skip_drawing = FALSE; if (settings.fb_hires && OpenTextureBuffer(cur_fb)) ; else { if (cur_fb.format != 0) rdp.skip_drawing = TRUE; if (rdp.ci_count == 0) { // if (rdp.num_of_ci > 1) // { rdp.scale_x = 1.0f; rdp.scale_y = 1.0f; // } } else if (!settings.fb_hires && (prev_fb.status == ci_main) && (prev_fb.width == cur_fb.width)) // for Pokemon Stadium CopyFrameBuffer (); } } cur_fb.status = ci_aux; } break; case ci_zimg: // ZIGGY // Zelda LoT effect save/restore depth buffer if (cur_fb.addr == rdp.zimg) { render_depth_mode = 1; } else { render_depth_mode = 2; } rdp.skip_drawing = TRUE; break; case ci_useless: //case ci_zcopy: rdp.skip_drawing = TRUE; break; case ci_copy_self: if (settings.fb_hires && (rdp.ci_count <= rdp.copy_ci_index) && (!SwapOK || settings.swapmode == 2)) OpenTextureBuffer(cur_fb); rdp.skip_drawing = FALSE; /* if (settings.fb_hires) { if (SwapOK) { rdp.cimg = rdp.frame_buffers[rdp.ci_count].addr; rdp.maincimg[0].addr = rdp.cimg; newSwapBuffers(); SwapOK = FALSE; OpenTextureBuffer(rdp.frame_buffers[rdp.ci_count]); } } */ break; default: rdp.skip_drawing = FALSE; } if ((rdp.ci_count > 0) && (prev_fb.status >= ci_aux)) //for Pokemon Stadium { if (!settings.fb_hires && prev_fb.format == 0) CopyFrameBuffer (); } if (!settings.fb_hires && cur_fb.status == ci_copy) { if (!rdp.motionblur && (rdp.num_of_ci > rdp.ci_count+1) && (next_fb.status != ci_aux)) { RestoreScale(); } } if (!settings.fb_hires && cur_fb.status == ci_aux) { if (cur_fb.format == 0) { if (settings.PPL && (rdp.scale_x < 1.1f)) //need to put current image back to frame buffer { int width = cur_fb.width; int height = cur_fb.height; WORD *ptr_dst = new WORD[width*height]; WORD *ptr_src = (WORD*)(gfx.RDRAM+cur_fb.addr); WORD c; for (int y=0; y> 1) | 0x8000; ptr_dst[x + y * width] = c; } } grLfbWriteRegion(GR_BUFFER_BACKBUFFER, 0, 0, GR_LFB_SRC_FMT_555, width, height, FXFALSE, width<<1, ptr_dst); delete[] ptr_dst; } /* else //just clear buffer { grColorMask(FXTRUE, FXTRUE); grBufferClear (0, 0, 0xFFFF); } */ } } if ((cur_fb.status == ci_main) && (rdp.ci_count > 0)) { BOOL to_org_res = TRUE; for (int i = rdp.ci_count + 1; i < rdp.num_of_ci; i++) { if ((rdp.frame_buffers[i].status != ci_main) && (rdp.frame_buffers[i].status != ci_zimg) && (rdp.frame_buffers[i].status != ci_zcopy)) { to_org_res = FALSE; break; } } if (to_org_res) { RDP("return to original scale\n"); rdp.scale_x = rdp.scale_x_bak; rdp.scale_y = rdp.scale_y_bak; if (settings.fb_hires && !rdp.read_whole_frame) CloseTextureBuffer(); } if (settings.fb_hires && !rdp.read_whole_frame && (prev_fb.status >= ci_aux) && (rdp.ci_count > rdp.copy_ci_index)) CloseTextureBuffer(); } rdp.ci_status = cur_fb.status; rdp.ci_count++; } rdp.ocimg = rdp.cimg; rdp.cimg = segoffset(rdp.cmd1) & BMASK; rdp.ci_width = (rdp.cmd0 & 0xFFF) + 1; if (settings.fb_smart) rdp.ci_height = rdp.frame_buffers[rdp.ci_count-1].height; else if (rdp.ci_width == 32) rdp.ci_height = 32; else rdp.ci_height = rdp.scissor_o.lr_y; if (rdp.zimg == rdp.cimg) { rdp.zi_width = rdp.ci_width; // int zi_height = std::min((int)rdp.zi_width*3/4, (int)rdp.vi_height); // rdp.zi_words = rdp.zi_width * zi_height; } DWORD format = (rdp.cmd0 >> 21) & 0x7; rdp.ci_size = (rdp.cmd0 >> 19) & 0x3; rdp.ci_end = rdp.cimg + ((rdp.ci_width*rdp.ci_height)<<(rdp.ci_size-1)); FRDP("setcolorimage - %08lx, width: %d, height: %d, format: %d, size: %d\n", rdp.cmd1, rdp.ci_width, rdp.ci_height, format, rdp.ci_size); FRDP("cimg: %08lx, ocimg: %08lx, SwapOK: %d\n", rdp.cimg, rdp.ocimg, SwapOK); if (format != 0 && !rdp.cur_image) //can't draw into non RGBA buffer { if (settings.fb_hires && rdp.ci_width <= 64) OpenTextureBuffer(rdp.frame_buffers[rdp.ci_count - 1]); else if (format > 2) rdp.skip_drawing = TRUE; return; } else { if (!settings.fb_smart) rdp.skip_drawing = FALSE; } CI_SET = TRUE; if (settings.swapmode > 0) { if (rdp.zimg == rdp.cimg) rdp.updatescreen = 1; BOOL viSwapOK = ((settings.swapmode == 2) && (rdp.vi_org_reg == *gfx.VI_ORIGIN_REG)) ? FALSE : TRUE; if ((rdp.zimg != rdp.cimg) && (rdp.ocimg != rdp.cimg) && SwapOK && viSwapOK && !rdp.cur_image) { if (settings.fb_smart) rdp.maincimg[0] = rdp.frame_buffers[rdp.main_ci_index]; else rdp.maincimg[0].addr = rdp.cimg; rdp.last_drawn_ci_addr = (settings.swapmode == 2) ? swapped_addr : rdp.maincimg[0].addr; swapped_addr = rdp.cimg; newSwapBuffers(); rdp.vi_org_reg = *gfx.VI_ORIGIN_REG; SwapOK = FALSE; if (settings.fb_hires) { if (rdp.copy_ci_index && (rdp.frame_buffers[rdp.ci_count-1].status != ci_zimg)) { int idx = (rdp.frame_buffers[rdp.ci_count].status == ci_aux_copy) ? rdp.main_ci_index : rdp.copy_ci_index; FRDP("attempt open tex buffer. status: %s, addr: %08lx\n", CIStatus[rdp.frame_buffers[idx].status], rdp.frame_buffers[idx].addr); OpenTextureBuffer(rdp.frame_buffers[idx]); if (rdp.frame_buffers[rdp.copy_ci_index].status == ci_main) //tidal wave rdp.copy_ci_index = 0; } else if (rdp.read_whole_frame && !rdp.cur_image) { OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); } } } } } static void rdp_trifill() { RDP_E("trifill - IGNORED\n"); RDP("trifill - IGNORED\n"); } static void rdp_trishade() { RDP_E("trishade - IGNORED\n"); RDP("trishade - IGNORED\n"); } static void rdp_tritxtr() { RDP_E("tritxtr - IGNORED\n"); RDP("tritxtr - IGNORED\n"); } static void rdp_trishadetxtr() { RDP_E("trishadetxtr - IGNORED\n"); RDP("trishadetxtr - IGNORED\n"); } static void rdp_trifillz() { RDP_E("trifillz - IGNORED\n"); RDP("trifillz - IGNORED\n"); } static void rdp_trishadez() { RDP_E("trishadez - IGNORED\n"); RDP("trishadez - IGNORED\n"); } static void rdp_tritxtrz() { RDP_E("tritxtrz - IGNORED\n"); RDP("tritxtrz - IGNORED\n"); } static void rdp_trishadetxtrz() { RDP_E("trishadetxtrz - IGNORED\n"); RDP("trishadetxtrz - IGNORED\n"); } static void rsp_reserved0() { RDP_E("reserved0 - IGNORED\n"); RDP("reserved0 - IGNORED\n"); } static void rsp_reserved1() { RDP("reserved1 - ignored\n"); } static void rsp_reserved2() { RDP("reserved2\n"); } static void rsp_reserved3() { RDP("reserved3 - ignored\n"); } void SetWireframeCol () { if (!fullscreen) return; switch (settings.wfmode) { //case 0: // normal colors, don't do anything case 1: // vertex colors grColorCombine (GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_NONE, FXFALSE); grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_ITERATED, GR_COMBINE_OTHER_NONE, FXFALSE); grAlphaBlendFunction (GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ZERO, GR_BLEND_ZERO); grTexCombine (GR_TMU0, GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE); grTexCombine (GR_TMU1, GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE); break; case 2: // red only grColorCombine (GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE, FXFALSE); grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE, FXFALSE); grConstantColorValue (0xFF0000FF); grAlphaBlendFunction (GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ZERO, GR_BLEND_ZERO); grTexCombine (GR_TMU0, GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE); grTexCombine (GR_TMU1, GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_ZERO, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE); break; } grAlphaTestFunction (GR_CMP_ALWAYS); grCullMode (GR_CULL_DISABLE); //grDepthBufferFunction (GR_CMP_ALWAYS); //grDepthMask (FXFALSE); rdp.update |= UPDATE_COMBINE | UPDATE_ALPHA_COMPARE; } #ifdef __cplusplus extern "C" { #endif /****************************************************************** Function: FrameBufferRead Purpose: This function is called to notify the dll that the frame buffer memory is beening read at the given address. DLL should copy content from its render buffer to the frame buffer in N64 RDRAM DLL is responsible to maintain its own frame buffer memory addr list DLL should copy 4KB block content back to RDRAM frame buffer. Emulator should not call this function again if other memory is read within the same 4KB range input: addr rdram address val val size 1 = BYTE, 2 = WORD, 4 = DWORD output: none *******************************************************************/ EXPORT void CALL FBRead(unsigned int addr) { LOG ("FBRead ()\n"); if (cpu_fb_ignore) return; if (cpu_fb_write_called) { cpu_fb_ignore = TRUE; cpu_fb_write = FALSE; return; } cpu_fb_read_called = TRUE; DWORD a = segoffset(addr); FRDP("FBRead. addr: %08lx\n", a); if (!rdp.fb_drawn && (a >= rdp.cimg) && (a < rdp.ci_end)) { fbreads_back++; //if (fbreads_back > 2) //&& (rdp.ci_width <= 320)) { CopyFrameBuffer (); rdp.fb_drawn = TRUE; } } if (!rdp.fb_drawn_front && (a >= rdp.maincimg[1].addr) && (a < rdp.maincimg[1].addr + rdp.ci_width*rdp.ci_height*2)) { fbreads_front++; //if (fbreads_front > 2)//&& (rdp.ci_width <= 320)) { DWORD cimg = rdp.cimg; rdp.cimg = rdp.maincimg[1].addr; if (settings.fb_smart) { rdp.ci_width = rdp.maincimg[1].width; rdp.ci_count = 0; DWORD h = rdp.frame_buffers[0].height; rdp.frame_buffers[0].height = rdp.maincimg[1].height; CopyFrameBuffer(GR_BUFFER_FRONTBUFFER); rdp.frame_buffers[0].height = h; } else { CopyFrameBuffer(GR_BUFFER_FRONTBUFFER); } rdp.cimg = cimg; rdp.fb_drawn_front = TRUE; } } } #if 0 //TODO: remove /****************************************************************** Function: FrameBufferWriteList Purpose: This function is called to notify the dll that the frame buffer has been modified by CPU at the given address. input: FrameBufferModifyEntry *plist size = size of the plist, max = 1024 output: none *******************************************************************/ EXPORT void CALL FBWList(FrameBufferModifyEntry *plist, DWORD size) { LOG ("FBWList ()\n"); FRDP("FBWList. size: %d\n", size); printf("FBWList. size: %d\n", size); } #endif /****************************************************************** Function: FrameBufferWrite Purpose: This function is called to notify the dll that the frame buffer has been modified by CPU at the given address. input: addr rdram address val val size 1 = BYTE, 2 = WORD, 4 = DWORD output: none *******************************************************************/ EXPORT void CALL FBWrite(unsigned int addr, unsigned int size) { LOG ("FBWrite ()\n"); if (cpu_fb_ignore) return; if (cpu_fb_read_called) { cpu_fb_ignore = TRUE; cpu_fb_write = FALSE; return; } cpu_fb_write_called = TRUE; DWORD a = segoffset(addr); FRDP("FBWrite. addr: %08lx\n", a); // ZIGGY : added a test on ci_width, otherwise we crash on zero division below if (!rdp.ci_width || a < rdp.cimg || a > rdp.ci_end) return; cpu_fb_write = TRUE; DWORD shift_l = (a-rdp.cimg) >> 1; DWORD shift_r = shift_l+2; d_ul_x = std::min(d_ul_x, shift_l%rdp.ci_width); d_ul_y = std::min(d_ul_y, shift_l/rdp.ci_width); d_lr_x = std::max(d_lr_x, shift_r%rdp.ci_width); d_lr_y = std::max(d_lr_y, shift_r/rdp.ci_width); } /************************************************************************ Function: FBGetFrameBufferInfo Purpose: This function is called by the emulator core to retrieve frame buffer information from the video plugin in order to be able to notify the video plugin about CPU frame buffer read/write operations size: = 1 byte = 2 word (16 bit) <-- this is N64 default depth buffer format = 4 dword (32 bit) when frame buffer information is not available yet, set all values in the FrameBufferInfo structure to 0 input: FrameBufferInfo pinfo[6] pinfo is pointed to a FrameBufferInfo structure which to be filled in by this function output: Values are return in the FrameBufferInfo structure Plugin can return up to 6 frame buffer info ************************************************************************/ ///* #if 0 //TODO: remove typedef struct { DWORD addr; DWORD size; DWORD width; DWORD height; } FrameBufferInfo; #endif EXPORT void CALL FBGetFrameBufferInfo(void *p) { LOG ("FBGetFrameBufferInfo ()\n"); FrameBufferInfo * pinfo = (FrameBufferInfo *)p; memset(pinfo,0,sizeof(FrameBufferInfo)*6); if (!settings.fb_get_info) return; RDP("FBGetFrameBufferInfo ()\n"); //* if (settings.fb_smart) { pinfo[0].addr = rdp.maincimg[1].addr; pinfo[0].size = rdp.maincimg[1].size; pinfo[0].width = rdp.maincimg[1].width; pinfo[0].height = rdp.maincimg[1].height; int info_index = 1; for (int i = 0; i < rdp.num_of_ci && info_index < 6; i++) { COLOR_IMAGE & cur_fb = rdp.frame_buffers[i]; if (cur_fb.status == ci_main || cur_fb.status == ci_copy_self || cur_fb.status == ci_old_copy) { pinfo[info_index].addr = cur_fb.addr; pinfo[info_index].size = cur_fb.size; pinfo[info_index].width = cur_fb.width; pinfo[info_index].height = cur_fb.height; info_index++; } } } else { pinfo[0].addr = rdp.maincimg[0].addr; pinfo[0].size = rdp.ci_size; pinfo[0].width = rdp.ci_width; pinfo[0].height = rdp.ci_width*3/4; pinfo[1].addr = rdp.maincimg[1].addr; pinfo[1].size = rdp.ci_size; pinfo[1].width = rdp.ci_width; pinfo[1].height = rdp.ci_width*3/4; } //*/ } #ifdef __cplusplus } #endif //*/ #include "UcodeFB.h" void DetectFrameBufferUsage () { RDP("DetectFrameBufferUsage\n"); DWORD dlist_start = *(DWORD*)(gfx.DMEM+0xFF0); #ifdef _WIN32 DWORD dlist_length = *(DWORD*)(gfx.DMEM+0xFF4); #endif // _WIN32 DWORD a; BOOL tidal = FALSE; if (settings.PM && (rdp.copy_ci_index || rdp.frame_buffers[rdp.copy_ci_index].status == ci_copy_self)) tidal = TRUE; DWORD ci = rdp.cimg, zi = rdp.zimg; // ci_width = rdp.ci_width; rdp.main_ci = rdp.main_ci_end = rdp.main_ci_bg = rdp.ci_count = 0; rdp.main_ci_index = rdp.copy_ci_index = 0; rdp.zimg_end = 0; rdp.tmpzimg = 0; rdp.motionblur = FALSE; rdp.main_ci_last_tex_addr = 0; BOOL previous_ci_was_read = rdp.read_previous_ci; rdp.read_previous_ci = FALSE; rdp.read_whole_frame = FALSE; rdp.swap_ci_index = rdp.black_ci_index = -1; SwapOK = TRUE; // Start executing at the start of the display list rdp.pc_i = 0; rdp.pc[rdp.pc_i] = dlist_start; rdp.dl_count = -1; rdp.halt = 0; rdp.scale_x_bak = rdp.scale_x; rdp.scale_y_bak = rdp.scale_y; // MAIN PROCESSING LOOP do { // Get the address of the next command a = rdp.pc[rdp.pc_i] & BMASK; // Load the next command and its input rdp.cmd0 = ((DWORD*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit rdp.cmd1 = ((DWORD*)gfx.RDRAM)[(a>>2)+1]; // / // Output the address before the command // Go to the next instruction rdp.pc[rdp.pc_i] = (a+8) & BMASK; if ((intptr_t)(gfx_instruction_lite[settings.ucode][rdp.cmd0>>24])) gfx_instruction_lite[settings.ucode][rdp.cmd0>>24] (); // check DL counter if (rdp.dl_count != -1) { rdp.dl_count --; if (rdp.dl_count == 0) { rdp.dl_count = -1; RDP ("End of DL\n"); rdp.pc_i --; } } } while (!rdp.halt); SwapOK = TRUE; if (rdp.ci_count > NUMTEXBUF) //overflow { rdp.cimg = ci; rdp.zimg = zi; rdp.num_of_ci = rdp.ci_count; rdp.scale_x = rdp.scale_x_bak; rdp.scale_y = rdp.scale_y_bak; return; } if (rdp.black_ci_index > 0 && rdp.black_ci_index < rdp.copy_ci_index) rdp.frame_buffers[rdp.black_ci_index].status = ci_main; if (rdp.frame_buffers[rdp.ci_count-1].status == ci_unknown) { if (rdp.ci_count > 1) rdp.frame_buffers[rdp.ci_count-1].status = ci_aux; else rdp.frame_buffers[rdp.ci_count-1].status = ci_main; } if ((rdp.frame_buffers[rdp.ci_count-1].status == ci_aux) && (rdp.frame_buffers[rdp.main_ci_index].width < 320) && (rdp.frame_buffers[rdp.ci_count-1].width > rdp.frame_buffers[rdp.main_ci_index].width)) { for (int i = 0; i < rdp.ci_count; i++) { if (rdp.frame_buffers[i].status == ci_main) rdp.frame_buffers[i].status = ci_aux; else if (rdp.frame_buffers[i].addr == rdp.frame_buffers[rdp.ci_count-1].addr) rdp.frame_buffers[i].status = ci_main; // FRDP("rdp.frame_buffers[%d].status = %d\n", i, rdp.frame_buffers[i].status); } rdp.main_ci_index = rdp.ci_count-1; } BOOL all_zimg = TRUE; int i; for (i = 0; i < rdp.ci_count; i++) { if (rdp.frame_buffers[i].status != ci_zimg) { all_zimg = FALSE; break; } } if (all_zimg) { for (i = 0; i < rdp.ci_count; i++) rdp.frame_buffers[i].status = ci_main; } RDP("detect fb final results: \n"); for (i = 0; i < rdp.ci_count; i++) { FRDP("rdp.frame_buffers[%d].status = %s, addr: %08lx, height: %d\n", i, CIStatus[rdp.frame_buffers[i].status], rdp.frame_buffers[i].addr, rdp.frame_buffers[i].height); } rdp.cimg = ci; rdp.zimg = zi; rdp.num_of_ci = rdp.ci_count; if (rdp.read_previous_ci && previous_ci_was_read) if (!settings.fb_hires || !rdp.copy_ci_index) rdp.motionblur = TRUE; if (rdp.motionblur || settings.fb_hires || (rdp.frame_buffers[rdp.copy_ci_index].status == ci_aux_copy)) { rdp.scale_x = rdp.scale_x_bak; rdp.scale_y = rdp.scale_y_bak; } if ((rdp.read_previous_ci || previous_ci_was_read) && !rdp.copy_ci_index) rdp.read_whole_frame = TRUE; if (rdp.read_whole_frame) { if (settings.fb_hires && !settings.fb_ignore_previous) { if (rdp.swap_ci_index < 0) { rdp.texbufs[0].clear_allowed = TRUE; OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]); } } else { if (rdp.motionblur) { if (settings.fb_motionblur) CopyFrameBuffer(); else memset(gfx.RDRAM+rdp.cimg, 0, rdp.ci_width*rdp.ci_height*rdp.ci_size); } else //if (ci_width == rdp.frame_buffers[rdp.main_ci_index].width) { if (rdp.maincimg[0].height > 65) //for 1080 { rdp.cimg = rdp.maincimg[0].addr; rdp.ci_width = rdp.maincimg[0].width; rdp.ci_count = 0; DWORD h = rdp.frame_buffers[0].height; rdp.frame_buffers[0].height = rdp.maincimg[0].height; CopyFrameBuffer(); rdp.frame_buffers[0].height = h; } else //conker { CopyFrameBuffer(); } } } } if (settings.fb_hires) { for (i = 0; i < num_tmu; i++) { rdp.texbufs[i].clear_allowed = TRUE; for (int j = 0; j < 256; j++) { rdp.texbufs[i].images[j].drawn = FALSE; rdp.texbufs[i].images[j].clear = TRUE; } } if (tidal) { //RDP("Tidal wave!\n"); rdp.copy_ci_index = rdp.main_ci_index; } } rdp.ci_count = 0; if (settings.fb_ignore_previous) rdp.read_whole_frame = FALSE; else rdp.maincimg[0] = rdp.frame_buffers[rdp.main_ci_index]; // rdp.scale_x = rdp.scale_x_bak; // rdp.scale_y = rdp.scale_y_bak; RDP("DetectFrameBufferUsage End\n"); } #ifdef __cplusplus extern "C" { #endif /****************************************************************** Function: ProcessRDPList Purpose: This function is called when there is a Dlist to be processed. (Low level GFX list) input: none output: none *******************************************************************/ EXPORT void CALL ProcessRDPList(void) { if (settings.KI) { *gfx.MI_INTR_REG |= 0x20; gfx.CheckInterrupts(); } LOG ("ProcessRDPList ()\n"); no_dlist = FALSE; update_screen_count = 0; ChangeSize (); #ifdef ALTTAB_FIX if (!hhkLowLevelKybd) { hhkLowLevelKybd = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hInstance, 0); } #endif LOG ("ProcessDList ()\n"); if (!fullscreen) { drawNoFullscreenMessage(); // Set an interrupt to allow the game to continue *gfx.MI_INTR_REG |= 0x20; gfx.CheckInterrupts(); } if (reset) { reset = 0; memset (microcode, 0, 4096); if (settings.autodetect_ucode) { // Thanks to ZeZu for ucode autodetection!!! DWORD startUcode = *(DWORD*)(gfx.DMEM+0xFD0); memcpy (microcode, gfx.RDRAM+startUcode, 4096); microcheck (); } } else if ( ((old_ucode == 6) && (settings.ucode == 1)) || settings.force_microcheck) { DWORD startUcode = *(DWORD*)(gfx.DMEM+0xFD0); memcpy (microcode, gfx.RDRAM+startUcode, 4096); microcheck (); } if (exception) return; // Switch to fullscreen? if (to_fullscreen) { to_fullscreen = FALSE; if (!InitGfx (FALSE)) { LOG ("FAILED!!!\n"); return; } fullscreen = TRUE; } // Clear out the RDP log #ifdef RDP_LOGGING if (settings.logging && settings.log_clear) { CLOSE_RDP_LOG (); OPEN_RDP_LOG (); } #endif #ifdef UNIMP_LOG if (settings.log_unk && settings.unk_clear) { std::ofstream unimp; unimp.open("unimp.txt"); unimp.close(); } #endif //* Set states *// if (settings.swapmode > 0) SwapOK = TRUE; rdp.updatescreen = 1; rdp.tri_n = 0; // 0 triangles so far this frame rdp.debug_n = 0; rdp.model_i = 0; // 0 matrices so far in stack //stack_size can be less then 32! Important for Silicon Vally. Thanks Orkin! rdp.model_stack_size = std::min((DWORD) 32, (*(DWORD*)(gfx.DMEM+0x0FE4))>>6); if (rdp.model_stack_size == 0) rdp.model_stack_size = 32; rdp.fb_drawn = rdp.fb_drawn_front = FALSE; rdp.update = 0x7FFFFFFF; // All but clear cache rdp.geom_mode = 0; rdp.acmp = 0; rdp.maincimg[1] = rdp.maincimg[0]; rdp.skip_drawing = FALSE; rdp.s2dex_tex_loaded = FALSE; fbreads_front = fbreads_back = 0; rdp.fog_multiplier = rdp.fog_offset = 0; rdp.zsrc = 0; if (cpu_fb_write == TRUE) DrawFrameBufferToScreen(); cpu_fb_write = FALSE; cpu_fb_read_called = FALSE; cpu_fb_write_called = FALSE; cpu_fb_ignore = FALSE; d_ul_x = 0xffff; d_ul_y = 0xffff; d_lr_x = 0; d_lr_y = 0; //analize possible frame buffer usage if (settings.fb_smart) DetectFrameBufferUsage(); if (!settings.lego || rdp.num_of_ci > 1) rdp.last_bg = 0; //* End of set states *// // Get the start of the display list and the length of it // DWORD dlist_start = *(DWORD*)(gfx.DMEM+0xFF0); // DWORD dlist_length = *(DWORD*)(gfx.DMEM+0xFF4); DWORD dlist_start = *gfx.DPC_CURRENT_REG; DWORD dlist_length = *gfx.DPC_END_REG - *gfx.DPC_CURRENT_REG; FRDP("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx, fbuf_width: %d, dlist start: %08lx, dlist_lenght: %d\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG, *gfx.VI_WIDTH_REG, dlist_start, dlist_length); FRDP_E("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG); if (settings.tonic && dlist_length < 16) { rdp_fullsync(); FRDP_E("DLIST is too short!\n"); return; } // Start executing at the start of the display list rdp.pc_i = 0; rdp.pc[rdp.pc_i] = dlist_start; rdp.dl_count = -1; rdp.halt = 0; DWORD a; // catches exceptions so that it doesn't freeze #ifdef CATCH_EXCEPTIONS try { #endif // MAIN PROCESSING LOOP do { // Get the address of the next command a = rdp.pc[rdp.pc_i] & BMASK; // Load the next command and its input rdp.cmd0 = ((DWORD*)gfx.RDRAM)[a>>2]; // \ Current command, 64 bit rdp.cmd1 = ((DWORD*)gfx.RDRAM)[(a>>2)+1]; // / // cmd2 and cmd3 are filled only when needed, by the function that needs them // Output the address before the command #ifdef LOG_COMMANDS FRDP ("%08lx (c0:%08lx, c1:%08lx): ", a, rdp.cmd0, rdp.cmd1); #else FRDP ("%08lx: ", a); #endif // Go to the next instruction rdp.pc[rdp.pc_i] = (a+8) & BMASK; #ifdef PERFORMANCE QueryPerformanceCounter ((LARGE_INTEGER*)&perf_cur); #endif // Process this instruction gfx_instruction[settings.ucode][((rdp.cmd0>>24)&0x3f) + 0x100-0x40] (); // check DL counter if (rdp.dl_count != -1) { rdp.dl_count --; if (rdp.dl_count == 0) { rdp.dl_count = -1; RDP ("End of DL\n"); rdp.pc_i --; } } #ifdef PERFORMANCE QueryPerformanceCounter ((LARGE_INTEGER*)&perf_next); __int64 t = perf_next-perf_cur; sprintf (out_buf, "perf %08lx: %016I64d\n", a-8, t); rdp_log << out_buf; #endif } while (0); #ifdef CATCH_EXCEPTIONS } catch (...) { if (fullscreen) ReleaseGfx (); WriteLog(M64MSG_ERROR, "The GFX plugin caused an exception and has been disabled."); exception = TRUE; } #endif if (settings.fb_smart) { rdp.scale_x = rdp.scale_x_bak; rdp.scale_y = rdp.scale_y_bak; } if (settings.fb_read_always) { CopyFrameBuffer (); } if (rdp.yuv_image) { DrawYUVImageToFrameBuffer(); rdp.yuv_image = FALSE; // FRDP("yuv image draw. ul_x: %f, ul_y: %f, lr_x: %f, lr_y: %f, begin: %08lx\n", // rdp.yuv_ul_x, rdp.yuv_ul_y, rdp.yuv_lr_x, rdp.yuv_lr_y, rdp.yuv_im_begin); rdp.yuv_ul_x = rdp.yuv_ul_y = rdp.yuv_lr_x = rdp.yuv_lr_y = 0; rdp.yuv_im_begin = 0x00FFFFFF; } if (rdp.cur_image) CloseTextureBuffer(rdp.read_whole_frame && (settings.PM || rdp.swap_ci_index >= 0)); if (settings.TGR2 && rdp.vi_org_reg != *gfx.VI_ORIGIN_REG && CI_SET) { newSwapBuffers (); CI_SET = FALSE; } RDP("ProcessDList end\n"); WriteLog(M64MSG_VERBOSE, "ProcessRPDList %x %x %x\n", *gfx.DPC_START_REG, *gfx.DPC_END_REG, *gfx.DPC_CURRENT_REG); //*gfx.DPC_STATUS_REG = 0xffffffff; // &= ~0x0002; *gfx.DPC_START_REG = *gfx.DPC_END_REG; *gfx.DPC_CURRENT_REG = *gfx.DPC_END_REG; } #ifdef __cplusplus } #endif // Local Variables: *** // tab-width:4 *** // c-file-offset:4 *** // End: *** mupen64plus-video-glide64-src-2.6.0/src/rdp.h000066400000000000000000000476011464507525600206210ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * Copyright (c) 2008 Günther * * 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 2 of the License, or * 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 * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** // Call this macro to automatically switch out of fullscreen, then break. :) // useful for debugging fullscreen areas that can't otherwise be accessed #ifndef RDP_H #define RDP_H #include #ifdef _WIN32 #include #else // _WIN32 #include "winlnxdefs.h" #endif // _WIN32 #include "glide.h" extern char out_buf[2048]; extern BOOL capture_screen; extern char capture_path[256]; extern DWORD frame_count; // frame counter #define MAX_CACHE 1024 #define MAX_TRI_CACHE 768 // this is actually # of vertices, not triangles #define MAX_VTX 256 #define MAX_TMU 2 #define TEXMEM_2MB_EDGE 2097152 // Supported flags #define SUP_TEXMIRROR 0x00000001 // Clipping flags #define CLIP_XMAX 0x00000001 #define CLIP_XMIN 0x00000002 #define CLIP_YMAX 0x00000004 #define CLIP_YMIN 0x00000008 #define CLIP_ZMIN 0x00000010 // Flags #define ZBUF_ENABLED 0x00000001 #define ZBUF_DECAL 0x00000002 #define ZBUF_COMPARE 0x00000004 #define ZBUF_UPDATE 0x00000008 #define ALPHA_COMPARE 0x00000010 #define FORCE_BL 0x00000020 #define CULL_FRONT 0x00001000 // * must be here #define CULL_BACK 0x00002000 // * must be here #define FOG_ENABLED 0x00010000 #define CULLMASK 0x00003000 #define CULLSHIFT 12 // Update flags #define UPDATE_ZBUF_ENABLED 0x00000001 #define UPDATE_TEXTURE 0x00000002 // \ Same thing! #define UPDATE_COMBINE 0x00000002 // / #define UPDATE_CULL_MODE 0x00000004 #define UPDATE_LIGHTS 0x00000010 #define UPDATE_BIASLEVEL 0x00000020 #define UPDATE_ALPHA_COMPARE 0x00000040 #define UPDATE_VIEWPORT 0x00000080 #define UPDATE_MULT_MAT 0x00000100 #define UPDATE_SCISSOR 0x00000200 #define UPDATE_FOG_ENABLED 0x00010000 #define CMB_MULT 0x00000001 #define CMB_SET 0x00000002 #define CMB_SUB 0x00000004 #define CMB_ADD 0x00000008 #define CMB_A_MULT 0x00000010 #define CMB_A_SET 0x00000020 #define CMB_A_SUB 0x00000040 #define CMB_A_ADD 0x00000080 #define CMB_SETSHADE_SHADEALPHA 0x00000100 #define CMB_INTER 0x00000200 #define CMB_MULT_OWN_ALPHA 0x00000400 #define CMB_COL_SUB_OWN 0x00000800 #define uc(x) coord[x<<1] #define vc(x) coord[(x<<1)+1] // Vertex structure typedef struct { float x, y, z, q; float u0, v0, u1, v1; float coord[4]; float w; WORD flags; BYTE b; // These values are arranged like this so that *(DWORD*)(VERTEX+?) is BYTE g; // ARGB format that glide can use. BYTE r; BYTE a; float f; //fog float vec[3]; // normal vector float sx, sy, sz; float x_w, y_w, z_w, u0_w, v0_w, u1_w, v1_w, oow; BYTE not_zclipped; BYTE screen_translated; BYTE shade_mods_allowed; BYTE uv_fixed; DWORD uv_calculated; // like crc float ou, ov; int number; // way to identify it int scr_off, z_off; // off the screen? } VERTEX; // Clipping (scissors) typedef struct { DWORD ul_x; DWORD ul_y; DWORD lr_x; DWORD lr_y; } SCISSOR; typedef struct { BYTE card_id; DWORD res_x, scr_res_x; DWORD res_y, scr_res_y; DWORD res_data, res_data_org; BOOL autodetect_ucode; DWORD ucode; BOOL wireframe; int wfmode; int lodmode; BYTE filtering; BOOL fog; BOOL buff_clear; // BOOL clear_8; BOOL vsync; BOOL fast_crc; BYTE swapmode; BOOL logging; BOOL elogging; BOOL log_clear; BOOL filter_cache; BOOL unk_as_red; BOOL log_unk; BOOL unk_clear; BYTE show_fps; BOOL clock; BOOL clock_24_hr; DWORD full_res; DWORD tex_filter; BOOL noditheredalpha; BOOL noglsl; BOOL FBO; BOOL disable_auxbuf; //Frame buffer emulation options BOOL fb_read_always; BOOL fb_read_alpha; BOOL fb_smart; BOOL fb_motionblur; BOOL fb_hires; BOOL fb_hires_buf_clear; BOOL fb_depth_clear; BOOL fb_depth_render; BOOL fb_optimize_texrect; BOOL fb_optimize_write; BOOL fb_ignore_aux_copy; BOOL fb_ignore_previous; BOOL fb_get_info; // Special fixes int offset_x, offset_y; int scale_x, scale_y; BOOL alt_tex_size; BOOL use_sts1_only; BOOL wrap_big_tex; BOOL flame_corona; //hack for zeldas flame's corona int fix_tex_coord; int depth_bias; BOOL soft_depth_compare; // use GR_CMP_LEQUAL instead of GR_CMP_LESS BOOL increase_texrect_edge; // add 1 to lower right corner coordinates of texrect BOOL decrease_fillrect_edge; // sub 1 from lower right corner coordinates of fillrect int stipple_mode; //used for dithered alpha emulation DWORD stipple_pattern; //used for dithered alpha emulation BOOL force_microcheck; //check microcode each frame, for mixed F3DEX-S2DEX games BOOL custom_ini; BOOL hotkeys; //Special game hacks BOOL force_depth_compare; //NFL Quarterback Club 99 and All-Star Baseball 2000 BOOL fillcolor_fix; //use first part of fillcolor in fillrects BOOL cpu_write_hack; //show images writed directly by CPU BOOL increase_primdepth; //increase prim_depth value for texrects BOOL zelda; //zeldas hacks BOOL bomberman64; //bomberman64 hacks BOOL diddy; //diddy kong racing BOOL tonic; //tonic trouble BOOL PPL; //pokemon puzzle league requires many special fixes BOOL ASB; //All-Star Baseball games BOOL doraemon2;//Doraemon 2 BOOL invaders; //Space Invaders BOOL BAR; //Beetle Adventure Racing BOOL ISS64; //International Superstar Soccer 64 BOOL RE2; //Resident Evil 2 BOOL nitro; //WCW Nitro BOOL chopper; //Chopper Attack BOOL yoshi; // Yoshi Story BOOL fzero; // F-Zero BOOL PM; //Paper Mario BOOL TGR; //Top Gear Rally BOOL TGR2; //Top Gear Rally 2 BOOL KI; //Killer Instinct BOOL lego; //LEGO Racers } SETTINGS; typedef struct { BYTE fb_always; BYTE fb_motionblur; BYTE filtering; BYTE corona; } HOTKEY_INFO; // This structure is what is passed in by rdp:settextureimage typedef struct { BYTE format; // format: ARGB, IA, ... BYTE size; // size: 4,8,16, or 32 bit WORD width; // used in settextureimage DWORD addr; // address in RDRAM to load the texture from BOOL set_by; // 0-loadblock 1-loadtile } TEXTURE_IMAGE; // This structure is a tile descriptor (as used by rdp:settile and rdp:settilesize) typedef struct { // rdp:settile BYTE format; // format: ARGB, IA, ... BYTE size; // size: 4,8,16, or 32 bit WORD line; // size of one row (x axis) in 64 bit words WORD t_mem; // location in texture memory (in 64 bit words, max 512 (4MB)) BYTE palette; // palette # to use BYTE clamp_t; // clamp or wrap (y axis)? BYTE mirror_t; // mirroring on (y axis)? BYTE mask_t; // mask to wrap around (ex: 5 would wrap around 32) (y axis) BYTE shift_t; // ??? (scaling) BYTE clamp_s; // clamp or wrap (x axis)? BYTE mirror_s; // mirroring on (x axis)? BYTE mask_s; // mask to wrap around (x axis) BYTE shift_s; // ??? (scaling) DWORD hack; // any hacks needed // rdp:settilesize WORD ul_s; // upper left s coordinate WORD ul_t; // upper left t coordinate WORD lr_s; // lower right s coordinate WORD lr_t; // lower right t coordinate float f_ul_s; float f_ul_t; // these are set by loadtile WORD t_ul_s; // upper left s coordinate WORD t_ul_t; // upper left t coordinate WORD t_lr_s; // lower right s coordinate WORD t_lr_t; // lower right t coordinate DWORD width; DWORD height; // uc0:texture BYTE on; float s_scale; float t_scale; WORD org_s_scale; WORD org_t_scale; } TILE; // This structure forms the lookup table for cached textures typedef struct { DWORD addr; // address in RDRAM DWORD crc; // CRC check DWORD palette; // Palette # DWORD width; // width DWORD height; // height DWORD format; // format DWORD size; // size DWORD last_used; // what frame # was this texture last used (used for replacing) DWORD line; DWORD flags; // clamp/wrap/mirror flags DWORD realwidth; // width of actual texture DWORD realheight; // height of actual texture DWORD lod; DWORD aspect; BOOL set_by; DWORD texrecting; float scale_x; // texture scaling float scale_y; float scale; // general scale to 256 GrTexInfo t_info; // texture info (glide) DWORD tmem_addr; // addres in texture memory (glide) int uses; // 1 triangle that uses this texture int splits; // number of splits int splitheight; float c_off; // ul center texel offset (both x and y) float c_scl_x; // scale to lower-right center-texel x float c_scl_y; // scale to lower-right center-texel y DWORD mod, mod_color, mod_color1, mod_color2, mod_factor; } CACHE_LUT; // Lights typedef struct { float r, g, b, a; // color float dir_x, dir_y, dir_z; // direction towards the light source float x, y, z, w; // light position float ca, la, qa; DWORD nonblack; DWORD nonzero; } LIGHT; typedef enum { noise_none, noise_combine, noise_texture } NOISE_MODE; typedef enum { ci_main, //0, main color image ci_zimg, //1, depth image ci_unknown, //2, status is unknown ci_useless, //3, status is unclear ci_old_copy, //4, auxilary color image, copy of last color image from previous frame ci_copy, //5, auxilary color image, copy of previous color image ci_copy_self, //6, main color image, it's content will be used to draw into itself ci_zcopy, //7, auxilary color image, copy of depth image ci_aux, //8, auxilary color image ci_aux_copy //9, auxilary color image, partial copy of previous color image } CI_STATUS; // Frame buffers typedef struct { DWORD addr; //color image address DWORD format; DWORD size; DWORD width; DWORD height; CI_STATUS status; int changed; } COLOR_IMAGE; typedef struct { GrChipID_t tmu; DWORD addr; //address of color image DWORD end_addr; DWORD tex_addr; //address in video memory DWORD width; //width of color image DWORD height; //height of color image WORD format; //format of color image BOOL clear; //flag. texture buffer must be cleared BOOL drawn; //flag. if equal to 1, this image was already drawn in current frame float scr_width; //width of rendered image float scr_height; //height of rendered image DWORD tex_width; //width of texture buffer DWORD tex_height; //height of texture buffer int tile; // WORD tile_uls; //shift from left bound of the texture WORD tile_ult; //shift from top of the texture DWORD v_shift; //shift from top of the texture DWORD u_shift; //shift from left of the texture float u_scale; //used to map vertex u,v coordinates into hires texture float v_scale; //used to map vertex u,v coordinates into hires texture GrTexInfo info; } HIRES_COLOR_IMAGE; typedef struct { GrChipID_t tmu; DWORD begin; //start of the block in video memory DWORD end; //end of the block in video memory BYTE count; //number of allocated texture buffers BOOL clear_allowed; //stack of buffers can be cleared HIRES_COLOR_IMAGE images[256]; } TEXTURE_BUFFER; #define NUMTEXBUF 92 typedef struct { float vi_width; float vi_height; BOOL window_changed; float offset_x, offset_y; float scale_x, scale_1024, scale_x_bak; float scale_y, scale_768, scale_y_bak; DWORD res_scale_x; DWORD res_scale_y; float view_scale[3]; float view_trans[3]; BOOL updatescreen; DWORD tri_n; // triangle counter DWORD debug_n; // Program counter DWORD pc[10]; // DList PC stack DWORD pc_i; // current PC index in the stack int dl_count; // number of instructions before returning // Segments DWORD segment[16]; // Segment pointer // Marks the end of DList execution (done in uc?:enddl) int halt; // Next command DWORD cmd0; DWORD cmd1; DWORD cmd2; DWORD cmd3; // Clipping SCISSOR scissor_o; SCISSOR scissor; // Colors DWORD fog_color; DWORD fill_color; DWORD prim_color; DWORD blend_color; DWORD env_color; DWORD prim_lodmin, prim_lodfrac; WORD prim_depth; BYTE K5; NOISE_MODE noise; float col[4]; // color multiplier float coladd[4]; // color add/subtract float shade_factor; float col_2[4]; DWORD cmb_flags, cmb_flags_2; // othermode_l flags int acmp; // 0 = none, 1 = threshold, 2 = dither int zsrc; // 0 = pixel, 1 = prim // Clipping int clip; // clipping flags VERTEX vtx1[256]; // copy vertex buffer #1 (used for clipping) VERTEX vtx2[256]; // copy vertex buffer #2 VERTEX *vtxbuf; // current vertex buffer (reset to vtx, used to determine current // vertex buffer) VERTEX *vtxbuf2; int n_global; // Used to pass the number of vertices from clip_z to clip_tri int vtx_buffer; // Matrices __declspec( align(16) ) float model[4][4]; __declspec( align(16) ) float proj[4][4]; __declspec( align(16) ) float combined[4][4]; __declspec( align(16) ) float dkrproj[3][4][4]; __declspec( align(16) ) float model_stack[32][4][4]; // 32 deep, will warn if overflow int model_i; // index in the model matrix stack int model_stack_size; // Textures TEXTURE_IMAGE timg; // 1 for each tmem address TILE tiles[8]; // 8 tile descriptors BYTE tmem[4096]; // 4k tmem DWORD addr[512]; // 512 addresses (used to determine address loaded from) int cur_tile; // current tile int mipmap_level; int last_tile; // last tile set int last_tile_size; // last tile size set CACHE_LUT cache[MAX_TMU][MAX_CACHE]; CACHE_LUT *cur_cache[2]; DWORD cur_cache_n[2]; int n_cached[MAX_TMU]; DWORD tmem_ptr[MAX_TMU]; int t0, t1; int best_tex; // if no 2-tmus, which texture? (0 or 1) int tex; int filter_mode; // Texture palette WORD pal_8[256]; DWORD pal_8_crc[16]; DWORD pal_256_crc; BYTE tlut_mode; BOOL LOD_en; // Lighting DWORD num_lights; LIGHT light[12]; float light_vector[12][3]; float lookat[2][3]; BOOL use_lookat; // Combine modes DWORD cycle1, cycle2, cycle_mode; BYTE c_a0, c_b0, c_c0, c_d0, c_Aa0, c_Ab0, c_Ac0, c_Ad0; BYTE c_a1, c_b1, c_c1, c_d1, c_Aa1, c_Ab1, c_Ac1, c_Ad1; BYTE fbl_a0, fbl_b0, fbl_c0, fbl_d0; BYTE fbl_a1, fbl_b1, fbl_c1, fbl_d1; BYTE uncombined; // which is uncombined: 0x01=color 0x02=alpha 0x03=both // float YUV_C0, YUV_C1, YUV_C2, YUV_C3, YUV_C4; //YUV textures conversion coefficients BOOL yuv_image; float yuv_ul_x, yuv_ul_y, yuv_lr_x, yuv_lr_y; DWORD yuv_im_begin; // What needs updating DWORD update; DWORD flags; BOOL first; // Vertices VERTEX vtx[MAX_VTX]; int v0, vn; DWORD tex_ctr; // same as above, incremented every time textures are updated BOOL allow_combine; // allow combine updating? BOOL s2dex_tex_loaded; // Debug stuff DWORD rm; // use othermode_l instead, this just as a check for changes DWORD render_mode_changed; DWORD geom_mode; DWORD othermode_h; DWORD othermode_l; // used to check if in texrect while loading texture DWORD texrecting; //frame buffer related slots. Added by Gonetz COLOR_IMAGE frame_buffers[NUMTEXBUF+2]; DWORD cimg, ocimg, zimg, tmpzimg, vi_org_reg; COLOR_IMAGE maincimg[2]; DWORD last_drawn_ci_addr; DWORD main_ci, main_ci_end, main_ci_bg, main_ci_last_tex_addr, zimg_end, last_bg; DWORD ci_width, ci_height, ci_size, ci_end; DWORD zi_width; int zi_lrx, zi_lry; BYTE ci_count, num_of_ci, main_ci_index, copy_ci_index; int swap_ci_index, black_ci_index; DWORD ci_upper_bound, ci_lower_bound; BOOL motionblur, fb_drawn, fb_drawn_front, read_previous_ci, read_whole_frame; CI_STATUS ci_status; TEXTURE_BUFFER texbufs[2]; HIRES_COLOR_IMAGE * cur_image; //image currently being drawn HIRES_COLOR_IMAGE * hires_tex; //image, which corresponds to currently selected texture BYTE cur_tex_buf; BYTE acc_tex_buf; BOOL skip_drawing; //rendering is not required. used for frame buffer emulation //fog related slots. Added by Gonetz float fog_multiplier, fog_offset; BOOL fog_coord_enabled; } RDP; void SetWireframeCol (); void ChangeSize (); extern RDP rdp; extern SETTINGS settings; extern HOTKEY_INFO hotkey_info; extern GrTexInfo fontTex; extern GrTexInfo cursorTex; extern DWORD offset_font; extern DWORD offset_cursor; extern DWORD offset_textures; extern DWORD offset_texbuf1; extern BOOL ucode_error_report; // RDP functions void rdp_reset (); // global strings extern const char *ACmp[4]; extern const char *Mode0[16]; extern const char *Mode1[16]; extern const char *Mode2[32]; extern const char *Mode3[8]; extern const char *Alpha0[8]; extern const char *Alpha2[8]; extern const char *str_zs[2]; extern const char *str_yn[2]; extern const char *str_offon[2]; extern const char *str_cull[4]; extern const char *str_format[8]; extern const char *str_size[4]; extern const char *str_cm[4]; extern const char *str_filter[3]; extern const char *str_tlut[4]; extern const char *CIStatus[10]; #define Alpha1 Alpha0 #define Alpha3 Alpha0 #define FBL_D_1 2 #define FBL_D_0 3 // Convert from u0/v0/u1/v1 to the real coordinates without regard to tmu __inline void ConvertCoordsKeep (VERTEX *v, int n) { for (int i=0; i 65535.0f) return 65535.0f; // return (z / 65535.0f) * z; // if (z < 4096.0f) return z * 0.25f; // z = (z / 16384.0f) * z; z *= 1.9f; if (z > 65534.0f) return 65534.0f; return z; } __inline void CalculateFog (VERTEX *v) { if (rdp.flags & FOG_ENABLED) { v->f = std::min(255.0f, std::max(0.0f, v->z_w * rdp.fog_multiplier + rdp.fog_offset)); v->a = (BYTE)v->f; } else { v->f = 1.0f; } } void newSwapBuffers(); extern BOOL SwapOK; // ** utility functions void load_palette (DWORD addr, WORD start, WORD count); #endif // ifndef RDP_H mupen64plus-video-glide64-src-2.6.0/src/ucode.h000066400000000000000000001653461464507525600211420ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** typedef void (*rdp_instr)(); // RDP graphic instructions pointer table static rdp_instr gfx_instruction[9][256] = { { // uCode 0 - RSP SW 2.0X // 00-3f // games: Super Mario 64, Tetrisphere, Demos spnoop, uc0_matrix, rsp_reserved0, uc0_movemem, uc0_vertex, rsp_reserved1, uc0_displaylist, rsp_reserved2, rsp_reserved3, uc6_sprite2d, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, // 40-7f: Unused undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, // 80-bf: Immediate commands undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, uc0_tri4, uc0_rdphalf_cont, uc0_rdphalf_2, uc0_rdphalf_1, uc0_quad3d, uc0_cleargeometrymode, uc0_setgeometrymode, uc0_enddl, uc0_setothermode_l, uc0_setothermode_h, uc0_texture, uc0_moveword, uc0_popmatrix, uc0_culldl, uc0_tri1, // c0-ff: RDP commands rdp_noop, undef, undef, undef, undef, undef, undef, undef, rdp_trifill, rdp_trifillz, rdp_tritxtr, rdp_tritxtrz, rdp_trishade, rdp_trishadez, rdp_trishadetxtr, rdp_trishadetxtrz, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, rdp_texrect, rdp_texrect, rdp_loadsync, rdp_pipesync, rdp_tilesync, rdp_fullsync, rdp_setkeygb, rdp_setkeyr, rdp_setconvert, rdp_setscissor, rdp_setprimdepth, rdp_setothermode, rdp_loadtlut, undef, rdp_settilesize, rdp_loadblock, rdp_loadtile, rdp_settile, rdp_fillrect, rdp_setfillcolor, rdp_setfogcolor, rdp_setblendcolor, rdp_setprimcolor, rdp_setenvcolor, rdp_setcombine, rdp_settextureimage, rdp_setdepthimage, rdp_setcolorimage }, // uCode 1 - F3DEX 1.XX // 00-3f // games: Mario Kart, Star Fox { spnoop, uc0_matrix, rsp_reserved0, uc0_movemem, uc1_vertex, rsp_reserved1, uc0_displaylist, rsp_reserved2, rsp_reserved3, uc6_sprite2d, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, // 40-7f: unused undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, // 80-bf: Immediate commands undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, uc6_loaducode, uc1_branch_z, uc1_tri2, uc2_modifyvtx, uc0_rdphalf_2, uc1_rdphalf_1, uc1_line3d, uc0_cleargeometrymode, uc0_setgeometrymode, uc0_enddl, uc0_setothermode_l, uc0_setothermode_h, uc0_texture, uc0_moveword, uc0_popmatrix, uc2_culldl, uc1_tri1, // c0-ff: RDP commands rdp_noop, undef, undef, undef, undef, undef, undef, undef, rdp_trifill, rdp_trifillz, rdp_tritxtr, rdp_tritxtrz, rdp_trishade, rdp_trishadez, rdp_trishadetxtr, rdp_trishadetxtrz, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, rdp_texrect, rdp_texrect, rdp_loadsync, rdp_pipesync, rdp_tilesync, rdp_fullsync, rdp_setkeygb, rdp_setkeyr, rdp_setconvert, rdp_setscissor, rdp_setprimdepth, rdp_setothermode, rdp_loadtlut, undef, rdp_settilesize, rdp_loadblock, rdp_loadtile, rdp_settile, rdp_fillrect, rdp_setfillcolor, rdp_setfogcolor, rdp_setblendcolor, rdp_setprimcolor, rdp_setenvcolor, rdp_setcombine, rdp_settextureimage, rdp_setdepthimage, rdp_setcolorimage }, // uCode 2 - F3DEX 2.XX // games: Zelda 64 { // 00-3f spnoop, uc2_vertex, uc2_modifyvtx, uc2_culldl, uc1_branch_z, uc2_tri1, uc2_quad, uc2_quad, uc2_line3d, uc6_bg_1cyc, uc6_bg_copy, uc6_obj_rendermode/*undef*/, undef, undef, undef, undef, uc0_tri4, uc0_tri4, uc0_tri4, uc0_tri4, uc0_tri4, uc0_tri4, uc0_tri4, uc0_tri4, uc0_tri4, uc0_tri4, uc0_tri4, uc0_tri4, uc0_tri4, uc0_tri4, uc0_tri4, uc0_tri4, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, // 40-7f: unused undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, // 80-bf: unused undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, // c0-ff: RDP commands mixed with uc2 commands rdp_noop, undef, undef, undef, undef, undef, undef, undef, rdp_trifill, rdp_trifillz, rdp_tritxtr, rdp_tritxtrz, rdp_trishade, rdp_trishadez, rdp_trishadetxtr, rdp_trishadetxtrz, undef, undef, undef, uc2_special3, uc2_special2, uc2_dlist_cnt, uc2_dma_io, uc0_texture, uc2_pop_matrix, uc2_geom_mode, uc2_matrix, uc2_moveword, uc2_movemem, uc2_load_ucode, uc0_displaylist, uc0_enddl, spnoop, uc1_rdphalf_1, uc0_setothermode_l,uc0_setothermode_h, rdp_texrect, rdp_texrect, rdp_loadsync, rdp_pipesync, rdp_tilesync, rdp_fullsync, rdp_setkeygb, rdp_setkeyr, rdp_setconvert, rdp_setscissor, rdp_setprimdepth, rdp_setothermode, rdp_loadtlut, uc2_rdphalf_2, rdp_settilesize, rdp_loadblock, rdp_loadtile, rdp_settile, rdp_fillrect, rdp_setfillcolor, rdp_setfogcolor, rdp_setblendcolor, rdp_setprimcolor, rdp_setenvcolor, rdp_setcombine, rdp_settextureimage, rdp_setdepthimage, rdp_setcolorimage }, // uCode 3 - "RSP SW 2.0D", but not really // 00-3f // games: Wave Race // ** Added by Gonetz ** { spnoop, uc0_matrix, rsp_reserved0, uc0_movemem, uc3_vertex, rsp_reserved1, uc0_displaylist, rsp_reserved2, rsp_reserved3, uc6_sprite2d, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, // 40-7f: unused undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, // 80-bf: Immediate commands undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, uc3_tri2, uc0_rdphalf_cont, uc0_rdphalf_2, uc0_rdphalf_1, uc3_quad3d, uc0_cleargeometrymode, uc0_setgeometrymode, uc0_enddl, uc0_setothermode_l, uc0_setothermode_h, uc0_texture, uc0_moveword, uc0_popmatrix, uc0_culldl, uc3_tri1, // c0-ff: RDP commands rdp_noop, undef, undef, undef, undef, undef, undef, undef, rdp_trifill, rdp_trifillz, rdp_tritxtr, rdp_tritxtrz, rdp_trishade, rdp_trishadez, rdp_trishadetxtr, rdp_trishadetxtrz, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, rdp_texrect, rdp_texrect, rdp_loadsync, rdp_pipesync, rdp_tilesync, rdp_fullsync, rdp_setkeygb, rdp_setkeyr, rdp_setconvert, rdp_setscissor, rdp_setprimdepth, rdp_setothermode, rdp_loadtlut, undef, rdp_settilesize, rdp_loadblock, rdp_loadtile, rdp_settile, rdp_fillrect, rdp_setfillcolor, rdp_setfogcolor, rdp_setblendcolor, rdp_setprimcolor, rdp_setenvcolor, rdp_setcombine, rdp_settextureimage, rdp_setdepthimage, rdp_setcolorimage }, { // uCode 4 - RSP SW 2.0D EXT // 00-3f // games: Star Wars: Shadows of the Empire spnoop, uc0_matrix, rsp_reserved0, uc0_movemem, uc4_vertex, rsp_reserved1, uc0_displaylist, rsp_reserved2, rsp_reserved3, uc6_sprite2d, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, // 40-7f: Unused undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, // 80-bf: Immediate commands undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, uc0_tri4, uc0_rdphalf_cont, uc0_rdphalf_2, uc0_rdphalf_1, uc4_quad3d, uc0_cleargeometrymode, uc0_setgeometrymode, uc0_enddl, uc0_setothermode_l, uc0_setothermode_h, uc0_texture, uc0_moveword, uc0_popmatrix, uc0_culldl, uc4_tri1, // c0-ff: RDP commands rdp_noop, undef, undef, undef, undef, undef, undef, undef, rdp_trifill, rdp_trifillz, rdp_tritxtr, rdp_tritxtrz, rdp_trishade, rdp_trishadez, rdp_trishadetxtr, rdp_trishadetxtrz, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, rdp_texrect, rdp_texrect, rdp_loadsync, rdp_pipesync, rdp_tilesync, rdp_fullsync, rdp_setkeygb, rdp_setkeyr, rdp_setconvert, rdp_setscissor, rdp_setprimdepth, rdp_setothermode, rdp_loadtlut, undef, rdp_settilesize, rdp_loadblock, rdp_loadtile, rdp_settile, rdp_fillrect, rdp_setfillcolor, rdp_setfogcolor, rdp_setblendcolor, rdp_setprimcolor, rdp_setenvcolor, rdp_setcombine, rdp_settextureimage, rdp_setdepthimage, rdp_setcolorimage }, { // uCode 5 - RSP SW 2.0 Diddy // 00-3f // games: Diddy Kong Racing spnoop, uc5_matrix, rsp_reserved0, uc0_movemem, uc5_vertex, uc5_tridma, uc0_displaylist, uc5_dl_in_mem, rsp_reserved3, uc6_sprite2d, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, // 40-7f: Unused undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, // 80-bf: Immediate commands undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, uc0_tri4, uc0_rdphalf_cont, uc0_rdphalf_2, uc0_rdphalf_1, uc0_quad3d, uc5_cleargeometrymode, uc5_setgeometrymode, uc0_enddl, uc0_setothermode_l, uc0_setothermode_h, uc0_texture, uc5_moveword, uc0_popmatrix, uc0_culldl, uc5_dma_offsets, // c0-ff: RDP commands rdp_noop, undef, undef, undef, undef, undef, undef, undef, rdp_trifill, rdp_trifillz, rdp_tritxtr, rdp_tritxtrz, rdp_trishade, rdp_trishadez, rdp_trishadetxtr, rdp_trishadetxtrz, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, rdp_texrect, rdp_texrect, rdp_loadsync, rdp_pipesync, rdp_tilesync, rdp_fullsync, rdp_setkeygb, rdp_setkeyr, rdp_setconvert, rdp_setscissor, rdp_setprimdepth, rdp_setothermode, rdp_loadtlut, undef, rdp_settilesize, rdp_loadblock, rdp_loadtile, rdp_settile, rdp_fillrect, rdp_setfillcolor, rdp_setfogcolor, rdp_setblendcolor, rdp_setprimcolor, rdp_setenvcolor, rdp_setcombine, rdp_settextureimage, rdp_setdepthimage, rdp_setcolorimage }, // uCode 6 - S2DEX 1.XX // games: Yoshi's Story { spnoop, uc6_bg_1cyc, uc6_bg_copy, uc6_obj_rectangle, uc6_obj_sprite, uc6_obj_movemem, uc0_displaylist, rsp_reserved2, rsp_reserved3, undef/*uc6_sprite2d*/, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, // 40-7f: unused undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, // 80-bf: Immediate commands undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, uc6_loaducode, uc6_select_dl, uc6_obj_rendermode, uc6_obj_rectangle_r, uc0_rdphalf_2, uc6_rdphalf_1, uc1_line3d, uc0_cleargeometrymode, uc0_setgeometrymode, uc0_enddl, uc0_setothermode_l, uc0_setothermode_h, uc0_texture, uc0_moveword, uc0_popmatrix, uc2_culldl, uc1_tri1, // c0-ff: RDP commands rdp_noop, uc6_obj_loadtxtr, uc6_obj_ldtx_sprite, uc6_obj_ldtx_rect, uc6_ldtx_rect_r, undef, undef, undef, rdp_trifill, rdp_trifillz, rdp_tritxtr, rdp_tritxtrz, rdp_trishade, rdp_trishadez, rdp_trishadetxtr, rdp_trishadetxtrz, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, rdp_texrect, rdp_texrect, rdp_loadsync, rdp_pipesync, rdp_tilesync, rdp_fullsync, rdp_setkeygb, rdp_setkeyr, rdp_setconvert, rdp_setscissor, rdp_setprimdepth, rdp_setothermode, rdp_loadtlut, undef, rdp_settilesize, rdp_loadblock, rdp_loadtile, rdp_settile, rdp_fillrect, rdp_setfillcolor, rdp_setfogcolor, rdp_setblendcolor, rdp_setprimcolor, rdp_setenvcolor, rdp_setcombine, rdp_settextureimage, rdp_setdepthimage, rdp_setcolorimage }, // uCode 7 - unknown // games: Perfect Dark { // 00-3f spnoop, uc0_matrix, rsp_reserved0, uc0_movemem, uc7_vertex, rsp_reserved1, uc0_displaylist, uc7_colorbase, rsp_reserved3, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, // 40-7f: unused undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, // 80-bf: unused undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, uc0_tri4, uc0_rdphalf_cont, uc0_rdphalf_2, uc0_rdphalf_1, uc1_tri2, uc0_cleargeometrymode, uc0_setgeometrymode, uc0_enddl, uc0_setothermode_l, uc0_setothermode_h, uc0_texture, uc0_moveword, uc0_popmatrix, uc0_culldl, uc0_tri1, // c0-ff: RDP commands mixed with uc2 commands rdp_noop, undef, undef, undef, undef, undef, undef, undef, rdp_trifill, rdp_trifillz, rdp_tritxtr, rdp_tritxtrz, rdp_trishade, rdp_trishadez, rdp_trishadetxtr, rdp_trishadetxtrz, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, rdp_texrect, rdp_texrect, rdp_loadsync, rdp_pipesync, rdp_tilesync, rdp_fullsync, rdp_setkeygb, rdp_setkeyr, rdp_setconvert, rdp_setscissor, rdp_setprimdepth, rdp_setothermode, rdp_loadtlut, uc0_rdphalf_2, rdp_settilesize, rdp_loadblock, rdp_loadtile, rdp_settile, rdp_fillrect, rdp_setfillcolor, rdp_setfogcolor, rdp_setblendcolor, rdp_setprimcolor, rdp_setenvcolor, rdp_setcombine, rdp_settextureimage, rdp_setdepthimage, rdp_setcolorimage }, // uCode 8 - unknown // games: Conker's Bad Fur Day { // 00-3f spnoop, uc8_vertex, uc2_modifyvtx, uc2_culldl, uc1_branch_z, uc2_tri1, uc2_quad, uc2_quad, uc2_line3d, uc6_bg_1cyc, uc6_bg_copy, uc6_obj_rendermode/*undef*/, undef, undef, undef, undef, uc8_tri4, uc8_tri4, uc8_tri4, uc8_tri4, uc8_tri4, uc8_tri4, uc8_tri4, uc8_tri4, uc8_tri4, uc8_tri4, uc8_tri4, uc8_tri4, uc8_tri4, uc8_tri4, uc8_tri4, uc8_tri4, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, // 40-7f: unused undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, // 80-bf: unused undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, undef, // c0-ff: RDP commands mixed with uc2 commands rdp_noop, undef, undef, undef, undef, undef, undef, undef, rdp_trifill, rdp_trifillz, rdp_tritxtr, rdp_tritxtrz, rdp_trishade, rdp_trishadez, rdp_trishadetxtr, rdp_trishadetxtrz, undef, undef, undef, uc2_special3, uc2_special2, uc2_dlist_cnt, uc2_dma_io, uc0_texture, uc2_pop_matrix, uc2_geom_mode, uc2_matrix, uc8_moveword, uc8_movemem, uc2_load_ucode, uc0_displaylist, uc0_enddl, spnoop, uc1_rdphalf_1, uc0_setothermode_l, uc0_setothermode_h, rdp_texrect, rdp_texrect, rdp_loadsync, rdp_pipesync, rdp_tilesync, rdp_fullsync, rdp_setkeygb, rdp_setkeyr, rdp_setconvert, rdp_setscissor, rdp_setprimdepth, rdp_setothermode, rdp_loadtlut, uc2_rdphalf_2, rdp_settilesize, rdp_loadblock, rdp_loadtile, rdp_settile, rdp_fillrect, rdp_setfillcolor, rdp_setfogcolor, rdp_setblendcolor, rdp_setprimcolor, rdp_setenvcolor, rdp_setcombine, rdp_settextureimage, rdp_setdepthimage, rdp_setcolorimage }, }; mupen64plus-video-glide64-src-2.6.0/src/ucode01.h000066400000000000000000000171411464507525600212700ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** // // vertex - loads vertices // static void uc1_vertex() { DWORD addr = segoffset(rdp.cmd1) & 0x00FFFFFF; int v0, i, n; float x, y, z; rdp.v0 = v0 = (rdp.cmd0 >> 17) & 0x7F; // Current vertex rdp.vn = n = (WORD)(rdp.cmd0 >> 10) & 0x3F; // Number to copy // This is special, not handled in update(), but here // * Matrix Pre-multiplication idea by Gonetz (Gonetz@ngs.ru) if (rdp.update & UPDATE_MULT_MAT) { rdp.update ^= UPDATE_MULT_MAT; MulMatrices(rdp.model, rdp.proj, rdp.combined); } // * // This is special, not handled in update() if (rdp.update & UPDATE_LIGHTS) { rdp.update ^= UPDATE_LIGHTS; // Calculate light vectors for (DWORD l=0; l>4)]; x = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 0)^1]; y = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 1)^1]; z = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 2)^1]; v->flags = ((WORD*)gfx.RDRAM)[(((addr+i) >> 1) + 3)^1]; v->ou = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 4)^1] * rdp.tiles[rdp.cur_tile].s_scale; v->ov = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 5)^1] * rdp.tiles[rdp.cur_tile].t_scale; v->a = ((BYTE*)gfx.RDRAM)[(addr+i + 15)^3]; v->x = x*rdp.combined[0][0] + y*rdp.combined[1][0] + z*rdp.combined[2][0] + rdp.combined[3][0]; v->y = x*rdp.combined[0][1] + y*rdp.combined[1][1] + z*rdp.combined[2][1] + rdp.combined[3][1]; v->z = x*rdp.combined[0][2] + y*rdp.combined[1][2] + z*rdp.combined[2][2] + rdp.combined[3][2]; v->w = x*rdp.combined[0][3] + y*rdp.combined[1][3] + z*rdp.combined[2][3] + rdp.combined[3][3]; v->oow = 1.0f / v->w; v->x_w = v->x * v->oow; v->y_w = v->y * v->oow; v->z_w = v->z * v->oow; CalculateFog (v); v->uv_calculated = 0xFFFFFFFF; v->screen_translated = 0; v->shade_mods_allowed = 1; v->uv_fixed = 0; v->scr_off = 0; if (v->x < -v->w) v->scr_off |= 1; if (v->x > v->w) v->scr_off |= 2; if (v->y < -v->w) v->scr_off |= 4; if (v->y > v->w) v->scr_off |= 8; if (v->w < 0.1f) v->scr_off |= 16; if (rdp.geom_mode & 0x00020000) { v->vec[0] = ((char*)gfx.RDRAM)[(addr+i + 12)^3]; v->vec[1] = ((char*)gfx.RDRAM)[(addr+i + 13)^3]; v->vec[2] = ((char*)gfx.RDRAM)[(addr+i + 14)^3]; if (rdp.geom_mode & 0x80000) calc_linear (v); else if (rdp.geom_mode & 0x40000) calc_sphere (v); NormalizeVector (v->vec); calc_light (v); } else { v->r = ((BYTE*)gfx.RDRAM)[(addr+i + 12)^3]; v->g = ((BYTE*)gfx.RDRAM)[(addr+i + 13)^3]; v->b = ((BYTE*)gfx.RDRAM)[(addr+i + 14)^3]; } #ifdef EXTREME_LOGGING FRDP ("v%d - x: %f, y: %f, z: %f, w: %f, u: %f, v: %f\n", i>>4, v->x, v->y, v->z, v->w, v->ou, v->ov); #endif } } // // tri1 - renders a triangle // static void uc1_tri1() { if (rdp.skip_drawing) { RDP("uc1:tri1. skipped\n"); return; } FRDP("uc1:tri1 #%d - %d, %d, %d - %08lx - %08lx\n", rdp.tri_n, ((rdp.cmd1 >> 17) & 0x7F), ((rdp.cmd1 >> 9) & 0x7F), ((rdp.cmd1 >> 1) & 0x7F), rdp.cmd0, rdp.cmd1); VERTEX *v[3] = { &rdp.vtx[(rdp.cmd1 >> 17) & 0x7F], &rdp.vtx[(rdp.cmd1 >> 9) & 0x7F], &rdp.vtx[(rdp.cmd1 >> 1) & 0x7F] }; if (cull_tri(v)) rdp.tri_n ++; else { update (); DrawTri (v); rdp.tri_n ++; } } static void uc1_tri2 () { if (rdp.skip_drawing) { RDP("uc1:tri2. skipped\n"); return; } RDP ("uc1:tri2"); FRDP(" #%d, #%d - %d, %d, %d - %d, %d, %d\n", rdp.tri_n, rdp.tri_n+1, ((rdp.cmd0 >> 17) & 0x7F), ((rdp.cmd0 >> 9) & 0x7F), ((rdp.cmd0 >> 1) & 0x7F), ((rdp.cmd1 >> 17) & 0x7F), ((rdp.cmd1 >> 9) & 0x7F), ((rdp.cmd1 >> 1) & 0x7F)); VERTEX *v[6] = { &rdp.vtx[(rdp.cmd0 >> 17) & 0x7F], &rdp.vtx[(rdp.cmd0 >> 9) & 0x7F], &rdp.vtx[(rdp.cmd0 >> 1) & 0x7F], &rdp.vtx[(rdp.cmd1 >> 17) & 0x7F], &rdp.vtx[(rdp.cmd1 >> 9) & 0x7F], &rdp.vtx[(rdp.cmd1 >> 1) & 0x7F] }; BOOL updated = 0; if (cull_tri(v)) rdp.tri_n ++; else { updated = 1; update (); DrawTri (v); rdp.tri_n ++; } if (cull_tri(v+3)) rdp.tri_n ++; else { if (!updated) update (); DrawTri (v+3); rdp.tri_n ++; } } static void uc1_line3d() { if (((rdp.cmd1&0xFF000000) == 0) && ((rdp.cmd0&0x00FFFFFF) == 0)) { WORD width = (WORD)(rdp.cmd1&0xFF) + 1; FRDP("uc1:line3d #%d, #%d - %d, %d\n", rdp.tri_n, rdp.tri_n+1, (rdp.cmd1 >> 17) & 0x7F, (rdp.cmd1 >> 9) & 0x7F); VERTEX *v[3] = { &rdp.vtx[(rdp.cmd1 >> 17) & 0x7F], &rdp.vtx[(rdp.cmd1 >> 9) & 0x7F], &rdp.vtx[(rdp.cmd1 >> 9) & 0x7F] }; if (cull_tri(v)) rdp.tri_n ++; else { update (); DrawTri (v, width); rdp.tri_n ++; } } else { FRDP("uc1:quad3d #%d, #%d\n", rdp.tri_n, rdp.tri_n+1); VERTEX *v[6] = { &rdp.vtx[(rdp.cmd1 >> 25) & 0x7F], &rdp.vtx[(rdp.cmd1 >> 17) & 0x7F], &rdp.vtx[(rdp.cmd1 >> 9) & 0x7F], &rdp.vtx[(rdp.cmd1 >> 1) & 0x7F], &rdp.vtx[(rdp.cmd1 >> 25) & 0x7F], &rdp.vtx[(rdp.cmd1 >> 9) & 0x7F] }; BOOL updated = 0; if (cull_tri(v)) rdp.tri_n ++; else { updated = 1; update (); DrawTri (v); rdp.tri_n ++; } if (cull_tri(v+3)) rdp.tri_n ++; else { if (!updated) update (); DrawTri (v+3); rdp.tri_n ++; } } } DWORD branch_dl = 0; static void uc1_rdphalf_1() { RDP ("uc1:rdphalf_1\n"); branch_dl = rdp.cmd1; } static void uc1_branch_z() { DWORD addr = segoffset(branch_dl); FRDP ("uc1:branch_less_z, addr: %08lx\n", addr); DWORD vtx = (rdp.cmd0 & 0xFFF) >> 1; if( fabs(rdp.vtx[vtx].z) <= (rdp.cmd1/*&0xFFFF*/) ) { rdp.pc[rdp.pc_i] = addr; } } mupen64plus-video-glide64-src-2.6.0/src/ucode02.h000066400000000000000000000562541464507525600213010ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** static void calc_point_light (VERTEX *v, float * vpos) { float light_intensity = 0.0f; float color[3] = {rdp.light[rdp.num_lights].r, rdp.light[rdp.num_lights].g, rdp.light[rdp.num_lights].b}; for (DWORD l=0; l 0.0f) light_intensity = 1/at;//DotProduct (lvec, nvec) / (light_len * normal_len * at); else light_intensity = 0.0f; } else { light_intensity = 0.0f; } if (light_intensity > 0.0f) { color[0] += rdp.light[l].r * light_intensity; color[1] += rdp.light[l].g * light_intensity; color[2] += rdp.light[l].b * light_intensity; } } if (color[0] > 1.0f) color[0] = 1.0f; if (color[1] > 1.0f) color[1] = 1.0f; if (color[2] > 1.0f) color[2] = 1.0f; v->r = (BYTE)(color[0]*255.0f); v->g = (BYTE)(color[1]*255.0f); v->b = (BYTE)(color[2]*255.0f); } static void uc2_vertex () { // This is special, not handled in update(), but here // * Matrix Pre-multiplication idea by Gonetz (Gonetz@ngs.ru) if (rdp.update & UPDATE_MULT_MAT) { rdp.update ^= UPDATE_MULT_MAT; MulMatrices(rdp.model, rdp.proj, rdp.combined); } if (rdp.update & UPDATE_LIGHTS) { rdp.update ^= UPDATE_LIGHTS; // Calculate light vectors for (DWORD l=0; l> 12) & 0xFF; rdp.v0 = v0 = ((rdp.cmd0 >> 1) & 0x7F) - n; FRDP ("uc2:vertex n: %d, v0: %d, from: %08lx\n", n, v0, addr); if (v0 < 0) { RDP_E ("** ERROR: uc2:vertex v0 < 0\n"); RDP ("** ERROR: uc2:vertex v0 < 0\n"); return; } DWORD geom_mode = rdp.geom_mode; if (settings.fzero && (rdp.geom_mode & 0x40000)) { if (((short*)gfx.RDRAM)[(((addr) >> 1) + 4)^1] || ((short*)gfx.RDRAM)[(((addr) >> 1) + 5)^1]) rdp.geom_mode ^= 0x40000; } for (i=0; i < (n<<4); i+=16) { VERTEX *v = &rdp.vtx[v0 + (i>>4)]; x = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 0)^1]; y = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 1)^1]; z = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 2)^1]; v->flags = ((WORD*)gfx.RDRAM)[(((addr+i) >> 1) + 3)^1]; v->ou = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 4)^1] * rdp.tiles[rdp.cur_tile].s_scale; v->ov = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 5)^1] * rdp.tiles[rdp.cur_tile].t_scale; v->a = ((BYTE*)gfx.RDRAM)[(addr+i + 15)^3]; #ifdef EXTREME_LOGGING FRDP ("before: v%d - x: %f, y: %f, z: %f, flags: %04lx, ou: %f, ov: %f\n", i>>4, x, y, z, v->flags, v->ou, v->ov); #endif v->x = x*rdp.combined[0][0] + y*rdp.combined[1][0] + z*rdp.combined[2][0] + rdp.combined[3][0]; v->y = x*rdp.combined[0][1] + y*rdp.combined[1][1] + z*rdp.combined[2][1] + rdp.combined[3][1]; v->z = x*rdp.combined[0][2] + y*rdp.combined[1][2] + z*rdp.combined[2][2] + rdp.combined[3][2]; v->w = x*rdp.combined[0][3] + y*rdp.combined[1][3] + z*rdp.combined[2][3] + rdp.combined[3][3]; v->oow = 1.0f / v->w; v->x_w = v->x * v->oow; v->y_w = v->y * v->oow; v->z_w = v->z * v->oow; CalculateFog (v); #ifdef EXTREME_LOGGING FRDP ("v%d - x: %f, y: %f, z: %f, w: %f, u: %f, v: %f, f: %f, z_w: %f, a: 0x%02lx\n", i>>4, v->x, v->y, v->z, v->w, v->ou, v->ov, v->f, v->z_w, v->a); #endif v->uv_calculated = 0xFFFFFFFF; v->screen_translated = 0; v->shade_mods_allowed = 1; v->uv_fixed = 0; v->scr_off = 0; if (v->x < -v->w) v->scr_off |= 1; if (v->x > v->w) v->scr_off |= 2; if (v->y < -v->w) v->scr_off |= 4; if (v->y > v->w) v->scr_off |= 8; if (v->w < 0.1f) v->scr_off |= 16; if (rdp.geom_mode & 0x00020000) { v->vec[0] = ((char*)gfx.RDRAM)[(addr+i + 12)^3]; v->vec[1] = ((char*)gfx.RDRAM)[(addr+i + 13)^3]; v->vec[2] = ((char*)gfx.RDRAM)[(addr+i + 14)^3]; // FRDP("Calc light. x: %f, y: %f z: %f\n", v->vec[0], v->vec[1], v->vec[2]); // if (!(rdp.geom_mode & 0x800000)) { if (rdp.geom_mode & 0x80000) { calc_linear (v); #ifdef EXTREME_LOGGING FRDP ("calc linear: v%d - u: %f, v: %f\n", i>>4, v->ou, v->ov); #endif } else if (rdp.geom_mode & 0x40000) { calc_sphere (v); #ifdef EXTREME_LOGGING FRDP ("calc sphere: v%d - u: %f, v: %f\n", i>>4, v->ou, v->ov); #endif } } if (rdp.geom_mode & 0x00400000) { float tmpvec[3] = {x, y, z}; calc_point_light (v, tmpvec); } else { NormalizeVector (v->vec); calc_light (v); } } else { v->r = ((BYTE*)gfx.RDRAM)[(addr+i + 12)^3]; v->g = ((BYTE*)gfx.RDRAM)[(addr+i + 13)^3]; v->b = ((BYTE*)gfx.RDRAM)[(addr+i + 14)^3]; } } rdp.geom_mode = geom_mode; } static void uc2_modifyvtx () { BYTE where = (BYTE)((rdp.cmd0 >> 16) & 0xFF); WORD vtx = (WORD)((rdp.cmd0 >> 1) & 0xFFFF); FRDP ("uc2:modifyvtx: vtx: %d, where: 0x%02lx, val: %08lx - ", vtx, where, rdp.cmd1); uc0_modifyvtx(where, vtx, rdp.cmd1); } static void uc2_culldl () { WORD vStart = (WORD)(rdp.cmd0 & 0xFFFF) >> 1; WORD vEnd = (WORD)(rdp.cmd1 & 0xFFFF) >> 1; DWORD cond = 0; FRDP ("uc2:culldl start: %d, end: %d\n", vStart, vEnd); if (vEnd < vStart) return; for (WORD i=vStart; i<=vEnd; i++) { /* VERTEX v = &rdp.vtx[i]; // Check if completely off the screen (quick frustrum clipping for 90 FOV) if (v->x >= -v->w) cond |= 0x01; if (v->x <= v->w) cond |= 0x02; if (v->y >= -v->w) cond |= 0x04; if (v->y <= v->w) cond |= 0x08; if (v->w >= 0.1f) cond |= 0x10; if (cond == 0x1F) return; //*/ #ifdef EXTREME_LOGGING FRDP (" v[%d] = (%02f, %02f, %02f, 0x%02lx)\n", i, rdp.vtx[i].x, rdp.vtx[i].y, rdp.vtx[i].w, rdp.vtx[i].scr_off); #endif cond |= (~rdp.vtx[i].scr_off) & 0x1F; if (cond == 0x1F) return; } RDP (" - "); // specify that the enddl is not a real command uc0_enddl (); } void uc6_obj_loadtxtr (); static void uc2_tri1() { if (rdp.skip_drawing) { RDP("uc2:tri1. skipped\n"); return; } if ((rdp.cmd0 & 0x00FFFFFF) == 0x17) { uc6_obj_loadtxtr (); return; } FRDP("uc1:tri1 #%d - %d, %d, %d\n", rdp.tri_n, ((rdp.cmd0 >> 17) & 0x7F), ((rdp.cmd0 >> 9) & 0x7F), ((rdp.cmd0 >> 1) & 0x7F)); VERTEX *v[3] = { &rdp.vtx[(rdp.cmd0 >> 17) & 0x7F], &rdp.vtx[(rdp.cmd0 >> 9) & 0x7F], &rdp.vtx[(rdp.cmd0 >> 1) & 0x7F] }; if (cull_tri(v)) rdp.tri_n ++; else { update (); DrawTri (v); rdp.tri_n ++; } } void uc6_obj_ldtx_sprite (); void uc6_obj_ldtx_rect (); static void uc2_quad () { if (rdp.skip_drawing) { RDP("uc2_quad. skipped\n"); return; } if ((rdp.cmd0 & 0x00FFFFFF) == 0x2F) { DWORD command = rdp.cmd0>>24; if (command == 0x6) { uc6_obj_ldtx_sprite (); return; } if (command == 0x7) { uc6_obj_ldtx_rect (); return; } } RDP("uc2:quad"); FRDP(" #%d, #%d - %d, %d, %d - %d, %d, %d\n", rdp.tri_n, rdp.tri_n+1, ((rdp.cmd0 >> 17) & 0x7F), ((rdp.cmd0 >> 9) & 0x7F), ((rdp.cmd0 >> 1) & 0x7F), ((rdp.cmd1 >> 17) & 0x7F), ((rdp.cmd1 >> 9) & 0x7F), ((rdp.cmd1 >> 1) & 0x7F)); VERTEX *v[6] = { &rdp.vtx[(rdp.cmd0 >> 17) & 0x7F], &rdp.vtx[(rdp.cmd0 >> 9) & 0x7F], &rdp.vtx[(rdp.cmd0 >> 1) & 0x7F], &rdp.vtx[(rdp.cmd1 >> 17) & 0x7F], &rdp.vtx[(rdp.cmd1 >> 9) & 0x7F], &rdp.vtx[(rdp.cmd1 >> 1) & 0x7F] }; BOOL updated = 0; if (cull_tri(v)) rdp.tri_n ++; else { updated = 1; update (); DrawTri (v); rdp.tri_n ++; } if (cull_tri(v+3)) rdp.tri_n ++; else { if (!updated) update (); DrawTri (v+3); rdp.tri_n ++; } } static void uc6_ldtx_rect_r (); static void uc2_line3d () { if ( (rdp.cmd0&0xFF) == 0x2F ) uc6_ldtx_rect_r (); else { FRDP("uc2:line3d #%d, #%d - %d, %d\n", rdp.tri_n, rdp.tri_n+1, (rdp.cmd0 >> 17) & 0x7F, (rdp.cmd0 >> 9) & 0x7F); VERTEX *v[3] = { &rdp.vtx[(rdp.cmd0 >> 17) & 0x7F], &rdp.vtx[(rdp.cmd0 >> 9) & 0x7F], &rdp.vtx[(rdp.cmd0 >> 9) & 0x7F] }; WORD width = (WORD)(rdp.cmd0&0xFF) + 1; if (cull_tri(v)) rdp.tri_n ++; else { update (); DrawTri (v, width); rdp.tri_n ++; } } } static void uc2_special3 () { RDP ("uc2:special3\n"); } static void uc2_special2 () { RDP ("uc2:special2\n"); } #ifdef _WIN32 static void uc2_special1 () { RDP ("uc2:special1\n"); } #endif // _WIN32 static void uc2_dma_io () { RDP ("uc2:dma_io\n"); } static void uc2_pop_matrix () { FRDP ("uc2:pop_matrix %08lx, %08lx\n", rdp.cmd0, rdp.cmd1); // Just pop the modelview matrix modelview_pop (rdp.cmd1 >> 6); } static void uc2_geom_mode () { // Switch around some things DWORD clr_mode = (rdp.cmd0 & 0x00DFC9FF) | ((rdp.cmd0 & 0x00000600) << 3) | ((rdp.cmd0 & 0x00200000) >> 12) | 0xFF000000; DWORD set_mode = (rdp.cmd1 & 0xFFDFC9FF) | ((rdp.cmd1 & 0x00000600) << 3) | ((rdp.cmd1 & 0x00200000) >> 12); FRDP("uc2:geom_mode c:%08lx, s:%08lx ", clr_mode, set_mode); rdp.geom_mode &= clr_mode; rdp.geom_mode |= set_mode; FRDP ("result:%08lx\n", rdp.geom_mode); if (rdp.geom_mode & 0x00000001) // Z-Buffer enable { if (!(rdp.flags & ZBUF_ENABLED)) { rdp.flags |= ZBUF_ENABLED; rdp.update |= UPDATE_ZBUF_ENABLED; } } else { if ((rdp.flags & ZBUF_ENABLED)) { if (!settings.flame_corona || (rdp.rm != 0x00504341)) //hack for flame's corona rdp.flags ^= ZBUF_ENABLED; rdp.update |= UPDATE_ZBUF_ENABLED; } } if (rdp.geom_mode & 0x00001000) // Front culling { if (!(rdp.flags & CULL_FRONT)) { rdp.flags |= CULL_FRONT; rdp.update |= UPDATE_CULL_MODE; } } else { if (rdp.flags & CULL_FRONT) { rdp.flags ^= CULL_FRONT; rdp.update |= UPDATE_CULL_MODE; } } if (rdp.geom_mode & 0x00002000) // Back culling { if (!(rdp.flags & CULL_BACK)) { rdp.flags |= CULL_BACK; rdp.update |= UPDATE_CULL_MODE; } } else { if (rdp.flags & CULL_BACK) { rdp.flags ^= CULL_BACK; rdp.update |= UPDATE_CULL_MODE; } } //Added by Gonetz if (rdp.geom_mode & 0x00010000) // Fog enable { if (!(rdp.flags & FOG_ENABLED)) { rdp.flags |= FOG_ENABLED; rdp.update |= UPDATE_FOG_ENABLED; } } else { if (rdp.flags & FOG_ENABLED) { rdp.flags ^= FOG_ENABLED; rdp.update |= UPDATE_FOG_ENABLED; } } } void uc6_obj_rectangle_r (); static void uc2_matrix () { if (!(rdp.cmd0 & 0x00FFFFFF)) { uc6_obj_rectangle_r(); return; } RDP ("uc2:matrix\n"); DWORD addr = segoffset(rdp.cmd1); BYTE command = (BYTE)((rdp.cmd0 ^ 1) & 0xFF); __declspec( align(16) ) float m[4][4]; int x,y; // matrix index addr >>= 1; for (x=0; x<16; x+=4) { // Adding 4 instead of one, just to remove mult. later for (y=0; y<4; y++) { m[x>>2][y] = (float)( (((__int32)((WORD*)gfx.RDRAM)[(addr+x+y)^1]) << 16) | ((WORD*)gfx.RDRAM)[(addr+x+y+16)^1] ) / 65536.0f; } } switch (command) { case 0: // modelview mul nopush RDP ("modelview mul\n"); modelview_mul (m); break; case 1: // modelview mul push RDP ("modelview mul push\n"); modelview_mul_push (m); break; case 2: // modelview load nopush RDP ("modelview load\n"); modelview_load (m); break; case 3: // modelview load push RDP ("modelview load push\n"); modelview_load_push (m); break; case 4: // projection mul nopush case 5: // projection mul push, can't push projection RDP ("projection mul\n"); projection_mul (m); break; case 6: // projection load nopush case 7: // projection load push, can't push projection RDP ("projection load\n"); projection_load (m); break; default: FRDP_E ("Unknown matrix command, %02lx", command); FRDP ("Unknown matrix command, %02lx", command); } #ifdef EXTREME_LOGGING FRDP ("{%f,%f,%f,%f}\n", m[0][0], m[0][1], m[0][2], m[0][3]); FRDP ("{%f,%f,%f,%f}\n", m[1][0], m[1][1], m[1][2], m[1][3]); FRDP ("{%f,%f,%f,%f}\n", m[2][0], m[2][1], m[2][2], m[2][3]); FRDP ("{%f,%f,%f,%f}\n", m[3][0], m[3][1], m[3][2], m[3][3]); FRDP ("\nmodel\n{%f,%f,%f,%f}\n", rdp.model[0][0], rdp.model[0][1], rdp.model[0][2], rdp.model[0][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.model[1][0], rdp.model[1][1], rdp.model[1][2], rdp.model[1][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.model[2][0], rdp.model[2][1], rdp.model[2][2], rdp.model[2][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.model[3][0], rdp.model[3][1], rdp.model[3][2], rdp.model[3][3]); FRDP ("\nproj\n{%f,%f,%f,%f}\n", rdp.proj[0][0], rdp.proj[0][1], rdp.proj[0][2], rdp.proj[0][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.proj[1][0], rdp.proj[1][1], rdp.proj[1][2], rdp.proj[1][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.proj[2][0], rdp.proj[2][1], rdp.proj[2][2], rdp.proj[2][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.proj[3][0], rdp.proj[3][1], rdp.proj[3][2], rdp.proj[3][3]); #endif } static void uc2_moveword () { BYTE index = (BYTE)((rdp.cmd0 >> 16) & 0xFF); WORD offset = (WORD)(rdp.cmd0 & 0xFFFF); DWORD data = rdp.cmd1; FRDP ("uc2:moveword "); switch (index) { // NOTE: right now it's assuming that it sets the integer part first. This could // be easily fixed, but only if i had something to test with. case 0x00: // moveword matrix { // do matrix pre-mult so it's re-updated next time if (rdp.update & UPDATE_MULT_MAT) { rdp.update ^= UPDATE_MULT_MAT; MulMatrices(rdp.model, rdp.proj, rdp.combined); } if (rdp.cmd0 & 0x20) // fractional part { int index_x = (rdp.cmd0 & 0x1F) >> 1; int index_y = index_x >> 2; index_x &= 3; float fpart = (rdp.cmd1>>16)/65536.0f; rdp.combined[index_y][index_x] = (float)(int)rdp.combined[index_y][index_x]; rdp.combined[index_y][index_x] += fpart; fpart = (rdp.cmd1&0xFFFF)/65536.0f; rdp.combined[index_y][index_x+1] = (float)(int)rdp.combined[index_y][index_x+1]; rdp.combined[index_y][index_x+1] += fpart; } else { int index_x = (rdp.cmd0 & 0x1F) >> 1; int index_y = index_x >> 2; index_x &= 3; rdp.combined[index_y][index_x] = (short)(rdp.cmd1>>16); rdp.combined[index_y][index_x+1] = (short)(rdp.cmd1&0xFFFF); } RDP ("matrix\n"); } break; case 0x02: rdp.num_lights = data / 24; rdp.update |= UPDATE_LIGHTS; FRDP ("numlights: %d\n", rdp.num_lights); break; case 0x04: FRDP ("mw_clip %08lx, %08lx\n", rdp.cmd0, rdp.cmd1); break; case 0x06: // moveword SEGMENT { FRDP ("SEGMENT %08lx -> seg%d\n", data, offset >> 2); if ((data&BMASK)> 2) & 0xF] = data; } break; case 0x08: { rdp.fog_multiplier = (short)(rdp.cmd1 >> 16); rdp.fog_offset = (short)(rdp.cmd1 & 0x0000FFFF); FRDP ("fog: multiplier: %f, offset: %f\n", rdp.fog_multiplier, rdp.fog_offset); } break; case 0x0a: // moveword LIGHTCOL { int n = offset / 24; FRDP ("lightcol light:%d, %08lx\n", n, data); rdp.light[n].r = (float)((data >> 24) & 0xFF) / 255.0f; rdp.light[n].g = (float)((data >> 16) & 0xFF) / 255.0f; rdp.light[n].b = (float)((data >> 8) & 0xFF) / 255.0f; rdp.light[n].a = 255; } break; case 0x0c: RDP_E ("uc2:moveword forcemtx - IGNORED\n"); RDP ("forcemtx - IGNORED\n"); break; case 0x0e: RDP ("perspnorm - IGNORED\n"); break; default: FRDP_E("uc2:moveword unknown (index: 0x%08lx, offset 0x%08lx)\n", index, offset); FRDP ("unknown (index: 0x%08lx, offset 0x%08lx)\n", index, offset); } } void uc6_obj_movemem (); static void uc2_movemem () { int idx = rdp.cmd0 & 0xFF; DWORD addr = segoffset(rdp.cmd1); int ofs = (rdp.cmd0 >> 5) & 0x7F8; FRDP ("uc2:movemem ofs:%d ", ofs); switch (idx) { case 0: case 2: uc6_obj_movemem (); break; case 8: // VIEWPORT { DWORD a = addr >> 1; short scale_x = ((short*)gfx.RDRAM)[(a+0)^1] >> 2; short scale_y = ((short*)gfx.RDRAM)[(a+1)^1] >> 2; short scale_z = ((short*)gfx.RDRAM)[(a+2)^1]; short trans_x = ((short*)gfx.RDRAM)[(a+4)^1] >> 2; short trans_y = ((short*)gfx.RDRAM)[(a+5)^1] >> 2; short trans_z = ((short*)gfx.RDRAM)[(a+6)^1]; rdp.view_scale[0] = scale_x * rdp.scale_x; rdp.view_scale[1] = -scale_y * rdp.scale_y; rdp.view_scale[2] = 32.0f * scale_z; rdp.view_trans[0] = trans_x * rdp.scale_x; rdp.view_trans[1] = trans_y * rdp.scale_y; rdp.view_trans[2] = 32.0f * trans_z; rdp.update |= UPDATE_VIEWPORT; FRDP ("viewport scale(%d, %d, %d), trans(%d, %d, %d), from:%08lx\n", scale_x, scale_y, scale_z, trans_x, trans_y, trans_z, a); } break; case 10: // LIGHT { int n = ofs / 24; if (n < 2) { char dir_x = ((char*)gfx.RDRAM)[(addr+8)^3]; rdp.lookat[n][0] = (float)(dir_x) / 127.0f; char dir_y = ((char*)gfx.RDRAM)[(addr+9)^3]; rdp.lookat[n][1] = (float)(dir_y) / 127.0f; char dir_z = ((char*)gfx.RDRAM)[(addr+10)^3]; rdp.lookat[n][2] = (float)(dir_z) / 127.0f; rdp.use_lookat = TRUE; if (n == 1) { if (!dir_x && !dir_y) rdp.use_lookat = FALSE; } FRDP("lookat_%d (%f, %f, %f)\n", n, rdp.lookat[n][0], rdp.lookat[n][1], rdp.lookat[n][2]); return; } n -= 2; if (n > 7) return; // Get the data BYTE col = gfx.RDRAM[(addr+0)^3]; rdp.light[n].r = (float)col / 255.0f; rdp.light[n].nonblack = col; col = gfx.RDRAM[(addr+1)^3]; rdp.light[n].g = (float)col / 255.0f; rdp.light[n].nonblack += col; col = gfx.RDRAM[(addr+2)^3]; rdp.light[n].b = (float)col / 255.0f; rdp.light[n].nonblack += col; rdp.light[n].a = 1.0f; // ** Thanks to Icepir8 for pointing this out ** // Lighting must be signed byte instead of byte rdp.light[n].dir_x = (float)(((char*)gfx.RDRAM)[(addr+8)^3]) / 127.0f; rdp.light[n].dir_y = (float)(((char*)gfx.RDRAM)[(addr+9)^3]) / 127.0f; rdp.light[n].dir_z = (float)(((char*)gfx.RDRAM)[(addr+10)^3]) / 127.0f; DWORD a = addr >> 1; rdp.light[n].x = (float)(((short*)gfx.RDRAM)[(a+4)^1]); rdp.light[n].y = (float)(((short*)gfx.RDRAM)[(a+5)^1]); rdp.light[n].z = (float)(((short*)gfx.RDRAM)[(a+6)^1]); rdp.light[n].ca = (float)(gfx.RDRAM[(addr+3)^3]) / 16.0f; rdp.light[n].la = (float)(gfx.RDRAM[(addr+7)^3]); rdp.light[n].qa = (float)(gfx.RDRAM[(addr+14)^3]) / 8.0f; #ifdef EXTREME_LOGGING FRDP ("light: n: %d, pos: x: %f, y: %f, z: %f, ca: %f, la:%f, qa: %f\n", n, rdp.light[n].x, rdp.light[n].y, rdp.light[n].z, rdp.light[n].ca, rdp.light[n].la, rdp.light[n].qa); #endif FRDP ("light: n: %d, r: %.3f, g: %.3f, b: %.3f. dir: x: %.3f, y: %.3f, z: %.3f\n", n, rdp.light[n].r, rdp.light[n].g, rdp.light[n].b, rdp.light[n].dir_x, rdp.light[n].dir_y, rdp.light[n].dir_z); } break; case 14: // matrix { // do not update the combined matrix! rdp.update &= ~UPDATE_MULT_MAT; int addr = segoffset(rdp.cmd1); FRDP ("matrix - addr: %08lx\n", addr); addr >>= 1; int x,y; for (x=0; x<16; x+=4) { // Adding 4 instead of one, just to remove mult. later for (y=0; y<4; y++) { rdp.combined[x>>2][y] = (float)( (((__int32)((WORD*)gfx.RDRAM)[(addr+x+y)^1]) << 16) | ((WORD*)gfx.RDRAM)[(addr+x+y+16)^1] ) / 65536.0f; } } #ifdef EXTREME_LOGGING FRDP ("{%f,%f,%f,%f}\n", rdp.combined[0][0], rdp.combined[0][1], rdp.combined[0][2], rdp.combined[0][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.combined[1][0], rdp.combined[1][1], rdp.combined[1][2], rdp.combined[1][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.combined[2][0], rdp.combined[2][1], rdp.combined[2][2], rdp.combined[2][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.combined[3][0], rdp.combined[3][1], rdp.combined[3][2], rdp.combined[3][3]); #endif } break; default: FRDP ("uc2:matrix unknown (%d)\n", idx); FRDP ("** UNKNOWN %d\n", idx); } } static void uc2_load_ucode () { RDP ("uc2:load_ucode\n"); } static void uc2_rdphalf_2 () { RDP ("uc2:rdphalf_2\n"); } static void uc2_dlist_cnt () { DWORD addr = segoffset(rdp.cmd1) & BMASK; int count = rdp.cmd0 & 0x000000FF; FRDP ("dl_count - addr: %08lx, count: %d\n", addr, count); if (addr == 0) return; if (rdp.pc_i >= 9) { RDP_E ("** DL stack overflow **\n"); RDP ("** DL stack overflow **\n"); return; } rdp.pc_i ++; // go to the next PC in the stack rdp.pc[rdp.pc_i] = addr; // jump to the address rdp.dl_count = count + 1; } mupen64plus-video-glide64-src-2.6.0/src/ucode03.h000066400000000000000000000153621464507525600212750ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** // // March 2002 Created by Gonetz (Gonetz@ngs.ru) // Info about this ucode is taken from Daedalus source. Thanks to Daedalus team. // //**************************************************************** // // vertex - loads vertices // static void uc3_vertex() { DWORD addr = segoffset(rdp.cmd1) & 0x00FFFFFF; int v0, i, n; float x, y, z; rdp.v0 = v0 = ((rdp.cmd0 >> 16) & 0xFF)/5; // Current vertex rdp.vn = n = (WORD)((rdp.cmd0&0xFFFF) + 1)/0x210; // Number to copy FRDP ("uc3:vertex v0:%d, n:%d, from: %08lx\n", v0, n, addr); if (v0 >= 32) v0 = 31; if ((v0 + n) > 32) { n = 32 - v0; } // This is special, not handled in update(), but here // * Matrix Pre-multiplication idea by Gonetz (Gonetz@ngs.ru) if (rdp.update & UPDATE_MULT_MAT) { rdp.update ^= UPDATE_MULT_MAT; MulMatrices(rdp.model, rdp.proj, rdp.combined); } // * // This is special, not handled in update() if (rdp.update & UPDATE_LIGHTS) { rdp.update ^= UPDATE_LIGHTS; // Calculate light vectors for (DWORD l=0; l>4)]; x = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 0)^1]; y = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 1)^1]; z = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 2)^1]; v->flags = ((WORD*)gfx.RDRAM)[(((addr+i) >> 1) + 3)^1]; v->ou = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 4)^1] * rdp.tiles[rdp.cur_tile].s_scale; v->ov = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 5)^1] * rdp.tiles[rdp.cur_tile].t_scale; v->a = ((BYTE*)gfx.RDRAM)[(addr+i + 15)^3]; v->x = x*rdp.combined[0][0] + y*rdp.combined[1][0] + z*rdp.combined[2][0] + rdp.combined[3][0]; v->y = x*rdp.combined[0][1] + y*rdp.combined[1][1] + z*rdp.combined[2][1] + rdp.combined[3][1]; v->z = x*rdp.combined[0][2] + y*rdp.combined[1][2] + z*rdp.combined[2][2] + rdp.combined[3][2]; v->w = x*rdp.combined[0][3] + y*rdp.combined[1][3] + z*rdp.combined[2][3] + rdp.combined[3][3]; v->oow = 1.0f / v->w; v->x_w = v->x * v->oow; v->y_w = v->y * v->oow; v->z_w = v->z * v->oow; CalculateFog (v); v->uv_calculated = 0xFFFFFFFF; v->screen_translated = 0; v->shade_mods_allowed = 1; v->scr_off = 0; if (v->x < -v->w) v->scr_off |= 1; if (v->x > v->w) v->scr_off |= 2; if (v->y < -v->w) v->scr_off |= 4; if (v->y > v->w) v->scr_off |= 8; if (v->w < 0.1f) v->scr_off |= 16; if (rdp.geom_mode & 0x00020000) { v->vec[0] = ((char*)gfx.RDRAM)[(addr+i + 12)^3]; v->vec[1] = ((char*)gfx.RDRAM)[(addr+i + 13)^3]; v->vec[2] = ((char*)gfx.RDRAM)[(addr+i + 14)^3]; if (rdp.geom_mode & 0x80000) calc_linear (v); else if (rdp.geom_mode & 0x40000) calc_sphere (v); NormalizeVector (v->vec); calc_light (v); } else { v->r = ((BYTE*)gfx.RDRAM)[(addr+i + 12)^3]; v->g = ((BYTE*)gfx.RDRAM)[(addr+i + 13)^3]; v->b = ((BYTE*)gfx.RDRAM)[(addr+i + 14)^3]; } } } // // tri1 - renders a triangle // static void uc3_tri1() { FRDP("uc3:tri1 #%d - %d, %d, %d - %08lx - %08lx\n", rdp.tri_n, ((rdp.cmd1 >> 16) & 0xFF)/5, ((rdp.cmd1 >> 8) & 0xFF)/5, ((rdp.cmd1 ) & 0xFF)/5, rdp.cmd0, rdp.cmd1); VERTEX *v[3] = { &rdp.vtx[((rdp.cmd1 >> 16) & 0xFF)/5], &rdp.vtx[((rdp.cmd1 >> 8) & 0xFF)/5], &rdp.vtx[(rdp.cmd1 & 0xFF)/5] }; if (cull_tri(v)) rdp.tri_n ++; else { update (); DrawTri (v); rdp.tri_n ++; } } static void uc3_tri2 () { FRDP("uc3:tri2 #%d, #%d - %d, %d, %d - %d, %d, %d\n", rdp.tri_n, rdp.tri_n+1, ((rdp.cmd0 >> 16) & 0xFF)/5, ((rdp.cmd0 >> 8) & 0xFF)/5, ((rdp.cmd0 ) & 0xFF)/5, ((rdp.cmd1 >> 16) & 0xFF)/5, ((rdp.cmd1 >> 8) & 0xFF)/5, ((rdp.cmd1 ) & 0xFF)/5); VERTEX *v[6] = { &rdp.vtx[((rdp.cmd0 >> 16) & 0xFF)/5], &rdp.vtx[((rdp.cmd0 >> 8) & 0xFF)/5], &rdp.vtx[(rdp.cmd0 & 0xFF)/5], &rdp.vtx[((rdp.cmd1 >> 16) & 0xFF)/5], &rdp.vtx[((rdp.cmd1 >> 8) & 0xFF)/5], &rdp.vtx[(rdp.cmd1 & 0xFF)/5] }; BOOL updated = 0; if (cull_tri(v)) rdp.tri_n ++; else { updated = 1; update (); DrawTri (v); rdp.tri_n ++; } if (cull_tri(v+3)) rdp.tri_n ++; else { if (!updated) update (); DrawTri (v+3); rdp.tri_n ++; } } static void uc3_quad3d() { FRDP("uc3:quad3d #%d, #%d\n", rdp.tri_n, rdp.tri_n+1); VERTEX *v[7] = { &rdp.vtx[((rdp.cmd1 >> 24) & 0xFF)/5], &rdp.vtx[((rdp.cmd1 >> 16) & 0xFF)/5], &rdp.vtx[((rdp.cmd1 >> 8) & 0xFF)/5], &rdp.vtx[(rdp.cmd1 & 0xFF)/5], &rdp.vtx[((rdp.cmd1 >> 24) & 0xFF)/5], &rdp.vtx[((rdp.cmd1 >> 8) & 0xFF)/5], &rdp.vtx[((rdp.cmd1 >> 24) & 0xFF)/5] }; BOOL updated = 0; if (cull_tri(v)) rdp.tri_n ++; else { updated = 1; update (); DrawTri (v); rdp.tri_n ++; } if (cull_tri(v+3)) rdp.tri_n ++; else { if (!updated) update (); DrawTri (v+3); rdp.tri_n ++; } } mupen64plus-video-glide64-src-2.6.0/src/ucode04.h000066400000000000000000000131341464507525600212710ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** //**************************************************************** // uCode 4 - RSP SW 2.0D EXT //**************************************************************** static void uc4_vertex() { DWORD addr = segoffset(rdp.cmd1) & 0x00FFFFFF; int v0, i, n; float x, y, z; rdp.v0 = v0 = 0; // Current vertex rdp.vn = n = ((rdp.cmd0 >> 4) & 0xFFF) / 33 + 1; // Number of vertices to copy FRDP("uc4:vertex: v0: %d, n: %d\n", v0, n); // This is special, not handled in update(), but here // * Matrix Pre-multiplication idea by Gonetz (Gonetz@ngs.ru) if (rdp.update & UPDATE_MULT_MAT) { rdp.update ^= UPDATE_MULT_MAT; MulMatrices(rdp.model, rdp.proj, rdp.combined); } // * // This is special, not handled in update() if (rdp.update & UPDATE_LIGHTS) { rdp.update ^= UPDATE_LIGHTS; // Calculate light vectors for (DWORD l=0; l>4)]; x = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 0)^1]; y = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 1)^1]; z = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 2)^1]; v->flags = ((WORD*)gfx.RDRAM)[(((addr+i) >> 1) + 3)^1]; v->ou = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 4)^1] * rdp.tiles[rdp.cur_tile].s_scale; v->ov = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 5)^1] * rdp.tiles[rdp.cur_tile].t_scale; v->a = ((BYTE*)gfx.RDRAM)[(addr+i + 15)^3]; v->x = x*rdp.combined[0][0] + y*rdp.combined[1][0] + z*rdp.combined[2][0] + rdp.combined[3][0]; v->y = x*rdp.combined[0][1] + y*rdp.combined[1][1] + z*rdp.combined[2][1] + rdp.combined[3][1]; v->z = x*rdp.combined[0][2] + y*rdp.combined[1][2] + z*rdp.combined[2][2] + rdp.combined[3][2]; v->w = x*rdp.combined[0][3] + y*rdp.combined[1][3] + z*rdp.combined[2][3] + rdp.combined[3][3]; v->oow = 1.0f / v->w; v->x_w = v->x * v->oow; v->y_w = v->y * v->oow; v->z_w = v->z * v->oow; CalculateFog (v); v->uv_calculated = 0xFFFFFFFF; v->screen_translated = 0; v->shade_mods_allowed = 1; v->scr_off = 0; if (v->x < -v->w) v->scr_off |= 1; if (v->x > v->w) v->scr_off |= 2; if (v->y < -v->w) v->scr_off |= 4; if (v->y > v->w) v->scr_off |= 8; if (v->w < 0.1f) v->scr_off |= 16; if (rdp.geom_mode & 0x00020000) { v->vec[0] = ((char*)gfx.RDRAM)[(addr+i + 12)^3]; v->vec[1] = ((char*)gfx.RDRAM)[(addr+i + 13)^3]; v->vec[2] = ((char*)gfx.RDRAM)[(addr+i + 14)^3]; if (rdp.geom_mode & 0x80000) calc_linear (v); else if (rdp.geom_mode & 0x40000) calc_sphere (v); NormalizeVector (v->vec); calc_light (v); } else { v->r = ((BYTE*)gfx.RDRAM)[(addr+i + 12)^3]; v->g = ((BYTE*)gfx.RDRAM)[(addr+i + 13)^3]; v->b = ((BYTE*)gfx.RDRAM)[(addr+i + 14)^3]; } } } static void uc4_tri1() { int v1 = ((rdp.cmd1 >> 16) & 0xFF) / 5; int v2 = ((rdp.cmd1 >> 8) & 0xFF) / 5; int v3 = (rdp.cmd1 & 0xFF) / 5; FRDP("uc4:tri1 #%d - %d, %d, %d\n", rdp.tri_n, v1, v2, v3); VERTEX *v[3] = { &rdp.vtx[v1], &rdp.vtx[v2], &rdp.vtx[v3] }; if (cull_tri(v)) rdp.tri_n ++; else { update (); DrawTri (v); rdp.tri_n ++; } } static void uc4_quad3d() { FRDP("uc4:quad3d #%d, #%d\n", rdp.tri_n, rdp.tri_n+1); VERTEX *v[6] = { &rdp.vtx[((rdp.cmd1 >> 24) & 0xFF) / 5], &rdp.vtx[((rdp.cmd1 >> 16) & 0xFF) / 5], &rdp.vtx[((rdp.cmd1 >> 8) & 0xFF) / 5], &rdp.vtx[((rdp.cmd1 >> 24) & 0xFF) / 5], &rdp.vtx[((rdp.cmd1 >> 8) & 0xFF) / 5], &rdp.vtx[(rdp.cmd1 & 0xFF) / 5] }; BOOL updated = 0; if (cull_tri(v)) rdp.tri_n ++; else { updated = 1; update (); DrawTri (v); rdp.tri_n ++; } if (cull_tri(v+3)) rdp.tri_n ++; else { if (!updated) update (); DrawTri (v+3); rdp.tri_n ++; } } mupen64plus-video-glide64-src-2.6.0/src/ucode05.h000066400000000000000000000262201464507525600212720ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** int cur_mtx = 0; BOOL billboarding = 0; int vtx_last = 0; DWORD dma_offset_mtx = 0; DWORD dma_offset_vtx = 0; static void uc5_dma_offsets () { dma_offset_mtx = rdp.cmd0 & 0x00FFFFFF; dma_offset_vtx = rdp.cmd1 & 0x00FFFFFF; vtx_last = 0; FRDP("uc5:dma_offsets - mtx: %08lx, vtx: %08lx\n", dma_offset_mtx, dma_offset_vtx); } static void uc5_matrix () { // Use segment offset to get the address DWORD addr = dma_offset_mtx + (segoffset(rdp.cmd1) & BMASK); BYTE n = (BYTE)((rdp.cmd0 >> 16) & 0xF); BYTE multiply; if (n == 0) //DKR { n = (BYTE)((rdp.cmd0 >> 22) & 0x3); multiply = 0; } else //JF { multiply = (BYTE)((rdp.cmd0 >> 23) & 0x1); } cur_mtx = n; FRDP("uc5:matrix - #%d, addr: %08lx\n", n, addr); addr >>= 1; int x,y; // matrix index if (multiply) { __declspec( align(16) ) float m[4][4]; for (x=0; x<16; x+=4) { // Adding 4 instead of one, just to remove mult. later for (y=0; y<4; y++) { m[x>>2][y] = (float)( (((__int32)((WORD*)gfx.RDRAM)[(addr+x+y)^1]) << 16) | ((WORD*)gfx.RDRAM)[(addr+x+y+16)^1] ) / 65536.0f; } } __declspec( align(16) ) float m_src[4][4]; memcpy (m_src, rdp.dkrproj[0], 64); MulMatrices(m, m_src, rdp.dkrproj[n]); } else { for (x=0; x<16; x+=4) { // Adding 4 instead of one, just to remove mult. later for (y=0; y<4; y++) { rdp.dkrproj[n][x>>2][y] = (float)( (((__int32)((WORD*)gfx.RDRAM)[(addr+x+y)^1]) << 16) | ((WORD*)gfx.RDRAM)[(addr+x+y+16)^1] ) / 65536.0f; } } } rdp.update |= UPDATE_MULT_MAT; #ifdef EXTREME_LOGGING FRDP ("{%f,%f,%f,%f}\n", rdp.dkrproj[n][0][0], rdp.dkrproj[n][0][1], rdp.dkrproj[n][0][2], rdp.dkrproj[n][0][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.dkrproj[n][1][0], rdp.dkrproj[n][1][1], rdp.dkrproj[n][1][2], rdp.dkrproj[n][1][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.dkrproj[n][2][0], rdp.dkrproj[n][2][1], rdp.dkrproj[n][2][2], rdp.dkrproj[n][2][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.dkrproj[n][3][0], rdp.dkrproj[n][3][1], rdp.dkrproj[n][3][2], rdp.dkrproj[n][3][3]); for (int i=0; i<3; i++) { FRDP ("proj %d\n", i); FRDP ("{%f,%f,%f,%f}\n", rdp.dkrproj[i][0][0], rdp.dkrproj[i][0][1], rdp.dkrproj[i][0][2], rdp.dkrproj[i][0][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.dkrproj[i][1][0], rdp.dkrproj[i][1][1], rdp.dkrproj[i][1][2], rdp.dkrproj[i][1][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.dkrproj[i][2][0], rdp.dkrproj[i][2][1], rdp.dkrproj[i][2][2], rdp.dkrproj[i][2][3]); FRDP ("{%f,%f,%f,%f}\n", rdp.dkrproj[i][3][0], rdp.dkrproj[i][3][1], rdp.dkrproj[i][3][2], rdp.dkrproj[i][3][3]); } #endif } static void uc5_vertex () { DWORD addr = dma_offset_vtx + (segoffset(rdp.cmd1) & BMASK); // | cccc cccc 1111 1??? 0000 0002 2222 2222 | cmd1 = address | // c = vtx command // 1 = method #1 of getting count // 2 = method #2 of getting count // ? = unknown, but used // 0 = unused int n = ((rdp.cmd0 >> 19) & 0x1F);// + 1; if (settings.diddy) n++; //int n = ((rdp.cmd0 & 0x1FF) - 8) / 18; // same thing! if (rdp.cmd0 & 0x00010000) { if (billboarding) vtx_last = 1; } else vtx_last = 0; int first = ((rdp.cmd0 >> 9) & 0x1F) + vtx_last; FRDP ("uc5:vertex - addr: %08lx, first: %d, count: %d, matrix: %08lx\n", addr, first, n, cur_mtx); int prj = cur_mtx; int start = 0; float x, y, z; for (int i=first; i> 1) + 0)^1]; y = (float)((short*)gfx.RDRAM)[(((addr+start) >> 1) + 1)^1]; z = (float)((short*)gfx.RDRAM)[(((addr+start) >> 1) + 2)^1]; v->x = x*rdp.dkrproj[prj][0][0] + y*rdp.dkrproj[prj][1][0] + z*rdp.dkrproj[prj][2][0] + rdp.dkrproj[prj][3][0]; v->y = x*rdp.dkrproj[prj][0][1] + y*rdp.dkrproj[prj][1][1] + z*rdp.dkrproj[prj][2][1] + rdp.dkrproj[prj][3][1]; v->z = x*rdp.dkrproj[prj][0][2] + y*rdp.dkrproj[prj][1][2] + z*rdp.dkrproj[prj][2][2] + rdp.dkrproj[prj][3][2]; v->w = x*rdp.dkrproj[prj][0][3] + y*rdp.dkrproj[prj][1][3] + z*rdp.dkrproj[prj][2][3] + rdp.dkrproj[prj][3][3]; if (billboarding) { v->x += rdp.vtx[0].x; v->y += rdp.vtx[0].y; v->z += rdp.vtx[0].z; v->w += rdp.vtx[0].w; } #ifdef EXTREME_LOGGING FRDP ("v%d - x: %f, y: %f, z: %f, w: %f\n", i, v->x, v->y, v->z, v->w); #endif v->oow = 1.0f / v->w; v->x_w = v->x * v->oow; v->y_w = v->y * v->oow; v->z_w = v->z * v->oow; v->uv_calculated = 0xFFFFFFFF; v->screen_translated = 0; v->shade_mods_allowed = 1; v->scr_off = 0; if (v->x < -v->w) v->scr_off |= 1; if (v->x > v->w) v->scr_off |= 2; if (v->y < -v->w) v->scr_off |= 4; if (v->y > v->w) v->scr_off |= 8; if (v->w < 0.1f) v->scr_off |= 16; v->r = ((BYTE*)gfx.RDRAM)[(addr+start + 6)^3]; v->g = ((BYTE*)gfx.RDRAM)[(addr+start + 7)^3]; v->b = ((BYTE*)gfx.RDRAM)[(addr+start + 8)^3]; v->a = ((BYTE*)gfx.RDRAM)[(addr+start + 9)^3]; CalculateFog (v); #ifdef EXTREME_LOGGING FRDP ("vtx%d: x: %f, y: %f, z: %f, w: %f\n", i, v->x, v->y, v->z, v->w); #endif } vtx_last += n; } static void uc5_tridma () { vtx_last = 0; // we've drawn something, so the vertex index needs resetting if (rdp.skip_drawing) return; // | cccc cccc 2222 0000 1111 1111 1111 0000 | cmd1 = address | // c = tridma command // 1 = method #1 of getting count // 2 = method #2 of getting count // 0 = unused DWORD addr = segoffset(rdp.cmd1) & BMASK; int num = (rdp.cmd0 & 0xFFF0) >> 4; //int num = ((rdp.cmd0 & 0x00F00000) >> 20) + 1; // same thing! FRDP("uc5:tridma #%d - addr: %08lx, count: %d\n", rdp.tri_n, addr, num); int start, v0, v1, v2, flags; for (int i=0; iou = (float)((short*)gfx.RDRAM)[((addr+start) >> 1) + 5] / 32.0f; v[0]->ov = (float)((short*)gfx.RDRAM)[((addr+start) >> 1) + 4] / 32.0f; v[1]->ou = (float)((short*)gfx.RDRAM)[((addr+start) >> 1) + 3] / 32.0f; v[1]->ov = (float)((short*)gfx.RDRAM)[((addr+start) >> 1) + 2] / 32.0f; v[2]->ou = (float)((short*)gfx.RDRAM)[((addr+start) >> 1) + 1] / 32.0f; v[2]->ov = (float)((short*)gfx.RDRAM)[((addr+start) >> 1) + 0] / 32.0f; v[0]->uv_calculated = 0xFFFFFFFF; v[1]->uv_calculated = 0xFFFFFFFF; v[2]->uv_calculated = 0xFFFFFFFF; if (cull_tri(v)) rdp.tri_n ++; else { update (); DrawTri (v); rdp.tri_n ++; } } } static void uc5_dl_in_mem () { DWORD addr = segoffset(rdp.cmd1) & BMASK; int count = (rdp.cmd0 & 0x00FF0000) >> 16; FRDP ("uc5:dl_in_mem - addr: %08lx, count: %d\n", addr, count); if (rdp.pc_i >= 9) { RDP_E ("** DL stack overflow **\n"); RDP ("** DL stack overflow **\n"); return; } rdp.pc_i ++; // go to the next PC in the stack rdp.pc[rdp.pc_i] = addr; // jump to the address rdp.dl_count = count + 1; } static void uc5_moveword() { RDP("uc5:moveword "); // Find which command this is (lowest byte of cmd0) switch (rdp.cmd0 & 0xFF) { case 0x02: // moveword matrix 2 billboard billboarding = (rdp.cmd1 & 1); FRDP ("matrix billboard - %s\n", str_offon[billboarding]); break; case 0x04: // clip (verified same) FRDP ("clip %08lx, %08lx\n", rdp.cmd0, rdp.cmd1); break; case 0x06: // segment (verified same) FRDP ("segment: %08lx -> seg%d\n", rdp.cmd1, (rdp.cmd0 >> 10) & 0x0F); rdp.segment[(rdp.cmd0 >> 10) & 0x0F] = rdp.cmd1; break; case 0x08: { rdp.fog_multiplier = (short)(rdp.cmd1 >> 16); rdp.fog_offset = (short)(rdp.cmd1 & 0x0000FFFF); FRDP ("fog: multiplier: %f, offset: %f\n", rdp.fog_multiplier, rdp.fog_offset); // rdp.update |= UPDATE_FOG_ENABLED; } break; case 0x0a: // moveword matrix select cur_mtx = (rdp.cmd1 >> 6) & 3; FRDP ("matrix select - mtx: %d\n", cur_mtx); break; default: FRDP ("(unknown) %02lx - IGNORED\n", rdp.cmd0&0xFF); } } static void uc5_setgeometrymode() { FRDP("uc0:setgeometrymode %08lx\n", rdp.cmd1); rdp.geom_mode |= rdp.cmd1; if (rdp.cmd1 & 0x00000001) // Z-Buffer enable { if (!(rdp.flags & ZBUF_ENABLED)) { rdp.flags |= ZBUF_ENABLED; rdp.update |= UPDATE_ZBUF_ENABLED; } } //Added by Gonetz if (rdp.cmd1 & 0x00010000) // Fog enable { if (!(rdp.flags & FOG_ENABLED)) { rdp.flags |= FOG_ENABLED; rdp.update |= UPDATE_FOG_ENABLED; } } } static void uc5_cleargeometrymode() { FRDP("uc0:cleargeometrymode %08lx\n", rdp.cmd1); rdp.geom_mode &= (~rdp.cmd1); if (rdp.cmd1 & 0x00000001) // Z-Buffer enable { if (rdp.flags & ZBUF_ENABLED) { rdp.flags ^= ZBUF_ENABLED; rdp.update |= UPDATE_ZBUF_ENABLED; } } //Added by Gonetz if (rdp.cmd1 & 0x00010000) // Fog enable { if (rdp.flags & FOG_ENABLED) { rdp.flags ^= FOG_ENABLED; rdp.update |= UPDATE_FOG_ENABLED; } } } mupen64plus-video-glide64-src-2.6.0/src/ucode06.h000066400000000000000000002025011464507525600212710ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** //**************************************************************** // STANDARD DRAWIMAGE - draws a 2d image based on the following structure void uc6_sprite2d (); typedef struct DRAWIMAGE_t { float frameX; float frameY; WORD frameW; WORD frameH; WORD imageX; WORD imageY; WORD imageW; WORD imageH; DWORD imagePtr; BYTE imageFmt; BYTE imageSiz; WORD imagePal; BYTE flipX; BYTE flipY; float scaleX; float scaleY; } DRAWIMAGE; void DrawHiresDepthImage (DRAWIMAGE *d) { WORD * src = (WORD*)(gfx.RDRAM+d->imagePtr); WORD image[512*512]; WORD * dst = image; for (int h = 0; h < d->imageH; h++) { for (int w = 0; w < d->imageW; w++) { *(dst++) = src[(w+h*d->imageW)^1]; } dst += (512 - d->imageW); } GrTexInfo t_info; t_info.format = GR_TEXFMT_RGB_565; t_info.data = image; t_info.smallLodLog2 = GR_LOD_LOG2_512; t_info.largeLodLog2 = GR_LOD_LOG2_512; t_info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; grTexDownloadMipMap (rdp.texbufs[1].tmu, rdp.texbufs[1].begin, GR_MIPMAPLEVELMASK_BOTH, &t_info); grTexSource (rdp.texbufs[1].tmu, rdp.texbufs[1].begin, GR_MIPMAPLEVELMASK_BOTH, &t_info); grTexCombine( GR_TMU1, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE ); grTexCombine( GR_TMU0, GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, FXFALSE, FXFALSE ); grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); grAlphaBlendFunction (GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO); grDepthBufferFunction (GR_CMP_ALWAYS); grDepthMask (FXFALSE); GrLOD_t LOD = GR_LOD_LOG2_1024; if (settings.scr_res_x > 1024) LOD = GR_LOD_LOG2_2048; float lr_x = (float)d->imageW * rdp.scale_x; float lr_y = (float)d->imageH * rdp.scale_y; float lr_u = (float)d->imageW * 0.5f;// - 0.5f; float lr_v = (float)d->imageH * 0.5f;// - 0.5f; VERTEX v[4] = { { 0, 0, 1.0f, 1.0f, 0, 0, 0, 0 }, { lr_x, 0, 1.0f, 1.0f, lr_u, 0, lr_u, 0 }, { 0, lr_y, 1.0f, 1.0f, 0, lr_v, 0, lr_v }, { lr_x, lr_y, 1.0f, 1.0f, lr_u, lr_v, lr_u, lr_v } }; for (int i=0; i<4; i++) { v[i].uc(0) = v[i].uc(1) = v[i].u0; v[i].vc(0) = v[i].vc(1) = v[i].v0; } grTextureBufferExt( rdp.texbufs[0].tmu, rdp.texbufs[0].begin, LOD, LOD, GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH ); grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT ); grAuxBufferExt( GR_BUFFER_AUXBUFFER ); grSstOrigin(GR_ORIGIN_UPPER_LEFT); grBufferClear (0, 0, 0xFFFF); grDrawTriangle (&v[0], &v[2], &v[1]); grDrawTriangle (&v[2], &v[3], &v[1]); grRenderBuffer( GR_BUFFER_BACKBUFFER ); grTextureAuxBufferExt( rdp.texbufs[0].tmu, rdp.texbufs[0].begin, LOD, LOD, GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH ); grAuxBufferExt( GR_BUFFER_TEXTUREAUXBUFFER_EXT ); grDepthMask (FXTRUE); } extern BOOL depthbuffersave; void DrawDepthImage (DRAWIMAGE *d) { if (!fullscreen || !settings.fb_depth_render) return; if (d->imageH > d->imageW) return; RDP("Depth image write\n"); float scale_x_dst = rdp.scale_x; float scale_y_dst = rdp.scale_y; float scale_x_src = 1.0f/rdp.scale_x; float scale_y_src = 1.0f/rdp.scale_y; int src_width = d->imageW; int src_height = d->imageH; int dst_width = std::min(int(src_width*scale_x_dst), (int)settings.scr_res_x); int dst_height = std::min(int(src_height*scale_y_dst), (int)settings.scr_res_y); #if 1 if (0 && grFramebufferCopyExt) { static unsigned int last; unsigned int crc = CRC_Calculate(0, gfx.RDRAM+d->imagePtr, d->imageW * d->imageH * 2); printf("depth CRC %x\n", crc); if (last == crc) { // ZIGGY // using special idiot setting FRONT-->FRONT so the wrapper knows what to // do (i.e. delay actual copy until after next buffer clear) // UGLY !! grFramebufferCopyExt(0, 0, dst_width, dst_height, GR_FBCOPY_BUFFER_FRONT, GR_FBCOPY_BUFFER_FRONT, GR_FBCOPY_MODE_DEPTH); depthbuffersave = TRUE; return; } last = crc; depthbuffersave = TRUE; } else { if (settings.fb_hires) { DrawHiresDepthImage(d); return; } } #endif WORD * src = (WORD*)(gfx.RDRAM+d->imagePtr); WORD * dst = new WORD[dst_width*dst_height]; for (int y=0; y < dst_height; y++) { for (int x=0; x < dst_width; x++) { dst[x+y*dst_width] = src[(int(x*scale_x_src)+int(y*scale_y_src)*src_width)^1]; } } grLfbWriteRegion(GR_BUFFER_AUXBUFFER, 0, 0, GR_LFB_SRC_FMT_ZA16, dst_width, dst_height, FXFALSE, dst_width<<1, dst); delete[] dst; } void DrawImage (DRAWIMAGE *d) { if (d->imageW == 0 || d->imageH == 0 || d->frameH == 0) return; int x_size; int y_size; int x_shift; int y_shift; int line; // choose optimum size for the format/size if (d->imageSiz == 0) { x_size = 128; y_size = 64; x_shift = 7; y_shift = 6; line = 8; } if (d->imageSiz == 1) { x_size = 64; y_size = 64; x_shift = 6; y_shift = 6; line = 8; } if (d->imageSiz == 2) { x_size = 64; y_size = 32; x_shift = 6; y_shift = 5; line = 16; } if (d->imageSiz == 3) { x_size = 32; y_size = 16; x_shift = 4; y_shift = 3; line = 16; } if (rdp.ci_width == 512 && !no_dlist) //RE2 { WORD width = (WORD)(*gfx.VI_WIDTH_REG & 0xFFF); d->frameH = d->imageH = (d->frameW*d->frameH)/width; d->frameW = d->imageW = width; if (rdp.zimg == rdp.cimg) { DrawDepthImage(d); rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_ALPHA_COMPARE | UPDATE_VIEWPORT; return; } } if (d->imageW%2 == 1) d->imageW -= 1; if (d->imageH%2 == 1) d->imageH -= 1; if (d->imageY > d->imageH) d->imageY = (d->imageY%d->imageH); // if (d->imageX > d->imageW) d->imageX = (d->imageX%d->imageW); if (!settings.PPL) { if ( (d->frameX > 0) && (d->frameW == rdp.ci_width) ) d->frameW -= (WORD)(2.0f*d->frameX); if ( (d->frameY > 0) && (d->frameH == rdp.ci_height) ) d->frameH -= (WORD)(2.0f*d->frameY); } int ul_u = (int)d->imageX; int ul_v = (int)d->imageY; int lr_u = (int)d->imageX + (int)(d->frameW * d->scaleX); int lr_v = (int)d->imageY + (int)(d->frameH * d->scaleY); float ul_x, ul_y, lr_x, lr_y; if (d->flipX) { ul_x = d->frameX + d->frameW; lr_x = d->frameX; } else { ul_x = d->frameX; lr_x = d->frameX + d->frameW; } if (d->flipY) { ul_y = d->frameY + d->frameH; lr_y = d->frameY; } else { ul_y = d->frameY; lr_y = d->frameY + d->frameH; } int min_wrap_u = ul_u / d->imageW; //int max_wrap_u = lr_u / d->wrapW; int min_wrap_v = ul_v / d->imageH; //int max_wrap_v = lr_v / d->wrapH; int min_256_u = ul_u >> x_shift; //int max_256_u = (lr_u-1) >> x_shift; int min_256_v = ul_v >> y_shift; //int max_256_v = (lr_v-1) >> y_shift; // SetTextureImage () rdp.timg.format = d->imageFmt; // RGBA rdp.timg.size = d->imageSiz; // 16-bit rdp.timg.addr = d->imagePtr; rdp.timg.width = d->imageW; rdp.timg.set_by = 0; // SetTile () TILE *tile = &rdp.tiles[0]; tile->format = d->imageFmt; // RGBA tile->size = d->imageSiz; // 16-bit tile->line = line; tile->t_mem = 0; tile->palette = (BYTE)d->imagePal; tile->clamp_t = 1; tile->mirror_t = 0; tile->mask_t = 0; tile->shift_t = 0; tile->clamp_s = 1; tile->mirror_s = 0; tile->mask_s = 0; tile->shift_s = 0; rdp.tiles[0].ul_s = 0; rdp.tiles[0].ul_t = 0; rdp.tiles[0].lr_s = x_size-1; rdp.tiles[0].lr_t = y_size-1; if (rdp.cycle_mode == 2) { rdp.allow_combine = 0; rdp.update &= ~UPDATE_TEXTURE; } update (); // note: allow loading of texture float Z = 1.0f; if (fullscreen) { //grFogMode (GR_FOG_DISABLE); grFogMode (GR_FOG_DISABLE); if (rdp.zsrc == 1 && (rdp.othermode_l & 0x00000030)) // othermode check makes sure it // USES the z-buffer. Otherwise it returns bad (unset) values for lot and telescope //in zelda:mm. { RDP("Background uses depth compare\n"); Z = ScaleZ(rdp.prim_depth); grDepthBufferFunction (GR_CMP_LEQUAL); grDepthMask (FXTRUE); } else { RDP("Background not uses depth compare\n"); grDepthBufferFunction (GR_CMP_ALWAYS); grDepthMask (FXFALSE); } // grClipWindow (0, 0, settings.res_x, settings.res_y); if (rdp.ci_width == 512 && !no_dlist) // grClipWindow (0, 0, (DWORD)(d->frameW * rdp.scale_x), (DWORD)(d->frameH * rdp.scale_y)); grClipWindow (0, 0, settings.scr_res_x, settings.scr_res_y); else grClipWindow (rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y); grCullMode (GR_CULL_DISABLE); // if (!settings.PPL) if (rdp.cycle_mode == 2) { rdp.allow_combine = 0; cmb.tmu0_func = GR_COMBINE_FUNCTION_LOCAL; cmb.tmu0_a_func = GR_COMBINE_FUNCTION_LOCAL; grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); grConstantColorValue (0xFFFFFFFF); grAlphaBlendFunction (GR_BLEND_ONE, // use alpha compare, but not T0 alpha GR_BLEND_ZERO, GR_BLEND_ZERO, GR_BLEND_ZERO); rdp.update |= UPDATE_COMBINE; } } // Texture () rdp.cur_tile = 0; rdp.tex = 1; float nul_x, nul_y, nlr_x, nlr_y; int nul_u, nul_v, nlr_u, nlr_v; float ful_u, ful_v, flr_u, flr_v; float ful_x, ful_y, flr_x, flr_y; float mx = (float)(lr_x - ul_x) / (float)(lr_u - ul_u); float bx = ul_x - mx * ul_u; float my = (float)(lr_y - ul_y) / (float)(lr_v - ul_v); float by = ul_y - my * ul_v; int cur_wrap_u, cur_wrap_v, cur_u, cur_v; int cb_u, cb_v; // coordinate-base int tb_u, tb_v; // texture-base nul_v = ul_v; nul_y = ul_y; // #162 cur_wrap_v = min_wrap_v + 1; cur_v = min_256_v + 1; cb_v = ((cur_v-1)<= d->imageH) cb_v -= d->imageH; tb_v = cb_v; while (1) { cur_wrap_u = min_wrap_u + 1 + 1024; // x wrapping is not required cur_u = min_256_u + 1; // calculate intersection with this point nlr_v = std::min(std::min(cur_wrap_v*d->imageH, (cur_v<= d->imageW) cb_u -= d->imageW; tb_u = cb_u; while (1) { // calculate intersection with this point nlr_u = std::min(std::min(cur_wrap_u*d->imageW, (cur_u<scale; ful_v *= rdp.cur_cache[0]->scale; flr_u *= rdp.cur_cache[0]->scale; flr_v *= rdp.cur_cache[0]->scale; ful_x = nul_x * rdp.scale_x; flr_x = nlr_x * rdp.scale_x; ful_y = nul_y * rdp.scale_y; flr_y = nlr_y * rdp.scale_y; // Make the vertices if ((flr_x <= rdp.scissor.lr_x) || (ful_x < rdp.scissor.lr_x)) { VERTEX v[4] = { { ful_x, ful_y, Z, 1.0f, ful_u, ful_v }, { flr_x, ful_y, Z, 1.0f, flr_u, ful_v }, { ful_x, flr_y, Z, 1.0f, ful_u, flr_v }, { flr_x, flr_y, Z, 1.0f, flr_u, flr_v } }; AllowShadeMods (v, 4); for (int s = 0; s < 4; s++) apply_shade_mods (&(v[s])); ConvertCoordsConvert (v, 4); if (fullscreen)// && /*hack for Zelda MM. Gonetz*/rdp.cur_cache[0]->addr > 0xffff && rdp.cur_cache[0]->crc != 0) { grDrawVertexArrayContiguous (GR_TRIANGLE_STRIP, 4, v, sizeof(VERTEX)); } if (debug.capture) { VERTEX vl[3]; vl[0] = v[0]; vl[1] = v[2]; vl[2] = v[1]; add_tri (vl, 3, TRI_BACKGROUND); rdp.tri_n ++; vl[0] = v[2]; vl[1] = v[3]; vl[2] = v[1]; add_tri (vl, 3, TRI_BACKGROUND); rdp.tri_n ++; } else rdp.tri_n += 2; } else { rdp.tri_n += 2; RDP("Clipped!\n"); } // increment whatever caused this split tb_u += x_size - (x_size-(nlr_u-cb_u)); cb_u = nlr_u; if (nlr_u == cur_wrap_u*d->imageW) { cur_wrap_u ++; tb_u = 0; } if (nlr_u == (cur_u<imageH) { cur_wrap_v ++; tb_v = 0; } if (nlr_v == (cur_v<imagePtr); if (!fullscreen) return; HIRES_COLOR_IMAGE *hires_tex = (rdp.motionblur)?&(rdp.texbufs[rdp.cur_tex_buf^1].images[0]):rdp.hires_tex; if (rdp.cycle_mode == 2) { rdp.allow_combine = 0; rdp.update &= ~UPDATE_TEXTURE; } update (); // note: allow loading of texture float Z = 1.0f; if (rdp.zsrc == 1 && (rdp.othermode_l & 0x00000030)) { RDP("Background uses depth compare\n"); Z = ScaleZ(rdp.prim_depth); grDepthBufferFunction (GR_CMP_LEQUAL); } else { RDP("Background not uses depth compare\n"); grDepthBufferFunction (GR_CMP_ALWAYS); } grDepthMask (FXFALSE); grClipWindow (0, 0, settings.res_x, settings.res_y); grCullMode (GR_CULL_DISABLE); if (rdp.cycle_mode == 2) { grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); grConstantColorValue (0xFFFFFFFF); grAlphaBlendFunction (GR_BLEND_ONE, // use alpha compare, but not T0 alpha GR_BLEND_ZERO, GR_BLEND_ZERO, GR_BLEND_ZERO); rdp.allow_combine = 1; } if (hires_tex->tmu == GR_TMU0) { grTexCombine( GR_TMU1, GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE ); grTexCombine( GR_TMU0, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE ); } else { grTexCombine( GR_TMU1, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE ); grTexCombine( GR_TMU0, GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, FXFALSE, FXFALSE ); } grTexSource( hires_tex->tmu, hires_tex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(hires_tex->info) ); if (d->imageW%2 == 1) d->imageW -= 1; if (d->imageH%2 == 1) d->imageH -= 1; if (d->imageY > d->imageH) d->imageY = (d->imageY%d->imageH); if (!settings.PPL) { if ( (d->frameX > 0) && (d->frameW == rdp.ci_width) ) d->frameW -= (WORD)(2.0f*d->frameX); if ( (d->frameY > 0) && (d->frameH == rdp.ci_height) ) d->frameH -= (WORD)(2.0f*d->frameY); } float ul_x, ul_y, ul_u, ul_v, lr_x, lr_y, lr_u, lr_v; if (screensize) { ul_x = 0.0f; ul_y = 0.0f; ul_u = 0.0f; ul_v = 0.0f; lr_x = (float)rdp.hires_tex->scr_width; lr_y = (float)rdp.hires_tex->scr_height; lr_u = rdp.hires_tex->u_scale * (float)(rdp.hires_tex->width);//255.0f - (1024 - settings.res_x)*0.25f; lr_v = rdp.hires_tex->v_scale * (float)(rdp.hires_tex->height);//255.0f - (1024 - settings.res_y)*0.25f; } else { ul_u = d->imageX; ul_v = d->imageY; lr_u = d->imageX + (d->frameW * d->scaleX) ; lr_v = d->imageY + (d->frameH * d->scaleY) ; ul_x = d->frameX; ul_y = d->frameY; lr_x = d->frameX + d->frameW; lr_y = d->frameY + d->frameH; ul_x *= rdp.scale_x; lr_x *= rdp.scale_x; ul_y *= rdp.scale_y; lr_y *= rdp.scale_y; ul_u *= rdp.hires_tex->u_scale; lr_u *= rdp.hires_tex->u_scale; ul_v *= rdp.hires_tex->v_scale; lr_v *= rdp.hires_tex->v_scale; if (lr_x > rdp.scissor.lr_x) lr_x = (float)rdp.scissor.lr_x; if (lr_y > rdp.scissor.lr_y) lr_y = (float)rdp.scissor.lr_y; } // Make the vertices VERTEX v[4] = { { ul_x, ul_y, Z, 1.0f, ul_u, ul_v, ul_u, ul_v }, { lr_x, ul_y, Z, 1.0f, lr_u, ul_v, lr_u, ul_v }, { ul_x, lr_y, Z, 1.0f, ul_u, lr_v, ul_u, lr_v }, { lr_x, lr_y, Z, 1.0f, lr_u, lr_v, lr_u, lr_v } }; ConvertCoordsConvert (v, 4); AllowShadeMods (v, 4); for (int s = 0; s < 4; s++) apply_shade_mods (&(v[s])); grDrawTriangle (&v[0], &v[2], &v[1]); grDrawTriangle (&v[2], &v[3], &v[1]); rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_TEXTURE | UPDATE_ALPHA_COMPARE | UPDATE_VIEWPORT; } //**************************************************************** struct mat2d_t { float A, B, C, D; float X, Y; float BaseScaleX; float BaseScaleY; } mat_2d; static void uc6_bg_1cyc () { if (render_depth_mode == 2) { // ZIGGY // Zelda LoT effect save/restore depth buffer RDP("bg_1cyc: saving depth buffer\n"); printf("bg_1cyc: saving depth buffer\n"); if (grFramebufferCopyExt) grFramebufferCopyExt(0, 0, settings.scr_res_x, settings.scr_res_y, GR_FBCOPY_BUFFER_BACK, GR_FBCOPY_BUFFER_FRONT, GR_FBCOPY_MODE_DEPTH); return; } if (rdp.skip_drawing) { RDP("bg_1cyc skipped\n"); return; } FRDP ("uc6:bg_1cyc #%d, #%d\n", rdp.tri_n, rdp.tri_n+1); FRDP_E ("uc6:bg_1cyc #%d, #%d\n", rdp.tri_n, rdp.tri_n+1); DWORD addr = segoffset(rdp.cmd1) >> 1; DRAWIMAGE d; d.imageX = (((WORD *)gfx.RDRAM)[(addr+0)^1] >> 5); // 0 d.imageW = (((WORD *)gfx.RDRAM)[(addr+1)^1] >> 2); // 1 d.frameX = ((short*)gfx.RDRAM)[(addr+2)^1] / 4.0f; // 2 d.frameW = ((WORD *)gfx.RDRAM)[(addr+3)^1] >> 2; // 3 d.imageY = (((WORD *)gfx.RDRAM)[(addr+4)^1] >> 5); // 4 d.imageH = (((WORD *)gfx.RDRAM)[(addr+5)^1] >> 2); // 5 d.frameY = ((short*)gfx.RDRAM)[(addr+6)^1] / 4.0f; // 6 d.frameH = ((WORD *)gfx.RDRAM)[(addr+7)^1] >> 2; // 7 d.imagePtr = segoffset(((DWORD*)gfx.RDRAM)[(addr+8)>>1]); // 8,9 // WORD imageLoad = ((WORD *)gfx.RDRAM)[(addr+10)^1]; // 10 d.imageFmt = ((BYTE *)gfx.RDRAM)[(((addr+11)<<1)+0)^3]; // 11 d.imageSiz = ((BYTE *)gfx.RDRAM)[(((addr+11)<<1)+1)^3]; // | d.imagePal = ((WORD *)gfx.RDRAM)[(addr+12)^1]; // 12 WORD imageFlip = ((WORD *)gfx.RDRAM)[(addr+13)^1]; // 13; d.flipX = (BYTE)imageFlip&0x01; d.scaleX = ((short *)gfx.RDRAM)[(addr+14)^1] / 1024.0f; // 14 d.scaleY = ((short *)gfx.RDRAM)[(addr+15)^1] / 1024.0f; // 15 if (settings.doraemon2) //Doraemon 2 scale fix { if (d.frameW == d.imageW) d.scaleX = 1.0f; if (d.frameH == d.imageH) d.scaleY = 1.0f; } d.flipY = 0; long imageYorig= ((long *)gfx.RDRAM)[(addr+16)>>1] >> 5; rdp.last_bg = d.imagePtr; FRDP ("imagePtr: %08lx\n", d.imagePtr); FRDP ("frameX: %f, frameW: %d, frameY: %f, frameH: %d\n", d.frameX, d.frameW, d.frameY, d.frameH); FRDP ("imageX: %d, imageW: %d, imageY: %d, imageH: %d\n", d.imageX, d.imageW, d.imageY, d.imageH); FRDP ("imageYorig: %d, scaleX: %f, scaleY: %f\n", imageYorig, d.scaleX, d.scaleY); FRDP ("imageFmt: %d, imageSiz: %d, imagePal: %d, imageFlip: %d\n", d.imageFmt, d.imageSiz, d.imagePal, d.flipX); if (settings.fb_hires && FindTextureBuffer(d.imagePtr, d.imageW)) { DrawHiresImage(&d); return; } if (settings.ucode == 2 || settings.PPL) { if ( (d.imagePtr != rdp.cimg) && (d.imagePtr != rdp.ocimg) && d.imagePtr) //can't draw from framebuffer DrawImage (&d); else { RDP("uc6:bg_1cyc skipped\n"); } } else DrawImage (&d); } static void uc6_bg_copy () { if (render_depth_mode == 1) { // ZIGGY // Zelda LoT effect save/restore depth buffer RDP("bg_copy: restoring depth buffer\n"); printf("bg_copy: restoring depth buffer\n"); if (grFramebufferCopyExt) grFramebufferCopyExt(0, 0, settings.scr_res_x, settings.scr_res_y, GR_FBCOPY_BUFFER_FRONT, GR_FBCOPY_BUFFER_BACK, GR_FBCOPY_MODE_DEPTH); return; } if (rdp.skip_drawing) { RDP("bg_copy skipped\n"); return; } FRDP ("uc6:bg_copy #%d, #%d\n", rdp.tri_n, rdp.tri_n+1); DWORD addr = segoffset(rdp.cmd1) >> 1; DRAWIMAGE d; d.imageX = (((WORD *)gfx.RDRAM)[(addr+0)^1] >> 5); // 0 d.imageW = (((WORD *)gfx.RDRAM)[(addr+1)^1] >> 2); // 1 d.frameX = ((short*)gfx.RDRAM)[(addr+2)^1] / 4.0f; // 2 d.frameW = ((WORD *)gfx.RDRAM)[(addr+3)^1] >> 2; // 3 d.imageY = (((WORD *)gfx.RDRAM)[(addr+4)^1] >> 5); // 4 d.imageH = (((WORD *)gfx.RDRAM)[(addr+5)^1] >> 2); // 5 d.frameY = ((short*)gfx.RDRAM)[(addr+6)^1] / 4.0f; // 6 d.frameH = ((WORD *)gfx.RDRAM)[(addr+7)^1] >> 2; // 7 d.imagePtr = segoffset(((DWORD*)gfx.RDRAM)[(addr+8)>>1]); // 8,9 d.imageFmt = ((BYTE *)gfx.RDRAM)[(((addr+11)<<1)+0)^3]; // 11 d.imageSiz = ((BYTE *)gfx.RDRAM)[(((addr+11)<<1)+1)^3]; // | d.imagePal = ((WORD *)gfx.RDRAM)[(addr+12)^1]; // 12 WORD imageFlip = ((WORD *)gfx.RDRAM)[(addr+13)^1]; // 13; d.flipX = (BYTE)imageFlip&0x01; d.scaleX = 1.0f; // 14 d.scaleY = 1.0f; // 15 d.flipY = 0; rdp.last_bg = d.imagePtr; FRDP ("imagePtr: %08lx\n", d.imagePtr); FRDP ("frameX: %f, frameW: %d, frameY: %f, frameH: %d\n", d.frameX, d.frameW, d.frameY, d.frameH); FRDP ("imageX: %d, imageW: %d, imageY: %d, imageH: %d\n", d.imageX, d.imageW, d.imageY, d.imageH); FRDP ("imageFmt: %d, imageSiz: %d, imagePal: %d\n", d.imageFmt, d.imageSiz, d.imagePal); if (settings.fb_hires && FindTextureBuffer(d.imagePtr, d.imageW)) { DrawHiresImage(&d); return; } if (settings.ucode == 2 || settings.PPL) { if ( (d.imagePtr != rdp.cimg) && (d.imagePtr != rdp.ocimg) && d.imagePtr) //can't draw from framebuffer DrawImage (&d); else { RDP("uc6:bg_copy skipped\n"); } } else DrawImage (&d); } static void draw_splitted_triangle(VERTEX **vtx) { vtx[0]->not_zclipped = vtx[1]->not_zclipped = vtx[2]->not_zclipped = 1; int index,i,j, min_256,max_256, cur_256,left_256,right_256; float percent; min_256 = std::min((int)vtx[0]->u0,(int)vtx[1]->u0); // bah, don't put two mins on one line min_256 = std::min(min_256,(int)vtx[2]->u0) >> 8; // or it will be calculated twice max_256 = std::max((int)vtx[0]->u0,(int)vtx[1]->u0); // not like it makes much difference max_256 = std::max(max_256,(int)vtx[2]->u0) >> 8; // anyway :P for (cur_256=min_256; cur_256<=max_256; cur_256++) { left_256 = cur_256 << 8; right_256 = (cur_256+1) << 8; // Set vertex buffers rdp.vtxbuf = rdp.vtx1; // copy from v to rdp.vtx1 rdp.vtxbuf2 = rdp.vtx2; rdp.vtx_buffer = 0; rdp.n_global = 3; index = 0; // ** Left plane ** for (i=0; i<3; i++) { j = i+1; if (j == 3) j = 0; VERTEX *v1 = vtx[i]; VERTEX *v2 = vtx[j]; if (v1->u0 >= left_256) { if (v2->u0 >= left_256) // Both are in, save the last one { rdp.vtxbuf[index] = *v2; rdp.vtxbuf[index].u0 -= left_256; rdp.vtxbuf[index++].v0 += rdp.cur_cache[0]->c_scl_y * (cur_256 * rdp.cur_cache[0]->splitheight); } else // First is in, second is out, save intersection { percent = (left_256 - v1->u0) / (v2->u0 - v1->u0); rdp.vtxbuf[index].x = v1->x + (v2->x - v1->x) * percent; rdp.vtxbuf[index].y = v1->y + (v2->y - v1->y) * percent; rdp.vtxbuf[index].z = 1; rdp.vtxbuf[index].q = 1; rdp.vtxbuf[index].u0 = 0.5f; rdp.vtxbuf[index].v0 = v1->v0 + (v2->v0 - v1->v0) * percent + rdp.cur_cache[0]->c_scl_y * cur_256 * rdp.cur_cache[0]->splitheight; rdp.vtxbuf[index].b = (BYTE)(v1->b + (v2->b - v1->b) * percent); rdp.vtxbuf[index].g = (BYTE)(v1->g + (v2->g - v1->g) * percent); rdp.vtxbuf[index].r = (BYTE)(v1->r + (v2->r - v1->r) * percent); rdp.vtxbuf[index++].a = (BYTE)(v1->a + (v2->a - v1->a) * percent); } } else { //if (v2->u0 < left_256) // Both are out, save nothing if (v2->u0 >= left_256) // First is out, second is in, save intersection & in point { percent = (left_256 - v2->u0) / (v1->u0 - v2->u0); rdp.vtxbuf[index].x = v2->x + (v1->x - v2->x) * percent; rdp.vtxbuf[index].y = v2->y + (v1->y - v2->y) * percent; rdp.vtxbuf[index].z = 1; rdp.vtxbuf[index].q = 1; rdp.vtxbuf[index].u0 = 0.5f; rdp.vtxbuf[index].v0 = v2->v0 + (v1->v0 - v2->v0) * percent + rdp.cur_cache[0]->c_scl_y * cur_256 * rdp.cur_cache[0]->splitheight; rdp.vtxbuf[index].b = (BYTE)(v2->b + (v1->b - v2->b) * percent); rdp.vtxbuf[index].g = (BYTE)(v2->g + (v1->g - v2->g) * percent); rdp.vtxbuf[index].r = (BYTE)(v2->r + (v1->r - v2->r) * percent); rdp.vtxbuf[index++].a = (BYTE)(v2->a + (v1->a - v2->a) * percent); // Save the in point rdp.vtxbuf[index] = *v2; rdp.vtxbuf[index].u0 -= left_256; rdp.vtxbuf[index++].v0 += rdp.cur_cache[0]->c_scl_y * (cur_256 * rdp.cur_cache[0]->splitheight); } } } rdp.n_global = index; rdp.vtxbuf = rdp.vtx2; // now vtx1 holds the value, & vtx2 is the destination rdp.vtxbuf2 = rdp.vtx1; rdp.vtx_buffer ^= 1; index = 0; for (i=0; iu0 <= 256.0f) { if (v2->u0 <= 256.0f) // Both are in, save the last one { rdp.vtxbuf[index++] = *v2; } else // First is in, second is out, save intersection { percent = (right_256 - v1->u0) / (v2->u0 - v1->u0); rdp.vtxbuf[index].x = v1->x + (v2->x - v1->x) * percent; rdp.vtxbuf[index].y = v1->y + (v2->y - v1->y) * percent; rdp.vtxbuf[index].z = 1; rdp.vtxbuf[index].q = 1; rdp.vtxbuf[index].u0 = 255.5f; rdp.vtxbuf[index].v0 = v1->v0 + (v2->v0 - v1->v0) * percent; rdp.vtxbuf[index].b = (BYTE)(v1->b + (v2->b - v1->b) * percent); rdp.vtxbuf[index].g = (BYTE)(v1->g + (v2->g - v1->g) * percent); rdp.vtxbuf[index].r = (BYTE)(v1->r + (v2->r - v1->r) * percent); rdp.vtxbuf[index++].a = (BYTE)(v1->a + (v2->a - v1->a) * percent); } } else { //if (v2->u0 > 256.0f) // Both are out, save nothing if (v2->u0 <= 256.0f) // First is out, second is in, save intersection & in point { percent = (right_256 - v2->u0) / (v1->u0 - v2->u0); rdp.vtxbuf[index].x = v2->x + (v1->x - v2->x) * percent; rdp.vtxbuf[index].y = v2->y + (v1->y - v2->y) * percent; rdp.vtxbuf[index].z = 1; rdp.vtxbuf[index].q = 1; rdp.vtxbuf[index].u0 = 255.5f; rdp.vtxbuf[index].v0 = v2->v0 + (v1->v0 - v2->v0) * percent; rdp.vtxbuf[index].b = (BYTE)(v2->b + (v1->b - v2->b) * percent); rdp.vtxbuf[index].g = (BYTE)(v2->g + (v1->g - v2->g) * percent); rdp.vtxbuf[index].r = (BYTE)(v2->r + (v1->r - v2->r) * percent); rdp.vtxbuf[index++].a = (BYTE)(v2->a + (v1->a - v2->a) * percent); // Save the in point rdp.vtxbuf[index++] = *v2; } } } rdp.n_global = index; do_triangle_stuff_2 (); } } static float set_sprite_combine_mode () { if (rdp.cycle_mode == 2) { rdp.tex = 1; rdp.allow_combine = 0; //* cmb.tmu1_func = cmb.tmu0_func = GR_COMBINE_FUNCTION_LOCAL; cmb.tmu1_fac = cmb.tmu0_fac = GR_COMBINE_FACTOR_NONE; cmb.tmu1_a_func = cmb.tmu0_a_func = GR_COMBINE_FUNCTION_LOCAL; cmb.tmu1_a_fac = cmb.tmu0_a_fac = GR_COMBINE_FACTOR_NONE; cmb.tmu1_invert = cmb.tmu0_invert = FXFALSE; cmb.tmu1_a_invert = cmb.tmu0_a_invert = FXFALSE; rdp.update |= UPDATE_COMBINE; //*/ } rdp.update |= UPDATE_TEXTURE; update (); rdp.allow_combine = 1; float Z = 1.0f; if (fullscreen) { grFogMode (GR_FOG_DISABLE); if (rdp.zsrc == 1 && (rdp.othermode_l & 0x00000030)) { RDP("Sprite uses depth compare\n"); Z = rdp.prim_depth; grDepthBufferFunction (GR_CMP_LEQUAL); grDepthMask (FXTRUE); } else { RDP("Sprite not uses depth compare\n"); grDepthBufferFunction (GR_CMP_ALWAYS); grDepthMask (FXFALSE); } grClipWindow (0, 0, settings.res_x, settings.res_y); grCullMode (GR_CULL_DISABLE); if (rdp.cycle_mode == 2) { grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); grAlphaBlendFunction (GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ZERO, GR_BLEND_ZERO); rdp.update |= UPDATE_ALPHA_COMPARE | UPDATE_COMBINE | UPDATE_ALPHA_COMPARE; } } return Z; } static void uc6_draw_polygons (VERTEX v[4]) { AllowShadeMods (v, 4); for (int s = 0; s < 4; s++) apply_shade_mods (&(v[s])); // Set vertex buffers if (rdp.cur_cache[0]->splits > 1) { VERTEX *vptr[3]; int i; for (i = 0; i < 3; i++) vptr[i] = &v[i]; draw_splitted_triangle(vptr); rdp.tri_n ++; for (i = 0; i < 3; i++) vptr[i] = &v[i+1]; draw_splitted_triangle(vptr); rdp.tri_n ++; } else { rdp.vtxbuf = rdp.vtx1; // copy from v to rdp.vtx1 rdp.vtxbuf2 = rdp.vtx2; rdp.vtx_buffer = 0; rdp.n_global = 3; memcpy (rdp.vtxbuf, v, sizeof(VERTEX)*3); do_triangle_stuff_2 (); rdp.tri_n ++; rdp.vtxbuf = rdp.vtx1; // copy from v to rdp.vtx1 rdp.vtxbuf2 = rdp.vtx2; rdp.vtx_buffer = 0; rdp.n_global = 3; memcpy (rdp.vtxbuf, v+1, sizeof(VERTEX)*3); do_triangle_stuff_2 (); rdp.tri_n ++; } rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_VIEWPORT; if (fullscreen && settings.fog && (rdp.flags & FOG_ENABLED)) { grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT); } } static void uc6_obj_rectangle () { // RDP ("uc6:obj_rectangle\n"); DWORD addr = segoffset(rdp.cmd1) >> 1; float objX = ((short*)gfx.RDRAM)[(addr+0)^1] / 4.0f; // 0 float scaleW = ((WORD *)gfx.RDRAM)[(addr+1)^1] / 1024.0f; // 1 short imageW = ((short*)gfx.RDRAM)[(addr+2)^1] >> 5; // 2, 3 is padding float objY = ((short*)gfx.RDRAM)[(addr+4)^1] / 4.0f; // 4 float scaleH = ((WORD *)gfx.RDRAM)[(addr+5)^1] / 1024.0f; // 5 short imageH = ((short*)gfx.RDRAM)[(addr+6)^1] >> 5; // 6, 7 is padding WORD imageStride = ((WORD *)gfx.RDRAM)[(addr+8)^1]; // 8 WORD imageAdrs = ((WORD *)gfx.RDRAM)[(addr+9)^1]; // 9 BYTE imageFmt = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+0)^3]; // 10 BYTE imageSiz = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+1)^3]; // | BYTE imagePal = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+2)^3]; // 11 BYTE imageFlags = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+3)^3]; // | if (imageW < 0) imageW = (short)rdp.scissor_o.lr_x - (short)objX - imageW; if (imageH < 0) imageH = (short)rdp.scissor_o.lr_y - (short)objY - imageH; FRDP ("uc6:obj_rectangle #%d, #%d\n" "objX: %f, scaleW: %f, imageW: %d\n" "objY: %f, scaleH: %f, imageH: %d\n" "size: %d, format: %d\n", rdp.tri_n, rdp.tri_n+1, objX, scaleW, imageW, objY, scaleH, imageH, imageSiz, imageFmt); if (imageAdrs > 4096) { FRDP("tmem: %08lx is out of bounds! return\n", imageAdrs); return; } if (!rdp.s2dex_tex_loaded) { RDP("Texture was not loaded! return\n"); return; } // SetTile () TILE *tile = &rdp.tiles[0]; tile->format = imageFmt; // RGBA tile->size = imageSiz; // 16-bit tile->line = imageStride; tile->t_mem = imageAdrs; tile->palette = imagePal; tile->clamp_t = 1; tile->mirror_t = 0; tile->mask_t = 0; tile->shift_t = 0; tile->clamp_s = 1; tile->mirror_s = 0; tile->mask_s = 0; tile->shift_s = 0; // SetTileSize () rdp.tiles[0].ul_s = 0; rdp.tiles[0].ul_t = 0; rdp.tiles[0].lr_s = (imageW>0)?imageW-1:0; rdp.tiles[0].lr_t = (imageH>0)?imageH-1:0; float Z = set_sprite_combine_mode (); float ul_x = objX; float lr_x = objX + imageW/scaleW; float ul_y = objY; float lr_y = objY + imageH/scaleH; float ul_u, lr_u, ul_v, lr_v; if (rdp.cur_cache[0]->splits > 1) { lr_u = (float)(imageW-1); lr_v = (float)(imageH-1); } else { lr_u = 255.0f*rdp.cur_cache[0]->scale_x; lr_v = 255.0f*rdp.cur_cache[0]->scale_y; } if (imageFlags&0x01) //flipS { ul_u = lr_u; lr_u = 0.5f; } else ul_u = 0.5f; if (imageFlags&0x10) //flipT { ul_v = lr_v; lr_v = 0.5f; } else ul_v = 0.5f; // Make the vertices VERTEX v[4] = { { ul_x, ul_y, Z, 1, ul_u, ul_v }, { lr_x, ul_y, Z, 1, lr_u, ul_v }, { ul_x, lr_y, Z, 1, ul_u, lr_v }, { lr_x, lr_y, Z, 1, lr_u, lr_v } }; int i; for (i=0; i<4; i++) { v[i].x *= rdp.scale_x; v[i].y *= rdp.scale_y; } uc6_draw_polygons (v); } void uc6_obj_sprite () { DWORD addr = segoffset(rdp.cmd1) >> 1; float objX = ((short*)gfx.RDRAM)[(addr+0)^1] / 4.0f; // 0 float scaleW = ((WORD *)gfx.RDRAM)[(addr+1)^1] / 1024.0f; // 1 short imageW = ((short*)gfx.RDRAM)[(addr+2)^1] >> 5; // 2, 3 is padding float objY = ((short*)gfx.RDRAM)[(addr+4)^1] / 4.0f; // 4 float scaleH = ((WORD *)gfx.RDRAM)[(addr+5)^1] / 1024.0f; // 5 short imageH = ((short*)gfx.RDRAM)[(addr+6)^1] >> 5; // 6, 7 is padding WORD imageStride = ((WORD *)gfx.RDRAM)[(addr+8)^1]; // 8 WORD imageAdrs = ((WORD *)gfx.RDRAM)[(addr+9)^1]; // 9 BYTE imageFmt = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+0)^3]; // 10 BYTE imageSiz = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+1)^3]; // | BYTE imagePal = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+2)^3]; // 11 BYTE imageFlags = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+3)^3]; // | FRDP ("uc6:obj_sprite #%d, #%d\n" "objX: %f, scaleW: %f, imageW: %d\n" "objY: %f, scaleH: %f, imageH: %d\n" "size: %d, format: %d\n", rdp.tri_n, rdp.tri_n+1, objX, scaleW, imageW, objY, scaleH, imageH, imageSiz, imageFmt); // SetTile () TILE *tile = &rdp.tiles[0]; tile->format = imageFmt; // RGBA tile->size = imageSiz; // 16-bit tile->line = imageStride; tile->t_mem = imageAdrs; tile->palette = imagePal; tile->clamp_t = 1; tile->mirror_t = 0; tile->mask_t = 0; tile->shift_t = 0; tile->clamp_s = 1; tile->mirror_s = 0; tile->mask_s = 0; tile->shift_s = 0; // SetTileSize () rdp.tiles[0].ul_s = 0; rdp.tiles[0].ul_t = 0; rdp.tiles[0].lr_s = (imageW>0)?imageW-1:0; rdp.tiles[0].lr_t = (imageH>0)?imageH-1:0; float Z = set_sprite_combine_mode (); float ul_x = objX; float lr_x = objX + imageW/scaleW; float ul_y = objY; float lr_y = objY + imageH/scaleH; float ul_u, lr_u, ul_v, lr_v; if (rdp.cur_cache[0]->splits > 1) { lr_u = (float)(imageW-1); lr_v = (float)(imageH-1); } else { lr_u = 255.0f*rdp.cur_cache[0]->scale_x; lr_v = 255.0f*rdp.cur_cache[0]->scale_y; } if (imageFlags&0x01) //flipS { ul_u = lr_u; lr_u = 0.5f; } else ul_u = 0.5f; if (imageFlags&0x10) //flipT { ul_v = lr_v; lr_v = 0.5f; } else ul_v = 0.5f; // Make the vertices // FRDP("scale_x: %f, scale_y: %f\n", rdp.cur_cache[0]->scale_x, rdp.cur_cache[0]->scale_y); VERTEX v[4] = { { ul_x, ul_y, Z, 1, ul_u, ul_v }, { lr_x, ul_y, Z, 1, lr_u, ul_v }, { ul_x, lr_y, Z, 1, ul_u, lr_v }, { lr_x, lr_y, Z, 1, lr_u, lr_v } }; int i; for (i=0; i<4; i++) { float x = v[i].x; float y = v[i].y; v[i].x = (x * mat_2d.A + y * mat_2d.B + mat_2d.X) * rdp.scale_x; v[i].y = (x * mat_2d.C + y * mat_2d.D + mat_2d.Y) * rdp.scale_y; } uc6_draw_polygons (v); } void uc6_obj_movemem () { RDP ("uc6:obj_movemem\n"); int index = rdp.cmd0 & 0xFFFF; DWORD addr = segoffset(rdp.cmd1) >> 1; if (index == 0) { // movemem matrix mat_2d.A = ((long*)gfx.RDRAM)[(addr+0)>>1] / 65536.0f; mat_2d.B = ((long*)gfx.RDRAM)[(addr+2)>>1] / 65536.0f; mat_2d.C = ((long*)gfx.RDRAM)[(addr+4)>>1] / 65536.0f; mat_2d.D = ((long*)gfx.RDRAM)[(addr+6)>>1] / 65536.0f; mat_2d.X = ((short*)gfx.RDRAM)[(addr+8)^1] / 4.0f; mat_2d.Y = ((short*)gfx.RDRAM)[(addr+9)^1] / 4.0f; mat_2d.BaseScaleX = ((WORD*)gfx.RDRAM)[(addr+10)^1] / 1024.0f; mat_2d.BaseScaleY = ((WORD*)gfx.RDRAM)[(addr+11)^1] / 1024.0f; FRDP ("mat_2d\nA: %f, B: %f, c: %f, D: %f\nX: %f, Y: %f\nBaseScaleX: %f, BaseScaleY: %f\n", mat_2d.A, mat_2d.B, mat_2d.C, mat_2d.D, mat_2d.X, mat_2d.Y, mat_2d.BaseScaleX, mat_2d.BaseScaleY); } else if (index == 2) { // movemem submatrix mat_2d.X = ((short*)gfx.RDRAM)[(addr+0)^1] / 4.0f; mat_2d.Y = ((short*)gfx.RDRAM)[(addr+1)^1] / 4.0f; mat_2d.BaseScaleX = ((WORD*)gfx.RDRAM)[(addr+2)^1] / 1024.0f; mat_2d.BaseScaleY = ((WORD*)gfx.RDRAM)[(addr+3)^1] / 1024.0f; FRDP ("submatrix\nX: %f, Y: %f\nBaseScaleX: %f, BaseScaleY: %f\n", mat_2d.X, mat_2d.Y, mat_2d.BaseScaleX, mat_2d.BaseScaleY); } } static void uc6_select_dl () { RDP ("uc6:select_dl\n"); RDP_E ("uc6:select_dl\n"); } static void uc6_obj_rendermode () { RDP ("uc6:obj_rendermode\n"); RDP_E ("uc6:obj_rendermode\n"); } void uc6_obj_rectangle_r () { // RDP ("uc6:obj_rectangle_r\n"); DWORD addr = segoffset(rdp.cmd1) >> 1; float objX = ((short*)gfx.RDRAM)[(addr+0)^1] / 4.0f; // 0 float scaleW = ((WORD *)gfx.RDRAM)[(addr+1)^1] / 1024.0f; // 1 short imageW = ((short*)gfx.RDRAM)[(addr+2)^1] >> 5; // 2, 3 is padding float objY = ((short*)gfx.RDRAM)[(addr+4)^1] / 4.0f; // 4 float scaleH = ((WORD *)gfx.RDRAM)[(addr+5)^1] / 1024.0f; // 5 short imageH = ((short*)gfx.RDRAM)[(addr+6)^1] >> 5; // 6, 7 is padding WORD imageStride = ((WORD *)gfx.RDRAM)[(addr+8)^1]; // 8 WORD imageAdrs = ((WORD *)gfx.RDRAM)[(addr+9)^1]; // 9 BYTE imageFmt = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+0)^3]; // 10 BYTE imageSiz = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+1)^3]; // | BYTE imagePal = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+2)^3]; // 11 BYTE imageFlags = ((BYTE *)gfx.RDRAM)[(((addr+10)<<1)+3)^3]; // | if (imageW < 0) imageW = (short)rdp.scissor_o.lr_x - (short)objX - imageW; if (imageH < 0) imageH = (short)rdp.scissor_o.lr_y - (short)objY - imageH; FRDP ("uc6:obj_rectangle_r #%d, #%d\n" "objX: %f, scaleW: %f, imageW: %d\n" "objY: %f, scaleH: %f, imageH: %d\n" "size: %d, format: %d\n", rdp.tri_n, rdp.tri_n+1, objX, scaleW, imageW, objY, scaleH, imageH, imageSiz, imageFmt); if (imageFmt == 1) //YUV { float ul_x = objX/mat_2d.BaseScaleX + mat_2d.X; float lr_x = (objX + imageW/scaleW)/mat_2d.BaseScaleX + mat_2d.X; float ul_y = objY/mat_2d.BaseScaleY + mat_2d.Y; float lr_y = (objY + imageH/scaleH)/mat_2d.BaseScaleY + mat_2d.Y; if (ul_x < rdp.yuv_ul_x) rdp.yuv_ul_x = ul_x; if (lr_x > rdp.yuv_lr_x) rdp.yuv_lr_x = lr_x; if (ul_y < rdp.yuv_ul_y) rdp.yuv_ul_y = ul_y; if (lr_y > rdp.yuv_lr_y) rdp.yuv_lr_y = lr_y; rdp.tri_n += 2; return; } // SetTile () TILE *tile = &rdp.tiles[0]; tile->format = imageFmt; // RGBA tile->size = imageSiz; // 16-bit tile->line = imageStride; tile->t_mem = imageAdrs; tile->palette = imagePal; tile->clamp_t = 1; tile->mirror_t = 0; tile->mask_t = 0; tile->shift_t = 0; tile->clamp_s = 1; tile->mirror_s = 0; tile->mask_s = 0; tile->shift_s = 0; // SetTileSize () rdp.tiles[0].ul_s = 0; rdp.tiles[0].ul_t = 0; rdp.tiles[0].lr_s = (imageW>0)?imageW-1:0; rdp.tiles[0].lr_t = (imageH>0)?imageH-1:0; float Z = set_sprite_combine_mode (); float ul_x = objX/mat_2d.BaseScaleX; float lr_x = (objX + imageW/scaleW)/mat_2d.BaseScaleX; float ul_y = objY/mat_2d.BaseScaleY; float lr_y = (objY + imageH/scaleH)/mat_2d.BaseScaleY; float ul_u, lr_u, ul_v, lr_v; if (rdp.cur_cache[0]->splits > 1) { lr_u = (float)(imageW-1); lr_v = (float)(imageH-1); } else { lr_u = 255.0f*rdp.cur_cache[0]->scale_x; lr_v = 255.0f*rdp.cur_cache[0]->scale_y; } if (imageFlags&0x01) //flipS { ul_u = lr_u; lr_u = 0.5f; } else ul_u = 0.5f; if (imageFlags&0x10) //flipT { ul_v = lr_v; lr_v = 0.5f; } else ul_v = 0.5f; // Make the vertices VERTEX v[4] = { { ul_x, ul_y, Z, 1, ul_u, ul_v }, { lr_x, ul_y, Z, 1, lr_u, ul_v }, { ul_x, lr_y, Z, 1, ul_u, lr_v }, { lr_x, lr_y, Z, 1, lr_u, lr_v } }; int i; for (i=0; i<4; i++) { float x = v[i].x; float y = v[i].y; v[i].x = (x + mat_2d.X) * rdp.scale_x; v[i].y = (y + mat_2d.Y) * rdp.scale_y; } uc6_draw_polygons (v); } void uc6_obj_loadtxtr () { RDP ("uc6:obj_loadtxtr "); rdp.s2dex_tex_loaded = TRUE; rdp.update |= UPDATE_TEXTURE; DWORD addr = segoffset(rdp.cmd1) >> 1; DWORD type = ((DWORD*)gfx.RDRAM)[(addr + 0) >> 1]; // 0, 1 if (type == 0x00000030) { // TLUT DWORD image = segoffset(((DWORD*)gfx.RDRAM)[(addr + 2) >> 1]); // 2, 3 WORD phead = ((WORD *)gfx.RDRAM)[(addr + 4) ^ 1] - 256; // 4 WORD pnum = ((WORD *)gfx.RDRAM)[(addr + 5) ^ 1] + 1; // 5 FRDP ("palette addr: %08lx, start: %d, num: %d\n", image, phead, pnum); load_palette (image, phead, pnum); } else if (type == 0x00001033) { // TxtrBlock DWORD image = segoffset(((DWORD*)gfx.RDRAM)[(addr + 2) >> 1]); // 2, 3 WORD tmem = ((WORD *)gfx.RDRAM)[(addr + 4) ^ 1]; // 4 WORD tsize = ((WORD *)gfx.RDRAM)[(addr + 5) ^ 1]; // 5 WORD tline = ((WORD *)gfx.RDRAM)[(addr + 6) ^ 1]; // 6 FRDP ("addr: %08lx, tmem: %08lx, size: %d\n", image, tmem, tsize); rdp.timg.addr = image; rdp.tiles[7].t_mem = tmem; rdp.tiles[7].size = 1; rdp.cmd0 = 0; rdp.cmd1 = 0x07000000 | (tsize << 14) | tline; rdp_loadblock (); } else if (type == 0x00fc1034) { DWORD image = segoffset(((DWORD*)gfx.RDRAM)[(addr + 2) >> 1]); // 2, 3 WORD tmem = ((WORD *)gfx.RDRAM)[(addr + 4) ^ 1]; // 4 WORD twidth = ((WORD *)gfx.RDRAM)[(addr + 5) ^ 1]; // 5 WORD theight = ((WORD *)gfx.RDRAM)[(addr + 6) ^ 1]; // 6 FRDP ("tile addr: %08lx, tmem: %08lx, twidth: %d, theight: %d\n", image, tmem, twidth, theight); int line = (twidth + 1) >> 2; rdp.timg.addr = image; rdp.timg.width = line << 3; rdp.tiles[7].t_mem = tmem; rdp.tiles[7].line = line; rdp.tiles[7].size = 1; rdp.cmd0 = 0; rdp.cmd1 = 0x07000000 | (twidth << 14) | (theight << 2); rdp_loadtile (); } else { FRDP ("UNKNOWN (0x%08lx)\n", type); FRDP_E ("uc6:obj_loadtxtr UNKNOWN (0x%08lx)\n", type); } } void uc6_obj_ldtx_sprite () { RDP ("uc6:obj_ldtx_sprite\n"); DWORD addr = rdp.cmd1; uc6_obj_loadtxtr (); rdp.cmd1 = addr + 24; uc6_obj_sprite (); } void uc6_obj_ldtx_rect () { RDP ("uc6:obj_ldtx_rect\n"); DWORD addr = rdp.cmd1; uc6_obj_loadtxtr (); rdp.cmd1 = addr + 24; uc6_obj_rectangle (); } static void uc6_ldtx_rect_r () { RDP ("uc6:ldtx_rect_r\n"); DWORD addr = rdp.cmd1; uc6_obj_loadtxtr (); rdp.cmd1 = addr + 24; uc6_obj_rectangle_r (); } #ifdef _WIN32 static void uc6_rdphalf_0 () { RDP ("uc6:rdphalf_0\n"); RDP_E ("uc6:rdphalf_0\n"); } #endif // _WIN32 static void uc6_rdphalf_1 () { RDP ("uc6:rdphalf_1\n"); RDP_E ("uc6:rdphalf_1\n"); } static void uc6_loaducode () { RDP ("uc6:load_ucode\n"); RDP_E ("uc6:load_ucode\n"); // copy the microcode data DWORD addr = segoffset(rdp.cmd1); DWORD size = (rdp.cmd0 & 0xFFFF) + 1; memcpy (microcode, gfx.RDRAM+addr, size); microcheck (); } void drawViRegBG() { DWORD VIwidth = *gfx.VI_WIDTH_REG; DRAWIMAGE d; d.imageX = 0; d.imageW = (WORD)VIwidth; if (d.imageW%4) d.imageW -= 2; d.frameX = 0; d.frameW = (WORD)rdp.vi_width; d.imageY = 0; d.imageH = (WORD)rdp.vi_height; d.frameY = 0; d.frameH = (WORD)(rdp.vi_height); RDP ("drawViRegBG\n"); FRDP ("frameX: %f, frameW: %d, frameY: %f, frameH: %d\n", d.frameX, d.frameW, d.frameY, d.frameH); FRDP ("imageX: %d, imageW: %d, imageY: %d, imageH: %d\n", d.imageX, d.imageW, d.imageY, d.imageH); if (!settings.RE2) { d.imagePtr = (*gfx.VI_ORIGIN_REG) - (VIwidth<<1); rdp.last_bg = d.imagePtr; rdp.cycle_mode = 2; d.imageSiz = 2; d.imageFmt = 0; d.imagePal = 0; d.scaleX = 1.0f; d.scaleY = 1.0f; d.flipX = 0; d.flipY = 0; // FRDP ("drawViRegBG imageW :%d, imageH: %d\n", d.imageW, d.imageH); if (!d.imageW || !d.imageH) { RDP("skipped\n"); return; } DrawImage (&d); if (settings.lego) { rdp.updatescreen = 1; newSwapBuffers (); DrawImage (&d); } return; } //Draw RE2 video d.imagePtr = (*gfx.VI_ORIGIN_REG) - (VIwidth<<2); rdp.last_bg = d.imagePtr; if (d.imageH > 256) d.imageH = 256; update_screen_count = 0; /* if (settings.RE2_native_video) //draw video in native resolution and without conversion. { DWORD * image = new DWORD[d.imageW*d.imageH]; DWORD * src = (DWORD*)(gfx.RDRAM+d.imagePtr); DWORD * dst = image; DWORD col; for (int h = 0; h < d.imageH; h++) { for (int w = 0; w < d.imageW; w++) { col = *(src++); *(dst++) = col >> 8; } } int x = (settings.scr_res_x - d.imageW) / 2; int y = (settings.scr_res_y - d.imageH) / 2; grLfbWriteRegion(GR_BUFFER_BACKBUFFER, x, y, GR_LFB_SRC_FMT_888, d.imageW, d.imageH, FXFALSE, d.imageW<<2, image); delete[] image; } else { */ DWORD * src = (DWORD*)(gfx.RDRAM+d.imagePtr); GrTexInfo t_info; t_info.smallLodLog2 = GR_LOD_LOG2_256; t_info.largeLodLog2 = GR_LOD_LOG2_256; t_info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; if (sup_32bit_tex) //use 32bit textures { DWORD image[256*256]; DWORD * dst = image; DWORD col; for (int h = 0; h < d.imageH; h++) { for (int w = 0; w < 256; w++) { col = *(src++); *(dst++) = (col >> 8) | 0xFF000000; } src += (d.imageW - 256); } t_info.format = GR_TEXFMT_ARGB_8888; t_info.data = image; grTexDownloadMipMap (GR_TMU0, grTexMinAddress(GR_TMU0)+offset_textures, GR_MIPMAPLEVELMASK_BOTH, &t_info); } else { WORD image[256*256]; WORD * dst = image; DWORD col; BYTE r, g, b; for (int h = 0; h < d.imageH; h++) { for (int w = 0; w < 256; w++) { col = *(src++); r = (BYTE)((col >> 24)&0xFF); r = (BYTE)((float)r / 255.0f * 31.0f); g = (BYTE)((col >> 16)&0xFF); g = (BYTE)((float)g / 255.0f * 63.0f); b = (BYTE)((col >> 8)&0xFF); b = (BYTE)((float)b / 255.0f * 31.0f); *(dst++) = (r << 11) | (g << 5) | b; } src += (d.imageW - 256); } t_info.format = GR_TEXFMT_RGB_565; t_info.data = image; grTexDownloadMipMap (GR_TMU0, grTexMinAddress(GR_TMU0)+offset_textures, GR_MIPMAPLEVELMASK_BOTH, &t_info); } grTexSource (GR_TMU0, grTexMinAddress(GR_TMU0)+offset_textures, GR_MIPMAPLEVELMASK_BOTH, &t_info); grTexCombine( GR_TMU1, GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE ); grTexCombine( GR_TMU0, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE ); grTexClampMode (GR_TMU0, GR_TEXTURECLAMP_WRAP, GR_TEXTURECLAMP_CLAMP); grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE, FXFALSE); grAlphaBlendFunction (GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO); grConstantColorValue (0xFFFFFFFF); grDepthBufferFunction (GR_CMP_ALWAYS); grDepthMask (FXFALSE); float scale_y = (float)d.imageW/rdp.vi_height; float height = settings.scr_res_x/scale_y; float ul_y = (settings.scr_res_y - height)/2.0f; float lr_y = settings.scr_res_y - ul_y - 1.0f; float lr_x = settings.scr_res_x-1.0f; float lr_u = d.imageW - 1.0f; float lr_v = d.imageH - 1.0f; VERTEX v[4] = { { 0, ul_y, 1.0f, 1.0f, 0, 0, 0, 0 }, { lr_x, ul_y, 1.0f, 1.0f, lr_u, 0, lr_u, 0 }, { 0, lr_y, 1.0f, 1.0f, 0, lr_v, 0, lr_v }, { lr_x, lr_y, 1.0f, 1.0f, lr_u, lr_v, lr_u, lr_v } }; for (int i=0; i<4; i++) { v[i].uc(0) = v[i].u0; v[i].vc(0) = v[i].v0; } grDrawTriangle (&v[0], &v[2], &v[1]); grDrawTriangle (&v[2], &v[3], &v[1]); } void uc6_sprite2d () { DWORD a = rdp.pc[rdp.pc_i] & BMASK; DWORD cmd0 = ((DWORD*)gfx.RDRAM)[a>>2]; //check next command if ( (cmd0>>24) != 0xBE ) return; FRDP ("uc6:uc6_sprite2d #%d, #%d\n", rdp.tri_n, rdp.tri_n+1); DWORD addr = segoffset(rdp.cmd1) >> 1; DRAWIMAGE d; d.imagePtr = segoffset(((DWORD*)gfx.RDRAM)[(addr+0)>>1]); // 0,1 DWORD tlut = ((DWORD*)gfx.RDRAM)[(addr + 2) >> 1]; // 2, 3 if (tlut) { rdp.tlut_mode = 2; load_palette (segoffset(tlut), 0, 256); } WORD stride = (((WORD *)gfx.RDRAM)[(addr+4)^1]); // 4 d.imageW = (((WORD *)gfx.RDRAM)[(addr+5)^1]); // 5 d.imageH = (((WORD *)gfx.RDRAM)[(addr+6)^1]); // 6 d.imageFmt = ((BYTE *)gfx.RDRAM)[(((addr+7)<<1)+0)^3]; // 7 d.imageSiz = ((BYTE *)gfx.RDRAM)[(((addr+7)<<1)+1)^3]; // | d.imagePal = 0; d.imageX = (((WORD *)gfx.RDRAM)[(addr+8)^1]); // 8 d.imageY = (((WORD *)gfx.RDRAM)[(addr+9)^1]); // 9 if (d.imageW == 0) return;// d.imageW = stride; cmd0 = ((DWORD*)gfx.RDRAM)[a>>2]; //check next command while (1) { if ( (cmd0>>24) == 0xBE ) { DWORD cmd1 = ((DWORD*)gfx.RDRAM)[(a>>2)+1]; rdp.pc[rdp.pc_i] = (a+8) & BMASK; d.scaleX = ((cmd1>>16)&0xFFFF)/1024.0f; d.scaleY = (cmd1&0xFFFF)/1024.0f; if( (cmd1&0xFFFF) < 0x100 ) d.scaleY = d.scaleX; d.flipX = (BYTE)((cmd0>>8)&0xFF); d.flipY = (BYTE)(cmd0&0xFF); a = rdp.pc[rdp.pc_i] & BMASK; rdp.pc[rdp.pc_i] = (a+8) & BMASK; cmd0 = ((DWORD*)gfx.RDRAM)[a>>2]; //check next command } if ( (cmd0>>24) == 0xBD ) { DWORD cmd1 = ((DWORD*)gfx.RDRAM)[(a>>2)+1]; d.frameX = ((short)((cmd1>>16)&0xFFFF)) / 4.0f; d.frameY = ((short)(cmd1&0xFFFF)) / 4.0f; d.frameW = (WORD) (d.imageW / d.scaleX); d.frameH = (WORD) (d.imageH / d.scaleY); if (settings.nitro) { int scaleY = (int)d.scaleY; d.imageH /= scaleY; d.imageY /= scaleY; stride *= scaleY; d.scaleY = 1.0f; } FRDP ("imagePtr: %08lx\n", d.imagePtr); FRDP ("frameX: %f, frameW: %d, frameY: %f, frameH: %d\n", d.frameX, d.frameW, d.frameY, d.frameH); FRDP ("imageX: %d, imageW: %d, imageY: %d, imageH: %d\n", d.imageX, d.imageW, d.imageY, d.imageH); FRDP ("imageFmt: %d, imageSiz: %d, imagePal: %d, imageStride: %d\n", d.imageFmt, d.imageSiz, d.imagePal, stride); FRDP ("scaleX: %f, scaleY: %f\n", d.scaleX, d.scaleY); } else { return; } DWORD texsize = d.imageW * d.imageH; if (d.imageSiz == 0) texsize >>= 1; else texsize <<= (d.imageSiz-1); if (texsize > 4096) { d.imageW = stride; d.imageH += d.imageY; DrawImage (&d); } else { WORD line = d.imageW; if (line & 7) line += 8; // round up line >>= 3; if (d.imageSiz == 0) { if (line%2) line++; line >>= 1; } else { line <<= (d.imageSiz-1); } if (line == 0) line = 1; rdp.timg.addr = d.imagePtr; rdp.timg.width = stride; rdp.tiles[7].t_mem = 0; rdp.tiles[7].line = line;//(d.imageW>>3); rdp.tiles[7].size = d.imageSiz; rdp.cmd0 = (d.imageX << 14) | (d.imageY << 2); rdp.cmd1 = 0x07000000 | ((d.imageX+d.imageW-1) << 14) | ((d.imageY+d.imageH-1) << 2); rdp_loadtile (); // SetTile () TILE *tile = &rdp.tiles[0]; tile->format = d.imageFmt; tile->size = d.imageSiz; tile->line = line;//(d.imageW>>3); tile->t_mem = 0; tile->palette = 0; tile->clamp_t = 1; tile->mirror_t = 0; tile->mask_t = 0; tile->shift_t = 0; tile->clamp_s = 1; tile->mirror_s = 0; tile->mask_s = 0; tile->shift_s = 0; // SetTileSize () rdp.tiles[0].ul_s = d.imageX; rdp.tiles[0].ul_t = d.imageY; rdp.tiles[0].lr_s = d.imageX+d.imageW-1; rdp.tiles[0].lr_t = d.imageY+d.imageH-1; float Z = set_sprite_combine_mode (); float ul_x, ul_y, lr_x, lr_y; if (d.flipX) { ul_x = d.frameX + d.frameW; lr_x = d.frameX; } else { ul_x = d.frameX; lr_x = d.frameX + d.frameW; } if (d.flipY) { ul_y = d.frameY + d.frameH; lr_y = d.frameY; } else { ul_y = d.frameY; lr_y = d.frameY + d.frameH; } float lr_u, lr_v; if (rdp.cur_cache[0]->splits > 1) { lr_u = (float)(d.imageW-1); lr_v = (float)(d.imageH-1); } else { lr_u = 255.0f*rdp.cur_cache[0]->scale_x; lr_v = 255.0f*rdp.cur_cache[0]->scale_y; } // Make the vertices VERTEX v[4] = { { ul_x, ul_y, Z, 1, 0.5f, 0.5f }, { lr_x, ul_y, Z, 1, lr_u, 0.5f }, { ul_x, lr_y, Z, 1, 0.5f, lr_v }, { lr_x, lr_y, Z, 1, lr_u, lr_v } }; int i; for (i=0; i<4; i++) { v[i].x *= rdp.scale_x; v[i].y *= rdp.scale_y; } // ConvertCoordsConvert (v, 4); AllowShadeMods (v, 4); for (int s = 0; s < 4; s++) apply_shade_mods (&(v[s])); // Set vertex buffers if (rdp.cur_cache[0]->splits > 1) { VERTEX *vptr[3]; for (i = 0; i < 3; i++) vptr[i] = &v[i]; draw_splitted_triangle(vptr); rdp.tri_n ++; for (i = 0; i < 3; i++) vptr[i] = &v[i+1]; draw_splitted_triangle(vptr); rdp.tri_n ++; } else { rdp.vtxbuf = rdp.vtx1; // copy from v to rdp.vtx1 rdp.vtxbuf2 = rdp.vtx2; rdp.vtx_buffer = 0; rdp.n_global = 3; memcpy (rdp.vtxbuf, v, sizeof(VERTEX)*3); do_triangle_stuff_2 (); rdp.tri_n ++; rdp.vtxbuf = rdp.vtx1; // copy from v to rdp.vtx1 rdp.vtxbuf2 = rdp.vtx2; rdp.vtx_buffer = 0; rdp.n_global = 3; memcpy (rdp.vtxbuf, v+1, sizeof(VERTEX)*3); do_triangle_stuff_2 (); rdp.tri_n ++; } rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_VIEWPORT; if (fullscreen && settings.fog && (rdp.flags & FOG_ENABLED)) { grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT); } } a = rdp.pc[rdp.pc_i] & BMASK; cmd0 = ((DWORD*)gfx.RDRAM)[a>>2]; //check next command if (( (cmd0>>24) == 0xBD ) || ( (cmd0>>24) == 0xBE )) rdp.pc[rdp.pc_i] = (a+8) & BMASK; else return; } } mupen64plus-video-glide64-src-2.6.0/src/ucode07.h000066400000000000000000000120061464507525600212710ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** // // Oct 2002 Created by Gonetz (Gonetz@ngs.ru) // Info about this ucode is taken from TR64 OGL plugin. Thanks, Icepir8! // Oct 2003 Modified by Gonetz (Gonetz@ngs.ru) // Bugs fixed with help from glN64 sources. Thanks, Orkin! //**************************************************************** DWORD pd_col_addr = 0; static void uc7_colorbase () { RDP("uc7_colorbase\n"); pd_col_addr = segoffset(rdp.cmd1); } typedef struct { short y; short x; WORD idx; short z; short t; short s; } vtx_uc7; static void uc7_vertex () { if (rdp.update & UPDATE_MULT_MAT) { rdp.update ^= UPDATE_MULT_MAT; MulMatrices(rdp.model, rdp.proj, rdp.combined); } // This is special, not handled in update() if (rdp.update & UPDATE_LIGHTS) { rdp.update ^= UPDATE_LIGHTS; // Calculate light vectors for (DWORD l=0; l> 16; rdp.vn = n = ((rdp.cmd0 & 0xF00000) >> 20) + 1; FRDP ("uc7:vertex n: %d, v0: %d, from: %08lx\n", n, v0, addr); vtx_uc7 *vertex = (vtx_uc7 *)&gfx.RDRAM[addr]; for(i = 0; i < n; i++) { VERTEX *v = &rdp.vtx[v0 + i]; x = (float)vertex->x; y = (float)vertex->y; z = (float)vertex->z; v->flags = 0; v->ou = (float)vertex->s * rdp.tiles[rdp.cur_tile].s_scale; v->ov = (float)vertex->t * rdp.tiles[rdp.cur_tile].t_scale; #ifdef EXTREME_LOGGING // FRDP ("before: v%d - x: %f, y: %f, z: %f, flags: %04lx, ou: %f, ov: %f\n", i>>4, x, y, z, v->flags, v->ou, v->ov); #endif v->x = x*rdp.combined[0][0] + y*rdp.combined[1][0] + z*rdp.combined[2][0] + rdp.combined[3][0]; v->y = x*rdp.combined[0][1] + y*rdp.combined[1][1] + z*rdp.combined[2][1] + rdp.combined[3][1]; v->z = x*rdp.combined[0][2] + y*rdp.combined[1][2] + z*rdp.combined[2][2] + rdp.combined[3][2]; v->w = x*rdp.combined[0][3] + y*rdp.combined[1][3] + z*rdp.combined[2][3] + rdp.combined[3][3]; v->oow = 1.0f / v->w; v->x_w = v->x * v->oow; v->y_w = v->y * v->oow; v->z_w = v->z * v->oow; v->uv_calculated = 0xFFFFFFFF; v->screen_translated = 0; v->scr_off = 0; if (v->x < -v->w) v->scr_off |= 1; if (v->x > v->w) v->scr_off |= 2; if (v->y < -v->w) v->scr_off |= 4; if (v->y > v->w) v->scr_off |= 8; if (v->w < 0.1f) v->scr_off |= 16; BYTE *color = &gfx.RDRAM[pd_col_addr + (vertex->idx & 0xff)]; v->a = color[0]; CalculateFog (v); if (rdp.geom_mode & 0x00020000) { v->vec[0] = (char)color[3]; v->vec[1] = (char)color[2]; v->vec[2] = (char)color[1]; if (rdp.geom_mode & 0x80000) { calc_linear (v); #ifdef EXTREME_LOGGING FRDP ("calc linear: v%d - u: %f, v: %f\n", i>>4, v->ou, v->ov); #endif } else if (rdp.geom_mode & 0x40000) { calc_sphere (v); #ifdef EXTREME_LOGGING FRDP ("calc sphere: v%d - u: %f, v: %f\n", i>>4, v->ou, v->ov); #endif } NormalizeVector (v->vec); calc_light (v); } else { v->r = color[3]; v->g = color[2]; v->b = color[1]; } #ifdef EXTREME_LOGGING FRDP ("v%d - x: %f, y: %f, z: %f, w: %f, u: %f, v: %f\n", i>>4, v->x, v->y, v->z, v->w, v->ou, v->ov); #endif vertex++; } } mupen64plus-video-glide64-src-2.6.0/src/ucode08.h000066400000000000000000000444341464507525600213040ustar00rootroot00000000000000/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * * 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 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA */ //**************************************************************** // // Glide64 - Glide Plugin for Nintendo 64 emulators (tested mostly with Project64) // Project started on December 29th, 2001 // // To modify Glide64: // * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me. // * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all. // // Official Glide64 development channel: #Glide64 on EFnet // // Original author: Dave2001 (Dave2999@hotmail.com) // Other authors: Gonetz, Gugaman // //**************************************************************** // // January 2004 Created by Gonetz (Gonetz@ngs.ru) //**************************************************************** DWORD uc8_normale_addr = 0; float uc8_coord_mod[16]; static void uc8_vertex () { if (rdp.update & UPDATE_MULT_MAT) { rdp.update ^= UPDATE_MULT_MAT; MulMatrices(rdp.model, rdp.proj, rdp.combined); } DWORD addr = segoffset(rdp.cmd1); int v0, i, n; float x, y, z; rdp.vn = n = (rdp.cmd0 >> 12) & 0xFF; rdp.v0 = v0 = ((rdp.cmd0 >> 1) & 0x7F) - n; FRDP ("uc8:vertex n: %d, v0: %d, from: %08lx\n", n, v0, addr); if (v0 < 0) { RDP_E ("** ERROR: uc2:vertex v0 < 0\n"); RDP ("** ERROR: uc2:vertex v0 < 0\n"); return; } //* // This is special, not handled in update() if (rdp.update & UPDATE_LIGHTS) { rdp.update ^= UPDATE_LIGHTS; // Calculate light vectors for (DWORD l=0; l>4)]; x = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 0)^1]; y = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 1)^1]; z = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 2)^1]; v->flags = ((WORD*)gfx.RDRAM)[(((addr+i) >> 1) + 3)^1]; v->ou = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 4)^1] * rdp.tiles[rdp.cur_tile].s_scale; v->ov = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 5)^1] * rdp.tiles[rdp.cur_tile].t_scale; v->a = ((BYTE*)gfx.RDRAM)[(addr+i + 15)^3]; #ifdef EXTREME_LOGGING FRDP ("before v%d - x: %f, y: %f, z: %f\n", i>>4, x, y, z); #endif v->x = x*rdp.combined[0][0] + y*rdp.combined[1][0] + z*rdp.combined[2][0] + rdp.combined[3][0]; v->y = x*rdp.combined[0][1] + y*rdp.combined[1][1] + z*rdp.combined[2][1] + rdp.combined[3][1]; v->z = x*rdp.combined[0][2] + y*rdp.combined[1][2] + z*rdp.combined[2][2] + rdp.combined[3][2]; v->w = x*rdp.combined[0][3] + y*rdp.combined[1][3] + z*rdp.combined[2][3] + rdp.combined[3][3]; #ifdef EXTREME_LOGGING FRDP ("v%d - x: %f, y: %f, z: %f, w: %f, u: %f, v: %f, flags: %d\n", i>>4, v->x, v->y, v->z, v->w, v->ou, v->ov, v->flags); #endif v->oow = 1.0f / v->w; v->x_w = v->x * v->oow; v->y_w = v->y * v->oow; v->z_w = v->z * v->oow; v->uv_calculated = 0xFFFFFFFF; v->screen_translated = 0; v->shade_mods_allowed = 1; v->scr_off = 0; if (v->x < -v->w) v->scr_off |= 1; if (v->x > v->w) v->scr_off |= 2; if (v->y < -v->w) v->scr_off |= 4; if (v->y > v->w) v->scr_off |= 8; if (v->w < 0.1f) v->scr_off |= 16; ///* v->r = ((BYTE*)gfx.RDRAM)[(addr+i + 12)^3]; v->g = ((BYTE*)gfx.RDRAM)[(addr+i + 13)^3]; v->b = ((BYTE*)gfx.RDRAM)[(addr+i + 14)^3]; #ifdef EXTREME_LOGGING FRDP ("r: %02lx, g: %02lx, b: %02lx, a: %02lx\n", v->r, v->g, v->b, v->a); #endif if ((rdp.geom_mode & 0x00020000)) { DWORD shift = v0 << 1; v->vec[0] = ((char*)gfx.RDRAM)[(uc8_normale_addr + (i>>3) + shift + 0)^3]; v->vec[1] = ((char*)gfx.RDRAM)[(uc8_normale_addr + (i>>3) + shift + 1)^3]; v->vec[2] = (char)(v->flags&0xff); if (rdp.geom_mode & 0x80000) { calc_linear (v); #ifdef EXTREME_LOGGING FRDP ("calc linear: v%d - u: %f, v: %f\n", i>>4, v->ou, v->ov); #endif } else if (rdp.geom_mode & 0x40000) { calc_sphere (v); #ifdef EXTREME_LOGGING FRDP ("calc sphere: v%d - u: %f, v: %f\n", i>>4, v->ou, v->ov); #endif } // FRDP("calc light. r: 0x%02lx, g: 0x%02lx, b: 0x%02lx, nx: %.3f, ny: %.3f, nz: %.3f\n", v->r, v->g, v->b, v->vec[0], v->vec[1], v->vec[2]); FRDP("v[%d] calc light. r: 0x%02lx, g: 0x%02lx, b: 0x%02lx\n", i>>4, v->r, v->g, v->b); float color[3] = {rdp.light[rdp.num_lights].r, rdp.light[rdp.num_lights].g, rdp.light[rdp.num_lights].b}; FRDP("ambient light. r: %f, g: %f, b: %f\n", color[0], color[1], color[2]); float light_intensity = 0.0f; DWORD l; if (rdp.geom_mode & 0x00400000) { NormalizeVector (v->vec); for (l = 0; l < rdp.num_lights-1; l++) { if (!rdp.light[l].nonblack) continue; light_intensity = DotProduct (rdp.light_vector[l], v->vec); FRDP("light %d, intensity : %f\n", l, light_intensity); if (light_intensity < 0.0f) continue; //* if (rdp.light[l].ca > 0.0f) { float vx = (v->x + uc8_coord_mod[8])*uc8_coord_mod[12] - rdp.light[l].x; float vy = (v->y + uc8_coord_mod[9])*uc8_coord_mod[13] - rdp.light[l].y; float vz = (v->z + uc8_coord_mod[10])*uc8_coord_mod[14] - rdp.light[l].z; float vw = (v->w + uc8_coord_mod[11])*uc8_coord_mod[15] - rdp.light[l].w; float len = (vx*vx+vy*vy+vz*vz+vw*vw)/65536.0f; float p_i = rdp.light[l].ca / len; if (p_i > 1.0f) p_i = 1.0f; light_intensity *= p_i; FRDP("light %d, len: %f, p_intensity : %f\n", l, len, p_i); } //*/ color[0] += rdp.light[l].r * light_intensity; color[1] += rdp.light[l].g * light_intensity; color[2] += rdp.light[l].b * light_intensity; FRDP("light %d r: %f, g: %f, b: %f\n", l, color[0], color[1], color[2]); } light_intensity = DotProduct (rdp.light_vector[l], v->vec); FRDP("light %d, intensity : %f\n", l, light_intensity); if (light_intensity > 0.0f) { color[0] += rdp.light[l].r * light_intensity; color[1] += rdp.light[l].g * light_intensity; color[2] += rdp.light[l].b * light_intensity; } FRDP("light %d r: %f, g: %f, b: %f\n", l, color[0], color[1], color[2]); } else { for (l = 0; l < rdp.num_lights; l++) { if (rdp.light[l].nonblack && rdp.light[l].nonzero) { float vx = (v->x + uc8_coord_mod[8])*uc8_coord_mod[12] - rdp.light[l].x; float vy = (v->y + uc8_coord_mod[9])*uc8_coord_mod[13] - rdp.light[l].y; float vz = (v->z + uc8_coord_mod[10])*uc8_coord_mod[14] - rdp.light[l].z; float vw = (v->w + uc8_coord_mod[11])*uc8_coord_mod[15] - rdp.light[l].w; float len = (vx*vx+vy*vy+vz*vz+vw*vw)/65536.0f; light_intensity = rdp.light[l].ca / len; if (light_intensity > 1.0f) light_intensity = 1.0f; FRDP("light %d, p_intensity : %f\n", l, light_intensity); color[0] += rdp.light[l].r * light_intensity; color[1] += rdp.light[l].g * light_intensity; color[2] += rdp.light[l].b * light_intensity; //FRDP("light %d r: %f, g: %f, b: %f\n", l, color[0], color[1], color[2]); } } } if (color[0] > 1.0f) color[0] = 1.0f; if (color[1] > 1.0f) color[1] = 1.0f; if (color[2] > 1.0f) color[2] = 1.0f; v->r = (BYTE)(((float)v->r)*color[0]); v->g = (BYTE)(((float)v->g)*color[1]); v->b = (BYTE)(((float)v->b)*color[2]); #ifdef EXTREME_LOGGING FRDP("color after light: r: 0x%02lx, g: 0x%02lx, b: 0x%02lx\n", v->r, v->g, v->b); #endif } } } static void uc8_moveword () { BYTE index = (BYTE)((rdp.cmd0 >> 16) & 0xFF); WORD offset = (WORD)(rdp.cmd0 & 0xFFFF); DWORD data = rdp.cmd1; FRDP ("uc8:moveword "); switch (index) { // NOTE: right now it's assuming that it sets the integer part first. This could // be easily fixed, but only if i had something to test with. case 0x02: rdp.num_lights = (data / 48); rdp.update |= UPDATE_LIGHTS; FRDP ("numlights: %d\n", rdp.num_lights); break; case 0x04: FRDP ("mw_clip %08lx, %08lx\n", rdp.cmd0, rdp.cmd1); break; case 0x06: // moveword SEGMENT { FRDP ("SEGMENT %08lx -> seg%d\n", data, offset >> 2); rdp.segment[(offset >> 2) & 0xF] = data; } break; case 0x08: { rdp.fog_multiplier = (short)(rdp.cmd1 >> 16); rdp.fog_offset = (short)(rdp.cmd1 & 0x0000FFFF); FRDP ("fog: multiplier: %f, offset: %f\n", rdp.fog_multiplier, rdp.fog_offset); } break; case 0x0c: RDP_E ("uc8:moveword forcemtx - IGNORED\n"); RDP ("forcemtx - IGNORED\n"); break; case 0x0e: RDP ("perspnorm - IGNORED\n"); break; case 0x10: // moveword coord mod { BYTE n = offset >> 2; FRDP ("coord mod:%d, %08lx\n", n, data); if (rdp.cmd0&8) return; DWORD idx = (rdp.cmd0>>1)&3; DWORD pos = rdp.cmd0&0x30; if (pos == 0) { uc8_coord_mod[0+idx] = (short)(rdp.cmd1>>16); uc8_coord_mod[1+idx] = (short)(rdp.cmd1&0xffff); } else if (pos == 0x10) { uc8_coord_mod[4+idx] = (rdp.cmd1>>16)/65536.0f; uc8_coord_mod[5+idx] = (rdp.cmd1&0xffff)/65536.0f; uc8_coord_mod[12+idx] = uc8_coord_mod[0+idx] + uc8_coord_mod[4+idx]; uc8_coord_mod[13+idx] = uc8_coord_mod[1+idx] + uc8_coord_mod[5+idx]; } else if (pos == 0x20) { uc8_coord_mod[8+idx] = (short)(rdp.cmd1>>16); uc8_coord_mod[9+idx] = (short)(rdp.cmd1&0xffff); #ifdef EXTREME_LOGGING if (idx) { for (int k = 8; k < 16; k++) { FRDP("coord_mod[%d]=%f\n", k, uc8_coord_mod[k]); } } #endif } } break; default: FRDP_E("uc8:moveword unknown (index: 0x%08lx, offset 0x%08lx)\n", index, offset); FRDP ("unknown (index: 0x%08lx, offset 0x%08lx)\n", index, offset); } } static void uc8_movemem () { int idx = rdp.cmd0 & 0xFF; DWORD addr = segoffset(rdp.cmd1); int ofs = (rdp.cmd0 >> 5) & 0x3FFF; FRDP ("uc8:movemem ofs:%d ", ofs); switch (idx) { case 8: // VIEWPORT { DWORD a = addr >> 1; short scale_x = ((short*)gfx.RDRAM)[(a+0)^1] >> 2; short scale_y = ((short*)gfx.RDRAM)[(a+1)^1] >> 2; short scale_z = ((short*)gfx.RDRAM)[(a+2)^1]; short trans_x = ((short*)gfx.RDRAM)[(a+4)^1] >> 2; short trans_y = ((short*)gfx.RDRAM)[(a+5)^1] >> 2; short trans_z = ((short*)gfx.RDRAM)[(a+6)^1]; rdp.view_scale[0] = scale_x * rdp.scale_x; rdp.view_scale[1] = -scale_y * rdp.scale_y; rdp.view_scale[2] = 32.0f * scale_z; rdp.view_trans[0] = trans_x * rdp.scale_x; rdp.view_trans[1] = trans_y * rdp.scale_y; rdp.view_trans[2] = 32.0f * trans_z; rdp.update |= UPDATE_VIEWPORT; FRDP ("viewport scale(%d, %d), trans(%d, %d), from:%08lx\n", scale_x, scale_y, trans_x, trans_y, a); } break; case 10: // LIGHT { int n = (ofs / 48); if (n < 2) { char dir_x = ((char*)gfx.RDRAM)[(addr+8)^3]; rdp.lookat[n][0] = (float)(dir_x) / 127.0f; char dir_y = ((char*)gfx.RDRAM)[(addr+9)^3]; rdp.lookat[n][1] = (float)(dir_y) / 127.0f; char dir_z = ((char*)gfx.RDRAM)[(addr+10)^3]; rdp.lookat[n][2] = (float)(dir_z) / 127.0f; rdp.use_lookat = TRUE; if (n == 1) { if (!dir_x && !dir_y) rdp.use_lookat = FALSE; } FRDP("lookat_%d (%f, %f, %f)\n", n, rdp.lookat[n][0], rdp.lookat[n][1], rdp.lookat[n][2]); return; } n -= 2; BYTE col = gfx.RDRAM[(addr+0)^3]; rdp.light[n].r = (float)col / 255.0f; rdp.light[n].nonblack = col; col = gfx.RDRAM[(addr+1)^3]; rdp.light[n].g = (float)col / 255.0f; rdp.light[n].nonblack += col; col = gfx.RDRAM[(addr+2)^3]; rdp.light[n].b = (float)col / 255.0f; rdp.light[n].nonblack += col; rdp.light[n].a = 1.0f; rdp.light[n].dir_x = (float)(((char*)gfx.RDRAM)[(addr+8)^3]) / 127.0f; rdp.light[n].dir_y = (float)(((char*)gfx.RDRAM)[(addr+9)^3]) / 127.0f; rdp.light[n].dir_z = (float)(((char*)gfx.RDRAM)[(addr+10)^3]) / 127.0f; // ** DWORD a = addr >> 1; //FIXME: Why unused? //short pos = ((short*)gfx.RDRAM)[(a+16)^1]; rdp.light[n].x = (float)(((short*)gfx.RDRAM)[(a+16)^1]); rdp.light[n].y = (float)(((short*)gfx.RDRAM)[(a+17)^1]); rdp.light[n].z = (float)(((short*)gfx.RDRAM)[(a+18)^1]); rdp.light[n].w = (float)(((short*)gfx.RDRAM)[(a+19)^1]); rdp.light[n].nonzero = gfx.RDRAM[(addr+12)^3]; rdp.light[n].ca = (float)rdp.light[n].nonzero / 16.0f; // rdp.light[n].la = rdp.light[n].ca * 1.0f; //#ifdef EXTREME_LOGGING FRDP ("light: n: %d, pos: x: %f, y: %f, z: %f, w: %f, ca: %f\n", n, rdp.light[n].x, rdp.light[n].y, rdp.light[n].z, rdp.light[n].w, rdp.light[n].ca); //#endif FRDP ("light: n: %d, r: %f, g: %f, b: %f. dir: x: %.3f, y: %.3f, z: %.3f\n", n, rdp.light[n].r, rdp.light[n].g, rdp.light[n].b, rdp.light[n].dir_x, rdp.light[n].dir_y, rdp.light[n].dir_z); #ifdef EXTREME_LOGGING for (int t=0; t < 24; t++) { FRDP ("light[%d] = 0x%04lx \n", t, ((WORD*)gfx.RDRAM)[(a+t)^1]); } #endif } break; case 14: //Normales { uc8_normale_addr = segoffset(rdp.cmd1); FRDP ("Normale - addr: %08lx\n", uc8_normale_addr); #ifdef EXTREME_LOGGING for (int i = 0; i < 32; i++) { char x = ((char*)gfx.RDRAM)[uc8_normale_addr + ((i<<1) + 0)^3]; char y = ((char*)gfx.RDRAM)[uc8_normale_addr + ((i<<1) + 1)^3]; FRDP("#%d x = %d, y = %d\n", i, x, y); } DWORD a = uc8_normale_addr >> 1; for (i = 0; i < 32; i++) { FRDP ("n[%d] = 0x%04lx \n", i, ((WORD*)gfx.RDRAM)[(a+i)^1]); } #endif } break; default: FRDP ("uc8:movemem unknown (%d)\n", idx); } } static void uc8_tri4() //by Gugaman Apr 19 2002 { if (rdp.skip_drawing) { RDP("uc8:tri4. skipped\n"); return; } FRDP("uc8:tri4 (#%d - #%d), %d-%d-%d, %d-%d-%d, %d-%d-%d, %d-%d-%d\n", rdp.tri_n, rdp.tri_n+3, ((rdp.cmd0 >> 23) & 0x1F), ((rdp.cmd0 >> 18) & 0x1F), ((((rdp.cmd0 >> 15) & 0x7) << 2) | ((rdp.cmd1 >> 30) &0x3)), ((rdp.cmd0 >> 10) & 0x1F), ((rdp.cmd0 >> 5) & 0x1F), ((rdp.cmd0 >> 0) & 0x1F), ((rdp.cmd1 >> 25) & 0x1F), ((rdp.cmd1 >> 20) & 0x1F), ((rdp.cmd1 >> 15) & 0x1F), ((rdp.cmd1 >> 10) & 0x1F), ((rdp.cmd1 >> 5) & 0x1F), ((rdp.cmd1 >> 0) & 0x1F)); VERTEX *v[12] = { &rdp.vtx[(rdp.cmd0 >> 23) & 0x1F], &rdp.vtx[(rdp.cmd0 >> 18) & 0x1F], &rdp.vtx[((((rdp.cmd0 >> 15) & 0x7) << 2) | ((rdp.cmd1 >> 30) &0x3))], &rdp.vtx[(rdp.cmd0 >> 10) & 0x1F], &rdp.vtx[(rdp.cmd0 >> 5) & 0x1F], &rdp.vtx[(rdp.cmd0 >> 0) & 0x1F], &rdp.vtx[(rdp.cmd1 >> 25) & 0x1F], &rdp.vtx[(rdp.cmd1 >> 20) & 0x1F], &rdp.vtx[(rdp.cmd1 >> 15) & 0x1F], &rdp.vtx[(rdp.cmd1 >> 10) & 0x1F], &rdp.vtx[(rdp.cmd1 >> 5) & 0x1F], &rdp.vtx[(rdp.cmd1 >> 0) & 0x1F] }; BOOL updated = 0; if (cull_tri(v)) rdp.tri_n ++; else { updated = 1; update (); DrawTri (v); rdp.tri_n ++; } if (cull_tri(v+3)) rdp.tri_n ++; else { if (!updated) { updated = 1; update (); } DrawTri (v+3); rdp.tri_n ++; } if (cull_tri(v+6)) rdp.tri_n ++; else { if (!updated) { updated = 1; update (); } DrawTri (v+6); rdp.tri_n ++; } if (cull_tri(v+9)) rdp.tri_n ++; else { if (!updated) { updated = 1; update (); } DrawTri (v+9); rdp.tri_n ++; } } mupen64plus-video-glide64-src-2.6.0/src/video_api_export.ver000066400000000000000000000004661464507525600237370ustar00rootroot00000000000000{ global: PluginStartup; PluginShutdown; PluginGetVersion; ChangeWindow; InitiateGFX; MoveScreen; ProcessDList; ProcessRDPList; RomClosed; RomOpen; ShowCFB; UpdateScreen; ViStatusChanged; ViWidthChanged; ReadScreen2; SetRenderingCallback; ResizeVideoOutput; FBRead; FBWrite; FBGetFrameBufferInfo; local: *; }; mupen64plus-video-glide64-src-2.6.0/src/winlnxdefs.h000066400000000000000000000031371464507525600222110ustar00rootroot00000000000000/** * Glide64 Video Plugin - winlnxdefs.h * Copyright (C) 2002 Dave2001 * * Mupen64Plus homepage: https://mupen64plus.org/ * * This program is free software; you can redistribute it and/ * or modify it under the terms of the GNU General Public Li- * cence as published by the Free Software Foundation; either * version 2 of the License, or any later version. * * This program is distributed in the hope that it will be use- * ful, but WITHOUT ANY WARRANTY; without even the implied war- * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public Licence for more details. * * You should have received a copy of the GNU General Public * Licence along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA * **/ #ifndef WINLNXDEFS_H #define WINLNXDEFS_H #ifndef WIN32 typedef int BOOL; typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned int DWORD; typedef int INT; typedef long long LONGLONG; typedef int __int32; typedef void* HINSTANCE; typedef int PROPSHEETHEADER; typedef int PROPSHEETPAGE; typedef int HWND; #define FALSE false #define TRUE true #define __stdcall #define __declspec(dllexport) #define _cdecl #define WINAPI typedef union _LARGE_INTEGER { struct { DWORD LowPart; INT HighPart; } s; struct { DWORD LowPart; INT HighPart; } u; LONGLONG QuadPart; } LARGE_INTEGER, *PLARGE_INTEGER; #define HIWORD(a) ((unsigned int)(a) >> 16) #define LOWORD(a) ((a) & 0xFFFF) #endif #endif // WINLNXDEFS_H mupen64plus-video-glide64-src-2.6.0/src/wrapper/000077500000000000000000000000001464507525600213335ustar00rootroot00000000000000mupen64plus-video-glide64-src-2.6.0/src/wrapper/2xsai.cpp000066400000000000000000000170421464507525600230710ustar00rootroot00000000000000/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus - glide64/wrapper/2xsai.cpp * * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2005-2006 Hacktarux * * * * 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 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "../Gfx1.3.h" static __inline int GetResult( DWORD A, DWORD B, DWORD C, DWORD D ) { int x = 0; int y = 0; int r = 0; if (A == C) x += 1; else if (B == C) y += 1; if (A == D) x += 1; else if (B == D) y += 1; if (x <= 1) r += 1; if (y <= 1) r -= 1; return r; } static __inline DWORD INTERPOLATE( DWORD A, DWORD B) { if (A != B) return ((A & 0xFEFEFEFE) >> 1) + (((B & 0xFEFEFEFE) >> 1) | (A & B & 0x01010101)); else return A; } static __inline DWORD Q_INTERPOLATE( DWORD A, DWORD B, DWORD C, DWORD D) { DWORD x = ((A & 0xFCFCFCFC) >> 2) + ((B & 0xFCFCFCFC) >> 2) + ((C & 0xFCFCFCFC) >> 2) + ((D & 0xFCFCFCFC) >> 2); DWORD y = (((A & 0x03030303) + (B & 0x03030303) + (C & 0x03030303) + (D & 0x03030303)) >> 2) & 0x03030303; return x | y; } void Super2xSaI( DWORD *srcPtr, DWORD *destPtr, DWORD width, DWORD height, DWORD pitch) { DWORD destWidth = width << 1; DWORD color4, color5, color6; DWORD color1, color2, color3; DWORD colorA0, colorA1, colorA2, colorA3; DWORD colorB0, colorB1, colorB2, colorB3; DWORD colorS1, colorS2; DWORD product1a, product1b, product2a, product2b; int row0, row1, row2, row3; int col0, col1, col2, col3; WORD y, x; for (y = 0; y < height; y++) { if (y > 0) { row0 = width; row0 = -row0; } else row0 = 0; row1 = 0; if (y < height - 1) { row2 = width; if (y < height - 2) row3 = width << 1; else row3 = width; } else { row2 = 0; row3 = 0; } for (x = 0; x < width; x++) { //--------------------------------------- B0 B1 B2 B3 // 4 5 6 S2 // 1 2 3 S1 // A0 A1 A2 A3 if (x > 0) col0 = -1; else col0 = 0; col1 = 0; if (x < width - 1) { col2 = 1; if (x < width - 2) col3 = 2; else col3 = 1; } else { col2 = 0; col3 = 0; } colorB0 = *(srcPtr + col0 + row0); colorB1 = *(srcPtr + col1 + row0); colorB2 = *(srcPtr + col2 + row0); colorB3 = *(srcPtr + col3 + row0); color4 = *(srcPtr + col0 + row1); color5 = *(srcPtr + col1 + row1); color6 = *(srcPtr + col2 + row1); colorS2 = *(srcPtr + col3 + row1); color1 = *(srcPtr + col0 + row2); color2 = *(srcPtr + col1 + row2); color3 = *(srcPtr + col2 + row2); colorS1 = *(srcPtr + col3 + row2); colorA0 = *(srcPtr + col0 + row3); colorA1 = *(srcPtr + col1 + row3); colorA2 = *(srcPtr + col2 + row3); colorA3 = *(srcPtr + col3 + row3); //-------------------------------------- if (color2 == color6 && color5 != color3) product2b = product1b = color2; else if (color5 == color3 && color2 != color6) product2b = product1b = color5; else if (color5 == color3 && color2 == color6) { int r = 0; r += GetResult (color6, color5, color1, colorA1); r += GetResult (color6, color5, color4, colorB1); r += GetResult (color6, color5, colorA2, colorS1); r += GetResult (color6, color5, colorB2, colorS2); if (r > 0) product2b = product1b = color6; else if (r < 0) product2b = product1b = color5; else product2b = product1b = INTERPOLATE (color5, color6); } else { if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0) product2b = Q_INTERPOLATE (color3, color3, color3, color2); else if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3) product2b = Q_INTERPOLATE (color2, color2, color2, color3); else product2b = INTERPOLATE (color2, color3); if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0) product1b = Q_INTERPOLATE (color6, color6, color6, color5); else if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3) product1b = Q_INTERPOLATE (color6, color5, color5, color5); else product1b = INTERPOLATE (color5, color6); } if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2) product2a = INTERPOLATE (color2, color5); else if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0) product2a = INTERPOLATE(color2, color5); else product2a = color2; if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2) product1a = INTERPOLATE (color2, color5); else if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0) product1a = INTERPOLATE(color2, color5); else product1a = color5; destPtr[0] = product1a; destPtr[1] = product1b; destPtr[destWidth] = product2a; destPtr[destWidth + 1] = product2b; srcPtr++; destPtr += 2; } srcPtr += (pitch-width); destPtr += (((pitch-width)<<1)+(pitch<<1)); } } mupen64plus-video-glide64-src-2.6.0/src/wrapper/2xsai.h000066400000000000000000000032701464507525600225340ustar00rootroot00000000000000/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus - glide64/wrapper/2xsai.h * * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2005-2006 Hacktarux * * * * 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 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #define uint32 unsigned long #define uint16 unsigned short #define uint8 unsigned char void Super2xSaI( DWORD *srcPtr, DWORD *destPtr, DWORD width, DWORD height, DWORD pitch); mupen64plus-video-glide64-src-2.6.0/src/wrapper/3dfx.h000066400000000000000000000067211464507525600223560ustar00rootroot00000000000000/* ** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY ** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT ** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX ** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE ** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com). ** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER ** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A ** FULL TEXT OF THE NON-WARRANTY PROVISIONS. ** ** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO ** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN ** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, ** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR ** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF ** THE UNITED STATES. ** ** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED ** ** $Revision: 1.3.4.2 $ ** $Date: 2003/05/05 06:50:41 $ */ #ifndef __3DFX_H__ #define __3DFX_H__ #include "glidesys.h" /* ** basic data types */ typedef unsigned char FxU8; typedef signed char FxI8; typedef unsigned short FxU16; typedef signed short FxI16; #if defined(__alpha__) || defined (__LP64__) typedef signed int FxI32; typedef unsigned int FxU32; #else typedef signed long FxI32; typedef unsigned long FxU32; #endif typedef unsigned long AnyPtr; typedef int FxBool; typedef float FxFloat; typedef double FxDouble; /* ** color types */ typedef unsigned long FxColor_t; typedef struct { float r, g, b, a; } FxColor4; /* ** fundamental types */ #define FXTRUE 1 #define FXFALSE 0 /* ** helper macros */ #define FXUNUSED( a ) ((void)(a)) #define FXBIT( i ) ( 1L << (i) ) /* ** export macros */ #if defined(__MSC__) || defined(_MSC_VER) # if defined (MSVC16) # define FX_ENTRY # define FX_CALL # else # define FX_ENTRY extern # define FX_CALL __stdcall # endif #elif defined(__WATCOMC__) # define FX_ENTRY extern # define FX_CALL __stdcall #elif defined (__IBMC__) || defined (__IBMCPP__) /* IBM Visual Age C/C++: */ # define FX_ENTRY extern # define FX_CALL __stdcall #elif defined(__DJGPP__) # define FX_ENTRY extern # define FX_CALL #elif defined(__MINGW32__) # define FX_ENTRY extern # define FX_CALL __stdcall #elif defined(__unix__) # define FX_ENTRY extern # define FX_CALL #elif defined(__MWERKS__) # if macintosh # define FX_ENTRY extern # define FX_CALL # else /* !macintosh */ # error "Unknown MetroWerks target platform" # endif /* !macintosh */ #elif defined(__APPLE__) # define FX_ENTRY extern # define FX_CALL #else # warning define FX_ENTRY & FX_CALL for your compiler # define FX_ENTRY extern # define FX_CALL #endif /* ** x86 compiler specific stuff */ #if defined(__BORLANDC_) # define REALMODE # define REGW( a, b ) ((a).x.b) # define REGB( a, b ) ((a).h.b) # define INT86( a, b, c ) int86(a,b,c) # define INT86X( a, b, c, d ) int86x(a,b,c,d) # define RM_SEG( a ) FP_SEG( a ) # define RM_OFF( a ) FP_OFF( a ) #elif defined(__WATCOMC__) # undef FP_SEG # undef FP_OFF # define REGW( a, b ) ((a).w.b) # define REGB( a, b ) ((a).h.b) # define INT86( a, b, c ) int386(a,b,c) # define INT86X( a, b, c, d ) int386x(a,b,c,d) # define RM_SEG( a ) ( ( ( ( FxU32 ) (a) ) & 0x000F0000 ) >> 4 ) # define RM_OFF( a ) ( ( FxU16 ) (a) ) #endif #endif /* !__3DFX_H__ */ mupen64plus-video-glide64-src-2.6.0/src/wrapper/COPYING000066400000000000000000000276411464507525600224000ustar00rootroot000000000000003DFX GLIDE Source Code General Public License 1. PREAMBLE This license is for software that provides a 3D graphics application program interface (API).The license is intended to offer terms similar to some standard General Public Licenses designed to foster open standards and unrestricted accessibility to source code. Some of these licenses require that, as a condition of the license of the software, any derivative works (that is, new software which is a work containing the original program or a portion of it) must be available for general use, without restriction other than for a minor transfer fee, and that the source code for such derivative works must likewise be made available. The only restriction is that such derivative works must be subject to the same General Public License terms as the original work. This 3dfx GLIDE Source Code General Public License differs from the standard licenses of this type in that it does not require the entire derivative work to be made available under the terms of this license nor is the recipient required to make available the source code for the entire derivative work. Rather, the license is limited to only the identifiable portion of the derivative work that is derived from the licensed software. The precise terms and conditions for copying, distribution and modification follow. 2. DEFINITIONS 2.1 This License applies to any program (or other "work") which contains a notice placed by the copyright holder saying it may be distributed under the terms of this 3dfx GLIDE Source Code General Public License. 2.2 The term "Program" as used in this Agreement refers to 3DFX's GLIDE source code and object code and any Derivative Work. 2.3 "Derivative Work" means, for the purpose of the License, that portion of any work that contains the Program or the identifiable portion of a work that is derived from the Program, either verbatim or with modifications and/or translated into another language, and that performs 3D graphics API operations. It does not include any other portions of a work. 2.4 "Modifications of the Program" means any work, which includes a Derivative Work, and includes the whole of such work. 2.5 "License" means this 3dfx GLIDE Source Code General Public License. 2.6 The "Source Code" for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, any associated interface definition files, and the scripts used to control compilation and installation of the executable work. 2.7 "3dfx" means 3dfx Interactive, Inc. 3. LICENSED ACTIVITIES 3.1 COPYING - You may copy and distribute verbatim copies of the Program's Source Code as you receive it, in any medium, subject to the provision of section 3.3 and provided also that: (a) you conspicuously and appropriately publish on each copy an appropriate copyright notice (3dfx Interactive, Inc. 1999), a notice that recipients who wish to copy, distribute or modify the Program can only do so subject to this License, and a disclaimer of warranty as set forth in section 5; (b) keep intact all the notices that refer to this License and to the absence of any warranty; and (c) do not make any use of the GLIDE trademark without the prior written permission of 3dfx, and (d) give all recipients of the Program a copy of this License along with the Program or instructions on how to easily receive a copy of this License. 3.2 MODIFICATION OF THE PROGRAM/DERIVATIVE WORKS - You may modify your copy or copies of the Program or any portion of it, and copy and distribute such modifications subject to the provisions of section 3.3 and provided that you also meet all of the following conditions: (a) you conspicuously and appropriately publish on each copy of a Derivative Work an appropriate copyright notice, a notice that recipients who wish to copy, distribute or modify the Derivative Work can only do so subject to this License, and a disclaimer of warranty as set forth in section 5; (b) keep intact all the notices that refer to this License and to the absence of any warranty; and (c) give all recipients of the Derivative Work a copy of this License along with the Derivative Work or instructions on how to easily receive a copy of this License. (d) You must cause the modified files of the Derivative Work to carry prominent notices stating that you changed the files and the date of any change. (e) You must cause any Derivative Work that you distribute or publish to be licensed at no charge to all third parties under the terms of this License. (f) You do not make any use of the GLIDE trademark without the prior written permission of 3dfx. (g) If the Derivative Work normally reads commands interactively when run, you must cause it, when started running for such interactive use, to print or display an announcement as follows: "COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED THIS SOFTWARE IS FREE AND PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED. THERE IS NO RIGHT TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX INTERACTIVE, INC. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A FULL TEXT OF THE DISTRIBUTION AND NON-WARRANTY PROVISIONS (REQUEST COPY FROM INFO@3DFX.COM)." (h) The requirements of this section 3.2 do not apply to the modified work as a whole but only to the Derivative Work. It is not the intent of this License to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of Derivative Works. 3.3 DISTRIBUTION (a) All copies of the Program or Derivative Works which are distributed must include in the file headers the following language verbatim: "THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC (info@3dfx.com). THIS PROGRAM. IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A FULL TEXT OF THE NON-WARRANTY PROVISIONS. USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF THE UNITED STATES. COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED" (b) You may distribute the Program or a Derivative Work in object code or executable form under the terms of Sections 3.1 and 3.2 provided that you also do one of the following: (1) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 3.1 and 3.2; or, (2) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 3.1 and 3.2 on a medium customarily used for software interchange; or, (3) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection 3.3(b)(2) above.) (c) The source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable code. (d) If distribution of executable code or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. (e) Each time you redistribute the Program or any Derivative Work, the recipient automatically receives a license from 3dfx and successor licensors to copy, distribute or modify the Program and Derivative Works subject to the terms and conditions of the License. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. (f) You may not make any use of the GLIDE trademark without the prior written permission of 3dfx. (g) You may not copy, modify, sublicense, or distribute the Program or any Derivative Works except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program or any Derivative Works is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 4. MISCELLANEOUS 4.1 Acceptance of this License is voluntary. By using, modifying or distributing the Program or any Derivative Work, you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. Nothing else grants you permission to modify or distribute the Program or Derivative Works and doing so without acceptance of this License is in violation of the U.S. and international copyright laws. 4.2 If the distribution and/or use of the Program or Derivative Works is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 4.3 This License is to be construed according to the laws of the State of California and you consent to personal jurisdiction in the State of California in the event it is necessary to enforce the provisions of this License. 5. NO WARRANTIES 5.1 TO THE EXTENT PERMITTED BY APPLICABLE LAW, THERE IS NO WARRANTY FOR THE PROGRAM. OR DERIVATIVE WORKS THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM AND ANY DERIVATIVE WORKS"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 AND ANY DERIVATIVE WORK IS WITH YOU. SHOULD THE PROGRAM OR ANY DERIVATIVE WORK PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 5.2 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL 3DFX INTERACTIVE, INC., OR ANY OTHER COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM OR DERIVATIVE WORKS 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 OR DERIVATIVE WORKS (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 OR DERIVATIVE WORKS TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. mupen64plus-video-glide64-src-2.6.0/src/wrapper/combiner.cpp000066400000000000000000004527601464507525600236530ustar00rootroot00000000000000/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus - glide64/wrapper/combiner.cpp * * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2005-2006 Hacktarux * * * * 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 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #ifndef _WIN32 #include #endif #include "glide.h" #include "main.h" #include "m64p.h" static int fct[4], source0[4], operand0[4], source1[4], operand1[4], source2[4], operand2[4]; static int fcta[4],sourcea0[4],operanda0[4],sourcea1[4],operanda1[4],sourcea2[4],operanda2[4]; static int alpha_ref, alpha_func; float texture_env_color[4]; float ccolor0[4]; float ccolor1[4]; static float chroma_color[4]; int fog_enabled; static int chroma_enabled; static int chroma_other_color; static int chroma_other_alpha; static int dither_enabled; int blackandwhite0; int blackandwhite1; int need_lambda[2]; float lambda_color[2][4]; // shaders variables int need_to_compile; static GLhandleARB fragment_shader_object; static GLhandleARB fragment_depth_shader_object; //static GLhandleARB fragment_bw_shader_object; static GLhandleARB vertex_shader_object; static GLhandleARB program_object_default; static GLhandleARB program_object_depth; //static GLhandleARB program_object_bw; static GLhandleARB program_object; static int constant_color_location; static int ccolor0_location; static int ccolor1_location; static int first_color = 1; static int first_alpha = 1; static int first_texture0 = 1; static int first_texture1 = 1; static int tex0_combiner_ext = 0; static int tex1_combiner_ext = 0; static int c_combiner_ext = 0; static int a_combiner_ext = 0; static const char* fragment_shader_header = "uniform sampler2D texture0; \n" "uniform sampler2D texture1; \n" "uniform sampler2D ditherTex; \n" "uniform vec4 constant_color; \n" "uniform vec4 ccolor0; \n" "uniform vec4 ccolor1; \n" "uniform vec4 chroma_color; \n" "uniform float lambda; \n" "varying vec4 fogValue; \n" " \n" "void test_chroma(vec4 ctexture1); \n" " \n" " \n" "void main() \n" "{ \n" ; // normal version compliant with glsl specs /*static const char* fragment_shader_dither = " if(texture2D(ditherTex, vec2(mod(gl_FragCoord.x,32)/32, \n" " mod(gl_FragCoord.y,32)/32)).a > 0.5) discard; \n" ;*/ // version without mod function (not supported by ATI drivers) /*static const char* fragment_shader_dither = " if(texture2D(ditherTex, vec2((gl_FragCoord.x-32.0*floor(gl_FragCoord.x/32.0))/32.0, \n" " (gl_FragCoord.y-32.0*floor(gl_FragCoord.y/32.0))/32.0)).a > 0.5) discard; \n" ;*/ // using gl_FragCoord is terribly slow on ATI and varying variables don't work for some unknown // reason, so we use the unused components of the texture2 coordinates static const char* fragment_shader_dither = " float dithx = (gl_TexCoord[2].b + 1.0)*0.5*1000.0; \n" " float dithy = (gl_TexCoord[2].a + 1.0)*0.5*1000.0; \n" " if(texture2D(ditherTex, vec2((dithx-32.0*floor(dithx/32.0))/32.0, \n" " (dithy-32.0*floor(dithy/32.0))/32.0)).a > 0.5) discard; \n" ; static const char* fragment_shader_default = " gl_FragColor = texture2D(texture0, vec2(gl_TexCoord[0])); \n" ; /* static const char* fragment_shader_depth = //" gl_FragDepth = dot(texture2D(texture0, vec2(gl_TexCoord[0])), vec4(0.3, 0.3, 0.3, 0)); \n" " gl_FragDepth = dot(texture2D(texture0, vec2(gl_TexCoord[0])), vec4(32*64*32/65536.0, 64*32/65536.0, 32/65536.0, 0))*0.5 + 0.5; \n" //" gl_FragDepth = (float(texture2D(texture0, vec2(gl_TexCoord[0]))[0])*31*64*32/65536.0 + float(texture2D(texture0, vec2(gl_TexCoord[0]))[1])*63*32/65536.0 + float(texture2D(texture0, vec2(gl_TexCoord[0]))[2])*31/65536.0)*0.5 + 0.5; \n" //" gl_FragDepth = texture2D(texture0, vec2(gl_TexCoord[0]))[0]*0.5+0.5; \n" ; static const char* fragment_shader_bw = " vec4 readtex0 = texture2D(texture0, vec2(gl_TexCoord[0])); \n" // " gl_FragColor = vec4(0.5,1,0,0.5); \n" // " gl_FragColor.a = 0.5; \n" " gl_FragColor = vec4(vec3(readtex0.b), \n" " readtex0.r + readtex0.g * 8.0 / 256.0); \n" ; */ static const char* fragment_shader_readtex0color = " vec4 readtex0 = texture2D(texture0, vec2(gl_TexCoord[0])); \n" ; static const char* fragment_shader_readtex0bw = " vec4 readtex0 = texture2D(texture0, vec2(gl_TexCoord[0])); \n" " readtex0 = vec4(vec3(readtex0.b), \n" " readtex0.r + readtex0.g * 8.0 / 256.0); \n" // " vec4 readtex0 = texture2D(texture0, vec2(gl_TexCoord[0])); \n" // " readtex0 = vec4(vec3(readtex0.b), \n" // " readtex0.r); \n" ; static const char* fragment_shader_readtex0bw_2 = // " float I = dot(texture2D(texture0, vec2(gl_TexCoord[0])), vec4(31*64*32, 63*32, 31, 0)) / 256.0; \n" // " float A = (I - floor(I))*256/255.0; \n" // " vec4 readtex0 = vec4(vec3(A), \n" // " I/255.0); \n" " vec4 readtex0 = vec4(dot(texture2D(texture0, vec2(gl_TexCoord[0])), vec4(1.0/3, 1.0/3, 1.0/3, 0))); \n" // " vec4 readtex0 = texture2D(texture0, vec2(gl_TexCoord[0])); \n" // " readtex0 = vec4(vec3(readtex0.b), \n" // " readtex0.r + readtex0.g * 8.0 / 256.0); \n" // " readtex0 = vec4(vec3(readtex0.r / 3.0 + readtex0.g / 3.0 + \n" // " readtex0.b / 3.0), readtex0.a); \n" ; static const char* fragment_shader_readtex1color = " vec4 readtex1 = texture2D(texture1, vec2(gl_TexCoord[1])); \n" ; static const char* fragment_shader_readtex1bw = " vec4 readtex1 = texture2D(texture1, vec2(gl_TexCoord[1])); \n" " readtex1 = vec4(vec3(readtex1.b), \n" " readtex1.r + readtex1.g * 8.0 / 256.0); \n" // " vec4 readtex1 = texture2D(texture1, vec2(gl_TexCoord[1])); \n" // " readtex1 = vec4(vec3(readtex1.b), \n" // " readtex1.r); \n" ; static const char* fragment_shader_readtex1bw_2 = // " float I = dot(texture2D(texture1, vec2(gl_TexCoord[1])), vec4(31*64*32, 63*32, 31, 0)) / 256.0; \n" // " float A = (I - floor(I))*256/255.0; \n" // " vec4 readtex1 = vec4(vec3(A), \n" // " I/255.0); \n" " vec4 readtex1 = vec4(dot(texture2D(texture1, vec2(gl_TexCoord[1])), vec4(1.0/3, 1.0/3, 1.0/3, 0))); \n" // " vec4 readtex1 = texture2D(texture1, vec2(gl_TexCoord[1])); \n" // " readtex1 = vec4(vec3(readtex1.b), \n" // " readtex1.r + readtex1.g * 8.0 / 256.0); \n" // " readtex1 = vec4(vec3(readtex1.r / 3.0 + readtex1.g / 3.0 + \n" // " readtex1.b / 3.0), readtex1.a); \n" ; static const char* fragment_shader_fog = " float fog; \n" " fog = gl_TexCoord[0].b; \n" " gl_FragColor = vec4(mix(gl_Fog.color.rgb, gl_FragColor.rgb, fog), gl_FragColor.a); \n" ; /*static const char* fragment_shader_fog = " float fog; \n" " fog = (gl_Fog.end - gl_FogFragCoord) * gl_Fog.scale; \n" " fog = clamp(fog, 0.0, 1.0); \n" " gl_FragColor = vec4(mix(vec3(gl_Fog.color), gl_FragColor.rgb, fog), gl_FragColor.a); \n" ;*/ /*static const char* fragment_shader_fog = " float fog; \n" " fog = (far - gl_FogFragCoord) / (far - near); \n" " fog = clamp(fog, 0.0, 1.0); \n" " gl_FragColor = vec4(mix(vec3(gl_Fog.color), gl_FragColor.rgb*256.0, fog), gl_FragColor.a); \n" ;*/ /*static const char* fragment_shader_fog = " gl_FragColor = vec4(mix(vec3(gl_Fog.color), gl_FragColor.rgb, fogValue), gl_FragColor.a); \n" ;*/ static const char* fragment_shader_end = "} \n" ; static const char* vertex_shader = "varying vec4 fogValue; \n" " \n" "void main() \n" "{ \n" " gl_Position = ftransform(); \n" " gl_FrontColor = gl_Color; \n" " gl_TexCoord[0] = gl_MultiTexCoord0; \n" " gl_TexCoord[1] = gl_MultiTexCoord1; \n" " float f = (gl_Fog.end - gl_SecondaryColor.r) * gl_Fog.scale; \n" // fog value passed through secondary color (workaround ATI bug) " f = clamp(f, 0.0, 1.0); \n" " gl_TexCoord[0].b = f; \n" // various data passed through " gl_TexCoord[2].b = gl_Vertex.x; \n" // texture coordinates " gl_TexCoord[2].a = gl_Vertex.y; \n" // again it is the only way "} \n" // i've found to get it working fast with ATI drivers ; static char fragment_shader_color_combiner[1024]; static char fragment_shader_alpha_combiner[1024]; static char fragment_shader_texture1[1024]; static char fragment_shader_texture0[1024]; static char fragment_shader_chroma[1024]; static char shader_log[2048]; void updateCombiner(int i) { glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, fct[i]); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, source0[i]); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, operand0[i]); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, source1[i]); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, operand1[i]); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, source2[i]); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, operand2[i]); } void updateCombinera(int i) { glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, fcta[i]); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, sourcea0[i]); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, operanda0[i]); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, sourcea1[i]); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, operanda1[i]); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, sourcea2[i]); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, operanda2[i]); } void init_combiner() { int texture[4] = {0, 0, 0, 0}; glActiveTextureARB(GL_TEXTURE0_ARB); glEnable(GL_TEXTURE_2D); // creating a fake texture glBindTexture(GL_TEXTURE_2D, default_texture); glTexImage2D(GL_TEXTURE_2D, 0, 3, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glActiveTextureARB(GL_TEXTURE1_ARB); glBindTexture(GL_TEXTURE_2D, default_texture); glEnable(GL_TEXTURE_2D); if(!glsl_support) { if (nbTextureUnits > 2) { glActiveTextureARB(GL_TEXTURE2_ARB); glBindTexture(GL_TEXTURE_2D, default_texture); glEnable(GL_TEXTURE_2D); } if (nbTextureUnits > 3) { glActiveTextureARB(GL_TEXTURE3_ARB); glBindTexture(GL_TEXTURE_2D, default_texture); glEnable(GL_TEXTURE_2D); } alpha_ref = 0; need_lambda[0] = need_lambda[1] = 0; } else { int texture0_location; int texture1_location; char *fragment_shader; GLint log_length; /*glActiveTextureARB(GL_TEXTURE2_ARB); glBindTexture(GL_TEXTURE_2D, default_texture); glEnable(GL_TEXTURE_2D); glActiveTextureARB(GL_TEXTURE0_ARB);*/ // depth shader fragment_depth_shader_object = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); char s[128]; // ZIGGY convert a 565 texture into depth component sprintf(s, "gl_FragDepth = dot(texture2D(texture0, vec2(gl_TexCoord[0])), vec4(31*64*32, 63*32, 31, 0))*%g + %g; \n", zscale/2/65535.0, 1-zscale/2); //sprintf(s, "gl_FragDepth = texture2D(texture0, vec2(gl_TexCoord[0]))[0]*%g + %g; \n", zscale/2, 1-zscale/2); fragment_shader = (char*)malloc(strlen(fragment_shader_header)+ strlen(s)+ strlen(fragment_shader_end)+1); strcpy(fragment_shader, fragment_shader_header); strcat(fragment_shader, s); strcat(fragment_shader, fragment_shader_end); glShaderSourceARB(fragment_depth_shader_object, 1, (const GLcharARB**)&fragment_shader, NULL); free(fragment_shader); glCompileShaderARB(fragment_depth_shader_object); // bw shader // fragment_bw_shader_object = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); // fragment_shader = (char*)malloc(strlen(fragment_shader_header)+ // strlen(fragment_shader_bw)+ // strlen(fragment_shader_end)+1); // strcpy(fragment_shader, fragment_shader_header); // strcat(fragment_shader, fragment_shader_bw); // strcat(fragment_shader, fragment_shader_end); // glShaderSourceARB(fragment_bw_shader_object, 1, (const GLcharARB**)&fragment_shader, NULL); // free(fragment_shader); // glCompileShaderARB(fragment_bw_shader_object); // default shader fragment_shader_object = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); fragment_shader = (char*)malloc(strlen(fragment_shader_header)+ strlen(fragment_shader_default)+ strlen(fragment_shader_end)+1); strcpy(fragment_shader, fragment_shader_header); strcat(fragment_shader, fragment_shader_default); strcat(fragment_shader, fragment_shader_end); glShaderSourceARB(fragment_shader_object, 1, (const GLcharARB**)&fragment_shader, NULL); free(fragment_shader); glCompileShaderARB(fragment_shader_object); vertex_shader_object = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); glShaderSourceARB(vertex_shader_object, 1, &vertex_shader, NULL); glCompileShaderARB(vertex_shader_object); // depth program program_object = glCreateProgramObjectARB(); program_object_depth = program_object; glAttachObjectARB(program_object, fragment_depth_shader_object); glAttachObjectARB(program_object, vertex_shader_object); glLinkProgramARB(program_object); glUseProgramObjectARB(program_object); glGetObjectParameterivARB(program_object, GL_OBJECT_LINK_STATUS_ARB , &log_length); if(!log_length) { glGetInfoLogARB(fragment_shader_object, 2048, &log_length, shader_log); if(log_length) display_warning("%s", shader_log); glGetInfoLogARB(vertex_shader_object, 2048, &log_length, shader_log); if(log_length) display_warning("%s", shader_log); glGetInfoLogARB(program_object, 2048, &log_length, shader_log); if(log_length) display_warning("%s", shader_log); } texture0_location = glGetUniformLocationARB(program_object, "texture0"); texture1_location = glGetUniformLocationARB(program_object, "texture1"); glUniform1iARB(texture0_location, 0); glUniform1iARB(texture1_location, 1); // bw program // program_object = glCreateProgramObjectARB(); // program_object_bw = program_object; // glAttachObjectARB(program_object, fragment_bw_shader_object); // glAttachObjectARB(program_object, vertex_shader_object); // glLinkProgramARB(program_object); // glUseProgramObjectARB(program_object); // glGetObjectParameterivARB(program_object, GL_OBJECT_LINK_STATUS_ARB , &log_length); // if(!log_length) // { // glGetInfoLogARB(fragment_shader_object, 2048, &log_length, shader_log); // if(log_length) display_warning(shader_log); // glGetInfoLogARB(vertex_shader_object, 2048, &log_length, shader_log); // if(log_length) display_warning(shader_log); // glGetInfoLogARB(program_object, 2048, &log_length, shader_log); // if(log_length) display_warning(shader_log); // } // texture0_location = glGetUniformLocationARB(program_object, "texture0"); // texture1_location = glGetUniformLocationARB(program_object, "texture1"); // glUniform1iARB(texture0_location, 0); // glUniform1iARB(texture1_location, 1); // default program program_object = glCreateProgramObjectARB(); program_object_default = program_object; glAttachObjectARB(program_object, fragment_shader_object); glAttachObjectARB(program_object, vertex_shader_object); glLinkProgramARB(program_object); glUseProgramObjectARB(program_object); glGetObjectParameterivARB(program_object, GL_OBJECT_LINK_STATUS_ARB , &log_length); if(!log_length) { glGetInfoLogARB(fragment_shader_object, 2048, &log_length, shader_log); if(log_length) display_warning("%s", shader_log); glGetInfoLogARB(vertex_shader_object, 2048, &log_length, shader_log); if(log_length) display_warning("%s", shader_log); glGetInfoLogARB(program_object, 2048, &log_length, shader_log); if(log_length) display_warning("%s", shader_log); } texture0_location = glGetUniformLocationARB(program_object, "texture0"); texture1_location = glGetUniformLocationARB(program_object, "texture1"); glUniform1iARB(texture0_location, 0); glUniform1iARB(texture1_location, 1); strcpy(fragment_shader_color_combiner, ""); strcpy(fragment_shader_alpha_combiner, ""); strcpy(fragment_shader_texture1, "vec4 ctexture1 = texture2D(texture0, vec2(gl_TexCoord[0])); \n"); strcpy(fragment_shader_texture0, ""); first_color = 1; first_alpha = 1; first_texture0 = 1; first_texture1 = 1; need_to_compile = 0; } fog_enabled = 0; chroma_enabled = 0; dither_enabled = 0; blackandwhite0 = 0; blackandwhite1 = 0; } void compile_chroma_shader() { strcpy(fragment_shader_chroma, "\nvoid test_chroma(vec4 ctexture1)\n{\n"); switch(chroma_other_alpha) { case GR_COMBINE_OTHER_ITERATED: strcat(fragment_shader_chroma, "float alpha = gl_Color.a; \n"); break; case GR_COMBINE_OTHER_TEXTURE: strcat(fragment_shader_chroma, "float alpha = ctexture1.a; \n"); break; case GR_COMBINE_OTHER_CONSTANT: strcat(fragment_shader_chroma, "float alpha = constant_color.a; \n"); break; default: display_warning("unknown compile_choma_shader_alpha : %x", chroma_other_alpha); } switch(chroma_other_color) { case GR_COMBINE_OTHER_ITERATED: strcat(fragment_shader_chroma, "vec4 color = vec4(vec3(gl_Color),alpha); \n"); break; case GR_COMBINE_OTHER_TEXTURE: strcat(fragment_shader_chroma, "vec4 color = vec4(vec3(ctexture1),alpha); \n"); break; case GR_COMBINE_OTHER_CONSTANT: strcat(fragment_shader_chroma, "vec4 color = vec4(vec3(constant_color),alpha); \n"); break; default: display_warning("unknown compile_choma_shader_alpha : %x", chroma_other_color); } strcat(fragment_shader_chroma, "if (color.rgb == chroma_color.rgb) discard; \n"); strcat(fragment_shader_chroma, "}"); } typedef struct _shader_program_key { int color_combiner; int alpha_combiner; int texture0_combiner; int texture1_combiner; int texture0_combinera; int texture1_combinera; int fog_enabled; int chroma_enabled; int dither_enabled; int blackandwhite0; int blackandwhite1; GLhandleARB fragment_shader_object; GLhandleARB program_object; } shader_program_key; static shader_program_key* shader_programs = NULL; static int number_of_programs = 0; static int color_combiner_key; static int alpha_combiner_key; static int texture0_combiner_key; static int texture1_combiner_key; static int texture0_combinera_key; static int texture1_combinera_key; void compile_shader() { int texture0_location; int texture1_location; int ditherTex_location; char *fragment_shader; int i; int chroma_color_location; GLint log_length; need_to_compile = 0; for(i=0; i> 24) & 0xFF) / 255.0f; texture_env_color[0] = ((value >> 16) & 0xFF) / 255.0f; texture_env_color[1] = ((value >> 8) & 0xFF) / 255.0f; texture_env_color[2] = (value & 0xFF) / 255.0f; break; case GR_COLORFORMAT_RGBA: texture_env_color[0] = ((value >> 24) & 0xFF) / 255.0f; texture_env_color[1] = ((value >> 16) & 0xFF) / 255.0f; texture_env_color[2] = ((value >> 8) & 0xFF) / 255.0f; texture_env_color[3] = (value & 0xFF) / 255.0f; break; default: display_warning("grConstantColorValue: unknown color format : %x", lfb_color_fmt); } if(!glsl_support) { if (!need_lambda[0]) { glActiveTextureARB(GL_TEXTURE0_ARB); glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, texture_env_color); } if (!need_lambda[1]) { glActiveTextureARB(GL_TEXTURE1_ARB); glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, texture_env_color); } if (nbTextureUnits > 2) { glActiveTextureARB(GL_TEXTURE2_ARB); glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, texture_env_color); } if (nbTextureUnits > 3) { glActiveTextureARB(GL_TEXTURE3_ARB); glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, texture_env_color); } } else { constant_color_location = glGetUniformLocationARB(program_object, "constant_color"); glUniform4fARB(constant_color_location, texture_env_color[0], texture_env_color[1], texture_env_color[2], texture_env_color[3]); } } int setOtherColorSource(int other) { switch(other) { case GR_COMBINE_OTHER_ITERATED: return GL_PRIMARY_COLOR_ARB; break; case GR_COMBINE_OTHER_TEXTURE: return GL_PREVIOUS_ARB; break; case GR_COMBINE_OTHER_CONSTANT: return GL_CONSTANT_ARB; break; default: display_warning("unknwown other color source : %x", other); } return 0; } int setLocalColorSource(int local) { switch(local) { case GR_COMBINE_LOCAL_ITERATED: return GL_PRIMARY_COLOR_ARB; break; case GR_COMBINE_LOCAL_CONSTANT: return GL_CONSTANT_ARB; break; default: display_warning("unknwown local color source : %x", local); } return 0; } void writeGLSLColorOther(int other) { switch(other) { case GR_COMBINE_OTHER_ITERATED: strcat(fragment_shader_color_combiner, "vec4 color_other = gl_Color; \n"); break; case GR_COMBINE_OTHER_TEXTURE: strcat(fragment_shader_color_combiner, "vec4 color_other = ctexture1; \n"); break; case GR_COMBINE_OTHER_CONSTANT: strcat(fragment_shader_color_combiner, "vec4 color_other = constant_color; \n"); break; default: display_warning("unknown writeGLSLColorOther : %x", other); } } void writeGLSLColorLocal(int local) { switch(local) { case GR_COMBINE_LOCAL_ITERATED: strcat(fragment_shader_color_combiner, "vec4 color_local = gl_Color; \n"); break; case GR_COMBINE_LOCAL_CONSTANT: strcat(fragment_shader_color_combiner, "vec4 color_local = constant_color; \n"); break; default: display_warning("unknown writeGLSLColorLocal : %x", local); } } void writeGLSLColorFactor(int factor, int local, int need_local, int other, int need_other) { switch(factor) { case GR_COMBINE_FACTOR_ZERO: strcat(fragment_shader_color_combiner, "vec4 color_factor = vec4(0.0); \n"); break; case GR_COMBINE_FACTOR_LOCAL: if(need_local) writeGLSLColorLocal(local); strcat(fragment_shader_color_combiner, "vec4 color_factor = color_local; \n"); break; case GR_COMBINE_FACTOR_OTHER_ALPHA: if(need_other) writeGLSLColorOther(other); strcat(fragment_shader_color_combiner, "vec4 color_factor = vec4(color_other.a); \n"); break; case GR_COMBINE_FACTOR_LOCAL_ALPHA: if(need_local) writeGLSLColorLocal(local); strcat(fragment_shader_color_combiner, "vec4 color_factor = vec4(color_local.a); \n"); break; case GR_COMBINE_FACTOR_TEXTURE_ALPHA: strcat(fragment_shader_color_combiner, "vec4 color_factor = vec4(ctexture1.a); \n"); break; case GR_COMBINE_FACTOR_TEXTURE_RGB: strcat(fragment_shader_color_combiner, "vec4 color_factor = ctexture1; \n"); break; case GR_COMBINE_FACTOR_ONE: strcat(fragment_shader_color_combiner, "vec4 color_factor = vec4(1.0); \n"); break; case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL: if(need_local) writeGLSLColorLocal(local); strcat(fragment_shader_color_combiner, "vec4 color_factor = vec4(1.0) - color_local; \n"); break; case GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA: if(need_other) writeGLSLColorOther(other); strcat(fragment_shader_color_combiner, "vec4 color_factor = vec4(1.0) - vec4(color_other.a); \n"); break; case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA: if(need_local) writeGLSLColorLocal(local); strcat(fragment_shader_color_combiner, "vec4 color_factor = vec4(1.0) - vec4(color_local.a); \n"); break; case GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA: strcat(fragment_shader_color_combiner, "vec4 color_factor = vec4(1.0) - vec4(ctexture1.a); \n"); break; default: display_warning("unknown writeGLSLColorFactor : %x", factor); } } FX_ENTRY void FX_CALL grColorCombine( GrCombineFunction_t function, GrCombineFactor_t factor, GrCombineLocal_t local, GrCombineOther_t other, FxBool invert ) { WriteLog(M64MSG_VERBOSE, "grColorCombine(%d,%d,%d,%d,%d)\r\n", function, factor, local, other, invert); if(glsl_support) { static int last_function = 0; static int last_factor = 0; static int last_local = 0; static int last_other = 0; if(last_function == function && last_factor == factor && last_local == local && last_other == other && first_color == 0 && !c_combiner_ext) return; first_color = 0; c_combiner_ext = 0; last_function = function; last_factor = factor; last_local = local; last_other = other; if (invert) display_warning("grColorCombine : inverted result"); color_combiner_key = function | (factor << 4) | (local << 8) | (other << 10); chroma_other_color = other; strcpy(fragment_shader_color_combiner, ""); switch(function) { case GR_COMBINE_FUNCTION_ZERO: strcat(fragment_shader_color_combiner, "gl_FragColor = vec4(0.0); \n"); break; case GR_COMBINE_FUNCTION_LOCAL: writeGLSLColorLocal(local); strcat(fragment_shader_color_combiner, "gl_FragColor = color_local; \n"); break; case GR_COMBINE_FUNCTION_LOCAL_ALPHA: writeGLSLColorLocal(local); strcat(fragment_shader_color_combiner, "gl_FragColor = vec4(color_local.a); \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER: writeGLSLColorOther(other); writeGLSLColorFactor(factor,local,1,other,0); strcat(fragment_shader_color_combiner, "gl_FragColor = color_factor * color_other; \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL: writeGLSLColorLocal(local); writeGLSLColorOther(other); writeGLSLColorFactor(factor,local,0,other,0); strcat(fragment_shader_color_combiner, "gl_FragColor = color_factor * color_other + color_local; \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA: writeGLSLColorLocal(local); writeGLSLColorOther(other); writeGLSLColorFactor(factor,local,0,other,0); strcat(fragment_shader_color_combiner, "gl_FragColor = color_factor * color_other + vec4(color_local.a); \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL: writeGLSLColorLocal(local); writeGLSLColorOther(other); writeGLSLColorFactor(factor,local,0,other,0); strcat(fragment_shader_color_combiner, "gl_FragColor = color_factor * (color_other - color_local); \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL: writeGLSLColorLocal(local); writeGLSLColorOther(other); writeGLSLColorFactor(factor,local,0,other,0); strcat(fragment_shader_color_combiner, "gl_FragColor = color_factor * (color_other - color_local) + color_local; \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA: writeGLSLColorLocal(local); writeGLSLColorOther(other); writeGLSLColorFactor(factor,local,0,other,0); strcat(fragment_shader_color_combiner, "gl_FragColor = color_factor * (color_other - color_local) + vec4(color_local.a); \n"); break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL: writeGLSLColorLocal(local); writeGLSLColorFactor(factor,local,0,other,1); strcat(fragment_shader_color_combiner, "gl_FragColor = color_factor * (-color_local) + color_local; \n"); break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA: writeGLSLColorLocal(local); writeGLSLColorFactor(factor,local,0,other,1); strcat(fragment_shader_color_combiner, "gl_FragColor = color_factor * (-color_local) + vec4(color_local.a); \n"); break; default: strcpy(fragment_shader_color_combiner, fragment_shader_default); display_warning("grColorCombine : unknown function : %x", function); } //compile_shader(); need_to_compile = 1; } else { int num_tex; if (invert) display_warning("grColorCombine : inverted result"); if (nbTextureUnits > 2) { glActiveTextureARB(GL_TEXTURE2_ARB); num_tex = 2; } else { glActiveTextureARB(GL_TEXTURE1_ARB); num_tex = 1; } fct[num_tex+1] = GL_REPLACE; source0[num_tex+1] = GL_PREVIOUS_ARB; operand0[num_tex+1] = GL_SRC_COLOR; switch(function) { case GR_COMBINE_FUNCTION_LOCAL: fct[num_tex] = GL_REPLACE; source0[num_tex] = setLocalColorSource(local); operand0[num_tex] = GL_SRC_COLOR; break; case GR_COMBINE_FUNCTION_SCALE_OTHER: switch(factor) { case GR_COMBINE_FACTOR_LOCAL: fct[num_tex] = GL_MODULATE; source0[num_tex] = setLocalColorSource(local); operand0[num_tex] = GL_SRC_COLOR; source1[num_tex] = setOtherColorSource(other); operand1[num_tex] = GL_SRC_COLOR; break; case GR_COMBINE_FACTOR_ONE: fct[num_tex] = GL_REPLACE; source0[num_tex] = setOtherColorSource(other); operand0[num_tex] = GL_SRC_COLOR; break; case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL: fct[num_tex] = GL_MODULATE; source0[num_tex] = setLocalColorSource(local); operand0[num_tex] = GL_ONE_MINUS_SRC_COLOR; source1[num_tex] = setOtherColorSource(other); operand1[num_tex] = GL_SRC_COLOR; break; case GR_COMBINE_FACTOR_OTHER_ALPHA: fct[num_tex] = GL_MODULATE; source0[num_tex] = setOtherColorSource(other); operand0[num_tex] = GL_SRC_ALPHA; source1[num_tex] = setOtherColorSource(other); operand1[num_tex] = GL_SRC_COLOR; break; case GR_COMBINE_FACTOR_TEXTURE_RGB: fct[num_tex] = GL_MODULATE; source0[num_tex] = GL_PREVIOUS_ARB; operand0[num_tex] = GL_SRC_COLOR; source1[num_tex] = setOtherColorSource(other); operand1[num_tex] = GL_SRC_COLOR; break; default: display_warning("grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER) : unknown factor : %x", factor); } break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL: switch(factor) { case GR_COMBINE_FACTOR_TEXTURE_RGB: fct[num_tex] = GL_MODULATE; source0[num_tex] = GL_PREVIOUS_ARB; operand0[num_tex] = GL_SRC_COLOR; source1[num_tex] = setOtherColorSource(other); operand1[num_tex] = GL_SRC_COLOR; fct[num_tex+1] = GL_ADD; source0[num_tex+1] = GL_PREVIOUS_ARB; operand0[num_tex+1] = GL_SRC_COLOR; source1[num_tex+1] = setLocalColorSource(local); operand1[num_tex+1] = GL_SRC_COLOR; if (source1[num_tex+1] == GL_PREVIOUS_ARB) source1[num_tex+1] = GL_TEXTURE0_ARB; break; case GR_COMBINE_FACTOR_ONE: fct[num_tex] = GL_ADD; source0[num_tex] = setOtherColorSource(other); operand0[num_tex] = GL_SRC_COLOR; source1[num_tex] = setLocalColorSource(local); operand1[num_tex] = GL_SRC_COLOR; break; case GR_COMBINE_FACTOR_LOCAL: fct[num_tex] = GL_MODULATE; source0[num_tex] = setLocalColorSource(local); operand0[num_tex] = GL_SRC_COLOR; source1[num_tex] = setOtherColorSource(other); operand1[num_tex] = GL_SRC_COLOR; fct[num_tex+1] = GL_ADD; source0[num_tex+1] = GL_PREVIOUS_ARB; operand0[num_tex+1] = GL_SRC_COLOR; source1[num_tex+1] = setLocalColorSource(local); operand1[num_tex+1] = GL_SRC_COLOR; if (source1[num_tex+1] == GL_PREVIOUS_ARB) source1[num_tex+1] = GL_TEXTURE0_ARB; break; case GR_COMBINE_FACTOR_LOCAL_ALPHA: fct[num_tex] = GL_MODULATE; source0[num_tex] = setLocalColorSource(local); operand0[num_tex] = GL_SRC_ALPHA; source1[num_tex] = setOtherColorSource(other); operand1[num_tex] = GL_SRC_COLOR; fct[num_tex+1] = GL_ADD; source0[num_tex+1] = GL_PREVIOUS_ARB; operand0[num_tex+1] = GL_SRC_COLOR; source1[num_tex+1] = setLocalColorSource(local); operand1[num_tex+1] = GL_SRC_COLOR; if (source1[num_tex+1] == GL_PREVIOUS_ARB) source1[num_tex+1] = GL_TEXTURE0_ARB; break; case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL: fct[num_tex] = GL_MODULATE; source0[num_tex] = setLocalColorSource(local); operand0[num_tex] = GL_ONE_MINUS_SRC_COLOR; source1[num_tex] = setOtherColorSource(other); operand1[num_tex] = GL_SRC_COLOR; fct[num_tex+1] = GL_ADD; source0[num_tex+1] = GL_PREVIOUS_ARB; operand0[num_tex+1] = GL_SRC_COLOR; source1[num_tex+1] = setLocalColorSource(local); operand1[num_tex+1] = GL_SRC_COLOR; if (source1[num_tex+1] == GL_PREVIOUS_ARB) source1[num_tex+1] = GL_TEXTURE0_ARB; break; case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA: fct[num_tex] = GL_MODULATE; source0[num_tex] = setLocalColorSource(local); operand0[num_tex] = GL_ONE_MINUS_SRC_ALPHA; source1[num_tex] = setOtherColorSource(other); operand1[num_tex] = GL_SRC_COLOR; fct[num_tex+1] = GL_ADD; source0[num_tex+1] = GL_PREVIOUS_ARB; operand0[num_tex+1] = GL_SRC_COLOR; source1[num_tex+1] = setLocalColorSource(local); operand1[num_tex+1] = GL_SRC_COLOR; if (source1[num_tex+1] == GL_PREVIOUS_ARB) source1[num_tex+1] = GL_TEXTURE0_ARB; break; default: display_warning("grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL) : unknown factor : %x", factor); } break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL: switch(factor) { case GR_COMBINE_FACTOR_TEXTURE_RGB: // this combiner mode isn't implemented correctly and doesn't work on a TNT fct[num_tex] = GL_SUBTRACT_ARB; source0[num_tex] = setOtherColorSource(other); operand0[num_tex] = GL_SRC_COLOR; source1[num_tex] = setLocalColorSource(local); operand1[num_tex] = GL_SRC_COLOR; fct[num_tex+1] = GL_MODULATE; source0[num_tex+1] = GL_TEXTURE0_ARB; operand0[num_tex+1] = GL_SRC_COLOR; source1[num_tex+1] = GL_PREVIOUS_ARB; operand1[num_tex+1] = GL_SRC_COLOR; break; case GR_COMBINE_FACTOR_ONE: // doesn't work on TNT fct[num_tex] = GL_SUBTRACT_ARB; source0[num_tex] = setOtherColorSource(other); operand0[num_tex] = GL_SRC_COLOR; source1[num_tex] = setLocalColorSource(local); operand1[num_tex] = GL_SRC_COLOR; break; default: display_warning("grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL) : unknown factor : %x", factor); } break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL: switch(factor) { case GR_COMBINE_FACTOR_OTHER_ALPHA: fct[num_tex] = GL_INTERPOLATE_ARB; source0[num_tex] = setOtherColorSource(other); operand0[num_tex] = GL_SRC_COLOR; source1[num_tex] = setLocalColorSource(local); operand1[num_tex] = GL_SRC_COLOR; source2[num_tex] = setOtherColorSource(other); operand2[num_tex] = GL_SRC_ALPHA; break; case GR_COMBINE_FACTOR_LOCAL_ALPHA: fct[num_tex] = GL_INTERPOLATE_ARB; source0[num_tex] = setOtherColorSource(other); operand0[num_tex] = GL_SRC_COLOR; source1[num_tex] = setLocalColorSource(local); operand1[num_tex] = GL_SRC_COLOR; source2[num_tex] = setLocalColorSource(local); operand2[num_tex] = GL_SRC_ALPHA; break; case GR_COMBINE_FACTOR_TEXTURE_ALPHA: fct[num_tex] = GL_INTERPOLATE_ARB; source0[num_tex] = setOtherColorSource(other); operand0[num_tex] = GL_SRC_COLOR; source1[num_tex] = setLocalColorSource(local); operand1[num_tex] = GL_SRC_COLOR; source2[num_tex] = GL_PREVIOUS_ARB; operand2[num_tex] = GL_SRC_ALPHA; break; case GR_COMBINE_FACTOR_TEXTURE_RGB: fct[num_tex] = GL_INTERPOLATE_ARB; source0[num_tex] = setOtherColorSource(other); operand0[num_tex] = GL_SRC_COLOR; source1[num_tex] = setLocalColorSource(local); operand1[num_tex] = GL_SRC_COLOR; source2[num_tex] = GL_PREVIOUS_ARB; operand2[num_tex] = GL_SRC_COLOR; break; default: display_warning("grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL) : unknown factor : %x", factor); } break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL: switch(factor) { case GR_COMBINE_FACTOR_TEXTURE_RGB: fct[num_tex] = GL_MODULATE; source0[num_tex] = GL_PREVIOUS_ARB; operand0[num_tex] = GL_ONE_MINUS_SRC_COLOR; source1[num_tex] = setLocalColorSource(local); operand1[num_tex] = GL_SRC_COLOR; break; default: display_warning("grColorCombine(GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL) : unknown factor : %x", factor); } break; default: display_warning("grColorCombine : unknown function : %x", function); } updateCombiner(num_tex); if (nbTextureUnits > 3) { glActiveTextureARB(GL_TEXTURE3_ARB); updateCombiner(num_tex+1); } } } int setOtherAlphaSource(int other) { switch(other) { case GR_COMBINE_OTHER_ITERATED: return GL_PRIMARY_COLOR_ARB; break; case GR_COMBINE_OTHER_TEXTURE: return GL_PREVIOUS_ARB; break; case GR_COMBINE_OTHER_CONSTANT: return GL_CONSTANT_ARB; break; default: display_warning("unknwown other alpha source : %x", other); } return 0; } int setLocalAlphaSource(int local) { switch(local) { case GR_COMBINE_LOCAL_ITERATED: return GL_PRIMARY_COLOR_ARB; break; case GR_COMBINE_LOCAL_CONSTANT: return GL_CONSTANT_ARB; break; default: display_warning("unknwown local alpha source : %x", local); } return 0; } void writeGLSLAlphaOther(int other) { switch(other) { case GR_COMBINE_OTHER_ITERATED: strcat(fragment_shader_alpha_combiner, "float alpha_other = gl_Color.a; \n"); break; case GR_COMBINE_OTHER_TEXTURE: strcat(fragment_shader_alpha_combiner, "float alpha_other = ctexture1.a; \n"); break; case GR_COMBINE_OTHER_CONSTANT: strcat(fragment_shader_alpha_combiner, "float alpha_other = constant_color.a; \n"); break; default: display_warning("unknown writeGLSLAlphaOther : %x", other); } } void writeGLSLAlphaLocal(int local) { switch(local) { case GR_COMBINE_LOCAL_ITERATED: strcat(fragment_shader_alpha_combiner, "float alpha_local = gl_Color.a; \n"); break; case GR_COMBINE_LOCAL_CONSTANT: strcat(fragment_shader_alpha_combiner, "float alpha_local = constant_color.a; \n"); break; default: display_warning("unknown writeGLSLAlphaLocal : %x", local); } } void writeGLSLAlphaFactor(int factor, int local, int need_local, int other, int need_other) { switch(factor) { case GR_COMBINE_FACTOR_ZERO: strcat(fragment_shader_alpha_combiner, "float alpha_factor = 0.0; \n"); break; case GR_COMBINE_FACTOR_LOCAL: if(need_local) writeGLSLAlphaLocal(local); strcat(fragment_shader_alpha_combiner, "float alpha_factor = alpha_local; \n"); break; case GR_COMBINE_FACTOR_OTHER_ALPHA: if(need_other) writeGLSLAlphaOther(other); strcat(fragment_shader_alpha_combiner, "float alpha_factor = alpha_other; \n"); break; case GR_COMBINE_FACTOR_LOCAL_ALPHA: if(need_local) writeGLSLAlphaLocal(local); strcat(fragment_shader_alpha_combiner, "float alpha_factor = alpha_local; \n"); break; case GR_COMBINE_FACTOR_TEXTURE_ALPHA: strcat(fragment_shader_alpha_combiner, "float alpha_factor = ctexture1.a; \n"); break; case GR_COMBINE_FACTOR_ONE: strcat(fragment_shader_alpha_combiner, "float alpha_factor = 1.0; \n"); break; case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL: if(need_local) writeGLSLAlphaLocal(local); strcat(fragment_shader_alpha_combiner, "float alpha_factor = 1.0 - alpha_local; \n"); break; case GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA: if(need_other) writeGLSLAlphaOther(other); strcat(fragment_shader_alpha_combiner, "float alpha_factor = 1.0 - alpha_other; \n"); break; case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA: if(need_local) writeGLSLAlphaLocal(local); strcat(fragment_shader_alpha_combiner, "float alpha_factor = 1.0 - alpha_local; \n"); break; case GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA: strcat(fragment_shader_alpha_combiner, "float alpha_factor = 1.0 - ctexture1.a; \n"); break; default: display_warning("unknown writeGLSLAlphaFactor : %x", factor); } } FX_ENTRY void FX_CALL grAlphaCombine( GrCombineFunction_t function, GrCombineFactor_t factor, GrCombineLocal_t local, GrCombineOther_t other, FxBool invert ) { WriteLog(M64MSG_VERBOSE, "grAlphaCombine(%d,%d,%d,%d,%d)\r\n", function, factor, local, other, invert); if(glsl_support) { static int last_function = 0; static int last_factor = 0; static int last_local = 0; static int last_other = 0; if(last_function == function && last_factor == factor && last_local == local && last_other == other && first_alpha == 0 && !a_combiner_ext) return; first_alpha = 0; a_combiner_ext = 0; last_function = function; last_factor = factor; last_local = local; last_other = other; if (invert) display_warning("grAlphaCombine : inverted result"); alpha_combiner_key = function | (factor << 4) | (local << 8) | (other << 10); chroma_other_alpha = other; strcpy(fragment_shader_alpha_combiner, ""); switch(function) { case GR_COMBINE_FUNCTION_ZERO: strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = 0.0; \n"); break; case GR_COMBINE_FUNCTION_LOCAL: writeGLSLAlphaLocal(local); strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = alpha_local; \n"); break; case GR_COMBINE_FUNCTION_LOCAL_ALPHA: writeGLSLAlphaLocal(local); strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = alpha_local; \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER: writeGLSLAlphaOther(other); writeGLSLAlphaFactor(factor,local,1,other,0); strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = alpha_factor * alpha_other; \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL: writeGLSLAlphaLocal(local); writeGLSLAlphaOther(other); writeGLSLAlphaFactor(factor,local,0,other,0); strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = alpha_factor * alpha_other + alpha_local; \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA: writeGLSLAlphaLocal(local); writeGLSLAlphaOther(other); writeGLSLAlphaFactor(factor,local,0,other,0); strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = alpha_factor * alpha_other + alpha_local; \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL: writeGLSLAlphaLocal(local); writeGLSLAlphaOther(other); writeGLSLAlphaFactor(factor,local,0,other,0); strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = alpha_factor * (alpha_other - alpha_local); \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL: writeGLSLAlphaLocal(local); writeGLSLAlphaOther(other); writeGLSLAlphaFactor(factor,local,0,other,0); strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = alpha_factor * (alpha_other - alpha_local) + alpha_local; \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA: writeGLSLAlphaLocal(local); writeGLSLAlphaOther(other); writeGLSLAlphaFactor(factor,local,0,other,0); strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = alpha_factor * (alpha_other - alpha_local) + alpha_local; \n"); break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL: writeGLSLAlphaLocal(local); writeGLSLAlphaFactor(factor,local,0,other,1); strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = alpha_factor * (-alpha_local) + alpha_local; \n"); break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA: writeGLSLAlphaLocal(local); writeGLSLAlphaFactor(factor,local,0,other,1); strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = alpha_factor * (-alpha_local) + alpha_local; \n"); break; default: display_warning("grAlphaCombine : unknown function : %x", function); } //compile_shader(); need_to_compile = 1; } else { int num_tex; if (invert) display_warning("grAlphaCombine : inverted result"); if (nbTextureUnits > 2) { glActiveTextureARB(GL_TEXTURE2_ARB); num_tex = 2; } else { glActiveTextureARB(GL_TEXTURE1_ARB); num_tex = 1; } fcta[num_tex+1] = GL_REPLACE; sourcea0[num_tex+1] = GL_PREVIOUS_ARB; operanda0[num_tex+1] = GL_SRC_ALPHA; switch(function) { case GR_COMBINE_FUNCTION_LOCAL: fcta[num_tex] = GL_REPLACE; sourcea0[num_tex] = setLocalAlphaSource(local); operanda0[num_tex] = GL_SRC_ALPHA; break; case GR_COMBINE_FUNCTION_SCALE_OTHER: switch (factor) { case GR_COMBINE_FACTOR_ONE: fcta[num_tex] = GL_REPLACE; sourcea0[num_tex] = setOtherAlphaSource(other); operanda0[num_tex] = GL_SRC_ALPHA; break; case GR_COMBINE_FACTOR_LOCAL: fcta[num_tex] = GL_MODULATE; sourcea0[num_tex] = setLocalAlphaSource(local); operanda0[num_tex] = GL_SRC_ALPHA; sourcea1[num_tex] = setOtherAlphaSource(other); operanda1[num_tex] = GL_SRC_ALPHA; break; case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL: fcta[num_tex] = GL_MODULATE; sourcea0[num_tex] = setLocalAlphaSource(local); operanda0[num_tex] = GL_ONE_MINUS_SRC_ALPHA; sourcea1[num_tex] = setOtherAlphaSource(other); operanda1[num_tex] = GL_SRC_ALPHA; break; case GR_COMBINE_FACTOR_TEXTURE_ALPHA: fcta[num_tex] = GL_MODULATE; sourcea0[num_tex] = GL_PREVIOUS_ARB; operanda0[num_tex] = GL_SRC_ALPHA; sourcea1[num_tex] = setOtherAlphaSource(other); operanda1[num_tex] = GL_SRC_ALPHA; break; case GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA: fcta[num_tex] = GL_MODULATE; sourcea0[num_tex] = GL_PREVIOUS_ARB; operanda0[num_tex] = GL_ONE_MINUS_SRC_ALPHA; sourcea1[num_tex] = setOtherAlphaSource(other); operanda1[num_tex] = GL_SRC_ALPHA; break; default: display_warning("grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER) : unknown factor : %x", factor); } break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL: switch(factor) { case GR_COMBINE_FACTOR_TEXTURE_ALPHA: fcta[num_tex] = GL_MODULATE; sourcea0[num_tex] = setOtherAlphaSource(other); operanda0[num_tex] = GL_SRC_ALPHA; sourcea1[num_tex] = GL_PREVIOUS_ARB; operanda0[num_tex] = GL_SRC_ALPHA; fcta[num_tex+1] = GL_ADD; sourcea0[num_tex+1] = GL_PREVIOUS_ARB; operanda0[num_tex+1] = GL_SRC_ALPHA; sourcea1[num_tex+1] = setLocalAlphaSource(local); operanda1[num_tex+1] = GL_SRC_ALPHA; if (sourcea1[num_tex+1] == GL_PREVIOUS_ARB) sourcea1[num_tex+1] = GL_TEXTURE0_ARB; break; case GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA: fcta[num_tex] = GL_MODULATE; sourcea0[num_tex] = setOtherAlphaSource(other); operanda0[num_tex] = GL_SRC_ALPHA; sourcea1[num_tex] = GL_PREVIOUS_ARB; operanda0[num_tex] = GL_ONE_MINUS_SRC_ALPHA; fcta[num_tex+1] = GL_ADD; sourcea0[num_tex+1] = GL_PREVIOUS_ARB; operanda0[num_tex+1] = GL_SRC_ALPHA; sourcea1[num_tex+1] = setLocalAlphaSource(local); operanda1[num_tex+1] = GL_SRC_ALPHA; if (sourcea1[num_tex+1] == GL_PREVIOUS_ARB) sourcea1[num_tex+1] = GL_TEXTURE0_ARB; break; case GR_COMBINE_FACTOR_LOCAL: fcta[num_tex] = GL_MODULATE; sourcea0[num_tex] = setOtherAlphaSource(other); operanda0[num_tex] = GL_SRC_ALPHA; sourcea1[num_tex] = setLocalAlphaSource(local); operanda0[num_tex] = GL_SRC_ALPHA; fcta[num_tex+1] = GL_ADD; sourcea0[num_tex+1] = GL_PREVIOUS_ARB; operanda0[num_tex+1] = GL_SRC_ALPHA; sourcea1[num_tex+1] = setLocalAlphaSource(local); operanda1[num_tex+1] = GL_SRC_ALPHA; if (sourcea1[num_tex+1] == GL_PREVIOUS_ARB) sourcea1[num_tex+1] = GL_TEXTURE0_ARB; break; case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA: fcta[num_tex] = GL_MODULATE; sourcea0[num_tex] = setOtherAlphaSource(other); operanda0[num_tex] = GL_SRC_ALPHA; sourcea1[num_tex] = setLocalAlphaSource(local); operanda0[num_tex] = GL_ONE_MINUS_SRC_ALPHA; fcta[num_tex+1] = GL_ADD; sourcea0[num_tex+1] = GL_PREVIOUS_ARB; operanda0[num_tex+1] = GL_SRC_ALPHA; sourcea1[num_tex+1] = setLocalAlphaSource(local); operanda1[num_tex+1] = GL_SRC_ALPHA; if (sourcea1[num_tex+1] == GL_PREVIOUS_ARB) sourcea1[num_tex+1] = GL_TEXTURE0_ARB; break; case GR_COMBINE_FACTOR_ONE: fcta[num_tex] = GL_ADD; sourcea0[num_tex] = setOtherAlphaSource(other); operanda0[num_tex] = GL_SRC_ALPHA; sourcea1[num_tex] = setLocalAlphaSource(local); operanda1[num_tex] = GL_SRC_ALPHA; break; default: display_warning("grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL) : unknown factor : %x", factor); } break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL: switch(factor) { case GR_COMBINE_FACTOR_TEXTURE_ALPHA: // this combiner mode isn't implemented correctly and doesn't work on a TNT fcta[num_tex] = GL_SUBTRACT_ARB; sourcea0[num_tex] = setOtherAlphaSource(other); operanda0[num_tex] = GL_SRC_ALPHA; sourcea1[num_tex] = setLocalAlphaSource(local); operanda1[num_tex] = GL_SRC_ALPHA; fcta[num_tex+1] = GL_MODULATE; sourcea0[num_tex+1] = GL_TEXTURE0_ARB; operanda0[num_tex+1] = GL_SRC_ALPHA; sourcea1[num_tex+1] = GL_PREVIOUS_ARB; operanda1[num_tex+1] = GL_SRC_ALPHA; break; case GR_COMBINE_FACTOR_LOCAL: fcta[num_tex] = GL_SUBTRACT_ARB; sourcea0[num_tex] = setOtherAlphaSource(other); operanda0[num_tex] = GL_SRC_ALPHA; sourcea1[num_tex] = setLocalAlphaSource(local); operanda1[num_tex] = GL_SRC_ALPHA; fcta[num_tex+1] = GL_MODULATE; sourcea0[num_tex+1] = setLocalAlphaSource(local); operanda0[num_tex+1] = GL_SRC_ALPHA; sourcea1[num_tex+1] = GL_PREVIOUS_ARB; operanda1[num_tex+1] = GL_SRC_ALPHA; break; case GR_COMBINE_FACTOR_ONE: // doesn't work on a TNT fcta[num_tex] = GL_SUBTRACT_ARB; sourcea0[num_tex] = setOtherAlphaSource(other); operanda0[num_tex] = GL_SRC_ALPHA; sourcea1[num_tex] = setLocalAlphaSource(local); operanda1[num_tex] = GL_SRC_ALPHA; break; default: display_warning("grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL) : unknown factor : %x", factor); } break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL: switch(factor) { case GR_COMBINE_FACTOR_TEXTURE_ALPHA: fcta[num_tex] = GL_INTERPOLATE_ARB; sourcea0[num_tex] = setOtherAlphaSource(other); operanda0[num_tex] = GL_SRC_ALPHA; sourcea1[num_tex] = setLocalAlphaSource(local); operanda1[num_tex] = GL_SRC_ALPHA; sourcea2[num_tex] = GL_PREVIOUS_ARB; operanda2[num_tex] = GL_SRC_ALPHA; break; default: display_warning("grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL) : unknown factor : %x", factor); } break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL: switch(factor) { case GR_COMBINE_FACTOR_TEXTURE_ALPHA: fcta[num_tex] = GL_MODULATE; sourcea0[num_tex] = GL_PREVIOUS_ARB; operanda0[num_tex] = GL_ONE_MINUS_SRC_ALPHA; sourcea1[num_tex] = setLocalAlphaSource(local); operanda1[num_tex] = GL_SRC_ALPHA; break; default: display_warning("grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL) : unknown factor : %x", factor); } break; default: display_warning("grAlphaCombine : unknown function : %x", function); } updateCombinera(num_tex); if (nbTextureUnits > 3) { glActiveTextureARB(GL_TEXTURE3_ARB); updateCombinera(num_tex+1); } } } void writeGLSLTextureColorFactor(int num_tex, int factor) { switch(factor) { case GR_COMBINE_FACTOR_ZERO: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 texture0_color_factor = vec4(0.0); \n"); else strcat(fragment_shader_texture1, "vec4 texture1_color_factor = vec4(0.0); \n"); break; case GR_COMBINE_FACTOR_LOCAL: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 texture0_color_factor = readtex0; \n"); else strcat(fragment_shader_texture1, "vec4 texture1_color_factor = readtex1; \n"); break; case GR_COMBINE_FACTOR_OTHER_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 texture0_color_factor = vec4(0.0); \n"); else strcat(fragment_shader_texture1, "vec4 texture1_color_factor = vec4(ctexture0.a); \n"); break; case GR_COMBINE_FACTOR_LOCAL_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 texture0_color_factor = vec4(readtex0.a); \n"); else strcat(fragment_shader_texture1, "vec4 texture1_color_factor = vec4(readtex1.a); \n"); break; case GR_COMBINE_FACTOR_DETAIL_FACTOR: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 texture0_color_factor = vec4(lambda); \n"); else strcat(fragment_shader_texture1, "vec4 texture1_color_factor = vec4(lambda); \n"); break; case GR_COMBINE_FACTOR_ONE: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 texture0_color_factor = vec4(1.0); \n"); else strcat(fragment_shader_texture1, "vec4 texture1_color_factor = vec4(1.0); \n"); break; case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 texture0_color_factor = vec4(1.0) - readtex0; \n"); else strcat(fragment_shader_texture1, "vec4 texture1_color_factor = vec4(1.0) - readtex1; \n"); break; case GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 texture0_color_factor = vec4(1.0) - vec4(0.0); \n"); else strcat(fragment_shader_texture1, "vec4 texture1_color_factor = vec4(1.0) - vec4(ctexture0.a); \n"); break; case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 texture0_color_factor = vec4(1.0) - vec4(readtex0.a); \n"); else strcat(fragment_shader_texture1, "vec4 texture1_color_factor = vec4(1.0) - vec4(readtex1.a); \n"); break; case GR_COMBINE_FACTOR_ONE_MINUS_DETAIL_FACTOR: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 texture0_color_factor = vec4(1.0) - vec4(lambda); \n"); else strcat(fragment_shader_texture1, "vec4 texture1_color_factor = vec4(1.0) - vec4(lambda); \n"); break; default: display_warning("unknown writeGLSLTextureColorFactor : %x", factor); } } void writeGLSLTextureAlphaFactor(int num_tex, int factor) { switch(factor) { case GR_COMBINE_FACTOR_ZERO: if(num_tex == 0) strcat(fragment_shader_texture0, "float texture0_alpha_factor = 0.0; \n"); else strcat(fragment_shader_texture1, "float texture1_alpha_factor = 0.0; \n"); break; case GR_COMBINE_FACTOR_LOCAL: if(num_tex == 0) strcat(fragment_shader_texture0, "float texture0_alpha_factor = readtex0.a; \n"); else strcat(fragment_shader_texture1, "float texture1_alpha_factor = readtex1.a; \n"); break; case GR_COMBINE_FACTOR_OTHER_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "float texture0_alpha_factor = 0.0; \n"); else strcat(fragment_shader_texture1, "float texture1_alpha_factor = ctexture0.a; \n"); break; case GR_COMBINE_FACTOR_LOCAL_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "float texture0_alpha_factor = readtex0.a; \n"); else strcat(fragment_shader_texture1, "float texture1_alpha_factor = readtex1.a; \n"); break; case GR_COMBINE_FACTOR_DETAIL_FACTOR: if(num_tex == 0) strcat(fragment_shader_texture0, "float texture0_alpha_factor = lambda; \n"); else strcat(fragment_shader_texture1, "float texture1_alpha_factor = lambda; \n"); break; case GR_COMBINE_FACTOR_ONE: if(num_tex == 0) strcat(fragment_shader_texture0, "float texture0_alpha_factor = 1.0; \n"); else strcat(fragment_shader_texture1, "float texture1_alpha_factor = 1.0; \n"); break; case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL: if(num_tex == 0) strcat(fragment_shader_texture0, "float texture0_alpha_factor = 1.0 - readtex0.a; \n"); else strcat(fragment_shader_texture1, "float texture1_alpha_factor = 1.0 - readtex1.a; \n"); break; case GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "float texture0_alpha_factor = 1.0 - 0.0; \n"); else strcat(fragment_shader_texture1, "float texture1_alpha_factor = 1.0 - ctexture0.a; \n"); break; case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "float texture0_alpha_factor = 1.0 - readtex0.a; \n"); else strcat(fragment_shader_texture1, "float texture1_alpha_factor = 1.0 - readtex1.a; \n"); break; case GR_COMBINE_FACTOR_ONE_MINUS_DETAIL_FACTOR: if(num_tex == 0) strcat(fragment_shader_texture0, "float texture0_alpha_factor = 1.0 - lambda; \n"); else strcat(fragment_shader_texture1, "float texture1_alpha_factor = 1.0 - lambda; \n"); break; default: display_warning("unknown writeGLSLTextureAlphaFactor : %x", factor); } } FX_ENTRY void FX_CALL grTexCombine( GrChipID_t tmu, GrCombineFunction_t rgb_function, GrCombineFactor_t rgb_factor, GrCombineFunction_t alpha_function, GrCombineFactor_t alpha_factor, FxBool rgb_invert, FxBool alpha_invert ) { WriteLog(M64MSG_VERBOSE, "grTexCombine(%d,%d,%d,%d,%d,%d,%d)\r\n", tmu, rgb_function, rgb_factor, alpha_function, alpha_factor, rgb_invert, alpha_invert); if(glsl_support) { int num_tex; if (tmu == GR_TMU0) num_tex = 1; else num_tex = 0; if(num_tex == 0) { static int last_function = 0; static int last_factor = 0; static int last_afunction = 0; static int last_afactor = 0; static int last_rgb_invert = 0; if(last_function == rgb_function && last_factor == rgb_factor && last_afunction == alpha_function && last_afactor == alpha_factor && last_rgb_invert == rgb_invert && first_texture0 == 0 && !tex0_combiner_ext) return; first_texture0 = 0; tex0_combiner_ext = 0; last_function = rgb_function; last_factor = rgb_factor; last_afunction = alpha_function; last_afactor = alpha_factor; last_rgb_invert= rgb_invert; texture0_combiner_key = rgb_function | (rgb_factor << 4) | (alpha_function << 8) | (alpha_factor << 12) | (rgb_invert << 16); texture0_combinera_key = 0; strcpy(fragment_shader_texture0, ""); } else { static int last_function = 0; static int last_factor = 0; static int last_afunction = 0; static int last_afactor = 0; static int last_rgb_invert = 0; if(last_function == rgb_function && last_factor == rgb_factor && last_afunction == alpha_function && last_afactor == alpha_factor && last_rgb_invert == rgb_invert && first_texture1 == 0 && !tex1_combiner_ext) return; first_texture1 = 0; tex1_combiner_ext = 0; last_function = rgb_function; last_factor = rgb_factor; last_afunction = alpha_function; last_afactor = alpha_factor; last_rgb_invert = rgb_invert; texture1_combiner_key = rgb_function | (rgb_factor << 4) | (alpha_function << 8) | (alpha_factor << 12) | (rgb_invert << 16); texture1_combinera_key = 0; strcpy(fragment_shader_texture1, ""); } switch(rgb_function) { case GR_COMBINE_FUNCTION_ZERO: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctexture0 = vec4(0.0); \n"); else strcat(fragment_shader_texture1, "vec4 ctexture1 = vec4(0.0); \n"); break; case GR_COMBINE_FUNCTION_LOCAL: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctexture0 = readtex0; \n"); else strcat(fragment_shader_texture1, "vec4 ctexture1 = readtex1; \n"); break; case GR_COMBINE_FUNCTION_LOCAL_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctexture0 = vec4(readtex0.a); \n"); else strcat(fragment_shader_texture1, "vec4 ctexture1 = vec4(readtex1.a); \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER: writeGLSLTextureColorFactor(num_tex, rgb_factor); if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctexture0 = texture0_color_factor * vec4(0.0); \n"); else strcat(fragment_shader_texture1, "vec4 ctexture1 = texture1_color_factor * ctexture0; \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL: writeGLSLTextureColorFactor(num_tex, rgb_factor); if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctexture0 = texture0_color_factor * vec4(0.0) + readtex0; \n"); else strcat(fragment_shader_texture1, "vec4 ctexture1 = texture1_color_factor * ctexture0 + readtex1; \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA: writeGLSLTextureColorFactor(num_tex, rgb_factor); if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctexture0 = texture0_color_factor * vec4(0.0) + vec4(readtex0.a); \n"); else strcat(fragment_shader_texture1, "vec4 ctexture1 = texture1_color_factor * ctexture0 + vec4(readtex1.a); \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL: writeGLSLTextureColorFactor(num_tex, rgb_factor); if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctexture0 = texture0_color_factor * (vec4(0.0) - readtex0); \n"); else strcat(fragment_shader_texture1, "vec4 ctexture1 = texture1_color_factor * (ctexture0 - readtex1); \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL: writeGLSLTextureColorFactor(num_tex, rgb_factor); if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctexture0 = texture0_color_factor * (vec4(0.0) - readtex0) + readtex0; \n"); else strcat(fragment_shader_texture1, "vec4 ctexture1 = texture1_color_factor * (ctexture0 - readtex1) + readtex1; \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA: writeGLSLTextureColorFactor(num_tex, rgb_factor); if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctexture0 = texture0_color_factor * (vec4(0.0) - readtex0) + vec4(readtex0.a); \n"); else strcat(fragment_shader_texture1, "vec4 ctexture1 = texture1_color_factor * (ctexture0 - readtex1) + vec4(readtex1.a); \n"); break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL: writeGLSLTextureColorFactor(num_tex, rgb_factor); if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctexture0 = texture0_color_factor * (-readtex0) + readtex0; \n"); else strcat(fragment_shader_texture1, "vec4 ctexture1 = texture1_color_factor * (-readtex1) + readtex1; \n"); break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA: writeGLSLTextureColorFactor(num_tex, rgb_factor); if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctexture0 = texture0_color_factor * (-readtex0) + vec4(readtex0.a); \n"); else strcat(fragment_shader_texture1, "vec4 ctexture1 = texture1_color_factor * (-readtex1) + vec4(readtex1.a); \n"); break; default: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctexture0 = readtex0; \n"); else strcat(fragment_shader_texture1, "vec4 ctexture1 = readtex1; \n"); display_warning("grTextCombine : unknown rgb function : %x", rgb_function); } if (rgb_invert) { if(num_tex == 0) strcat(fragment_shader_texture0, "ctexture0 = vec4(1.0) - ctexture0; \n"); else strcat(fragment_shader_texture1, "ctexture1 = vec4(1.0) - ctexture1; \n"); } switch(alpha_function) { case GR_COMBINE_FACTOR_ZERO: if(num_tex == 0) strcat(fragment_shader_texture0, "ctexture0.a = 0.0; \n"); else strcat(fragment_shader_texture1, "ctexture1.a = 0.0; \n"); break; case GR_COMBINE_FUNCTION_LOCAL: if(num_tex == 0) strcat(fragment_shader_texture0, "ctexture0.a = readtex0.a; \n"); else strcat(fragment_shader_texture1, "ctexture1.a = readtex1.a; \n"); break; case GR_COMBINE_FUNCTION_LOCAL_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "ctexture0.a = readtex0.a; \n"); else strcat(fragment_shader_texture1, "ctexture1.a = readtex1.a; \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER: writeGLSLTextureAlphaFactor(num_tex, alpha_factor); if(num_tex == 0) strcat(fragment_shader_texture0, "ctexture0.a = texture0_alpha_factor * 0.0; \n"); else strcat(fragment_shader_texture1, "ctexture1.a = texture1_alpha_factor * ctexture0.a; \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL: writeGLSLTextureAlphaFactor(num_tex, alpha_factor); if(num_tex == 0) strcat(fragment_shader_texture0, "ctexture0.a = texture0_alpha_factor * 0.0 + readtex0.a; \n"); else strcat(fragment_shader_texture1, "ctexture1.a = texture1_alpha_factor * ctexture0.a + readtex1.a; \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA: writeGLSLTextureAlphaFactor(num_tex, alpha_factor); if(num_tex == 0) strcat(fragment_shader_texture0, "ctexture0.a = texture0_alpha_factor * 0.0 + readtex0.a; \n"); else strcat(fragment_shader_texture1, "ctexture1.a = texture1_alpha_factor * ctexture0.a + readtex1.a; \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL: writeGLSLTextureAlphaFactor(num_tex, alpha_factor); if(num_tex == 0) strcat(fragment_shader_texture0, "ctexture0.a = texture0_alpha_factor * (0.0 - readtex0.a); \n"); else strcat(fragment_shader_texture1, "ctexture1.a = texture1_alpha_factor * (ctexture0.a - readtex1.a); \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL: writeGLSLTextureAlphaFactor(num_tex, alpha_factor); if(num_tex == 0) strcat(fragment_shader_texture0, "ctexture0.a = texture0_alpha_factor * (0.0 - readtex0.a) + readtex0.a; \n"); else strcat(fragment_shader_texture1, "ctexture1.a = texture1_alpha_factor * (ctexture0.a - readtex1.a) + readtex1.a; \n"); break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA: writeGLSLTextureAlphaFactor(num_tex, alpha_factor); if(num_tex == 0) strcat(fragment_shader_texture0, "ctexture0.a = texture0_alpha_factor * (0.0 - readtex0.a) + readtex0.a; \n"); else strcat(fragment_shader_texture1, "ctexture1.a = texture1_alpha_factor * (ctexture0.a - readtex1.a) + readtex1.a; \n"); break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL: writeGLSLTextureAlphaFactor(num_tex, alpha_factor); if(num_tex == 0) strcat(fragment_shader_texture0, "ctexture0.a = texture0_alpha_factor * (-readtex0.a) + readtex0.a; \n"); else strcat(fragment_shader_texture1, "ctexture1.a = texture1_alpha_factor * (-readtex1.a) + readtex1.a; \n"); break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA: writeGLSLTextureAlphaFactor(num_tex, alpha_factor); if(num_tex == 0) strcat(fragment_shader_texture0, "ctexture0.a = texture0_alpha_factor * (-readtex0.a) + readtex0.a; \n"); else strcat(fragment_shader_texture1, "ctexture1.a = texture1_alpha_factor * (-readtex1.a) + readtex1.a; \n"); break; default: if(num_tex == 0) strcat(fragment_shader_texture0, "ctexture0.a = readtex0.a; \n"); else strcat(fragment_shader_texture1, "ctexture1.a = ctexture0.a; \n"); display_warning("grTextCombine : unknown alpha function : %x", alpha_function); } if (alpha_invert) { if(num_tex == 0) strcat(fragment_shader_texture0, "ctexture0.a = 1.0 - ctexture0.a; \n"); else strcat(fragment_shader_texture1, "ctexture1.a = 1.0 - ctexture1.a; \n"); } //compile_shader(); need_to_compile = 1; } else { int num_tex; int will_need_lambda = 0; //if (rgb_invert) display_warning("grTexCombine : inverted rgb result"); if (alpha_invert) display_warning("grTexCombine : inverted alpha result"); if (tmu == GR_TMU1 && nbTextureUnits <= 2) return; if (tmu == GR_TMU0) { if (nbTextureUnits <= 2) { glActiveTextureARB(GL_TEXTURE0_ARB); num_tex = 0; } else { glActiveTextureARB(GL_TEXTURE1_ARB); num_tex = 1; } } else { glActiveTextureARB(GL_TEXTURE0_ARB); num_tex = 0; } switch(rgb_function) { case GR_COMBINE_FUNCTION_ZERO: fct[num_tex] = GL_REPLACE; source0[num_tex] = GL_PRIMARY_COLOR_ARB; operand0[num_tex] = GL_SRC_COLOR; break; case GR_COMBINE_FUNCTION_LOCAL: fct[num_tex] = GL_REPLACE; source0[num_tex] = GL_TEXTURE; operand0[num_tex] = GL_SRC_COLOR; break; case GR_COMBINE_FUNCTION_SCALE_OTHER: switch(rgb_factor) { case GR_COMBINE_FACTOR_LOCAL: fct[num_tex] = GL_MODULATE; source0[num_tex] = GL_PREVIOUS_ARB; operand0[num_tex] = GL_SRC_COLOR; source1[num_tex] = GL_TEXTURE; operand1[num_tex] = GL_SRC_COLOR; break; case GR_COMBINE_FACTOR_LOCAL_ALPHA: fct[num_tex] = GL_MODULATE; source0[num_tex] = GL_PREVIOUS_ARB; operand0[num_tex] = GL_SRC_COLOR; source1[num_tex] = GL_TEXTURE; operand1[num_tex] = GL_SRC_ALPHA; break; case GR_COMBINE_FACTOR_ONE: fct[num_tex] = GL_REPLACE; source0[num_tex] = GL_PREVIOUS_ARB; operand0[num_tex] = GL_SRC_COLOR; break; default: display_warning("grTextCombine(GR_COMBINE_FUNCTION_SCALE_OTHER) : unknown rgb factor : %x", rgb_factor); } break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL: switch(rgb_factor) { case GR_COMBINE_FACTOR_ONE: fct[num_tex] = GL_ADD; source0[num_tex] = GL_PREVIOUS_ARB; operand0[num_tex] = GL_SRC_COLOR; source1[num_tex] = GL_TEXTURE; operand1[num_tex] = GL_SRC_COLOR; break; case GR_COMBINE_FACTOR_OTHER_ALPHA: if (num_tex==1) { fct[num_tex-1] = GL_MODULATE; source0[num_tex-1] = GL_TEXTURE; operand0[num_tex-1] = GL_SRC_COLOR; source1[num_tex-1] = GL_TEXTURE; operand1[num_tex-1] = GL_SRC_ALPHA; fct[num_tex] = GL_ADD; source0[num_tex] = GL_PREVIOUS_ARB; operand0[num_tex] = GL_SRC_COLOR; source1[num_tex] = GL_TEXTURE; operand1[num_tex] = GL_SRC_COLOR; } break; case GR_COMBINE_FACTOR_DETAIL_FACTOR: if (num_tex==1) { fct[num_tex-1] = GL_MODULATE; source0[num_tex-1] = GL_TEXTURE; operand0[num_tex-1] = GL_SRC_COLOR; source1[num_tex-1] = GL_CONSTANT_ARB; operand1[num_tex-1] = GL_SRC_ALPHA; fct[num_tex] = GL_ADD; source0[num_tex] = GL_PREVIOUS_ARB; operand0[num_tex] = GL_SRC_COLOR; source1[num_tex] = GL_TEXTURE; operand1[num_tex] = GL_SRC_COLOR; will_need_lambda = 1; } break; default: display_warning("grTextCombine(GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL) : unknown rgb factor : %x", rgb_factor); } break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL: switch(rgb_factor) { case GR_COMBINE_FACTOR_DETAIL_FACTOR: fct[num_tex] = GL_INTERPOLATE_ARB; source0[num_tex] = GL_PREVIOUS_ARB; operand0[num_tex] = GL_SRC_COLOR; source1[num_tex] = GL_TEXTURE; operand1[num_tex] = GL_SRC_COLOR; source2[num_tex] = GL_CONSTANT_ARB; operand2[num_tex] = GL_SRC_ALPHA; will_need_lambda = 1; break; case GR_COMBINE_FACTOR_ONE_MINUS_LOCAL: fct[num_tex] = GL_INTERPOLATE_ARB; source0[num_tex] = GL_PREVIOUS_ARB; operand0[num_tex] = GL_SRC_COLOR; source1[num_tex] = GL_TEXTURE; operand1[num_tex] = GL_SRC_COLOR; source2[num_tex] = GL_TEXTURE; operand2[num_tex] = GL_ONE_MINUS_SRC_COLOR; break; default: display_warning("grTextCombine(GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL) : unknown rgb factor : %x", rgb_factor); } break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL: switch(rgb_factor) { case GR_COMBINE_FACTOR_LOCAL: // this combiner mode isn't implemented correctly and doesn't work on a TNT if (num_tex==1) { fct[num_tex-1] = GL_SUBTRACT_ARB; source0[num_tex-1] = GL_TEXTURE0_ARB; operand0[num_tex-1] = GL_SRC_COLOR; source1[num_tex-1] = GL_TEXTURE1_ARB; operand1[num_tex-1] = GL_SRC_COLOR; fct[num_tex] = GL_MODULATE; source0[num_tex] = GL_PREVIOUS_ARB; operand0[num_tex] = GL_SRC_COLOR; source1[num_tex] = GL_TEXTURE; operand1[num_tex] = GL_SRC_COLOR; } break; default: display_warning("grTextCombine(GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL) : unknown rgb factor : %x", rgb_factor); } default: display_warning("grTextCombine : unknown rgb function : %x", rgb_function); } switch(alpha_function) { case GR_COMBINE_FUNCTION_ZERO: fcta[num_tex] = GL_REPLACE; sourcea0[num_tex] = GL_PRIMARY_COLOR_ARB; operanda0[num_tex] = GL_SRC_ALPHA; break; case GR_COMBINE_FUNCTION_LOCAL: fcta[num_tex] = GL_REPLACE; sourcea0[num_tex] = GL_TEXTURE; operanda0[num_tex] = GL_SRC_ALPHA; break; case GR_COMBINE_FUNCTION_SCALE_OTHER: switch(alpha_factor) { case GR_COMBINE_FACTOR_LOCAL: fcta[num_tex] = GL_MODULATE; sourcea0[num_tex] = GL_TEXTURE; operanda0[num_tex] = GL_SRC_ALPHA; sourcea1[num_tex] = GL_PREVIOUS_ARB; operanda1[num_tex] = GL_SRC_ALPHA; break; case GR_COMBINE_FACTOR_ONE: fcta[num_tex] = GL_REPLACE; sourcea0[num_tex] = GL_PREVIOUS_ARB; operanda0[num_tex] = GL_SRC_ALPHA; break; default: display_warning("grTextCombine(GR_COMBINE_FUNCTION_SCALE_OTHER) : unknown alpha factor : %x", alpha_factor); } break; case GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL: switch(alpha_factor) { case GR_COMBINE_FACTOR_ONE: fcta[num_tex] = GL_ADD; sourcea0[num_tex] = GL_PREVIOUS_ARB; operanda0[num_tex] = GL_SRC_ALPHA; sourcea1[num_tex] = GL_TEXTURE; operanda1[num_tex] = GL_SRC_ALPHA; break; case GR_COMBINE_FACTOR_DETAIL_FACTOR: if (num_tex==1) { fct[num_tex-1] = GL_MODULATE; source0[num_tex-1] = GL_TEXTURE; operand0[num_tex-1] = GL_SRC_ALPHA; source1[num_tex-1] = GL_CONSTANT_ARB; operand1[num_tex-1] = GL_SRC_ALPHA; fct[num_tex] = GL_ADD; source0[num_tex] = GL_PREVIOUS_ARB; operand0[num_tex] = GL_SRC_ALPHA; source1[num_tex] = GL_TEXTURE; operand1[num_tex] = GL_SRC_ALPHA; will_need_lambda = 1; } break; default: display_warning("grTextCombine(GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL) : unknown alpha factor : %x", alpha_factor); } break; case GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL: switch(alpha_factor) { case GR_COMBINE_FACTOR_DETAIL_FACTOR: fcta[num_tex] = GL_INTERPOLATE_ARB; sourcea0[num_tex] = GL_PREVIOUS_ARB; operanda0[num_tex] = GL_SRC_ALPHA; sourcea1[num_tex] = GL_TEXTURE; operanda1[num_tex] = GL_SRC_ALPHA; sourcea2[num_tex] = GL_CONSTANT_ARB; operanda2[num_tex] = GL_SRC_ALPHA; will_need_lambda = 1; break; default: display_warning("grTextCombine(GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL) : unknown alpha factor : %x", alpha_factor); } break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL: switch(alpha_factor) { case GR_COMBINE_FACTOR_DETAIL_FACTOR: fcta[num_tex] = GL_MODULATE; sourcea0[num_tex] = GL_CONSTANT_ARB; operanda0[num_tex] = GL_ONE_MINUS_SRC_ALPHA; sourcea1[num_tex] = GL_TEXTURE; operanda1[num_tex] = GL_SRC_ALPHA; will_need_lambda = 1; break; default: display_warning("grTextCombine(GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL) : unknown alpha factor : %x", alpha_factor); } break; case GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA: switch(alpha_factor) { case GR_COMBINE_FACTOR_OTHER_ALPHA: fcta[num_tex] = GL_MODULATE; sourcea0[num_tex] = GL_PREVIOUS_ARB; operanda0[num_tex] = GL_ONE_MINUS_SRC_ALPHA; sourcea1[num_tex] = GL_TEXTURE; operanda1[num_tex] = GL_SRC_ALPHA; break; default: display_warning("grTextCombine(GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA) : unknown alpha factor : %x", alpha_factor); } break; default: display_warning("grTextCombine : unknown alpha function : %x", alpha_function); } if (will_need_lambda != need_lambda[num_tex]) { need_lambda[num_tex] = will_need_lambda; if (need_lambda[num_tex]) { int i; for (i=0; i<3; i++) lambda_color[num_tex][i] = texture_env_color[i]; lambda_color[num_tex][3] = lambda; glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, lambda_color[num_tex]); } else glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, texture_env_color); } updateCombiner(num_tex); updateCombinera(num_tex); } } FX_ENTRY void FX_CALL grAlphaBlendFunction( GrAlphaBlendFnc_t rgb_sf, GrAlphaBlendFnc_t rgb_df, GrAlphaBlendFnc_t alpha_sf, GrAlphaBlendFnc_t alpha_df ) { int sfactorRGB = 0, dfactorRGB = 0, sfactorAlpha = 0, dfactorAlpha = 0; WriteLog(M64MSG_VERBOSE, "grAlphaBlendFunction(%d,%d,%d,%d)\r\n", rgb_sf, rgb_df, alpha_sf, alpha_df); switch(rgb_sf) { case GR_BLEND_ZERO: sfactorRGB = GL_ZERO; break; case GR_BLEND_SRC_ALPHA: sfactorRGB = GL_SRC_ALPHA; break; case GR_BLEND_ONE: sfactorRGB = GL_ONE; break; case GR_BLEND_ONE_MINUS_SRC_ALPHA: sfactorRGB = GL_ONE_MINUS_SRC_ALPHA; break; default: display_warning("grAlphaBlendFunction : rgb_sf = %x", rgb_sf); } switch(rgb_df) { case GR_BLEND_ZERO: dfactorRGB = GL_ZERO; break; case GR_BLEND_SRC_ALPHA: dfactorRGB = GL_SRC_ALPHA; break; case GR_BLEND_ONE: dfactorRGB = GL_ONE; break; case GR_BLEND_ONE_MINUS_SRC_ALPHA: dfactorRGB = GL_ONE_MINUS_SRC_ALPHA; break; default: display_warning("grAlphaBlendFunction : rgb_df = %x", rgb_df); } switch(alpha_sf) { case GR_BLEND_ZERO: sfactorAlpha = GL_ZERO; break; case GR_BLEND_ONE: sfactorAlpha = GL_ONE; break; default: display_warning("grAlphaBlendFunction : alpha_sf = %x", alpha_sf); } switch(alpha_df) { case GR_BLEND_ZERO: dfactorAlpha = GL_ZERO; break; case GR_BLEND_ONE: dfactorAlpha = GL_ONE; break; default: display_warning("grAlphaBlendFunction : alpha_df = %x", alpha_df); } glEnable(GL_BLEND); if (blend_func_separate_support) glBlendFuncSeparateEXT(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); else glBlendFunc(sfactorRGB, dfactorRGB); } FX_ENTRY void FX_CALL grAlphaTestReferenceValue( GrAlpha_t value ) { WriteLog(M64MSG_VERBOSE, "grAlphaTestReferenceValue(%d)\r\n", value); alpha_ref = value; grAlphaTestFunction(alpha_func); } FX_ENTRY void FX_CALL grAlphaTestFunction( GrCmpFnc_t function ) { WriteLog(M64MSG_VERBOSE, "grAlphaTestFunction(%d)\r\n", function); alpha_func = function; switch(function) { case GR_CMP_GREATER: glAlphaFunc(GL_GREATER, alpha_ref/255.0f); break; case GR_CMP_GEQUAL: glAlphaFunc(GL_GEQUAL, alpha_ref/255.0f); break; case GR_CMP_ALWAYS: glAlphaFunc(GL_ALWAYS, alpha_ref/255.0f); glDisable(GL_ALPHA_TEST); return; break; default: display_warning("grAlphaTestFunction : unknown function : %x", function); } glEnable(GL_ALPHA_TEST); } // fog FX_ENTRY void FX_CALL grFogMode( GrFogMode_t mode ) { WriteLog(M64MSG_VERBOSE, "grFogMode(%d)\r\n", mode); switch(mode) { case GR_FOG_DISABLE: glDisable(GL_FOG); fog_enabled = 0; break; case GR_FOG_WITH_TABLE_ON_Q: glEnable(GL_FOG); glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT); fog_enabled = 1; break; case GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT: glEnable(GL_FOG); glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT); fog_enabled = 2; break; default: display_warning("grFogMode : unknown mode : %x", mode); } if(glsl_support) need_to_compile = 1; } FX_ENTRY float FX_CALL guFogTableIndexToW( int i ) { WriteLog(M64MSG_VERBOSE, "guFogTableIndexToW(%d)\r\n", i); return (float)(pow(2.0, 3.0+(double)(i>>2)) / (8-(i&3))); } FX_ENTRY void FX_CALL guFogGenerateLinear(GrFog_t *fogtable, float nearZ, float farZ ) { WriteLog(M64MSG_VERBOSE, "guFogGenerateLinear(%f,%f)\r\n", nearZ, farZ); if(!glsl_support) { glFogi(GL_FOG_MODE, GL_LINEAR); glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT); glFogf(GL_FOG_START, nearZ /*/ 256.0f*/); glFogf(GL_FOG_END, farZ /*/ 256.0f*/); } else { /*int near_location; int far_location; nearF = nearZ / 256.0f; farF = farF / 256.0f; near_location = glGetUniformLocationARB(program_object, "near"); glUniform1fARB(near_location, nearF); far_location = glGetUniformLocationARB(program_object, "far"); glUniform1fARB(far_location, farF);*/ glFogi(GL_FOG_MODE, GL_LINEAR); glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT); glFogf(GL_FOG_START, nearZ / 255.0f); glFogf(GL_FOG_END, farZ / 255.0f); } } FX_ENTRY void FX_CALL grFogTable( const GrFog_t ft[] ) { WriteLog(M64MSG_VERBOSE, "grFogTable()\r\n"); } FX_ENTRY void FX_CALL grFogColorValue( GrColor_t fogcolor ) { float color[4]; WriteLog(M64MSG_VERBOSE, "grFogColorValue(%x)\r\n", fogcolor); switch(lfb_color_fmt) { case GR_COLORFORMAT_ARGB: color[3] = ((fogcolor >> 24) & 0xFF) / 255.0f; color[0] = ((fogcolor >> 16) & 0xFF) / 255.0f; color[1] = ((fogcolor >> 8) & 0xFF) / 255.0f; color[2] = (fogcolor & 0xFF) / 255.0f; break; case GR_COLORFORMAT_RGBA: color[0] = ((fogcolor >> 24) & 0xFF) / 255.0f; color[1] = ((fogcolor >> 16) & 0xFF) / 255.0f; color[2] = ((fogcolor >> 8) & 0xFF) / 255.0f; color[3] = (fogcolor & 0xFF) / 255.0f; break; default: display_warning("grFogColorValue: unknown color format : %x", lfb_color_fmt); } glFogfv(GL_FOG_COLOR, color); } // chroma FX_ENTRY void FX_CALL grChromakeyMode( GrChromakeyMode_t mode ) { WriteLog(M64MSG_VERBOSE, "grChromakeyMode(%d)\r\n", mode); switch(mode) { case GR_CHROMAKEY_DISABLE: chroma_enabled = 0; break; case GR_CHROMAKEY_ENABLE: if(!glsl_support) display_warning("grChromakeyMode : unknown mode : %x", mode); else chroma_enabled = 1; break; default: display_warning("grChromakeyMode : unknown mode : %x", mode); } if(glsl_support) need_to_compile = 1; } FX_ENTRY void FX_CALL grChromakeyValue( GrColor_t value ) { WriteLog(M64MSG_VERBOSE, "grChromakeyValue(%x)\r\n", value); if(!glsl_support) display_warning("grChromakeyValue"); else { int chroma_color_location; switch(lfb_color_fmt) { case GR_COLORFORMAT_ARGB: chroma_color[3] = 1.0;//((value >> 24) & 0xFF) / 255.0f; chroma_color[0] = ((value >> 16) & 0xFF) / 255.0f; chroma_color[1] = ((value >> 8) & 0xFF) / 255.0f; chroma_color[2] = (value & 0xFF) / 255.0f; break; case GR_COLORFORMAT_RGBA: chroma_color[0] = ((value >> 24) & 0xFF) / 255.0f; chroma_color[1] = ((value >> 16) & 0xFF) / 255.0f; chroma_color[2] = ((value >> 8) & 0xFF) / 255.0f; chroma_color[3] = 1.0;//(value & 0xFF) / 255.0f; break; default: display_warning("grChromakeyValue: unknown color format : %x", lfb_color_fmt); } chroma_color_location = glGetUniformLocationARB(program_object, "chroma_color"); glUniform4fARB(chroma_color_location, chroma_color[0], chroma_color[1], chroma_color[2], chroma_color[3]); } } static void setPattern() { int i; GLubyte stip[32*4]; for(i=0; i<32; i++) { unsigned int val = (rand() << 17) | ((rand() & 1) << 16) | (rand() << 1) | (rand() & 1); stip[i*4+0] = (val >> 24) & 0xFF; stip[i*4+1] = (val >> 16) & 0xFF; stip[i*4+2] = (val >> 8) & 0xFF; stip[i*4+3] = val & 0xFF; } if(!glsl_support) glPolygonStipple(stip); else { GLubyte texture[32*32*4]; for(i=0; i<32; i++) { int j; for(j=0; j<4; j++) { texture[(i*32+j*8+0)*4+3] = ((stip[i*4+j] >> 7) & 1) ? 255 : 0; texture[(i*32+j*8+1)*4+3] = ((stip[i*4+j] >> 6) & 1) ? 255 : 0; texture[(i*32+j*8+2)*4+3] = ((stip[i*4+j] >> 5) & 1) ? 255 : 0; texture[(i*32+j*8+3)*4+3] = ((stip[i*4+j] >> 4) & 1) ? 255 : 0; texture[(i*32+j*8+4)*4+3] = ((stip[i*4+j] >> 3) & 1) ? 255 : 0; texture[(i*32+j*8+5)*4+3] = ((stip[i*4+j] >> 2) & 1) ? 255 : 0; texture[(i*32+j*8+6)*4+3] = ((stip[i*4+j] >> 1) & 1) ? 255 : 0; texture[(i*32+j*8+7)*4+3] = ((stip[i*4+j] >> 0) & 1) ? 255 : 0; } } glActiveTextureARB(GL_TEXTURE2_ARB); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 33*1024*1024); glTexImage2D(GL_TEXTURE_2D, 0, 4, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glDisable(GL_TEXTURE_2D); } } FX_ENTRY void FX_CALL grStipplePattern( GrStipplePattern_t stipple) { WriteLog(M64MSG_VERBOSE, "grStipplePattern(%x)\r\n", stipple); srand(stipple); setPattern(); } int getDisableDitheredAlpha(); FX_ENTRY void FX_CALL grStippleMode( GrStippleMode_t mode ) { WriteLog(M64MSG_VERBOSE, "grStippleMode(%d)\r\n", mode); if(getDisableDitheredAlpha()) return; switch(mode) { case GR_STIPPLE_DISABLE: if(!glsl_support) glDisable(GL_POLYGON_STIPPLE); else { dither_enabled = 0; glActiveTextureARB(GL_TEXTURE2_ARB); glDisable(GL_TEXTURE_2D); } break; case GR_STIPPLE_PATTERN: setPattern(); if(!glsl_support) glEnable(GL_POLYGON_STIPPLE); else { dither_enabled = 1; glActiveTextureARB(GL_TEXTURE2_ARB); glEnable(GL_TEXTURE_2D); } break; case GR_STIPPLE_ROTATE: setPattern(); if(!glsl_support) glEnable(GL_POLYGON_STIPPLE); else { dither_enabled = 1; glActiveTextureARB(GL_TEXTURE2_ARB); glEnable(GL_TEXTURE_2D); } break; default: display_warning("grStippleMode:%x", mode); } if(glsl_support) need_to_compile = 1; } FX_ENTRY void FX_CALL grColorCombineExt(GrCCUColor_t a, GrCombineMode_t a_mode, GrCCUColor_t b, GrCombineMode_t b_mode, GrCCUColor_t c, FxBool c_invert, GrCCUColor_t d, FxBool d_invert, FxU32 shift, FxBool invert) { WriteLog(M64MSG_VERBOSE, "grColorCombineExt(%d, %d, %d, %d, %d, %d, %d, %d, %d, %d)\r\n", a, a_mode, b, b_mode, c, c_invert, d, d_invert, shift, invert); if (invert) display_warning("grColorCombineExt : inverted result"); if (shift) display_warning("grColorCombineExt : shift = %d", shift); color_combiner_key = 0x80000000 | (a & 0x1F) | ((a_mode & 3) << 5) | ((b & 0x1F) << 7) | ((b_mode & 3) << 12) | ((c & 0x1F) << 14) | ((c_invert & 1) << 19) | ((d & 0x1F) << 20) | ((d_invert & 1) << 25); c_combiner_ext = 1; strcpy(fragment_shader_color_combiner, ""); switch(a) { case GR_CMBX_ZERO: strcat(fragment_shader_color_combiner, "vec4 cs_a = vec4(0.0); \n"); break; case GR_CMBX_TEXTURE_ALPHA: strcat(fragment_shader_color_combiner, "vec4 cs_a = vec4(ctexture1.a); \n"); break; case GR_CMBX_CONSTANT_ALPHA: strcat(fragment_shader_color_combiner, "vec4 cs_a = vec4(constant_color.a); \n"); break; case GR_CMBX_CONSTANT_COLOR: strcat(fragment_shader_color_combiner, "vec4 cs_a = constant_color; \n"); break; case GR_CMBX_ITALPHA: strcat(fragment_shader_color_combiner, "vec4 cs_a = vec4(gl_Color.a); \n"); break; case GR_CMBX_ITRGB: strcat(fragment_shader_color_combiner, "vec4 cs_a = gl_Color; \n"); break; case GR_CMBX_TEXTURE_RGB: strcat(fragment_shader_color_combiner, "vec4 cs_a = ctexture1; \n"); break; default: display_warning("grColorCombineExt : a = %x", a); strcat(fragment_shader_color_combiner, "vec4 cs_a = vec4(0.0); \n"); } switch(a_mode) { case GR_FUNC_MODE_ZERO: strcat(fragment_shader_color_combiner, "vec4 c_a = vec4(0.0); \n"); break; case GR_FUNC_MODE_X: strcat(fragment_shader_color_combiner, "vec4 c_a = cs_a; \n"); break; case GR_FUNC_MODE_ONE_MINUS_X: strcat(fragment_shader_color_combiner, "vec4 c_a = vec4(1.0) - cs_a; \n"); break; case GR_FUNC_MODE_NEGATIVE_X: strcat(fragment_shader_color_combiner, "vec4 c_a = -cs_a; \n"); break; default: display_warning("grColorCombineExt : a_mode = %x", a_mode); strcat(fragment_shader_color_combiner, "vec4 c_a = vec4(0.0); \n"); } switch(b) { case GR_CMBX_ZERO: strcat(fragment_shader_color_combiner, "vec4 cs_b = vec4(0.0); \n"); break; case GR_CMBX_TEXTURE_ALPHA: strcat(fragment_shader_color_combiner, "vec4 cs_b = vec4(ctexture1.a); \n"); break; case GR_CMBX_CONSTANT_ALPHA: strcat(fragment_shader_color_combiner, "vec4 cs_b = vec4(constant_color.a); \n"); break; case GR_CMBX_CONSTANT_COLOR: strcat(fragment_shader_color_combiner, "vec4 cs_b = constant_color; \n"); break; case GR_CMBX_ITALPHA: strcat(fragment_shader_color_combiner, "vec4 cs_b = vec4(gl_Color.a); \n"); break; case GR_CMBX_ITRGB: strcat(fragment_shader_color_combiner, "vec4 cs_b = gl_Color; \n"); break; case GR_CMBX_TEXTURE_RGB: strcat(fragment_shader_color_combiner, "vec4 cs_b = ctexture1; \n"); break; default: display_warning("grColorCombineExt : b = %x", b); strcat(fragment_shader_color_combiner, "vec4 cs_b = vec4(0.0); \n"); } switch(b_mode) { case GR_FUNC_MODE_ZERO: strcat(fragment_shader_color_combiner, "vec4 c_b = vec4(0.0); \n"); break; case GR_FUNC_MODE_X: strcat(fragment_shader_color_combiner, "vec4 c_b = cs_b; \n"); break; case GR_FUNC_MODE_ONE_MINUS_X: strcat(fragment_shader_color_combiner, "vec4 c_b = vec4(1.0) - cs_b; \n"); break; case GR_FUNC_MODE_NEGATIVE_X: strcat(fragment_shader_color_combiner, "vec4 c_b = -cs_b; \n"); break; default: display_warning("grColorCombineExt : b_mode = %x", b_mode); strcat(fragment_shader_color_combiner, "vec4 c_b = vec4(0.0); \n"); } switch(c) { case GR_CMBX_ZERO: strcat(fragment_shader_color_combiner, "vec4 c_c = vec4(0.0); \n"); break; case GR_CMBX_TEXTURE_ALPHA: strcat(fragment_shader_color_combiner, "vec4 c_c = vec4(ctexture1.a); \n"); break; case GR_CMBX_ALOCAL: strcat(fragment_shader_color_combiner, "vec4 c_c = vec4(c_b.a); \n"); break; case GR_CMBX_AOTHER: strcat(fragment_shader_color_combiner, "vec4 c_c = vec4(c_a.a); \n"); break; case GR_CMBX_B: strcat(fragment_shader_color_combiner, "vec4 c_c = cs_b; \n"); break; case GR_CMBX_CONSTANT_ALPHA: strcat(fragment_shader_color_combiner, "vec4 c_c = vec4(constant_color.a); \n"); break; case GR_CMBX_CONSTANT_COLOR: strcat(fragment_shader_color_combiner, "vec4 c_c = constant_color; \n"); break; case GR_CMBX_ITALPHA: strcat(fragment_shader_color_combiner, "vec4 c_c = vec4(gl_Color.a); \n"); break; case GR_CMBX_ITRGB: strcat(fragment_shader_color_combiner, "vec4 c_c = gl_Color; \n"); break; case GR_CMBX_TEXTURE_RGB: strcat(fragment_shader_color_combiner, "vec4 c_c = ctexture1; \n"); break; default: display_warning("grColorCombineExt : c = %x", c); strcat(fragment_shader_color_combiner, "vec4 c_c = vec4(0.0); \n"); } if(c_invert) strcat(fragment_shader_color_combiner, "c_c = vec4(1.0) - c_c; \n"); switch(d) { case GR_CMBX_ZERO: strcat(fragment_shader_color_combiner, "vec4 c_d = vec4(0.0); \n"); break; case GR_CMBX_ALOCAL: strcat(fragment_shader_color_combiner, "vec4 c_d = vec4(c_b.a); \n"); break; case GR_CMBX_B: strcat(fragment_shader_color_combiner, "vec4 c_d = cs_b; \n"); break; case GR_CMBX_TEXTURE_RGB: strcat(fragment_shader_color_combiner, "vec4 c_d = ctexture1; \n"); break; case GR_CMBX_ITRGB: strcat(fragment_shader_color_combiner, "vec4 c_d = gl_Color; \n"); break; default: display_warning("grColorCombineExt : d = %x", d); strcat(fragment_shader_color_combiner, "vec4 c_d = vec4(0.0); \n"); } if(d_invert) strcat(fragment_shader_color_combiner, "c_d = vec4(1.0) - c_d; \n"); strcat(fragment_shader_color_combiner, "gl_FragColor = (c_a + c_b) * c_c + c_d; \n"); need_to_compile = 1; } FX_ENTRY void FX_CALL grAlphaCombineExt(GrACUColor_t a, GrCombineMode_t a_mode, GrACUColor_t b, GrCombineMode_t b_mode, GrACUColor_t c, FxBool c_invert, GrACUColor_t d, FxBool d_invert, FxU32 shift, FxBool invert) { WriteLog(M64MSG_VERBOSE, "grAlphaCombineExt(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)\r\n", a, a_mode, b, b_mode, c, c_invert, d, d_invert, shift, invert); if (invert) display_warning("grAlphaCombineExt : inverted result"); if (shift) display_warning("grAlphaCombineExt : shift = %d", shift); alpha_combiner_key = 0x80000000 | (a & 0x1F) | ((a_mode & 3) << 5) | ((b & 0x1F) << 7) | ((b_mode & 3) << 12) | ((c & 0x1F) << 14) | ((c_invert & 1) << 19) | ((d & 0x1F) << 20) | ((d_invert & 1) << 25); a_combiner_ext = 1; strcpy(fragment_shader_alpha_combiner, ""); switch(a) { case GR_CMBX_ZERO: strcat(fragment_shader_alpha_combiner, "float as_a = 0.0; \n"); break; case GR_CMBX_TEXTURE_ALPHA: strcat(fragment_shader_alpha_combiner, "float as_a = ctexture1.a; \n"); break; case GR_CMBX_CONSTANT_ALPHA: strcat(fragment_shader_alpha_combiner, "float as_a = constant_color.a; \n"); break; case GR_CMBX_ITALPHA: strcat(fragment_shader_alpha_combiner, "float as_a = gl_Color.a; \n"); break; default: display_warning("grAlphaCombineExt : a = %x", a); strcat(fragment_shader_alpha_combiner, "float as_a = 0.0; \n"); } switch(a_mode) { case GR_FUNC_MODE_ZERO: strcat(fragment_shader_alpha_combiner, "float a_a = 0.0; \n"); break; case GR_FUNC_MODE_X: strcat(fragment_shader_alpha_combiner, "float a_a = as_a; \n"); break; case GR_FUNC_MODE_ONE_MINUS_X: strcat(fragment_shader_alpha_combiner, "float a_a = 1.0 - as_a; \n"); break; case GR_FUNC_MODE_NEGATIVE_X: strcat(fragment_shader_alpha_combiner, "float a_a = -as_a; \n"); break; default: display_warning("grAlphaCombineExt : a_mode = %x", a_mode); strcat(fragment_shader_alpha_combiner, "float a_a = 0.0; \n"); } switch(b) { case GR_CMBX_ZERO: strcat(fragment_shader_alpha_combiner, "float as_b = 0.0; \n"); break; case GR_CMBX_TEXTURE_ALPHA: strcat(fragment_shader_alpha_combiner, "float as_b = ctexture1.a; \n"); break; case GR_CMBX_CONSTANT_ALPHA: strcat(fragment_shader_alpha_combiner, "float as_b = constant_color.a; \n"); break; case GR_CMBX_ITALPHA: strcat(fragment_shader_alpha_combiner, "float as_b = gl_Color.a; \n"); break; default: display_warning("grAlphaCombineExt : b = %x", b); strcat(fragment_shader_alpha_combiner, "float as_b = 0.0; \n"); } switch(b_mode) { case GR_FUNC_MODE_ZERO: strcat(fragment_shader_alpha_combiner, "float a_b = 0.0; \n"); break; case GR_FUNC_MODE_X: strcat(fragment_shader_alpha_combiner, "float a_b = as_b; \n"); break; case GR_FUNC_MODE_ONE_MINUS_X: strcat(fragment_shader_alpha_combiner, "float a_b = 1.0 - as_b; \n"); break; case GR_FUNC_MODE_NEGATIVE_X: strcat(fragment_shader_alpha_combiner, "float a_b = -as_b; \n"); break; default: display_warning("grAlphaCombineExt : b_mode = %x", b_mode); strcat(fragment_shader_alpha_combiner, "float a_b = 0.0; \n"); } switch(c) { case GR_CMBX_ZERO: strcat(fragment_shader_alpha_combiner, "float a_c = 0.0; \n"); break; case GR_CMBX_TEXTURE_ALPHA: strcat(fragment_shader_alpha_combiner, "float a_c = ctexture1.a; \n"); break; case GR_CMBX_ALOCAL: strcat(fragment_shader_alpha_combiner, "float a_c = as_b; \n"); break; case GR_CMBX_AOTHER: strcat(fragment_shader_alpha_combiner, "float a_c = as_a; \n"); break; case GR_CMBX_B: strcat(fragment_shader_alpha_combiner, "float a_c = as_b; \n"); break; case GR_CMBX_CONSTANT_ALPHA: strcat(fragment_shader_alpha_combiner, "float a_c = constant_color.a; \n"); break; case GR_CMBX_ITALPHA: strcat(fragment_shader_alpha_combiner, "float a_c = gl_Color.a; \n"); break; default: display_warning("grAlphaCombineExt : c = %x", c); strcat(fragment_shader_alpha_combiner, "float a_c = 0.0; \n"); } if(c_invert) strcat(fragment_shader_alpha_combiner, "a_c = 1.0 - a_c; \n"); switch(d) { case GR_CMBX_ZERO: strcat(fragment_shader_alpha_combiner, "float a_d = 0.0; \n"); break; case GR_CMBX_TEXTURE_ALPHA: strcat(fragment_shader_alpha_combiner, "float a_d = ctexture1.a; \n"); break; case GR_CMBX_ALOCAL: strcat(fragment_shader_alpha_combiner, "float a_d = as_b; \n"); break; case GR_CMBX_B: strcat(fragment_shader_alpha_combiner, "float a_d = as_b; \n"); break; default: display_warning("grAlphaCombineExt : d = %x", d); strcat(fragment_shader_alpha_combiner, "float a_d = 0.0; \n"); } if(d_invert) strcat(fragment_shader_alpha_combiner, "a_d = 1.0 - a_d; \n"); strcat(fragment_shader_alpha_combiner, "gl_FragColor.a = (a_a + a_b) * a_c + a_d; \n"); need_to_compile = 1; } FX_ENTRY void FX_CALL grTexColorCombineExt(GrChipID_t tmu, GrTCCUColor_t a, GrCombineMode_t a_mode, GrTCCUColor_t b, GrCombineMode_t b_mode, GrTCCUColor_t c, FxBool c_invert, GrTCCUColor_t d, FxBool d_invert, FxU32 shift, FxBool invert) { int num_tex; WriteLog(M64MSG_VERBOSE, "grTexColorCombineExt(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)\r\n", tmu, a, a_mode, b, b_mode, c, c_invert, d, d_invert, shift, invert); if (invert) display_warning("grTexColorCombineExt : inverted result"); if (shift) display_warning("grTexColorCombineExt : shift = %d", shift); if (tmu == GR_TMU0) num_tex = 1; else num_tex = 0; if(num_tex == 0) { texture0_combiner_key = 0x80000000 | (a & 0x1F) | ((a_mode & 3) << 5) | ((b & 0x1F) << 7) | ((b_mode & 3) << 12) | ((c & 0x1F) << 14) | ((c_invert & 1) << 19) | ((d & 0x1F) << 20) | ((d_invert & 1) << 25); tex0_combiner_ext = 1; strcpy(fragment_shader_texture0, ""); } else { texture1_combiner_key = 0x80000000 | (a & 0x1F) | ((a_mode & 3) << 5) | ((b & 0x1F) << 7) | ((b_mode & 3) << 12) | ((c & 0x1F) << 14) | ((c_invert & 1) << 19) | ((d & 0x1F) << 20) | ((d_invert & 1) << 25); tex1_combiner_ext = 1; strcpy(fragment_shader_texture1, ""); } switch(a) { case GR_CMBX_ZERO: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0s_a = vec4(0.0); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1s_a = vec4(0.0); \n"); break; case GR_CMBX_ITALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0s_a = vec4(gl_Color.a); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1s_a = vec4(gl_Color.a); \n"); break; case GR_CMBX_ITRGB: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0s_a = gl_Color; \n"); else strcat(fragment_shader_texture1, "vec4 ctex1s_a = gl_Color; \n"); break; case GR_CMBX_LOCAL_TEXTURE_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0s_a = vec4(readtex0.a); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1s_a = vec4(readtex1.a); \n"); break; case GR_CMBX_LOCAL_TEXTURE_RGB: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0s_a = readtex0; \n"); else strcat(fragment_shader_texture1, "vec4 ctex1s_a = readtex1; \n"); break; case GR_CMBX_OTHER_TEXTURE_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0s_a = vec4(0.0); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1s_a = vec4(ctexture0.a); \n"); break; case GR_CMBX_OTHER_TEXTURE_RGB: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0s_a = vec4(0.0); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1s_a = ctexture0; \n"); break; case GR_CMBX_TMU_CCOLOR: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0s_a = ccolor0; \n"); else strcat(fragment_shader_texture1, "vec4 ctex1s_a = ccolor1; \n"); break; case GR_CMBX_TMU_CALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0s_a = vec4(ccolor0.a); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1s_a = vec4(ccolor1.a); \n"); break; default: display_warning("grTexColorCombineExt : a = %x", a); if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0s_a = vec4(0.0); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1s_a = vec4(0.0); \n"); } switch(a_mode) { case GR_FUNC_MODE_ZERO: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_a = vec4(0.0); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_a = vec4(0.0); \n"); break; case GR_FUNC_MODE_X: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_a = ctex0s_a; \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_a = ctex1s_a; \n"); break; case GR_FUNC_MODE_ONE_MINUS_X: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_a = vec4(1.0) - ctex0s_a; \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_a = vec4(1.0) - ctex1s_a; \n"); break; case GR_FUNC_MODE_NEGATIVE_X: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_a = -ctex0s_a; \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_a = -ctex1s_a; \n"); break; default: display_warning("grTexColorCombineExt : a_mode = %x", a_mode); if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_a = vec4(0.0); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_a = vec4(0.0); \n"); } switch(b) { case GR_CMBX_ZERO: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0s_b = vec4(0.0); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1s_b = vec4(0.0); \n"); break; case GR_CMBX_ITALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0s_b = vec4(gl_Color.a); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1s_b = vec4(gl_Color.a); \n"); break; case GR_CMBX_ITRGB: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0s_b = gl_Color; \n"); else strcat(fragment_shader_texture1, "vec4 ctex1s_b = gl_Color; \n"); break; case GR_CMBX_LOCAL_TEXTURE_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0s_b = vec4(readtex0.a); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1s_b = vec4(readtex1.a); \n"); break; case GR_CMBX_LOCAL_TEXTURE_RGB: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0s_b = readtex0; \n"); else strcat(fragment_shader_texture1, "vec4 ctex1s_b = readtex1; \n"); break; case GR_CMBX_OTHER_TEXTURE_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0s_b = vec4(0.0); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1s_b = vec4(ctexture0.a); \n"); break; case GR_CMBX_OTHER_TEXTURE_RGB: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0s_b = vec4(0.0); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1s_b = ctexture0; \n"); break; case GR_CMBX_TMU_CALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0s_b = vec4(ccolor0.a); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1s_b = vec4(ccolor1.a); \n"); break; case GR_CMBX_TMU_CCOLOR: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0s_b = ccolor0; \n"); else strcat(fragment_shader_texture1, "vec4 ctex1s_b = ccolor1; \n"); break; default: display_warning("grTexColorCombineExt : b = %x", b); if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0s_b = vec4(0.0); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1s_b = vec4(0.0); \n"); } switch(b_mode) { case GR_FUNC_MODE_ZERO: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_b = vec4(0.0); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_b = vec4(0.0); \n"); break; case GR_FUNC_MODE_X: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_b = ctex0s_b; \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_b = ctex1s_b; \n"); break; case GR_FUNC_MODE_ONE_MINUS_X: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_b = vec4(1.0) - ctex0s_b; \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_b = vec4(1.0) - ctex1s_b; \n"); break; case GR_FUNC_MODE_NEGATIVE_X: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_b = -ctex0s_b; \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_b = -ctex1s_b; \n"); break; default: display_warning("grTexColorCombineExt : b_mode = %x", b_mode); if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_b = vec4(0.0); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_b = vec4(0.0); \n"); } switch(c) { case GR_CMBX_ZERO: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_c = vec4(0.0); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_c = vec4(0.0); \n"); break; case GR_CMBX_B: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_c = ctex0s_b; \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_c = ctex1s_b; \n"); break; case GR_CMBX_DETAIL_FACTOR: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_c = vec4(lambda); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_c = vec4(lambda); \n"); break; case GR_CMBX_ITRGB: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_c = gl_Color; \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_c = gl_Color; \n"); break; case GR_CMBX_ITALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_c = vec4(gl_Color.a); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_c = vec4(gl_Color.a); \n"); break; case GR_CMBX_LOCAL_TEXTURE_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_c = vec4(readtex0.a); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_c = vec4(readtex1.a); \n"); break; case GR_CMBX_LOCAL_TEXTURE_RGB: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_c = readtex0; \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_c = readtex1; \n"); break; case GR_CMBX_OTHER_TEXTURE_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_c = vec4(0.0); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_c = vec4(ctexture0.a); \n"); break; case GR_CMBX_OTHER_TEXTURE_RGB: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_c = vec4(0.0); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_c = ctexture0; \n"); break; case GR_CMBX_TMU_CALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_c = vec4(ccolor0.a); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_c = vec4(ccolor1.a); \n"); break; case GR_CMBX_TMU_CCOLOR: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_c = ccolor0; \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_c = ccolor1; \n"); break; default: display_warning("grTexColorCombineExt : c = %x", c); if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_c = vec4(0.0); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_c = vec4(0.0); \n"); } if(c_invert) { if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_c = vec4(1.0) - ctex0_c; \n"); else strcat(fragment_shader_texture1, "ctex1_c = vec4(1.0) - ctex1_c; \n"); } switch(d) { case GR_CMBX_ZERO: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_d = vec4(0.0); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_d = vec4(0.0); \n"); break; case GR_CMBX_B: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_d = ctex0s_b; \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_d = ctex1s_b; \n"); break; case GR_CMBX_ITRGB: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_d = gl_Color; \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_d = gl_Color; \n"); break; case GR_CMBX_LOCAL_TEXTURE_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_d = vec4(readtex0.a); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_d = vec4(readtex1.a); \n"); break; default: display_warning("grTexColorCombineExt : d = %x", d); if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctex0_d = vec4(0.0); \n"); else strcat(fragment_shader_texture1, "vec4 ctex1_d = vec4(0.0); \n"); } if(d_invert) { if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_d = vec4(1.0) - ctex0_d; \n"); else strcat(fragment_shader_texture1, "ctex1_d = vec4(1.0) - ctex1_d; \n"); } if(num_tex == 0) strcat(fragment_shader_texture0, "vec4 ctexture0 = (ctex0_a + ctex0_b) * ctex0_c + ctex0_d; \n"); else strcat(fragment_shader_texture1, "vec4 ctexture1 = (ctex1_a + ctex1_b) * ctex1_c + ctex1_d; \n"); need_to_compile = 1; } FX_ENTRY void FX_CALL grTexAlphaCombineExt(GrChipID_t tmu, GrTACUColor_t a, GrCombineMode_t a_mode, GrTACUColor_t b, GrCombineMode_t b_mode, GrTACUColor_t c, FxBool c_invert, GrTACUColor_t d, FxBool d_invert, FxU32 shift, FxBool invert) { int num_tex; WriteLog(M64MSG_VERBOSE, "grTexAlphaCombineExt(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)\r\n", tmu, a, a_mode, b, b_mode, c, c_invert, d, d_invert, shift, invert); if (invert) display_warning("grTexAlphaCombineExt : inverted result"); if (shift) display_warning("grTexAlphaCombineExt : shift = %d", shift); if (tmu == GR_TMU0) num_tex = 1; else num_tex = 0; if(num_tex == 0) { texture0_combinera_key = 0x80000000 | (a & 0x1F) | ((a_mode & 3) << 5) | ((b & 0x1F) << 7) | ((b_mode & 3) << 12) | ((c & 0x1F) << 14) | ((c_invert & 1) << 19) | ((d & 0x1F) << 20) | ((d_invert & 1) << 25); } else { texture1_combinera_key = 0x80000000 | (a & 0x1F) | ((a_mode & 3) << 5) | ((b & 0x1F) << 7) | ((b_mode & 3) << 12) | ((c & 0x1F) << 14) | ((c_invert & 1) << 19) | ((d & 0x1F) << 20) | ((d_invert & 1) << 25); } switch(a) { case GR_CMBX_ITALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0s_a.a = gl_Color.a; \n"); else strcat(fragment_shader_texture1, "ctex1s_a.a = gl_Color.a; \n"); break; case GR_CMBX_LOCAL_TEXTURE_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0s_a.a = readtex0.a; \n"); else strcat(fragment_shader_texture1, "ctex1s_a.a = readtex1.a; \n"); break; case GR_CMBX_OTHER_TEXTURE_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0s_a.a = 0.0; \n"); else strcat(fragment_shader_texture1, "ctex1s_a.a = ctexture0.a; \n"); break; case GR_CMBX_TMU_CALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0s_a.a = ccolor0.a; \n"); else strcat(fragment_shader_texture1, "ctex1s_a.a = ccolor1.a; \n"); break; default: display_warning("grTexAlphaCombineExt : a = %x", a); if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0s_a.a = 0.0; \n"); else strcat(fragment_shader_texture1, "ctex1s_a.a = 0.0; \n"); } switch(a_mode) { case GR_FUNC_MODE_ZERO: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_a.a = 0.0; \n"); else strcat(fragment_shader_texture1, "ctex1_a.a = 0.0; \n"); break; case GR_FUNC_MODE_X: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_a.a = ctex0s_a.a; \n"); else strcat(fragment_shader_texture1, "ctex1_a.a = ctex1s_a.a; \n"); break; case GR_FUNC_MODE_ONE_MINUS_X: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_a.a = 1.0 - ctex0s_a.a; \n"); else strcat(fragment_shader_texture1, "ctex1_a.a = 1.0 - ctex1s_a.a; \n"); break; case GR_FUNC_MODE_NEGATIVE_X: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_a.a = -ctex0s_a.a; \n"); else strcat(fragment_shader_texture1, "ctex1_a.a = -ctex1s_a.a; \n"); break; default: display_warning("grTexAlphaCombineExt : a_mode = %x", a_mode); if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_a.a = 0.0; \n"); else strcat(fragment_shader_texture1, "ctex1_a.a = 0.0; \n"); } switch(b) { case GR_CMBX_ITALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0s_b.a = gl_Color.a; \n"); else strcat(fragment_shader_texture1, "ctex1s_b.a = gl_Color.a; \n"); break; case GR_CMBX_LOCAL_TEXTURE_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0s_b.a = readtex0.a; \n"); else strcat(fragment_shader_texture1, "ctex1s_b.a = readtex1.a; \n"); break; case GR_CMBX_OTHER_TEXTURE_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0s_b.a = 0.0; \n"); else strcat(fragment_shader_texture1, "ctex1s_b.a = ctexture0.a; \n"); break; case GR_CMBX_TMU_CALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0s_b.a = ccolor0.a; \n"); else strcat(fragment_shader_texture1, "ctex1s_b.a = ccolor1.a; \n"); break; default: display_warning("grTexAlphaCombineExt : b = %x", b); if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0s_b.a = 0.0; \n"); else strcat(fragment_shader_texture1, "ctex1s_b.a = 0.0; \n"); } switch(b_mode) { case GR_FUNC_MODE_ZERO: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_b.a = 0.0; \n"); else strcat(fragment_shader_texture1, "ctex1_b.a = 0.0; \n"); break; case GR_FUNC_MODE_X: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_b.a = ctex0s_b.a; \n"); else strcat(fragment_shader_texture1, "ctex1_b.a = ctex1s_b.a; \n"); break; case GR_FUNC_MODE_ONE_MINUS_X: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_b.a = 1.0 - ctex0s_b.a; \n"); else strcat(fragment_shader_texture1, "ctex1_b.a = 1.0 - ctex1s_b.a; \n"); break; case GR_FUNC_MODE_NEGATIVE_X: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_b.a = -ctex0s_b.a; \n"); else strcat(fragment_shader_texture1, "ctex1_b.a = -ctex1s_b.a; \n"); break; default: display_warning("grTexAlphaCombineExt : b_mode = %x", b_mode); if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_b.a = 0.0; \n"); else strcat(fragment_shader_texture1, "ctex1_b.a = 0.0; \n"); } switch(c) { case GR_CMBX_ZERO: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_c.a = 0.0; \n"); else strcat(fragment_shader_texture1, "ctex1_c.a = 0.0; \n"); break; case GR_CMBX_B: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_c.a = ctex0s_b.a; \n"); else strcat(fragment_shader_texture1, "ctex1_c.a = ctex1s_b.a; \n"); break; case GR_CMBX_DETAIL_FACTOR: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_c.a = lambda; \n"); else strcat(fragment_shader_texture1, "ctex1_c.a = lambda; \n"); break; case GR_CMBX_ITALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_c.a = gl_Color.a; \n"); else strcat(fragment_shader_texture1, "ctex1_c.a = gl_Color.a; \n"); break; case GR_CMBX_LOCAL_TEXTURE_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_c.a = readtex0.a; \n"); else strcat(fragment_shader_texture1, "ctex1_c.a = readtex1.a; \n"); break; case GR_CMBX_OTHER_TEXTURE_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_c.a = 0.0; \n"); else strcat(fragment_shader_texture1, "ctex1_c.a = ctexture0.a; \n"); break; case GR_CMBX_TMU_CALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_c.a = ccolor0.a; \n"); else strcat(fragment_shader_texture1, "ctex1_c.a = ccolor1.a; \n"); break; default: display_warning("grTexAlphaCombineExt : c = %x", c); if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_c.a = 0.0; \n"); else strcat(fragment_shader_texture1, "ctex1_c.a = 0.0; \n"); } if(c_invert) { if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_c.a = 1.0 - ctex0_c.a; \n"); else strcat(fragment_shader_texture1, "ctex1_c.a = 1.0 - ctex1_c.a; \n"); } switch(d) { case GR_CMBX_ZERO: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_d.a = 0.0; \n"); else strcat(fragment_shader_texture1, "ctex1_d.a = 0.0; \n"); break; case GR_CMBX_B: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_d.a = ctex0s_b.a; \n"); else strcat(fragment_shader_texture1, "ctex1_d.a = ctex1s_b.a; \n"); break; case GR_CMBX_ITALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_d.a = gl_Color.a; \n"); else strcat(fragment_shader_texture1, "ctex1_d.a = gl_Color.a; \n"); break; case GR_CMBX_ITRGB: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_d.a = gl_Color.a; \n"); else strcat(fragment_shader_texture1, "ctex1_d.a = gl_Color.a; \n"); break; case GR_CMBX_LOCAL_TEXTURE_ALPHA: if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_d.a = readtex0.a; \n"); else strcat(fragment_shader_texture1, "ctex1_d.a = readtex1.a; \n"); break; default: display_warning("grTexAlphaCombineExt : d = %x", d); if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_d.a = 0.0; \n"); else strcat(fragment_shader_texture1, "ctex1_d.a = 0.0; \n"); } if(d_invert) { if(num_tex == 0) strcat(fragment_shader_texture0, "ctex0_d.a = 1.0 - ctex0_d.a; \n"); else strcat(fragment_shader_texture1, "ctex1_d.a = 1.0 - ctex1_d.a; \n"); } if(num_tex == 0) strcat(fragment_shader_texture0, "ctexture0.a = (ctex0_a.a + ctex0_b.a) * ctex0_c.a + ctex0_d.a; \n"); else strcat(fragment_shader_texture1, "ctexture1.a = (ctex1_a.a + ctex1_b.a) * ctex1_c.a + ctex1_d.a; \n"); need_to_compile = 1; } FX_ENTRY void FX_CALL grConstantColorValueExt(GrChipID_t tmu, GrColor_t value) { int num_tex; WriteLog(M64MSG_VERBOSE, "grConstantColorValueExt(%d,%d)\r\n", tmu, value); if (tmu == GR_TMU0) num_tex = 1; else num_tex = 0; switch(lfb_color_fmt) { case GR_COLORFORMAT_ARGB: if(num_tex == 0) { ccolor0[3] = ((value >> 24) & 0xFF) / 255.0f; ccolor0[0] = ((value >> 16) & 0xFF) / 255.0f; ccolor0[1] = ((value >> 8) & 0xFF) / 255.0f; ccolor0[2] = (value & 0xFF) / 255.0f; } else { ccolor1[3] = ((value >> 24) & 0xFF) / 255.0f; ccolor1[0] = ((value >> 16) & 0xFF) / 255.0f; ccolor1[1] = ((value >> 8) & 0xFF) / 255.0f; ccolor1[2] = (value & 0xFF) / 255.0f; } break; case GR_COLORFORMAT_RGBA: if(num_tex == 0) { ccolor0[0] = ((value >> 24) & 0xFF) / 255.0f; ccolor0[1] = ((value >> 16) & 0xFF) / 255.0f; ccolor0[2] = ((value >> 8) & 0xFF) / 255.0f; ccolor0[3] = (value & 0xFF) / 255.0f; } else { ccolor1[0] = ((value >> 24) & 0xFF) / 255.0f; ccolor1[1] = ((value >> 16) & 0xFF) / 255.0f; ccolor1[2] = ((value >> 8) & 0xFF) / 255.0f; ccolor1[3] = (value & 0xFF) / 255.0f; } break; default: display_warning("grConstantColorValue: unknown color format : %x", lfb_color_fmt); } if(num_tex == 0) { ccolor0_location = glGetUniformLocationARB(program_object, "ccolor0"); glUniform4fARB(ccolor0_location, ccolor0[0], ccolor0[1], ccolor0[2], ccolor0[3]); } else { ccolor1_location = glGetUniformLocationARB(program_object, "ccolor1"); glUniform4fARB(ccolor1_location, ccolor1[0], ccolor1[1], ccolor1[2], ccolor1[3]); } } mupen64plus-video-glide64-src-2.6.0/src/wrapper/config.cpp000066400000000000000000000043721464507525600233120ustar00rootroot00000000000000/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus - glide64/wrapper/config.cpp * * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2005-2006 Hacktarux * * * * 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 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include "glide.h" #include "main.h" #include "../winlnxdefs.h" typedef struct _wrapper_config { int res; int filter; int disable_glsl; int disable_dithered_alpha; int FBO; int disable_auxbuf; } wrapper_config; FX_ENTRY void FX_CALL grConfigWrapperExt(HINSTANCE instance, HWND hwnd) { } #include "../rdp.h" FX_ENTRY GrScreenResolution_t FX_CALL grWrapperFullScreenResolutionExt(void) { return settings.full_res; } int getFilter() { return settings.tex_filter; } int getDisableDitheredAlpha() { return settings.noditheredalpha; } int getEnableFBO() { return settings.FBO; } int getDisableAuxbuf() { return settings.disable_auxbuf; } int getDisableGLSL() { return settings.noglsl; } mupen64plus-video-glide64-src-2.6.0/src/wrapper/filter.cpp000066400000000000000000000423531464507525600233330ustar00rootroot00000000000000/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus - glide64/wrapper/filter.cpp * * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2005-2006 Hacktarux * * * * 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 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include "../winlnxdefs.h" #include "main.h" #include "2xsai.h" // this filter is crap, it's just some stuffs i tried to see what they're doing // it's blurring texture edges which is good for some textures, bad for some others. unsigned char *blur_edges(unsigned char *source, int width, int height, int *width2, int *height2) { unsigned char *result, *temp, *temp2; signed char mx[3*3] = {-1, 0, 1, -2, 0, 2, -1, 0, 1}; signed char my[3*3] = {-1, -2, -1, 0, 0, 0, 1, 2 ,1}; int i,j; *width2 = width*2; *height2 = height*2; result = (unsigned char*)malloc(width*2*height*2*4); temp = (unsigned char*)malloc(width*2*height*2*4); temp2 = (unsigned char*)malloc(width*2*height*2*4); // size * 2 for (j=0; j>1; temp[j*2*width*2*4 + (i*2+1)*4 + 1] = ((int)source[j*width*4 + i*4 + 1] + (int)source[j*width*4 + (i+1)*4 + 1])>>1; temp[j*2*width*2*4 + (i*2+1)*4 + 2] = ((int)source[j*width*4 + i*4 + 2] + (int)source[j*width*4 + (i+1)*4 + 2])>>1; temp[j*2*width*2*4 + (i*2+1)*4 + 3] = ((int)source[j*width*4 + i*4 + 3] + (int)source[j*width*4 + (i+1)*4 + 3])>>1; } else { temp[j*2*width*2*4 + (i*2+1)*4 + 0] = temp[j*2*width*2*4 + i*2*4 + 0]; temp[j*2*width*2*4 + (i*2+1)*4 + 1] = temp[j*2*width*2*4 + i*2*4 + 1]; temp[j*2*width*2*4 + (i*2+1)*4 + 2] = temp[j*2*width*2*4 + i*2*4 + 2]; temp[j*2*width*2*4 + (i*2+1)*4 + 3] = temp[j*2*width*2*4 + i*2*4 + 3]; } if (j < (height-1)) { temp[(j*2+1)*width*2*4 + i*2*4 + 0] = ((int)source[j*width*4 + i*4 + 0] + (int)source[(j+1)*width*4 + i*4 + 0])>>1; temp[(j*2+1)*width*2*4 + i*2*4 + 1] = ((int)source[j*width*4 + i*4 + 1] + (int)source[(j+1)*width*4 + i*4 + 1])>>1; temp[(j*2+1)*width*2*4 + i*2*4 + 2] = ((int)source[j*width*4 + i*4 + 2] + (int)source[(j+1)*width*4 + i*4 + 2])>>1; temp[(j*2+1)*width*2*4 + i*2*4 + 3] = ((int)source[j*width*4 + i*4 + 3] + (int)source[(j+1)*width*4 + i*4 + 3])>>1; if (i < (width-1)) { temp[(j*2+1)*width*2*4 + (i*2+1)*4 + 0] = ((int)source[j*width*4 + i*4 + 0] + (int)source[(j+1)*width*4 + (i+1)*4 + 0])>>1; temp[(j*2+1)*width*2*4 + (i*2+1)*4 + 1] = ((int)source[j*width*4 + i*4 + 1] + (int)source[(j+1)*width*4 + (i+1)*4 + 1])>>1; temp[(j*2+1)*width*2*4 + (i*2+1)*4 + 2] = ((int)source[j*width*4 + i*4 + 2] + (int)source[(j+1)*width*4 + (i+1)*4 + 2])>>1; temp[(j*2+1)*width*2*4 + (i*2+1)*4 + 3] = ((int)source[j*width*4 + i*4 + 3] + (int)source[(j+1)*width*4 + (i+1)*4 + 3])>>1; } else { temp[(j*2+1)*width*2*4 + (i*2+1)*4 + 0] = temp[j*2*width*2*4 + i*2*4 + 0]; temp[(j*2+1)*width*2*4 + (i*2+1)*4 + 1] = temp[j*2*width*2*4 + i*2*4 + 1]; temp[(j*2+1)*width*2*4 + (i*2+1)*4 + 2] = temp[j*2*width*2*4 + i*2*4 + 2]; temp[(j*2+1)*width*2*4 + (i*2+1)*4 + 3] = temp[j*2*width*2*4 + i*2*4 + 3]; } } else { temp[(j*2+1)*width*2*4 + i*2*4 + 0] = temp[j*2*width*2*4 + i*2*4 + 0]; temp[(j*2+1)*width*2*4 + i*2*4 + 1] = temp[j*2*width*2*4 + i*2*4 + 1]; temp[(j*2+1)*width*2*4 + i*2*4 + 2] = temp[j*2*width*2*4 + i*2*4 + 2]; temp[(j*2+1)*width*2*4 + i*2*4 + 3] = temp[j*2*width*2*4 + i*2*4 + 3]; temp[(j*2+1)*width*2*4 + (i*2+1)*4 + 0] = temp[j*2*width*2*4 + i*2*4 + 0]; temp[(j*2+1)*width*2*4 + (i*2+1)*4 + 1] = temp[j*2*width*2*4 + i*2*4 + 1]; temp[(j*2+1)*width*2*4 + (i*2+1)*4 + 2] = temp[j*2*width*2*4 + i*2*4 + 2]; temp[(j*2+1)*width*2*4 + (i*2+1)*4 + 3] = temp[j*2*width*2*4 + i*2*4 + 3]; } } } // gradient for (j=0; j #include #include #ifdef __cplusplus extern "C" { #endif /* ** ----------------------------------------------------------------------- ** TYPE DEFINITIONS ** ----------------------------------------------------------------------- */ /* ** ----------------------------------------------------------------------- ** CONSTANTS AND TYPES ** ----------------------------------------------------------------------- */ /* * gregk 5/3/99 * Constants defined for SSTH3_ALPHADITHERMODE registry key */ #define OPTIMAL 1 #define SHARPER 2 #define SMOOTHER 3 /* tbext */ #define GR_BUFFER_TEXTUREBUFFER_EXT 0x6 #define GR_BUFFER_TEXTUREAUXBUFFER_EXT 0x7 typedef FxU32 GrPixelFormat_t; #define GR_PIXFMT_I_8 0x0001 #define GR_PIXFMT_AI_88 0x0002 #define GR_PIXFMT_RGB_565 0x0003 #define GR_PIXFMT_ARGB_1555 0x0004 #define GR_PIXFMT_ARGB_8888 0x0005 #define GR_PIXFMT_AA_2_RGB_565 0x0006 #define GR_PIXFMT_AA_2_ARGB_1555 0x0007 #define GR_PIXFMT_AA_2_ARGB_8888 0x0008 #define GR_PIXFMT_AA_4_RGB_565 0x0009 #define GR_PIXFMT_AA_4_ARGB_1555 0x000a #define GR_PIXFMT_AA_4_ARGB_8888 0x000b #define GR_PIXFMT_AA_8_RGB_565 0x000c /* 8xaa */ #define GR_PIXFMT_AA_8_ARGB_1555 0x000d #define GR_PIXFMT_AA_8_ARGB_8888 0x000e #define GR_LFBWRITEMODE_Z32 0x0008 typedef FxU32 GrAAMode_t; #define GR_AA_NONE 0x0000 #define GR_AA_4SAMPLES 0x0001 typedef FxU8 GrStencil_t; typedef FxU32 GrStencilOp_t; #define GR_STENCILOP_KEEP 0x00 /* keep current value */ #define GR_STENCILOP_ZERO 0x01 /* set to zero */ #define GR_STENCILOP_REPLACE 0x02 /* replace with reference value */ #define GR_STENCILOP_INCR_CLAMP 0x03 /* increment - clamp */ #define GR_STENCILOP_DECR_CLAMP 0x04 /* decrement - clamp */ #define GR_STENCILOP_INVERT 0x05 /* bitwise inversion */ #define GR_STENCILOP_INCR_WRAP 0x06 /* increment - wrap */ #define GR_STENCILOP_DECR_WRAP 0x07 /* decrement - wrap */ #define GR_TEXTURE_UMA_EXT 0x06 #define GR_STENCIL_MODE_EXT 0x07 #define GR_OPENGL_MODE_EXT 0x08 typedef FxU32 GrCCUColor_t; typedef FxU32 GrACUColor_t; typedef FxU32 GrTCCUColor_t; typedef FxU32 GrTACUColor_t; #define GR_CMBX_ZERO 0x00 #define GR_CMBX_TEXTURE_ALPHA 0x01 #define GR_CMBX_ALOCAL 0x02 #define GR_CMBX_AOTHER 0x03 #define GR_CMBX_B 0x04 #define GR_CMBX_CONSTANT_ALPHA 0x05 #define GR_CMBX_CONSTANT_COLOR 0x06 #define GR_CMBX_DETAIL_FACTOR 0x07 #define GR_CMBX_ITALPHA 0x08 #define GR_CMBX_ITRGB 0x09 #define GR_CMBX_LOCAL_TEXTURE_ALPHA 0x0a #define GR_CMBX_LOCAL_TEXTURE_RGB 0x0b #define GR_CMBX_LOD_FRAC 0x0c #define GR_CMBX_OTHER_TEXTURE_ALPHA 0x0d #define GR_CMBX_OTHER_TEXTURE_RGB 0x0e #define GR_CMBX_TEXTURE_RGB 0x0f #define GR_CMBX_TMU_CALPHA 0x10 #define GR_CMBX_TMU_CCOLOR 0x11 typedef FxU32 GrCombineMode_t; #define GR_FUNC_MODE_ZERO 0x00 #define GR_FUNC_MODE_X 0x01 #define GR_FUNC_MODE_ONE_MINUS_X 0x02 #define GR_FUNC_MODE_NEGATIVE_X 0x03 #define GR_FUNC_MODE_X_MINUS_HALF 0x04 typedef FxU32 GrAlphaBlendOp_t; #define GR_BLEND_OP_ADD 0x00 #define GR_BLEND_OP_SUB 0x01 #define GR_BLEND_OP_REVSUB 0x02 #define GR_BLEND_SAME_COLOR_EXT 0x08 #define GR_BLEND_ONE_MINUS_SAME_COLOR_EXT 0x09 /* Napalm extensions to GrTextureFormat_t */ #define GR_TEXFMT_ARGB_CMP_FXT1 0x11 #define GR_TEXFMT_ARGB_8888 0x12 #define GR_TEXFMT_YUYV_422 0x13 #define GR_TEXFMT_UYVY_422 0x14 #define GR_TEXFMT_AYUV_444 0x15 #define GR_TEXFMT_ARGB_CMP_DXT1 0x16 #define GR_TEXFMT_ARGB_CMP_DXT2 0x17 #define GR_TEXFMT_ARGB_CMP_DXT3 0x18 #define GR_TEXFMT_ARGB_CMP_DXT4 0x19 #define GR_TEXFMT_ARGB_CMP_DXT5 0x1A #define GR_TEXTFMT_RGB_888 0xFF /* Napalm extensions to GrLOD_t */ #define GR_LOD_LOG2_2048 0xb #define GR_LOD_LOG2_1024 0xa #define GR_LOD_LOG2_512 0x9 /* Napalm extensions to GrTexBaseRange_t */ #define GR_TEXBASE_2048 0x7 #define GR_TEXBASE_1024 0x6 #define GR_TEXBASE_512 0x5 #define GR_TEXBASE_256_TO_1 0x4 #ifdef __cplusplus } #endif #include #endif /* __H3EXT_H__ */ mupen64plus-video-glide64-src-2.6.0/src/wrapper/geometry.cpp000066400000000000000000000701761464507525600237050ustar00rootroot00000000000000/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus - glide64/wrapper/geometry.cpp * * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2005-2006 Hacktarux * * * * 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 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include "glide.h" #include "main.h" #define Z_MAX (65536.0f) //#define Z_MAX 1000.0f static int xy_off; static int xy_en; static int z_en; static int z_off; static int q_off; static int q_en; static int pargb_off; static int pargb_en; static int st0_off; static int st0_en; static int st1_off; static int st1_en; static int fog_ext_off; static int fog_ext_en; int w_buffer_mode; int inverted_culling; int culling_mode; //static float depth_bias; inline float ZCALC(const float & z, const float & q) { //float res = z_en ? ((z) / Z_MAX) / (q-(float)depth_bias*q*q*zscale*2/128.0f) : 1.0f; //float res = z_en ? ((z) / Z_MAX) / (q-(float)depth_bias*zscale*9/255000000.0f) : 1.0f; float res = z_en ? ((z) / Z_MAX) / (q) : 1.0f; return res; } #define zclamp (1.0f-1.0f/zscale) static inline void zclamp_glVertex4f(float a, float b, float c, float d) { if (c float biasFactor = 0; void FindBestDepthBias() { float f, bestz = 0.25f; int x; if (biasFactor) return; biasFactor = 64.0f; // default value glPushAttrib(GL_ALL_ATTRIB_BITS); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_ALWAYS); glEnable(GL_POLYGON_OFFSET_FILL); glDrawBuffer(GL_BACK); glReadBuffer(GL_BACK); glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); glColor4ub(255,255,255,255); glDepthMask(GL_TRUE); for (x=0, f=1.0f; f<=65536.0f; x+=4, f*=2.0f) { float z; glPolygonOffset(0, f); glBegin(GL_TRIANGLE_STRIP); glVertex3f(float(x+4 - widtho)/(width/2), float(0 - heighto)/(height/2), 0.5); glVertex3f(float(x - widtho)/(width/2), float(0 - heighto)/(height/2), 0.5); glVertex3f(float(x+4 - widtho)/(width/2), float(4 - heighto)/(height/2), 0.5); glVertex3f(float(x - widtho)/(width/2), float(4 - heighto)/(height/2), 0.5); glEnd(); glReadPixels(x+2, 2+viewport_offset, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z); z -= 0.75f + 8e-6f; if (z<0.0f) z = -z; if (z < bestz) { bestz = z; biasFactor = f; } WriteLog(M64MSG_VERBOSE, "f %g z %g\n", f, z); } WriteLog(M64MSG_INFO, " --> bias factor %g\n", biasFactor); glPopAttrib(); // SDL_GL_SwapBuffers(); // getchar(); } FX_ENTRY void FX_CALL grDepthBiasLevel( FxI32 level ) { WriteLog(M64MSG_VERBOSE, "grDepthBiasLevel(%d)\r\n", level); //depth_bias = level; if (level) { if(w_buffer_mode) glPolygonOffset(1.0f, -(float)level*zscale/255.0f); else glPolygonOffset(0, (float)level*biasFactor); //glPolygonOffset(0, (float)level*128.0f*zscale/2); glEnable(GL_POLYGON_OFFSET_FILL); } else { glPolygonOffset(0,0); glDisable(GL_POLYGON_OFFSET_FILL); } } // draw FX_ENTRY void FX_CALL grDrawTriangle( const void *a, const void *b, const void *c ) { float *a_x = (float*)a + xy_off/sizeof(float); float *a_y = (float*)a + xy_off/sizeof(float) + 1; float *a_z = (float*)a + z_off/sizeof(float); float *a_q = (float*)a + q_off/sizeof(float); unsigned char *a_pargb = (unsigned char*)a + pargb_off; float *a_s0 = (float*)a + st0_off/sizeof(float); float *a_t0 = (float*)a + st0_off/sizeof(float) + 1; float *a_s1 = (float*)a + st1_off/sizeof(float); float *a_t1 = (float*)a + st1_off/sizeof(float) + 1; float *a_fog = (float*)a + fog_ext_off/sizeof(float); float *b_x = (float*)b + xy_off/sizeof(float); float *b_y = (float*)b + xy_off/sizeof(float) + 1; float *b_z = (float*)b + z_off/sizeof(float); float *b_q = (float*)b + q_off/sizeof(float); unsigned char *b_pargb = (unsigned char*)b + pargb_off; float *b_s0 = (float*)b + st0_off/sizeof(float); float *b_t0 = (float*)b + st0_off/sizeof(float) + 1; float *b_s1 = (float*)b + st1_off/sizeof(float); float *b_t1 = (float*)b + st1_off/sizeof(float) + 1; float *b_fog = (float*)b + fog_ext_off/sizeof(float); float *c_x = (float*)c + xy_off/sizeof(float); float *c_y = (float*)c + xy_off/sizeof(float) + 1; float *c_z = (float*)c + z_off/sizeof(float); float *c_q = (float*)c + q_off/sizeof(float); unsigned char *c_pargb = (unsigned char*)c + pargb_off; float *c_s0 = (float*)c + st0_off/sizeof(float); float *c_t0 = (float*)c + st0_off/sizeof(float) + 1; float *c_s1 = (float*)c + st1_off/sizeof(float); float *c_t1 = (float*)c + st1_off/sizeof(float) + 1; float *c_fog = (float*)c + fog_ext_off/sizeof(float); WriteLog(M64MSG_VERBOSE, "grDrawTriangle()\r\n"); //if(*a_fog == 0.0f) *a_fog = 1.0f; //if(*b_fog == 0.0f) *b_fog = 1.0f; //if(*c_fog == 0.0f) *c_fog = 1.0f; // ugly ? i know but nvidia drivers are losing the viewport otherwise if(!render_to_texture && viewport_width) { glViewport(0, viewport_offset, viewport_width, viewport_height); viewport_width=0; } reloadTexture(); if(glsl_support && need_to_compile) compile_shader(); glBegin(GL_TRIANGLES); if (nbTextureUnits > 2) { if (st0_en) glMultiTexCoord2fARB(GL_TEXTURE1_ARB, *a_s0 / *a_q / (float)tex1_width, ytex(0, *a_t0 / *a_q / (float)tex1_height)); if (st1_en) glMultiTexCoord2fARB(GL_TEXTURE0_ARB, *a_s1 / *a_q / (float)tex0_width, ytex(1, *a_t1 / *a_q / (float)tex0_height)); } else { if (st0_en) glTexCoord2f(*a_s0 / *a_q / (float)tex0_width, ytex(0, *a_t0 / *a_q / (float)tex0_height)); } if (pargb_en) glColor4f(a_pargb[2]/255.0f, a_pargb[1]/255.0f, a_pargb[0]/255.0f, a_pargb[3]/255.0f); if (fog_enabled && fog_coord_support) { if(!glsl_support) { if(!fog_ext_en || fog_enabled != 2) glFogCoordfEXT((1.0f / *a_q)/*/256.0f*/); else glFogCoordfEXT((1.0f / *a_fog)/*/256.0f*/); } else { if(!fog_ext_en || fog_enabled != 2) glSecondaryColor3f((1.0f / *a_q) / 255.0f, 0.0f, 0.0f); else glSecondaryColor3f((1.0f / *a_fog) / 255.0f, 0.0f, 0.0f); /*if(!fog_ext_en || fog_enabled != 2) glFogCoordfEXT((1.0f / *a_q)/255.0f); else glFogCoordfEXT((1.0f / *a_fog)/255.0f);*/ } } glVertex4f((*a_x - (float)widtho) / (float)(width/2) / *a_q, -(*a_y - (float)heighto) / (float)(height/2) / *a_q, ZCALC(*a_z, *a_q), 1.0f / *a_q); if (nbTextureUnits > 2) { if (st0_en) glMultiTexCoord2fARB(GL_TEXTURE1_ARB, *b_s0 / *b_q / (float)tex1_width, ytex(0, *b_t0 / *b_q / (float)tex1_height)); if (st1_en) glMultiTexCoord2fARB(GL_TEXTURE0_ARB, *b_s1 / *b_q / (float)tex0_width, ytex(1, *b_t1 / *b_q / (float)tex0_height)); } else { if (st0_en) glTexCoord2f(*b_s0 / *b_q / (float)tex0_width, ytex(0, *b_t0 / *b_q / (float)tex0_height)); } if (pargb_en) glColor4f(b_pargb[2]/255.0f, b_pargb[1]/255.0f, b_pargb[0]/255.0f, b_pargb[3]/255.0f); if (fog_enabled && fog_coord_support) { if(!glsl_support) { if(!fog_ext_en || fog_enabled != 2) glFogCoordfEXT((1.0f / *b_q)/*/256.0f*/); else glFogCoordfEXT((1.0f / *b_fog)/*/256.0f*/); } else { if(!fog_ext_en || fog_enabled != 2) glSecondaryColor3f((1.0f / *b_q) / 255.0f, 0.0f, 0.0f); else glSecondaryColor3f((1.0f / *b_fog) / 255.0f, 0.0f, 0.0f); /*if(!fog_ext_en || fog_enabled != 2) glFogCoordfEXT((1.0f / *b_q)/255.0f); else glFogCoordfEXT((1.0f / *b_fog)/255.0f);*/ } } glVertex4f((*b_x - (float)widtho) / (float)(width/2) / *b_q, -(*b_y - (float)heighto) / (float)(height/2) / *b_q, ZCALC(*b_z, *b_q), 1.0f / *b_q); if (nbTextureUnits > 2) { if (st0_en) glMultiTexCoord2fARB(GL_TEXTURE1_ARB, *c_s0 / *c_q / (float)tex1_width, ytex(0, *c_t0 / *c_q / (float)tex1_height)); if (st1_en) glMultiTexCoord2fARB(GL_TEXTURE0_ARB, *c_s1 / *c_q / (float)tex0_width, ytex(1, *c_t1 / *c_q / (float)tex0_height)); } else { if (st0_en) glTexCoord2f(*c_s0 / *c_q / (float)tex0_width, ytex(0, *c_t0 / *c_q / (float)tex0_height)); } if (pargb_en) glColor4f(c_pargb[2]/255.0f, c_pargb[1]/255.0f, c_pargb[0]/255.0f, c_pargb[3]/255.0f); if (fog_enabled && fog_coord_support) { if(!glsl_support) { if(!fog_ext_en || fog_enabled != 2) glFogCoordfEXT((1.0f / *c_q)/*/256.0f*/); else glFogCoordfEXT((1.0f / *c_fog)/*/256.0f*/); } else { if(!fog_ext_en || fog_enabled != 2) glSecondaryColor3f((1.0f / *c_q) / 255.0f, 0.0f, 0.0f); else glSecondaryColor3f((1.0f / *c_fog) / 255.0f, 0.0f, 0.0f); /*if(!fog_ext_en || fog_enabled != 2) glFogCoordfEXT((1.0f / *c_q)/255.0f); else glFogCoordfEXT((1.0f / *c_fog)/255.0f);*/ } } glVertex4f((*c_x - (float)widtho) / (float)(width/2) / *c_q, -(*c_y - (float)heighto) / (float)(height/2) / *c_q, ZCALC(*c_z ,*c_q), 1.0f / *c_q); glEnd(); } FX_ENTRY void FX_CALL grDrawPoint( const void *pt ) { float *x = (float*)pt + xy_off/sizeof(float); float *y = (float*)pt + xy_off/sizeof(float) + 1; float *z = (float*)pt + z_off/sizeof(float); float *q = (float*)pt + q_off/sizeof(float); unsigned char *pargb = (unsigned char*)pt + pargb_off; float *s0 = (float*)pt + st0_off/sizeof(float); float *t0 = (float*)pt + st0_off/sizeof(float) + 1; float *s1 = (float*)pt + st1_off/sizeof(float); float *t1 = (float*)pt + st1_off/sizeof(float) + 1; float *fog = (float*)pt + fog_ext_off/sizeof(float); WriteLog(M64MSG_VERBOSE, "grDrawPoint()\r\n"); reloadTexture(); if(glsl_support && need_to_compile) compile_shader(); glBegin(GL_POINTS); if (nbTextureUnits > 2) { if (st0_en) glMultiTexCoord2fARB(GL_TEXTURE1_ARB, *s0 / *q / (float)tex1_width, ytex(0, *t0 / *q / (float)tex1_height)); if (st1_en) glMultiTexCoord2fARB(GL_TEXTURE0_ARB, *s1 / *q / (float)tex0_width, ytex(1, *t1 / *q / (float)tex0_height)); } else { if (st0_en) glTexCoord2f(*s0 / *q / (float)tex0_width, ytex(0, *t0 / *q / (float)tex0_height)); } if (pargb_en) glColor4f(pargb[2]/255.0f, pargb[1]/255.0f, pargb[0]/255.0f, pargb[3]/255.0f); if (fog_enabled && fog_coord_support) { if(!glsl_support) { if(!fog_ext_en || fog_enabled != 2) glFogCoordfEXT((1.0f / *q)/*/256.0f*/); else glFogCoordfEXT((1.0f / *fog)/*/256.0f*/); } else { if(!fog_ext_en || fog_enabled != 2) glSecondaryColor3f((1.0f / *q) / 255.0f, 0.0f, 0.0f); else glSecondaryColor3f((1.0f / *fog) / 255.0f, 0.0f, 0.0f); /*if(!fog_ext_en || fog_enabled != 2) glFogCoordfEXT((1.0f / *q)/255.0f); else glFogCoordfEXT((1.0f / *fog)/255.0f);*/ } } glVertex4f((*x - (float)widtho) / (float)(width/2) / *q, -(*y - (float)heighto) / (float)(height/2) / *q, ZCALC(*z ,*q), 1.0f / *q); glEnd(); } FX_ENTRY void FX_CALL grDrawLine( const void *a, const void *b ) { float *a_x = (float*)a + xy_off/sizeof(float); float *a_y = (float*)a + xy_off/sizeof(float) + 1; float *a_z = (float*)a + z_off/sizeof(float); float *a_q = (float*)a + q_off/sizeof(float); unsigned char *a_pargb = (unsigned char*)a + pargb_off; float *a_s0 = (float*)a + st0_off/sizeof(float); float *a_t0 = (float*)a + st0_off/sizeof(float) + 1; float *a_s1 = (float*)a + st1_off/sizeof(float); float *a_t1 = (float*)a + st1_off/sizeof(float) + 1; float *a_fog = (float*)a + fog_ext_off/sizeof(float); float *b_x = (float*)b + xy_off/sizeof(float); float *b_y = (float*)b + xy_off/sizeof(float) + 1; float *b_z = (float*)b + z_off/sizeof(float); float *b_q = (float*)b + q_off/sizeof(float); unsigned char *b_pargb = (unsigned char*)b + pargb_off; float *b_s0 = (float*)b + st0_off/sizeof(float); float *b_t0 = (float*)b + st0_off/sizeof(float) + 1; float *b_s1 = (float*)b + st1_off/sizeof(float); float *b_t1 = (float*)b + st1_off/sizeof(float) + 1; float *b_fog = (float*)b + fog_ext_off/sizeof(float); WriteLog(M64MSG_VERBOSE, "grDrawLine()\r\n"); //if(*a_fog == 0.0f) *a_fog = 1.0f; //if(*b_fog == 0.0f) *b_fog = 1.0f; reloadTexture(); if(glsl_support && need_to_compile) compile_shader(); glBegin(GL_LINES); if (nbTextureUnits > 2) { if (st0_en) glMultiTexCoord2fARB(GL_TEXTURE1_ARB, *a_s0 / *a_q / (float)tex1_width, ytex(0, *a_t0 / *a_q / (float)tex1_height)); if (st1_en) glMultiTexCoord2fARB(GL_TEXTURE0_ARB, *a_s1 / *a_q / (float)tex0_width, ytex(1, *a_t1 / *a_q / (float)tex0_height)); } else { if (st0_en) glTexCoord2f(*a_s0 / *a_q / (float)tex0_width, ytex(0, *a_t0 / *a_q / (float)tex0_height)); } if (pargb_en) glColor4f(a_pargb[2]/255.0f, a_pargb[1]/255.0f, a_pargb[0]/255.0f, a_pargb[3]/255.0f); if (fog_enabled && fog_coord_support) { if(!glsl_support) { if(!fog_ext_en || fog_enabled != 2) glFogCoordfEXT((1.0f / *a_q)/*/256.0f*/); else glFogCoordfEXT((1.0f / *a_fog)/*/256.0f*/); } else { if(!fog_ext_en || fog_enabled != 2) glSecondaryColor3f((1.0f / *a_q) / 255.0f, 0.0f, 0.0f); else glSecondaryColor3f((1.0f / *a_fog) / 255.0f, 0.0f, 0.0f); /*if(!fog_ext_en || fog_enabled != 2) glFogCoordfEXT((1.0f / *a_q)/255.0f); else glFogCoordfEXT((1.0f / *a_fog)/255.0f);*/ } } glVertex4f((*a_x - (float)widtho) / (float)(width/2) / *a_q, -(*a_y - (float)heighto) / (float)(height/2) / *a_q, ZCALC(*a_z, *a_q), 1.0f / *a_q); if (nbTextureUnits > 2) { if (st0_en) glMultiTexCoord2fARB(GL_TEXTURE1_ARB, *b_s0 / *b_q / (float)tex1_width, ytex(0, *b_t0 / *b_q / (float)tex1_height)); if (st1_en) glMultiTexCoord2fARB(GL_TEXTURE0_ARB, *b_s1 / *b_q / (float)tex0_width, ytex(1, *b_t1 / *b_q / (float)tex0_height)); } else { if (st0_en) glTexCoord2f(*b_s0 / *b_q / (float)tex0_width, ytex(0, *b_t0 / *b_q / (float)tex0_height)); } if (pargb_en) glColor4f(b_pargb[2]/255.0f, b_pargb[1]/255.0f, b_pargb[0]/255.0f, b_pargb[3]/255.0f); if (fog_enabled && fog_coord_support) { if(!glsl_support) { if(!fog_ext_en || fog_enabled != 2) glFogCoordfEXT((1.0f / *b_q)/*/256.0f*/); else glFogCoordfEXT((1.0f / *b_fog)/*/256.0f*/); } else { if(!fog_ext_en || fog_enabled != 2) glSecondaryColor3f((1.0f / *b_q) / 255.0f, 0.0f, 0.0f); else glSecondaryColor3f((1.0f / *b_fog) / 255.0f, 0.0f, 0.0f); /*if(!fog_ext_en || fog_enabled != 2) glFogCoordfEXT((1.0f / *b_q)/255.0f); else glFogCoordfEXT((1.0f / *b_fog)/255.0f);*/ } } glVertex4f((*b_x - (float)widtho) / (float)(width/2) / *b_q, -(*b_y - (float)heighto) / (float)(height/2) / *b_q, ZCALC(*b_z, *b_q), 1.0f / *b_q); glEnd(); } FX_ENTRY void FX_CALL grDrawVertexArray(FxU32 mode, FxU32 Count, void *pointers2) { unsigned int i; float *x, *y, *q, *s0, *t0, *s1, *t1, *z, *fog; unsigned char *pargb; void **pointers = (void**)pointers2; WriteLog(M64MSG_VERBOSE, "grDrawVertexArray(%d,%d)\r\n", mode, Count); reloadTexture(); if(glsl_support && need_to_compile) compile_shader(); switch(mode) { case GR_TRIANGLE_FAN: glBegin(GL_TRIANGLE_FAN); break; default: display_warning("grDrawVertexArray : unknown mode : %x", mode); } for (i=0; i 2) { if (st0_en) glMultiTexCoord2fARB(GL_TEXTURE1_ARB, *s0 / *q / (float)tex1_width, ytex(0, *t0 / *q / (float)tex1_height)); if (st1_en) glMultiTexCoord2fARB(GL_TEXTURE0_ARB, *s1 / *q / (float)tex0_width, ytex(1, *t1 / *q / (float)tex0_height)); } else { if (st0_en) glTexCoord2f(*s0 / *q / (float)tex0_width, ytex(0, *t0 / *q / (float)tex0_height)); } if (pargb_en) glColor4f(pargb[2]/255.0f, pargb[1]/255.0f, pargb[0]/255.0f, pargb[3]/255.0f); if (fog_enabled && fog_coord_support) { if(!glsl_support) { if(!fog_ext_en || fog_enabled != 2) glFogCoordfEXT((1.0f / *q)/*/256.0f*/); else glFogCoordfEXT((1.0f / *fog)/*/256.0f*/); } else { if(!fog_ext_en || fog_enabled != 2) glSecondaryColor3f((1.0f / *q) / 255.0f, 0.0f, 0.0f); else glSecondaryColor3f((1.0f / *fog) / 255.0f, 0.0f, 0.0f); /*if(!fog_ext_en || fog_enabled != 2) glFogCoordfEXT((1.0f / *q)/255.0f); else glFogCoordfEXT((1.0f / *fog)/255.0f);*/ } } //glFogCoordfEXT(192.0f); //glSecondaryColor3f(192.0f / 256.0f,0,0); //if((1.0f / *fog)/256.0f < 0.0f || (1.0f / *fog)/256.0f > 1.0f) glVertex4f((*x - (float)widtho) / (float)(width/2) / *q, -(*y - (float)heighto) / (float)(height/2) / *q, ZCALC(*z, *q), 1.0f / *q); } glEnd(); } FX_ENTRY void FX_CALL grDrawVertexArrayContiguous(FxU32 mode, FxU32 Count, void *pointers, FxU32 stride) { unsigned int i; float *x, *y, *q, *s0, *t0, *s1, *t1, *z, *fog; unsigned char *pargb; WriteLog(M64MSG_VERBOSE, "grDrawVertexArrayContiguous(%d,%d,%d)\r\n", mode, Count, stride); // ZIGGY apparently, grDrawVertexArrayContiguous is only used to overwrite the // whole screen, so we treat it as a grClearBuffer, no need to reload the texture buffer_cleared = TRUE; //reloadTexture(); if(glsl_support && need_to_compile) compile_shader(); switch(mode) { case GR_TRIANGLE_STRIP: glBegin(GL_TRIANGLE_STRIP); break; case GR_TRIANGLE_FAN: glBegin(GL_TRIANGLE_FAN); break; default: display_warning("grDrawVertexArrayContiguous : unknown mode : %x", mode); } for (i=0; i 2) { if (st0_en) glMultiTexCoord2fARB(GL_TEXTURE1_ARB, *s0 / *q / (float)tex1_width, ytex(0, *t0 / *q / (float)tex1_height)); if (st1_en) glMultiTexCoord2fARB(GL_TEXTURE0_ARB, *s1 / *q / (float)tex0_width, ytex(1, *t1 / *q / (float)tex0_height)); } else { if (st0_en) glTexCoord2f(*s0 / *q / (float)tex0_width, ytex(0, *t0 / *q / (float)tex0_height)); } if (pargb_en) glColor4f(pargb[2]/255.0f, pargb[1]/255.0f, pargb[0]/255.0f, pargb[3]/255.0f); if (fog_enabled && fog_coord_support) { if(!glsl_support) { if(!fog_ext_en || fog_enabled != 2) glFogCoordfEXT((1.0f / *q)/*/256.0f*/); else glFogCoordfEXT((1.0f / *fog)/*/256.0f*/); } else { if(!fog_ext_en || fog_enabled != 2) glSecondaryColor3f((1.0f / *q) / 255.0f, 0.0f, 0.0f); else glSecondaryColor3f((1.0f / *fog) / 255.0f, 0.0f, 0.0f); /*if(!fog_ext_en || fog_enabled != 2) glFogCoordfEXT((1.0f / *q)/255.0f); else glFogCoordfEXT((1.0f / *fog)/255.0f);*/ } } glVertex4f((*x - (float)widtho) / (float)(width/2) / *q, -(*y - (float)heighto) / (float)(height/2) / *q, ZCALC(*z, *q), 1.0f / *q); } glEnd(); } mupen64plus-video-glide64-src-2.6.0/src/wrapper/glide.h000066400000000000000000000730461464507525600226020ustar00rootroot00000000000000/* ** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY ** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT ** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX ** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE ** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com). ** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER ** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A ** FULL TEXT OF THE NON-WARRANTY PROVISIONS. ** ** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO ** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN ** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, ** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR ** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF ** THE UNITED STATES. ** ** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED */ /* ** GLIDE.H ** ** The following #defines are relevant when using Glide: ** ** One of the following "platform constants" must be defined during ** compilation: ** ** __DOS__ Defined for 32-bit DOS applications ** __WIN32__ Defined for 32-bit Windows applications ** __sparc__ Defined for Sun Solaris/SunOS ** __linux__ Defined for Linux applications ** __FreeBSD__ Defined for FreeBSD applications ** __NetBSD__ Defined for NetBSD applications ** __OpenBSD__ Defined for OpenBSD applications ** __IRIX__ Defined for SGI Irix applications ** */ #ifndef __GLIDE_H__ #define __GLIDE_H__ #include <3dfx.h> #include #include #ifdef __cplusplus extern "C" { #endif /* ** ----------------------------------------------------------------------- ** TYPE DEFINITIONS ** ----------------------------------------------------------------------- */ typedef FxU32 GrColor_t; typedef FxU8 GrAlpha_t; typedef FxU32 GrMipMapId_t; typedef FxU32 GrStipplePattern_t; typedef FxU8 GrFog_t; typedef FxU32 GrContext_t; typedef int (FX_CALL *GrProc)(); /* ** ----------------------------------------------------------------------- ** CONSTANTS AND TYPES ** ----------------------------------------------------------------------- */ #define GR_NULL_MIPMAP_HANDLE ((GrMipMapId_t) -1) #define GR_MIPMAPLEVELMASK_EVEN FXBIT(0) #define GR_MIPMAPLEVELMASK_ODD FXBIT(1) #define GR_MIPMAPLEVELMASK_BOTH (GR_MIPMAPLEVELMASK_EVEN | GR_MIPMAPLEVELMASK_ODD ) #define GR_LODBIAS_BILINEAR 0.5 #define GR_LODBIAS_TRILINEAR 0.0 typedef FxI32 GrChipID_t; #define GR_TMU0 0x0 #define GR_TMU1 0x1 #define GR_TMU2 0x2 #define GR_FBI 0x0 typedef FxI32 GrCombineFunction_t; #define GR_COMBINE_FUNCTION_ZERO 0x0 #define GR_COMBINE_FUNCTION_NONE GR_COMBINE_FUNCTION_ZERO #define GR_COMBINE_FUNCTION_LOCAL 0x1 #define GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2 #define GR_COMBINE_FUNCTION_SCALE_OTHER 0x3 #define GR_COMBINE_FUNCTION_BLEND_OTHER GR_COMBINE_FUNCTION_SCALE_OTHER #define GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4 #define GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5 #define GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6 #define GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7 #define GR_COMBINE_FUNCTION_BLEND GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL #define GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8 #define GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9 #define GR_COMBINE_FUNCTION_BLEND_LOCAL GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL #define GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10 typedef FxI32 GrCombineFactor_t; #define GR_COMBINE_FACTOR_ZERO 0x0 #define GR_COMBINE_FACTOR_NONE GR_COMBINE_FACTOR_ZERO #define GR_COMBINE_FACTOR_LOCAL 0x1 #define GR_COMBINE_FACTOR_OTHER_ALPHA 0x2 #define GR_COMBINE_FACTOR_LOCAL_ALPHA 0x3 #define GR_COMBINE_FACTOR_TEXTURE_ALPHA 0x4 #define GR_COMBINE_FACTOR_TEXTURE_RGB 0x5 #define GR_COMBINE_FACTOR_DETAIL_FACTOR GR_COMBINE_FACTOR_TEXTURE_ALPHA #define GR_COMBINE_FACTOR_LOD_FRACTION 0x5 #define GR_COMBINE_FACTOR_ONE 0x8 #define GR_COMBINE_FACTOR_ONE_MINUS_LOCAL 0x9 #define GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA 0xa #define GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA 0xb #define GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA 0xc #define GR_COMBINE_FACTOR_ONE_MINUS_DETAIL_FACTOR GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA #define GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION 0xd typedef FxI32 GrCombineLocal_t; #define GR_COMBINE_LOCAL_ITERATED 0x0 #define GR_COMBINE_LOCAL_CONSTANT 0x1 #define GR_COMBINE_LOCAL_NONE GR_COMBINE_LOCAL_CONSTANT #define GR_COMBINE_LOCAL_DEPTH 0x2 typedef FxI32 GrCombineOther_t; #define GR_COMBINE_OTHER_ITERATED 0x0 #define GR_COMBINE_OTHER_TEXTURE 0x1 #define GR_COMBINE_OTHER_CONSTANT 0x2 #define GR_COMBINE_OTHER_NONE GR_COMBINE_OTHER_CONSTANT typedef FxI32 GrAlphaSource_t; #define GR_ALPHASOURCE_CC_ALPHA 0x0 #define GR_ALPHASOURCE_ITERATED_ALPHA 0x1 #define GR_ALPHASOURCE_TEXTURE_ALPHA 0x2 #define GR_ALPHASOURCE_TEXTURE_ALPHA_TIMES_ITERATED_ALPHA 0x3 typedef FxI32 GrColorCombineFnc_t; #define GR_COLORCOMBINE_ZERO 0x0 #define GR_COLORCOMBINE_CCRGB 0x1 #define GR_COLORCOMBINE_ITRGB 0x2 #define GR_COLORCOMBINE_ITRGB_DELTA0 0x3 #define GR_COLORCOMBINE_DECAL_TEXTURE 0x4 #define GR_COLORCOMBINE_TEXTURE_TIMES_CCRGB 0x5 #define GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB 0x6 #define GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB_DELTA0 0x7 #define GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB_ADD_ALPHA 0x8 #define GR_COLORCOMBINE_TEXTURE_TIMES_ALPHA 0x9 #define GR_COLORCOMBINE_TEXTURE_TIMES_ALPHA_ADD_ITRGB 0xa #define GR_COLORCOMBINE_TEXTURE_ADD_ITRGB 0xb #define GR_COLORCOMBINE_TEXTURE_SUB_ITRGB 0xc #define GR_COLORCOMBINE_CCRGB_BLEND_ITRGB_ON_TEXALPHA 0xd #define GR_COLORCOMBINE_DIFF_SPEC_A 0xe #define GR_COLORCOMBINE_DIFF_SPEC_B 0xf #define GR_COLORCOMBINE_ONE 0x10 typedef FxI32 GrAlphaBlendFnc_t; #define GR_BLEND_ZERO 0x0 #define GR_BLEND_SRC_ALPHA 0x1 #define GR_BLEND_SRC_COLOR 0x2 #define GR_BLEND_DST_COLOR GR_BLEND_SRC_COLOR #define GR_BLEND_DST_ALPHA 0x3 #define GR_BLEND_ONE 0x4 #define GR_BLEND_ONE_MINUS_SRC_ALPHA 0x5 #define GR_BLEND_ONE_MINUS_SRC_COLOR 0x6 #define GR_BLEND_ONE_MINUS_DST_COLOR GR_BLEND_ONE_MINUS_SRC_COLOR #define GR_BLEND_ONE_MINUS_DST_ALPHA 0x7 #define GR_BLEND_RESERVED_8 0x8 #define GR_BLEND_RESERVED_9 0x9 #define GR_BLEND_RESERVED_A 0xa #define GR_BLEND_RESERVED_B 0xb #define GR_BLEND_RESERVED_C 0xc #define GR_BLEND_RESERVED_D 0xd #define GR_BLEND_RESERVED_E 0xe #define GR_BLEND_ALPHA_SATURATE 0xf #define GR_BLEND_PREFOG_COLOR GR_BLEND_ALPHA_SATURATE typedef FxI32 GrAspectRatio_t; #define GR_ASPECT_LOG2_8x1 3 /* 8W x 1H */ #define GR_ASPECT_LOG2_4x1 2 /* 4W x 1H */ #define GR_ASPECT_LOG2_2x1 1 /* 2W x 1H */ #define GR_ASPECT_LOG2_1x1 0 /* 1W x 1H */ #define GR_ASPECT_LOG2_1x2 -1 /* 1W x 2H */ #define GR_ASPECT_LOG2_1x4 -2 /* 1W x 4H */ #define GR_ASPECT_LOG2_1x8 -3 /* 1W x 8H */ typedef FxI32 GrBuffer_t; #define GR_BUFFER_FRONTBUFFER 0x0 #define GR_BUFFER_BACKBUFFER 0x1 #define GR_BUFFER_AUXBUFFER 0x2 #define GR_BUFFER_DEPTHBUFFER 0x3 #define GR_BUFFER_ALPHABUFFER 0x4 #define GR_BUFFER_TRIPLEBUFFER 0x5 typedef FxI32 GrChromakeyMode_t; #define GR_CHROMAKEY_DISABLE 0x0 #define GR_CHROMAKEY_ENABLE 0x1 typedef FxI32 GrChromaRangeMode_t; #define GR_CHROMARANGE_RGB_ALL_EXT 0x0 #define GR_CHROMARANGE_DISABLE_EXT 0x00 #define GR_CHROMARANGE_ENABLE_EXT 0x01 typedef FxI32 GrTexChromakeyMode_t; #define GR_TEXCHROMA_DISABLE_EXT 0x0 #define GR_TEXCHROMA_ENABLE_EXT 0x1 #define GR_TEXCHROMARANGE_RGB_ALL_EXT 0x0 typedef FxI32 GrCmpFnc_t; #define GR_CMP_NEVER 0x0 #define GR_CMP_LESS 0x1 #define GR_CMP_EQUAL 0x2 #define GR_CMP_LEQUAL 0x3 #define GR_CMP_GREATER 0x4 #define GR_CMP_NOTEQUAL 0x5 #define GR_CMP_GEQUAL 0x6 #define GR_CMP_ALWAYS 0x7 typedef FxI32 GrColorFormat_t; #define GR_COLORFORMAT_ARGB 0x0 #define GR_COLORFORMAT_ABGR 0x1 #define GR_COLORFORMAT_RGBA 0x2 #define GR_COLORFORMAT_BGRA 0x3 typedef FxI32 GrCullMode_t; #define GR_CULL_DISABLE 0x0 #define GR_CULL_NEGATIVE 0x1 #define GR_CULL_POSITIVE 0x2 typedef FxI32 GrDepthBufferMode_t; #define GR_DEPTHBUFFER_DISABLE 0x0 #define GR_DEPTHBUFFER_ZBUFFER 0x1 #define GR_DEPTHBUFFER_WBUFFER 0x2 #define GR_DEPTHBUFFER_ZBUFFER_COMPARE_TO_BIAS 0x3 #define GR_DEPTHBUFFER_WBUFFER_COMPARE_TO_BIAS 0x4 typedef FxI32 GrDitherMode_t; #define GR_DITHER_DISABLE 0x0 #define GR_DITHER_2x2 0x1 #define GR_DITHER_4x4 0x2 typedef FxI32 GrStippleMode_t; #define GR_STIPPLE_DISABLE 0x0 #define GR_STIPPLE_PATTERN 0x1 #define GR_STIPPLE_ROTATE 0x2 typedef FxI32 GrFogMode_t; #define GR_FOG_DISABLE 0x0 #define GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT 0x1 #define GR_FOG_WITH_TABLE_ON_Q 0x2 #define GR_FOG_WITH_TABLE_ON_W GR_FOG_WITH_TABLE_ON_Q #define GR_FOG_WITH_ITERATED_Z 0x3 #define GR_FOG_WITH_ITERATED_ALPHA_EXT 0x4 #define GR_FOG_MULT2 0x100 #define GR_FOG_ADD2 0x200 typedef FxU32 GrLock_t; #define GR_LFB_READ_ONLY 0x00 #define GR_LFB_WRITE_ONLY 0x01 #define GR_LFB_IDLE 0x00 #define GR_LFB_NOIDLE 0x10 #define GR_LFB_WRITE_ONLY_EXPLICIT_EXT 0x02 /* explicitly not allow reading from the lfb pointer */ typedef FxI32 GrLfbBypassMode_t; #define GR_LFBBYPASS_DISABLE 0x0 #define GR_LFBBYPASS_ENABLE 0x1 typedef FxI32 GrLfbWriteMode_t; #define GR_LFBWRITEMODE_565 0x0 /* RGB:RGB */ #define GR_LFBWRITEMODE_555 0x1 /* RGB:RGB */ #define GR_LFBWRITEMODE_1555 0x2 /* ARGB:ARGB */ #define GR_LFBWRITEMODE_RESERVED1 0x3 #define GR_LFBWRITEMODE_888 0x4 /* RGB */ #define GR_LFBWRITEMODE_8888 0x5 /* ARGB */ #define GR_LFBWRITEMODE_RESERVED2 0x6 #define GR_LFBWRITEMODE_RESERVED3 0x7 #define GR_LFBWRITEMODE_RESERVED4 0x8 #define GR_LFBWRITEMODE_RESERVED5 0x9 #define GR_LFBWRITEMODE_RESERVED6 0xa #define GR_LFBWRITEMODE_RESERVED7 0xb #define GR_LFBWRITEMODE_565_DEPTH 0xc /* RGB:DEPTH */ #define GR_LFBWRITEMODE_555_DEPTH 0xd /* RGB:DEPTH */ #define GR_LFBWRITEMODE_1555_DEPTH 0xe /* ARGB:DEPTH */ #define GR_LFBWRITEMODE_ZA16 0xf /* DEPTH:DEPTH */ #define GR_LFBWRITEMODE_ANY 0xFF typedef FxI32 GrOriginLocation_t; #define GR_ORIGIN_UPPER_LEFT 0x0 #define GR_ORIGIN_LOWER_LEFT 0x1 #define GR_ORIGIN_ANY 0xFF typedef struct { int size; void *lfbPtr; FxU32 strideInBytes; GrLfbWriteMode_t writeMode; GrOriginLocation_t origin; } GrLfbInfo_t; typedef FxI32 GrLOD_t; #define GR_LOD_LOG2_256 0x8 #define GR_LOD_LOG2_128 0x7 #define GR_LOD_LOG2_64 0x6 #define GR_LOD_LOG2_32 0x5 #define GR_LOD_LOG2_16 0x4 #define GR_LOD_LOG2_8 0x3 #define GR_LOD_LOG2_4 0x2 #define GR_LOD_LOG2_2 0x1 #define GR_LOD_LOG2_1 0x0 typedef FxI32 GrMipMapMode_t; #define GR_MIPMAP_DISABLE 0x0 /* no mip mapping */ #define GR_MIPMAP_NEAREST 0x1 /* use nearest mipmap */ #define GR_MIPMAP_NEAREST_DITHER 0x2 /* GR_MIPMAP_NEAREST + LOD dith */ typedef FxI32 GrSmoothingMode_t; #define GR_SMOOTHING_DISABLE 0x0 #define GR_SMOOTHING_ENABLE 0x1 typedef FxI32 GrTextureClampMode_t; #define GR_TEXTURECLAMP_WRAP 0x0 #define GR_TEXTURECLAMP_CLAMP 0x1 #define GR_TEXTURECLAMP_MIRROR_EXT 0x2 typedef FxI32 GrTextureCombineFnc_t; #define GR_TEXTURECOMBINE_ZERO 0x0 /* texout = 0 */ #define GR_TEXTURECOMBINE_DECAL 0x1 /* texout = texthis */ #define GR_TEXTURECOMBINE_OTHER 0x2 /* this TMU in passthru mode */ #define GR_TEXTURECOMBINE_ADD 0x3 /* tout = tthis + t(this+1) */ #define GR_TEXTURECOMBINE_MULTIPLY 0x4 /* texout = tthis * t(this+1) */ #define GR_TEXTURECOMBINE_SUBTRACT 0x5 /* Sutract from upstream TMU */ #define GR_TEXTURECOMBINE_DETAIL 0x6 /* detail--detail on tthis */ #define GR_TEXTURECOMBINE_DETAIL_OTHER 0x7 /* detail--detail on tthis+1 */ #define GR_TEXTURECOMBINE_TRILINEAR_ODD 0x8 /* trilinear--odd levels tthis*/ #define GR_TEXTURECOMBINE_TRILINEAR_EVEN 0x9 /*trilinear--even levels tthis*/ #define GR_TEXTURECOMBINE_ONE 0xa /* texout = 0xFFFFFFFF */ typedef FxI32 GrTextureFilterMode_t; #define GR_TEXTUREFILTER_POINT_SAMPLED 0x0 #define GR_TEXTUREFILTER_BILINEAR 0x1 typedef FxI32 GrTextureFormat_t; /* KoolSmoky - */ #define GR_TEXFMT_8BIT 0x0 #define GR_TEXFMT_RGB_332 GR_TEXFMT_8BIT #define GR_TEXFMT_YIQ_422 0x1 #define GR_TEXFMT_ALPHA_8 0x2 /* (0..0xFF) alpha */ #define GR_TEXFMT_INTENSITY_8 0x3 /* (0..0xFF) intensity */ #define GR_TEXFMT_ALPHA_INTENSITY_44 0x4 #define GR_TEXFMT_P_8 0x5 /* 8-bit palette */ #define GR_TEXFMT_RSVD0 0x6 /* GR_TEXFMT_P_8_RGBA */ #define GR_TEXFMT_P_8_6666 GR_TEXFMT_RSVD0 #define GR_TEXFMT_P_8_6666_EXT GR_TEXFMT_RSVD0 #define GR_TEXFMT_RSVD1 0x7 #define GR_TEXFMT_16BIT 0x8 #define GR_TEXFMT_ARGB_8332 GR_TEXFMT_16BIT #define GR_TEXFMT_AYIQ_8422 0x9 #define GR_TEXFMT_RGB_565 0xa #define GR_TEXFMT_ARGB_1555 0xb #define GR_TEXFMT_ARGB_4444 0xc #define GR_TEXFMT_ALPHA_INTENSITY_88 0xd #define GR_TEXFMT_AP_88 0xe /* 8-bit alpha 8-bit palette */ #define GR_TEXFMT_RSVD2 0xf #define GR_TEXFMT_RSVD4 GR_TEXFMT_RSVD2 typedef FxU32 GrTexTable_t; #define GR_TEXTABLE_NCC0 0x0 #define GR_TEXTABLE_NCC1 0x1 #define GR_TEXTABLE_PALETTE 0x2 #define GR_TEXTABLE_PALETTE_6666_EXT 0x3 typedef FxU32 GrNCCTable_t; #define GR_NCCTABLE_NCC0 0x0 #define GR_NCCTABLE_NCC1 0x1 typedef FxU32 GrTexBaseRange_t; #define GR_TEXBASE_256 0x3 #define GR_TEXBASE_128 0x2 #define GR_TEXBASE_64 0x1 #define GR_TEXBASE_32_TO_1 0x0 typedef FxU32 GrEnableMode_t; #define GR_MODE_DISABLE 0x0 #define GR_MODE_ENABLE 0x1 #define GR_AA_ORDERED 0x01 #define GR_ALLOW_MIPMAP_DITHER 0x02 #define GR_PASSTHRU 0x03 #define GR_SHAMELESS_PLUG 0x04 #define GR_VIDEO_SMOOTHING 0x05 typedef FxU32 GrCoordinateSpaceMode_t; #define GR_WINDOW_COORDS 0x00 #define GR_CLIP_COORDS 0x01 /* Types of data in strips */ #define GR_FLOAT 0 #define GR_U8 1 /* Parameters for strips */ #define GR_PARAM_XY 0x01 #define GR_PARAM_Z 0x02 #define GR_PARAM_W 0x03 #define GR_PARAM_Q 0x04 #define GR_PARAM_FOG_EXT 0x05 #define GR_PARAM_A 0x10 #define GR_PARAM_RGB 0x20 #define GR_PARAM_PARGB 0x30 #define GR_PARAM_ST0 0x40 #define GR_PARAM_ST1 GR_PARAM_ST0+1 #define GR_PARAM_ST2 GR_PARAM_ST0+2 #define GR_PARAM_Q0 0x50 #define GR_PARAM_Q1 GR_PARAM_Q0+1 #define GR_PARAM_Q2 GR_PARAM_Q0+2 #define GR_PARAM_DISABLE 0x00 #define GR_PARAM_ENABLE 0x01 /* ** grDrawVertexArray/grDrawVertexArrayContiguous primitive type */ #define GR_POINTS 0 #define GR_LINE_STRIP 1 #define GR_LINES 2 #define GR_POLYGON 3 #define GR_TRIANGLE_STRIP 4 #define GR_TRIANGLE_FAN 5 #define GR_TRIANGLES 6 #define GR_TRIANGLE_STRIP_CONTINUE 7 #define GR_TRIANGLE_FAN_CONTINUE 8 /* ** grGet/grReset types */ #define GR_BITS_DEPTH 0x01 #define GR_BITS_RGBA 0x02 #define GR_FIFO_FULLNESS 0x03 #define GR_FOG_TABLE_ENTRIES 0x04 #define GR_GAMMA_TABLE_ENTRIES 0x05 #define GR_GLIDE_STATE_SIZE 0x06 #define GR_GLIDE_VERTEXLAYOUT_SIZE 0x07 #define GR_IS_BUSY 0x08 #define GR_LFB_PIXEL_PIPE 0x09 #define GR_MAX_TEXTURE_SIZE 0x0a #define GR_MAX_TEXTURE_ASPECT_RATIO 0x0b #define GR_MEMORY_FB 0x0c #define GR_MEMORY_TMU 0x0d #define GR_MEMORY_UMA 0x0e #define GR_NUM_BOARDS 0x0f #define GR_NON_POWER_OF_TWO_TEXTURES 0x10 #define GR_NUM_FB 0x11 #define GR_NUM_SWAP_HISTORY_BUFFER 0x12 #define GR_NUM_TMU 0x13 #define GR_PENDING_BUFFERSWAPS 0x14 #define GR_REVISION_FB 0x15 #define GR_REVISION_TMU 0x16 #define GR_STATS_LINES 0x17 /* grGet/grReset */ #define GR_STATS_PIXELS_AFUNC_FAIL 0x18 #define GR_STATS_PIXELS_CHROMA_FAIL 0x19 #define GR_STATS_PIXELS_DEPTHFUNC_FAIL 0x1a #define GR_STATS_PIXELS_IN 0x1b #define GR_STATS_PIXELS_OUT 0x1c #define GR_STATS_PIXELS 0x1d /* grReset */ #define GR_STATS_POINTS 0x1e /* grGet/grReset */ #define GR_STATS_TRIANGLES_IN 0x1f #define GR_STATS_TRIANGLES_OUT 0x20 #define GR_STATS_TRIANGLES 0x21 /* grReset */ #define GR_SWAP_HISTORY 0x22 #define GR_SUPPORTS_PASSTHRU 0x23 #define GR_TEXTURE_ALIGN 0x24 #define GR_VIDEO_POSITION 0x25 #define GR_VIEWPORT 0x26 #define GR_WDEPTH_MIN_MAX 0x27 #define GR_ZDEPTH_MIN_MAX 0x28 #define GR_VERTEX_PARAMETER 0x29 #define GR_BITS_GAMMA 0x2a #define GR_GET_RESERVED_1 0x1000 /* ** grGetString types */ #define GR_EXTENSION 0xa0 #define GR_HARDWARE 0xa1 #define GR_RENDERER 0xa2 #define GR_VENDOR 0xa3 #define GR_VERSION 0xa4 /* ** ----------------------------------------------------------------------- ** STRUCTURES ** ----------------------------------------------------------------------- */ typedef struct { GrLOD_t smallLodLog2; GrLOD_t largeLodLog2; GrAspectRatio_t aspectRatioLog2; GrTextureFormat_t format; void *data; } GrTexInfo; typedef struct GrSstPerfStats_s { FxU32 pixelsIn; /* # pixels processed (minus buffer clears) */ FxU32 chromaFail; /* # pixels not drawn due to chroma key */ FxU32 zFuncFail; /* # pixels not drawn due to Z comparison */ FxU32 aFuncFail; /* # pixels not drawn due to alpha comparison */ FxU32 pixelsOut; /* # pixels drawn (including buffer clears) */ } GrSstPerfStats_t; typedef struct { GrScreenResolution_t resolution; GrScreenRefresh_t refresh; int numColorBuffers; int numAuxBuffers; } GrResolution; typedef GrResolution GlideResolution; #define GR_QUERY_ANY ((FxU32)(~0)) typedef FxU32 GrLfbSrcFmt_t; #define GR_LFB_SRC_FMT_565 0x00 #define GR_LFB_SRC_FMT_555 0x01 #define GR_LFB_SRC_FMT_1555 0x02 #define GR_LFB_SRC_FMT_888 0x04 #define GR_LFB_SRC_FMT_8888 0x05 #define GR_LFB_SRC_FMT_565_DEPTH 0x0c #define GR_LFB_SRC_FMT_555_DEPTH 0x0d #define GR_LFB_SRC_FMT_1555_DEPTH 0x0e #define GR_LFB_SRC_FMT_ZA16 0x0f #define GR_LFB_SRC_FMT_RLE16 0x80 #ifdef H3D #define GR_HINT_H3DENABLE 4 #undef GR_HINTTYPE_MAX #define GR_HINTTYPE_MAX 4 #endif /* ** ----------------------------------------------------------------------- ** FUNCTION PROTOTYPES ** ----------------------------------------------------------------------- */ #ifndef FX_GLIDE_NO_FUNC_PROTO /* ** rendering functions */ FX_ENTRY void FX_CALL grDrawPoint( const void *pt ); FX_ENTRY void FX_CALL grDrawLine( const void *v1, const void *v2 ); FX_ENTRY void FX_CALL grDrawTriangle( const void *a, const void *b, const void *c ); FX_ENTRY void FX_CALL grVertexLayout(FxU32 param, FxI32 offset, FxU32 mode); FX_ENTRY void FX_CALL grDrawVertexArray(FxU32 mode, FxU32 Count, void *pointers); FX_ENTRY void FX_CALL grDrawVertexArrayContiguous(FxU32 mode, FxU32 Count, void *pointers, FxU32 stride); /* ** Antialiasing Functions */ FX_ENTRY void FX_CALL grAADrawTriangle( const void *a, const void *b, const void *c, FxBool ab_antialias, FxBool bc_antialias, FxBool ca_antialias ); /* ** buffer management */ FX_ENTRY void FX_CALL grBufferClear( GrColor_t color, GrAlpha_t alpha, FxU32 depth ); FX_ENTRY void FX_CALL grBufferSwap( FxU32 swap_interval ); FX_ENTRY void FX_CALL grRenderBuffer( GrBuffer_t buffer ); /* ** error management */ typedef void (*GrErrorCallbackFnc_t)( const char *string, FxBool fatal ); FX_ENTRY void FX_CALL grErrorSetCallback( GrErrorCallbackFnc_t fnc ); /* ** SST routines */ FX_ENTRY void FX_CALL grFinish(void); FX_ENTRY void FX_CALL grFlush(void); FX_ENTRY GrContext_t FX_CALL grSstWinOpen( FxU32 hWnd, GrScreenResolution_t screen_resolution, GrScreenRefresh_t refresh_rate, GrColorFormat_t color_format, GrOriginLocation_t origin_location, int nColBuffers, int nAuxBuffers); FX_ENTRY FxBool FX_CALL grSstWinClose( GrContext_t context ); FX_ENTRY void FX_CALL grSetNumPendingBuffers(FxI32 NumPendingBuffers); FX_ENTRY FxBool FX_CALL grSelectContext( GrContext_t context ); FX_ENTRY void FX_CALL grSstOrigin(GrOriginLocation_t origin); FX_ENTRY void FX_CALL grSstSelect( int which_sst ); /* ** Glide configuration and special effect maintenance functions */ FX_ENTRY void FX_CALL grAlphaBlendFunction( GrAlphaBlendFnc_t rgb_sf, GrAlphaBlendFnc_t rgb_df, GrAlphaBlendFnc_t alpha_sf, GrAlphaBlendFnc_t alpha_df ); FX_ENTRY void FX_CALL grAlphaCombine( GrCombineFunction_t function, GrCombineFactor_t factor, GrCombineLocal_t local, GrCombineOther_t other, FxBool invert ); FX_ENTRY void FX_CALL grAlphaControlsITRGBLighting( FxBool enable ); FX_ENTRY void FX_CALL grAlphaTestFunction( GrCmpFnc_t function ); FX_ENTRY void FX_CALL grAlphaTestReferenceValue( GrAlpha_t value ); FX_ENTRY void FX_CALL grChromakeyMode( GrChromakeyMode_t mode ); FX_ENTRY void FX_CALL grChromakeyValue( GrColor_t value ); FX_ENTRY void FX_CALL grClipWindow( FxU32 minx, FxU32 miny, FxU32 maxx, FxU32 maxy ); FX_ENTRY void FX_CALL grColorCombine( GrCombineFunction_t function, GrCombineFactor_t factor, GrCombineLocal_t local, GrCombineOther_t other, FxBool invert ); FX_ENTRY void FX_CALL grColorMask( FxBool rgb, FxBool a ); FX_ENTRY void FX_CALL grCullMode( GrCullMode_t mode ); FX_ENTRY void FX_CALL grConstantColorValue( GrColor_t value ); FX_ENTRY void FX_CALL grDepthBiasLevel( FxI32 level ); FX_ENTRY void FX_CALL grDepthBufferFunction( GrCmpFnc_t function ); FX_ENTRY void FX_CALL grDepthBufferMode( GrDepthBufferMode_t mode ); FX_ENTRY void FX_CALL grDepthMask( FxBool mask ); FX_ENTRY void FX_CALL grDisableAllEffects( void ); FX_ENTRY void FX_CALL grDitherMode( GrDitherMode_t mode ); FX_ENTRY void FX_CALL grFogColorValue( GrColor_t fogcolor ); FX_ENTRY void FX_CALL grFogMode( GrFogMode_t mode ); FX_ENTRY void FX_CALL grFogTable( const GrFog_t ft[] ); FX_ENTRY void FX_CALL grLoadGammaTable( FxU32 nentries, FxU32 *red, FxU32 *green, FxU32 *blue); FX_ENTRY void FX_CALL grSplash(float x, float y, float width, float height, FxU32 frame); FX_ENTRY FxU32 FX_CALL grGet( FxU32 pname, FxU32 plength, FxI32 *params ); FX_ENTRY const char * FX_CALL grGetString( FxU32 pname ); FX_ENTRY FxI32 FX_CALL grQueryResolutions( const GrResolution *resTemplate, GrResolution *output ); FX_ENTRY FxBool FX_CALL grReset( FxU32 what ); FX_ENTRY GrProc FX_CALL grGetProcAddress( const char *procName ); FX_ENTRY void FX_CALL grEnable( GrEnableMode_t mode ); FX_ENTRY void FX_CALL grDisable( GrEnableMode_t mode ); FX_ENTRY void FX_CALL grCoordinateSpace( GrCoordinateSpaceMode_t mode ); FX_ENTRY void FX_CALL grDepthRange( FxFloat n, FxFloat f ); FX_ENTRY void FX_CALL grStippleMode( GrStippleMode_t mode ); FX_ENTRY void FX_CALL grStipplePattern( GrStipplePattern_t mode ); FX_ENTRY void FX_CALL grViewport( FxI32 x, FxI32 y, FxI32 width, FxI32 height ); /* ** texture mapping control functions */ FX_ENTRY FxU32 FX_CALL grTexCalcMemRequired( GrLOD_t lodmin, GrLOD_t lodmax, GrAspectRatio_t aspect, GrTextureFormat_t fmt); FX_ENTRY FxU32 FX_CALL grTexTextureMemRequired( FxU32 evenOdd, GrTexInfo *info ); FX_ENTRY FxU32 FX_CALL grTexMinAddress( GrChipID_t tmu ); FX_ENTRY FxU32 FX_CALL grTexMaxAddress( GrChipID_t tmu ); FX_ENTRY void FX_CALL grTexNCCTable( GrNCCTable_t table ); FX_ENTRY void FX_CALL grTexSource( GrChipID_t tmu, FxU32 startAddress, FxU32 evenOdd, GrTexInfo *info ); FX_ENTRY void FX_CALL grTexClampMode( GrChipID_t tmu, GrTextureClampMode_t s_clampmode, GrTextureClampMode_t t_clampmode ); FX_ENTRY void FX_CALL grTexCombine( GrChipID_t tmu, GrCombineFunction_t rgb_function, GrCombineFactor_t rgb_factor, GrCombineFunction_t alpha_function, GrCombineFactor_t alpha_factor, FxBool rgb_invert, FxBool alpha_invert ); FX_ENTRY void FX_CALL grTexDetailControl( GrChipID_t tmu, int lod_bias, FxU8 detail_scale, float detail_max ); FX_ENTRY void FX_CALL grTexFilterMode( GrChipID_t tmu, GrTextureFilterMode_t minfilter_mode, GrTextureFilterMode_t magfilter_mode ); FX_ENTRY void FX_CALL grTexLodBiasValue(GrChipID_t tmu, float bias ); FX_ENTRY void FX_CALL grTexDownloadMipMap( GrChipID_t tmu, FxU32 startAddress, FxU32 evenOdd, GrTexInfo *info ); FX_ENTRY void FX_CALL grTexDownloadMipMapLevel( GrChipID_t tmu, FxU32 startAddress, GrLOD_t thisLod, GrLOD_t largeLod, GrAspectRatio_t aspectRatio, GrTextureFormat_t format, FxU32 evenOdd, void *data ); FX_ENTRY FxBool FX_CALL grTexDownloadMipMapLevelPartial( GrChipID_t tmu, FxU32 startAddress, GrLOD_t thisLod, GrLOD_t largeLod, GrAspectRatio_t aspectRatio, GrTextureFormat_t format, FxU32 evenOdd, void *data, int start, int end ); FX_ENTRY void FX_CALL grTexDownloadTable( GrTexTable_t type, void *data ); FX_ENTRY void FX_CALL grTexDownloadTablePartial( GrTexTable_t type, void *data, int start, int end ); FX_ENTRY void FX_CALL grTexMipMapMode( GrChipID_t tmu, GrMipMapMode_t mode, FxBool lodBlend ); FX_ENTRY void FX_CALL grTexMultibase( GrChipID_t tmu, FxBool enable ); FX_ENTRY void FX_CALL grTexMultibaseAddress( GrChipID_t tmu, GrTexBaseRange_t range, FxU32 startAddress, FxU32 evenOdd, GrTexInfo *info ); /* ** linear frame buffer functions */ FX_ENTRY FxBool FX_CALL grLfbLock( GrLock_t type, GrBuffer_t buffer, GrLfbWriteMode_t writeMode, GrOriginLocation_t origin, FxBool pixelPipeline, GrLfbInfo_t *info ); FX_ENTRY FxBool FX_CALL grLfbUnlock( GrLock_t type, GrBuffer_t buffer ); FX_ENTRY void FX_CALL grLfbConstantAlpha( GrAlpha_t alpha ); FX_ENTRY void FX_CALL grLfbConstantDepth( FxU32 depth ); FX_ENTRY void FX_CALL grLfbWriteColorSwizzle(FxBool swizzleBytes, FxBool swapWords); FX_ENTRY void FX_CALL grLfbWriteColorFormat(GrColorFormat_t colorFormat); FX_ENTRY FxBool FX_CALL grLfbWriteRegion( GrBuffer_t dst_buffer, FxU32 dst_x, FxU32 dst_y, GrLfbSrcFmt_t src_format, FxU32 src_width, FxU32 src_height, FxBool pixelPipeline, FxI32 src_stride, void *src_data ); FX_ENTRY FxBool FX_CALL grLfbReadRegion( GrBuffer_t src_buffer, FxU32 src_x, FxU32 src_y, FxU32 src_width, FxU32 src_height, FxU32 dst_stride, void *dst_data ); /* ** glide management functions */ FX_ENTRY void FX_CALL grGlideInit( void ); FX_ENTRY void FX_CALL grGlideShutdown( void ); FX_ENTRY void FX_CALL grGlideGetState( void *state ); FX_ENTRY void FX_CALL grGlideSetState( const void *state ); FX_ENTRY void FX_CALL grGlideGetVertexLayout( void *layout ); FX_ENTRY void FX_CALL grGlideSetVertexLayout( const void *layout ); #endif /* FX_GLIDE_NO_FUNC_PROTO */ #ifdef __cplusplus } #endif #include #endif /* __GLIDE_H__ */ mupen64plus-video-glide64-src-2.6.0/src/wrapper/glidesys.h000066400000000000000000000117751464507525600233420ustar00rootroot00000000000000/* ** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY ** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT ** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX ** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE ** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com). ** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER ** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A ** FULL TEXT OF THE NON-WARRANTY PROVISIONS. ** ** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO ** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN ** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, ** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR ** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF ** THE UNITED STATES. ** ** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED ** ** $Header: /cvsroot/glide/glide3x/h5/glide3/src/glidesys.h,v 1.3.4.3 2003/07/24 03:51:08 anholt Exp $ ** $Log: ** 3 3dfx 1.0.1.0.1.0 10/11/00 Brent Forced check in to enforce ** branching. ** 2 3dfx 1.0.1.0 06/20/00 Joseph Kain Changes to support the ** Napalm Glide open source release. Changes include cleaned up offensive ** comments and new legal headers. ** 1 3dfx 1.0 09/11/99 StarTeam VTS Administrator ** $ ** ** 4 11/05/98 11:18a Russp ** Fix GLIDE_NUM_TMU error check (change "&&" to "||") ** ** 3 7/24/98 1:41p Hohn ** ** 2 6/15/98 10:50a Peter ** made csim compile time option * * 1 1/16/98 4:29p Atai * create glide 3 src * * 10 12/09/97 12:20p Peter * mac glide port * * 9 11/04/97 4:00p Dow * Banshee Mods * * 8 8/18/97 3:52p Peter * pre-hw arrival fixes/cleanup * * 7 6/02/97 4:09p Peter * Compile w/ gcc for Dural * * 6 5/27/97 1:16p Peter * Basic cvg, w/o cmd fifo stuff. * * 5 5/21/97 6:05a Peter */ #ifndef __GLIDESYS_H__ #define __GLIDESYS_H__ /* n** ----------------------------------------------------------------------- ** COMPILER/ENVIRONMENT CONFIGURATION ** ----------------------------------------------------------------------- */ /* Endianness is stored in bits [30:31] */ #define GLIDE_ENDIAN_SHIFT 30 #define GLIDE_ENDIAN_LITTLE (0x1 << GLIDE_ENDIAN_SHIFT) #define GLIDE_ENDIAN_BIG (0x2 << GLIDE_ENDIAN_SHIFT) /* OS is stored in bits [0:6] */ #define GLIDE_OS_SHIFT 0 #define GLIDE_OS_UNIX 0x1 #define GLIDE_OS_DOS32 0x2 #define GLIDE_OS_WIN32 0x4 #define GLIDE_OS_MACOS 0x8 #define GLIDE_OS_OS2 0x10 #define GLIDE_OS_OTHER 0x40 /* For Proprietary Arcade HW */ /* Sim vs. Hardware is stored in bits [7:8] */ #define GLIDE_SST_SHIFT 7 #define GLIDE_SST_SIM (0x1 << GLIDE_SST_SHIFT) #define GLIDE_SST_HW (0x2 << GLIDE_SST_SHIFT) /* Hardware Type is stored in bits [9:13] */ #define GLIDE_HW_SHIFT 9 #define GLIDE_HW_SST1 (0x1 << GLIDE_HW_SHIFT) #define GLIDE_HW_SST96 (0x2 << GLIDE_HW_SHIFT) #define GLIDE_HW_H3 (0x4 << GLIDE_HW_SHIFT) #define GLIDE_HW_SST2 (0x8 << GLIDE_HW_SHIFT) #define GLIDE_HW_CVG (0x10 << GLIDE_HW_SHIFT) /* ** Make sure we handle all instances of WIN32 */ #ifndef __WIN32__ # if defined (_WIN32) || defined (WIN32) || defined(__NT__) # define __WIN32__ # endif #endif /* We need two checks on the OS: one for endian, the other for OS */ /* Check for endianness */ #if defined(__IRIX__) || defined(__sparc__) || defined(MACOS) # define GLIDE_ENDIAN GLIDE_ENDIAN_BIG #else # define GLIDE_ENDIAN GLIDE_ENDIAN_LITTLE #endif /* Check for OS */ #if defined(__IRIX__) || defined(__sparc__) || defined(__linux__) || \ defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ defined(__APPLE__) || defined(__FreeBSD_kernel__) || defined(__GNU__) # define GLIDE_OS GLIDE_OS_UNIX #elif defined(__DOS__) # define GLIDE_OS GLIDE_OS_DOS32 #elif defined(__WIN32__) # define GLIDE_OS GLIDE_OS_WIN32 #elif defined(macintosh) # define GLIDE_OS GLIDE_OS_MACOS #else #error "Unknown OS" #endif /* Check for Simulator vs. Hardware */ #if HAL_CSIM || HWC_CSIM # define GLIDE_SST GLIDE_SST_SIM #else # define GLIDE_SST GLIDE_SST_HW #endif /* Check for type of hardware */ #ifdef SST96 # define GLIDE_HW GLIDE_HW_SST96 #elif defined(H3) # define GLIDE_HW GLIDE_HW_H3 #elif defined(SST2) # define GLIDE_HW GLIDE_HW_SST2 #elif defined(CVG) # define GLIDE_HW GLIDE_HW_CVG #else /* Default to SST1 */ # define GLIDE_HW GLIDE_HW_SST1 #endif #define GLIDE_PLATFORM (GLIDE_ENDIAN | GLIDE_OS | GLIDE_SST | GLIDE_HW) /* ** Control the number of TMUs */ #ifndef GLIDE_NUM_TMU # define GLIDE_NUM_TMU 2 #endif #if ((GLIDE_NUM_TMU < 0) || (GLIDE_NUM_TMU > 3)) # error "GLIDE_NUM_TMU set to an invalid value" #endif #endif /* __GLIDESYS_H__ */ mupen64plus-video-glide64-src-2.6.0/src/wrapper/glideutl.h000066400000000000000000000074231464507525600233230ustar00rootroot00000000000000/* ** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY ** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT ** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX ** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE ** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com). ** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER ** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A ** FULL TEXT OF THE NON-WARRANTY PROVISIONS. ** ** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO ** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN ** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, ** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR ** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF ** THE UNITED STATES. ** ** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED ** ** $Header: /cvsroot/glide/glide3x/h5/glide3/src/glideutl.h,v 1.3.4.2 2003/06/05 08:23:53 koolsmoky Exp $ ** $Log: ** 3 3dfx 1.0.1.0.1.0 10/11/00 Brent Forced check in to enforce ** branching. ** 2 3dfx 1.0.1.0 06/20/00 Joseph Kain Changes to support the ** Napalm Glide open source release. Changes include cleaned up offensive ** comments and new legal headers. ** 1 3dfx 1.0 09/11/99 StarTeam VTS Administrator ** $ ** ** 4 7/24/98 1:41p Hohn ** ** 3 1/30/98 4:27p Atai ** gufog* prototype ** ** 1 1/29/98 4:00p Atai * * 1 1/16/98 4:29p Atai * create glide 3 src * * 11 1/07/98 11:18a Atai * remove GrMipMapInfo and GrGC.mm_table in glide3 * * 10 1/06/98 6:47p Atai * undo grSplash and remove gu routines * * 9 1/05/98 6:04p Atai * move 3df gu related data structure from glide.h to glideutl.h * * 8 12/18/97 2:13p Peter * fogTable cataclysm * * 7 12/15/97 5:52p Atai * disable obsolete glide2 api for glide3 * * 6 8/14/97 5:32p Pgj * remove dead code per GMT * * 5 6/12/97 5:19p Pgj * Fix bug 578 * * 4 3/05/97 9:36p Jdt * Removed guFbWriteRegion added guEncodeRLE16 * * 3 1/16/97 3:45p Dow * Embedded fn protos in ifndef FX_GLIDE_NO_FUNC_PROTO */ /* Glide Utility routines */ #ifndef __GLIDEUTL_H__ #define __GLIDEUTL_H__ #ifdef __cplusplus extern "C" { #endif /* ** 3DF texture file structs */ typedef struct { FxU32 width, height; int small_lod, large_lod; GrAspectRatio_t aspect_ratio; GrTextureFormat_t format; } Gu3dfHeader; typedef struct { FxU8 yRGB[16]; FxI16 iRGB[4][3]; FxI16 qRGB[4][3]; FxU32 packed_data[12]; } GuNccTable; typedef struct { FxU32 data[256]; } GuTexPalette; typedef union { GuNccTable nccTable; GuTexPalette palette; } GuTexTable; typedef struct { Gu3dfHeader header; GuTexTable table; void *data; FxU32 mem_required; /* memory required for mip map in bytes. */ } Gu3dfInfo; #ifndef FX_GLIDE_NO_FUNC_PROTO /* ** Gamma functions */ FX_ENTRY void FX_CALL guGammaCorrectionRGB( FxFloat red, FxFloat green, FxFloat blue ); /* ** fog stuff */ FX_ENTRY float FX_CALL guFogTableIndexToW( int i ); FX_ENTRY void FX_CALL guFogGenerateExp( GrFog_t *fogtable, float density ); FX_ENTRY void FX_CALL guFogGenerateExp2( GrFog_t *fogtable, float density ); FX_ENTRY void FX_CALL guFogGenerateLinear(GrFog_t *fogtable, float nearZ, float farZ ); /* ** hi-level texture manipulation tools. */ FX_ENTRY FxBool FX_CALL gu3dfGetInfo( const char *filename, Gu3dfInfo *info ); FX_ENTRY FxBool FX_CALL gu3dfLoad( const char *filename, Gu3dfInfo *data ); #endif /* FX_GLIDE_NO_FUNC_PROTO */ #ifdef __cplusplus } #endif #endif /* __GLIDEUTL_H__ */ mupen64plus-video-glide64-src-2.6.0/src/wrapper/hq2x.cpp000066400000000000000000001623051464507525600227300ustar00rootroot00000000000000/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus - hq2x.cpp * * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2003 MaxSt ( maxst@hiend3d.com ) * * * * 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 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include static int LUT16to32[65536]; static int RGBtoYUV[65536]; static int YUV1, YUV2; const int Ymask = 0x00FF0000; const int Umask = 0x0000FF00; const int Vmask = 0x000000FF; const int trY = 0x00300000; const int trU = 0x00000700; const int trV = 0x00000006; inline void Interp1(unsigned char * pc, int c1, int c2) { *((int*)pc) = (c1*3+c2) >> 2; } inline void Interp2(unsigned char * pc, int c1, int c2, int c3) { *((int*)pc) = (c1*2+c2+c3) >> 2; } inline void Interp5(unsigned char * pc, int c1, int c2) { *((int*)pc) = (c1+c2) >> 1; } inline void Interp6(unsigned char * pc, int c1, int c2, int c3) { //*((int*)pc) = (c1*5+c2*2+c3)/8; *((int*)pc) = ((((c1 & 0x00FF00)*5 + (c2 & 0x00FF00)*2 + (c3 & 0x00FF00) ) & 0x0007F800) + (((c1 & 0xFF00FF)*5 + (c2 & 0xFF00FF)*2 + (c3 & 0xFF00FF) ) & 0x07F807F8)) >> 3; } inline void Interp7(unsigned char * pc, int c1, int c2, int c3) { //*((int*)pc) = (c1*6+c2+c3)/8; *((int*)pc) = ((((c1 & 0x00FF00)*6 + (c2 & 0x00FF00) + (c3 & 0x00FF00) ) & 0x0007F800) + (((c1 & 0xFF00FF)*6 + (c2 & 0xFF00FF) + (c3 & 0xFF00FF) ) & 0x07F807F8)) >> 3; } inline void Interp9(unsigned char * pc, int c1, int c2, int c3) { //*((int*)pc) = (c1*2+(c2+c3)*3)/8; *((int*)pc) = ((((c1 & 0x00FF00)*2 + ((c2 & 0x00FF00) + (c3 & 0x00FF00))*3 ) & 0x0007F800) + (((c1 & 0xFF00FF)*2 + ((c2 & 0xFF00FF) + (c3 & 0xFF00FF))*3 ) & 0x07F807F8)) >> 3; } inline void Interp10(unsigned char * pc, int c1, int c2, int c3) { //*((int*)pc) = (c1*14+c2+c3)/16; *((int*)pc) = ((((c1 & 0x00FF00)*14 + (c2 & 0x00FF00) + (c3 & 0x00FF00) ) & 0x000FF000) + (((c1 & 0xFF00FF)*14 + (c2 & 0xFF00FF) + (c3 & 0xFF00FF) ) & 0x0FF00FF0)) >> 4; } #define PIXEL00_0 *((int*)(pOut)) = c[5]; #define PIXEL00_10 Interp1(pOut, c[5], c[1]); #define PIXEL00_11 Interp1(pOut, c[5], c[4]); #define PIXEL00_12 Interp1(pOut, c[5], c[2]); #define PIXEL00_20 Interp2(pOut, c[5], c[4], c[2]); #define PIXEL00_21 Interp2(pOut, c[5], c[1], c[2]); #define PIXEL00_22 Interp2(pOut, c[5], c[1], c[4]); #define PIXEL00_60 Interp6(pOut, c[5], c[2], c[4]); #define PIXEL00_61 Interp6(pOut, c[5], c[4], c[2]); #define PIXEL00_70 Interp7(pOut, c[5], c[4], c[2]); #define PIXEL00_90 Interp9(pOut, c[5], c[4], c[2]); #define PIXEL00_100 Interp10(pOut, c[5], c[4], c[2]); #define PIXEL01_0 *((int*)(pOut+4)) = c[5]; #define PIXEL01_10 Interp1(pOut+4, c[5], c[3]); #define PIXEL01_11 Interp1(pOut+4, c[5], c[2]); #define PIXEL01_12 Interp1(pOut+4, c[5], c[6]); #define PIXEL01_20 Interp2(pOut+4, c[5], c[2], c[6]); #define PIXEL01_21 Interp2(pOut+4, c[5], c[3], c[6]); #define PIXEL01_22 Interp2(pOut+4, c[5], c[3], c[2]); #define PIXEL01_60 Interp6(pOut+4, c[5], c[6], c[2]); #define PIXEL01_61 Interp6(pOut+4, c[5], c[2], c[6]); #define PIXEL01_70 Interp7(pOut+4, c[5], c[2], c[6]); #define PIXEL01_90 Interp9(pOut+4, c[5], c[2], c[6]); #define PIXEL01_100 Interp10(pOut+4, c[5], c[2], c[6]); #define PIXEL10_0 *((int*)(pOut+BpL)) = c[5]; #define PIXEL10_10 Interp1(pOut+BpL, c[5], c[7]); #define PIXEL10_11 Interp1(pOut+BpL, c[5], c[8]); #define PIXEL10_12 Interp1(pOut+BpL, c[5], c[4]); #define PIXEL10_20 Interp2(pOut+BpL, c[5], c[8], c[4]); #define PIXEL10_21 Interp2(pOut+BpL, c[5], c[7], c[4]); #define PIXEL10_22 Interp2(pOut+BpL, c[5], c[7], c[8]); #define PIXEL10_60 Interp6(pOut+BpL, c[5], c[4], c[8]); #define PIXEL10_61 Interp6(pOut+BpL, c[5], c[8], c[4]); #define PIXEL10_70 Interp7(pOut+BpL, c[5], c[8], c[4]); #define PIXEL10_90 Interp9(pOut+BpL, c[5], c[8], c[4]); #define PIXEL10_100 Interp10(pOut+BpL, c[5], c[8], c[4]); #define PIXEL11_0 *((int*)(pOut+BpL+4)) = c[5]; #define PIXEL11_10 Interp1(pOut+BpL+4, c[5], c[9]); #define PIXEL11_11 Interp1(pOut+BpL+4, c[5], c[6]); #define PIXEL11_12 Interp1(pOut+BpL+4, c[5], c[8]); #define PIXEL11_20 Interp2(pOut+BpL+4, c[5], c[6], c[8]); #define PIXEL11_21 Interp2(pOut+BpL+4, c[5], c[9], c[8]); #define PIXEL11_22 Interp2(pOut+BpL+4, c[5], c[9], c[6]); #define PIXEL11_60 Interp6(pOut+BpL+4, c[5], c[8], c[6]); #define PIXEL11_61 Interp6(pOut+BpL+4, c[5], c[6], c[8]); #define PIXEL11_70 Interp7(pOut+BpL+4, c[5], c[6], c[8]); #define PIXEL11_90 Interp9(pOut+BpL+4, c[5], c[6], c[8]); #define PIXEL11_100 Interp10(pOut+BpL+4, c[5], c[6], c[8]); inline bool Diff(unsigned int w1, unsigned int w2) { YUV1 = RGBtoYUV[w1]; YUV2 = RGBtoYUV[w2]; return ( ( abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY ) || ( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) || ( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) ); } static void InitLUTs(void) { int i, j, k, r, g, b, Y, u, v; for (i=0; i<65536; i++) LUT16to32[i] = ((i & 0xF800) << 8) + ((i & 0x07E0) << 5) + ((i & 0x001F) << 3); for (i=0; i<32; i++) for (j=0; j<64; j++) for (k=0; k<32; k++) { r = i << 3; g = j << 2; b = k << 3; Y = (r + g + b) >> 2; u = 128 + ((r - b) >> 2); v = 128 + ((-r + 2*g -b)>>3); RGBtoYUV[ (i << 11) + (j << 5) + k ] = (Y<<16) + (u<<8) + v; } } void hq2x_32( unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int BpL ) { int i, j, k; int prevline, nextline; int w[10]; int c[10]; static int lut_initialized = 0; if(!lut_initialized) { InitLUTs(); lut_initialized = 1; } unsigned char *pOut1 = pOut; unsigned char *pIn1 = pIn; // +----+----+----+ // | | | | // | w1 | w2 | w3 | // +----+----+----+ // | | | | // | w4 | w5 | w6 | // +----+----+----+ // | | | | // | w7 | w8 | w9 | // +----+----+----+ for (j=0; j0) prevline = -Xres*2; else prevline = 0; if (j0) prevline = -Xres*4; else prevline = 0; if (j> 3) & 0x1F) << 11) | (((w[2] >> 10) & 0x3F) << 5) | ((w[2] >> 19) & 0x1F); w[5] = (((w[5] >> 3) & 0x1F) << 11) | (((w[5] >> 10) & 0x3F) << 5) | ((w[5] >> 19) & 0x1F); w[8] = (((w[8] >> 3) & 0x1F) << 11) | (((w[8] >> 10) & 0x3F) << 5) | ((w[8] >> 19) & 0x1F); if (i>0) { /*w[1] = *((unsigned short*)(pIn + prevline - 2)); w[4] = *((unsigned short*)(pIn - 2)); w[7] = *((unsigned short*)(pIn + nextline - 2));*/ w[1] = *((unsigned int*)(pIn + prevline - 4)); w[4] = *((unsigned int*)(pIn - 4)); w[7] = *((unsigned int*)(pIn + nextline - 4)); w[1] = (((w[1] >> 3) & 0x1F) << 11) | (((w[1] >> 10) & 0x3F) << 5) | ((w[1] >> 19) & 0x1F); w[4] = (((w[4] >> 3) & 0x1F) << 11) | (((w[4] >> 10) & 0x3F) << 5) | ((w[4] >> 19) & 0x1F); w[7] = (((w[7] >> 3) & 0x1F) << 11) | (((w[7] >> 10) & 0x3F) << 5) | ((w[7] >> 19) & 0x1F); } else { w[1] = w[2]; w[4] = w[5]; w[7] = w[8]; } if (i> 3) & 0x1F) << 11) | (((w[3] >> 10) & 0x3F) << 5) | ((w[3] >> 19) & 0x1F); w[6] = (((w[6] >> 3) & 0x1F) << 11) | (((w[6] >> 10) & 0x3F) << 5) | ((w[6] >> 19) & 0x1F); w[9] = (((w[9] >> 3) & 0x1F) << 11) | (((w[9] >> 10) & 0x3F) << 5) | ((w[9] >> 19) & 0x1F); } else { w[3] = w[2]; w[6] = w[5]; w[9] = w[8]; } int pattern = 0; int flag = 1; YUV1 = RGBtoYUV[w[5]]; for (k=1; k<=9; k++) { if (k==5) continue; if ( w[k] != w[5] ) { YUV2 = RGBtoYUV[w[k]]; if ( ( abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY ) || ( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) || ( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) ) pattern |= flag; } flag <<= 1; } for (k=1; k<=9; k++) c[k] = LUT16to32[w[k]]; switch (pattern) { case 0: case 1: case 4: case 32: case 128: case 5: case 132: case 160: case 33: case 129: case 36: case 133: case 164: case 161: case 37: case 165: { PIXEL00_20 PIXEL01_20 PIXEL10_20 PIXEL11_20 break; } case 2: case 34: case 130: case 162: { PIXEL00_22 PIXEL01_21 PIXEL10_20 PIXEL11_20 break; } case 16: case 17: case 48: case 49: { PIXEL00_20 PIXEL01_22 PIXEL10_20 PIXEL11_21 break; } case 64: case 65: case 68: case 69: { PIXEL00_20 PIXEL01_20 PIXEL10_21 PIXEL11_22 break; } case 8: case 12: case 136: case 140: { PIXEL00_21 PIXEL01_20 PIXEL10_22 PIXEL11_20 break; } case 3: case 35: case 131: case 163: { PIXEL00_11 PIXEL01_21 PIXEL10_20 PIXEL11_20 break; } case 6: case 38: case 134: case 166: { PIXEL00_22 PIXEL01_12 PIXEL10_20 PIXEL11_20 break; } case 20: case 21: case 52: case 53: { PIXEL00_20 PIXEL01_11 PIXEL10_20 PIXEL11_21 break; } case 144: case 145: case 176: case 177: { PIXEL00_20 PIXEL01_22 PIXEL10_20 PIXEL11_12 break; } case 192: case 193: case 196: case 197: { PIXEL00_20 PIXEL01_20 PIXEL10_21 PIXEL11_11 break; } case 96: case 97: case 100: case 101: { PIXEL00_20 PIXEL01_20 PIXEL10_12 PIXEL11_22 break; } case 40: case 44: case 168: case 172: { PIXEL00_21 PIXEL01_20 PIXEL10_11 PIXEL11_20 break; } case 9: case 13: case 137: case 141: { PIXEL00_12 PIXEL01_20 PIXEL10_22 PIXEL11_20 break; } case 18: case 50: { PIXEL00_22 if (Diff(w[2], w[6])) { PIXEL01_10 } else { PIXEL01_20 } PIXEL10_20 PIXEL11_21 break; } case 80: case 81: { PIXEL00_20 PIXEL01_22 PIXEL10_21 if (Diff(w[6], w[8])) { PIXEL11_10 } else { PIXEL11_20 } break; } case 72: case 76: { PIXEL00_21 PIXEL01_20 if (Diff(w[8], w[4])) { PIXEL10_10 } else { PIXEL10_20 } PIXEL11_22 break; } case 10: case 138: { if (Diff(w[4], w[2])) { PIXEL00_10 } else { PIXEL00_20 } PIXEL01_21 PIXEL10_22 PIXEL11_20 break; } case 66: { PIXEL00_22 PIXEL01_21 PIXEL10_21 PIXEL11_22 break; } case 24: { PIXEL00_21 PIXEL01_22 PIXEL10_22 PIXEL11_21 break; } case 7: case 39: case 135: { PIXEL00_11 PIXEL01_12 PIXEL10_20 PIXEL11_20 break; } case 148: case 149: case 180: { PIXEL00_20 PIXEL01_11 PIXEL10_20 PIXEL11_12 break; } case 224: case 228: case 225: { PIXEL00_20 PIXEL01_20 PIXEL10_12 PIXEL11_11 break; } case 41: case 169: case 45: { PIXEL00_12 PIXEL01_20 PIXEL10_11 PIXEL11_20 break; } case 22: case 54: { PIXEL00_22 if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_20 PIXEL11_21 break; } case 208: case 209: { PIXEL00_20 PIXEL01_22 PIXEL10_21 if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 104: case 108: { PIXEL00_21 PIXEL01_20 if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_20 } PIXEL11_22 break; } case 11: case 139: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_21 PIXEL10_22 PIXEL11_20 break; } case 19: case 51: { if (Diff(w[2], w[6])) { PIXEL00_11 PIXEL01_10 } else { PIXEL00_60 PIXEL01_90 } PIXEL10_20 PIXEL11_21 break; } case 146: case 178: { PIXEL00_22 if (Diff(w[2], w[6])) { PIXEL01_10 PIXEL11_12 } else { PIXEL01_90 PIXEL11_61 } PIXEL10_20 break; } case 84: case 85: { PIXEL00_20 if (Diff(w[6], w[8])) { PIXEL01_11 PIXEL11_10 } else { PIXEL01_60 PIXEL11_90 } PIXEL10_21 break; } case 112: case 113: { PIXEL00_20 PIXEL01_22 if (Diff(w[6], w[8])) { PIXEL10_12 PIXEL11_10 } else { PIXEL10_61 PIXEL11_90 } break; } case 200: case 204: { PIXEL00_21 PIXEL01_20 if (Diff(w[8], w[4])) { PIXEL10_10 PIXEL11_11 } else { PIXEL10_90 PIXEL11_60 } break; } case 73: case 77: { if (Diff(w[8], w[4])) { PIXEL00_12 PIXEL10_10 } else { PIXEL00_61 PIXEL10_90 } PIXEL01_20 PIXEL11_22 break; } case 42: case 170: { if (Diff(w[4], w[2])) { PIXEL00_10 PIXEL10_11 } else { PIXEL00_90 PIXEL10_60 } PIXEL01_21 PIXEL11_20 break; } case 14: case 142: { if (Diff(w[4], w[2])) { PIXEL00_10 PIXEL01_12 } else { PIXEL00_90 PIXEL01_61 } PIXEL10_22 PIXEL11_20 break; } case 67: { PIXEL00_11 PIXEL01_21 PIXEL10_21 PIXEL11_22 break; } case 70: { PIXEL00_22 PIXEL01_12 PIXEL10_21 PIXEL11_22 break; } case 28: { PIXEL00_21 PIXEL01_11 PIXEL10_22 PIXEL11_21 break; } case 152: { PIXEL00_21 PIXEL01_22 PIXEL10_22 PIXEL11_12 break; } case 194: { PIXEL00_22 PIXEL01_21 PIXEL10_21 PIXEL11_11 break; } case 98: { PIXEL00_22 PIXEL01_21 PIXEL10_12 PIXEL11_22 break; } case 56: { PIXEL00_21 PIXEL01_22 PIXEL10_11 PIXEL11_21 break; } case 25: { PIXEL00_12 PIXEL01_22 PIXEL10_22 PIXEL11_21 break; } case 26: case 31: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_22 PIXEL11_21 break; } case 82: case 214: { PIXEL00_22 if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_21 if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 88: case 248: { PIXEL00_21 PIXEL01_22 if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_20 } if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 74: case 107: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_21 if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_20 } PIXEL11_22 break; } case 27: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_10 PIXEL10_22 PIXEL11_21 break; } case 86: { PIXEL00_22 if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_21 PIXEL11_10 break; } case 216: { PIXEL00_21 PIXEL01_22 PIXEL10_10 if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 106: { PIXEL00_10 PIXEL01_21 if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_20 } PIXEL11_22 break; } case 30: { PIXEL00_10 if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_22 PIXEL11_21 break; } case 210: { PIXEL00_22 PIXEL01_10 PIXEL10_21 if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 120: { PIXEL00_21 PIXEL01_22 if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_20 } PIXEL11_10 break; } case 75: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_21 PIXEL10_10 PIXEL11_22 break; } case 29: { PIXEL00_12 PIXEL01_11 PIXEL10_22 PIXEL11_21 break; } case 198: { PIXEL00_22 PIXEL01_12 PIXEL10_21 PIXEL11_11 break; } case 184: { PIXEL00_21 PIXEL01_22 PIXEL10_11 PIXEL11_12 break; } case 99: { PIXEL00_11 PIXEL01_21 PIXEL10_12 PIXEL11_22 break; } case 57: { PIXEL00_12 PIXEL01_22 PIXEL10_11 PIXEL11_21 break; } case 71: { PIXEL00_11 PIXEL01_12 PIXEL10_21 PIXEL11_22 break; } case 156: { PIXEL00_21 PIXEL01_11 PIXEL10_22 PIXEL11_12 break; } case 226: { PIXEL00_22 PIXEL01_21 PIXEL10_12 PIXEL11_11 break; } case 60: { PIXEL00_21 PIXEL01_11 PIXEL10_11 PIXEL11_21 break; } case 195: { PIXEL00_11 PIXEL01_21 PIXEL10_21 PIXEL11_11 break; } case 102: { PIXEL00_22 PIXEL01_12 PIXEL10_12 PIXEL11_22 break; } case 153: { PIXEL00_12 PIXEL01_22 PIXEL10_22 PIXEL11_12 break; } case 58: { if (Diff(w[4], w[2])) { PIXEL00_10 } else { PIXEL00_70 } if (Diff(w[2], w[6])) { PIXEL01_10 } else { PIXEL01_70 } PIXEL10_11 PIXEL11_21 break; } case 83: { PIXEL00_11 if (Diff(w[2], w[6])) { PIXEL01_10 } else { PIXEL01_70 } PIXEL10_21 if (Diff(w[6], w[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 92: { PIXEL00_21 PIXEL01_11 if (Diff(w[8], w[4])) { PIXEL10_10 } else { PIXEL10_70 } if (Diff(w[6], w[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 202: { if (Diff(w[4], w[2])) { PIXEL00_10 } else { PIXEL00_70 } PIXEL01_21 if (Diff(w[8], w[4])) { PIXEL10_10 } else { PIXEL10_70 } PIXEL11_11 break; } case 78: { if (Diff(w[4], w[2])) { PIXEL00_10 } else { PIXEL00_70 } PIXEL01_12 if (Diff(w[8], w[4])) { PIXEL10_10 } else { PIXEL10_70 } PIXEL11_22 break; } case 154: { if (Diff(w[4], w[2])) { PIXEL00_10 } else { PIXEL00_70 } if (Diff(w[2], w[6])) { PIXEL01_10 } else { PIXEL01_70 } PIXEL10_22 PIXEL11_12 break; } case 114: { PIXEL00_22 if (Diff(w[2], w[6])) { PIXEL01_10 } else { PIXEL01_70 } PIXEL10_12 if (Diff(w[6], w[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 89: { PIXEL00_12 PIXEL01_22 if (Diff(w[8], w[4])) { PIXEL10_10 } else { PIXEL10_70 } if (Diff(w[6], w[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 90: { if (Diff(w[4], w[2])) { PIXEL00_10 } else { PIXEL00_70 } if (Diff(w[2], w[6])) { PIXEL01_10 } else { PIXEL01_70 } if (Diff(w[8], w[4])) { PIXEL10_10 } else { PIXEL10_70 } if (Diff(w[6], w[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 55: case 23: { if (Diff(w[2], w[6])) { PIXEL00_11 PIXEL01_0 } else { PIXEL00_60 PIXEL01_90 } PIXEL10_20 PIXEL11_21 break; } case 182: case 150: { PIXEL00_22 if (Diff(w[2], w[6])) { PIXEL01_0 PIXEL11_12 } else { PIXEL01_90 PIXEL11_61 } PIXEL10_20 break; } case 213: case 212: { PIXEL00_20 if (Diff(w[6], w[8])) { PIXEL01_11 PIXEL11_0 } else { PIXEL01_60 PIXEL11_90 } PIXEL10_21 break; } case 241: case 240: { PIXEL00_20 PIXEL01_22 if (Diff(w[6], w[8])) { PIXEL10_12 PIXEL11_0 } else { PIXEL10_61 PIXEL11_90 } break; } case 236: case 232: { PIXEL00_21 PIXEL01_20 if (Diff(w[8], w[4])) { PIXEL10_0 PIXEL11_11 } else { PIXEL10_90 PIXEL11_60 } break; } case 109: case 105: { if (Diff(w[8], w[4])) { PIXEL00_12 PIXEL10_0 } else { PIXEL00_61 PIXEL10_90 } PIXEL01_20 PIXEL11_22 break; } case 171: case 43: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL10_11 } else { PIXEL00_90 PIXEL10_60 } PIXEL01_21 PIXEL11_20 break; } case 143: case 15: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL01_12 } else { PIXEL00_90 PIXEL01_61 } PIXEL10_22 PIXEL11_20 break; } case 124: { PIXEL00_21 PIXEL01_11 if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_20 } PIXEL11_10 break; } case 203: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_21 PIXEL10_10 PIXEL11_11 break; } case 62: { PIXEL00_10 if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_11 PIXEL11_21 break; } case 211: { PIXEL00_11 PIXEL01_10 PIXEL10_21 if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 118: { PIXEL00_22 if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_12 PIXEL11_10 break; } case 217: { PIXEL00_12 PIXEL01_22 PIXEL10_10 if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 110: { PIXEL00_10 PIXEL01_12 if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_20 } PIXEL11_22 break; } case 155: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_10 PIXEL10_22 PIXEL11_12 break; } case 188: { PIXEL00_21 PIXEL01_11 PIXEL10_11 PIXEL11_12 break; } case 185: { PIXEL00_12 PIXEL01_22 PIXEL10_11 PIXEL11_12 break; } case 61: { PIXEL00_12 PIXEL01_11 PIXEL10_11 PIXEL11_21 break; } case 157: { PIXEL00_12 PIXEL01_11 PIXEL10_22 PIXEL11_12 break; } case 103: { PIXEL00_11 PIXEL01_12 PIXEL10_12 PIXEL11_22 break; } case 227: { PIXEL00_11 PIXEL01_21 PIXEL10_12 PIXEL11_11 break; } case 230: { PIXEL00_22 PIXEL01_12 PIXEL10_12 PIXEL11_11 break; } case 199: { PIXEL00_11 PIXEL01_12 PIXEL10_21 PIXEL11_11 break; } case 220: { PIXEL00_21 PIXEL01_11 if (Diff(w[8], w[4])) { PIXEL10_10 } else { PIXEL10_70 } if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 158: { if (Diff(w[4], w[2])) { PIXEL00_10 } else { PIXEL00_70 } if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_22 PIXEL11_12 break; } case 234: { if (Diff(w[4], w[2])) { PIXEL00_10 } else { PIXEL00_70 } PIXEL01_21 if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_20 } PIXEL11_11 break; } case 242: { PIXEL00_22 if (Diff(w[2], w[6])) { PIXEL01_10 } else { PIXEL01_70 } PIXEL10_12 if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 59: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } if (Diff(w[2], w[6])) { PIXEL01_10 } else { PIXEL01_70 } PIXEL10_11 PIXEL11_21 break; } case 121: { PIXEL00_12 PIXEL01_22 if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_20 } if (Diff(w[6], w[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 87: { PIXEL00_11 if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_21 if (Diff(w[6], w[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 79: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_12 if (Diff(w[8], w[4])) { PIXEL10_10 } else { PIXEL10_70 } PIXEL11_22 break; } case 122: { if (Diff(w[4], w[2])) { PIXEL00_10 } else { PIXEL00_70 } if (Diff(w[2], w[6])) { PIXEL01_10 } else { PIXEL01_70 } if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_20 } if (Diff(w[6], w[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 94: { if (Diff(w[4], w[2])) { PIXEL00_10 } else { PIXEL00_70 } if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_20 } if (Diff(w[8], w[4])) { PIXEL10_10 } else { PIXEL10_70 } if (Diff(w[6], w[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 218: { if (Diff(w[4], w[2])) { PIXEL00_10 } else { PIXEL00_70 } if (Diff(w[2], w[6])) { PIXEL01_10 } else { PIXEL01_70 } if (Diff(w[8], w[4])) { PIXEL10_10 } else { PIXEL10_70 } if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 91: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } if (Diff(w[2], w[6])) { PIXEL01_10 } else { PIXEL01_70 } if (Diff(w[8], w[4])) { PIXEL10_10 } else { PIXEL10_70 } if (Diff(w[6], w[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 229: { PIXEL00_20 PIXEL01_20 PIXEL10_12 PIXEL11_11 break; } case 167: { PIXEL00_11 PIXEL01_12 PIXEL10_20 PIXEL11_20 break; } case 173: { PIXEL00_12 PIXEL01_20 PIXEL10_11 PIXEL11_20 break; } case 181: { PIXEL00_20 PIXEL01_11 PIXEL10_20 PIXEL11_12 break; } case 186: { if (Diff(w[4], w[2])) { PIXEL00_10 } else { PIXEL00_70 } if (Diff(w[2], w[6])) { PIXEL01_10 } else { PIXEL01_70 } PIXEL10_11 PIXEL11_12 break; } case 115: { PIXEL00_11 if (Diff(w[2], w[6])) { PIXEL01_10 } else { PIXEL01_70 } PIXEL10_12 if (Diff(w[6], w[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 93: { PIXEL00_12 PIXEL01_11 if (Diff(w[8], w[4])) { PIXEL10_10 } else { PIXEL10_70 } if (Diff(w[6], w[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 206: { if (Diff(w[4], w[2])) { PIXEL00_10 } else { PIXEL00_70 } PIXEL01_12 if (Diff(w[8], w[4])) { PIXEL10_10 } else { PIXEL10_70 } PIXEL11_11 break; } case 205: case 201: { PIXEL00_12 PIXEL01_20 if (Diff(w[8], w[4])) { PIXEL10_10 } else { PIXEL10_70 } PIXEL11_11 break; } case 174: case 46: { if (Diff(w[4], w[2])) { PIXEL00_10 } else { PIXEL00_70 } PIXEL01_12 PIXEL10_11 PIXEL11_20 break; } case 179: case 147: { PIXEL00_11 if (Diff(w[2], w[6])) { PIXEL01_10 } else { PIXEL01_70 } PIXEL10_20 PIXEL11_12 break; } case 117: case 116: { PIXEL00_20 PIXEL01_11 PIXEL10_12 if (Diff(w[6], w[8])) { PIXEL11_10 } else { PIXEL11_70 } break; } case 189: { PIXEL00_12 PIXEL01_11 PIXEL10_11 PIXEL11_12 break; } case 231: { PIXEL00_11 PIXEL01_12 PIXEL10_12 PIXEL11_11 break; } case 126: { PIXEL00_10 if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_20 } if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_20 } PIXEL11_10 break; } case 219: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_10 PIXEL10_10 if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 125: { if (Diff(w[8], w[4])) { PIXEL00_12 PIXEL10_0 } else { PIXEL00_61 PIXEL10_90 } PIXEL01_11 PIXEL11_10 break; } case 221: { PIXEL00_12 if (Diff(w[6], w[8])) { PIXEL01_11 PIXEL11_0 } else { PIXEL01_60 PIXEL11_90 } PIXEL10_10 break; } case 207: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL01_12 } else { PIXEL00_90 PIXEL01_61 } PIXEL10_10 PIXEL11_11 break; } case 238: { PIXEL00_10 PIXEL01_12 if (Diff(w[8], w[4])) { PIXEL10_0 PIXEL11_11 } else { PIXEL10_90 PIXEL11_60 } break; } case 190: { PIXEL00_10 if (Diff(w[2], w[6])) { PIXEL01_0 PIXEL11_12 } else { PIXEL01_90 PIXEL11_61 } PIXEL10_11 break; } case 187: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL10_11 } else { PIXEL00_90 PIXEL10_60 } PIXEL01_10 PIXEL11_12 break; } case 243: { PIXEL00_11 PIXEL01_10 if (Diff(w[6], w[8])) { PIXEL10_12 PIXEL11_0 } else { PIXEL10_61 PIXEL11_90 } break; } case 119: { if (Diff(w[2], w[6])) { PIXEL00_11 PIXEL01_0 } else { PIXEL00_60 PIXEL01_90 } PIXEL10_12 PIXEL11_10 break; } case 237: case 233: { PIXEL00_12 PIXEL01_20 if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_100 } PIXEL11_11 break; } case 175: case 47: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_100 } PIXEL01_12 PIXEL10_11 PIXEL11_20 break; } case 183: case 151: { PIXEL00_11 if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_100 } PIXEL10_20 PIXEL11_12 break; } case 245: case 244: { PIXEL00_20 PIXEL01_11 PIXEL10_12 if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_100 } break; } case 250: { PIXEL00_10 PIXEL01_10 if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_20 } if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 123: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_10 if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_20 } PIXEL11_10 break; } case 95: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_10 PIXEL11_10 break; } case 222: { PIXEL00_10 if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_10 if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 252: { PIXEL00_21 PIXEL01_11 if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_20 } if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_100 } break; } case 249: { PIXEL00_12 PIXEL01_22 if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_100 } if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 235: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_21 if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_100 } PIXEL11_11 break; } case 111: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_100 } PIXEL01_12 if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_20 } PIXEL11_22 break; } case 63: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_100 } if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_11 PIXEL11_21 break; } case 159: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_100 } PIXEL10_22 PIXEL11_12 break; } case 215: { PIXEL00_11 if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_100 } PIXEL10_21 if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 246: { PIXEL00_22 if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_20 } PIXEL10_12 if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_100 } break; } case 254: { PIXEL00_10 if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_20 } if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_20 } if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_100 } break; } case 253: { PIXEL00_12 PIXEL01_11 if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_100 } if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_100 } break; } case 251: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_10 if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_100 } if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 239: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_100 } PIXEL01_12 if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_100 } PIXEL11_11 break; } case 127: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_100 } if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_20 } if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_20 } PIXEL11_10 break; } case 191: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_100 } if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_100 } PIXEL10_11 PIXEL11_12 break; } case 223: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_100 } PIXEL10_10 if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_20 } break; } case 247: { PIXEL00_11 if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_100 } PIXEL10_12 if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_100 } break; } case 255: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_100 } if (Diff(w[2], w[6])) { PIXEL01_0 } else { PIXEL01_100 } if (Diff(w[8], w[4])) { PIXEL10_0 } else { PIXEL10_100 } if (Diff(w[6], w[8])) { PIXEL11_0 } else { PIXEL11_100 } break; } } //pIn+=2; pIn+=4; pOut+=8; } pOut+=BpL; } for (j=0; j #include #include static int LUT16to32[65536]; static int RGBtoYUV[65536]; static int YUV1, YUV2; const int Ymask = 0x00FF0000; const int Umask = 0x0000FF00; const int Vmask = 0x000000FF; const int trY = 0x00300000; const int trU = 0x00000700; const int trV = 0x00000006; inline void Interp1(unsigned char * pc, int c1, int c2) { *((int*)pc) = (c1*3+c2) >> 2; } inline void Interp2(unsigned char * pc, int c1, int c2, int c3) { *((int*)pc) = (c1*2+c2+c3) >> 2; } inline void Interp3(unsigned char * pc, int c1, int c2) { //*((int*)pc) = (c1*7+c2)/8; *((int*)pc) = ((((c1 & 0x00FF00)*7 + (c2 & 0x00FF00) ) & 0x0007F800) + (((c1 & 0xFF00FF)*7 + (c2 & 0xFF00FF) ) & 0x07F807F8)) >> 3; } inline void Interp5(unsigned char * pc, int c1, int c2) { *((int*)pc) = (c1+c2) >> 1; } inline void Interp6(unsigned char * pc, int c1, int c2, int c3) { //*((int*)pc) = (c1*5+c2*2+c3)/8; *((int*)pc) = ((((c1 & 0x00FF00)*5 + (c2 & 0x00FF00)*2 + (c3 & 0x00FF00) ) & 0x0007F800) + (((c1 & 0xFF00FF)*5 + (c2 & 0xFF00FF)*2 + (c3 & 0xFF00FF) ) & 0x07F807F8)) >> 3; } inline void Interp7(unsigned char * pc, int c1, int c2, int c3) { //*((int*)pc) = (c1*6+c2+c3)/8; *((int*)pc) = ((((c1 & 0x00FF00)*6 + (c2 & 0x00FF00) + (c3 & 0x00FF00) ) & 0x0007F800) + (((c1 & 0xFF00FF)*6 + (c2 & 0xFF00FF) + (c3 & 0xFF00FF) ) & 0x07F807F8)) >> 3; } inline void Interp8(unsigned char * pc, int c1, int c2) { //*((int*)pc) = (c1*5+c2*3)/8; *((int*)pc) = ((((c1 & 0x00FF00)*5 + (c2 & 0x00FF00)*3 ) & 0x0007F800) + (((c1 & 0xFF00FF)*5 + (c2 & 0xFF00FF)*3 ) & 0x07F807F8)) >> 3; } #define PIXEL00_0 *((int*)(pOut)) = c[5]; #define PIXEL00_11 Interp1(pOut, c[5], c[4]); #define PIXEL00_12 Interp1(pOut, c[5], c[2]); #define PIXEL00_20 Interp2(pOut, c[5], c[2], c[4]); #define PIXEL00_50 Interp5(pOut, c[2], c[4]); #define PIXEL00_80 Interp8(pOut, c[5], c[1]); #define PIXEL00_81 Interp8(pOut, c[5], c[4]); #define PIXEL00_82 Interp8(pOut, c[5], c[2]); #define PIXEL01_0 *((int*)(pOut+4)) = c[5]; #define PIXEL01_10 Interp1(pOut+4, c[5], c[1]); #define PIXEL01_12 Interp1(pOut+4, c[5], c[2]); #define PIXEL01_14 Interp1(pOut+4, c[2], c[5]); #define PIXEL01_21 Interp2(pOut+4, c[2], c[5], c[4]); #define PIXEL01_31 Interp3(pOut+4, c[5], c[4]); #define PIXEL01_50 Interp5(pOut+4, c[2], c[5]); #define PIXEL01_60 Interp6(pOut+4, c[5], c[2], c[4]); #define PIXEL01_61 Interp6(pOut+4, c[5], c[2], c[1]); #define PIXEL01_82 Interp8(pOut+4, c[5], c[2]); #define PIXEL01_83 Interp8(pOut+4, c[2], c[4]); #define PIXEL02_0 *((int*)(pOut+8)) = c[5]; #define PIXEL02_10 Interp1(pOut+8, c[5], c[3]); #define PIXEL02_11 Interp1(pOut+8, c[5], c[2]); #define PIXEL02_13 Interp1(pOut+8, c[2], c[5]); #define PIXEL02_21 Interp2(pOut+8, c[2], c[5], c[6]); #define PIXEL02_32 Interp3(pOut+8, c[5], c[6]); #define PIXEL02_50 Interp5(pOut+8, c[2], c[5]); #define PIXEL02_60 Interp6(pOut+8, c[5], c[2], c[6]); #define PIXEL02_61 Interp6(pOut+8, c[5], c[2], c[3]); #define PIXEL02_81 Interp8(pOut+8, c[5], c[2]); #define PIXEL02_83 Interp8(pOut+8, c[2], c[6]); #define PIXEL03_0 *((int*)(pOut+12)) = c[5]; #define PIXEL03_11 Interp1(pOut+12, c[5], c[2]); #define PIXEL03_12 Interp1(pOut+12, c[5], c[6]); #define PIXEL03_20 Interp2(pOut+12, c[5], c[2], c[6]); #define PIXEL03_50 Interp5(pOut+12, c[2], c[6]); #define PIXEL03_80 Interp8(pOut+12, c[5], c[3]); #define PIXEL03_81 Interp8(pOut+12, c[5], c[2]); #define PIXEL03_82 Interp8(pOut+12, c[5], c[6]); #define PIXEL10_0 *((int*)(pOut+BpL)) = c[5]; #define PIXEL10_10 Interp1(pOut+BpL, c[5], c[1]); #define PIXEL10_11 Interp1(pOut+BpL, c[5], c[4]); #define PIXEL10_13 Interp1(pOut+BpL, c[4], c[5]); #define PIXEL10_21 Interp2(pOut+BpL, c[4], c[5], c[2]); #define PIXEL10_32 Interp3(pOut+BpL, c[5], c[2]); #define PIXEL10_50 Interp5(pOut+BpL, c[4], c[5]); #define PIXEL10_60 Interp6(pOut+BpL, c[5], c[4], c[2]); #define PIXEL10_61 Interp6(pOut+BpL, c[5], c[4], c[1]); #define PIXEL10_81 Interp8(pOut+BpL, c[5], c[4]); #define PIXEL10_83 Interp8(pOut+BpL, c[4], c[2]); #define PIXEL11_0 *((int*)(pOut+BpL+4)) = c[5]; #define PIXEL11_30 Interp3(pOut+BpL+4, c[5], c[1]); #define PIXEL11_31 Interp3(pOut+BpL+4, c[5], c[4]); #define PIXEL11_32 Interp3(pOut+BpL+4, c[5], c[2]); #define PIXEL11_70 Interp7(pOut+BpL+4, c[5], c[4], c[2]); #define PIXEL12_0 *((int*)(pOut+BpL+8)) = c[5]; #define PIXEL12_30 Interp3(pOut+BpL+8, c[5], c[3]); #define PIXEL12_31 Interp3(pOut+BpL+8, c[5], c[2]); #define PIXEL12_32 Interp3(pOut+BpL+8, c[5], c[6]); #define PIXEL12_70 Interp7(pOut+BpL+8, c[5], c[6], c[2]); #define PIXEL13_0 *((int*)(pOut+BpL+12)) = c[5]; #define PIXEL13_10 Interp1(pOut+BpL+12, c[5], c[3]); #define PIXEL13_12 Interp1(pOut+BpL+12, c[5], c[6]); #define PIXEL13_14 Interp1(pOut+BpL+12, c[6], c[5]); #define PIXEL13_21 Interp2(pOut+BpL+12, c[6], c[5], c[2]); #define PIXEL13_31 Interp3(pOut+BpL+12, c[5], c[2]); #define PIXEL13_50 Interp5(pOut+BpL+12, c[6], c[5]); #define PIXEL13_60 Interp6(pOut+BpL+12, c[5], c[6], c[2]); #define PIXEL13_61 Interp6(pOut+BpL+12, c[5], c[6], c[3]); #define PIXEL13_82 Interp8(pOut+BpL+12, c[5], c[6]); #define PIXEL13_83 Interp8(pOut+BpL+12, c[6], c[2]); #define PIXEL20_0 *((int*)(pOut+BpL+BpL)) = c[5]; #define PIXEL20_10 Interp1(pOut+BpL+BpL, c[5], c[7]); #define PIXEL20_12 Interp1(pOut+BpL+BpL, c[5], c[4]); #define PIXEL20_14 Interp1(pOut+BpL+BpL, c[4], c[5]); #define PIXEL20_21 Interp2(pOut+BpL+BpL, c[4], c[5], c[8]); #define PIXEL20_31 Interp3(pOut+BpL+BpL, c[5], c[8]); #define PIXEL20_50 Interp5(pOut+BpL+BpL, c[4], c[5]); #define PIXEL20_60 Interp6(pOut+BpL+BpL, c[5], c[4], c[8]); #define PIXEL20_61 Interp6(pOut+BpL+BpL, c[5], c[4], c[7]); #define PIXEL20_82 Interp8(pOut+BpL+BpL, c[5], c[4]); #define PIXEL20_83 Interp8(pOut+BpL+BpL, c[4], c[8]); #define PIXEL21_0 *((int*)(pOut+BpL+BpL+4)) = c[5]; #define PIXEL21_30 Interp3(pOut+BpL+BpL+4, c[5], c[7]); #define PIXEL21_31 Interp3(pOut+BpL+BpL+4, c[5], c[8]); #define PIXEL21_32 Interp3(pOut+BpL+BpL+4, c[5], c[4]); #define PIXEL21_70 Interp7(pOut+BpL+BpL+4, c[5], c[4], c[8]); #define PIXEL22_0 *((int*)(pOut+BpL+BpL+8)) = c[5]; #define PIXEL22_30 Interp3(pOut+BpL+BpL+8, c[5], c[9]); #define PIXEL22_31 Interp3(pOut+BpL+BpL+8, c[5], c[6]); #define PIXEL22_32 Interp3(pOut+BpL+BpL+8, c[5], c[8]); #define PIXEL22_70 Interp7(pOut+BpL+BpL+8, c[5], c[6], c[8]); #define PIXEL23_0 *((int*)(pOut+BpL+BpL+12)) = c[5]; #define PIXEL23_10 Interp1(pOut+BpL+BpL+12, c[5], c[9]); #define PIXEL23_11 Interp1(pOut+BpL+BpL+12, c[5], c[6]); #define PIXEL23_13 Interp1(pOut+BpL+BpL+12, c[6], c[5]); #define PIXEL23_21 Interp2(pOut+BpL+BpL+12, c[6], c[5], c[8]); #define PIXEL23_32 Interp3(pOut+BpL+BpL+12, c[5], c[8]); #define PIXEL23_50 Interp5(pOut+BpL+BpL+12, c[6], c[5]); #define PIXEL23_60 Interp6(pOut+BpL+BpL+12, c[5], c[6], c[8]); #define PIXEL23_61 Interp6(pOut+BpL+BpL+12, c[5], c[6], c[9]); #define PIXEL23_81 Interp8(pOut+BpL+BpL+12, c[5], c[6]); #define PIXEL23_83 Interp8(pOut+BpL+BpL+12, c[6], c[8]); #define PIXEL30_0 *((int*)(pOut+BpL+BpL+BpL)) = c[5]; #define PIXEL30_11 Interp1(pOut+BpL+BpL+BpL, c[5], c[8]); #define PIXEL30_12 Interp1(pOut+BpL+BpL+BpL, c[5], c[4]); #define PIXEL30_20 Interp2(pOut+BpL+BpL+BpL, c[5], c[8], c[4]); #define PIXEL30_50 Interp5(pOut+BpL+BpL+BpL, c[8], c[4]); #define PIXEL30_80 Interp8(pOut+BpL+BpL+BpL, c[5], c[7]); #define PIXEL30_81 Interp8(pOut+BpL+BpL+BpL, c[5], c[8]); #define PIXEL30_82 Interp8(pOut+BpL+BpL+BpL, c[5], c[4]); #define PIXEL31_0 *((int*)(pOut+BpL+BpL+BpL+4)) = c[5]; #define PIXEL31_10 Interp1(pOut+BpL+BpL+BpL+4, c[5], c[7]); #define PIXEL31_11 Interp1(pOut+BpL+BpL+BpL+4, c[5], c[8]); #define PIXEL31_13 Interp1(pOut+BpL+BpL+BpL+4, c[8], c[5]); #define PIXEL31_21 Interp2(pOut+BpL+BpL+BpL+4, c[8], c[5], c[4]); #define PIXEL31_32 Interp3(pOut+BpL+BpL+BpL+4, c[5], c[4]); #define PIXEL31_50 Interp5(pOut+BpL+BpL+BpL+4, c[8], c[5]); #define PIXEL31_60 Interp6(pOut+BpL+BpL+BpL+4, c[5], c[8], c[4]); #define PIXEL31_61 Interp6(pOut+BpL+BpL+BpL+4, c[5], c[8], c[7]); #define PIXEL31_81 Interp8(pOut+BpL+BpL+BpL+4, c[5], c[8]); #define PIXEL31_83 Interp8(pOut+BpL+BpL+BpL+4, c[8], c[4]); #define PIXEL32_0 *((int*)(pOut+BpL+BpL+BpL+8)) = c[5]; #define PIXEL32_10 Interp1(pOut+BpL+BpL+BpL+8, c[5], c[9]); #define PIXEL32_12 Interp1(pOut+BpL+BpL+BpL+8, c[5], c[8]); #define PIXEL32_14 Interp1(pOut+BpL+BpL+BpL+8, c[8], c[5]); #define PIXEL32_21 Interp2(pOut+BpL+BpL+BpL+8, c[8], c[5], c[6]); #define PIXEL32_31 Interp3(pOut+BpL+BpL+BpL+8, c[5], c[6]); #define PIXEL32_50 Interp5(pOut+BpL+BpL+BpL+8, c[8], c[5]); #define PIXEL32_60 Interp6(pOut+BpL+BpL+BpL+8, c[5], c[8], c[6]); #define PIXEL32_61 Interp6(pOut+BpL+BpL+BpL+8, c[5], c[8], c[9]); #define PIXEL32_82 Interp8(pOut+BpL+BpL+BpL+8, c[5], c[8]); #define PIXEL32_83 Interp8(pOut+BpL+BpL+BpL+8, c[8], c[6]); #define PIXEL33_0 *((int*)(pOut+BpL+BpL+BpL+12)) = c[5]; #define PIXEL33_11 Interp1(pOut+BpL+BpL+BpL+12, c[5], c[6]); #define PIXEL33_12 Interp1(pOut+BpL+BpL+BpL+12, c[5], c[8]); #define PIXEL33_20 Interp2(pOut+BpL+BpL+BpL+12, c[5], c[8], c[6]); #define PIXEL33_50 Interp5(pOut+BpL+BpL+BpL+12, c[8], c[6]); #define PIXEL33_80 Interp8(pOut+BpL+BpL+BpL+12, c[5], c[9]); #define PIXEL33_81 Interp8(pOut+BpL+BpL+BpL+12, c[5], c[6]); #define PIXEL33_82 Interp8(pOut+BpL+BpL+BpL+12, c[5], c[8]); inline bool Diff(unsigned int w1, unsigned int w2) { YUV1 = RGBtoYUV[w1]; YUV2 = RGBtoYUV[w2]; return ( ( abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY ) || ( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) || ( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) ); } static void InitLUTs(void) { int i, j, k, r, g, b, Y, u, v; for (i=0; i<65536; i++) LUT16to32[i] = ((i & 0xF800) << 8) + ((i & 0x07E0) << 5) + ((i & 0x001F) << 3); for (i=0; i<32; i++) for (j=0; j<64; j++) for (k=0; k<32; k++) { r = i << 3; g = j << 2; b = k << 3; Y = (r + g + b) >> 2; u = 128 + ((r - b) >> 2); v = 128 + ((-r + 2*g -b)>>3); RGBtoYUV[ (i << 11) + (j << 5) + k ] = (Y<<16) + (u<<8) + v; } } void hq4x_32( unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int BpL ) { int i, j, k; int prevline, nextline; int w[10]; int c[10]; static int lut_initialized = 0; if(!lut_initialized) { InitLUTs(); lut_initialized = 1; } unsigned char *pOut1 = pOut; unsigned char *pIn1 = pIn; // +----+----+----+ // | | | | // | w1 | w2 | w3 | // +----+----+----+ // | | | | // | w4 | w5 | w6 | // +----+----+----+ // | | | | // | w7 | w8 | w9 | // +----+----+----+ for (j=0; j0) prevline = -Xres*2; else prevline = 0; if (j0) prevline = -Xres*4; else prevline = 0; if (j> 3) & 0x1F) << 11) | (((w[2] >> 10) & 0x3F) << 5) | ((w[2] >> 19) & 0x1F); w[5] = (((w[5] >> 3) & 0x1F) << 11) | (((w[5] >> 10) & 0x3F) << 5) | ((w[5] >> 19) & 0x1F); w[8] = (((w[8] >> 3) & 0x1F) << 11) | (((w[8] >> 10) & 0x3F) << 5) | ((w[8] >> 19) & 0x1F); if (i>0) { /*w[1] = *((unsigned short*)(pIn + prevline - 2)); w[4] = *((unsigned short*)(pIn - 2)); w[7] = *((unsigned short*)(pIn + nextline - 2));*/ w[1] = *((unsigned int*)(pIn + prevline - 4)); w[4] = *((unsigned int*)(pIn - 4)); w[7] = *((unsigned int*)(pIn + nextline - 4)); w[1] = (((w[1] >> 3) & 0x1F) << 11) | (((w[1] >> 10) & 0x3F) << 5) | ((w[1] >> 19) & 0x1F); w[4] = (((w[4] >> 3) & 0x1F) << 11) | (((w[4] >> 10) & 0x3F) << 5) | ((w[4] >> 19) & 0x1F); w[7] = (((w[7] >> 3) & 0x1F) << 11) | (((w[7] >> 10) & 0x3F) << 5) | ((w[7] >> 19) & 0x1F); } else { w[1] = w[2]; w[4] = w[5]; w[7] = w[8]; } if (i> 3) & 0x1F) << 11) | (((w[3] >> 10) & 0x3F) << 5) | ((w[3] >> 19) & 0x1F); w[6] = (((w[6] >> 3) & 0x1F) << 11) | (((w[6] >> 10) & 0x3F) << 5) | ((w[6] >> 19) & 0x1F); w[9] = (((w[9] >> 3) & 0x1F) << 11) | (((w[9] >> 10) & 0x3F) << 5) | ((w[9] >> 19) & 0x1F); } else { w[3] = w[2]; w[6] = w[5]; w[9] = w[8]; } int pattern = 0; int flag = 1; YUV1 = RGBtoYUV[w[5]]; for (k=1; k<=9; k++) { if (k==5) continue; if ( w[k] != w[5] ) { YUV2 = RGBtoYUV[w[k]]; if ( ( abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY ) || ( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) || ( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) ) pattern |= flag; } flag <<= 1; } for (k=1; k<=9; k++) c[k] = LUT16to32[w[k]]; switch (pattern) { case 0: case 1: case 4: case 32: case 128: case 5: case 132: case 160: case 33: case 129: case 36: case 133: case 164: case 161: case 37: case 165: { PIXEL00_20 PIXEL01_60 PIXEL02_60 PIXEL03_20 PIXEL10_60 PIXEL11_70 PIXEL12_70 PIXEL13_60 PIXEL20_60 PIXEL21_70 PIXEL22_70 PIXEL23_60 PIXEL30_20 PIXEL31_60 PIXEL32_60 PIXEL33_20 break; } case 2: case 34: case 130: case 162: { PIXEL00_80 PIXEL01_10 PIXEL02_10 PIXEL03_80 PIXEL10_61 PIXEL11_30 PIXEL12_30 PIXEL13_61 PIXEL20_60 PIXEL21_70 PIXEL22_70 PIXEL23_60 PIXEL30_20 PIXEL31_60 PIXEL32_60 PIXEL33_20 break; } case 16: case 17: case 48: case 49: { PIXEL00_20 PIXEL01_60 PIXEL02_61 PIXEL03_80 PIXEL10_60 PIXEL11_70 PIXEL12_30 PIXEL13_10 PIXEL20_60 PIXEL21_70 PIXEL22_30 PIXEL23_10 PIXEL30_20 PIXEL31_60 PIXEL32_61 PIXEL33_80 break; } case 64: case 65: case 68: case 69: { PIXEL00_20 PIXEL01_60 PIXEL02_60 PIXEL03_20 PIXEL10_60 PIXEL11_70 PIXEL12_70 PIXEL13_60 PIXEL20_61 PIXEL21_30 PIXEL22_30 PIXEL23_61 PIXEL30_80 PIXEL31_10 PIXEL32_10 PIXEL33_80 break; } case 8: case 12: case 136: case 140: { PIXEL00_80 PIXEL01_61 PIXEL02_60 PIXEL03_20 PIXEL10_10 PIXEL11_30 PIXEL12_70 PIXEL13_60 PIXEL20_10 PIXEL21_30 PIXEL22_70 PIXEL23_60 PIXEL30_80 PIXEL31_61 PIXEL32_60 PIXEL33_20 break; } case 3: case 35: case 131: case 163: { PIXEL00_81 PIXEL01_31 PIXEL02_10 PIXEL03_80 PIXEL10_81 PIXEL11_31 PIXEL12_30 PIXEL13_61 PIXEL20_60 PIXEL21_70 PIXEL22_70 PIXEL23_60 PIXEL30_20 PIXEL31_60 PIXEL32_60 PIXEL33_20 break; } case 6: case 38: case 134: case 166: { PIXEL00_80 PIXEL01_10 PIXEL02_32 PIXEL03_82 PIXEL10_61 PIXEL11_30 PIXEL12_32 PIXEL13_82 PIXEL20_60 PIXEL21_70 PIXEL22_70 PIXEL23_60 PIXEL30_20 PIXEL31_60 PIXEL32_60 PIXEL33_20 break; } case 20: case 21: case 52: case 53: { PIXEL00_20 PIXEL01_60 PIXEL02_81 PIXEL03_81 PIXEL10_60 PIXEL11_70 PIXEL12_31 PIXEL13_31 PIXEL20_60 PIXEL21_70 PIXEL22_30 PIXEL23_10 PIXEL30_20 PIXEL31_60 PIXEL32_61 PIXEL33_80 break; } case 144: case 145: case 176: case 177: { PIXEL00_20 PIXEL01_60 PIXEL02_61 PIXEL03_80 PIXEL10_60 PIXEL11_70 PIXEL12_30 PIXEL13_10 PIXEL20_60 PIXEL21_70 PIXEL22_32 PIXEL23_32 PIXEL30_20 PIXEL31_60 PIXEL32_82 PIXEL33_82 break; } case 192: case 193: case 196: case 197: { PIXEL00_20 PIXEL01_60 PIXEL02_60 PIXEL03_20 PIXEL10_60 PIXEL11_70 PIXEL12_70 PIXEL13_60 PIXEL20_61 PIXEL21_30 PIXEL22_31 PIXEL23_81 PIXEL30_80 PIXEL31_10 PIXEL32_31 PIXEL33_81 break; } case 96: case 97: case 100: case 101: { PIXEL00_20 PIXEL01_60 PIXEL02_60 PIXEL03_20 PIXEL10_60 PIXEL11_70 PIXEL12_70 PIXEL13_60 PIXEL20_82 PIXEL21_32 PIXEL22_30 PIXEL23_61 PIXEL30_82 PIXEL31_32 PIXEL32_10 PIXEL33_80 break; } case 40: case 44: case 168: case 172: { PIXEL00_80 PIXEL01_61 PIXEL02_60 PIXEL03_20 PIXEL10_10 PIXEL11_30 PIXEL12_70 PIXEL13_60 PIXEL20_31 PIXEL21_31 PIXEL22_70 PIXEL23_60 PIXEL30_81 PIXEL31_81 PIXEL32_60 PIXEL33_20 break; } case 9: case 13: case 137: case 141: { PIXEL00_82 PIXEL01_82 PIXEL02_60 PIXEL03_20 PIXEL10_32 PIXEL11_32 PIXEL12_70 PIXEL13_60 PIXEL20_10 PIXEL21_30 PIXEL22_70 PIXEL23_60 PIXEL30_80 PIXEL31_61 PIXEL32_60 PIXEL33_20 break; } case 18: case 50: { PIXEL00_80 PIXEL01_10 if (Diff(w[2], w[6])) { PIXEL02_10 PIXEL03_80 PIXEL12_30 PIXEL13_10 } else { PIXEL02_50 PIXEL03_50 PIXEL12_0 PIXEL13_50 } PIXEL10_61 PIXEL11_30 PIXEL20_60 PIXEL21_70 PIXEL22_30 PIXEL23_10 PIXEL30_20 PIXEL31_60 PIXEL32_61 PIXEL33_80 break; } case 80: case 81: { PIXEL00_20 PIXEL01_60 PIXEL02_61 PIXEL03_80 PIXEL10_60 PIXEL11_70 PIXEL12_30 PIXEL13_10 PIXEL20_61 PIXEL21_30 if (Diff(w[6], w[8])) { PIXEL22_30 PIXEL23_10 PIXEL32_10 PIXEL33_80 } else { PIXEL22_0 PIXEL23_50 PIXEL32_50 PIXEL33_50 } PIXEL30_80 PIXEL31_10 break; } case 72: case 76: { PIXEL00_80 PIXEL01_61 PIXEL02_60 PIXEL03_20 PIXEL10_10 PIXEL11_30 PIXEL12_70 PIXEL13_60 if (Diff(w[8], w[4])) { PIXEL20_10 PIXEL21_30 PIXEL30_80 PIXEL31_10 } else { PIXEL20_50 PIXEL21_0 PIXEL30_50 PIXEL31_50 } PIXEL22_30 PIXEL23_61 PIXEL32_10 PIXEL33_80 break; } case 10: case 138: { if (Diff(w[4], w[2])) { PIXEL00_80 PIXEL01_10 PIXEL10_10 PIXEL11_30 } else { PIXEL00_50 PIXEL01_50 PIXEL10_50 PIXEL11_0 } PIXEL02_10 PIXEL03_80 PIXEL12_30 PIXEL13_61 PIXEL20_10 PIXEL21_30 PIXEL22_70 PIXEL23_60 PIXEL30_80 PIXEL31_61 PIXEL32_60 PIXEL33_20 break; } case 66: { PIXEL00_80 PIXEL01_10 PIXEL02_10 PIXEL03_80 PIXEL10_61 PIXEL11_30 PIXEL12_30 PIXEL13_61 PIXEL20_61 PIXEL21_30 PIXEL22_30 PIXEL23_61 PIXEL30_80 PIXEL31_10 PIXEL32_10 PIXEL33_80 break; } case 24: { PIXEL00_80 PIXEL01_61 PIXEL02_61 PIXEL03_80 PIXEL10_10 PIXEL11_30 PIXEL12_30 PIXEL13_10 PIXEL20_10 PIXEL21_30 PIXEL22_30 PIXEL23_10 PIXEL30_80 PIXEL31_61 PIXEL32_61 PIXEL33_80 break; } case 7: case 39: case 135: { PIXEL00_81 PIXEL01_31 PIXEL02_32 PIXEL03_82 PIXEL10_81 PIXEL11_31 PIXEL12_32 PIXEL13_82 PIXEL20_60 PIXEL21_70 PIXEL22_70 PIXEL23_60 PIXEL30_20 PIXEL31_60 PIXEL32_60 PIXEL33_20 break; } case 148: case 149: case 180: { PIXEL00_20 PIXEL01_60 PIXEL02_81 PIXEL03_81 PIXEL10_60 PIXEL11_70 PIXEL12_31 PIXEL13_31 PIXEL20_60 PIXEL21_70 PIXEL22_32 PIXEL23_32 PIXEL30_20 PIXEL31_60 PIXEL32_82 PIXEL33_82 break; } case 224: case 228: case 225: { PIXEL00_20 PIXEL01_60 PIXEL02_60 PIXEL03_20 PIXEL10_60 PIXEL11_70 PIXEL12_70 PIXEL13_60 PIXEL20_82 PIXEL21_32 PIXEL22_31 PIXEL23_81 PIXEL30_82 PIXEL31_32 PIXEL32_31 PIXEL33_81 break; } case 41: case 169: case 45: { PIXEL00_82 PIXEL01_82 PIXEL02_60 PIXEL03_20 PIXEL10_32 PIXEL11_32 PIXEL12_70 PIXEL13_60 PIXEL20_31 PIXEL21_31 PIXEL22_70 PIXEL23_60 PIXEL30_81 PIXEL31_81 PIXEL32_60 PIXEL33_20 break; } case 22: case 54: { PIXEL00_80 PIXEL01_10 if (Diff(w[2], w[6])) { PIXEL02_0 PIXEL03_0 PIXEL13_0 } else { PIXEL02_50 PIXEL03_50 PIXEL13_50 } PIXEL10_61 PIXEL11_30 PIXEL12_0 PIXEL20_60 PIXEL21_70 PIXEL22_30 PIXEL23_10 PIXEL30_20 PIXEL31_60 PIXEL32_61 PIXEL33_80 break; } case 208: case 209: { PIXEL00_20 PIXEL01_60 PIXEL02_61 PIXEL03_80 PIXEL10_60 PIXEL11_70 PIXEL12_30 PIXEL13_10 PIXEL20_61 PIXEL21_30 PIXEL22_0 if (Diff(w[6], w[8])) { PIXEL23_0 PIXEL32_0 PIXEL33_0 } else { PIXEL23_50 PIXEL32_50 PIXEL33_50 } PIXEL30_80 PIXEL31_10 break; } case 104: case 108: { PIXEL00_80 PIXEL01_61 PIXEL02_60 PIXEL03_20 PIXEL10_10 PIXEL11_30 PIXEL12_70 PIXEL13_60 if (Diff(w[8], w[4])) { PIXEL20_0 PIXEL30_0 PIXEL31_0 } else { PIXEL20_50 PIXEL30_50 PIXEL31_50 } PIXEL21_0 PIXEL22_30 PIXEL23_61 PIXEL32_10 PIXEL33_80 break; } case 11: case 139: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL01_0 PIXEL10_0 } else { PIXEL00_50 PIXEL01_50 PIXEL10_50 } PIXEL02_10 PIXEL03_80 PIXEL11_0 PIXEL12_30 PIXEL13_61 PIXEL20_10 PIXEL21_30 PIXEL22_70 PIXEL23_60 PIXEL30_80 PIXEL31_61 PIXEL32_60 PIXEL33_20 break; } case 19: case 51: { if (Diff(w[2], w[6])) { PIXEL00_81 PIXEL01_31 PIXEL02_10 PIXEL03_80 PIXEL12_30 PIXEL13_10 } else { PIXEL00_12 PIXEL01_14 PIXEL02_83 PIXEL03_50 PIXEL12_70 PIXEL13_21 } PIXEL10_81 PIXEL11_31 PIXEL20_60 PIXEL21_70 PIXEL22_30 PIXEL23_10 PIXEL30_20 PIXEL31_60 PIXEL32_61 PIXEL33_80 break; } case 146: case 178: { PIXEL00_80 PIXEL01_10 if (Diff(w[2], w[6])) { PIXEL02_10 PIXEL03_80 PIXEL12_30 PIXEL13_10 PIXEL23_32 PIXEL33_82 } else { PIXEL02_21 PIXEL03_50 PIXEL12_70 PIXEL13_83 PIXEL23_13 PIXEL33_11 } PIXEL10_61 PIXEL11_30 PIXEL20_60 PIXEL21_70 PIXEL22_32 PIXEL30_20 PIXEL31_60 PIXEL32_82 break; } case 84: case 85: { PIXEL00_20 PIXEL01_60 PIXEL02_81 if (Diff(w[6], w[8])) { PIXEL03_81 PIXEL13_31 PIXEL22_30 PIXEL23_10 PIXEL32_10 PIXEL33_80 } else { PIXEL03_12 PIXEL13_14 PIXEL22_70 PIXEL23_83 PIXEL32_21 PIXEL33_50 } PIXEL10_60 PIXEL11_70 PIXEL12_31 PIXEL20_61 PIXEL21_30 PIXEL30_80 PIXEL31_10 break; } case 112: case 113: { PIXEL00_20 PIXEL01_60 PIXEL02_61 PIXEL03_80 PIXEL10_60 PIXEL11_70 PIXEL12_30 PIXEL13_10 PIXEL20_82 PIXEL21_32 if (Diff(w[6], w[8])) { PIXEL22_30 PIXEL23_10 PIXEL30_82 PIXEL31_32 PIXEL32_10 PIXEL33_80 } else { PIXEL22_70 PIXEL23_21 PIXEL30_11 PIXEL31_13 PIXEL32_83 PIXEL33_50 } break; } case 200: case 204: { PIXEL00_80 PIXEL01_61 PIXEL02_60 PIXEL03_20 PIXEL10_10 PIXEL11_30 PIXEL12_70 PIXEL13_60 if (Diff(w[8], w[4])) { PIXEL20_10 PIXEL21_30 PIXEL30_80 PIXEL31_10 PIXEL32_31 PIXEL33_81 } else { PIXEL20_21 PIXEL21_70 PIXEL30_50 PIXEL31_83 PIXEL32_14 PIXEL33_12 } PIXEL22_31 PIXEL23_81 break; } case 73: case 77: { if (Diff(w[8], w[4])) { PIXEL00_82 PIXEL10_32 PIXEL20_10 PIXEL21_30 PIXEL30_80 PIXEL31_10 } else { PIXEL00_11 PIXEL10_13 PIXEL20_83 PIXEL21_70 PIXEL30_50 PIXEL31_21 } PIXEL01_82 PIXEL02_60 PIXEL03_20 PIXEL11_32 PIXEL12_70 PIXEL13_60 PIXEL22_30 PIXEL23_61 PIXEL32_10 PIXEL33_80 break; } case 42: case 170: { if (Diff(w[4], w[2])) { PIXEL00_80 PIXEL01_10 PIXEL10_10 PIXEL11_30 PIXEL20_31 PIXEL30_81 } else { PIXEL00_50 PIXEL01_21 PIXEL10_83 PIXEL11_70 PIXEL20_14 PIXEL30_12 } PIXEL02_10 PIXEL03_80 PIXEL12_30 PIXEL13_61 PIXEL21_31 PIXEL22_70 PIXEL23_60 PIXEL31_81 PIXEL32_60 PIXEL33_20 break; } case 14: case 142: { if (Diff(w[4], w[2])) { PIXEL00_80 PIXEL01_10 PIXEL02_32 PIXEL03_82 PIXEL10_10 PIXEL11_30 } else { PIXEL00_50 PIXEL01_83 PIXEL02_13 PIXEL03_11 PIXEL10_21 PIXEL11_70 } PIXEL12_32 PIXEL13_82 PIXEL20_10 PIXEL21_30 PIXEL22_70 PIXEL23_60 PIXEL30_80 PIXEL31_61 PIXEL32_60 PIXEL33_20 break; } case 67: { PIXEL00_81 PIXEL01_31 PIXEL02_10 PIXEL03_80 PIXEL10_81 PIXEL11_31 PIXEL12_30 PIXEL13_61 PIXEL20_61 PIXEL21_30 PIXEL22_30 PIXEL23_61 PIXEL30_80 PIXEL31_10 PIXEL32_10 PIXEL33_80 break; } case 70: { PIXEL00_80 PIXEL01_10 PIXEL02_32 PIXEL03_82 PIXEL10_61 PIXEL11_30 PIXEL12_32 PIXEL13_82 PIXEL20_61 PIXEL21_30 PIXEL22_30 PIXEL23_61 PIXEL30_80 PIXEL31_10 PIXEL32_10 PIXEL33_80 break; } case 28: { PIXEL00_80 PIXEL01_61 PIXEL02_81 PIXEL03_81 PIXEL10_10 PIXEL11_30 PIXEL12_31 PIXEL13_31 PIXEL20_10 PIXEL21_30 PIXEL22_30 PIXEL23_10 PIXEL30_80 PIXEL31_61 PIXEL32_61 PIXEL33_80 break; } case 152: { PIXEL00_80 PIXEL01_61 PIXEL02_61 PIXEL03_80 PIXEL10_10 PIXEL11_30 PIXEL12_30 PIXEL13_10 PIXEL20_10 PIXEL21_30 PIXEL22_32 PIXEL23_32 PIXEL30_80 PIXEL31_61 PIXEL32_82 PIXEL33_82 break; } case 194: { PIXEL00_80 PIXEL01_10 PIXEL02_10 PIXEL03_80 PIXEL10_61 PIXEL11_30 PIXEL12_30 PIXEL13_61 PIXEL20_61 PIXEL21_30 PIXEL22_31 PIXEL23_81 PIXEL30_80 PIXEL31_10 PIXEL32_31 PIXEL33_81 break; } case 98: { PIXEL00_80 PIXEL01_10 PIXEL02_10 PIXEL03_80 PIXEL10_61 PIXEL11_30 PIXEL12_30 PIXEL13_61 PIXEL20_82 PIXEL21_32 PIXEL22_30 PIXEL23_61 PIXEL30_82 PIXEL31_32 PIXEL32_10 PIXEL33_80 break; } case 56: { PIXEL00_80 PIXEL01_61 PIXEL02_61 PIXEL03_80 PIXEL10_10 PIXEL11_30 PIXEL12_30 PIXEL13_10 PIXEL20_31 PIXEL21_31 PIXEL22_30 PIXEL23_10 PIXEL30_81 PIXEL31_81 PIXEL32_61 PIXEL33_80 break; } case 25: { PIXEL00_82 PIXEL01_82 PIXEL02_61 PIXEL03_80 PIXEL10_32 PIXEL11_32 PIXEL12_30 PIXEL13_10 PIXEL20_10 PIXEL21_30 PIXEL22_30 PIXEL23_10 PIXEL30_80 PIXEL31_61 PIXEL32_61 PIXEL33_80 break; } case 26: case 31: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL01_0 PIXEL10_0 } else { PIXEL00_50 PIXEL01_50 PIXEL10_50 } if (Diff(w[2], w[6])) { PIXEL02_0 PIXEL03_0 PIXEL13_0 } else { PIXEL02_50 PIXEL03_50 PIXEL13_50 } PIXEL11_0 PIXEL12_0 PIXEL20_10 PIXEL21_30 PIXEL22_30 PIXEL23_10 PIXEL30_80 PIXEL31_61 PIXEL32_61 PIXEL33_80 break; } case 82: case 214: { PIXEL00_80 PIXEL01_10 if (Diff(w[2], w[6])) { PIXEL02_0 PIXEL03_0 PIXEL13_0 } else { PIXEL02_50 PIXEL03_50 PIXEL13_50 } PIXEL10_61 PIXEL11_30 PIXEL12_0 PIXEL20_61 PIXEL21_30 PIXEL22_0 if (Diff(w[6], w[8])) { PIXEL23_0 PIXEL32_0 PIXEL33_0 } else { PIXEL23_50 PIXEL32_50 PIXEL33_50 } PIXEL30_80 PIXEL31_10 break; } case 88: case 248: { PIXEL00_80 PIXEL01_61 PIXEL02_61 PIXEL03_80 PIXEL10_10 PIXEL11_30 PIXEL12_30 PIXEL13_10 if (Diff(w[8], w[4])) { PIXEL20_0 PIXEL30_0 PIXEL31_0 } else { PIXEL20_50 PIXEL30_50 PIXEL31_50 } PIXEL21_0 PIXEL22_0 if (Diff(w[6], w[8])) { PIXEL23_0 PIXEL32_0 PIXEL33_0 } else { PIXEL23_50 PIXEL32_50 PIXEL33_50 } break; } case 74: case 107: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL01_0 PIXEL10_0 } else { PIXEL00_50 PIXEL01_50 PIXEL10_50 } PIXEL02_10 PIXEL03_80 PIXEL11_0 PIXEL12_30 PIXEL13_61 if (Diff(w[8], w[4])) { PIXEL20_0 PIXEL30_0 PIXEL31_0 } else { PIXEL20_50 PIXEL30_50 PIXEL31_50 } PIXEL21_0 PIXEL22_30 PIXEL23_61 PIXEL32_10 PIXEL33_80 break; } case 27: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL01_0 PIXEL10_0 } else { PIXEL00_50 PIXEL01_50 PIXEL10_50 } PIXEL02_10 PIXEL03_80 PIXEL11_0 PIXEL12_30 PIXEL13_10 PIXEL20_10 PIXEL21_30 PIXEL22_30 PIXEL23_10 PIXEL30_80 PIXEL31_61 PIXEL32_61 PIXEL33_80 break; } case 86: { PIXEL00_80 PIXEL01_10 if (Diff(w[2], w[6])) { PIXEL02_0 PIXEL03_0 PIXEL13_0 } else { PIXEL02_50 PIXEL03_50 PIXEL13_50 } PIXEL10_61 PIXEL11_30 PIXEL12_0 PIXEL20_61 PIXEL21_30 PIXEL22_30 PIXEL23_10 PIXEL30_80 PIXEL31_10 PIXEL32_10 PIXEL33_80 break; } case 216: { PIXEL00_80 PIXEL01_61 PIXEL02_61 PIXEL03_80 PIXEL10_10 PIXEL11_30 PIXEL12_30 PIXEL13_10 PIXEL20_10 PIXEL21_30 PIXEL22_0 if (Diff(w[6], w[8])) { PIXEL23_0 PIXEL32_0 PIXEL33_0 } else { PIXEL23_50 PIXEL32_50 PIXEL33_50 } PIXEL30_80 PIXEL31_10 break; } case 106: { PIXEL00_80 PIXEL01_10 PIXEL02_10 PIXEL03_80 PIXEL10_10 PIXEL11_30 PIXEL12_30 PIXEL13_61 if (Diff(w[8], w[4])) { PIXEL20_0 PIXEL30_0 PIXEL31_0 } else { PIXEL20_50 PIXEL30_50 PIXEL31_50 } PIXEL21_0 PIXEL22_30 PIXEL23_61 PIXEL32_10 PIXEL33_80 break; } case 30: { PIXEL00_80 PIXEL01_10 if (Diff(w[2], w[6])) { PIXEL02_0 PIXEL03_0 PIXEL13_0 } else { PIXEL02_50 PIXEL03_50 PIXEL13_50 } PIXEL10_10 PIXEL11_30 PIXEL12_0 PIXEL20_10 PIXEL21_30 PIXEL22_30 PIXEL23_10 PIXEL30_80 PIXEL31_61 PIXEL32_61 PIXEL33_80 break; } case 210: { PIXEL00_80 PIXEL01_10 PIXEL02_10 PIXEL03_80 PIXEL10_61 PIXEL11_30 PIXEL12_30 PIXEL13_10 PIXEL20_61 PIXEL21_30 PIXEL22_0 if (Diff(w[6], w[8])) { PIXEL23_0 PIXEL32_0 PIXEL33_0 } else { PIXEL23_50 PIXEL32_50 PIXEL33_50 } PIXEL30_80 PIXEL31_10 break; } case 120: { PIXEL00_80 PIXEL01_61 PIXEL02_61 PIXEL03_80 PIXEL10_10 PIXEL11_30 PIXEL12_30 PIXEL13_10 if (Diff(w[8], w[4])) { PIXEL20_0 PIXEL30_0 PIXEL31_0 } else { PIXEL20_50 PIXEL30_50 PIXEL31_50 } PIXEL21_0 PIXEL22_30 PIXEL23_10 PIXEL32_10 PIXEL33_80 break; } case 75: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL01_0 PIXEL10_0 } else { PIXEL00_50 PIXEL01_50 PIXEL10_50 } PIXEL02_10 PIXEL03_80 PIXEL11_0 PIXEL12_30 PIXEL13_61 PIXEL20_10 PIXEL21_30 PIXEL22_30 PIXEL23_61 PIXEL30_80 PIXEL31_10 PIXEL32_10 PIXEL33_80 break; } case 29: { PIXEL00_82 PIXEL01_82 PIXEL02_81 PIXEL03_81 PIXEL10_32 PIXEL11_32 PIXEL12_31 PIXEL13_31 PIXEL20_10 PIXEL21_30 PIXEL22_30 PIXEL23_10 PIXEL30_80 PIXEL31_61 PIXEL32_61 PIXEL33_80 break; } case 198: { PIXEL00_80 PIXEL01_10 PIXEL02_32 PIXEL03_82 PIXEL10_61 PIXEL11_30 PIXEL12_32 PIXEL13_82 PIXEL20_61 PIXEL21_30 PIXEL22_31 PIXEL23_81 PIXEL30_80 PIXEL31_10 PIXEL32_31 PIXEL33_81 break; } case 184: { PIXEL00_80 PIXEL01_61 PIXEL02_61 PIXEL03_80 PIXEL10_10 PIXEL11_30 PIXEL12_30 PIXEL13_10 PIXEL20_31 PIXEL21_31 PIXEL22_32 PIXEL23_32 PIXEL30_81 PIXEL31_81 PIXEL32_82 PIXEL33_82 break; } case 99: { PIXEL00_81 PIXEL01_31 PIXEL02_10 PIXEL03_80 PIXEL10_81 PIXEL11_31 PIXEL12_30 PIXEL13_61 PIXEL20_82 PIXEL21_32 PIXEL22_30 PIXEL23_61 PIXEL30_82 PIXEL31_32 PIXEL32_10 PIXEL33_80 break; } case 57: { PIXEL00_82 PIXEL01_82 PIXEL02_61 PIXEL03_80 PIXEL10_32 PIXEL11_32 PIXEL12_30 PIXEL13_10 PIXEL20_31 PIXEL21_31 PIXEL22_30 PIXEL23_10 PIXEL30_81 PIXEL31_81 PIXEL32_61 PIXEL33_80 break; } case 71: { PIXEL00_81 PIXEL01_31 PIXEL02_32 PIXEL03_82 PIXEL10_81 PIXEL11_31 PIXEL12_32 PIXEL13_82 PIXEL20_61 PIXEL21_30 PIXEL22_30 PIXEL23_61 PIXEL30_80 PIXEL31_10 PIXEL32_10 PIXEL33_80 break; } case 156: { PIXEL00_80 PIXEL01_61 PIXEL02_81 PIXEL03_81 PIXEL10_10 PIXEL11_30 PIXEL12_31 PIXEL13_31 PIXEL20_10 PIXEL21_30 PIXEL22_32 PIXEL23_32 PIXEL30_80 PIXEL31_61 PIXEL32_82 PIXEL33_82 break; } case 226: { PIXEL00_80 PIXEL01_10 PIXEL02_10 PIXEL03_80 PIXEL10_61 PIXEL11_30 PIXEL12_30 PIXEL13_61 PIXEL20_82 PIXEL21_32 PIXEL22_31 PIXEL23_81 PIXEL30_82 PIXEL31_32 PIXEL32_31 PIXEL33_81 break; } case 60: { PIXEL00_80 PIXEL01_61 PIXEL02_81 PIXEL03_81 PIXEL10_10 PIXEL11_30 PIXEL12_31 PIXEL13_31 PIXEL20_31 PIXEL21_31 PIXEL22_30 PIXEL23_10 PIXEL30_81 PIXEL31_81 PIXEL32_61 PIXEL33_80 break; } case 195: { PIXEL00_81 PIXEL01_31 PIXEL02_10 PIXEL03_80 PIXEL10_81 PIXEL11_31 PIXEL12_30 PIXEL13_61 PIXEL20_61 PIXEL21_30 PIXEL22_31 PIXEL23_81 PIXEL30_80 PIXEL31_10 PIXEL32_31 PIXEL33_81 break; } case 102: { PIXEL00_80 PIXEL01_10 PIXEL02_32 PIXEL03_82 PIXEL10_61 PIXEL11_30 PIXEL12_32 PIXEL13_82 PIXEL20_82 PIXEL21_32 PIXEL22_30 PIXEL23_61 PIXEL30_82 PIXEL31_32 PIXEL32_10 PIXEL33_80 break; } case 153: { PIXEL00_82 PIXEL01_82 PIXEL02_61 PIXEL03_80 PIXEL10_32 PIXEL11_32 PIXEL12_30 PIXEL13_10 PIXEL20_10 PIXEL21_30 PIXEL22_32 PIXEL23_32 PIXEL30_80 PIXEL31_61 PIXEL32_82 PIXEL33_82 break; } case 58: { if (Diff(w[4], w[2])) { PIXEL00_80 PIXEL01_10 PIXEL10_10 PIXEL11_30 } else { PIXEL00_20 PIXEL01_12 PIXEL10_11 PIXEL11_0 } if (Diff(w[2], w[6])) { PIXEL02_10 PIXEL03_80 PIXEL12_30 PIXEL13_10 } else { PIXEL02_11 PIXEL03_20 PIXEL12_0 PIXEL13_12 } PIXEL20_31 PIXEL21_31 PIXEL22_30 PIXEL23_10 PIXEL30_81 PIXEL31_81 PIXEL32_61 PIXEL33_80 break; } case 83: { PIXEL00_81 PIXEL01_31 if (Diff(w[2], w[6])) { PIXEL02_10 PIXEL03_80 PIXEL12_30 PIXEL13_10 } else { PIXEL02_11 PIXEL03_20 PIXEL12_0 PIXEL13_12 } PIXEL10_81 PIXEL11_31 PIXEL20_61 PIXEL21_30 if (Diff(w[6], w[8])) { PIXEL22_30 PIXEL23_10 PIXEL32_10 PIXEL33_80 } else { PIXEL22_0 PIXEL23_11 PIXEL32_12 PIXEL33_20 } PIXEL30_80 PIXEL31_10 break; } case 92: { PIXEL00_80 PIXEL01_61 PIXEL02_81 PIXEL03_81 PIXEL10_10 PIXEL11_30 PIXEL12_31 PIXEL13_31 if (Diff(w[8], w[4])) { PIXEL20_10 PIXEL21_30 PIXEL30_80 PIXEL31_10 } else { PIXEL20_12 PIXEL21_0 PIXEL30_20 PIXEL31_11 } if (Diff(w[6], w[8])) { PIXEL22_30 PIXEL23_10 PIXEL32_10 PIXEL33_80 } else { PIXEL22_0 PIXEL23_11 PIXEL32_12 PIXEL33_20 } break; } case 202: { if (Diff(w[4], w[2])) { PIXEL00_80 PIXEL01_10 PIXEL10_10 PIXEL11_30 } else { PIXEL00_20 PIXEL01_12 PIXEL10_11 PIXEL11_0 } PIXEL02_10 PIXEL03_80 PIXEL12_30 PIXEL13_61 if (Diff(w[8], w[4])) { PIXEL20_10 PIXEL21_30 PIXEL30_80 PIXEL31_10 } else { PIXEL20_12 PIXEL21_0 PIXEL30_20 PIXEL31_11 } PIXEL22_31 PIXEL23_81 PIXEL32_31 PIXEL33_81 break; } case 78: { if (Diff(w[4], w[2])) { PIXEL00_80 PIXEL01_10 PIXEL10_10 PIXEL11_30 } else { PIXEL00_20 PIXEL01_12 PIXEL10_11 PIXEL11_0 } PIXEL02_32 PIXEL03_82 PIXEL12_32 PIXEL13_82 if (Diff(w[8], w[4])) { PIXEL20_10 PIXEL21_30 PIXEL30_80 PIXEL31_10 } else { PIXEL20_12 PIXEL21_0 PIXEL30_20 PIXEL31_11 } PIXEL22_30 PIXEL23_61 PIXEL32_10 PIXEL33_80 break; } case 154: { if (Diff(w[4], w[2])) { PIXEL00_80 PIXEL01_10 PIXEL10_10 PIXEL11_30 } else { PIXEL00_20 PIXEL01_12 PIXEL10_11 PIXEL11_0 } if (Diff(w[2], w[6])) { PIXEL02_10 PIXEL03_80 PIXEL12_30 PIXEL13_10 } else { PIXEL02_11 PIXEL03_20 PIXEL12_0 PIXEL13_12 } PIXEL20_10 PIXEL21_30 PIXEL22_32 PIXEL23_32 PIXEL30_80 PIXEL31_61 PIXEL32_82 PIXEL33_82 break; } case 114: { PIXEL00_80 PIXEL01_10 if (Diff(w[2], w[6])) { PIXEL02_10 PIXEL03_80 PIXEL12_30 PIXEL13_10 } else { PIXEL02_11 PIXEL03_20 PIXEL12_0 PIXEL13_12 } PIXEL10_61 PIXEL11_30 PIXEL20_82 PIXEL21_32 if (Diff(w[6], w[8])) { PIXEL22_30 PIXEL23_10 PIXEL32_10 PIXEL33_80 } else { PIXEL22_0 PIXEL23_11 PIXEL32_12 PIXEL33_20 } PIXEL30_82 PIXEL31_32 break; } case 89: { PIXEL00_82 PIXEL01_82 PIXEL02_61 PIXEL03_80 PIXEL10_32 PIXEL11_32 PIXEL12_30 PIXEL13_10 if (Diff(w[8], w[4])) { PIXEL20_10 PIXEL21_30 PIXEL30_80 PIXEL31_10 } else { PIXEL20_12 PIXEL21_0 PIXEL30_20 PIXEL31_11 } if (Diff(w[6], w[8])) { PIXEL22_30 PIXEL23_10 PIXEL32_10 PIXEL33_80 } else { PIXEL22_0 PIXEL23_11 PIXEL32_12 PIXEL33_20 } break; } case 90: { if (Diff(w[4], w[2])) { PIXEL00_80 PIXEL01_10 PIXEL10_10 PIXEL11_30 } else { PIXEL00_20 PIXEL01_12 PIXEL10_11 PIXEL11_0 } if (Diff(w[2], w[6])) { PIXEL02_10 PIXEL03_80 PIXEL12_30 PIXEL13_10 } else { PIXEL02_11 PIXEL03_20 PIXEL12_0 PIXEL13_12 } if (Diff(w[8], w[4])) { PIXEL20_10 PIXEL21_30 PIXEL30_80 PIXEL31_10 } else { PIXEL20_12 PIXEL21_0 PIXEL30_20 PIXEL31_11 } if (Diff(w[6], w[8])) { PIXEL22_30 PIXEL23_10 PIXEL32_10 PIXEL33_80 } else { PIXEL22_0 PIXEL23_11 PIXEL32_12 PIXEL33_20 } break; } case 55: case 23: { if (Diff(w[2], w[6])) { PIXEL00_81 PIXEL01_31 PIXEL02_0 PIXEL03_0 PIXEL12_0 PIXEL13_0 } else { PIXEL00_12 PIXEL01_14 PIXEL02_83 PIXEL03_50 PIXEL12_70 PIXEL13_21 } PIXEL10_81 PIXEL11_31 PIXEL20_60 PIXEL21_70 PIXEL22_30 PIXEL23_10 PIXEL30_20 PIXEL31_60 PIXEL32_61 PIXEL33_80 break; } case 182: case 150: { PIXEL00_80 PIXEL01_10 if (Diff(w[2], w[6])) { PIXEL02_0 PIXEL03_0 PIXEL12_0 PIXEL13_0 PIXEL23_32 PIXEL33_82 } else { PIXEL02_21 PIXEL03_50 PIXEL12_70 PIXEL13_83 PIXEL23_13 PIXEL33_11 } PIXEL10_61 PIXEL11_30 PIXEL20_60 PIXEL21_70 PIXEL22_32 PIXEL30_20 PIXEL31_60 PIXEL32_82 break; } case 213: case 212: { PIXEL00_20 PIXEL01_60 PIXEL02_81 if (Diff(w[6], w[8])) { PIXEL03_81 PIXEL13_31 PIXEL22_0 PIXEL23_0 PIXEL32_0 PIXEL33_0 } else { PIXEL03_12 PIXEL13_14 PIXEL22_70 PIXEL23_83 PIXEL32_21 PIXEL33_50 } PIXEL10_60 PIXEL11_70 PIXEL12_31 PIXEL20_61 PIXEL21_30 PIXEL30_80 PIXEL31_10 break; } case 241: case 240: { PIXEL00_20 PIXEL01_60 PIXEL02_61 PIXEL03_80 PIXEL10_60 PIXEL11_70 PIXEL12_30 PIXEL13_10 PIXEL20_82 PIXEL21_32 if (Diff(w[6], w[8])) { PIXEL22_0 PIXEL23_0 PIXEL30_82 PIXEL31_32 PIXEL32_0 PIXEL33_0 } else { PIXEL22_70 PIXEL23_21 PIXEL30_11 PIXEL31_13 PIXEL32_83 PIXEL33_50 } break; } case 236: case 232: { PIXEL00_80 PIXEL01_61 PIXEL02_60 PIXEL03_20 PIXEL10_10 PIXEL11_30 PIXEL12_70 PIXEL13_60 if (Diff(w[8], w[4])) { PIXEL20_0 PIXEL21_0 PIXEL30_0 PIXEL31_0 PIXEL32_31 PIXEL33_81 } else { PIXEL20_21 PIXEL21_70 PIXEL30_50 PIXEL31_83 PIXEL32_14 PIXEL33_12 } PIXEL22_31 PIXEL23_81 break; } case 109: case 105: { if (Diff(w[8], w[4])) { PIXEL00_82 PIXEL10_32 PIXEL20_0 PIXEL21_0 PIXEL30_0 PIXEL31_0 } else { PIXEL00_11 PIXEL10_13 PIXEL20_83 PIXEL21_70 PIXEL30_50 PIXEL31_21 } PIXEL01_82 PIXEL02_60 PIXEL03_20 PIXEL11_32 PIXEL12_70 PIXEL13_60 PIXEL22_30 PIXEL23_61 PIXEL32_10 PIXEL33_80 break; } case 171: case 43: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL01_0 PIXEL10_0 PIXEL11_0 PIXEL20_31 PIXEL30_81 } else { PIXEL00_50 PIXEL01_21 PIXEL10_83 PIXEL11_70 PIXEL20_14 PIXEL30_12 } PIXEL02_10 PIXEL03_80 PIXEL12_30 PIXEL13_61 PIXEL21_31 PIXEL22_70 PIXEL23_60 PIXEL31_81 PIXEL32_60 PIXEL33_20 break; } case 143: case 15: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL01_0 PIXEL02_32 PIXEL03_82 PIXEL10_0 PIXEL11_0 } else { PIXEL00_50 PIXEL01_83 PIXEL02_13 PIXEL03_11 PIXEL10_21 PIXEL11_70 } PIXEL12_32 PIXEL13_82 PIXEL20_10 PIXEL21_30 PIXEL22_70 PIXEL23_60 PIXEL30_80 PIXEL31_61 PIXEL32_60 PIXEL33_20 break; } case 124: { PIXEL00_80 PIXEL01_61 PIXEL02_81 PIXEL03_81 PIXEL10_10 PIXEL11_30 PIXEL12_31 PIXEL13_31 if (Diff(w[8], w[4])) { PIXEL20_0 PIXEL30_0 PIXEL31_0 } else { PIXEL20_50 PIXEL30_50 PIXEL31_50 } PIXEL21_0 PIXEL22_30 PIXEL23_10 PIXEL32_10 PIXEL33_80 break; } case 203: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL01_0 PIXEL10_0 } else { PIXEL00_50 PIXEL01_50 PIXEL10_50 } PIXEL02_10 PIXEL03_80 PIXEL11_0 PIXEL12_30 PIXEL13_61 PIXEL20_10 PIXEL21_30 PIXEL22_31 PIXEL23_81 PIXEL30_80 PIXEL31_10 PIXEL32_31 PIXEL33_81 break; } case 62: { PIXEL00_80 PIXEL01_10 if (Diff(w[2], w[6])) { PIXEL02_0 PIXEL03_0 PIXEL13_0 } else { PIXEL02_50 PIXEL03_50 PIXEL13_50 } PIXEL10_10 PIXEL11_30 PIXEL12_0 PIXEL20_31 PIXEL21_31 PIXEL22_30 PIXEL23_10 PIXEL30_81 PIXEL31_81 PIXEL32_61 PIXEL33_80 break; } case 211: { PIXEL00_81 PIXEL01_31 PIXEL02_10 PIXEL03_80 PIXEL10_81 PIXEL11_31 PIXEL12_30 PIXEL13_10 PIXEL20_61 PIXEL21_30 PIXEL22_0 if (Diff(w[6], w[8])) { PIXEL23_0 PIXEL32_0 PIXEL33_0 } else { PIXEL23_50 PIXEL32_50 PIXEL33_50 } PIXEL30_80 PIXEL31_10 break; } case 118: { PIXEL00_80 PIXEL01_10 if (Diff(w[2], w[6])) { PIXEL02_0 PIXEL03_0 PIXEL13_0 } else { PIXEL02_50 PIXEL03_50 PIXEL13_50 } PIXEL10_61 PIXEL11_30 PIXEL12_0 PIXEL20_82 PIXEL21_32 PIXEL22_30 PIXEL23_10 PIXEL30_82 PIXEL31_32 PIXEL32_10 PIXEL33_80 break; } case 217: { PIXEL00_82 PIXEL01_82 PIXEL02_61 PIXEL03_80 PIXEL10_32 PIXEL11_32 PIXEL12_30 PIXEL13_10 PIXEL20_10 PIXEL21_30 PIXEL22_0 if (Diff(w[6], w[8])) { PIXEL23_0 PIXEL32_0 PIXEL33_0 } else { PIXEL23_50 PIXEL32_50 PIXEL33_50 } PIXEL30_80 PIXEL31_10 break; } case 110: { PIXEL00_80 PIXEL01_10 PIXEL02_32 PIXEL03_82 PIXEL10_10 PIXEL11_30 PIXEL12_32 PIXEL13_82 if (Diff(w[8], w[4])) { PIXEL20_0 PIXEL30_0 PIXEL31_0 } else { PIXEL20_50 PIXEL30_50 PIXEL31_50 } PIXEL21_0 PIXEL22_30 PIXEL23_61 PIXEL32_10 PIXEL33_80 break; } case 155: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL01_0 PIXEL10_0 } else { PIXEL00_50 PIXEL01_50 PIXEL10_50 } PIXEL02_10 PIXEL03_80 PIXEL11_0 PIXEL12_30 PIXEL13_10 PIXEL20_10 PIXEL21_30 PIXEL22_32 PIXEL23_32 PIXEL30_80 PIXEL31_61 PIXEL32_82 PIXEL33_82 break; } case 188: { PIXEL00_80 PIXEL01_61 PIXEL02_81 PIXEL03_81 PIXEL10_10 PIXEL11_30 PIXEL12_31 PIXEL13_31 PIXEL20_31 PIXEL21_31 PIXEL22_32 PIXEL23_32 PIXEL30_81 PIXEL31_81 PIXEL32_82 PIXEL33_82 break; } case 185: { PIXEL00_82 PIXEL01_82 PIXEL02_61 PIXEL03_80 PIXEL10_32 PIXEL11_32 PIXEL12_30 PIXEL13_10 PIXEL20_31 PIXEL21_31 PIXEL22_32 PIXEL23_32 PIXEL30_81 PIXEL31_81 PIXEL32_82 PIXEL33_82 break; } case 61: { PIXEL00_82 PIXEL01_82 PIXEL02_81 PIXEL03_81 PIXEL10_32 PIXEL11_32 PIXEL12_31 PIXEL13_31 PIXEL20_31 PIXEL21_31 PIXEL22_30 PIXEL23_10 PIXEL30_81 PIXEL31_81 PIXEL32_61 PIXEL33_80 break; } case 157: { PIXEL00_82 PIXEL01_82 PIXEL02_81 PIXEL03_81 PIXEL10_32 PIXEL11_32 PIXEL12_31 PIXEL13_31 PIXEL20_10 PIXEL21_30 PIXEL22_32 PIXEL23_32 PIXEL30_80 PIXEL31_61 PIXEL32_82 PIXEL33_82 break; } case 103: { PIXEL00_81 PIXEL01_31 PIXEL02_32 PIXEL03_82 PIXEL10_81 PIXEL11_31 PIXEL12_32 PIXEL13_82 PIXEL20_82 PIXEL21_32 PIXEL22_30 PIXEL23_61 PIXEL30_82 PIXEL31_32 PIXEL32_10 PIXEL33_80 break; } case 227: { PIXEL00_81 PIXEL01_31 PIXEL02_10 PIXEL03_80 PIXEL10_81 PIXEL11_31 PIXEL12_30 PIXEL13_61 PIXEL20_82 PIXEL21_32 PIXEL22_31 PIXEL23_81 PIXEL30_82 PIXEL31_32 PIXEL32_31 PIXEL33_81 break; } case 230: { PIXEL00_80 PIXEL01_10 PIXEL02_32 PIXEL03_82 PIXEL10_61 PIXEL11_30 PIXEL12_32 PIXEL13_82 PIXEL20_82 PIXEL21_32 PIXEL22_31 PIXEL23_81 PIXEL30_82 PIXEL31_32 PIXEL32_31 PIXEL33_81 break; } case 199: { PIXEL00_81 PIXEL01_31 PIXEL02_32 PIXEL03_82 PIXEL10_81 PIXEL11_31 PIXEL12_32 PIXEL13_82 PIXEL20_61 PIXEL21_30 PIXEL22_31 PIXEL23_81 PIXEL30_80 PIXEL31_10 PIXEL32_31 PIXEL33_81 break; } case 220: { PIXEL00_80 PIXEL01_61 PIXEL02_81 PIXEL03_81 PIXEL10_10 PIXEL11_30 PIXEL12_31 PIXEL13_31 if (Diff(w[8], w[4])) { PIXEL20_10 PIXEL21_30 PIXEL30_80 PIXEL31_10 } else { PIXEL20_12 PIXEL21_0 PIXEL30_20 PIXEL31_11 } PIXEL22_0 if (Diff(w[6], w[8])) { PIXEL23_0 PIXEL32_0 PIXEL33_0 } else { PIXEL23_50 PIXEL32_50 PIXEL33_50 } break; } case 158: { if (Diff(w[4], w[2])) { PIXEL00_80 PIXEL01_10 PIXEL10_10 PIXEL11_30 } else { PIXEL00_20 PIXEL01_12 PIXEL10_11 PIXEL11_0 } if (Diff(w[2], w[6])) { PIXEL02_0 PIXEL03_0 PIXEL13_0 } else { PIXEL02_50 PIXEL03_50 PIXEL13_50 } PIXEL12_0 PIXEL20_10 PIXEL21_30 PIXEL22_32 PIXEL23_32 PIXEL30_80 PIXEL31_61 PIXEL32_82 PIXEL33_82 break; } case 234: { if (Diff(w[4], w[2])) { PIXEL00_80 PIXEL01_10 PIXEL10_10 PIXEL11_30 } else { PIXEL00_20 PIXEL01_12 PIXEL10_11 PIXEL11_0 } PIXEL02_10 PIXEL03_80 PIXEL12_30 PIXEL13_61 if (Diff(w[8], w[4])) { PIXEL20_0 PIXEL30_0 PIXEL31_0 } else { PIXEL20_50 PIXEL30_50 PIXEL31_50 } PIXEL21_0 PIXEL22_31 PIXEL23_81 PIXEL32_31 PIXEL33_81 break; } case 242: { PIXEL00_80 PIXEL01_10 if (Diff(w[2], w[6])) { PIXEL02_10 PIXEL03_80 PIXEL12_30 PIXEL13_10 } else { PIXEL02_11 PIXEL03_20 PIXEL12_0 PIXEL13_12 } PIXEL10_61 PIXEL11_30 PIXEL20_82 PIXEL21_32 PIXEL22_0 if (Diff(w[6], w[8])) { PIXEL23_0 PIXEL32_0 PIXEL33_0 } else { PIXEL23_50 PIXEL32_50 PIXEL33_50 } PIXEL30_82 PIXEL31_32 break; } case 59: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL01_0 PIXEL10_0 } else { PIXEL00_50 PIXEL01_50 PIXEL10_50 } if (Diff(w[2], w[6])) { PIXEL02_10 PIXEL03_80 PIXEL12_30 PIXEL13_10 } else { PIXEL02_11 PIXEL03_20 PIXEL12_0 PIXEL13_12 } PIXEL11_0 PIXEL20_31 PIXEL21_31 PIXEL22_30 PIXEL23_10 PIXEL30_81 PIXEL31_81 PIXEL32_61 PIXEL33_80 break; } case 121: { PIXEL00_82 PIXEL01_82 PIXEL02_61 PIXEL03_80 PIXEL10_32 PIXEL11_32 PIXEL12_30 PIXEL13_10 if (Diff(w[8], w[4])) { PIXEL20_0 PIXEL30_0 PIXEL31_0 } else { PIXEL20_50 PIXEL30_50 PIXEL31_50 } PIXEL21_0 if (Diff(w[6], w[8])) { PIXEL22_30 PIXEL23_10 PIXEL32_10 PIXEL33_80 } else { PIXEL22_0 PIXEL23_11 PIXEL32_12 PIXEL33_20 } break; } case 87: { PIXEL00_81 PIXEL01_31 if (Diff(w[2], w[6])) { PIXEL02_0 PIXEL03_0 PIXEL13_0 } else { PIXEL02_50 PIXEL03_50 PIXEL13_50 } PIXEL10_81 PIXEL11_31 PIXEL12_0 PIXEL20_61 PIXEL21_30 if (Diff(w[6], w[8])) { PIXEL22_30 PIXEL23_10 PIXEL32_10 PIXEL33_80 } else { PIXEL22_0 PIXEL23_11 PIXEL32_12 PIXEL33_20 } PIXEL30_80 PIXEL31_10 break; } case 79: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL01_0 PIXEL10_0 } else { PIXEL00_50 PIXEL01_50 PIXEL10_50 } PIXEL02_32 PIXEL03_82 PIXEL11_0 PIXEL12_32 PIXEL13_82 if (Diff(w[8], w[4])) { PIXEL20_10 PIXEL21_30 PIXEL30_80 PIXEL31_10 } else { PIXEL20_12 PIXEL21_0 PIXEL30_20 PIXEL31_11 } PIXEL22_30 PIXEL23_61 PIXEL32_10 PIXEL33_80 break; } case 122: { if (Diff(w[4], w[2])) { PIXEL00_80 PIXEL01_10 PIXEL10_10 PIXEL11_30 } else { PIXEL00_20 PIXEL01_12 PIXEL10_11 PIXEL11_0 } if (Diff(w[2], w[6])) { PIXEL02_10 PIXEL03_80 PIXEL12_30 PIXEL13_10 } else { PIXEL02_11 PIXEL03_20 PIXEL12_0 PIXEL13_12 } if (Diff(w[8], w[4])) { PIXEL20_0 PIXEL30_0 PIXEL31_0 } else { PIXEL20_50 PIXEL30_50 PIXEL31_50 } PIXEL21_0 if (Diff(w[6], w[8])) { PIXEL22_30 PIXEL23_10 PIXEL32_10 PIXEL33_80 } else { PIXEL22_0 PIXEL23_11 PIXEL32_12 PIXEL33_20 } break; } case 94: { if (Diff(w[4], w[2])) { PIXEL00_80 PIXEL01_10 PIXEL10_10 PIXEL11_30 } else { PIXEL00_20 PIXEL01_12 PIXEL10_11 PIXEL11_0 } if (Diff(w[2], w[6])) { PIXEL02_0 PIXEL03_0 PIXEL13_0 } else { PIXEL02_50 PIXEL03_50 PIXEL13_50 } PIXEL12_0 if (Diff(w[8], w[4])) { PIXEL20_10 PIXEL21_30 PIXEL30_80 PIXEL31_10 } else { PIXEL20_12 PIXEL21_0 PIXEL30_20 PIXEL31_11 } if (Diff(w[6], w[8])) { PIXEL22_30 PIXEL23_10 PIXEL32_10 PIXEL33_80 } else { PIXEL22_0 PIXEL23_11 PIXEL32_12 PIXEL33_20 } break; } case 218: { if (Diff(w[4], w[2])) { PIXEL00_80 PIXEL01_10 PIXEL10_10 PIXEL11_30 } else { PIXEL00_20 PIXEL01_12 PIXEL10_11 PIXEL11_0 } if (Diff(w[2], w[6])) { PIXEL02_10 PIXEL03_80 PIXEL12_30 PIXEL13_10 } else { PIXEL02_11 PIXEL03_20 PIXEL12_0 PIXEL13_12 } if (Diff(w[8], w[4])) { PIXEL20_10 PIXEL21_30 PIXEL30_80 PIXEL31_10 } else { PIXEL20_12 PIXEL21_0 PIXEL30_20 PIXEL31_11 } PIXEL22_0 if (Diff(w[6], w[8])) { PIXEL23_0 PIXEL32_0 PIXEL33_0 } else { PIXEL23_50 PIXEL32_50 PIXEL33_50 } break; } case 91: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL01_0 PIXEL10_0 } else { PIXEL00_50 PIXEL01_50 PIXEL10_50 } if (Diff(w[2], w[6])) { PIXEL02_10 PIXEL03_80 PIXEL12_30 PIXEL13_10 } else { PIXEL02_11 PIXEL03_20 PIXEL12_0 PIXEL13_12 } PIXEL11_0 if (Diff(w[8], w[4])) { PIXEL20_10 PIXEL21_30 PIXEL30_80 PIXEL31_10 } else { PIXEL20_12 PIXEL21_0 PIXEL30_20 PIXEL31_11 } if (Diff(w[6], w[8])) { PIXEL22_30 PIXEL23_10 PIXEL32_10 PIXEL33_80 } else { PIXEL22_0 PIXEL23_11 PIXEL32_12 PIXEL33_20 } break; } case 229: { PIXEL00_20 PIXEL01_60 PIXEL02_60 PIXEL03_20 PIXEL10_60 PIXEL11_70 PIXEL12_70 PIXEL13_60 PIXEL20_82 PIXEL21_32 PIXEL22_31 PIXEL23_81 PIXEL30_82 PIXEL31_32 PIXEL32_31 PIXEL33_81 break; } case 167: { PIXEL00_81 PIXEL01_31 PIXEL02_32 PIXEL03_82 PIXEL10_81 PIXEL11_31 PIXEL12_32 PIXEL13_82 PIXEL20_60 PIXEL21_70 PIXEL22_70 PIXEL23_60 PIXEL30_20 PIXEL31_60 PIXEL32_60 PIXEL33_20 break; } case 173: { PIXEL00_82 PIXEL01_82 PIXEL02_60 PIXEL03_20 PIXEL10_32 PIXEL11_32 PIXEL12_70 PIXEL13_60 PIXEL20_31 PIXEL21_31 PIXEL22_70 PIXEL23_60 PIXEL30_81 PIXEL31_81 PIXEL32_60 PIXEL33_20 break; } case 181: { PIXEL00_20 PIXEL01_60 PIXEL02_81 PIXEL03_81 PIXEL10_60 PIXEL11_70 PIXEL12_31 PIXEL13_31 PIXEL20_60 PIXEL21_70 PIXEL22_32 PIXEL23_32 PIXEL30_20 PIXEL31_60 PIXEL32_82 PIXEL33_82 break; } case 186: { if (Diff(w[4], w[2])) { PIXEL00_80 PIXEL01_10 PIXEL10_10 PIXEL11_30 } else { PIXEL00_20 PIXEL01_12 PIXEL10_11 PIXEL11_0 } if (Diff(w[2], w[6])) { PIXEL02_10 PIXEL03_80 PIXEL12_30 PIXEL13_10 } else { PIXEL02_11 PIXEL03_20 PIXEL12_0 PIXEL13_12 } PIXEL20_31 PIXEL21_31 PIXEL22_32 PIXEL23_32 PIXEL30_81 PIXEL31_81 PIXEL32_82 PIXEL33_82 break; } case 115: { PIXEL00_81 PIXEL01_31 if (Diff(w[2], w[6])) { PIXEL02_10 PIXEL03_80 PIXEL12_30 PIXEL13_10 } else { PIXEL02_11 PIXEL03_20 PIXEL12_0 PIXEL13_12 } PIXEL10_81 PIXEL11_31 PIXEL20_82 PIXEL21_32 if (Diff(w[6], w[8])) { PIXEL22_30 PIXEL23_10 PIXEL32_10 PIXEL33_80 } else { PIXEL22_0 PIXEL23_11 PIXEL32_12 PIXEL33_20 } PIXEL30_82 PIXEL31_32 break; } case 93: { PIXEL00_82 PIXEL01_82 PIXEL02_81 PIXEL03_81 PIXEL10_32 PIXEL11_32 PIXEL12_31 PIXEL13_31 if (Diff(w[8], w[4])) { PIXEL20_10 PIXEL21_30 PIXEL30_80 PIXEL31_10 } else { PIXEL20_12 PIXEL21_0 PIXEL30_20 PIXEL31_11 } if (Diff(w[6], w[8])) { PIXEL22_30 PIXEL23_10 PIXEL32_10 PIXEL33_80 } else { PIXEL22_0 PIXEL23_11 PIXEL32_12 PIXEL33_20 } break; } case 206: { if (Diff(w[4], w[2])) { PIXEL00_80 PIXEL01_10 PIXEL10_10 PIXEL11_30 } else { PIXEL00_20 PIXEL01_12 PIXEL10_11 PIXEL11_0 } PIXEL02_32 PIXEL03_82 PIXEL12_32 PIXEL13_82 if (Diff(w[8], w[4])) { PIXEL20_10 PIXEL21_30 PIXEL30_80 PIXEL31_10 } else { PIXEL20_12 PIXEL21_0 PIXEL30_20 PIXEL31_11 } PIXEL22_31 PIXEL23_81 PIXEL32_31 PIXEL33_81 break; } case 205: case 201: { PIXEL00_82 PIXEL01_82 PIXEL02_60 PIXEL03_20 PIXEL10_32 PIXEL11_32 PIXEL12_70 PIXEL13_60 if (Diff(w[8], w[4])) { PIXEL20_10 PIXEL21_30 PIXEL30_80 PIXEL31_10 } else { PIXEL20_12 PIXEL21_0 PIXEL30_20 PIXEL31_11 } PIXEL22_31 PIXEL23_81 PIXEL32_31 PIXEL33_81 break; } case 174: case 46: { if (Diff(w[4], w[2])) { PIXEL00_80 PIXEL01_10 PIXEL10_10 PIXEL11_30 } else { PIXEL00_20 PIXEL01_12 PIXEL10_11 PIXEL11_0 } PIXEL02_32 PIXEL03_82 PIXEL12_32 PIXEL13_82 PIXEL20_31 PIXEL21_31 PIXEL22_70 PIXEL23_60 PIXEL30_81 PIXEL31_81 PIXEL32_60 PIXEL33_20 break; } case 179: case 147: { PIXEL00_81 PIXEL01_31 if (Diff(w[2], w[6])) { PIXEL02_10 PIXEL03_80 PIXEL12_30 PIXEL13_10 } else { PIXEL02_11 PIXEL03_20 PIXEL12_0 PIXEL13_12 } PIXEL10_81 PIXEL11_31 PIXEL20_60 PIXEL21_70 PIXEL22_32 PIXEL23_32 PIXEL30_20 PIXEL31_60 PIXEL32_82 PIXEL33_82 break; } case 117: case 116: { PIXEL00_20 PIXEL01_60 PIXEL02_81 PIXEL03_81 PIXEL10_60 PIXEL11_70 PIXEL12_31 PIXEL13_31 PIXEL20_82 PIXEL21_32 if (Diff(w[6], w[8])) { PIXEL22_30 PIXEL23_10 PIXEL32_10 PIXEL33_80 } else { PIXEL22_0 PIXEL23_11 PIXEL32_12 PIXEL33_20 } PIXEL30_82 PIXEL31_32 break; } case 189: { PIXEL00_82 PIXEL01_82 PIXEL02_81 PIXEL03_81 PIXEL10_32 PIXEL11_32 PIXEL12_31 PIXEL13_31 PIXEL20_31 PIXEL21_31 PIXEL22_32 PIXEL23_32 PIXEL30_81 PIXEL31_81 PIXEL32_82 PIXEL33_82 break; } case 231: { PIXEL00_81 PIXEL01_31 PIXEL02_32 PIXEL03_82 PIXEL10_81 PIXEL11_31 PIXEL12_32 PIXEL13_82 PIXEL20_82 PIXEL21_32 PIXEL22_31 PIXEL23_81 PIXEL30_82 PIXEL31_32 PIXEL32_31 PIXEL33_81 break; } case 126: { PIXEL00_80 PIXEL01_10 if (Diff(w[2], w[6])) { PIXEL02_0 PIXEL03_0 PIXEL13_0 } else { PIXEL02_50 PIXEL03_50 PIXEL13_50 } PIXEL10_10 PIXEL11_30 PIXEL12_0 if (Diff(w[8], w[4])) { PIXEL20_0 PIXEL30_0 PIXEL31_0 } else { PIXEL20_50 PIXEL30_50 PIXEL31_50 } PIXEL21_0 PIXEL22_30 PIXEL23_10 PIXEL32_10 PIXEL33_80 break; } case 219: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL01_0 PIXEL10_0 } else { PIXEL00_50 PIXEL01_50 PIXEL10_50 } PIXEL02_10 PIXEL03_80 PIXEL11_0 PIXEL12_30 PIXEL13_10 PIXEL20_10 PIXEL21_30 PIXEL22_0 if (Diff(w[6], w[8])) { PIXEL23_0 PIXEL32_0 PIXEL33_0 } else { PIXEL23_50 PIXEL32_50 PIXEL33_50 } PIXEL30_80 PIXEL31_10 break; } case 125: { if (Diff(w[8], w[4])) { PIXEL00_82 PIXEL10_32 PIXEL20_0 PIXEL21_0 PIXEL30_0 PIXEL31_0 } else { PIXEL00_11 PIXEL10_13 PIXEL20_83 PIXEL21_70 PIXEL30_50 PIXEL31_21 } PIXEL01_82 PIXEL02_81 PIXEL03_81 PIXEL11_32 PIXEL12_31 PIXEL13_31 PIXEL22_30 PIXEL23_10 PIXEL32_10 PIXEL33_80 break; } case 221: { PIXEL00_82 PIXEL01_82 PIXEL02_81 if (Diff(w[6], w[8])) { PIXEL03_81 PIXEL13_31 PIXEL22_0 PIXEL23_0 PIXEL32_0 PIXEL33_0 } else { PIXEL03_12 PIXEL13_14 PIXEL22_70 PIXEL23_83 PIXEL32_21 PIXEL33_50 } PIXEL10_32 PIXEL11_32 PIXEL12_31 PIXEL20_10 PIXEL21_30 PIXEL30_80 PIXEL31_10 break; } case 207: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL01_0 PIXEL02_32 PIXEL03_82 PIXEL10_0 PIXEL11_0 } else { PIXEL00_50 PIXEL01_83 PIXEL02_13 PIXEL03_11 PIXEL10_21 PIXEL11_70 } PIXEL12_32 PIXEL13_82 PIXEL20_10 PIXEL21_30 PIXEL22_31 PIXEL23_81 PIXEL30_80 PIXEL31_10 PIXEL32_31 PIXEL33_81 break; } case 238: { PIXEL00_80 PIXEL01_10 PIXEL02_32 PIXEL03_82 PIXEL10_10 PIXEL11_30 PIXEL12_32 PIXEL13_82 if (Diff(w[8], w[4])) { PIXEL20_0 PIXEL21_0 PIXEL30_0 PIXEL31_0 PIXEL32_31 PIXEL33_81 } else { PIXEL20_21 PIXEL21_70 PIXEL30_50 PIXEL31_83 PIXEL32_14 PIXEL33_12 } PIXEL22_31 PIXEL23_81 break; } case 190: { PIXEL00_80 PIXEL01_10 if (Diff(w[2], w[6])) { PIXEL02_0 PIXEL03_0 PIXEL12_0 PIXEL13_0 PIXEL23_32 PIXEL33_82 } else { PIXEL02_21 PIXEL03_50 PIXEL12_70 PIXEL13_83 PIXEL23_13 PIXEL33_11 } PIXEL10_10 PIXEL11_30 PIXEL20_31 PIXEL21_31 PIXEL22_32 PIXEL30_81 PIXEL31_81 PIXEL32_82 break; } case 187: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL01_0 PIXEL10_0 PIXEL11_0 PIXEL20_31 PIXEL30_81 } else { PIXEL00_50 PIXEL01_21 PIXEL10_83 PIXEL11_70 PIXEL20_14 PIXEL30_12 } PIXEL02_10 PIXEL03_80 PIXEL12_30 PIXEL13_10 PIXEL21_31 PIXEL22_32 PIXEL23_32 PIXEL31_81 PIXEL32_82 PIXEL33_82 break; } case 243: { PIXEL00_81 PIXEL01_31 PIXEL02_10 PIXEL03_80 PIXEL10_81 PIXEL11_31 PIXEL12_30 PIXEL13_10 PIXEL20_82 PIXEL21_32 if (Diff(w[6], w[8])) { PIXEL22_0 PIXEL23_0 PIXEL30_82 PIXEL31_32 PIXEL32_0 PIXEL33_0 } else { PIXEL22_70 PIXEL23_21 PIXEL30_11 PIXEL31_13 PIXEL32_83 PIXEL33_50 } break; } case 119: { if (Diff(w[2], w[6])) { PIXEL00_81 PIXEL01_31 PIXEL02_0 PIXEL03_0 PIXEL12_0 PIXEL13_0 } else { PIXEL00_12 PIXEL01_14 PIXEL02_83 PIXEL03_50 PIXEL12_70 PIXEL13_21 } PIXEL10_81 PIXEL11_31 PIXEL20_82 PIXEL21_32 PIXEL22_30 PIXEL23_10 PIXEL30_82 PIXEL31_32 PIXEL32_10 PIXEL33_80 break; } case 237: case 233: { PIXEL00_82 PIXEL01_82 PIXEL02_60 PIXEL03_20 PIXEL10_32 PIXEL11_32 PIXEL12_70 PIXEL13_60 PIXEL20_0 PIXEL21_0 PIXEL22_31 PIXEL23_81 if (Diff(w[8], w[4])) { PIXEL30_0 } else { PIXEL30_20 } PIXEL31_0 PIXEL32_31 PIXEL33_81 break; } case 175: case 47: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_0 PIXEL02_32 PIXEL03_82 PIXEL10_0 PIXEL11_0 PIXEL12_32 PIXEL13_82 PIXEL20_31 PIXEL21_31 PIXEL22_70 PIXEL23_60 PIXEL30_81 PIXEL31_81 PIXEL32_60 PIXEL33_20 break; } case 183: case 151: { PIXEL00_81 PIXEL01_31 PIXEL02_0 if (Diff(w[2], w[6])) { PIXEL03_0 } else { PIXEL03_20 } PIXEL10_81 PIXEL11_31 PIXEL12_0 PIXEL13_0 PIXEL20_60 PIXEL21_70 PIXEL22_32 PIXEL23_32 PIXEL30_20 PIXEL31_60 PIXEL32_82 PIXEL33_82 break; } case 245: case 244: { PIXEL00_20 PIXEL01_60 PIXEL02_81 PIXEL03_81 PIXEL10_60 PIXEL11_70 PIXEL12_31 PIXEL13_31 PIXEL20_82 PIXEL21_32 PIXEL22_0 PIXEL23_0 PIXEL30_82 PIXEL31_32 PIXEL32_0 if (Diff(w[6], w[8])) { PIXEL33_0 } else { PIXEL33_20 } break; } case 250: { PIXEL00_80 PIXEL01_10 PIXEL02_10 PIXEL03_80 PIXEL10_10 PIXEL11_30 PIXEL12_30 PIXEL13_10 if (Diff(w[8], w[4])) { PIXEL20_0 PIXEL30_0 PIXEL31_0 } else { PIXEL20_50 PIXEL30_50 PIXEL31_50 } PIXEL21_0 PIXEL22_0 if (Diff(w[6], w[8])) { PIXEL23_0 PIXEL32_0 PIXEL33_0 } else { PIXEL23_50 PIXEL32_50 PIXEL33_50 } break; } case 123: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL01_0 PIXEL10_0 } else { PIXEL00_50 PIXEL01_50 PIXEL10_50 } PIXEL02_10 PIXEL03_80 PIXEL11_0 PIXEL12_30 PIXEL13_10 if (Diff(w[8], w[4])) { PIXEL20_0 PIXEL30_0 PIXEL31_0 } else { PIXEL20_50 PIXEL30_50 PIXEL31_50 } PIXEL21_0 PIXEL22_30 PIXEL23_10 PIXEL32_10 PIXEL33_80 break; } case 95: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL01_0 PIXEL10_0 } else { PIXEL00_50 PIXEL01_50 PIXEL10_50 } if (Diff(w[2], w[6])) { PIXEL02_0 PIXEL03_0 PIXEL13_0 } else { PIXEL02_50 PIXEL03_50 PIXEL13_50 } PIXEL11_0 PIXEL12_0 PIXEL20_10 PIXEL21_30 PIXEL22_30 PIXEL23_10 PIXEL30_80 PIXEL31_10 PIXEL32_10 PIXEL33_80 break; } case 222: { PIXEL00_80 PIXEL01_10 if (Diff(w[2], w[6])) { PIXEL02_0 PIXEL03_0 PIXEL13_0 } else { PIXEL02_50 PIXEL03_50 PIXEL13_50 } PIXEL10_10 PIXEL11_30 PIXEL12_0 PIXEL20_10 PIXEL21_30 PIXEL22_0 if (Diff(w[6], w[8])) { PIXEL23_0 PIXEL32_0 PIXEL33_0 } else { PIXEL23_50 PIXEL32_50 PIXEL33_50 } PIXEL30_80 PIXEL31_10 break; } case 252: { PIXEL00_80 PIXEL01_61 PIXEL02_81 PIXEL03_81 PIXEL10_10 PIXEL11_30 PIXEL12_31 PIXEL13_31 if (Diff(w[8], w[4])) { PIXEL20_0 PIXEL30_0 PIXEL31_0 } else { PIXEL20_50 PIXEL30_50 PIXEL31_50 } PIXEL21_0 PIXEL22_0 PIXEL23_0 PIXEL32_0 if (Diff(w[6], w[8])) { PIXEL33_0 } else { PIXEL33_20 } break; } case 249: { PIXEL00_82 PIXEL01_82 PIXEL02_61 PIXEL03_80 PIXEL10_32 PIXEL11_32 PIXEL12_30 PIXEL13_10 PIXEL20_0 PIXEL21_0 PIXEL22_0 if (Diff(w[6], w[8])) { PIXEL23_0 PIXEL32_0 PIXEL33_0 } else { PIXEL23_50 PIXEL32_50 PIXEL33_50 } if (Diff(w[8], w[4])) { PIXEL30_0 } else { PIXEL30_20 } PIXEL31_0 break; } case 235: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL01_0 PIXEL10_0 } else { PIXEL00_50 PIXEL01_50 PIXEL10_50 } PIXEL02_10 PIXEL03_80 PIXEL11_0 PIXEL12_30 PIXEL13_61 PIXEL20_0 PIXEL21_0 PIXEL22_31 PIXEL23_81 if (Diff(w[8], w[4])) { PIXEL30_0 } else { PIXEL30_20 } PIXEL31_0 PIXEL32_31 PIXEL33_81 break; } case 111: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_0 PIXEL02_32 PIXEL03_82 PIXEL10_0 PIXEL11_0 PIXEL12_32 PIXEL13_82 if (Diff(w[8], w[4])) { PIXEL20_0 PIXEL30_0 PIXEL31_0 } else { PIXEL20_50 PIXEL30_50 PIXEL31_50 } PIXEL21_0 PIXEL22_30 PIXEL23_61 PIXEL32_10 PIXEL33_80 break; } case 63: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_0 if (Diff(w[2], w[6])) { PIXEL02_0 PIXEL03_0 PIXEL13_0 } else { PIXEL02_50 PIXEL03_50 PIXEL13_50 } PIXEL10_0 PIXEL11_0 PIXEL12_0 PIXEL20_31 PIXEL21_31 PIXEL22_30 PIXEL23_10 PIXEL30_81 PIXEL31_81 PIXEL32_61 PIXEL33_80 break; } case 159: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL01_0 PIXEL10_0 } else { PIXEL00_50 PIXEL01_50 PIXEL10_50 } PIXEL02_0 if (Diff(w[2], w[6])) { PIXEL03_0 } else { PIXEL03_20 } PIXEL11_0 PIXEL12_0 PIXEL13_0 PIXEL20_10 PIXEL21_30 PIXEL22_32 PIXEL23_32 PIXEL30_80 PIXEL31_61 PIXEL32_82 PIXEL33_82 break; } case 215: { PIXEL00_81 PIXEL01_31 PIXEL02_0 if (Diff(w[2], w[6])) { PIXEL03_0 } else { PIXEL03_20 } PIXEL10_81 PIXEL11_31 PIXEL12_0 PIXEL13_0 PIXEL20_61 PIXEL21_30 PIXEL22_0 if (Diff(w[6], w[8])) { PIXEL23_0 PIXEL32_0 PIXEL33_0 } else { PIXEL23_50 PIXEL32_50 PIXEL33_50 } PIXEL30_80 PIXEL31_10 break; } case 246: { PIXEL00_80 PIXEL01_10 if (Diff(w[2], w[6])) { PIXEL02_0 PIXEL03_0 PIXEL13_0 } else { PIXEL02_50 PIXEL03_50 PIXEL13_50 } PIXEL10_61 PIXEL11_30 PIXEL12_0 PIXEL20_82 PIXEL21_32 PIXEL22_0 PIXEL23_0 PIXEL30_82 PIXEL31_32 PIXEL32_0 if (Diff(w[6], w[8])) { PIXEL33_0 } else { PIXEL33_20 } break; } case 254: { PIXEL00_80 PIXEL01_10 if (Diff(w[2], w[6])) { PIXEL02_0 PIXEL03_0 PIXEL13_0 } else { PIXEL02_50 PIXEL03_50 PIXEL13_50 } PIXEL10_10 PIXEL11_30 PIXEL12_0 if (Diff(w[8], w[4])) { PIXEL20_0 PIXEL30_0 PIXEL31_0 } else { PIXEL20_50 PIXEL30_50 PIXEL31_50 } PIXEL21_0 PIXEL22_0 PIXEL23_0 PIXEL32_0 if (Diff(w[6], w[8])) { PIXEL33_0 } else { PIXEL33_20 } break; } case 253: { PIXEL00_82 PIXEL01_82 PIXEL02_81 PIXEL03_81 PIXEL10_32 PIXEL11_32 PIXEL12_31 PIXEL13_31 PIXEL20_0 PIXEL21_0 PIXEL22_0 PIXEL23_0 if (Diff(w[8], w[4])) { PIXEL30_0 } else { PIXEL30_20 } PIXEL31_0 PIXEL32_0 if (Diff(w[6], w[8])) { PIXEL33_0 } else { PIXEL33_20 } break; } case 251: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL01_0 PIXEL10_0 } else { PIXEL00_50 PIXEL01_50 PIXEL10_50 } PIXEL02_10 PIXEL03_80 PIXEL11_0 PIXEL12_30 PIXEL13_10 PIXEL20_0 PIXEL21_0 PIXEL22_0 if (Diff(w[6], w[8])) { PIXEL23_0 PIXEL32_0 PIXEL33_0 } else { PIXEL23_50 PIXEL32_50 PIXEL33_50 } if (Diff(w[8], w[4])) { PIXEL30_0 } else { PIXEL30_20 } PIXEL31_0 break; } case 239: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_0 PIXEL02_32 PIXEL03_82 PIXEL10_0 PIXEL11_0 PIXEL12_32 PIXEL13_82 PIXEL20_0 PIXEL21_0 PIXEL22_31 PIXEL23_81 if (Diff(w[8], w[4])) { PIXEL30_0 } else { PIXEL30_20 } PIXEL31_0 PIXEL32_31 PIXEL33_81 break; } case 127: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_0 if (Diff(w[2], w[6])) { PIXEL02_0 PIXEL03_0 PIXEL13_0 } else { PIXEL02_50 PIXEL03_50 PIXEL13_50 } PIXEL10_0 PIXEL11_0 PIXEL12_0 if (Diff(w[8], w[4])) { PIXEL20_0 PIXEL30_0 PIXEL31_0 } else { PIXEL20_50 PIXEL30_50 PIXEL31_50 } PIXEL21_0 PIXEL22_30 PIXEL23_10 PIXEL32_10 PIXEL33_80 break; } case 191: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_0 PIXEL02_0 if (Diff(w[2], w[6])) { PIXEL03_0 } else { PIXEL03_20 } PIXEL10_0 PIXEL11_0 PIXEL12_0 PIXEL13_0 PIXEL20_31 PIXEL21_31 PIXEL22_32 PIXEL23_32 PIXEL30_81 PIXEL31_81 PIXEL32_82 PIXEL33_82 break; } case 223: { if (Diff(w[4], w[2])) { PIXEL00_0 PIXEL01_0 PIXEL10_0 } else { PIXEL00_50 PIXEL01_50 PIXEL10_50 } PIXEL02_0 if (Diff(w[2], w[6])) { PIXEL03_0 } else { PIXEL03_20 } PIXEL11_0 PIXEL12_0 PIXEL13_0 PIXEL20_10 PIXEL21_30 PIXEL22_0 if (Diff(w[6], w[8])) { PIXEL23_0 PIXEL32_0 PIXEL33_0 } else { PIXEL23_50 PIXEL32_50 PIXEL33_50 } PIXEL30_80 PIXEL31_10 break; } case 247: { PIXEL00_81 PIXEL01_31 PIXEL02_0 if (Diff(w[2], w[6])) { PIXEL03_0 } else { PIXEL03_20 } PIXEL10_81 PIXEL11_31 PIXEL12_0 PIXEL13_0 PIXEL20_82 PIXEL21_32 PIXEL22_0 PIXEL23_0 PIXEL30_82 PIXEL31_32 PIXEL32_0 if (Diff(w[6], w[8])) { PIXEL33_0 } else { PIXEL33_20 } break; } case 255: { if (Diff(w[4], w[2])) { PIXEL00_0 } else { PIXEL00_20 } PIXEL01_0 PIXEL02_0 if (Diff(w[2], w[6])) { PIXEL03_0 } else { PIXEL03_20 } PIXEL10_0 PIXEL11_0 PIXEL12_0 PIXEL13_0 PIXEL20_0 PIXEL21_0 PIXEL22_0 PIXEL23_0 if (Diff(w[8], w[4])) { PIXEL30_0 } else { PIXEL30_20 } PIXEL31_0 PIXEL32_0 if (Diff(w[6], w[8])) { PIXEL33_0 } else { PIXEL33_20 } break; } } //pIn+=2; pIn+=4; pOut+=16; } pOut+=BpL; pOut+=BpL; pOut+=BpL; } for (j=0; j #include #ifndef WIN32 #include #endif #include #include #include #include "glide.h" #include "main.h" #include "m64p.h" #define SAVE_CBUFFER #ifdef VPDEBUG #include #endif extern void FindBestDepthBias(); extern int getEnableFBO(); extern int getDisableAuxbuf(); extern int drawFlag; // draw flag for rendering callback #ifdef WIN32 PFNGLACTIVETEXTUREARBPROC glActiveTextureARB; PFNGLATTACHOBJECTARBPROC glAttachObjectARB; PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT; PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT; PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT; PFNGLCOMPILESHADERARBPROC glCompileShaderARB; PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB; PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB; PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT; PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT; PFNGLFOGCOORDFEXTPROC glFogCoordfEXT; PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT; PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT; PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT; PFNGLGETINFOLOGARBPROC glGetInfoLogARB; PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB; PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB; PFNGLLINKPROGRAMARBPROC glLinkProgramARB; PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB; PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT; PFNGLSECONDARYCOLOR3FPROC glSecondaryColor3f; PFNGLSHADERSOURCEARBPROC glShaderSourceARB; PFNGLUNIFORM1FARBPROC glUniform1fARB; PFNGLUNIFORM1IARBPROC glUniform1iARB; PFNGLUNIFORM4FARBPROC glUniform4fARB; PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB; static void APIENTRY EmptyFunc(void) { return; } #define INIT_ENTRY_POINT(type, funcname) \ funcname = (type) CoreVideo_GL_GetProcAddress(#funcname); \ if (funcname == NULL) { WriteLog(M64MSG_WARNING, \ "Couldn't get address of OpenGL function: '%s'", #funcname); funcname = (type) EmptyFunc; } static void InitGLPrototypes() { INIT_ENTRY_POINT(PFNGLACTIVETEXTUREARBPROC, glActiveTextureARB); INIT_ENTRY_POINT(PFNGLATTACHOBJECTARBPROC, glAttachObjectARB); INIT_ENTRY_POINT(PFNGLBINDFRAMEBUFFEREXTPROC, glBindFramebufferEXT); INIT_ENTRY_POINT(PFNGLBINDRENDERBUFFEREXTPROC, glBindRenderbufferEXT); INIT_ENTRY_POINT(PFNGLBLENDFUNCSEPARATEEXTPROC, glBlendFuncSeparateEXT); INIT_ENTRY_POINT(PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC, glCheckFramebufferStatusEXT); INIT_ENTRY_POINT(PFNGLCOMPILESHADERARBPROC, glCompileShaderARB); INIT_ENTRY_POINT(PFNGLCREATEPROGRAMOBJECTARBPROC, glCreateProgramObjectARB); INIT_ENTRY_POINT(PFNGLCREATESHADEROBJECTARBPROC, glCreateShaderObjectARB); INIT_ENTRY_POINT(PFNGLDELETERENDERBUFFERSEXTPROC, glDeleteRenderbuffersEXT); INIT_ENTRY_POINT(PFNGLDELETEFRAMEBUFFERSEXTPROC, glDeleteFramebuffersEXT); INIT_ENTRY_POINT(PFNGLFOGCOORDFEXTPROC, glFogCoordfEXT); INIT_ENTRY_POINT(PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC, glFramebufferRenderbufferEXT); INIT_ENTRY_POINT(PFNGLFRAMEBUFFERTEXTURE2DEXTPROC, glFramebufferTexture2DEXT); INIT_ENTRY_POINT(PFNGLGENFRAMEBUFFERSEXTPROC, glGenFramebuffersEXT); INIT_ENTRY_POINT(PFNGLGENRENDERBUFFERSEXTPROC, glGenRenderbuffersEXT); INIT_ENTRY_POINT(PFNGLGETINFOLOGARBPROC, glGetInfoLogARB); INIT_ENTRY_POINT(PFNGLGETOBJECTPARAMETERIVARBPROC, glGetObjectParameterivARB); INIT_ENTRY_POINT(PFNGLGETUNIFORMLOCATIONARBPROC, glGetUniformLocationARB); INIT_ENTRY_POINT(PFNGLLINKPROGRAMARBPROC, glLinkProgramARB); INIT_ENTRY_POINT(PFNGLMULTITEXCOORD2FARBPROC, glMultiTexCoord2fARB); INIT_ENTRY_POINT(PFNGLRENDERBUFFERSTORAGEEXTPROC, glRenderbufferStorageEXT); INIT_ENTRY_POINT(PFNGLSECONDARYCOLOR3FPROC, glSecondaryColor3f); INIT_ENTRY_POINT(PFNGLSHADERSOURCEARBPROC, glShaderSourceARB); INIT_ENTRY_POINT(PFNGLUNIFORM1FARBPROC, glUniform1fARB); INIT_ENTRY_POINT(PFNGLUNIFORM1IARBPROC, glUniform1iARB); INIT_ENTRY_POINT(PFNGLUNIFORM4FARBPROC, glUniform4fARB); INIT_ENTRY_POINT(PFNGLUSEPROGRAMOBJECTARBPROC, glUseProgramObjectARB); } #else static void InitGLPrototypes() { return; } #endif int screen_width, screen_height; static inline void opt_glCopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border ) { GLsizei w, h; GLenum fmt; glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, (GLint *) &fmt); //printf("copyteximage %dx%d fmt %x oldfmt %x\n", width, height, internalFormat, fmt); if (w == width && h == height && fmt == internalFormat) { if (x+width >= screen_width) { width = screen_width - x; //printf("resizing w --> %d\n", width); } if (y+height >= screen_height+viewport_offset) { height = screen_height+viewport_offset - y; //printf("resizing h --> %d\n", height); } glCopyTexSubImage2D(target, level, 0, 0, x, y, width, height); } else { WriteLog(M64MSG_VERBOSE, "copyteximage %dx%d fmt %x old %dx%d oldfmt %x\n", width, height, internalFormat, w, h, fmt); // glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, internalFormat, GL_UNSIGNED_BYTE, 0); // glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt); // printf("--> %dx%d newfmt %x\n", width, height, fmt); glCopyTexImage2D(target, level, internalFormat, x, y, width, height, border); } } #define glCopyTexImage2D opt_glCopyTexImage2D typedef struct { unsigned int address; int width; int height; GLuint fbid; GLuint zbid; GLuint texid; int buff_clear; } fb; GLint nbTextureUnits; GLint nbAuxBuffers, current_buffer; int width, widtho, heighto, height; int saved_width, saved_height; int blend_func_separate_support; int npot_support; int fog_coord_support; int render_to_texture = 0; int texture_unit; int use_fbo; int buffer_cleared; // ZIGGY // to allocate a new static texture name, take the value (free_texture++) int free_texture; int default_texture; // the infamous "32*1024*1024" is now configurable int current_texture; int depth_texture, color_texture; int glsl_support = 0; int viewport_width, viewport_height, viewport_offset = 0; int save_w, save_h; int lfb_color_fmt; float invtex[2]; static unsigned long fullscreen; static int savedWidtho, savedHeighto; static int savedWidth, savedHeight; unsigned int pBufferAddress; static int pBufferFmt; static int pBufferWidth, pBufferHeight; static fb fbs[100]; static int nb_fb = 0; static unsigned int curBufferAddr = 0; struct s_usage { unsigned int min, max; }; struct s_usage tmu_usage[2] = { {0xfffffff, 0}, {0xfffffff, 0} }; struct texbuf_t { DWORD start, end; int fmt; }; #define NB_TEXBUFS 128 // MUST be a power of two static texbuf_t texbufs[NB_TEXBUFS]; static int texbuf_i; static SDL_Surface *m_pScreen; // unsigned short * frameBuffer = NULL; // unsigned short * depthBuffer = NULL; unsigned short frameBuffer[2048*2048]; unsigned short depthBuffer[2048*2048]; //#define VOODOO1 void display_warning(const char *text, ...) { static int first_message = 100; if (first_message) { char buf[1000]; va_list ap; va_start(ap, text); vsprintf((char*)buf, (char*)text, ap); va_end(ap); WriteLog(M64MSG_WARNING, "%s", buf); first_message--; } } #ifdef LOGGING FILE *log_file = NULL; void OPEN_LOG() { log_file = fopen("wrapper_log.txt", "wb+"); } void CLOSE_LOG() { if(log_file == NULL) return; fclose(log_file); log_file = NULL; } void LOG(char *text, ...) { #ifdef VPDEBUG if (!dumping) return; #endif va_list ap; if(log_file == NULL) return; va_start(ap, text); vfprintf(log_file, text, ap); vfprintf(stderr, text, ap); va_end(ap); } #endif // LOGGING FX_ENTRY void FX_CALL grSstOrigin(GrOriginLocation_t origin) { WriteLog(M64MSG_VERBOSE, "grSstOrigin(%d)\r\n", origin); if (origin != GR_ORIGIN_UPPER_LEFT) display_warning("grSstOrigin : %x", origin); } FX_ENTRY void FX_CALL grClipWindow( FxU32 minx, FxU32 miny, FxU32 maxx, FxU32 maxy ) { WriteLog(M64MSG_VERBOSE, "grClipWindow(%d,%d,%d,%d)\r\n", minx, miny, maxx, maxy); if (use_fbo && render_to_texture) { glScissor(minx, miny, maxx - minx, maxy - miny); glEnable(GL_SCISSOR_TEST); return; } if (!use_fbo) { int th = height; if (!use_fbo && th > screen_height) th = screen_height; maxy = th - maxy; miny = th - miny; FxU32 tmp = maxy; maxy = miny; miny = tmp; // if (minx < 0) minx = 0; // if (miny < 0) miny = 0; if (maxx > (unsigned int) width) maxx = width; if (maxy > (unsigned int) height) maxy = height; glScissor(minx, miny+viewport_offset, maxx - minx, maxy - miny); //printf("gl scissor %d %d %d %d\n", minx, miny, maxx, maxy); //glScissor(minx, (viewport_offset)+height-maxy, maxx - minx, maxy - miny); } else { glScissor(minx, (viewport_offset)+height-maxy, maxx - minx, maxy - miny); } glEnable(GL_SCISSOR_TEST); } FX_ENTRY void FX_CALL grColorMask( FxBool rgb, FxBool a ) { WriteLog(M64MSG_VERBOSE, "grColorMask(%d, %d)\r\n", rgb, a); glColorMask(rgb, rgb, rgb, a); } FX_ENTRY void FX_CALL grGlideInit( void ) { OPEN_LOG(); WriteLog(M64MSG_VERBOSE, "grGlideInit()\r\n"); } FX_ENTRY void FX_CALL grSstSelect( int which_sst ) { WriteLog(M64MSG_VERBOSE, "grSstSelect(%d)\r\n", which_sst); } BOOL isExtensionSupported(const char *extension) { const GLubyte *extensions = NULL; const GLubyte *start; GLubyte *where, *terminator; where = (GLubyte *)strchr(extension, ' '); if (where || *extension == '\0') return 0; extensions = glGetString(GL_EXTENSIONS); start = extensions; for (;;) { where = (GLubyte *) strstr((const char *) start, extension); if (!where) break; terminator = where + strlen(extension); if (where == start || *(where - 1) == ' ') if (*terminator == ' ' || *terminator == '\0') return TRUE; start = terminator; } return FALSE; } #define GrPixelFormat_t int FX_ENTRY GrContext_t FX_CALL grSstWinOpenExt( FxU32 hWnd, GrScreenResolution_t screen_resolution, GrScreenRefresh_t refresh_rate, GrColorFormat_t color_format, GrOriginLocation_t origin_location, GrPixelFormat_t pixelformat, int nColBuffers, int nAuxBuffers) { WriteLog(M64MSG_VERBOSE, "grSstWinOpenExt(%d, %d, %d, %d, %d, %d %d)\r\n", hWnd, screen_resolution, refresh_rate, color_format, origin_location, nColBuffers, nAuxBuffers); return grSstWinOpen(hWnd, screen_resolution, refresh_rate, color_format, origin_location, nColBuffers, nAuxBuffers); } FX_ENTRY GrContext_t FX_CALL grSstWinOpen( FxU32 hWnd, GrScreenResolution_t screen_resolution, GrScreenRefresh_t refresh_rate, GrColorFormat_t color_format, GrOriginLocation_t origin_location, int nColBuffers, int nAuxBuffers) { static int show_warning = 1; // { // static int inidebug; // if (!inidebug) { // inidebug = 1; // FILE * newstdout = freopen("wrapper-debug.txt", "w", stdout); // _dup2(_fileno(stdout), _fileno(stderr)); // } // } // ZIGGY // allocate static texture names // the initial value should be big enough to support the maximal resolution free_texture = 32*2048*2048; default_texture = free_texture++; color_texture = free_texture++; depth_texture = free_texture++; WriteLog(M64MSG_VERBOSE, "grSstWinOpen(%d, %d, %d, %d, %d, %d %d)\r\n", hWnd, screen_resolution, refresh_rate, color_format, origin_location, nColBuffers, nAuxBuffers); PackedScreenResolution packedResolution; packedResolution.resolution = screen_resolution; width = packedResolution.width; height = packedResolution.height; m64p_video_mode screen_mode; if (packedResolution.fullscreen) screen_mode = M64VIDEO_FULLSCREEN; else screen_mode = M64VIDEO_WINDOWED; if (CoreVideo_GL_SetAttribute(M64P_GL_DOUBLEBUFFER, 1) != M64ERR_SUCCESS || CoreVideo_GL_SetAttribute(M64P_GL_BUFFER_SIZE, 16) != M64ERR_SUCCESS || CoreVideo_GL_SetAttribute(M64P_GL_DEPTH_SIZE, 16) != M64ERR_SUCCESS) { WriteLog(M64MSG_ERROR, "Could not set video attributes."); return 0; } if (CoreVideo_SetVideoMode(width, height, 0, screen_mode, (m64p_video_flags) 0) != M64ERR_SUCCESS) { WriteLog(M64MSG_ERROR, "Could not set video mode."); return 0; } CoreVideo_SetCaption("Glide64"); fullscreen = 0; InitGLPrototypes(); // ZIGGY viewport_offset is WIN32 specific, with SDL just set it to zero viewport_offset = 0; //-10 //-20; glViewport(0, viewport_offset, width, height); //if (color_format != GR_COLORFORMAT_ARGB) display_warning("color format is not ARGB"); lfb_color_fmt = color_format; if (origin_location != GR_ORIGIN_UPPER_LEFT) display_warning("origin must be in upper left corner"); if (nColBuffers != 2) display_warning("number of color buffer is not 2"); if (nAuxBuffers != 1) display_warning("number of auxiliary buffer is not 1"); if (isExtensionSupported("GL_ARB_texture_env_combine") == FALSE && isExtensionSupported("GL_EXT_texture_env_combine") == FALSE && show_warning) display_warning("Your video card doesn't support GL_ARB_texture_env_combine extension"); if (isExtensionSupported("GL_ARB_multitexture") == FALSE && show_warning) display_warning("Your video card doesn't support GL_ARB_multitexture extension"); if (isExtensionSupported("GL_ARB_texture_mirrored_repeat") == FALSE && show_warning) display_warning("Your video card doesn't support GL_ARB_texture_mirrored_repeat extension"); show_warning = 0; nbTextureUnits = 0; glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &nbTextureUnits); if (nbTextureUnits == 1) display_warning("You need a video card that has at least 2 texture units"); nbAuxBuffers = 0; if (!getDisableAuxbuf()) glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &nbAuxBuffers); if (nbAuxBuffers > 0) WriteLog(M64MSG_INFO, "Congratulations, you have %d auxiliary buffers, we'll use them wisely !\n", nbAuxBuffers); #ifdef VOODOO1 nbTextureUnits = 2; #endif if (isExtensionSupported("GL_EXT_blend_func_separate") == FALSE) blend_func_separate_support = 0; else blend_func_separate_support = 1; if (isExtensionSupported("GL_EXT_packed_pixels") == FALSE) packed_pixels_support = 0; else { WriteLog(M64MSG_INFO, "packed pixels extension used\n"); packed_pixels_support = 1; } if (isExtensionSupported("GL_ARB_texture_non_power_of_two") == FALSE) npot_support = 0; else { WriteLog(M64MSG_INFO, "NPOT extension used\n"); npot_support = 1; } if (isExtensionSupported("GL_EXT_fog_coord") == FALSE) fog_coord_support = 0; else fog_coord_support = 1; use_fbo = getEnableFBO(); WriteLog(M64MSG_INFO, "use_fbo %d\n", use_fbo); if (isExtensionSupported("GL_ARB_shading_language_100") && isExtensionSupported("GL_ARB_shader_objects") && isExtensionSupported("GL_ARB_fragment_shader") && isExtensionSupported("GL_ARB_vertex_shader") && !getDisableGLSL()) { glsl_support = 1; } else glsl_support = 0; glViewport(0, viewport_offset, width, height); viewport_width = width; viewport_height = height; // void do_benchmarks(); // do_benchmarks(); // VP try to resolve z precision issues glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0, 0, 1-zscale); glScalef(1, 1, zscale); // glAlphaFunc(GL_GREATER, 0.5); // glEnable(GL_ALPHA_TEST); widtho = width/2; heighto = height/2; pBufferWidth = pBufferHeight = -1; current_buffer = GL_BACK; if(!glsl_support) { switch(nbTextureUnits) { case 2: texture_unit = GL_TEXTURE1_ARB; break; case 3: texture_unit = GL_TEXTURE2_ARB; break; default: texture_unit = GL_TEXTURE3_ARB; } } else texture_unit = GL_TEXTURE0_ARB; // frameBuffer = (unsigned short *) calloc(2048, 2048*sizeof(unsigned short)); // depthBuffer = (unsigned short *) calloc(2048, 2048*sizeof(unsigned short)); screen_width = width; screen_height = height; { int i; for (i=0; i> -aspect; } else { pBufferWidth = 1 << lodmin; pBufferHeight = pBufferWidth >> aspect; } if (curBufferAddr && startAddress+1 != curBufferAddr) updateTexture(); #ifdef SAVE_CBUFFER //printf("saving %dx%d\n", pBufferWidth, pBufferHeight); // save color buffer if (nbAuxBuffers > 0) { glDrawBuffer(GL_AUX0); current_buffer = GL_AUX0; } else { int tw, th; if (pBufferWidth < screen_width) tw = pBufferWidth; else tw = screen_width; if (pBufferHeight < screen_height) th = pBufferHeight; else th = screen_height; glReadBuffer(GL_BACK); glActiveTextureARB(texture_unit); glBindTexture(GL_TEXTURE_2D, color_texture); // save incrementally the framebuffer if (save_w) { if (tw > save_w && th > save_h) { glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, save_h, 0, viewport_offset+save_h, tw, th-save_h); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, save_w, 0, save_w, viewport_offset, tw-save_w, save_h); save_w = tw; save_h = th; } else if (tw > save_w) { glCopyTexSubImage2D(GL_TEXTURE_2D, 0, save_w, 0, save_w, viewport_offset, tw-save_w, save_h); save_w = tw; } else if (th > save_h) { glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, save_h, 0, viewport_offset+save_h, save_w, th-save_h); save_h = th; } } else { glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, viewport_offset, tw, th); save_w = tw; save_h = th; } glBindTexture(GL_TEXTURE_2D, default_texture); } #endif if (startAddress+1 != curBufferAddr || (curBufferAddr == 0L && nbAuxBuffers == 0)) buffer_cleared = FALSE; curBufferAddr = pBufferAddress = startAddress+1; pBufferFmt = fmt; int rtmu = startAddress < grTexMinAddress(GR_TMU1)? 0 : 1; int size = pBufferWidth*pBufferHeight*2; //grTexFormatSize(fmt); if (tmu_usage[rtmu].min > pBufferAddress) tmu_usage[rtmu].min = pBufferAddress; if (tmu_usage[rtmu].max < pBufferAddress+size) tmu_usage[rtmu].max = pBufferAddress+size; // printf("tmu %d usage now %gMb - %gMb\n", // rtmu, tmu_usage[rtmu].min/1024.0f, tmu_usage[rtmu].max/1024.0f); width = pBufferWidth; height = pBufferHeight; widtho = width/2; heighto = height/2; // this could be improved, but might be enough as long as the set of // texture buffer addresses stay small for (i=(texbuf_i-1)&(NB_TEXBUFS-1) ; i!=texbuf_i; i=(i-1)&(NB_TEXBUFS-1)) if (texbufs[i].start == pBufferAddress) break; texbufs[i].start = pBufferAddress; texbufs[i].end = pBufferAddress + size; texbufs[i].fmt = fmt; if (i == texbuf_i) texbuf_i = (texbuf_i+1)&(NB_TEXBUFS-1); //printf("texbuf %x fmt %x\n", pBufferAddress, fmt); // ZIGGY it speeds things up to not delete the buffers // a better thing would be to delete them *sometimes* // remove_tex(pBufferAddress+1, pBufferAddress + size); add_tex(pBufferAddress); //printf("viewport %dx%d\n", width, height); if (height > screen_height) { glViewport( 0, viewport_offset + screen_height - height, width, height); } else glViewport( 0, viewport_offset, width, height); glScissor(0, viewport_offset, width, height); // glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); // glClear( GL_COLOR_BUFFER_BIT ); // glClear( GL_DEPTH_BUFFER_BIT ); } else { if (!render_to_texture) //initialization { if(!fbs_init) { for(i=0; i<100; i++) fbs[i].address = 0; fbs_init = 1; nb_fb = 0; } return; //no need to allocate FBO if render buffer is not texture buffer } render_to_texture = 2; if (aspect < 0) { pBufferHeight = 1 << lodmin; pBufferWidth = pBufferHeight >> -aspect; } else { pBufferWidth = 1 << lodmin; pBufferHeight = pBufferWidth >> aspect; } pBufferAddress = startAddress+1; width = pBufferWidth; height = pBufferHeight; widtho = width/2; heighto = height/2; //glScissor(0, 0, width, height); //glEnable(GL_SCISSOR_TEST); for (i=0; i 1) memmove(&(fbs[i]), &(fbs[i+1]), sizeof(fb)*(nb_fb-i)); nb_fb--; break; } } } remove_tex(pBufferAddress, pBufferAddress + width*height*2/*grTexFormatSize(fmt)*/); //create new FBO glGenFramebuffersEXT( 1, &(fbs[nb_fb].fbid) ); glGenRenderbuffersEXT( 1, &(fbs[nb_fb].zbid) ); glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, fbs[nb_fb].zbid ); // VP ported from mudlord glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height); //glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height); fbs[nb_fb].address = pBufferAddress; fbs[nb_fb].width = width; fbs[nb_fb].height = height; fbs[nb_fb].texid = pBufferAddress; fbs[nb_fb].buff_clear = 0; add_tex(fbs[nb_fb].texid); glBindTexture(GL_TEXTURE_2D, fbs[nb_fb].texid); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fbs[nb_fb].fbid); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbs[nb_fb].texid, 0); glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbs[nb_fb].zbid ); glViewport(0,0,width,height); glScissor(0,0,width,height); glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); glDepthMask(TRUE); glClear( GL_DEPTH_BUFFER_BIT ); CHECK_FRAMEBUFFER_STATUS(); curBufferAddr = pBufferAddress; nb_fb++; } } int CheckTextureBufferFormat(GrChipID_t tmu, FxU32 startAddress, GrTexInfo *info ) { int found, i; if (!use_fbo) { for (found=i=0; i<2; i++) if (tmu_usage[i].min <= startAddress && tmu_usage[i].max > startAddress) { //printf("tmu %d == framebuffer %x\n", tmu, startAddress); found = 1; break; } // if (found && info->format == GR_TEXFMT_ALPHA_INTENSITY_88) { // // now check the original buffer format // // if it was 565, then we are dealing with a b&w conversion hack // // so use special shader for it // for (i=(texbuf_i-1)&(NB_TEXBUFS-1); i!=texbuf_i; i = (i-1)&(NB_TEXBUFS-1)) // if (texbufs[i].start == startAddress) { // if (texbufs[i].fmt != GR_TEXFMT_ALPHA_INTENSITY_88) // found = 2; // if (found == 2) // printf("texbuf %x fmt now %x\n", startAddress, info->format); // break; // } // if (i == texbuf_i) // display_warning("Couldn't find texbuf %x !\n", startAddress); // } } else { found = i = 0; while (i < nb_fb) { unsigned int end = fbs[i].address + fbs[i].width*fbs[i].height*2; if (startAddress >= fbs[i].address && startAddress < end) { found = 1; break; } i++; } } if (!use_fbo && found) { int tw, th, rh, cw, ch; if (info->aspectRatioLog2 < 0) { th = 1 << info->largeLodLog2; tw = th >> -info->aspectRatioLog2; } else { tw = 1 << info->largeLodLog2; th = tw >> info->aspectRatioLog2; } if (info->aspectRatioLog2 < 0) { ch = 256; cw = ch >> -info->aspectRatioLog2; } else { cw = 256; ch = cw >> info->aspectRatioLog2; } if (use_fbo || th < screen_height) rh = th; else rh = screen_height; //printf("th %d rh %d ch %d\n", th, rh, ch); invtex[tmu] = 1.0f - (th - rh) / (float)th; } else invtex[tmu] = 0; if (info->format == GR_TEXFMT_ALPHA_INTENSITY_88 ) { if (!found) { return 0; } //glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE8_ALPHA8, fbs[i].width, fbs[i].height, 0, GL_LUMINANCE8_ALPHA8, GL_UNSIGNED_BYTE, NULL); if(tmu == 0) { if(blackandwhite1 != found) { blackandwhite1 = found; need_to_compile = 1; } } else { if(blackandwhite0 != found) { blackandwhite0 = found; need_to_compile = 1; } } return 1; } return 0; } FX_ENTRY void FX_CALL grTextureAuxBufferExt( GrChipID_t tmu, FxU32 startAddress, GrLOD_t thisLOD, GrLOD_t largeLOD, GrAspectRatio_t aspectRatio, GrTextureFormat_t format, FxU32 odd_even_mask ) { WriteLog(M64MSG_VERBOSE, "grTextureAuxBufferExt(%d, %d, %d, %d %d, %d, %d)\r\n", tmu, startAddress, thisLOD, largeLOD, aspectRatio, format, odd_even_mask); //display_warning("grTextureAuxBufferExt"); } FX_ENTRY void FX_CALL grAuxBufferExt( GrBuffer_t buffer ); FX_ENTRY GrProc FX_CALL grGetProcAddress( const char *procName ) { WriteLog(M64MSG_VERBOSE, "grGetProcAddress(%s)\r\n", procName); if(!strcmp(procName, "grSstWinOpenExt")) return (GrProc)grSstWinOpenExt; if(!strcmp(procName, "grTextureBufferExt")) return (GrProc)grTextureBufferExt; if(!strcmp(procName, "grChromaRangeExt")) return (GrProc)grChromaRangeExt; if(!strcmp(procName, "grChromaRangeModeExt")) return (GrProc)grChromaRangeModeExt; if(!strcmp(procName, "grTexChromaRangeExt")) return (GrProc)grTexChromaRangeExt; if(!strcmp(procName, "grTexChromaModeExt")) return (GrProc)grTexChromaModeExt; if(!strcmp(procName, "grConfigWrapperExt")) return (GrProc)grConfigWrapperExt; // ZIGGY framebuffer copy extension if(/*glsl_support && */!strcmp(procName, "grFramebufferCopyExt")) return (GrProc)grFramebufferCopyExt; if(!strcmp(procName, "grWrapperFullScreenResolutionExt")) return (GrProc)grWrapperFullScreenResolutionExt; if(!strcmp(procName, "grColorCombineExt")) return (GrProc)grColorCombineExt; if(!strcmp(procName, "grAlphaCombineExt")) return (GrProc)grAlphaCombineExt; if(!strcmp(procName, "grTexColorCombineExt")) return (GrProc)grTexColorCombineExt; if(!strcmp(procName, "grTexAlphaCombineExt")) return (GrProc)grTexAlphaCombineExt; if(!strcmp(procName, "grConstantColorValueExt")) return (GrProc)grConstantColorValueExt; if(!strcmp(procName, "grTextureAuxBufferExt")) return (GrProc)grTextureAuxBufferExt; if(!strcmp(procName, "grAuxBufferExt")) return (GrProc)grAuxBufferExt; display_warning("grGetProcAddress : %s", procName); return 0; } FX_ENTRY FxU32 FX_CALL grGet( FxU32 pname, FxU32 plength, FxI32 *params ) { WriteLog(M64MSG_VERBOSE, "grGet(%d,%d)\r\n", pname, plength); switch(pname) { case GR_MAX_TEXTURE_SIZE: if (plength < 4 || params == NULL) return 0; params[0] = 2048; return 4; break; case GR_NUM_TMU: if (plength < 4 || params == NULL) return 0; if (!nbTextureUnits) { grSstWinOpen((unsigned long)NULL, GR_RESOLUTION_640x480 | 0x80, 0, GR_COLORFORMAT_ARGB, GR_ORIGIN_UPPER_LEFT, 2, 1); grSstWinClose(0); } #ifdef VOODOO1 params[0] = 1; #else if (nbTextureUnits > 2) params[0] = 2; else params[0] = 1; #endif return 4; break; case GR_NUM_BOARDS: case GR_NUM_FB: case GR_REVISION_FB: case GR_REVISION_TMU: if (plength < 4 || params == NULL) return 0; params[0] = 1; return 4; break; case GR_MEMORY_FB: if (plength < 4 || params == NULL) return 0; params[0] = 16*1024*1024; return 4; break; case GR_MEMORY_TMU: if (plength < 4 || params == NULL) return 0; params[0] = 16*1024*1024; return 4; break; case GR_MEMORY_UMA: if (plength < 4 || params == NULL) return 0; params[0] = 16*1024*1024*nbTextureUnits; return 4; break; case GR_BITS_RGBA: if (plength < 16 || params == NULL) return 0; params[0] = 8; params[1] = 8; params[2] = 8; params[3] = 8; return 16; break; case GR_BITS_DEPTH: if (plength < 4 || params == NULL) return 0; params[0] = 16; return 4; break; case GR_BITS_GAMMA: case GR_GAMMA_TABLE_ENTRIES: return 0; break; case GR_FOG_TABLE_ENTRIES: if (plength < 4 || params == NULL) return 0; params[0] = 64; return 4; break; case GR_WDEPTH_MIN_MAX: if (plength < 8 || params == NULL) return 0; params[0] = 0; params[1] = 65528; return 8; break; case GR_ZDEPTH_MIN_MAX: if (plength < 8 || params == NULL) return 0; params[0] = 0; params[1] = 65535; return 8; break; case GR_LFB_PIXEL_PIPE: if (plength < 4 || params == NULL) return 0; params[0] = FXFALSE; return 4; break; case GR_MAX_TEXTURE_ASPECT_RATIO: if (plength < 4 || params == NULL) return 0; params[0] = 3; return 4; break; case GR_NON_POWER_OF_TWO_TEXTURES: if (plength < 4 || params == NULL) return 0; params[0] = FXFALSE; return 4; break; case GR_TEXTURE_ALIGN: if (plength < 4 || params == NULL) return 0; params[0] = 0; return 4; break; default: display_warning("unknown pname in grGet : %x", pname); } return 0; } FX_ENTRY const char * FX_CALL grGetString( FxU32 pname ) { WriteLog(M64MSG_VERBOSE, "grGetString(%d)\r\n", pname); switch(pname) { case GR_EXTENSION: { static int glsl_combiner = -1; static char extension1[] = "CHROMARANGE TEXCHROMA TEXMIRROR PALETTE6666 FOGCOORD EVOODOO TEXTUREBUFFER TEXFMT COMBINE"; static char extension2[] = "CHROMARANGE TEXCHROMA TEXMIRROR PALETTE6666 FOGCOORD EVOODOO TEXTUREBUFFER TEXFMT"; if(glsl_combiner == -1) { /* JOSH FIXME: hack to avoid implementing CreateGLWindow and KillGLWindow * Rather than calling glGetString to check for the appropriate extensions, * just let getDisableGLSL() decide. */ glsl_combiner = 1; /* Just use the disable flag */ } if(glsl_combiner == 1 && !getDisableGLSL()) return extension1; else return extension2; } break; case GR_HARDWARE: { static char hardware[] = "Voodoo5 (tm)"; return hardware; } break; case GR_VENDOR: { static char vendor[] = "3Dfx Interactive"; return vendor; } break; case GR_RENDERER: { static char renderer[] = "Glide"; return renderer; } break; case GR_VERSION: { static char version[] = "3.0"; return version; } break; default: display_warning("unknown grGetString selector : %x", pname); } return NULL; } static void render_rectangle(int texture_number, int dst_x, int dst_y, int src_width, int src_height, int tex_width, int tex_height, int invert) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBegin(GL_QUADS); glMultiTexCoord2fARB(texture_number, 0.0f, 0.0f); glVertex2f(((int)dst_x - widtho) / (float)(width/2), invert*-((int)dst_y - heighto) / (float)(height/2)); glMultiTexCoord2fARB(texture_number, 0.0f, (float)src_height / (float)tex_height); glVertex2f(((int)dst_x - widtho) / (float)(width/2), invert*-((int)dst_y + (int)src_height - heighto) / (float)(height/2)); glMultiTexCoord2fARB(texture_number, (float)src_width / (float)tex_width, (float)src_height / (float)tex_height); glVertex2f(((int)dst_x + (int)src_width - widtho) / (float)(width/2), invert*-((int)dst_y + (int)src_height - heighto) / (float)(height/2)); glMultiTexCoord2fARB(texture_number, (float)src_width / (float)tex_width, 0.0f); glVertex2f(((int)dst_x + (int)src_width - widtho) / (float)(width/2), invert*-((int)dst_y - heighto) / (float)(height/2)); glMultiTexCoord2fARB(texture_number, 0.0f, 0.0f); glVertex2f(((int)dst_x - widtho) / (float)(width/2), invert*-((int)dst_y - heighto) / (float)(height/2)); glEnd(); if(!glsl_support) { switch(nbTextureUnits) { case 2: updateCombiner(1); updateCombiner(1); break; case 3: updateCombiner(2); updateCombiner(2); break; default: updateCombiner(3); updateCombiner(3); } } else compile_shader(); glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); } void reloadTexture() { if (use_fbo || !render_to_texture || buffer_cleared) return; WriteLog(M64MSG_VERBOSE, "reload texture %dx%d\n", width, height); buffer_cleared = TRUE; glPushAttrib(GL_ALL_ATTRIB_BITS); glActiveTextureARB(texture_unit); glBindTexture(GL_TEXTURE_2D, pBufferAddress); glDisable(GL_ALPHA_TEST); glDrawBuffer(current_buffer); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); set_copy_shader(); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); int w = 0, h = 0; //if (width > screen_width) w = screen_width - width; if (height > screen_height) h = screen_height - height; render_rectangle(texture_unit, -w, -h, width, height, width, height, -1); glBindTexture(GL_TEXTURE_2D, default_texture); glPopAttrib(); } void updateTexture() { if (!use_fbo && render_to_texture == 2) { WriteLog(M64MSG_VERBOSE, "update texture %x\n", pBufferAddress); //printf("update texture %x\n", pBufferAddress); // nothing changed, don't update the texture if (!buffer_cleared) { WriteLog(M64MSG_VERBOSE, "update cancelled\n"); return; } glPushAttrib(GL_ALL_ATTRIB_BITS); // save result of render to texture into actual texture glReadBuffer(current_buffer); glActiveTextureARB(texture_unit); // ZIGGY // deleting the texture before resampling it increases speed on certain old // nvidia cards (geforce 2 for example), unfortunatly it slows down a lot // on newer cards. //glDeleteTextures( 1, &pBufferAddress ); glBindTexture(GL_TEXTURE_2D, pBufferAddress); glCopyTexImage2D(GL_TEXTURE_2D, 0, (!glsl_support && pBufferFmt == GR_TEXFMT_ALPHA_INTENSITY_88)? GL_INTENSITY : GL_RGB, 0, viewport_offset, width, height, 0); glBindTexture(GL_TEXTURE_2D, default_texture); glPopAttrib(); } } FX_ENTRY void FX_CALL grFramebufferCopyExt(int x, int y, int w, int h, int from, int to, int mode) { if (mode == GR_FBCOPY_MODE_DEPTH) { if(!glsl_support) { return; } int tw = 1, th = 1; if (npot_support) { tw = width; th = height; } else { while (tw < width) tw <<= 1; while (th < height) th <<= 1; } if (from == GR_FBCOPY_BUFFER_BACK && to == GR_FBCOPY_BUFFER_FRONT) { WriteLog(M64MSG_VERBOSE, "save depth buffer %d\n", render_to_texture); // save the depth image in a texture //glDisable(GL_ALPHA_TEST); glReadBuffer(current_buffer); glBindTexture(GL_TEXTURE_2D, depth_texture); glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0, viewport_offset, tw, th, 0); glBindTexture(GL_TEXTURE_2D, default_texture); return; } if (from == GR_FBCOPY_BUFFER_FRONT && to == GR_FBCOPY_BUFFER_BACK) { WriteLog(M64MSG_VERBOSE, "writing to depth buffer %d\n", render_to_texture); glPushAttrib(GL_ALL_ATTRIB_BITS); glDisable(GL_ALPHA_TEST); glDrawBuffer(current_buffer); glActiveTextureARB(texture_unit); glBindTexture(GL_TEXTURE_2D, depth_texture); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); set_depth_shader(); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_ALWAYS); glDisable(GL_CULL_FACE); render_rectangle(texture_unit, 0, 0, width, height, tw, th, -1); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glBindTexture(GL_TEXTURE_2D, default_texture); glPopAttrib(); return; } } } FX_ENTRY void FX_CALL grRenderBuffer( GrBuffer_t buffer ) { WriteLog(M64MSG_VERBOSE, "grRenderBuffer(%d)\r\n", buffer); //printf("grRenderBuffer(%d)\n", buffer); switch(buffer) { case GR_BUFFER_BACKBUFFER: if(render_to_texture) { updateTexture(); // VP z fix glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0, 0, 1-zscale); glScalef(1, 1, zscale); inverted_culling = 0; grCullMode(culling_mode); width = savedWidth; height = savedHeight; widtho = savedWidtho; heighto = savedHeighto; if (use_fbo) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 ); } curBufferAddr = 0; glViewport(0, viewport_offset, width, viewport_height); glScissor(0, viewport_offset, width, height); #ifdef SAVE_CBUFFER if (!use_fbo && render_to_texture == 2) { // restore color buffer if (nbAuxBuffers > 0) { glDrawBuffer(GL_BACK); current_buffer = GL_BACK; } else if (save_w) { int tw = 1, th = 1; //printf("restore %dx%d\n", save_w, save_h); if (npot_support) { tw = screen_width; th = screen_height; } else { while (tw < screen_width) tw <<= 1; while (th < screen_height) th <<= 1; } glPushAttrib(GL_ALL_ATTRIB_BITS); glDisable(GL_ALPHA_TEST); glDrawBuffer(GL_BACK); glActiveTextureARB(texture_unit); glBindTexture(GL_TEXTURE_2D, color_texture); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); set_copy_shader(); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); render_rectangle(texture_unit, 0, 0, save_w, save_h, tw, th, -1); glBindTexture(GL_TEXTURE_2D, default_texture); glPopAttrib(); save_w = save_h = 0; } } #endif // ZIGGY // restore depth buffer // grFramebufferCopyExt(0, 0, width, height, // GR_FBCOPY_BUFFER_FRONT, GR_FBCOPY_BUFFER_BACK, // GR_FBCOPY_MODE_DEPTH); render_to_texture = 0; } glDrawBuffer(GL_BACK); break; case 6: // RENDER TO TEXTURE if(!render_to_texture) { // ZIGGY // save depth buffer // grFramebufferCopyExt(0, 0, width, height, // GR_FBCOPY_BUFFER_BACK, GR_FBCOPY_BUFFER_FRONT, // GR_FBCOPY_MODE_DEPTH); savedWidth = width; savedHeight = height; savedWidtho = widtho; savedHeighto = heighto; } { if (!use_fbo) { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0, 0, 1-zscale); glScalef(1, 1, zscale); inverted_culling = 0; } else { float m[4*4] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f,-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; glMatrixMode(GL_MODELVIEW); glLoadMatrixf(m); // VP z fix glTranslatef(0, 0, 1-zscale); glScalef(1, 1*1, zscale); inverted_culling = 1; grCullMode(culling_mode); } } render_to_texture = 1; break; default: display_warning("grRenderBuffer : unknown buffer : %x", buffer); } } FX_ENTRY void FX_CALL grAuxBufferExt( GrBuffer_t buffer ) { WriteLog(M64MSG_VERBOSE, "grAuxBufferExt(%d)\r\n", buffer); //display_warning("grAuxBufferExt"); if (glsl_support && buffer == GR_BUFFER_AUXBUFFER) { invtex[0] = 0; invtex[1] = 0; need_to_compile = 0; set_depth_shader(); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_ALWAYS); glDisable(GL_CULL_FACE); glDisable(GL_ALPHA_TEST); glDepthMask(GL_TRUE); grTexFilterMode(GR_TMU1, GR_TEXTUREFILTER_POINT_SAMPLED, GR_TEXTUREFILTER_POINT_SAMPLED); // glActiveTextureARB(texture_unit); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } else { glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); need_to_compile = 1; } } FX_ENTRY void FX_CALL grBufferClear( GrColor_t color, GrAlpha_t alpha, FxU32 depth ) { WriteLog(M64MSG_VERBOSE, "grBufferClear(%d,%d,%d)\r\n", color, alpha, depth); switch(lfb_color_fmt) { case GR_COLORFORMAT_ARGB: glClearColor(((color >> 16) & 0xFF) / 255.0f, ((color >> 8) & 0xFF) / 255.0f, ( color & 0xFF) / 255.0f, alpha / 255.0f); break; case GR_COLORFORMAT_RGBA: glClearColor(((color >> 24) & 0xFF) / 255.0f, ((color >> 16) & 0xFF) / 255.0f, (color & 0xFF) / 255.0f, alpha / 255.0f); break; default: display_warning("grBufferClear: unknown color format : %x", lfb_color_fmt); } if (w_buffer_mode) glClearDepth(1.0f - ((1.0f + (depth >> 4) / 4096.0f) * (1 << (depth & 0xF))) / 65528.0); else glClearDepth(depth / 65535.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // ZIGGY TODO check that color mask is on buffer_cleared = TRUE; } extern void (*renderCallback)(int); // #include FX_ENTRY void FX_CALL grBufferSwap( FxU32 swap_interval ) { if(renderCallback) (*renderCallback)(drawFlag); drawFlag = 1; //TODO: set drawFlag to 0 here //TODO: need to find the proper place to set drawFlag to 1 when a frame has been rendered int i; WriteLog(M64MSG_VERBOSE, "grBufferSwap(%d)\r\n", swap_interval); //printf("swap\n"); if (render_to_texture) { display_warning("swap while render_to_texture\n"); return; } CoreVideo_GL_SwapBuffers(); for (i = 0; i < nb_fb; i++) fbs[i].buff_clear = 1; // VP debugging #ifdef VPDEBUG dump_stop(); SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_KEYDOWN: switch (event.key.keysym.sym) { case 'd': printf("Dumping !\n"); dump_start(); break; case 'w': { static int wireframe; wireframe = !wireframe; glPolygonMode(GL_FRONT_AND_BACK, wireframe? GL_LINE : GL_FILL); break; default: break; } } break; } } #endif } // frame buffer FX_ENTRY FxBool FX_CALL grLfbLock( GrLock_t type, GrBuffer_t buffer, GrLfbWriteMode_t writeMode, GrOriginLocation_t origin, FxBool pixelPipeline, GrLfbInfo_t *info ) { WriteLog(M64MSG_VERBOSE, "grLfbLock(%d,%d,%d,%d,%d)\r\n", type, buffer, writeMode, origin, pixelPipeline); if (type == GR_LFB_WRITE_ONLY) { display_warning("grLfbLock : write only"); } else { unsigned char *buf; int i,j; switch(buffer) { case GR_BUFFER_FRONTBUFFER: glReadBuffer(GL_FRONT); break; case GR_BUFFER_BACKBUFFER: glReadBuffer(GL_BACK); break; /*case GR_BUFFER_AUXBUFFER: glReadBuffer(current_buffer); break;*/ default: display_warning("grLfbLock : unknown buffer : %x", buffer); } if(buffer != GR_BUFFER_AUXBUFFER) { if (writeMode == GR_LFBWRITEMODE_888) { info->lfbPtr = frameBuffer; info->strideInBytes = width*4; info->writeMode = GR_LFBWRITEMODE_888; info->origin = origin; glReadPixels(0, viewport_offset, width, height, GL_BGRA, GL_UNSIGNED_BYTE, frameBuffer); } else { buf = (unsigned char*)malloc(width*height*4); info->lfbPtr = frameBuffer; info->strideInBytes = width*2; info->writeMode = GR_LFBWRITEMODE_565; info->origin = origin; glReadPixels(0, viewport_offset, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buf); for (j=0; j> 3) << 11) | ((buf[j*width*4+i*4+1] >> 2) << 5) | (buf[j*width*4+i*4+2] >> 3); } } //adler32b = adler32(0, (const unsigned char*)frameBuffer, width*height*2); free(buf); } } else { info->lfbPtr = depthBuffer; info->strideInBytes = width*2; info->writeMode = GR_LFBWRITEMODE_ZA16; info->origin = origin; glReadPixels(0, viewport_offset, width, height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, depthBuffer); } } return FXTRUE; } FX_ENTRY FxBool FX_CALL grLfbUnlock( GrLock_t type, GrBuffer_t buffer ) { WriteLog(M64MSG_VERBOSE, "grLfbUnlock(%d,%d)\r\n", type, buffer); if (type == GR_LFB_WRITE_ONLY) { display_warning("grLfbUnlock : write only"); } return FXTRUE; } FX_ENTRY FxBool FX_CALL grLfbReadRegion( GrBuffer_t src_buffer, FxU32 src_x, FxU32 src_y, FxU32 src_width, FxU32 src_height, FxU32 dst_stride, void *dst_data ) { unsigned char *buf; unsigned int i,j; unsigned short *frameBuffer = (unsigned short*)dst_data; unsigned short *depthBuffer = (unsigned short*)dst_data; WriteLog(M64MSG_VERBOSE, "grLfbReadRegion(%d,%d,%d,%d,%d,%d)\r\n", src_buffer, src_x, src_y, src_width, src_height, dst_stride); switch(src_buffer) { case GR_BUFFER_FRONTBUFFER: glReadBuffer(GL_FRONT); break; case GR_BUFFER_BACKBUFFER: glReadBuffer(GL_BACK); break; /*case GR_BUFFER_AUXBUFFER: glReadBuffer(current_buffer); break;*/ default: display_warning("grReadRegion : unknown buffer : %x", src_buffer); } if(src_buffer != GR_BUFFER_AUXBUFFER) { buf = (unsigned char*)malloc(src_width*src_height*4); glReadPixels(src_x, (viewport_offset)+height-src_y-src_height, src_width, src_height, GL_RGBA, GL_UNSIGNED_BYTE, buf); for (j=0; j> 3) << 11) | ((buf[(src_height-j-1)*src_width*4+i*4+1] >> 2) << 5) | (buf[(src_height-j-1)*src_width*4+i*4+2] >> 3); } } free(buf); } else { buf = (unsigned char*)malloc(src_width*src_height*2); glReadPixels(src_x, (viewport_offset)+height-src_y-src_height, src_width, src_height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, depthBuffer); for (j=0;j>10)&0x1F)<<3; buf[j*tex_width*4+i*4+1]=((frameBuffer[j*(src_stride/2)+i]>> 5)&0x1F)<<3; buf[j*tex_width*4+i*4+2]=((frameBuffer[j*(src_stride/2)+i]>> 0)&0x1F)<<3; buf[j*tex_width*4+i*4+3]=(frameBuffer[j*(src_stride/2)+i]>>15)?0xFF:0; } } break; case GR_LFBWRITEMODE_555: for (j=0; j>10)&0x1F)<<3; buf[j*tex_width*4+i*4+1]=((frameBuffer[j*(src_stride/2)+i]>> 5)&0x1F)<<3; buf[j*tex_width*4+i*4+2]=((frameBuffer[j*(src_stride/2)+i]>> 0)&0x1F)<<3; buf[j*tex_width*4+i*4+3]=0xFF; } } break; default: display_warning("grLfbWriteRegion : unknown format : %d", src_format); } #ifdef VPDEBUG if (dumping) { ilTexImage(tex_width, tex_height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, buf); char name[128]; static int id; sprintf(name, "dump/writecolor%d.png", id++); ilSaveImage(name); printf("dumped gdLfbWriteRegion %s\n", name); } #endif glBindTexture(GL_TEXTURE_2D, default_texture); glTexImage2D(GL_TEXTURE_2D, 0, 4, tex_width, tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); free(buf); set_copy_shader(); glDisable(GL_DEPTH_TEST); glDisable(GL_BLEND); render_rectangle(texture_number, dst_x, dst_y, src_width, src_height, tex_width, tex_height, +1); } else { float *buf = (float*)malloc(src_width*(src_height+(viewport_offset))*sizeof(float)); if (src_format != GR_LFBWRITEMODE_ZA16) display_warning("unknown depth buffer write format:%x", src_format); if(dst_x || dst_y) display_warning("dst_x:%d, dst_y:%d\n",dst_x, dst_y); for (j=0; jresolution != GR_QUERY_ANY) { res_inf = res_sup = resTemplate->resolution; } if ((unsigned int)resTemplate->refresh == GR_QUERY_ANY) display_warning("querying any refresh rate"); if ((unsigned int)resTemplate->numAuxBuffers == GR_QUERY_ANY) display_warning("querying any numAuxBuffers"); if ((unsigned int)resTemplate->numColorBuffers == GR_QUERY_ANY) display_warning("querying any numColorBuffers"); if (output == NULL) return res_sup - res_inf + 1; for (i=res_inf; i<=res_sup; i++) { output[n].resolution = i; output[n].refresh = resTemplate->refresh; output[n].numAuxBuffers = resTemplate->numAuxBuffers; output[n].numColorBuffers = resTemplate->numColorBuffers; n++; } return res_sup - res_inf + 1; } FX_ENTRY FxBool FX_CALL grReset( FxU32 what ) { display_warning("grReset"); return 1; } FX_ENTRY void FX_CALL grEnable( GrEnableMode_t mode ) { display_warning("grEnable"); } FX_ENTRY void FX_CALL grDisable( GrEnableMode_t mode ) { display_warning("grDisable"); } FX_ENTRY void FX_CALL grDisableAllEffects( void ) { display_warning("grDisableAllEffects"); } FX_ENTRY void FX_CALL grErrorSetCallback( GrErrorCallbackFnc_t fnc ) { display_warning("grErrorSetCallback"); } FX_ENTRY void FX_CALL grFinish(void) { display_warning("grFinish"); } FX_ENTRY void FX_CALL grFlush(void) { display_warning("grFlush"); } FX_ENTRY void FX_CALL grTexMultibase( GrChipID_t tmu, FxBool enable ) { display_warning("grTexMultibase"); } FX_ENTRY void FX_CALL grTexMipMapMode( GrChipID_t tmu, GrMipMapMode_t mode, FxBool lodBlend ) { display_warning("grTexMipMapMode"); } FX_ENTRY void FX_CALL grTexDownloadTablePartial( GrTexTable_t type, void *data, int start, int end ) { display_warning("grTexDownloadTablePartial"); } FX_ENTRY void FX_CALL grTexDownloadTable( GrTexTable_t type, void *data ) { display_warning("grTexDownloadTable"); } FX_ENTRY FxBool FX_CALL grTexDownloadMipMapLevelPartial( GrChipID_t tmu, FxU32 startAddress, GrLOD_t thisLod, GrLOD_t largeLod, GrAspectRatio_t aspectRatio, GrTextureFormat_t format, FxU32 evenOdd, void *data, int start, int end ) { display_warning("grTexDownloadMipMapLevelPartial"); return 1; } FX_ENTRY void FX_CALL grTexDownloadMipMapLevel( GrChipID_t tmu, FxU32 startAddress, GrLOD_t thisLod, GrLOD_t largeLod, GrAspectRatio_t aspectRatio, GrTextureFormat_t format, FxU32 evenOdd, void *data ) { display_warning("grTexDownloadMipMapLevel"); } FX_ENTRY void FX_CALL grTexNCCTable( GrNCCTable_t table ) { display_warning("grTexNCCTable"); } FX_ENTRY void FX_CALL grViewport( FxI32 x, FxI32 y, FxI32 width, FxI32 height ) { display_warning("grViewport"); } FX_ENTRY void FX_CALL grDepthRange( FxFloat n, FxFloat f ) { display_warning("grDepthRange"); } FX_ENTRY void FX_CALL grSplash(float x, float y, float width, float height, FxU32 frame) { display_warning("grSplash"); } FX_ENTRY FxBool FX_CALL grSelectContext( GrContext_t context ) { display_warning("grSelectContext"); return 1; } FX_ENTRY void FX_CALL grAADrawTriangle( const void *a, const void *b, const void *c, FxBool ab_antialias, FxBool bc_antialias, FxBool ca_antialias ) { display_warning("grAADrawTriangle"); } FX_ENTRY void FX_CALL grAlphaControlsITRGBLighting( FxBool enable ) { display_warning("grAlphaControlsITRGBLighting"); } FX_ENTRY void FX_CALL grGlideSetVertexLayout( const void *layout ) { display_warning("grGlideSetVertexLayout"); } FX_ENTRY void FX_CALL grGlideGetVertexLayout( void *layout ) { display_warning("grGlideGetVertexLayout"); } FX_ENTRY void FX_CALL grGlideSetState( const void *state ) { display_warning("grGlideSetState"); } FX_ENTRY void FX_CALL grGlideGetState( void *state ) { display_warning("grGlideGetState"); } FX_ENTRY void FX_CALL grLfbWriteColorFormat(GrColorFormat_t colorFormat) { display_warning("grLfbWriteColorFormat"); } FX_ENTRY void FX_CALL grLfbWriteColorSwizzle(FxBool swizzleBytes, FxBool swapWords) { display_warning("grLfbWriteColorSwizzle"); } FX_ENTRY void FX_CALL grLfbConstantDepth( FxU32 depth ) { display_warning("grLfbConstantDepth"); } FX_ENTRY void FX_CALL grLfbConstantAlpha( GrAlpha_t alpha ) { display_warning("grLfbConstantAlpha"); } FX_ENTRY void FX_CALL grTexMultibaseAddress( GrChipID_t tmu, GrTexBaseRange_t range, FxU32 startAddress, FxU32 evenOdd, GrTexInfo *info ) { display_warning("grTexMultibaseAddress"); } FX_ENTRY void FX_CALL grLoadGammaTable( FxU32 nentries, FxU32 *red, FxU32 *green, FxU32 *blue) { display_warning("grLoadGammaTable"); } FX_ENTRY void FX_CALL grDitherMode( GrDitherMode_t mode ) { display_warning("grDitherMode"); } void grChromaRangeExt(GrColor_t color0, GrColor_t color1, FxU32 mode) { display_warning("grChromaRangeExt"); } void grChromaRangeModeExt(GrChromakeyMode_t mode) { display_warning("grChromaRangeModeExt"); } void grTexChromaRangeExt(GrChipID_t tmu, GrColor_t color0, GrColor_t color1, GrTexChromakeyMode_t mode) { display_warning("grTexChromaRangeExt"); } void grTexChromaModeExt(GrChipID_t tmu, GrChromakeyMode_t mode) { display_warning("grTexChromaRangeModeExt"); } // VP debug int dumping; #ifdef VPDEBUG static int tl_i; static int tl[10240]; void dump_start() { static int init; if (!init) { init = 1; ilInit(); ilEnable(IL_FILE_OVERWRITE); } dumping = 1; tl_i = 0; } void dump_stop() { if (!dumping) return; int i, j; for (i=0; i>8; frameByte[(i+j*width)*3+2] = c&0xff; } } ilTexImage(width, height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, frameBuffer); ilSaveImage("dump/framedepth.png"); for (i=0; i extern PFNGLACTIVETEXTUREARBPROC glActiveTextureARB; extern PFNGLATTACHOBJECTARBPROC glAttachObjectARB; extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT; extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; extern PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT; extern PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT; extern PFNGLCOMPILESHADERARBPROC glCompileShaderARB; extern PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB; extern PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB; extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT; extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT; extern PFNGLFOGCOORDFEXTPROC glFogCoordfEXT; extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT; extern PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT; extern PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT; extern PFNGLGETINFOLOGARBPROC glGetInfoLogARB; extern PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB; extern PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB; extern PFNGLLINKPROGRAMARBPROC glLinkProgramARB; extern PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB; extern PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT; extern PFNGLSECONDARYCOLOR3FPROC glSecondaryColor3f; extern PFNGLSHADERSOURCEARBPROC glShaderSourceARB; extern PFNGLUNIFORM1FARBPROC glUniform1fARB; extern PFNGLUNIFORM1IARBPROC glUniform1iARB; extern PFNGLUNIFORM4FARBPROC glUniform4fARB; extern PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB; #else #define GL_GLEXT_PROTOTYPES #include #endif #include "../winlnxdefs.h" #ifdef VPDEBUG void dump_tex(int id); void dump_start(); void dump_stop(); extern int dumping; #endif // VP z precision fix // no more necessary, now using z clamping instead. //#define zscale 0.025f #define zscale 1.0f //#define zscale 2.0f //#define zscale 0.5f // VP added this utility function // returns the bytes per pixel of a given GR texture format int grTexFormatSize(int fmt); extern int packed_pixels_support; extern int default_texture; // the infamous "32*1024*1024" is now configurable extern int depth_texture; void set_depth_shader(); void set_bw_shader(); extern float invtex[2]; extern int buffer_cleared; // mark that the buffer has been cleared, used to check if we need to reload the texture buffer content #include "glide.h" void display_warning(const unsigned char *text, ...); void display_warning(const char *text, ...); void init_geometry(); void init_textures(); void init_combiner(); void free_textures(); void updateCombiner(int i); void updateCombinera(int i); void remove_tex(unsigned int idmin, unsigned int idmax); void add_tex(unsigned int id); extern int w_buffer_mode; extern GLint nbTextureUnits; extern int width, height, widtho, heighto; extern int tex0_width, tex0_height, tex1_width, tex1_height; extern float texture_env_color[4]; extern int fog_enabled; extern float lambda; extern int need_lambda[2]; extern float lambda_color[2][4]; extern int inverted_culling; extern int culling_mode; extern int render_to_texture; extern int lfb_color_fmt; extern int need_to_compile; extern int blackandwhite0; extern int blackandwhite1; extern int blend_func_separate_support; extern int fog_coord_support; //extern int pbuffer_support; extern int glsl_support; extern unsigned int pBufferAddress; extern int viewport_width, viewport_height, viewport_offset; void grChromaRangeExt(GrColor_t color0, GrColor_t color1, FxU32 mode); void grChromaRangeModeExt(GrChromakeyMode_t mode); void grTexChromaRangeExt(GrChipID_t tmu, GrColor_t color0, GrColor_t color1, GrTexChromakeyMode_t mode); void grTexChromaModeExt(GrChipID_t tmu, GrChromakeyMode_t mode); void updateTexture(); void reloadTexture(); void free_combiners(); void compile_shader(); void set_lambda(); void set_copy_shader(); // config functions FX_ENTRY void FX_CALL grConfigWrapperExt(HINSTANCE instance, HWND hwnd); FX_ENTRY GrScreenResolution_t FX_CALL grWrapperFullScreenResolutionExt(void); int getFullScreenWidth(); int getFullScreenHeight(); int getFilter(); int getDisableGLSL(); // ZIGGY framebuffer copy extension // allow to copy the depth or color buffer from back/front to front/back #define GR_FBCOPY_MODE_DEPTH 0 #define GR_FBCOPY_MODE_COLOR 1 #define GR_FBCOPY_BUFFER_BACK 0 #define GR_FBCOPY_BUFFER_FRONT 1 FX_ENTRY void FX_CALL grFramebufferCopyExt(int x, int y, int w, int h, int buffer_from, int buffer_to, int mode); // COMBINE extension typedef FxU32 GrCCUColor_t; typedef FxU32 GrACUColor_t; typedef FxU32 GrTCCUColor_t; typedef FxU32 GrTACUColor_t; typedef FxU32 GrCombineMode_t; #define GR_FUNC_MODE_ZERO 0x00 #define GR_FUNC_MODE_X 0x01 #define GR_FUNC_MODE_ONE_MINUS_X 0x02 #define GR_FUNC_MODE_NEGATIVE_X 0x03 #define GR_FUNC_MODE_X_MINUS_HALF 0x04 #define GR_CMBX_ZERO 0x00 #define GR_CMBX_TEXTURE_ALPHA 0x01 #define GR_CMBX_ALOCAL 0x02 #define GR_CMBX_AOTHER 0x03 #define GR_CMBX_B 0x04 #define GR_CMBX_CONSTANT_ALPHA 0x05 #define GR_CMBX_CONSTANT_COLOR 0x06 #define GR_CMBX_DETAIL_FACTOR 0x07 #define GR_CMBX_ITALPHA 0x08 #define GR_CMBX_ITRGB 0x09 #define GR_CMBX_LOCAL_TEXTURE_ALPHA 0x0a #define GR_CMBX_LOCAL_TEXTURE_RGB 0x0b #define GR_CMBX_LOD_FRAC 0x0c #define GR_CMBX_OTHER_TEXTURE_ALPHA 0x0d #define GR_CMBX_OTHER_TEXTURE_RGB 0x0e #define GR_CMBX_TEXTURE_RGB 0x0f #define GR_CMBX_TMU_CALPHA 0x10 #define GR_CMBX_TMU_CCOLOR 0x11 FX_ENTRY void FX_CALL grColorCombineExt(GrCCUColor_t a, GrCombineMode_t a_mode, GrCCUColor_t b, GrCombineMode_t b_mode, GrCCUColor_t c, FxBool c_invert, GrCCUColor_t d, FxBool d_invert, FxU32 shift, FxBool invert); FX_ENTRY void FX_CALL grAlphaCombineExt(GrACUColor_t a, GrCombineMode_t a_mode, GrACUColor_t b, GrCombineMode_t b_mode, GrACUColor_t c, FxBool c_invert, GrACUColor_t d, FxBool d_invert, FxU32 shift, FxBool invert); FX_ENTRY void FX_CALL grTexColorCombineExt(GrChipID_t tmu, GrTCCUColor_t a, GrCombineMode_t a_mode, GrTCCUColor_t b, GrCombineMode_t b_mode, GrTCCUColor_t c, FxBool c_invert, GrTCCUColor_t d, FxBool d_invert, FxU32 shift, FxBool invert); FX_ENTRY void FX_CALL grTexAlphaCombineExt(GrChipID_t tmu, GrTACUColor_t a, GrCombineMode_t a_mode, GrTACUColor_t b, GrCombineMode_t b_mode, GrTACUColor_t c, FxBool c_invert, GrTACUColor_t d, FxBool d_invert, FxU32 shift, FxBool invert); FX_ENTRY void FX_CALL grConstantColorValueExt(GrChipID_t tmu, GrColor_t value); #ifndef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT #define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT 0x8CD8 #endif #define CHECK_FRAMEBUFFER_STATUS() \ {\ GLenum status; \ status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); \ /*display_warning("%x\n", status);*/\ switch(status) { \ case GL_FRAMEBUFFER_COMPLETE_EXT: \ /*display_warning("framebuffer complete!\n");*/\ break; \ case GL_FRAMEBUFFER_UNSUPPORTED_EXT: \ display_warning("framebuffer GL_FRAMEBUFFER_UNSUPPORTED_EXT\n");\ /* you gotta choose different formats */ \ /*assert(0);*/ \ break; \ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: \ display_warning("framebuffer INCOMPLETE_ATTACHMENT\n");\ break; \ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: \ display_warning("framebuffer FRAMEBUFFER_MISSING_ATTACHMENT\n");\ break; \ case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: \ display_warning("framebuffer FRAMEBUFFER_DIMENSIONS\n");\ break; \ case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT: \ display_warning("framebuffer INCOMPLETE_DUPLICATE_ATTACHMENT\n");\ break; \ case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: \ display_warning("framebuffer INCOMPLETE_FORMATS\n");\ break; \ case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: \ display_warning("framebuffer INCOMPLETE_DRAW_BUFFER\n");\ break; \ case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: \ display_warning("framebuffer INCOMPLETE_READ_BUFFER\n");\ break; \ case GL_FRAMEBUFFER_BINDING_EXT: \ display_warning("framebuffer BINDING_EXT\n");\ break; \ default: \ break; \ /* programming error; will fail on all hardware */ \ /*assert(0);*/ \ }\ } #ifdef VPDEBUG #define LOGGING #endif #ifdef LOGGING void OPEN_LOG(); void CLOSE_LOG(); void LOG(char *text, ...); #else // LOGGING #define OPEN_LOG() #define CLOSE_LOG() //#define LOG(...) #endif // LOGGING #endif mupen64plus-video-glide64-src-2.6.0/src/wrapper/sst1vid.h000066400000000000000000000117751464507525600231140ustar00rootroot00000000000000/* ** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY ** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT ** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX ** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE ** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com). ** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER ** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A ** FULL TEXT OF THE NON-WARRANTY PROVISIONS. ** ** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO ** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN ** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, ** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR ** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF ** THE UNITED STATES. ** ** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED ** ** $Header: /cvsroot/glide/glide3x/h5/incsrc/sst1vid.h,v 1.3.4.1 2003/04/06 18:23:10 koolsmoky Exp $ ** $Log: ** 7 3dfx 1.4.1.0.1.0 10/11/00 Brent Forced check in to enforce ** branching. ** 6 3dfx 1.4.1.0 06/20/00 Joseph Kain Changes to support the ** Napalm Glide open source release. Changes include cleaned up offensive ** comments and new legal headers. ** 5 3dfx 1.4 12/10/99 Leo Galway Removed previous hi-res ** mode information for Glide3. These modes were only necessary for ** Cornerstone (or future hi-res) support in RT4.2 source branch and ** proceeded to break the V3 and V2 builds (from 3dfx view), hence they have ** been removed. ** 4 3dfx 1.3 12/08/99 Leo Galway Added mode information for ** 1600x1280, 1792x1440, 1920x1080, 1920x1200, 2046x1536 (as a result of ** glide being tested with Cornerstone modes). Although not all of these ** modes are currently capable under Glide, their inclusion prevents Glide ** apps from displaying in incorrect modes when these hi-res modes are ** selected. Search for SUSTAINED_ENGINEERING_CHANGE_BEGIN. ** 3 3dfx 1.2 09/17/99 Jeremy Zelsnack ** 2 3dfx 1.1 09/17/99 Jeremy Zelsnack ** 1 3dfx 1.0 09/11/99 StarTeam VTS Administrator ** $ ** ** 8 3/04/99 1:19p Atai ** sync new res modes ** ** 10 2/27/99 12:28p Dow ** new resolutions ** ** 6 2/13/99 1:56p Dow ** Added new resolution constants ** ** 5 7/24/98 1:38p Hohn * * 4 9/09/97 7:35p Sellers * Added 400x300 resolution * * 3 8/24/97 9:31a Sellers * moved new video timing to sst1vid.h * redefined 1600x1280 to be 1600x1200 * * 2 6/05/97 11:14p Pgj * * 5 7/24/96 3:43p Sellers * added 512x384 @ 60 Hz for arcade monitors * added 512x256 @ 60 Hz for arcade monitors * * 4 7/18/96 10:58a Sellers * fixed FT and TF clock delay values for lower frequencies with * .5/.5 combos * * 3 6/18/96 6:54p Sellers * added sst1InitShutdownSli() to fix Glide Splash screen problems with * SLI * * 2 6/13/96 7:45p Sellers * added "voodoo.ini" support * added DirectX support * misc cleanup * * 2 6/11/96 1:43p Sellers * added support for 60, 75, 85, and 120 Hz refresh rates for "most" * resolutions * * 1 5/08/96 5:43p Paik * Video definitions */ #ifndef __SST1VID_H__ #define __SST1VID_H__ #ifdef __cplusplus extern "C" { #endif /* Video defines */ typedef FxI32 GrScreenRefresh_t; #define GR_REFRESH_60Hz 0x0 #define GR_REFRESH_70Hz 0x1 #define GR_REFRESH_72Hz 0x2 #define GR_REFRESH_75Hz 0x3 #define GR_REFRESH_80Hz 0x4 #define GR_REFRESH_90Hz 0x5 #define GR_REFRESH_100Hz 0x6 #define GR_REFRESH_85Hz 0x7 #define GR_REFRESH_120Hz 0x8 #define GR_REFRESH_NONE 0xff typedef FxI32 GrScreenResolution_t; #define GR_RESOLUTION_320x200 0x0 #define GR_RESOLUTION_320x240 0x1 #define GR_RESOLUTION_400x256 0x2 #define GR_RESOLUTION_512x384 0x3 #define GR_RESOLUTION_640x200 0x4 #define GR_RESOLUTION_640x350 0x5 #define GR_RESOLUTION_640x400 0x6 #define GR_RESOLUTION_640x480 0x7 #define GR_RESOLUTION_800x600 0x8 #define GR_RESOLUTION_960x720 0x9 #define GR_RESOLUTION_856x480 0xa #define GR_RESOLUTION_512x256 0xb #define GR_RESOLUTION_1024x768 0xC #define GR_RESOLUTION_1280x1024 0xD #define GR_RESOLUTION_1600x1200 0xE #define GR_RESOLUTION_400x300 0xF #define GR_RESOLUTION_1152x864 0x10 #define GR_RESOLUTION_1280x960 0x11 #define GR_RESOLUTION_1600x1024 0x12 #define GR_RESOLUTION_1792x1344 0x13 #define GR_RESOLUTION_1856x1392 0x14 #define GR_RESOLUTION_1920x1440 0x15 #define GR_RESOLUTION_2048x1536 0x16 #define GR_RESOLUTION_2048x2048 0x17 #define GR_RESOLUTION_NONE 0xff #ifdef GR_RESOLUTION_MAX #undef GR_RESOLUTION_MAX #endif #ifdef GR_RESOLUTION_MIN #undef GR_RESOLUTION_MIN #endif #define GR_RESOLUTION_MIN GR_RESOLUTION_320x200 #define GR_RESOLUTION_MAX GR_RESOLUTION_2048x2048 #ifdef __cplusplus } #endif #endif /* __SST1VID_H__ */ mupen64plus-video-glide64-src-2.6.0/src/wrapper/textures.cpp000066400000000000000000000634641464507525600237370ustar00rootroot00000000000000/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Mupen64plus - glide64/wrapper/textures.cpp * * Mupen64Plus homepage: https://mupen64plus.org/ * * Copyright (C) 2005-2006 Hacktarux * * * * 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 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include "glide.h" #include "main.h" extern BOOL isExtensionSupported(const char *extension); // defined in main.cpp /* Napalm extensions to GrTextureFormat_t */ #define GR_TEXFMT_ARGB_CMP_FXT1 0x11 #define GR_TEXFMT_ARGB_8888 0x12 #define GR_TEXFMT_YUYV_422 0x13 #define GR_TEXFMT_UYVY_422 0x14 #define GR_TEXFMT_AYUV_444 0x15 #define GR_TEXFMT_ARGB_CMP_DXT1 0x16 #define GR_TEXFMT_ARGB_CMP_DXT2 0x17 #define GR_TEXFMT_ARGB_CMP_DXT3 0x18 #define GR_TEXFMT_ARGB_CMP_DXT4 0x19 #define GR_TEXFMT_ARGB_CMP_DXT5 0x1A #define GR_TEXTFMT_RGB_888 0xFF #define TMU_SIZE 8*2048*2048 int tex0_width, tex0_height, tex1_width, tex1_height; float lambda; static int min_filter0, mag_filter0, wrap_s0, wrap_t0; static int min_filter1, mag_filter1, wrap_s1, wrap_t1; unsigned char *filter(unsigned char *source, int width, int height, int *width2, int *height2); typedef struct _texlist { unsigned int id; struct _texlist *next; } texlist; static int nbTex = 0; static texlist *list = NULL; void remove_tex(unsigned int idmin, unsigned int idmax) { GLuint *t; int n = 0; texlist *aux = list; int sz = nbTex; if (aux == NULL) return; t = (GLuint*)malloc(sz * sizeof(int)); while (aux && aux->id >= idmin && aux->id < idmax) { if (n >= sz) t = (GLuint*)realloc(t, ++sz*sizeof(int)); t[n++] = aux->id; aux = aux->next; free(list); list = aux; nbTex--; } while (aux != NULL && aux->next != NULL) { if (aux->next->id >= idmin && aux->next->id < idmax) { texlist *aux2 = aux->next->next; if (n >= sz) t = (GLuint*)realloc(t, ++sz*sizeof(int)); t[n++] = aux->next->id; free(aux->next); aux->next = aux2; nbTex--; } aux = aux->next; } glDeleteTextures(n, t); free(t); //printf("RMVTEX nbtex is now %d (%06x - %06x)\n", nbTex, idmin, idmax); } // void remove_all_tex() // { // texlist *aux = list; // int sz = nbTex; // if (aux == NULL) return; // FILE * fp = fopen("toto.txt", "w"); // while (aux) // { // fprintf(fp, "%x\n", aux->id); // fflush(fp); // glDeleteTextures(1, &aux->id); // fprintf(fp, "%x %x\n", aux, aux->next); // fflush(fp); // aux = aux->next; // free(list); // fprintf(fp, "plop\n"); // fflush(fp); // list = aux; // nbTex--; // } // fclose(fp); // } void add_tex(unsigned int id) { texlist *aux = list; texlist *aux2; //printf("ADDTEX nbtex is now %d (%06x)\n", nbTex, id); if (list == NULL || id < list->id) { nbTex++; list = (texlist*)malloc(sizeof(texlist)); list->next = aux; list->id = id; return; } while (aux->next != NULL && aux->next->id < id) aux = aux->next; // ZIGGY added this test so that add_tex now accept re-adding an existing texture if (aux->next != NULL && aux->next->id == id) return; nbTex++; aux2 = aux->next; aux->next = (texlist*)malloc(sizeof(texlist)); aux->next->id = id; aux->next->next = aux2; } void init_textures() { tex0_width = tex0_height = tex1_width = tex1_height = 2; // ZIGGY because free_textures isn't called (Pj64 doesn't like it), it's better // to leave these so that they'll be reused (otherwise we have a memory leak) // list = NULL; // nbTex = 0; } void free_textures() { remove_tex(0x00000000, 0xFFFFFFFF); } FX_ENTRY FxU32 FX_CALL grTexMinAddress( GrChipID_t tmu ) { WriteLog(M64MSG_VERBOSE, "grTexMinAddress(%d)\r\n", tmu); return tmu*TMU_SIZE; } FX_ENTRY FxU32 FX_CALL grTexMaxAddress( GrChipID_t tmu ) { WriteLog(M64MSG_VERBOSE, "grTexMaxAddress(%d)\r\n", tmu); return tmu*TMU_SIZE + TMU_SIZE - 1; } FX_ENTRY FxU32 FX_CALL grTexTextureMemRequired( FxU32 evenOdd, GrTexInfo *info ) { int width, height; WriteLog(M64MSG_VERBOSE, "grTextureMemRequired(%d)\r\n", evenOdd); if (info->largeLodLog2 != info->smallLodLog2) display_warning("grTexTextureMemRequired : loading more than one LOD"); if (info->aspectRatioLog2 < 0) { height = 1 << info->largeLodLog2; width = height >> -info->aspectRatioLog2; } else { width = 1 << info->largeLodLog2; height = width >> info->aspectRatioLog2; } switch(info->format) { case GR_TEXFMT_ALPHA_8: case GR_TEXFMT_ALPHA_INTENSITY_44: return width*height; break; case GR_TEXFMT_ARGB_1555: case GR_TEXFMT_ARGB_4444: case GR_TEXFMT_ALPHA_INTENSITY_88: case GR_TEXFMT_RGB_565: return width*height*2; break; case GR_TEXFMT_ARGB_8888: return width*height*4; break; default: display_warning("grTexTextureMemRequired : unknown texture format: %x", info->format); } return 0; } FX_ENTRY FxU32 FX_CALL grTexCalcMemRequired( GrLOD_t lodmin, GrLOD_t lodmax, GrAspectRatio_t aspect, GrTextureFormat_t fmt) { int width, height; WriteLog(M64MSG_VERBOSE, "grTexCalcMemRequired(%d, %d, %d, %d)\r\n", lodmin, lodmax, aspect, fmt); if (lodmax != lodmin) display_warning("grTexCalcMemRequired : loading more than one LOD"); if (aspect < 0) { height = 1 << lodmax; width = height >> -aspect; } else { width = 1 << lodmax; height = width >> aspect; } switch(fmt) { case GR_TEXFMT_ALPHA_8: case GR_TEXFMT_ALPHA_INTENSITY_44: return width*height; break; case GR_TEXFMT_ARGB_1555: case GR_TEXFMT_ARGB_4444: case GR_TEXFMT_ALPHA_INTENSITY_88: case GR_TEXFMT_RGB_565: return width*height*2; break; case GR_TEXFMT_ARGB_8888: return width*height*4; break; default: display_warning("grTexTextureMemRequired : unknown texture format: %x", fmt); } return 0; } int grTexFormatSize(int fmt) { int factor = -1; switch(fmt) { case GR_TEXFMT_ALPHA_8: factor = 1; break; case GR_TEXFMT_ALPHA_INTENSITY_44: factor = 1; break; case GR_TEXFMT_RGB_565: factor = 2; break; case GR_TEXFMT_ARGB_1555: factor = 2; break; case GR_TEXFMT_ALPHA_INTENSITY_88: factor = 2; break; case GR_TEXFMT_ARGB_4444: factor = 2; break; case GR_TEXFMT_ARGB_8888: factor = 4; break; default: display_warning("grTexFormatSize : unknown texture format: %x", fmt); } return factor; } int packed_pixels_support = -1; int grTexFormat2GLPackedFmt(int fmt, int * gltexfmt, int * glpixfmt, int * glpackfmt) { int factor = -1; switch(fmt) { case GR_TEXFMT_ALPHA_8: factor = 1; *gltexfmt = GL_INTENSITY; *glpixfmt = GL_LUMINANCE; *glpackfmt = GL_UNSIGNED_BYTE; break; case GR_TEXFMT_ALPHA_INTENSITY_44: return -1; // factor = 1; // gltexfmt = GL_LUMINANCE4_ALPHA4; // glpixfmt = GL_LUMINANCE_ALPHA; // glpackfmt = GL_UNSIGNED_BYTE; break; case GR_TEXFMT_RGB_565: // trick, this format is only used actually for depth texture // factor = 2; // *gltexfmt = GL_DEPTH_COMPONENT; // *glpixfmt = GL_DEPTH_COMPONENT; // *glpackfmt = GL_UNSIGNED_SHORT; // break; // return -1; factor = 2; *gltexfmt = GL_RGB; *glpixfmt = GL_RGB; *glpackfmt = GL_UNSIGNED_SHORT_5_6_5; break; case GR_TEXFMT_ARGB_1555: factor = 2; *gltexfmt = GL_RGBA; *glpixfmt = GL_BGRA; *glpackfmt = GL_UNSIGNED_SHORT_1_5_5_5_REV; break; case GR_TEXFMT_ALPHA_INTENSITY_88: factor = 2; *gltexfmt = GL_LUMINANCE_ALPHA; *glpixfmt = GL_LUMINANCE_ALPHA; *glpackfmt = GL_UNSIGNED_BYTE; break; case GR_TEXFMT_ARGB_4444: factor = 2; *gltexfmt = GL_RGBA; *glpixfmt = GL_BGRA; *glpackfmt = GL_UNSIGNED_SHORT_4_4_4_4_REV; break; case GR_TEXFMT_ARGB_8888: factor = 4; *gltexfmt = GL_RGBA; *glpixfmt = GL_BGRA; *glpackfmt = GL_UNSIGNED_INT_8_8_8_8_REV; break; default: display_warning("grTexFormat2GLPackedFmt : unknown texture format: %x", fmt); } return factor; } FX_ENTRY void FX_CALL grTexDownloadMipMap( GrChipID_t tmu, FxU32 startAddress, FxU32 evenOdd, GrTexInfo *info ) { int width, height, i, j; unsigned char* texture = NULL; unsigned char* filtered_texture = NULL; int factor; int glformat = GL_RGBA8; int gltexfmt, glpixfmt, glpackfmt; gltexfmt = glpixfmt = glpackfmt = 0; WriteLog(M64MSG_VERBOSE, "grTexDownloadMipMap(%d,%d,%d)\r\n", tmu, startAddress, evenOdd); if (info->largeLodLog2 != info->smallLodLog2) display_warning("grTexDownloadMipMap : loading more than one LOD"); if (info->aspectRatioLog2 < 0) { height = 1 << info->largeLodLog2; width = height >> -info->aspectRatioLog2; } else { width = 1 << info->largeLodLog2; height = width >> info->aspectRatioLog2; } if (packed_pixels_support < 0) { if (isExtensionSupported("GL_EXT_packed_pixels") == FALSE) packed_pixels_support = 0; else packed_pixels_support = 1; } if (!packed_pixels_support || getFilter()) factor = -1; else factor = grTexFormat2GLPackedFmt(info->format, &gltexfmt, &glpixfmt, &glpackfmt); if (factor < 0) { texture = (unsigned char*)malloc(width*height*4); // VP fixed the texture conversions to be more accurate, also swapped // the for i/j loops so that is is less likely to break the memory cache switch(info->format) { case GR_TEXFMT_ALPHA_8: for (i=0; idata)[i*width+j]; texture[i*width*4+j*4+1]= ((unsigned char*)info->data)[i*width+j]; texture[i*width*4+j*4+2]= ((unsigned char*)info->data)[i*width+j]; texture[i*width*4+j*4+3]= ((unsigned char*)info->data)[i*width+j]; } } factor = 1; glformat = GL_INTENSITY8; break; case GR_TEXFMT_ALPHA_INTENSITY_44: for (i=0; i FF and 0 --> 00 FxU32 a = ((unsigned char*)info->data)[i*width+j]&0xF0; a = a | (a>>4); texture[i*width*4+j*4+3]= a | (a>>4); a = ((unsigned char*)info->data)[i*width+j]&0x0F; a = a | (a<<4); texture[i*width*4+j*4+0]= a; texture[i*width*4+j*4+1]= a; texture[i*width*4+j*4+2]= a; } } factor = 1; glformat = GL_LUMINANCE4_ALPHA4; break; case GR_TEXFMT_RGB_565: for (i=0; idata)[i*width+j]>>11)&0x1F); texture[i*width*4+j*4+0]=(a<<3) | (a>>2); a = ((((unsigned short*)info->data)[i*width+j]>> 5)&0x3F); texture[i*width*4+j*4+1]=(a<<2) | (a>>4); a = ((((unsigned short*)info->data)[i*width+j]>> 0)&0x1F); texture[i*width*4+j*4+2]=(a<<3) | (a>>2); } } factor = 2; break; case GR_TEXFMT_ARGB_1555: for (i=0; idata)[i*width+j]>>15)!=0 ? 0xFF : 0; a = ((((unsigned short*)info->data)[i*width+j]>>10)&0x1F); texture[i*width*4+j*4+0]=(a<<3) | (a>>2); a = ((((unsigned short*)info->data)[i*width+j]>> 5)&0x1F); texture[i*width*4+j*4+1]=(a<<3) | (a>>2); a = ((((unsigned short*)info->data)[i*width+j]>> 0)&0x1F); texture[i*width*4+j*4+2]=(a<<3) | (a>>2); } } factor = 2; glformat = GL_RGB5_A1; break; case GR_TEXFMT_ALPHA_INTENSITY_88: for (i=0; idata)[i*width*2+j*2+1]; texture[i*width*4+j*4+0]= ((unsigned char*)info->data)[i*width*2+j*2]; texture[i*width*4+j*4+1]= ((unsigned char*)info->data)[i*width*2+j*2]; texture[i*width*4+j*4+2]= ((unsigned char*)info->data)[i*width*2+j*2]; } } factor = 2; glformat = GL_LUMINANCE8_ALPHA8; break; case GR_TEXFMT_ARGB_4444: for (i=0; i FF and 0 --> 00 FxU32 a = ((((unsigned short*)info->data)[i*width+j]>>12)); texture[i*width*4+j*4+3]=a | (a<<4); a = ((((unsigned short*)info->data)[i*width+j]>> 8)&0xF); texture[i*width*4+j*4+0]=a | (a<<4); a = ((((unsigned short*)info->data)[i*width+j]>> 4)&0xF); texture[i*width*4+j*4+1]=a | (a<<4); a = ((((unsigned short*)info->data)[i*width+j] )&0xF); texture[i*width*4+j*4+2]=a | (a<<4); } } factor = 2; glformat = GL_RGBA4; break; case GR_TEXFMT_ARGB_8888: for (i=0; idata)[i*width*4+j*4+3]; texture[i*width*4+j*4+0]= ((unsigned char*)info->data)[i*width*4+j*4+2]; texture[i*width*4+j*4+1]= ((unsigned char*)info->data)[i*width*4+j*4+1]; texture[i*width*4+j*4+2]= ((unsigned char*)info->data)[i*width*4+j*4+0]; } } factor = 4; glformat = GL_RGBA8; break; default: display_warning("grTexDownloadMipMap : unknown texture format: %x", info->format); factor = 0; } } if (nbTextureUnits <= 2) glActiveTextureARB(GL_TEXTURE1_ARB); else glActiveTextureARB(GL_TEXTURE2_ARB); remove_tex(startAddress+1, startAddress+1+width*height*factor); add_tex(startAddress+1); glBindTexture(GL_TEXTURE_2D, startAddress+1); if (texture != NULL) { if (getFilter() == 0) { glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture); } else { int width2, height2; filtered_texture = filter(texture, width, height, &width2, &height2); glTexImage2D(GL_TEXTURE_2D, 0, 4, width2, height2, 0, GL_RGBA, GL_UNSIGNED_BYTE, filtered_texture); } } else { glTexImage2D(GL_TEXTURE_2D, 0, gltexfmt, width, height, 0, glpixfmt, glpackfmt, info->data); // if (info->format == GR_TEXFMT_RGB_565) { // GLint ifmt; // glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &ifmt); // LOG("dltex (%06x) %3dx%3d format %x --> %x\n", startAddress, width, height, info->format, ifmt); // printf("dltex (%06x) %3dx%3d format %x --> %x\n", startAddress, width, height, info->format, ifmt); // } } glBindTexture(GL_TEXTURE_2D, default_texture); if (texture) free(texture); if (filtered_texture) free(filtered_texture); } int CheckTextureBufferFormat(GrChipID_t tmu, FxU32 startAddress, GrTexInfo *info ); FX_ENTRY void FX_CALL grTexSource( GrChipID_t tmu, FxU32 startAddress, FxU32 evenOdd, GrTexInfo *info ) { WriteLog(M64MSG_VERBOSE, "grTexSource(%d,%d,%d)\r\n", tmu, startAddress, evenOdd); //if ((startAddress+1) == pBufferAddress && render_to_texture) updateTexture(); //if ((startAddress+1) == pBufferAddress) display_warning("texsource"); if (tmu == GR_TMU1 || nbTextureUnits <= 2) { if (tmu == GR_TMU1 && nbTextureUnits <= 2) return; glActiveTextureARB(GL_TEXTURE0_ARB); if (info->aspectRatioLog2 < 0) { tex0_height = 256; tex0_width = tex0_height >> -info->aspectRatioLog2; } else { tex0_width = 256; tex0_height = tex0_width >> info->aspectRatioLog2; } glBindTexture(GL_TEXTURE_2D, startAddress+1); #ifdef VPDEBUG dump_tex(startAddress+1); #endif glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t0); if(!glsl_support) { if (need_lambda[0]) glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, lambda_color[0]); else glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, texture_env_color); updateCombiner(0); updateCombinera(0); } //printf("grTexSource %x %dx%d fmt %x\n", startAddress+1, tex0_width, tex0_height, info->format); } else { glActiveTextureARB(GL_TEXTURE1_ARB); if (info->aspectRatioLog2 < 0) { tex1_height = 256; tex1_width = tex1_height >> -info->aspectRatioLog2; } else { tex1_width = 256; tex1_height = tex1_width >> info->aspectRatioLog2; } glBindTexture(GL_TEXTURE_2D, startAddress+1); #ifdef VPDEBUG dump_tex(startAddress+1); #endif glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t1); if(!glsl_support) { if (need_lambda[1]) glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, lambda_color[1]); else glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, texture_env_color); updateCombiner(1); updateCombinera(1); } //printf("grTexSource %x %dx%d fmt %x\n", startAddress+1, tex1_width, tex1_height, info->format); } if(!CheckTextureBufferFormat(tmu, startAddress+1, info)) { if(tmu == 0 && blackandwhite1 != 0) { blackandwhite1 = 0; need_to_compile = 1; } if(tmu == 1 && blackandwhite0 != 0) { blackandwhite0 = 0; need_to_compile = 1; } } } FX_ENTRY void FX_CALL grTexDetailControl( GrChipID_t tmu, int lod_bias, FxU8 detail_scale, float detail_max ) { WriteLog(M64MSG_VERBOSE, "grTexDetailControl(%d,%d,%d,%f)\r\n", tmu, lod_bias, detail_scale, detail_max); if (lod_bias != 31 && detail_scale != 7) { if (!lod_bias && !detail_scale && !detail_max) return; else display_warning("grTexDetailControl : %d, %d, %f", lod_bias, detail_scale, detail_max); } lambda = detail_max; if(lambda > 1.0f) { lambda = 1.0f - (255.0f - lambda); } if(lambda > 1.0f) display_warning("lambda:%f", lambda); if(!glsl_support) { if (tmu == GR_TMU1 || nbTextureUnits <= 2) { if (tmu == GR_TMU1 && nbTextureUnits <= 2) return; if (need_lambda[0]) { int i; glActiveTextureARB(GL_TEXTURE0_ARB); for (i=0; i<3; i++) lambda_color[0][i] = texture_env_color[i]; lambda_color[0][3] = lambda; glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, lambda_color[0]); } } else { if (need_lambda[1]) { int i; glActiveTextureARB(GL_TEXTURE1_ARB); for (i=0; i<3; i++) lambda_color[1][i] = texture_env_color[i]; lambda_color[1][3] = lambda; glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, lambda_color[1]); } } } else set_lambda(); } FX_ENTRY void FX_CALL grTexLodBiasValue(GrChipID_t tmu, float bias ) { WriteLog(M64MSG_VERBOSE, "grTexLodBiasValue(%d,%f)\r\n", tmu, bias); /*if (bias != 0 && bias != 1.0f) display_warning("grTexLodBiasValue : %f", bias);*/ } FX_ENTRY void FX_CALL grTexFilterMode( GrChipID_t tmu, GrTextureFilterMode_t minfilter_mode, GrTextureFilterMode_t magfilter_mode ) { WriteLog(M64MSG_VERBOSE, "grTexFilterMode(%d,%d,%d)\r\n", tmu, minfilter_mode, magfilter_mode); if (tmu == GR_TMU1 || nbTextureUnits <= 2) { if (tmu == GR_TMU1 && nbTextureUnits <= 2) return; if (minfilter_mode == GR_TEXTUREFILTER_POINT_SAMPLED) min_filter0 = GL_NEAREST; else min_filter0 = GL_LINEAR; if (magfilter_mode == GR_TEXTUREFILTER_POINT_SAMPLED) mag_filter0 = GL_NEAREST; else mag_filter0 = GL_LINEAR; glActiveTextureARB(GL_TEXTURE0_ARB); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter0); } else { if (minfilter_mode == GR_TEXTUREFILTER_POINT_SAMPLED) min_filter1 = GL_NEAREST; else min_filter1 = GL_LINEAR; if (magfilter_mode == GR_TEXTUREFILTER_POINT_SAMPLED) mag_filter1 = GL_NEAREST; else mag_filter1 = GL_LINEAR; glActiveTextureARB(GL_TEXTURE1_ARB); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter1); } } FX_ENTRY void FX_CALL grTexClampMode( GrChipID_t tmu, GrTextureClampMode_t s_clampmode, GrTextureClampMode_t t_clampmode ) { WriteLog(M64MSG_VERBOSE, "grTexClampMode(%d, %d, %d)\r\n", tmu, s_clampmode, t_clampmode); if (tmu == GR_TMU1 || nbTextureUnits <= 2) { if (tmu == GR_TMU1 && nbTextureUnits <= 2) return; switch(s_clampmode) { case GR_TEXTURECLAMP_WRAP: wrap_s0 = GL_REPEAT; break; case GR_TEXTURECLAMP_CLAMP: wrap_s0 = GL_CLAMP_TO_EDGE; break; case GR_TEXTURECLAMP_MIRROR_EXT: wrap_s0 = GL_MIRRORED_REPEAT_ARB; break; default: display_warning("grTexClampMode : unknown s_clampmode : %x", s_clampmode); } switch(t_clampmode) { case GR_TEXTURECLAMP_WRAP: wrap_t0 = GL_REPEAT; break; case GR_TEXTURECLAMP_CLAMP: wrap_t0 = GL_CLAMP_TO_EDGE; break; case GR_TEXTURECLAMP_MIRROR_EXT: wrap_t0 = GL_MIRRORED_REPEAT_ARB; break; default: display_warning("grTexClampMode : unknown t_clampmode : %x", t_clampmode); } glActiveTextureARB(GL_TEXTURE0_ARB); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t0); } else { switch(s_clampmode) { case GR_TEXTURECLAMP_WRAP: wrap_s1 = GL_REPEAT; break; case GR_TEXTURECLAMP_CLAMP: wrap_s1 = GL_CLAMP_TO_EDGE; break; case GR_TEXTURECLAMP_MIRROR_EXT: wrap_s1 = GL_MIRRORED_REPEAT_ARB; break; default: display_warning("grTexClampMode : unknown s_clampmode : %x", s_clampmode); } switch(t_clampmode) { case GR_TEXTURECLAMP_WRAP: wrap_t1 = GL_REPEAT; break; case GR_TEXTURECLAMP_CLAMP: wrap_t1 = GL_CLAMP_TO_EDGE; break; case GR_TEXTURECLAMP_MIRROR_EXT: wrap_t1 = GL_MIRRORED_REPEAT_ARB; break; default: display_warning("grTexClampMode : unknown t_clampmode : %x", t_clampmode); } glActiveTextureARB(GL_TEXTURE1_ARB); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t1); } }