diff --git a/libmupen64plus/mupen64plus-video-glide64/COPYING b/libmupen64plus/mupen64plus-video-glide64/COPYING new file mode 100644 index 0000000000..d511905c16 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/COPYING @@ -0,0 +1,339 @@ + 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. diff --git a/libmupen64plus/mupen64plus-video-glide64/data/Glide64.ini b/libmupen64plus/mupen64plus-video-glide64/data/Glide64.ini new file mode 100644 index 0000000000..bc5061c191 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/data/Glide64.ini @@ -0,0 +1,2555 @@ +; 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 + diff --git a/libmupen64plus/mupen64plus-video-glide64/projects/msvc9/mupen64plus-video-glide64.sln b/libmupen64plus/mupen64plus-video-glide64/projects/msvc9/mupen64plus-video-glide64.sln new file mode 100644 index 0000000000..67e577b050 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/projects/msvc9/mupen64plus-video-glide64.sln @@ -0,0 +1,20 @@ + +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 diff --git a/libmupen64plus/mupen64plus-video-glide64/projects/msvc9/mupen64plus-video-glide64.vcproj b/libmupen64plus/mupen64plus-video-glide64/projects/msvc9/mupen64plus-video-glide64.vcproj new file mode 100644 index 0000000000..0eac54f238 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/projects/msvc9/mupen64plus-video-glide64.vcproj @@ -0,0 +1,453 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libmupen64plus/mupen64plus-video-glide64/projects/unix/Makefile b/libmupen64plus/mupen64plus-video-glide64/projects/unix/Makefile new file mode 100644 index 0000000000..a7c07f0eb0 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/projects/unix/Makefile @@ -0,0 +1,412 @@ +#/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +# * Mupen64plus-video-glide64 - Makefile * +# * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * +# * 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 + $(warning OS type "$(UNAME)" not officially supported.') +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 'http://code.google.com/p/mupen64plus/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 'http://code.google.com/p/mupen64plus/issues') +endif + +# base CFLAGS, LDLIBS, and LDFLAGS +OPTFLAGS ?= -O3 +WARNFLAGS ?= -Wall +CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -ffast-math -fno-strict-aliasing -fvisibility=hidden -I../../src -I../../src/wrapper -DGCC +CXXFLAGS += -fvisibility-inlines-hidden +LDFLAGS += $(SHARED) + +# default configuration programs +SDL_CONFIG = $(CROSS_COMPILE)sdl-config +PKG_CONFIG = $(CROSS_COMPILE)pkg-config + +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 + LDFLAGS += -fPIC +else + CFLAGS += -fno-PIC + LDFLAGS += -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 + CFLAGS += -m32 + LDFLAGS += -m32 -Wl,-m,elf_i386 +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 -arch x86_64 + 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 -arch i686 + LDLIBS += -ldl + endif + endif +endif +ifeq ($(OS), FREEBSD) + LDLIBS += -lc +endif + +# search for OpenGL libraries +GL_LIBS= +ifeq ($(OS), OSX) + GL_LIBS = -framework OpenGL +endif +ifeq ($(OS), MINGW) + GL_LIBS = -lopengl32 +endif +ifeq ("$(GL_LIBS)", "") + ifeq ($(shell which $(PKG_CONFIG) 2>/dev/null),) + $(error $(PKG_CONFIG) not found) + endif + ifeq ($(shell $(PKG_CONFIG) --modversion gl 2>/dev/null),) + $(error No OpenGL development libraries found!) + endif + CFLAGS += $(shell $(PKG_CONFIG) --cflags gl) + GL_LIBS = $(shell $(PKG_CONFIG) --libs gl) +endif +LDLIBS += $(GL_LIBS) + +# test for presence of SDL +ifeq ($(shell which $(SDL_CONFIG) 2>/dev/null),) + $(error No SDL development libraries found!) +endif +ifeq ($(OS),FREEBSD) + CFLAGS += $(shell $(SDL_CONFIG) --cflags) + LDLIBS += $(shell $(SDL_CONFIG) --libs) +endif +ifeq ($(OS),OSX) + CFLAGS += $(shell $(SDL_CONFIG) --cflags) + # sdl-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 + LDLIBS += -L/usr/local/lib -lSDL -Wl,-framework,Cocoa +endif +ifeq ($(OS),LINUX) + CFLAGS += $(shell $(SDL_CONFIG) --cflags) + LDLIBS += $(shell $(SDL_CONFIG) --libs) +endif +ifeq ($(OS), MINGW) + CFLAGS += $(shell $(SDL_CONFIG) --cflags) + LDLIBS += $(shell $(SDL_CONFIG) --libs) +endif + +# 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) $(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 + +SRCDIR = ../../src +OBJDIR = _obj$(POSTFIX) + +# 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)" + @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 " LTO=1 == enable experimental build with link-time optimization" + @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 "../../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 +-include $(OBJECTS:.o=.d) + +CXXFLAGS += $(CFLAGS) +ifeq ($(LTO), 1) + CFLAGS += -flto -ffunction-sections -fdata-sections + CXXFLAGS += -flto -ffunction-sections -fdata-sections + LDFLAGS += -fuse-linker-plugin -Wl,--gc-sections $(CXXFLAGS) +endif + +# 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 diff --git a/libmupen64plus/mupen64plus-video-glide64/src/3dmath.cpp b/libmupen64plus/mupen64plus-video-glide64/src/3dmath.cpp new file mode 100644 index 0000000000..79ff2035ed --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/3dmath.cpp @@ -0,0 +1,394 @@ +/* +* 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; + register 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 = min(rdp.tiles[rdp.cur_tile].org_s_scale >> 6, rdp.tiles[rdp.cur_tile].lr_s); + t_scale = min(rdp.tiles[rdp.cur_tile].org_t_scale >> 6, 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 = __builtin_ia32_loadups(m2[0]); + v4sf row1 = __builtin_ia32_loadups(m2[1]); + v4sf row2 = __builtin_ia32_loadups(m2[2]); + v4sf row3 = __builtin_ia32_loadups(m2[3]); + + for (int i = 0; i < 4; ++i) + { + v4sf leftrow = __builtin_ia32_loadups(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; + + __builtin_ia32_storeups(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"); + } +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/3dmath.h b/libmupen64plus/mupen64plus-video-glide64/src/3dmath.h new file mode 100644 index 0000000000..8fb54b072f --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/3dmath.h @@ -0,0 +1,74 @@ +/* +* 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(register float *v1, register float *v2) +{ + register float result; + result = v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; + return(result); +} + +__inline void NormalizeVector(float *v) +{ + register 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; + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/AUTHORS b/libmupen64plus/mupen64plus-video-glide64/src/AUTHORS new file mode 100644 index 0000000000..9ae665ec3a --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/AUTHORS @@ -0,0 +1,7 @@ +Dave2001 +Gonetz +Gugaman +Hacktarux +Josh +Ziggy +Günther \ No newline at end of file diff --git a/libmupen64plus/mupen64plus-video-glide64/src/CRC.cpp b/libmupen64plus/mupen64plus-video-glide64/src/CRC.cpp new file mode 100644 index 0000000000..e54bf84405 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/CRC.cpp @@ -0,0 +1,77 @@ +/* +* 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 ); + } +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/CRC.h b/libmupen64plus/mupen64plus-video-glide64/src/CRC.h new file mode 100644 index 0000000000..541e1b0176 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/CRC.h @@ -0,0 +1,91 @@ +/* +* 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 +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/Changes.txt b/libmupen64plus/mupen64plus-video-glide64/src/Changes.txt new file mode 100644 index 0000000000..84681358c5 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/Changes.txt @@ -0,0 +1,1417 @@ + +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 diff --git a/libmupen64plus/mupen64plus-video-glide64/src/Combine.cpp b/libmupen64plus/mupen64plus-video-glide64/src/Combine.cpp new file mode 100644 index 0000000000..9ad66b7f7a --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/Combine.cpp @@ -0,0 +1,12582 @@ +/* +* 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; + } +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/Combine.h b/libmupen64plus/mupen64plus-video-glide64/src/Combine.h new file mode 100644 index 0000000000..665cf48605 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/Combine.h @@ -0,0 +1,118 @@ +/* +* 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 + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/Config.cpp b/libmupen64plus/mupen64plus-video-glide64/src/Config.cpp new file mode 100644 index 0000000000..8f3913f720 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/Config.cpp @@ -0,0 +1,68 @@ +/* +* 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); + } + +} diff --git a/libmupen64plus/mupen64plus-video-glide64/src/Config.h b/libmupen64plus/mupen64plus-video-glide64/src/Config.h new file mode 100644 index 0000000000..354118e152 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/Config.h @@ -0,0 +1,34 @@ +/* +* 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 */ + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/Debugger.cpp b/libmupen64plus/mupen64plus-video-glide64/src/Debugger.cpp new file mode 100644 index 0000000000..d68a89b226 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/Debugger.cpp @@ -0,0 +1,1054 @@ +/* +* 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; + } +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/Debugger.h b/libmupen64plus/mupen64plus-video-glide64/src/Debugger.h new file mode 100644 index 0000000000..15539be4f5 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/Debugger.h @@ -0,0 +1,137 @@ +/* +* 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, ...); + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/DepthBufferRender.cpp b/libmupen64plus/mupen64plus-video-glide64/src/DepthBufferRender.cpp new file mode 100644 index 0000000000..e67d1228c6 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/DepthBufferRender.cpp @@ -0,0 +1,353 @@ +/* +* 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; +} + +/* +int idiv16(int x, int y); // (x << 16) / y +#pragma aux idiv16 = \ + " mov edx,eax "\ + " sar edx,16 "\ + " shl eax,16 "\ + " idiv ebx "\ + parm [eax] [ebx] modify exact [eax edx] value [eax] +*/ +__inline int idiv16(int x, int y) // (x << 16) / y +{ + //x = (((long long)x) << 16) / ((long long)y); +#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)); +#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; + } + } +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/DepthBufferRender.h b/libmupen64plus/mupen64plus-video-glide64/src/DepthBufferRender.h new file mode 100644 index 0000000000..27368eb96b --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/DepthBufferRender.h @@ -0,0 +1,54 @@ +/* +* 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 + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/Gfx1.3.h b/libmupen64plus/mupen64plus-video-glide64/src/Gfx1.3.h new file mode 100644 index 0000000000..f8d629fe96 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/Gfx1.3.h @@ -0,0 +1,783 @@ +/* +* 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__ + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/INSTALL b/libmupen64plus/mupen64plus-video-glide64/src/INSTALL new file mode 100644 index 0000000000..a896c4d864 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/INSTALL @@ -0,0 +1,8 @@ +For 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 \ No newline at end of file diff --git a/libmupen64plus/mupen64plus-video-glide64/src/Ini.cpp b/libmupen64plus/mupen64plus-video-glide64/src/Ini.cpp new file mode 100644 index 0000000000..9436ff79d8 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/Ini.cpp @@ -0,0 +1,540 @@ +/* +* 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 (path == 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); +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/Ini.h b/libmupen64plus/mupen64plus-video-glide64/src/Ini.h new file mode 100644 index 0000000000..0eed64a2ab --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/Ini.h @@ -0,0 +1,49 @@ +/* +* 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 ); + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/LICENSES b/libmupen64plus/mupen64plus-video-glide64/src/LICENSES new file mode 100644 index 0000000000..bc0680c089 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/LICENSES @@ -0,0 +1,27 @@ +The 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 + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/Main.cpp b/libmupen64plus/mupen64plus-video-glide64/src/Main.cpp new file mode 100644 index 0000000000..4d50f8368e --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/Main.cpp @@ -0,0 +1,1804 @@ +/* +* 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_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 +#if !defined(__GNUC__) + cur = _byteswap_ulong(~*(data++)); +#else + cur = __builtin_bswap32(~*(data++)); +#endif + + 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 ((FxU32)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 ((FxU32)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: 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 + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/MiClWr16b.h b/libmupen64plus/mupen64plus-video-glide64/src/MiClWr16b.h new file mode 100644 index 0000000000..f6fb78f668 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/MiClWr16b.h @@ -0,0 +1,298 @@ +/* +* 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 +// +//**************************************************************** + +//**************************************************************** +// 16-bit Horizontal Mirror + +void Mirror16bS (unsigned char * tex, DWORD mask, DWORD max_width, DWORD real_width, DWORD height) +{ + if (mask == 0) return; + + DWORD mask_width = (1 << mask); + DWORD 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; + int line = line_full - count; + if (line < 0) return; + unsigned short * start = (unsigned short *)(tex) + mask_width; + + unsigned short * edi = start; + for(unsigned int ecx = height; ecx; --ecx) + { + for (int edx = 0; edx != count; ++edx) + { + unsigned short * esi = (unsigned short *)(tex); + if ((mask_width + edx) & mask_width) + { + esi += (mask_mask - ((edx >> 1) & mask_mask)) / 2; + } + else + { + esi += ((edx >> 1) & mask_mask) / 2; + } + *edi = *esi; + ++edi; + } + edi += line; + tex += line_full * 2; + } +} + +//**************************************************************** +// 16-bit Vertical Mirror + +void Mirror16bT (unsigned char * tex, DWORD mask, DWORD max_height, DWORD real_width) +{ + if (mask == 0) return; + + DWORD mask_height = (1 << mask); + DWORD 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 (DWORD y=mask_height; y> 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); +#if !defined(__GNUC__) && !defined(NO_ASM) + __asm { + mov edi,dword ptr [start] + + mov ecx,dword ptr [height] +loop_y: + + xor edx,edx +loop_x: + + mov esi,dword ptr [tex] + mov eax,edx + and eax,dword ptr [mask_mask] + shl eax,2 + add esi,eax + mov eax,dword ptr [esi] + mov dword ptr [edi],eax + add edi,4 + + inc edx + cmp edx,dword ptr [count] + jne loop_x + + add edi,dword ptr [line] + mov eax,dword ptr [tex] + add eax,dword ptr [line_full] + mov dword ptr [tex],eax + + dec ecx + jnz loop_y + } +#elif !defined(NO_ASM) + //printf("wrap16bS\n"); + intptr_t fake_esi, fake_eax; + asm volatile ( + "0: \n" + + "xor %%edx, %%edx \n" + "1: \n" + + "mov %[tex], %[S] \n" + "mov %%edx, %%eax \n" + "and %[mask_mask], %%eax \n" + "shl $2, %%eax \n" + "add %[a], %[S] \n" + "mov (%[S]), %%eax \n" + "mov %%eax, (%[start]) \n" + "add $4, %[start] \n" + + "inc %%edx \n" + "cmp %[count], %%edx \n" + "jne 1b \n" + + "add %[line], %[start] \n" + "add %[line_full], %[tex] \n" + + "dec %%ecx \n" + "jnz 0b \n" + : [S] "=&S" (fake_esi), [a]"=&a"(fake_eax), [start]"+D"(start), "+c"(height), [tex] "+r"(tex) + : [mask_mask] "g" (mask_mask), [count] "g" (count), [line] "g" ((intptr_t)line), [line_full] "g" ((intptr_t)line_full) + : "memory", "cc", "edx" + ); +#endif // _WIN32 +} + +//**************************************************************** +// 16-bit Vertical Wrap + +void Wrap16bT (unsigned char * tex, DWORD mask, DWORD max_height, DWORD real_width) +{ + if (mask == 0) return; + + DWORD mask_height = (1 << mask); + DWORD 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 (DWORD y=mask_height; y +* +* 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 +// +//**************************************************************** + +//**************************************************************** +// 8-bit Horizontal Mirror + +void Mirror8bS (unsigned char * tex, DWORD mask, DWORD max_width, DWORD real_width, DWORD height) +{ + if (mask == 0) return; + + DWORD mask_width = (1 << mask); + DWORD mask_mask = (mask_width-1); + if (mask_width >= 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); +#if !defined(__GNUC__) && !defined(NO_ASM) + __asm { + mov edi,dword ptr [start] + + mov ecx,dword ptr [height] +loop_y: + + xor edx,edx +loop_x: + mov esi,dword ptr [tex] + mov ebx,dword ptr [mask_width] + add ebx,edx + and ebx,dword ptr [mask_width] + jnz is_mirrored + + mov eax,edx + and eax,dword ptr [mask_mask] + add esi,eax + mov al,byte ptr [esi] + mov byte ptr [edi],al + inc edi + jmp end_mirror_check +is_mirrored: + add esi,dword ptr [mask_mask] + mov eax,edx + and eax,dword ptr [mask_mask] + sub esi,eax + mov al,byte ptr [esi] + mov byte ptr [edi],al + inc edi +end_mirror_check: + + inc edx + cmp edx,dword ptr [count] + jne loop_x + + add edi,dword ptr [line] + mov eax,dword ptr [tex] + add eax,dword ptr [line_full] + mov dword ptr [tex],eax + + dec ecx + jnz loop_y + } +#elif !defined(NO_ASM) + //printf("Mirror8bS\n"); + intptr_t fake_esi,fake_eax; + asm volatile ( + "1: \n" // loop_y3 + + "xor %%edx, %%edx \n" + "2: \n" // loop_x3 + "mov %[tex], %[S] \n" + "mov %[mask_width], %%eax \n" + "add %%edx, %%eax \n" + "and %[mask_width], %%eax \n" + "jnz 3f \n" // is_mirrored2 + + "mov %%edx, %%eax \n" + "and %[mask_mask], %[a] \n" + "add %[a], %[S] \n" + "mov (%[S]), %%al \n" + "mov %%al, (%[start]) \n" + "inc %[start] \n" + "jmp 4f \n" // end_mirror_check2 + "3: \n" // is_mirrored2 + "add %[mask_mask], %[S] \n" + "mov %%edx, %%eax \n" + "and %[mask_mask], %[a] \n" + "sub %[a], %[S] \n" + "mov (%[S]), %%al \n" + "mov %%al, (%[start]) \n" + "inc %[start] \n" + "4: \n" // end_mirror_check2 + + "inc %%edx \n" + "cmp %[count], %%edx \n" + "jne 2b \n" // loop_x3 + + "add %[line], %[start] \n" + "add %[line_full], %[tex] \n" + + "dec %%ecx \n" + "jnz 1b \n" // loop_y3 + : [S] "=&S" (fake_esi), [a]"=&a"(fake_eax), [start]"+D"(start), "+c"(height), [tex] "+r" (tex) + : [mask_width] "g" (mask_width), [mask_mask] "g" ((intptr_t)mask_mask), [count] "g" (count), [line] "g" ((intptr_t)line), [line_full] "g" ((intptr_t)line_full) + : "memory", "cc", "edx" + ); +#endif // _WIN32 +} + +//**************************************************************** +// 8-bit Vertical Mirror + +void Mirror8bT (unsigned char * tex, DWORD mask, DWORD max_height, DWORD real_width) +{ + if (mask == 0) return; + + DWORD mask_height = (1 << mask); + DWORD 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 (DWORD y=mask_height; y> 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); +#if !defined(__GNUC__) && !defined(NO_ASM) + __asm { + mov edi,dword ptr [start] + + mov ecx,dword ptr [height] +loop_y: + + xor edx,edx +loop_x: + + mov esi,dword ptr [tex] + mov eax,edx + and eax,dword ptr [mask_mask] + shl eax,2 + add esi,eax + mov eax,dword ptr [esi] + mov dword ptr [edi],eax + add edi,4 + + inc edx + cmp edx,dword ptr [count] + jne loop_x + + add edi,dword ptr [line] + mov eax,dword ptr [tex] + add eax,dword ptr [line_full] + mov dword ptr [tex],eax + + dec ecx + jnz loop_y + } +#elif !defined(NO_ASM) + //printf("wrap8bS\n"); + intptr_t fake_esi,fake_eax; + asm volatile ( + "1: \n" // loop_y4 + + "xor %%edx, %%edx \n" + "2: \n" // loop_x4 + + "mov %[tex], %[S] \n" + "mov %%edx, %%eax \n" + "and %[mask_mask], %%eax \n" + "shl $2, %%eax \n" + "add %[a], %[S] \n" + "mov (%[S]), %%eax \n" + "mov %%eax, (%[start]) \n" + "add $4, %[start] \n" + + "inc %%edx \n" + "cmp %[count], %%edx \n" + "jne 2b \n" // loop_x4 + + "add %[line], %[start] \n" + "add %[line_full], %[tex] \n" + + "dec %%ecx \n" + "jnz 1b \n" // loop_y4 + : [S] "=&S" (fake_esi), [a]"=&a"(fake_eax), [start]"+D"(start), [tex] "+r" (tex), "+c"(height) + : [mask_mask] "g" (mask_mask), [count] "g" (count), [line] "g" ((intptr_t)line), [line_full] "g" ((intptr_t)line_full) + : "memory", "cc", "edx" + ); +#endif +} + +//**************************************************************** +// 8-bit Vertical Wrap + +void Wrap8bT (unsigned char * tex, DWORD mask, DWORD max_height, DWORD real_width) +{ + if (mask == 0) return; + + DWORD mask_height = (1 << mask); + DWORD 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 (DWORD y=mask_height; y +#endif // _WIN32 + +#define max(a,b) ((a) > (b) ? (a) : (b)) +#define min(a,b) ((a) < (b) ? (a) : (b)) + +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 = min(cimage.width * rdp.scale_x, settings.scr_res_x); + float height = min(rdp.vi_height,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 = 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) + memcpy(&(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) + memcpy(&(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; +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/TexBuffer.h b/libmupen64plus/mupen64plus-video-glide64/src/TexBuffer.h new file mode 100644 index 0000000000..1d9b5e55f6 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/TexBuffer.h @@ -0,0 +1,54 @@ +/* +* 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 + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/TexCache.cpp b/libmupen64plus/mupen64plus-video-glide64/src/TexCache.cpp new file mode 100644 index 0000000000..d995a53427 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/TexCache.cpp @@ -0,0 +1,1475 @@ +/* +* 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" + +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; + } +} + +//**************************************************************** +// 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 = min(mask_width, tile_width); + // actual width + rdp.tiles[tile].width = tile_width; + } + else + { + // wrap all the way + width = 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 = min(mask_height, tile_height); + // actual height + rdp.tiles[tile].height = tile_height; + } + else + { + // wrap all the way + height = 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 = 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 = 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 + 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) + { + + // Check the CRC +#if !defined(__GNUC__) && !defined(NO_ASM) + __asm { + xor eax,eax // eax is final result + mov ebx,dword ptr [line] + mov ecx,dword ptr [height] // ecx is height counter + mov edi,dword ptr [addr] // edi is ptr to texture memory + crc_loop_y: + push ecx + + mov ecx,dword ptr [wid_64] + crc_loop_x: + + add eax,dword ptr [edi] // MUST be 64-bit aligned, so manually unroll + add eax,dword ptr [edi+4] + mov edx,ecx + mul edx + add eax,edx + add edi,8 + + dec ecx + jnz crc_loop_x + + pop ecx + + mov edx,ecx + mul edx + add eax,edx + + add edi,ebx + + dec ecx + jnz crc_loop_y + + mov dword ptr [crc],eax // store the result + } +#elif !defined(NO_ASM) + int i; + int tempheight = height; + asm volatile ( + "xor %[crc], %[crc] \n" // eax is final result + "crc_loop_y: \n" + + "mov %[wid_64], %[i] \n" + "crc_loop_x: \n" + + "add (%[addr]), %[crc] \n" // MUST be 64-bit aligned, so manually unroll + "add 4(%[addr]), %[crc] \n" + "mov %[i], %%edx \n" + "mul %%edx \n" // edx:eax/crc := eax/crc * edx + "add %%edx, %[crc] \n" + "add $8, %[addr] \n" + + "dec %[i] \n" + "jnz crc_loop_x \n" + + "mov %[tempheight], %%edx \n" + "mul %%edx \n" + "add %%edx, %[crc] \n" + + "add %[line], %[addr] \n" + + "dec %[tempheight] \n" + "jnz crc_loop_y \n" + : [crc] "=&a"(crc), [i] "=&r" (i), [tempheight] "+r"(tempheight), [addr]"+r"(addr) + : [line] "g" ((intptr_t)line), [wid_64] "g" (wid_64) + : "memory", "cc", "edx" + ); +#endif + // ** END CRC CHECK + } + } + 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 = 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 = 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"); +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/TexCache.h b/libmupen64plus/mupen64plus-video-glide64/src/TexCache.h new file mode 100644 index 0000000000..53c9bf3282 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/TexCache.h @@ -0,0 +1,46 @@ +/* +* 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 + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/TexConv.h b/libmupen64plus/mupen64plus-video-glide64/src/TexConv.h new file mode 100644 index 0000000000..b9854c9622 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/TexConv.h @@ -0,0 +1,459 @@ +/* +* 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 +// +//**************************************************************** + +void TexConv_ARGB1555_ARGB4444 (unsigned char * _src, unsigned char * _dst, int width, int height) +{ + int _size = (width * height) << 1; +#if !defined(__GNUC__) && !defined(NO_ASM) + __asm { + mov esi,dword ptr [_src] + mov edi,dword ptr [_dst] + mov ecx,dword ptr [_size] + +tc1_loop: + mov eax,dword ptr [esi] + add esi,4 + + // arrr rrgg gggb bbbb + // aaaa rrrr gggg bbbb + mov edx,eax + and eax,0x80008000 + mov ebx,eax // ebx = 0xa000000000000000 + shr eax,1 + or ebx,eax // ebx = 0xaa00000000000000 + shr eax,1 + or ebx,eax // ebx = 0xaaa0000000000000 + shr eax,1 + or ebx,eax // ebx = 0xaaaa000000000000 + + mov eax,edx + and eax,0x78007800 // eax = 0x0rrrr00000000000 + shr eax,3 // eax = 0x0000rrrr00000000 + or ebx,eax // ebx = 0xaaaarrrr00000000 + + mov eax,edx + and eax,0x03c003c0 // eax = 0x000000gggg000000 + shr eax,2 // eax = 0x00000000gggg0000 + or ebx,eax // ebx = 0xaaaarrrrgggg0000 + + and edx,0x001e001e // edx = 0x00000000000bbbb0 + shr edx,1 // edx = 0x000000000000bbbb + or ebx,edx // ebx = 0xaaaarrrrggggbbbb + + mov dword ptr [edi],ebx + add edi,4 + + dec ecx + jnz tc1_loop + } +#elif !defined(NO_ASM) + //printf("TexConv_ARGB1555_ARGB4444\n"); + asm volatile ( + //"tc1_loop2: \n" + "0: \n" + "mov (%[_src]), %%eax \n" + "add $4, %[_src] \n" + + // arrr rrgg gggb bbbb + // aaaa rrrr gggg bbbb + "mov %%eax, %%edx \n" + "and $0x80008000, %%eax \n" + "mov %%eax, %%ecx \n" // ecx = 0xa000000000000000 + "shr $1, %%eax \n" + "or %%eax, %%ecx \n" // ecx = 0xaa00000000000000 + "shr $1, %%eax \n" + "or %%eax, %%ecx \n" // ecx = 0xaaa0000000000000 + "shr $1, %%eax \n" + "or %%eax, %%ecx \n" // ecx = 0xaaaa000000000000 + + "mov %%edx, %%eax \n" + "and $0x78007800, %%eax \n" // eax = 0x0rrrr00000000000 + "shr $3, %%eax \n" // eax = 0x0000rrrr00000000 + "or %%eax, %%ecx \n" // ecx = 0xaaaarrrr00000000 + + "mov %%edx, %%eax \n" + "and $0x03c003c0, %%eax \n" // eax = 0x000000gggg000000 + "shr $2, %%eax \n" // eax = 0x00000000gggg0000 + "or %%eax, %%ecx \n" // ecx = 0xaaaarrrrgggg0000 + + "and $0x001e001e, %%edx \n" // edx = 0x00000000000bbbb0 + "shr $1, %%edx \n" // edx = 0x000000000000bbbb + "or %%edx, %%ecx \n" // ecx = 0xaaaarrrrggggbbbb + + "mov %%ecx, (%[_dst]) \n" + "add $4, %[_dst] \n" + + "decl %[_size] \n" + "jnz 0b \n" + : [_src]"+S"(_src), [_dst]"+D"(_dst), [_size]"+g"(_size) + : + : "memory", "cc", "eax", "edx", "ecx" + ); +#endif +} + +void TexConv_AI88_ARGB4444 (unsigned char * _src, unsigned char * _dst, int width, int height) +{ + int _size = (width * height) << 1; +#if !defined(__GNUC__) && !defined(NO_ASM) + __asm { + mov esi,dword ptr [_src] + mov edi,dword ptr [_dst] + mov ecx,dword ptr [_size] + +tc1_loop: + mov eax,dword ptr [esi] + add esi,4 + + // aaaa aaaa iiii iiii + // aaaa rrrr gggg bbbb + mov edx,eax + and eax,0xF000F000 // eax = 0xaaaa000000000000 + mov ebx,eax // ebx = 0xaaaa000000000000 + + and edx,0x00F000F0 // edx = 0x00000000iiii0000 + shl edx,4 // edx = 0x0000iiii00000000 + or ebx,edx // ebx = 0xaaaaiiii00000000 + shr edx,4 // edx = 0x00000000iiii0000 + or ebx,edx // ebx = 0xaaaaiiiiiiii0000 + shr edx,4 // edx = 0x000000000000iiii + or ebx,edx // ebx = 0xaaaaiiiiiiiiiiii + + mov dword ptr [edi],ebx + add edi,4 + + dec ecx + jnz tc1_loop + } +#elif !defined(NO_ASM) + //printf("TexConv_AI88_ARGB4444\n"); + asm volatile ( + //"tc1_loop3: \n" + "0: \n" + "mov (%[_src]), %%eax \n" + "add $4, %[_src] \n" + + // aaaa aaaa iiii iiii + // aaaa rrrr gggg bbbb + "mov %%eax, %%edx \n" + "and $0xF000F000, %%eax \n" // eax = 0xaaaa000000000000 + "mov %%eax, %%ecx \n" // ecx = 0xaaaa000000000000 + + "and $0x00F000F0, %%edx \n" // edx = 0x00000000iiii0000 + "shl $4, %%edx \n" // edx = 0x0000iiii00000000 + "or %%edx, %%ecx \n" // ecx = 0xaaaaiiii00000000 + "shr $4, %%edx \n" // edx = 0x00000000iiii0000 + "or %%edx, %%ecx \n" // ecx = 0xaaaaiiiiiiii0000 + "shr $4, %%edx \n" // edx = 0x000000000000iiii + "or %%edx, %%ecx \n" // ecx = 0xaaaaiiiiiiiiiiii + + "mov %%ecx, (%[_dst]) \n" + "add $4, %[_dst] \n" + + "decl %[_size] \n" + "jnz 0b \n" + : [_src]"+S"(_src), [_dst]"+D"(_dst), [_size]"+g"(_size) + : + : "memory", "cc", "eax", "edx", "ecx" + ); +#endif +} + +void TexConv_AI44_ARGB4444 (unsigned char * _src, unsigned char * _dst, int width, int height) +{ + int _size = width * height; +#if !defined(__GNUC__) && !defined(NO_ASM) + __asm { + mov esi,dword ptr [_src] + mov edi,dword ptr [_dst] + mov ecx,dword ptr [_size] + +tc1_loop: + mov eax,dword ptr [esi] + add esi,4 + + // aaaa3 iiii3 aaaa2 iiii2 aaaa1 iiii1 aaaa0 iiii0 + // aaaa1 rrrr1 gggg1 bbbb1 aaaa0 rrrr0 gggg0 bbbb0 + // aaaa3 rrrr3 gggg3 bbbb3 aaaa2 rrrr2 gggg2 bbbb2 + mov edx,eax // eax = aaaa3 iiii3 aaaa2 iiii2 aaaa1 iiii1 aaaa0 iiii0 + shl eax,16 // eax = aaaa1 iiii1 aaaa0 iiii0 0000 0000 0000 0000 + and eax,0xFF000000 // eax = aaaa1 iiii1 0000 0000 0000 0000 0000 0000 + mov ebx,eax // ebx = aaaa1 iiii1 0000 0000 0000 0000 0000 0000 + and eax,0x0F000000 // eax = 0000 iiii1 0000 0000 0000 0000 0000 0000 + shr eax,4 // eax = 0000 0000 iiii1 0000 0000 0000 0000 0000 + or ebx,eax // ebx = aaaa1 iiii1 iiii1 0000 0000 0000 0000 0000 + shr eax,4 // eax = 0000 0000 0000 iiii1 0000 0000 0000 0000 + or ebx,eax // ebx = aaaa1 iiii1 iiii1 iiii1 0000 0000 0000 0000 + + mov eax,edx // eax = aaaa3 iiii3 aaaa2 iiii2 aaaa1 iiii1 aaaa0 iiii0 + shl eax,8 // eax = aaaa2 iiii2 aaaa1 iiii1 aaaa0 iiii0 0000 0000 + and eax,0x0000FF00 // eax = 0000 0000 0000 0000 aaaa0 iiii0 0000 0000 + or ebx,eax // ebx = aaaa1 iiii1 iiii1 iiii1 aaaa0 iiii0 0000 0000 + and eax,0x00000F00 // eax = 0000 0000 0000 0000 0000 iiii0 0000 0000 + shr eax,4 // eax = 0000 0000 0000 0000 0000 0000 iiii0 0000 + or ebx,eax // ebx = aaaa1 iiii1 iiii1 iiii1 aaaa0 iiii0 iiii0 0000 + shr eax,4 // eax = 0000 0000 0000 0000 0000 0000 0000 iiii0 + or ebx,eax // ebx = aaaa1 iiii1 iiii1 iiii1 aaaa0 iiii0 iiii0 iiii0 + + mov dword ptr [edi],ebx + add edi,4 + + mov eax,edx // eax = aaaa3 iiii3 aaaa2 iiii2 aaaa1 iiii1 aaaa0 iiii0 + and eax,0xFF000000 // eax = aaaa3 iiii3 0000 0000 0000 0000 0000 0000 + mov ebx,eax // ebx = aaaa3 iiii3 0000 0000 0000 0000 0000 0000 + and eax,0x0F000000 // eax = 0000 iiii3 0000 0000 0000 0000 0000 0000 + shr eax,4 // eax = 0000 0000 iiii3 0000 0000 0000 0000 0000 + or ebx,eax // ebx = aaaa3 iiii3 iiii3 0000 0000 0000 0000 0000 + shr eax,4 // eax = 0000 0000 0000 iiii3 0000 0000 0000 0000 + or ebx,eax // ebx = aaaa3 iiii3 iiii3 iiii3 0000 0000 0000 0000 + + // edx = aaaa3 iiii3 aaaa2 iiii2 aaaa1 iiii1 aaaa0 iiii0 + shr edx,8 // edx = 0000 0000 aaaa3 aaaa3 aaaa2 iiii2 aaaa1 iiii1 + and edx,0x0000FF00 // edx = 0000 0000 0000 0000 aaaa2 iiii2 0000 0000 + or ebx,edx // ebx = aaaa3 iiii3 iiii3 iiii3 aaaa2 iiii2 0000 0000 + and edx,0x00000F00 // edx = 0000 0000 0000 0000 0000 iiii2 0000 0000 + shr edx,4 // edx = 0000 0000 0000 0000 0000 0000 iiii2 0000 + or ebx,edx // ebx = aaaa3 iiii3 iiii3 iiii3 aaaa2 iiii2 iiii2 0000 + shr edx,4 // edx = 0000 0000 0000 0000 0000 0000 0000 iiii2 + or ebx,edx // ebx = aaaa3 iiii3 iiii3 iiii3 aaaa2 iiii2 iiii2 iiii2 + + mov dword ptr [edi],ebx + add edi,4 + + dec ecx + jnz tc1_loop + } +#elif !defined(NO_ASM) + //printf("TexConv_AI44_ARGB4444\n"); + asm volatile ( + //"tc1_loop4: \n" + "0: \n" + "mov (%[_src]), %%eax \n" + "add $4, %[_src] \n" + + // aaaa3 iiii3 aaaa2 iiii2 aaaa1 iiii1 aaaa0 iiii0 + // aaaa1 rrrr1 gggg1 bbbb1 aaaa0 rrrr0 gggg0 bbbb0 + // aaaa3 rrrr3 gggg3 bbbb3 aaaa2 rrrr2 gggg2 bbbb2 + "mov %%eax, %%edx \n" // eax = aaaa3 iiii3 aaaa2 iiii2 aaaa1 iiii1 aaaa0 iiii0 + "shl $16, %%eax \n" // eax = aaaa1 iiii1 aaaa0 iiii0 0000 0000 0000 0000 + "and $0xFF000000, %%eax \n" // eax = aaaa1 iiii1 0000 0000 0000 0000 0000 0000 + "mov %%eax, %%ecx \n" // ecx = aaaa1 iiii1 0000 0000 0000 0000 0000 0000 + "and $0x0F000000, %%eax \n" // eax = 0000 iiii1 0000 0000 0000 0000 0000 0000 + "shr $4, %%eax \n" // eax = 0000 0000 iiii1 0000 0000 0000 0000 0000 + "or %%eax, %%ecx \n" // ecx = aaaa1 iiii1 iiii1 0000 0000 0000 0000 0000 + "shr $4, %%eax \n" // eax = 0000 0000 0000 iiii1 0000 0000 0000 0000 + "or %%eax, %%ecx \n" // ecx = aaaa1 iiii1 iiii1 iiii1 0000 0000 0000 0000 + + "mov %%edx, %%eax \n" // eax = aaaa3 iiii3 aaaa2 iiii2 aaaa1 iiii1 aaaa0 iiii0 + "shl $8, %%eax \n" // eax = aaaa2 iiii2 aaaa1 iiii1 aaaa0 iiii0 0000 0000 + "and $0x0000FF00, %%eax \n" // eax = 0000 0000 0000 0000 aaaa0 iiii0 0000 0000 + "or %%eax, %%ecx \n" // ecx = aaaa1 iiii1 iiii1 iiii1 aaaa0 iiii0 0000 0000 + "and $0x00000F00, %%eax \n" // eax = 0000 0000 0000 0000 0000 iiii0 0000 0000 + "shr $4, %%eax \n" // eax = 0000 0000 0000 0000 0000 0000 iiii0 0000 + "or %%eax, %%ecx \n" // ecx = aaaa1 iiii1 iiii1 iiii1 aaaa0 iiii0 iiii0 0000 + "shr $4, %%eax \n" // eax = 0000 0000 0000 0000 0000 0000 0000 iiii0 + "or %%eax, %%ecx \n" // ecx = aaaa1 iiii1 iiii1 iiii1 aaaa0 iiii0 iiii0 iiii0 + + "mov %%ecx, (%[_dst]) \n" + "add $4, %[_dst] \n" + + "mov %%edx, %%eax \n" // eax = aaaa3 iiii3 aaaa2 iiii2 aaaa1 iiii1 aaaa0 iiii0 + "and $0xFF000000, %%eax \n" // eax = aaaa3 iiii3 0000 0000 0000 0000 0000 0000 + "mov %%eax, %%ecx \n" // ecx = aaaa3 iiii3 0000 0000 0000 0000 0000 0000 + "and $0x0F000000, %%eax \n" // eax = 0000 iiii3 0000 0000 0000 0000 0000 0000 + "shr $4, %%eax \n" // eax = 0000 0000 iiii3 0000 0000 0000 0000 0000 + "or %%eax, %%ecx \n" // ecx = aaaa3 iiii3 iiii3 0000 0000 0000 0000 0000 + "shr $4, %%eax \n" // eax = 0000 0000 0000 iiii3 0000 0000 0000 0000 + "or %%eax, %%ecx \n" // ecx = aaaa3 iiii3 iiii3 iiii3 0000 0000 0000 0000 + + // edx = aaaa3 iiii3 aaaa2 iiii2 aaaa1 iiii1 aaaa0 iiii0 + "shr $8, %%edx \n" // edx = 0000 0000 aaaa3 aaaa3 aaaa2 iiii2 aaaa1 iiii1 + "and $0x0000FF00, %%edx \n" // edx = 0000 0000 0000 0000 aaaa2 iiii2 0000 0000 + "or %%edx, %%ecx \n" // ecx = aaaa3 iiii3 iiii3 iiii3 aaaa2 iiii2 0000 0000 + "and $0x00000F00, %%edx \n" // edx = 0000 0000 0000 0000 0000 iiii2 0000 0000 + "shr $4, %%edx \n" // edx = 0000 0000 0000 0000 0000 0000 iiii2 0000 + "or %%edx, %%ecx \n" // ecx = aaaa3 iiii3 iiii3 iiii3 aaaa2 iiii2 iiii2 0000 + "shr $4, %%edx \n" // edx = 0000 0000 0000 0000 0000 0000 0000 iiii2 + "or %%edx, %%ecx \n" // ecx = aaaa3 iiii3 iiii3 iiii3 aaaa2 iiii2 iiii2 iiii2 + + "mov %%ecx, (%[_dst]) \n" + "add $4, %[_dst] \n" + + "decl %[_size] \n" + "jnz 0b \n" + : [_src]"+S"(_src), [_dst]"+D"(_dst), [_size]"+g"(_size) + : + : "memory", "cc", "eax", "edx", "ecx" + ); +#endif +} + +void TexConv_A8_ARGB4444 (unsigned char * _src, unsigned char * _dst, int width, int height) +{ + int _size = (width * height) << 1; +#if !defined(__GNUC__) && !defined(NO_ASM) + __asm { + mov esi,dword ptr [_src] + mov edi,dword ptr [_dst] + mov ecx,dword ptr [_size] + +tc1_loop: + mov eax,dword ptr [esi] + add esi,4 + + // aaaa3 aaaa3 aaaa2 aaaa2 aaaa1 aaaa1 aaaa0 aaaa0 + // aaaa1 rrrr1 gggg1 bbbb1 aaaa0 rrrr0 gggg0 bbbb0 + // aaaa3 rrrr3 gggg3 bbbb3 aaaa2 rrrr2 gggg2 bbbb2 + mov edx,eax + and eax,0x0000F000 // eax = 00 00 00 00 a1 00 00 00 + shl eax,16 // eax = a1 00 00 00 00 00 00 00 + mov ebx,eax // ebx = a1 00 00 00 00 00 00 00 + shr eax,4 + or ebx,eax // ebx = a1 a1 00 00 00 00 00 00 + shr eax,4 + or ebx,eax // ebx = a1 a1 a1 00 00 00 00 00 + shr eax,4 + or ebx,eax // ebx = a1 a1 a1 a1 00 00 00 00 + + mov eax,edx + and eax,0x000000F0 // eax = 00 00 00 00 00 00 a0 00 + shl eax,8 // eax = 00 00 00 00 a0 00 00 00 + or ebx,eax + shr eax,4 + or ebx,eax + shr eax,4 + or ebx,eax + shr eax,4 + or ebx,eax // ebx = a1 a1 a1 a1 a0 a0 a0 a0 + + mov dword ptr [edi],ebx + add edi,4 + + mov eax,edx // eax = a3 a3 a2 a2 a1 a1 a0 a0 + and eax,0xF0000000 // eax = a3 00 00 00 00 00 00 00 + mov ebx,eax // ebx = a3 00 00 00 00 00 00 00 + shr eax,4 + or ebx,eax // ebx = a3 a3 00 00 00 00 00 00 + shr eax,4 + or ebx,eax // ebx = a3 a3 a3 00 00 00 00 00 + shr eax,4 + or ebx,eax // ebx = a3 a3 a3 a3 00 00 00 00 + + and edx,0x00F00000 // eax = 00 00 a2 00 00 00 00 00 + shr edx,8 // eax = 00 00 00 00 a2 00 00 00 + or ebx,edx + shr edx,4 + or ebx,edx + shr edx,4 + or ebx,edx + shr edx,4 + or ebx,edx // ebx = a3 a3 a3 a3 a2 a2 a2 a2 + + mov dword ptr [edi],ebx + add edi,4 + + dec ecx + jnz tc1_loop + } +#elif !defined(NO_ASM) + //printf("TexConv_A8_ARGB4444\n"); + asm volatile ( + //"tc1_loop: \n" + "0: \n" + "mov (%[src]), %%eax \n" + "add $4, %[src] \n" + + // aaaa3 aaaa3 aaaa2 aaaa2 aaaa1 aaaa1 aaaa0 aaaa0 + // aaaa1 rrrr1 gggg1 bbbb1 aaaa0 rrrr0 gggg0 bbbb0 + // aaaa3 rrrr3 gggg3 bbbb3 aaaa2 rrrr2 gggg2 bbbb2 + "mov %%eax, %%edx \n" + "and $0x0000F000, %%eax \n" // eax = 00 00 00 00 a1 00 00 00 + "shl $16, %%eax \n" // eax = a1 00 00 00 00 00 00 00 + "mov %%eax, %%ecx \n" // ecx = a1 00 00 00 00 00 00 00 + "shr $4, %%eax \n" + "or %%eax, %%ecx \n" // ecx = a1 a1 00 00 00 00 00 00 + "shr $4, %%eax \n" + "or %%eax, %%ecx \n" // ecx = a1 a1 a1 00 00 00 00 00 + "shr $4, %%eax \n" + "or %%eax, %%ecx \n" // ecx = a1 a1 a1 a1 00 00 00 00 + + "mov %%edx, %%eax \n" + "and $0x000000F0, %%eax \n" // eax = 00 00 00 00 00 00 a0 00 + "shl $8, %%eax \n" // eax = 00 00 00 00 a0 00 00 00 + "or %%eax, %%ecx \n" + "shr $4, %%eax \n" + "or %%eax, %%ecx \n" + "shr $4, %%eax \n" + "or %%eax, %%ecx \n" + "shr $4, %%eax \n" + "or %%eax, %%ecx \n" // ecx = a1 a1 a1 a1 a0 a0 a0 a0 + + "mov %%ecx, (%[_dst]) \n" + "add $4, %[_dst] \n" + + "mov %%edx, %%eax \n" // eax = a3 a3 a2 a2 a1 a1 a0 a0 + "and $0xF0000000, %%eax \n" // eax = a3 00 00 00 00 00 00 00 + "mov %%eax, %%ecx \n" // ecx = a3 00 00 00 00 00 00 00 + "shr $4, %%eax \n" + "or %%eax, %%ecx \n" // ecx = a3 a3 00 00 00 00 00 00 + "shr $4, %%eax \n" + "or %%eax, %%ecx \n" // ecx = a3 a3 a3 00 00 00 00 00 + "shr $4, %%eax \n" + "or %%eax, %%ecx \n" // ecx = a3 a3 a3 a3 00 00 00 00 + + "and $0x00F00000, %%edx \n" // eax = 00 00 a2 00 00 00 00 00 + "shr $8, %%edx \n" // eax = 00 00 00 00 a2 00 00 00 + "or %%edx, %%ecx \n" + "shr $4, %%edx \n" + "or %%edx, %%ecx \n" + "shr $4, %%edx \n" + "or %%edx, %%ecx \n" + "shr $4, %%edx \n" + "or %%edx, %%ecx \n" // ecx = a3 a3 a3 a3 a2 a2 a2 a2 + + "mov %%ecx, (%[_dst]) \n" + "add $4, %[_dst] \n" + + "decl %[_size] \n" + "jnz 0b \n" + : [src]"+S"(_src), [_dst]"+D"(_dst), [_size]"+g"(_size) + : + : "memory", "cc", "eax", "ecx", "edx" + ); +#endif +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/TexLoad.h b/libmupen64plus/mupen64plus-video-glide64/src/TexLoad.h new file mode 100644 index 0000000000..fc7ac64335 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/TexLoad.h @@ -0,0 +1,59 @@ +/* +* 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 + +DWORD LoadNone (unsigned char * dst, unsigned char * src, int wid_64, int height, int line, int real_width, int tile) +{ + memset (texture, 0xFF, sizeof(texture)); + return GR_TEXFMT_ARGB_1555; +} + +typedef DWORD (*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} +}; + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/TexLoad16b.h b/libmupen64plus/mupen64plus-video-glide64/src/TexLoad16b.h new file mode 100644 index 0000000000..b64fd718c4 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/TexLoad16b.h @@ -0,0 +1,357 @@ +/* +* 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 + +DWORD Load16bRGBA (unsigned char * dst, unsigned char * 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 !defined(__GNUC__) && !defined(NO_ASM) + __asm { + mov esi,dword ptr [src] + mov edi,dword ptr [dst] + + mov ecx,dword ptr [height] +y_loop: + push ecx + + mov ecx,dword ptr [wid_64] +x_loop: + mov eax,dword ptr [esi] // read both pixels + add esi,4 + bswap eax + mov edx,eax + + ror ax,1 + ror eax,16 + ror ax,1 + + mov dword ptr [edi],eax + add edi,4 + + // * copy + mov eax,dword ptr [esi] // read both pixels + add esi,4 + bswap eax + mov edx,eax + + ror ax,1 + ror eax,16 + ror ax,1 + + mov dword ptr [edi],eax + add edi,4 + // * + + dec ecx + jnz x_loop + + pop ecx + dec ecx + jz end_y_loop + push ecx + + add esi,dword ptr [line] + add edi,dword ptr [ext] + + mov ecx,dword ptr [wid_64] +x_loop_2: + mov eax,dword ptr [esi+4] // read both pixels + bswap eax + mov edx,eax + + ror ax,1 + ror eax,16 + ror ax,1 + + mov dword ptr [edi],eax + add edi,4 + + // * copy + mov eax,dword ptr [esi] // read both pixels + add esi,8 + bswap eax + mov edx,eax + + ror ax,1 + ror eax,16 + ror ax,1 + + mov dword ptr [edi],eax + add edi,4 + // * + + dec ecx + jnz x_loop_2 + + add esi,dword ptr [line] + add edi,dword ptr [ext] + + pop ecx + dec ecx + jnz y_loop + +end_y_loop: + } +#elif !defined(NO_ASM) + //printf("Load16bRGBA\n"); + long lTemp, lHeight = (long) height; + asm volatile ( + "y_loop7: \n" + "mov %[c], %[temp] \n" + + "mov %[wid_64], %%ecx \n" + "x_loop7: \n" + "mov (%[src]), %%eax \n" // read both pixels + "add $4, %[src] \n" + "bswap %%eax \n" + "mov %%eax, %%edx \n" + + "ror $1, %%ax \n" + "ror $16, %%eax \n" + "ror $1, %%ax \n" + + "mov %%eax, (%[dst]) \n" + "add $4, %[dst] \n" + + // * copy + "mov (%[src]), %%eax \n" // read both pixels + "add $4, %[src] \n" + "bswap %%eax \n" + "mov %%eax, %%edx \n" + + "ror $1, %%ax \n" + "ror $16, %%eax \n" + "ror $1, %%ax \n" + + "mov %%eax, (%[dst]) \n" + "add $4, %[dst] \n" + // * + + "dec %%ecx \n" + "jnz x_loop7 \n" + + "mov %[temp], %[c] \n" + "dec %%ecx \n" + "jz end_y_loop7 \n" + "mov %[c], %[temp] \n" + + "add %[line], %[src] \n" + "add %[ext], %[dst] \n" + + "mov %[wid_64], %%ecx \n" + "x_loop_27: \n" + "mov 4(%[src]), %%eax \n" // read both pixels + "bswap %%eax \n" + "mov %%eax, %%edx \n" + + "ror $1, %%ax \n" + "ror $16, %%eax \n" + "ror $1, %%ax \n" + + "mov %%eax, (%[dst]) \n" + "add $4, %[dst] \n" + + // * copy + "mov (%[src]), %%eax \n" // read both pixels + "add $8, %[src] \n" + "bswap %%eax \n" + "mov %%eax, %%edx \n" + + "ror $1, %%ax \n" + "ror $16, %%eax \n" + "ror $1, %%ax \n" + + "mov %%eax, (%[dst]) \n" + "add $4, %[dst] \n" + // * + + "dec %%ecx \n" + "jnz x_loop_27 \n" + + "add %[line], %[src] \n" + "add %[ext], %[dst] \n" + + "mov %[temp], %[c] \n" + "dec %%ecx \n" + "jnz y_loop7 \n" + + "end_y_loop7: \n" + : [temp]"=m"(lTemp), [src]"+S"(src), [dst]"+D"(dst), [c]"+c"(lHeight) + : [wid_64] "g" (wid_64), [line] "g" ((uintptr_t)line), [ext] "g" ((uintptr_t)ext) + : "memory", "cc", "eax", "edx" + ); +#endif + return (1 << 16) | GR_TEXFMT_ARGB_1555; +} + +//**************************************************************** +// Size: 2, Format: 3 +// +// ** by Gugaman/Dave2001 ** + +DWORD Load16bIA (unsigned char * dst, unsigned char * 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 !defined(__GNUC__) && !defined(NO_ASM) + __asm { + mov esi,dword ptr [src] + mov edi,dword ptr [dst] + + mov ecx,dword ptr [height] +y_loop: + push ecx + + mov ecx,dword ptr [wid_64] +x_loop: + mov eax,dword ptr [esi] // read both pixels + add esi,4 + mov dword ptr [edi],eax + add edi,4 + + // * copy + mov eax,dword ptr [esi] // read both pixels + add esi,4 + mov dword ptr [edi],eax + add edi,4 + // * + + dec ecx + jnz x_loop + + pop ecx + dec ecx + jz end_y_loop + push ecx + + add esi,dword ptr [line] + add edi,dword ptr [ext] + + mov ecx,dword ptr [wid_64] +x_loop_2: + mov eax,dword ptr [esi+4] // read both pixels + mov dword ptr [edi],eax + add edi,4 + + // * copy + mov eax,dword ptr [esi] // read both pixels + add esi,8 + mov dword ptr [edi],eax + add edi,4 + // * + + dec ecx + jnz x_loop_2 + + add esi,dword ptr [line] + add edi,dword ptr [ext] + + pop ecx + dec ecx + jnz y_loop + +end_y_loop: + } +#elif !defined(NO_ASM) + //printf("Load16bIA\n"); + long lTemp, lHeight = (long) height; + asm volatile ( + "y_loop8: \n" + "mov %[c], %[temp] \n" + + "mov %[wid_64], %%ecx \n" + "x_loop8: \n" + "mov (%[src]), %%eax \n" // read both pixels + "add $4, %[src] \n" + "mov %%eax, (%[dst]) \n" + "add $4, %[dst] \n" + + // * copy + "mov (%[src]), %%eax \n" // read both pixels + "add $4, %[src] \n" + "mov %%eax, (%[dst]) \n" + "add $4, %[dst] \n" + // * + + "dec %%ecx \n" + "jnz x_loop8 \n" + + "mov %[temp], %[c] \n" + "dec %%ecx \n" + "jz end_y_loop8 \n" + "mov %[c], %[temp] \n" + + "add %[line], %[src] \n" + "add %[ext], %[dst] \n" + + "mov %[wid_64], %%ecx \n" + "x_loop_28: \n" + "mov 4(%[src]), %%eax \n" // read both pixels + "mov %%eax, (%[dst]) \n" + "add $4, %[dst] \n" + + // * copy + "mov (%[src]), %%eax \n" // read both pixels + "add $8, %[src] \n" + "mov %%eax, (%[dst]) \n" + "add $4, %[dst] \n" + // * + + "dec %%ecx \n" + "jnz x_loop_28 \n" + + "add %[line], %[src] \n" + "add %[ext], %[dst] \n" + + "mov %[temp], %[c] \n" + "dec %%ecx \n" + "jnz y_loop8 \n" + + "end_y_loop8: \n" + : [temp]"=m"(lTemp), [src]"+S"(src), [dst]"+D"(dst), [c]"+c"(lHeight) + : [wid_64] "g" (wid_64), [line] "g" ((uintptr_t)line), [ext] "g" ((uintptr_t)ext) + : "memory", "cc", "eax" + ); +#endif + return (1 << 16) | GR_TEXFMT_ALPHA_INTENSITY_88; +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/TexLoad32b.h b/libmupen64plus/mupen64plus-video-glide64/src/TexLoad32b.h new file mode 100644 index 0000000000..f575498e77 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/TexLoad32b.h @@ -0,0 +1,472 @@ +/* +* 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 + +DWORD Load32bRGBA (unsigned char * dst, unsigned char * 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 << 1)) << 1; + + wid_64 >>= 1; // re-shift it, load twice as many quadwords +#if !defined(__GNUC__) && !defined(NO_ASM) + __asm { + mov esi,dword ptr [src] + mov edi,dword ptr [dst] + + mov ecx,dword ptr [height] +y_loop: + push ecx + + mov ecx,dword ptr [wid_64] +x_loop: + mov eax,dword ptr [esi] // read first pixel + add esi,4 + bswap eax + mov edx,eax + + xor ebx,ebx + shl eax,8 // 0x000000F0 -> 0x0000F000 (a) + and eax,0x0000F000 + or ebx,eax + shr edx,12 // 0x0000F000 -> 0x0000000F (b) + mov eax,edx + and eax,0x0000000F + or ebx,eax + shr edx,4 // 0x00F00000 went to 0x00000F00 -> 0x000000F0 (g) + mov eax,edx + and eax,0x000000F0 + or ebx,eax + shr edx,4 // 0xF0000000 went to 0x000F0000 went to 0x0000F000 -> 0x00000F00 (r) + and edx,0x00000F00 + or ebx,edx + + mov eax,dword ptr [esi] // read second pixel + add esi,4 + bswap eax + mov edx,eax + + shl eax,24 // 0x000000F0 -> 0xF0000000 (a) + and eax,0xF0000000 + or ebx,eax + // 0x00F00000 -> 0x00F00000 (g) + mov eax,edx + and eax,0x00F00000 + or ebx,eax + rol edx,4 // 0x0000F000 (did not shift) -> 0x000F0000 (b) + mov eax,edx + and eax,0x000F0000 + or ebx,eax + shl edx,24 // 0xF0000000 went to 0x0000000F -> 0x0F000000 (r) + and edx,0x0F000000 + or ebx,edx + + mov dword ptr [edi],ebx + add edi,4 + + // * copy + mov eax,dword ptr [esi] // read first pixel + add esi,4 + bswap eax + mov edx,eax + + xor ebx,ebx + shl eax,8 // 0x000000F0 -> 0x0000F000 (a) + and eax,0x0000F000 + or ebx,eax + shr edx,12 // 0x0000F000 -> 0x0000000F (b) + mov eax,edx + and eax,0x0000000F + or ebx,eax + shr edx,4 // 0x00F00000 went to 0x00000F00 -> 0x000000F0 (g) + mov eax,edx + and eax,0x000000F0 + or ebx,eax + shr edx,4 // 0xF0000000 went to 0x000F0000 went to 0x0000F000 -> 0x00000F00 (r) + and edx,0x00000F00 + or ebx,edx + + mov eax,dword ptr [esi] // read second pixel + add esi,4 + bswap eax + mov edx,eax + + shl eax,24 // 0x000000F0 -> 0xF0000000 (a) + and eax,0xF0000000 + or ebx,eax + // 0x00F00000 -> 0x00F00000 (g) + mov eax,edx + and eax,0x00F00000 + or ebx,eax + rol edx,4 // 0x0000F000 (did not shift) -> 0x000F0000 (b) + mov eax,edx + and eax,0x000F0000 + or ebx,eax + shl edx,24 // 0xF0000000 went to 0x0000000F -> 0x0F000000 (r) + and edx,0x0F000000 + or ebx,edx + + mov dword ptr [edi],ebx + add edi,4 + // * + + dec ecx + jnz x_loop + + pop ecx + dec ecx + jz end_y_loop + push ecx + + add esi,dword ptr [line] + add edi,dword ptr [ext] + + mov ecx,dword ptr [wid_64] +x_loop_2: + mov eax,dword ptr [esi+8] // read first pixel + bswap eax + mov edx,eax + + xor ebx,ebx + shl eax,8 // 0x000000F0 -> 0x0000F000 (a) + and eax,0x0000F000 + or ebx,eax + shr edx,12 // 0x0000F000 -> 0x0000000F (b) + mov eax,edx + and eax,0x0000000F + or ebx,eax + shr edx,4 // 0x00F00000 went to 0x00000F00 -> 0x000000F0 (g) + mov eax,edx + and eax,0x000000F0 + or ebx,eax + shr edx,4 // 0xF0000000 went to 0x000F0000 went to 0x0000F000 -> 0x00000F00 (r) + and edx,0x00000F00 + or ebx,edx + + mov eax,dword ptr [esi+12] // read second pixel + bswap eax + mov edx,eax + + shl eax,24 // 0x000000F0 -> 0xF0000000 (a) + and eax,0xF0000000 + or ebx,eax + // 0x00F00000 -> 0x00F00000 (g) + mov eax,edx + and eax,0x00F00000 + or ebx,eax + rol edx,4 // 0x0000F000 (did not shift) -> 0x000F0000 (b) + mov eax,edx + and eax,0x000F0000 + or ebx,eax + shl edx,24 // 0xF0000000 went to 0x0000000F -> 0x0F000000 (r) + and edx,0x0F000000 + or ebx,edx + + mov dword ptr [edi],ebx + add edi,4 + + // * copy + mov eax,dword ptr [esi+0] // read first pixel + bswap eax + mov edx,eax + + xor ebx,ebx + shl eax,8 // 0x000000F0 -> 0x0000F000 (a) + and eax,0x0000F000 + or ebx,eax + shr edx,12 // 0x0000F000 -> 0x0000000F (b) + mov eax,edx + and eax,0x0000000F + or ebx,eax + shr edx,4 // 0x00F00000 went to 0x00000F00 -> 0x000000F0 (g) + mov eax,edx + and eax,0x000000F0 + or ebx,eax + shr edx,4 // 0xF0000000 went to 0x000F0000 went to 0x0000F000 -> 0x00000F00 (r) + and edx,0x00000F00 + or ebx,edx + + mov eax,dword ptr [esi+4] // read second pixel + add esi,16 + bswap eax + mov edx,eax + + shl eax,24 // 0x000000F0 -> 0xF0000000 (a) + and eax,0xF0000000 + or ebx,eax + // 0x00F00000 -> 0x00F00000 (g) + mov eax,edx + and eax,0x00F00000 + or ebx,eax + rol edx,4 // 0x0000F000 (did not shift) -> 0x000F0000 (b) + mov eax,edx + and eax,0x000F0000 + or ebx,eax + shl edx,24 // 0xF0000000 went to 0x0000000F -> 0x0F000000 (r) + and edx,0x0F000000 + or ebx,edx + + mov dword ptr [edi],ebx + add edi,4 + // * + + dec ecx + jnz x_loop_2 + + add esi,dword ptr [line] + add edi,dword ptr [ext] + + pop ecx + dec ecx + jnz y_loop + +end_y_loop: + } +#elif !defined(NO_ASM) + //printf("Load32bRGBA\n"); + int lTemp, lHeight = (int) height; + asm volatile ( + "y_loop9: \n" + + "mov %[wid_64], %%eax \n" + "mov %%eax, %[temp] \n" + "x_loop9: \n" + "mov (%[src]), %%eax \n" // read first pixel + "add $4, %[src] \n" + "bswap %%eax \n" + "mov %%eax, %%edx \n" + + "xor %%ecx, %%ecx \n" + "shl $8, %%eax \n" // 0x000000F0 -> 0x0000F000 (a) + "and $0x0000F000, %%eax \n" + "or %%eax, %%ecx \n" + "shr $12, %%edx \n" // 0x0000F000 -> 0x0000000F (b) + "mov %%edx, %%eax \n" + "and $0x0000000F, %%eax \n" + "or %%eax, %%ecx \n" + "shr $4, %%edx \n" // 0x00F00000 went to 0x00000F00 -> 0x000000F0 (g) + "mov %%edx, %%eax \n" + "and $0x000000F0, %%eax \n" + "or %%eax, %%ecx \n" + "shr $4, %%edx \n" // 0xF0000000 went to 0x000F0000 went to 0x0000F000 -> 0x00000F00 (r) + "and $0x00000F00, %%edx \n" + "or %%edx, %%ecx \n" + + "mov (%[src]), %%eax \n" // read second pixel + "add $4, %[src] \n" + "bswap %%eax \n" + "mov %%eax, %%edx \n" + + "shl $24, %%eax \n" // 0x000000F0 -> 0xF0000000 (a) + "and $0xF0000000, %%eax \n" + "or %%eax, %%ecx \n" // 0x00F00000 -> 0x00F00000 (g) + "mov %%edx, %%eax \n" + "and $0x00F00000, %%eax \n" + "or %%eax, %%ecx \n" + "rol $4, %%edx \n" // 0x0000F000 (did not shift) -> 0x000F0000 (b) + "mov %%edx, %%eax \n" + "and $0x000F0000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $24, %%edx \n" // 0xF0000000 went to 0x0000000F -> 0x0F000000 (r) + "and $0x0F000000, %%edx \n" + "or %%edx, %%ecx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + + // * copy + "mov (%[src]), %%eax \n" // read first pixel + "add $4, %[src] \n" + "bswap %%eax \n" + "mov %%eax, %%edx \n" + + "xor %%ecx, %%ecx \n" + "shl $8, %%eax \n" // 0x000000F0 -> 0x0000F000 (a) + "and $0x0000F000, %%eax \n" + "or %%eax, %%ecx \n" + "shr $12, %%edx \n" // 0x0000F000 -> 0x0000000F (b) + "mov %%edx, %%eax \n" + "and $0x0000000F, %%eax \n" + "or %%eax, %%ecx \n" + "shr $4, %%edx \n" // 0x00F00000 went to 0x00000F00 -> 0x000000F0 (g) + "mov %%edx, %%eax \n" + "and $0x000000F0, %%eax \n" + "or %%eax, %%ecx \n" + "shr $4, %%edx \n" // 0xF0000000 went to 0x000F0000 went to 0x0000F000 -> 0x00000F00 (r) + "and $0x00000F00, %%edx \n" + "or %%edx, %%ecx \n" + + "mov (%[src]), %%eax \n" // read second pixel + "add $4, %[src] \n" + "bswap %%eax \n" + "mov %%eax, %%edx \n" + + "shl $24, %%eax \n" // 0x000000F0 -> 0xF0000000 (a) + "and $0xF0000000, %%eax \n" + "or %%eax, %%ecx \n" // 0x00F00000 -> 0x00F00000 (g) + "mov %%edx, %%eax \n" + "and $0x00F00000, %%eax \n" + "or %%eax, %%ecx \n" + "rol $4, %%edx \n" // 0x0000F000 (did not shift) -> 0x000F0000 (b) + "mov %%edx, %%eax \n" + "and $0x000F0000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $24, %%edx \n" // 0xF0000000 went to 0x0000000F -> 0x0F000000 (r) + "and $0x0F000000, %%edx \n" + "or %%edx, %%ecx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // * + + "decl %[temp] \n" + "jnz x_loop9 \n" + + "decl %[height] \n" + "jz end_y_loop9 \n" + + "add %[line], %[src] \n" + "add %[ext], %[dst] \n" + + "mov %[wid_64], %%eax \n" + "mov %%eax, %[temp] \n" + "x_loop_29: \n" + "mov 8(%[src]), %%eax \n" // read first pixel + "bswap %%eax \n" + "mov %%eax, %%edx \n" + + "xor %%ecx, %%ecx \n" + "shl $8, %%eax \n" // 0x000000F0 -> 0x0000F000 (a) + "and $0x0000F000, %%eax \n" + "or %%eax, %%ecx \n" + "shr $12, %%edx \n" // 0x0000F000 -> 0x0000000F (b) + "mov %%edx, %%eax \n" + "and $0x0000000F, %%eax \n" + "or %%eax, %%ecx \n" + "shr $4, %%edx \n" // 0x00F00000 went to 0x00000F00 -> 0x000000F0 (g) + "mov %%edx, %%eax \n" + "and $0x000000F0, %%eax \n" + "or %%eax, %%ecx \n" + "shr $4, %%edx \n" // 0xF0000000 went to 0x000F0000 went to 0x0000F000 -> 0x00000F00 (r) + "and $0x00000F00, %%edx \n" + "or %%edx, %%ecx \n" + + "mov 12(%[src]), %%eax \n" // read second pixel + "bswap %%eax \n" + "mov %%eax, %%edx \n" + + "shl $24, %%eax \n" // 0x000000F0 -> 0xF0000000 (a) + "and $0xF0000000, %%eax \n" + "or %%eax, %%ecx \n" // 0x00F00000 -> 0x00F00000 (g) + "mov %%edx, %%eax \n" + "and $0x00F00000, %%eax \n" + "or %%eax, %%ecx \n" + "rol $4, %%edx \n" // 0x0000F000 (did not shift) -> 0x000F0000 (b) + "mov %%edx, %%eax \n" + "and $0x000F0000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $24, %%edx \n" // 0xF0000000 went to 0x0000000F -> 0x0F000000 (r) + "and $0x0F000000, %%edx \n" + "or %%edx, %%ecx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + + // * copy + "mov (%[src]), %%eax \n" // read first pixel + "bswap %%eax \n" + "mov %%eax, %%edx \n" + + "xor %%ecx, %%ecx \n" + "shl $8, %%eax \n" // 0x000000F0 -> 0x0000F000 (a) + "and $0x0000F000, %%eax \n" + "or %%eax, %%ecx \n" + "shr $12, %%edx \n" // 0x0000F000 -> 0x0000000F (b) + "mov %%edx, %%eax \n" + "and $0x0000000F, %%eax \n" + "or %%eax, %%ecx \n" + "shr $4, %%edx \n" // 0x00F00000 went to 0x00000F00 -> 0x000000F0 (g) + "mov %%edx, %%eax \n" + "and $0x000000F0, %%eax \n" + "or %%eax, %%ecx \n" + "shr $4, %%edx \n" // 0xF0000000 went to 0x000F0000 went to 0x0000F000 -> 0x00000F00 (r) + "and $0x00000F00, %%edx \n" + "or %%edx, %%ecx \n" + + "mov 4(%[src]), %%eax \n" // read second pixel + "add $16, %[src] \n" + "bswap %%eax \n" + "mov %%eax, %%edx \n" + + "shl $24, %%eax \n" // 0x000000F0 -> 0xF0000000 (a) + "and $0xF0000000, %%eax \n" + "or %%eax, %%ecx \n" // 0x00F00000 -> 0x00F00000 (g) + "mov %%edx, %%eax \n" + "and $0x00F00000, %%eax \n" + "or %%eax, %%ecx \n" + "rol $4, %%edx \n" // 0x0000F000 (did not shift) -> 0x000F0000 (b) + "mov %%edx, %%eax \n" + "and $0x000F0000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $24, %%edx \n" // 0xF0000000 went to 0x0000000F -> 0x0F000000 (r) + "and $0x0F000000, %%edx \n" + "or %%edx, %%ecx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // * + + "decl %[temp] \n" + "jnz x_loop_29 \n" + + "add %[line], %[src] \n" + "add %[ext], %[dst] \n" + + "decl %[height] \n" + "jnz y_loop9 \n" + + "end_y_loop9: \n" + : [temp]"=m"(lTemp), [src]"+S"(src), [dst]"+D"(dst), [height]"+g"(lHeight) + : [wid_64] "g" (wid_64), [line] "g" ((uintptr_t)line), [ext] "g" ((uintptr_t)ext) + : "memory", "cc", "ecx", "eax", "edx" + ); +#endif + return (1 << 16) | GR_TEXFMT_ARGB_4444; +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/TexLoad4b.h b/libmupen64plus/mupen64plus-video-glide64/src/TexLoad4b.h new file mode 100644 index 0000000000..76969cfe1d --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/TexLoad4b.h @@ -0,0 +1,3735 @@ +/* +* 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: 0, Format: 2 + +DWORD Load4bCI (unsigned char * dst, unsigned char * 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; + unsigned short * pal = (rdp.pal_8 + (rdp.tiles[tile].palette << 4)); + if (rdp.tlut_mode == 2) + { +#if !defined(__GNUC__) && !defined(NO_ASM) + __asm { + mov ebx,dword ptr [pal] + + mov esi,dword ptr [src] + mov edi,dword ptr [dst] + + mov ecx,dword ptr [height] +y_loop: + push ecx + + mov ecx,dword ptr [wid_64] +x_loop: + push ecx + + mov eax,dword ptr [esi] // read all 8 pixels + bswap eax + add esi,4 + mov edx,eax + + // 1st dword output { + shr eax,23 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + mov eax,edx + shr eax,27 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword output { + mov eax,edx + shr eax,15 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + mov eax,edx + shr eax,19 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 3rd dword output { + mov eax,edx + shr eax,7 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + mov eax,edx + shr eax,11 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 4th dword output { + mov eax,edx + shl eax,1 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + shr edx,3 + and edx,0x1E + mov cx,word ptr [ebx+edx] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // * copy + mov eax,dword ptr [esi] // read all 8 pixels + bswap eax + add esi,4 + mov edx,eax + + // 1st dword output { + shr eax,23 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + mov eax,edx + shr eax,27 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword output { + mov eax,edx + shr eax,15 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + mov eax,edx + shr eax,19 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 3rd dword output { + mov eax,edx + shr eax,7 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + mov eax,edx + shr eax,11 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 4th dword output { + mov eax,edx + shl eax,1 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + shr edx,3 + and edx,0x1E + mov cx,word ptr [ebx+edx] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + // * + + pop ecx + + dec ecx + jnz x_loop + + pop ecx + dec ecx + jz end_y_loop + push ecx + + add esi,dword ptr [line] + add edi,dword ptr [ext] + + mov ecx,dword ptr [wid_64] +x_loop_2: + push ecx + + mov eax,dword ptr [esi+4] // read all 8 pixels + bswap eax + mov edx,eax + + // 1st dword output { + shr eax,23 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + mov eax,edx + shr eax,27 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword output { + mov eax,edx + shr eax,15 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + mov eax,edx + shr eax,19 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 3rd dword output { + mov eax,edx + shr eax,7 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + mov eax,edx + shr eax,11 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 4th dword output { + mov eax,edx + shl eax,1 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + shr edx,3 + and edx,0x1E + mov cx,word ptr [ebx+edx] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // * copy + mov eax,dword ptr [esi] // read all 8 pixels + bswap eax + add esi,8 + mov edx,eax + + // 1st dword output { + shr eax,23 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + mov eax,edx + shr eax,27 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword output { + mov eax,edx + shr eax,15 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + mov eax,edx + shr eax,19 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 3rd dword output { + mov eax,edx + shr eax,7 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + mov eax,edx + shr eax,11 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 4th dword output { + mov eax,edx + shl eax,1 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + shr edx,3 + and edx,0x1E + mov cx,word ptr [ebx+edx] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + // * + + pop ecx + + dec ecx + jnz x_loop_2 + + add esi,dword ptr [line] + add edi,dword ptr [ext] + + pop ecx + dec ecx + jnz y_loop + +end_y_loop: + } +#elif !defined(NO_ASM) + //printf("Load4bCI1\n"); + // This way, gcc generates either a 32 bit or a 64 bit register + long lTempX, lTempY, lHeight = (long) height; + intptr_t fake_eax, fake_edx; + asm volatile ( + "1: \n" // y_loop + "mov %[c], %[tempy] \n" + + "mov %[wid_64], %%ecx \n" + "2: \n" // x_loop + "mov %[c], %[tempx] \n" + + "mov (%[src]), %%eax \n" // read all 8 pixels + "bswap %%eax \n" + "add $4, %[src] \n" + "mov %%eax, %%edx \n" + + // 1st dword output { + "shr $23, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $27, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword output { + "mov %%edx, %%eax \n" + "shr $15, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $19, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 3rd dword output { + "mov %%edx, %%eax \n" + "shr $7,%%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]),%%cx \n" + "ror $1,%%cx \n" + "shl $16,%%ecx \n" + + "mov %%edx, %%eax \n" + "shr $11, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 4th dword output { + "mov %%edx, %%eax \n" + "shl $1, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + "shl $16, %%ecx \n" + + "shr $3, %%edx \n" + "and $0x1E, %%edx \n" + "mov (%[pal],%[d]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // * copy + "mov (%[src]), %%eax \n" // read all 8 pixels + "bswap %%eax \n" + "add $4, %[src] \n" + "mov %%eax, %%edx \n" + + // 1st dword output { + "shr $23, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $27, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword output { + "mov %%edx, %%eax \n" + "shr $15, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $19, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 3rd dword output { + "mov %%edx, %%eax \n" + "shr $7, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $11, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 4th dword output { + "mov %%edx, %%eax \n" + "shl $1, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + "shl $16, %%ecx \n" + + "shr $3, %%edx \n" + "and $0x1E, %%edx \n" + "mov (%[pal],%[d]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + // * + + "mov %[tempx], %[c] \n" + + "dec %%ecx \n" + "jnz 2b \n" // x_loop + + "mov %[tempy], %[c] \n" + "dec %%ecx \n" + "jz 4f \n" // end_y_loop + "mov %[c], %[tempy] \n" + + "add %[line], %[src] \n" + "add %[ext], %[dst] \n" + + "mov %[wid_64], %%ecx \n" + "3: \n" // x_loop_2 + "mov %[c], %[tempx] \n" + + "mov 4(%[src]), %%eax \n" // read all 8 pixels + "bswap %%eax \n" + "mov %%eax, %%edx \n" + + // 1st dword output { + "shr $23, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $27, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword output { + "mov %%edx, %%eax \n" + "shr $15, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $19, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 3rd dword output { + "mov %%edx, %%eax \n" + "shr $7, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $11, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 4th dword output { + "mov %%edx, %%eax \n" + "shl $1, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + "shl $16, %%ecx \n" + + "shr $3, %%edx \n" + "and $0x1E, %%edx \n" + "mov (%[pal],%[d]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // * copy + "mov (%[src]), %%eax \n" // read all 8 pixels + "bswap %%eax \n" + "add $8, %[src] \n" + "mov %%eax, %%edx \n" + + // 1st dword output { + "shr $23, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $27, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword output { + "mov %%edx, %%eax \n" + "shr $15, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $19, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 3rd dword output { + "mov %%edx, %%eax \n" + "shr $7, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $11, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 4th dword output { + "mov %%edx, %%eax \n" + "shl $1, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + "shl $16, %%ecx \n" + + "shr $3, %%edx \n" + "and $0x1E, %%edx \n" + "mov (%[pal],%[d]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + // * + + "mov %[tempx], %[c] \n" + + "dec %%ecx \n" + "jnz 3b \n" // x_loop_2 + + "add %[line], %[src] \n" + "add %[ext], %[dst] \n" + + "mov %[tempy], %[c] \n" + "dec %%ecx \n" + "jnz 1b \n" // y_loop + + "4: \n" // end_y_loop + : [tempx]"=m"(lTempX), [tempy]"=m"(lTempY), [a] "=&a"(fake_eax), [d] "=&d"(fake_edx), [src] "+S"(src), [dst] "+D"(dst), [c] "+c"(lHeight) + // pal needs to be in a register because its used in mov (%[pal],...), ... + : [pal] "r" (pal), [wid_64] "g" (wid_64), [line] "g" ((uintptr_t)line), [ext] "g" ((uintptr_t)ext) + : "memory", "cc" + ); +#endif + } + else + { +#if !defined(__GNUC__) && !defined(NO_ASM) + __asm { + mov ebx,dword ptr [pal] + + mov esi,dword ptr [src] + mov edi,dword ptr [dst] + + mov ecx,dword ptr [height] +ia_y_loop: + push ecx + + mov ecx,dword ptr [wid_64] +ia_x_loop: + push ecx + + mov eax,dword ptr [esi] // read all 8 pixels + bswap eax + add esi,4 + mov edx,eax + + // 1st dword output { + shr eax,23 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + mov eax,edx + shr eax,27 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword output { + mov eax,edx + shr eax,15 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + mov eax,edx + shr eax,19 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 3rd dword output { + mov eax,edx + shr eax,7 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + mov eax,edx + shr eax,11 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 4th dword output { + mov eax,edx + shl eax,1 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + shr edx,3 + and edx,0x1E + mov cx,word ptr [ebx+edx] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // * copy + mov eax,dword ptr [esi] // read all 8 pixels + bswap eax + add esi,4 + mov edx,eax + + // 1st dword output { + shr eax,23 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + mov eax,edx + shr eax,27 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword output { + mov eax,edx + shr eax,15 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + mov eax,edx + shr eax,19 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 3rd dword output { + mov eax,edx + shr eax,7 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + mov eax,edx + shr eax,11 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 4th dword output { + mov eax,edx + shl eax,1 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + shr edx,3 + and edx,0x1E + mov cx,word ptr [ebx+edx] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + // * + + pop ecx + + dec ecx + jnz ia_x_loop + + pop ecx + dec ecx + jz ia_end_y_loop + push ecx + + add esi,dword ptr [line] + add edi,dword ptr [ext] + + mov ecx,dword ptr [wid_64] +ia_x_loop_2: + push ecx + + mov eax,dword ptr [esi+4] // read all 8 pixels + bswap eax + mov edx,eax + + // 1st dword output { + shr eax,23 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + mov eax,edx + shr eax,27 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword output { + mov eax,edx + shr eax,15 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + mov eax,edx + shr eax,19 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 3rd dword output { + mov eax,edx + shr eax,7 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + mov eax,edx + shr eax,11 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 4th dword output { + mov eax,edx + shl eax,1 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + shr edx,3 + and edx,0x1E + mov cx,word ptr [ebx+edx] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // * copy + mov eax,dword ptr [esi] // read all 8 pixels + bswap eax + add esi,8 + mov edx,eax + + // 1st dword output { + shr eax,23 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + mov eax,edx + shr eax,27 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword output { + mov eax,edx + shr eax,15 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + mov eax,edx + shr eax,19 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 3rd dword output { + mov eax,edx + shr eax,7 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + mov eax,edx + shr eax,11 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 4th dword output { + mov eax,edx + shl eax,1 + and eax,0x1E + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + shr edx,3 + and edx,0x1E + mov cx,word ptr [ebx+edx] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + // * + + pop ecx + + dec ecx + jnz ia_x_loop_2 + + add esi,dword ptr [line] + add edi,dword ptr [ext] + + pop ecx + dec ecx + jnz ia_y_loop + +ia_end_y_loop: + } +#elif !defined(NO_ASM) + //printf("Load4bCI2\n"); + long lTempX, lTempY, lHeight = (long) height; + intptr_t fake_eax, fake_edx; + asm volatile ( + "1: \n" // ia_y_loop + "mov %[c], %[tempy] \n" + + "mov %[wid_64], %%ecx \n" + "2: \n" // ia_x_loop + "mov %[c], %[tempx] \n" + + "mov (%[src]), %%eax \n" // read all 8 pixels + "bswap %%eax \n" + "add $4, %[src] \n" + "mov %%eax, %%edx \n" + + // 1st dword output { + "shr $23, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $27, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword output { + "mov %%edx, %%eax \n" + "shr $15, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $19, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 3rd dword output { + "mov %%edx, %%eax \n" + "shr $7, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $11, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 4th dword output { + "mov %%edx, %%eax \n" + "shl $1, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + "shl $16, %%ecx \n" + + "shr $3, %%edx \n" + "and $0x1E, %%edx \n" + "mov (%[pal],%[d]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // * copy + "mov (%[src]), %%eax \n" // read all 8 pixels + "bswap %%eax \n" + "add $4, %[src] \n" + "mov %%eax, %%edx \n" + + // 1st dword output { + "shr $23, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $27, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword output { + "mov %%edx, %%eax \n" + "shr $15, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $19, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 3rd dword output { + "mov %%edx, %%eax \n" + "shr $7, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8,%%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $11, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 4th dword output { + "mov %%edx, %%eax \n" + "shl $1, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + "shl $16, %%ecx \n" + + "shr $3, %%edx \n" + "and $0x1E, %%edx \n" + "mov (%[pal],%[d]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + // * + + "mov %[tempx], %[c] \n" + + "dec %%ecx \n" + "jnz 2b \n" // ia_x_loop + + "mov %[tempy], %[c] \n" + "dec %%ecx \n" + "jz 4f \n" // ia_end_y_loop + "mov %[c], %[tempy] \n" + + "add %[line], %[src] \n" + "add %[ext], %[dst] \n" + + "mov %[wid_64], %%ecx \n" + "3: \n" // ia_x_loop_2 + "mov %[c], %[tempx] \n" + + "mov 4(%[src]), %%eax \n" // read all 8 pixels + "bswap %%eax \n" + "mov %%eax, %%edx \n" + + // 1st dword output { + "shr $23, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $27, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword output { + "mov %%edx, %%eax \n" + "shr $15, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $19, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 3rd dword output { + "mov %%edx, %%eax \n" + "shr $7, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $11, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 4th dword output { + "mov %%edx, %%eax \n" + "shl $1, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + "shl $16, %%ecx \n" + + "shr $3, %%edx \n" + "and $0x1E, %%edx \n" + "mov (%[pal],%[d]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // * copy + "mov (%[src]), %%eax \n" // read all 8 pixels + "bswap %%eax \n" + "add $8, %[src] \n" + "mov %%eax, %%edx \n" + + // 1st dword output { + "shr $23, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $27, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword output { + "mov %%edx, %%eax \n" + "shr $15, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $19, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 3rd dword output { + "mov %%edx, %%eax \n" + "shr $7, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $11, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 4th dword output { + "mov %%edx, %%eax \n" + "shl $1, %%eax \n" + "and $0x1E, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + "shl $16, %%ecx \n" + + "shr $3, %%edx \n" + "and $0x1E, %%edx \n" + "mov (%[pal],%[d]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + // * + + "mov %[tempx], %[c] \n" + + "dec %%ecx \n" + "jnz 3b \n" // ia_x_loop_2 + + "add %[line], %[src] \n" + "add %[ext], %[dst] \n" + + "mov %[tempy], %[c] \n" + "dec %%ecx \n" + "jnz 1b \n" // ia_y_loop + + "4: \n" // ia_end_y_loop + : [tempx]"=m"(lTempX), [tempy]"=m"(lTempY), [a] "=&a"(fake_eax), [d] "=&d"(fake_edx), [src] "+S"(src), [dst] "+D"(dst), [c] "+c"(lHeight) + // pal needs to be in a register because its used in mov (%[pal],...), ... + : [pal] "r" (pal), [wid_64] "g" (wid_64), [line] "g" ((uintptr_t)line), [ext] "g" ((uintptr_t)ext) + : "memory", "cc" + ); +#endif + return (1 << 16) | GR_TEXFMT_ALPHA_INTENSITY_88; + } + + return (1 << 16) | GR_TEXFMT_ARGB_1555; +} + +//**************************************************************** +// Size: 0, Format: 3 +// +// ** BY GUGAMAN ** + +DWORD 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 !defined(__GNUC__) && !defined(NO_ASM) + __asm { + mov esi,dword ptr [src] + mov edi,dword ptr [dst] + + mov ecx,dword ptr [height] +y_loop: + push ecx + + mov ecx,dword ptr [wid_64] +x_loop: + push ecx + + mov eax,dword ptr [esi] // read all 8 pixels + bswap eax + add esi,4 + mov edx,eax + + // 1st dword { + xor ecx,ecx + + // pixel #1 + // IIIAxxxxxxxxxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxxxxxxxxxAAAAIIII + mov eax,edx + shr eax,24 //Alpha + and eax,0x00000010 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shr eax,28 // Intensity + and eax,0x0000000E + or ecx,eax + shr eax,3 + or ecx,eax + + // pixel #2 + // xxxxIIIAxxxxxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxAAAAIIIIxxxxxxxx + mov eax,edx + shr eax,12 //Alpha + and eax,0x00001000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shr eax,16 // Intensity + and eax,0x00000E00 + or ecx,eax + shr eax,3 + and eax,0x00000100 + or ecx,eax + + // pixel #3 + // xxxxxxxxIIIAxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxAAAAIIIIxxxxxxxxxxxxxxxx + //Alpha + mov eax,edx + and eax,0x00100000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shr eax,4 // Intensity + and eax,0x000E0000 + or ecx,eax + shr eax,3 + and eax,0x00010000 + or ecx,eax + + // pixel #4 + // xxxxxxxxxxxxIIIAxxxxxxxxxxxxxxxx + // AAAAIIIIxxxxxxxxxxxxxxxxxxxxxxxx + mov eax,edx + shl eax,12 //Alpha + and eax,0x10000000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shl eax,8 // Intensity + and eax,0x0E000000 + or ecx,eax + shr eax,3 + and eax,0x01000000 + or ecx,eax + + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword { + xor ecx,ecx + + // pixel #5 + // xxxxxxxxxxxxxxxxIIIAxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxxxxxxxxxAAAAIIII + mov eax,edx + shr eax,8 //Alpha + and eax,0x00000010 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shr eax,12 // Intensity + and eax,0x0000000E + or ecx,eax + shr eax,3 + or ecx,eax + + // pixel #6 + // xxxxxxxxxxxxxxxxxxxxIIIAxxxxxxxx + // xxxxxxxxxxxxxxxxAAAAIIIIxxxxxxxx + //Alpha + mov eax,edx + shl eax,4 + and eax,0x00001000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx // Intensity + and eax,0x00000E00 + or ecx,eax + shr eax,3 + and eax,0x00000100 + or ecx,eax + + // pixel #7 + // xxxxxxxxxxxxxxxxxxxxxxxxIIIAxxxx + // xxxxxxxxAAAAIIIIxxxxxxxxxxxxxxxx + //Alpha + mov eax,edx + shl eax,16 + and eax,0x00100000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shl eax,12 // Intensity + and eax,0x000E0000 + or ecx,eax + shr eax,3 + and eax,0x00010000 + or ecx,eax + + // pixel #8 + // xxxxxxxxxxxxxxxxxxxxxxxxxxxxIIIA + // AAAAIIIIxxxxxxxxxxxxxxxxxxxxxxxx + mov eax,edx + shl eax,28 //Alpha + and eax,0x10000000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shl eax,24 // Intensity + and eax,0x0E000000 + or ecx,eax + shr eax,3 + and eax,0x01000000 + or ecx,eax + + mov dword ptr [edi],ecx + add edi,4 + // } + + // * copy + mov eax,dword ptr [esi] // read all 8 pixels + bswap eax + add esi,4 + mov edx,eax + + // 1st dword { + xor ecx,ecx + + // pixel #1 + // IIIAxxxxxxxxxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxxxxxxxxxAAAAIIII + mov eax,edx + shr eax,24 //Alpha + and eax,0x00000010 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shr eax,28 // Intensity + and eax,0x0000000E + or ecx,eax + shr eax,3 + or ecx,eax + + // pixel #2 + // xxxxIIIAxxxxxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxAAAAIIIIxxxxxxxx + mov eax,edx + shr eax,12 //Alpha + and eax,0x00001000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shr eax,16 // Intensity + and eax,0x00000E00 + or ecx,eax + shr eax,3 + and eax,0x00000100 + or ecx,eax + + // pixel #3 + // xxxxxxxxIIIAxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxAAAAIIIIxxxxxxxxxxxxxxxx + //Alpha + mov eax,edx + and eax,0x00100000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shr eax,4 // Intensity + and eax,0x000E0000 + or ecx,eax + shr eax,3 + and eax,0x00010000 + or ecx,eax + + // pixel #4 + // xxxxxxxxxxxxIIIAxxxxxxxxxxxxxxxx + // AAAAIIIIxxxxxxxxxxxxxxxxxxxxxxxx + mov eax,edx + shl eax,12 //Alpha + and eax,0x10000000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shl eax,8 // Intensity + and eax,0x0E000000 + or ecx,eax + shr eax,3 + and eax,0x01000000 + or ecx,eax + + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword { + xor ecx,ecx + + // pixel #5 + // xxxxxxxxxxxxxxxxIIIAxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxxxxxxxxxAAAAIIII + mov eax,edx + shr eax,8 //Alpha + and eax,0x00000010 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shr eax,12 // Intensity + and eax,0x0000000E + or ecx,eax + shr eax,3 + or ecx,eax + + // pixel #6 + // xxxxxxxxxxxxxxxxxxxxIIIAxxxxxxxx + // xxxxxxxxxxxxxxxxAAAAIIIIxxxxxxxx + //Alpha + mov eax,edx + shl eax,4 + and eax,0x00001000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx // Intensity + and eax,0x00000E00 + or ecx,eax + shr eax,3 + and eax,0x00000100 + or ecx,eax + + // pixel #7 + // xxxxxxxxxxxxxxxxxxxxxxxxIIIAxxxx + // xxxxxxxxAAAAIIIIxxxxxxxxxxxxxxxx + //Alpha + mov eax,edx + shl eax,16 + and eax,0x00100000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shl eax,12 // Intensity + and eax,0x000E0000 + or ecx,eax + shr eax,3 + and eax,0x00010000 + or ecx,eax + + // pixel #8 + // xxxxxxxxxxxxxxxxxxxxxxxxxxxxIIIA + // AAAAIIIIxxxxxxxxxxxxxxxxxxxxxxxx + mov eax,edx + shl eax,28 //Alpha + and eax,0x10000000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shl eax,24 // Intensity + and eax,0x0E000000 + or ecx,eax + shr eax,3 + and eax,0x01000000 + or ecx,eax + + mov dword ptr [edi],ecx + add edi,4 + // } + + // * + + pop ecx + dec ecx + jnz x_loop + + pop ecx + dec ecx + jz end_y_loop + push ecx + + add esi,dword ptr [line] + add edi,dword ptr [ext] + + mov ecx,dword ptr [wid_64] +x_loop_2: + push ecx + + mov eax,dword ptr [esi+4] // read all 8 pixels + bswap eax + mov edx,eax + + // 1st dword { + xor ecx,ecx + + // pixel #1 + // IIIAxxxxxxxxxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxxxxxxxxxAAAAIIII + mov eax,edx + shr eax,24 //Alpha + and eax,0x00000010 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shr eax,28 // Intensity + and eax,0x0000000E + or ecx,eax + shr eax,3 + or ecx,eax + + // pixel #2 + // xxxxIIIAxxxxxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxAAAAIIIIxxxxxxxx + mov eax,edx + shr eax,12 //Alpha + and eax,0x00001000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shr eax,16 // Intensity + and eax,0x00000E00 + or ecx,eax + shr eax,3 + and eax,0x00000100 + or ecx,eax + + // pixel #3 + // xxxxxxxxIIIAxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxAAAAIIIIxxxxxxxxxxxxxxxx + //Alpha + mov eax,edx + and eax,0x00100000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shr eax,4 // Intensity + and eax,0x000E0000 + or ecx,eax + shr eax,3 + and eax,0x00010000 + or ecx,eax + + // pixel #4 + // xxxxxxxxxxxxIIIAxxxxxxxxxxxxxxxx + // AAAAIIIIxxxxxxxxxxxxxxxxxxxxxxxx + mov eax,edx + shl eax,12 //Alpha + and eax,0x10000000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shl eax,8 // Intensity + and eax,0x0E000000 + or ecx,eax + shr eax,3 + and eax,0x01000000 + or ecx,eax + + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword { + xor ecx,ecx + + // pixel #5 + // xxxxxxxxxxxxxxxxIIIAxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxxxxxxxxxAAAAIIII + mov eax,edx + shr eax,8 //Alpha + and eax,0x00000010 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shr eax,12 // Intensity + and eax,0x0000000E + or ecx,eax + shr eax,3 + or ecx,eax + + // pixel #6 + // xxxxxxxxxxxxxxxxxxxxIIIAxxxxxxxx + // xxxxxxxxxxxxxxxxAAAAIIIIxxxxxxxx + //Alpha + mov eax,edx + shl eax,4 + and eax,0x00001000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx // Intensity + and eax,0x00000E00 + or ecx,eax + shr eax,3 + and eax,0x00000100 + or ecx,eax + + // pixel #7 + // xxxxxxxxxxxxxxxxxxxxxxxxIIIAxxxx + // xxxxxxxxAAAAIIIIxxxxxxxxxxxxxxxx + //Alpha + mov eax,edx + shl eax,16 + and eax,0x00100000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shl eax,12 // Intensity + and eax,0x000E0000 + or ecx,eax + shr eax,3 + and eax,0x00010000 + or ecx,eax + + // pixel #8 + // xxxxxxxxxxxxxxxxxxxxxxxxxxxxIIIA + // AAAAIIIIxxxxxxxxxxxxxxxxxxxxxxxx + mov eax,edx + shl eax,28 //Alpha + and eax,0x10000000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shl eax,24 // Intensity + and eax,0x0E000000 + or ecx,eax + shr eax,3 + and eax,0x01000000 + or ecx,eax + + mov dword ptr [edi],ecx + add edi,4 + // } + + // * copy + mov eax,dword ptr [esi] // read all 8 pixels + bswap eax + add esi,8 + mov edx,eax + +// 1st dword { + xor ecx,ecx + + // pixel #1 + // IIIAxxxxxxxxxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxxxxxxxxxAAAAIIII + mov eax,edx + shr eax,24 //Alpha + and eax,0x00000010 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shr eax,28 // Intensity + and eax,0x0000000E + or ecx,eax + shr eax,3 + or ecx,eax + + // pixel #2 + // xxxxIIIAxxxxxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxAAAAIIIIxxxxxxxx + mov eax,edx + shr eax,12 //Alpha + and eax,0x00001000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shr eax,16 // Intensity + and eax,0x00000E00 + or ecx,eax + shr eax,3 + and eax,0x00000100 + or ecx,eax + + // pixel #3 + // xxxxxxxxIIIAxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxAAAAIIIIxxxxxxxxxxxxxxxx + //Alpha + mov eax,edx + and eax,0x00100000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shr eax,4 // Intensity + and eax,0x000E0000 + or ecx,eax + shr eax,3 + and eax,0x00010000 + or ecx,eax + + // pixel #4 + // xxxxxxxxxxxxIIIAxxxxxxxxxxxxxxxx + // AAAAIIIIxxxxxxxxxxxxxxxxxxxxxxxx + mov eax,edx + shl eax,12 //Alpha + and eax,0x10000000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shl eax,8 // Intensity + and eax,0x0E000000 + or ecx,eax + shr eax,3 + and eax,0x01000000 + or ecx,eax + + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword { + xor ecx,ecx + + // pixel #5 + // xxxxxxxxxxxxxxxxIIIAxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxxxxxxxxxAAAAIIII + mov eax,edx + shr eax,8 //Alpha + and eax,0x00000010 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shr eax,12 // Intensity + and eax,0x0000000E + or ecx,eax + shr eax,3 + or ecx,eax + + // pixel #6 + // xxxxxxxxxxxxxxxxxxxxIIIAxxxxxxxx + // xxxxxxxxxxxxxxxxAAAAIIIIxxxxxxxx + //Alpha + mov eax,edx + shl eax,4 + and eax,0x00001000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx // Intensity + and eax,0x00000E00 + or ecx,eax + shr eax,3 + and eax,0x00000100 + or ecx,eax + + // pixel #7 + // xxxxxxxxxxxxxxxxxxxxxxxxIIIAxxxx + // xxxxxxxxAAAAIIIIxxxxxxxxxxxxxxxx + //Alpha + mov eax,edx + shl eax,16 + and eax,0x00100000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shl eax,12 // Intensity + and eax,0x000E0000 + or ecx,eax + shr eax,3 + and eax,0x00010000 + or ecx,eax + + // pixel #8 + // xxxxxxxxxxxxxxxxxxxxxxxxxxxxIIIA + // AAAAIIIIxxxxxxxxxxxxxxxxxxxxxxxx + mov eax,edx + shl eax,28 //Alpha + and eax,0x10000000 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + shl eax,1 + or ecx,eax + mov eax,edx + shl eax,24 // Intensity + and eax,0x0E000000 + or ecx,eax + shr eax,3 + and eax,0x01000000 + or ecx,eax + + mov dword ptr [edi],ecx + add edi,4 + // } + // * + + pop ecx + dec ecx + jnz x_loop_2 + + add esi,dword ptr [line] + add edi,dword ptr [ext] + + pop ecx + dec ecx + jnz y_loop + +end_y_loop: + } +#elif !defined(NO_ASM) + //printf("Load4bIA\n"); + long lTempX, lTempY, lHeight = (long) height; + asm volatile ( + "1: \n" // y_loop2 + "mov %[c], %[tempy] \n" + + "mov %[wid_64], %%ecx \n" + "2: \n" // x_loop2 + "mov %[c], %[tempx] \n" + + "mov (%[src]), %%eax \n" // read all 8 pixels + "bswap %%eax \n" + "add $4, %[src] \n" + "mov %%eax, %%edx \n" + + // 1st dword { + "xor %%ecx, %%ecx \n" + + // pixel #1 + // IIIAxxxxxxxxxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxxxxxxxxxAAAAIIII + "mov %%edx, %%eax \n" + "shr $24, %%eax \n" //Alpha + "and $0x00000010, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shr $28, %%eax \n" // Intensity + "and $0x0000000E, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #2 + // xxxxIIIAxxxxxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxAAAAIIIIxxxxxxxx + "mov %%edx, %%eax \n" + "shr $12, %%eax \n" //Alpha + "and $0x00001000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shr $16, %%eax \n" // Intensity + "and $0x00000E00, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x00000100, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #3 + // xxxxxxxxIIIAxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxAAAAIIIIxxxxxxxxxxxxxxxx + //Alpha + "mov %%edx, %%eax \n" + "and $0x00100000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shr $4, %%eax \n" // Intensity + "and $0x000E0000, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x00010000, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #4 + // xxxxxxxxxxxxIIIAxxxxxxxxxxxxxxxx + // AAAAIIIIxxxxxxxxxxxxxxxxxxxxxxxx + "mov %%edx, %%eax \n" + "shl $12, %%eax \n" //Alpha + "and $0x10000000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shl $8, %%eax \n" // Intensity + "and $0x0E000000, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x01000000, %%eax \n" + "or %%eax, %%ecx \n" + + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword { + "xor %%ecx, %%ecx \n" + + // pixel #5 + // xxxxxxxxxxxxxxxxIIIAxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxxxxxxxxxAAAAIIII + "mov %%edx, %%eax \n" + "shr $8, %%eax \n" //Alpha + "and $0x00000010, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shr $12, %%eax \n" // Intensity + "and $0x0000000E, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #6 + // xxxxxxxxxxxxxxxxxxxxIIIAxxxxxxxx + // xxxxxxxxxxxxxxxxAAAAIIIIxxxxxxxx + //Alpha + "mov %%edx, %%eax \n" + "shl $4, %%eax \n" + "and $0x00001000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" // Intensity + "and $0x00000E00, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x00000100, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #7 + // xxxxxxxxxxxxxxxxxxxxxxxxIIIAxxxx + // xxxxxxxxAAAAIIIIxxxxxxxxxxxxxxxx + //Alpha + "mov %%edx, %%eax \n" + "shl $16, %%eax \n" + "and $0x00100000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shl $12, %%eax \n" // Intensity + "and $0x000E0000, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x00010000, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #8 + // xxxxxxxxxxxxxxxxxxxxxxxxxxxxIIIA + // AAAAIIIIxxxxxxxxxxxxxxxxxxxxxxxx + "mov %%edx, %%eax \n" + "shl $28, %%eax \n" //Alpha + "and $0x10000000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shl $24, %%eax \n" // Intensity + "and $0x0E000000, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x01000000, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // * copy + "mov (%[src]), %%eax \n" // read all 8 pixels + "bswap %%eax \n" + "add $4, %[src] \n" + "mov %%eax, %%edx \n" + + // 1st dword { + "xor %%ecx, %%ecx \n" + + // pixel #1 + // IIIAxxxxxxxxxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxxxxxxxxxAAAAIIII + "mov %%edx, %%eax \n" + "shr $24, %%eax \n" //Alpha + "and $0x00000010, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shr $28, %%eax \n" // Intensity + "and $0x0000000E, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #2 + // xxxxIIIAxxxxxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxAAAAIIIIxxxxxxxx + "mov %%edx, %%eax \n" + "shr $12, %%eax \n" //Alpha + "and $0x00001000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shr $16, %%eax \n" // Intensity + "and $0x00000E00, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x00000100, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #3 + // xxxxxxxxIIIAxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxAAAAIIIIxxxxxxxxxxxxxxxx + //Alpha + "mov %%edx, %%eax \n" + "and $0x00100000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shr $4, %%eax \n" // Intensity + "and $0x000E0000, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x00010000, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #4 + // xxxxxxxxxxxxIIIAxxxxxxxxxxxxxxxx + // AAAAIIIIxxxxxxxxxxxxxxxxxxxxxxxx + "mov %%edx, %%eax \n" + "shl $12, %%eax \n" //Alpha + "and $0x10000000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shl $8, %%eax \n" // Intensity + "and $0x0E000000, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x01000000, %%eax \n" + "or %%eax, %%ecx \n" + + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword { + "xor %%ecx, %%ecx \n" + + // pixel #5 + // xxxxxxxxxxxxxxxxIIIAxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxxxxxxxxxAAAAIIII + "mov %%edx, %%eax \n" + "shr $8, %%eax \n" //Alpha + "and $0x00000010, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shr $12, %%eax \n" // Intensity + "and $0x0000000E, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #6 + // xxxxxxxxxxxxxxxxxxxxIIIAxxxxxxxx + // xxxxxxxxxxxxxxxxAAAAIIIIxxxxxxxx + //Alpha + "mov %%edx, %%eax \n" + "shl $4, %%eax \n" + "and $0x00001000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" // Intensity + "and $0x00000E00, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x00000100, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #7 + // xxxxxxxxxxxxxxxxxxxxxxxxIIIAxxxx + // xxxxxxxxAAAAIIIIxxxxxxxxxxxxxxxx + //Alpha + "mov %%edx, %%eax \n" + "shl $16, %%eax \n" + "and $0x00100000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shl $12, %%eax \n" // Intensity + "and $0x000E0000, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x00010000, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #8 + // xxxxxxxxxxxxxxxxxxxxxxxxxxxxIIIA + // AAAAIIIIxxxxxxxxxxxxxxxxxxxxxxxx + "mov %%edx, %%eax \n" + "shl $28, %%eax \n" //Alpha + "and $0x10000000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shl $24, %%eax \n" // Intensity + "and $0x0E000000, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x01000000, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // * + + "mov %[tempx], %[c] \n" + "dec %%ecx \n" + "jnz 2b \n" // x_loop2 + + "mov %[tempy], %[c] \n" + "dec %%ecx \n" + "jz 4f \n" // end_y_loop2 + "mov %[c], %[tempy] \n" + + "add %[line], %[src] \n" + "add %[ext], %[dst] \n" + + "mov %[wid_64], %%ecx \n" + "3: \n" // x_loop_22 + "mov %[c], %[tempx] \n" + + "mov 4(%[src]), %%eax \n" // read all 8 pixels + "bswap %%eax \n" + "mov %%eax, %%edx \n" + + // 1st dword { + "xor %%ecx, %%ecx \n" + + // pixel #1 + // IIIAxxxxxxxxxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxxxxxxxxxAAAAIIII + "mov %%edx, %%eax \n" + "shr $24, %%eax \n" //Alpha + "and $0x00000010, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shr $28, %%eax \n" // Intensity + "and $0x0000000E, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #2 + // xxxxIIIAxxxxxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxAAAAIIIIxxxxxxxx + "mov %%edx, %%eax \n" + "shr $12, %%eax \n" //Alpha + "and $0x00001000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shr $16, %%eax \n" // Intensity + "and $0x00000E00, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x00000100, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #3 + // xxxxxxxxIIIAxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxAAAAIIIIxxxxxxxxxxxxxxxx + //Alpha + "mov %%edx, %%eax \n" + "and $0x00100000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shr $4, %%eax \n" // Intensity + "and $0x000E0000, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x00010000, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #4 + // xxxxxxxxxxxxIIIAxxxxxxxxxxxxxxxx + // AAAAIIIIxxxxxxxxxxxxxxxxxxxxxxxx + "mov %%edx, %%eax \n" + "shl $12, %%eax \n" //Alpha + "and $0x10000000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shl $8, %%eax \n" // Intensity + "and $0x0E000000, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x01000000, %%eax \n" + "or %%eax, %%ecx \n" + + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword { + "xor %%ecx, %%ecx \n" + + // pixel #5 + // xxxxxxxxxxxxxxxxIIIAxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxxxxxxxxxAAAAIIII + "mov %%edx, %%eax \n" + "shr $8, %%eax \n" //Alpha + "and $0x00000010, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shr $12, %%eax \n" // Intensity + "and $0x0000000E, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #6 + // xxxxxxxxxxxxxxxxxxxxIIIAxxxxxxxx + // xxxxxxxxxxxxxxxxAAAAIIIIxxxxxxxx + //Alpha + "mov %%edx, %%eax \n" + "shl $4, %%eax \n" + "and $0x00001000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" // Intensity + "and $0x00000E00, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x00000100, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #7 + // xxxxxxxxxxxxxxxxxxxxxxxxIIIAxxxx + // xxxxxxxxAAAAIIIIxxxxxxxxxxxxxxxx + //Alpha + "mov %%edx, %%eax \n" + "shl $16, %%eax \n" + "and $0x00100000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shl $12, %%eax \n" // Intensity + "and $0x000E0000, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x00010000, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #8 + // xxxxxxxxxxxxxxxxxxxxxxxxxxxxIIIA + // AAAAIIIIxxxxxxxxxxxxxxxxxxxxxxxx + "mov %%edx, %%eax \n" + "shl $28, %%eax \n" //Alpha + "and $0x10000000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shl $24, %%eax \n" // Intensity + "and $0x0E000000, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x01000000, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // * copy + "mov (%[src]), %%eax \n" // read all 8 pixels + "bswap %%eax \n" + "add $8, %[src] \n" + "mov %%eax, %%edx \n" + + // 1st dword { + "xor %%ecx, %%ecx \n" + + // pixel #1 + // IIIAxxxxxxxxxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxxxxxxxxxAAAAIIII + "mov %%edx, %%eax \n" + "shr $24, %%eax \n" //Alpha + "and $0x00000010, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shr $28, %%eax \n" // Intensity + "and $0x0000000E, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #2 + // xxxxIIIAxxxxxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxAAAAIIIIxxxxxxxx + "mov %%edx, %%eax \n" + "shr $12, %%eax \n" //Alpha + "and $0x00001000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shr $16, %%eax \n" // Intensity + "and $0x00000E00, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x00000100, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #3 + // xxxxxxxxIIIAxxxxxxxxxxxxxxxxxxxx + // xxxxxxxxAAAAIIIIxxxxxxxxxxxxxxxx + //Alpha + "mov %%edx, %%eax \n" + "and $0x00100000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shr $4, %%eax \n" // Intensity + "and $0x000E0000, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x00010000, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #4 + // xxxxxxxxxxxxIIIAxxxxxxxxxxxxxxxx + // AAAAIIIIxxxxxxxxxxxxxxxxxxxxxxxx + "mov %%edx, %%eax \n" + "shl $12, %%eax \n" //Alpha + "and $0x10000000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shl $8, %%eax \n" // Intensity + "and $0x0E000000, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x01000000, %%eax \n" + "or %%eax, %%ecx \n" + + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword { + "xor %%ecx, %%ecx \n" + + // pixel #5 + // xxxxxxxxxxxxxxxxIIIAxxxxxxxxxxxx + // xxxxxxxxxxxxxxxxxxxxxxxxAAAAIIII + "mov %%edx, %%eax \n" + "shr $8, %%eax \n" //Alpha + "and $0x00000010, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shr $12, %%eax \n" // Intensity + "and $0x0000000E, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #6 + // xxxxxxxxxxxxxxxxxxxxIIIAxxxxxxxx + // xxxxxxxxxxxxxxxxAAAAIIIIxxxxxxxx + //Alpha + "mov %%edx, %%eax \n" + "shl $4, %%eax \n" + "and $0x00001000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" // Intensity + "and $0x00000E00, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x00000100, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #7 + // xxxxxxxxxxxxxxxxxxxxxxxxIIIAxxxx + // xxxxxxxxAAAAIIIIxxxxxxxxxxxxxxxx + //Alpha + "mov %%edx, %%eax \n" + "shl $16, %%eax \n" + "and $0x00100000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shl $12, %%eax \n" // Intensity + "and $0x000E0000, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x00010000, %%eax \n" + "or %%eax, %%ecx \n" + + // pixel #8 + // xxxxxxxxxxxxxxxxxxxxxxxxxxxxIIIA + // AAAAIIIIxxxxxxxxxxxxxxxxxxxxxxxx + "mov %%edx, %%eax \n" + "shl $28, %%eax \n" //Alpha + "and $0x10000000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "shl $1, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n" + "shl $24, %%eax \n" // Intensity + "and $0x0E000000, %%eax \n" + "or %%eax, %%ecx \n" + "shr $3, %%eax \n" + "and $0x01000000, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + // * + + "mov %[tempx], %[c] \n" + "dec %%ecx \n" + "jnz 3b \n" // x_loop_22 + + "add %[line], %[src] \n" + "add %[ext], %[dst] \n" + + "mov %[tempy], %[c] \n" + "dec %%ecx \n" + "jnz 1b \n" // y_loop2 + + "4: \n" // end_y_loop2 + : [tempx]"=m"(lTempX), [tempy]"=m"(lTempY), [src]"+S"(src), [dst]"+D"(dst), [c]"+c"(lHeight) + : [wid_64] "g" (wid_64), [line] "g" ((uintptr_t)line), [ext] "g" ((uintptr_t)ext) + : "memory", "cc", "eax", "edx" + ); +#endif + + return /*(0 << 16) | */GR_TEXFMT_ALPHA_INTENSITY_44; +} + +//**************************************************************** +// Size: 0, Format: 4 + +DWORD 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 !defined(__GNUC__) && !defined(NO_ASM) + __asm { + mov esi,dword ptr [src] + mov edi,dword ptr [dst] + + mov ecx,dword ptr [height] +y_loop: + push ecx + + mov ecx,dword ptr [wid_64] +x_loop: + push ecx + + mov eax,dword ptr [esi] // read all 8 pixels + bswap eax + add esi,4 + mov edx,eax + + // 1st dword { + xor ecx,ecx + shr eax,28 // 0xF0000000 -> 0x0000000F + or ecx,eax + shl eax,4 + or ecx,eax + + mov eax,edx // 0x0F000000 -> 0x00000F00 + shr eax,16 + and eax,0x00000F00 + or ecx,eax + shl eax,4 + or ecx,eax + + mov eax,edx + shr eax,4 // 0x00F00000 -> 0x000F0000 + and eax,0x000F0000 + or ecx,eax + shl eax,4 + or ecx,eax + + mov eax,edx + shl eax,8 // 0x000F0000 -> 0x0F000000 + and eax,0x0F000000 + or ecx,eax + shl eax,4 + or ecx,eax + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword { + xor ecx,ecx + mov eax,edx + shr eax,12 // 0x0000F000 -> 0x0000000F + and eax,0x0000000F + or ecx,eax + shl eax,4 + or ecx,eax + + mov eax,edx // 0x00000F00 -> 0x00000F00 + and eax,0x00000F00 + or ecx,eax + shl eax,4 + or ecx,eax + + mov eax,edx + shl eax,12 // 0x000000F0 -> 0x000F0000 + and eax,0x000F0000 + or ecx,eax + shl eax,4 + or ecx,eax + + shl edx,24 // 0x0000000F -> 0x0F000000 + and edx,0x0F000000 + or ecx,edx + shl edx,4 + or ecx,edx + + mov dword ptr [edi],ecx + add edi,4 + // } + + // * copy + mov eax,dword ptr [esi] // read all 8 pixels + bswap eax + add esi,4 + mov edx,eax + + // 1st dword { + xor ecx,ecx + shr eax,28 // 0xF0000000 -> 0x0000000F + or ecx,eax + shl eax,4 + or ecx,eax + + mov eax,edx // 0x0F000000 -> 0x00000F00 + shr eax,16 + and eax,0x00000F00 + or ecx,eax + shl eax,4 + or ecx,eax + + mov eax,edx + shr eax,4 // 0x00F00000 -> 0x000F0000 + and eax,0x000F0000 + or ecx,eax + shl eax,4 + or ecx,eax + + mov eax,edx + shl eax,8 // 0x000F0000 -> 0x0F000000 + and eax,0x0F000000 + or ecx,eax + shl eax,4 + or ecx,eax + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword { + xor ecx,ecx + mov eax,edx + shr eax,12 // 0x0000F000 -> 0x0000000F + and eax,0x0000000F + or ecx,eax + shl eax,4 + or ecx,eax + + mov eax,edx // 0x00000F00 -> 0x00000F00 + and eax,0x00000F00 + or ecx,eax + shl eax,4 + or ecx,eax + + mov eax,edx + shl eax,12 // 0x000000F0 -> 0x000F0000 + and eax,0x000F0000 + or ecx,eax + shl eax,4 + or ecx,eax + + shl edx,24 // 0x0000000F -> 0x0F000000 + and edx,0x0F000000 + or ecx,edx + shl edx,4 + or ecx,edx + + mov dword ptr [edi],ecx + add edi,4 + // } + // * + + pop ecx + dec ecx + jnz x_loop + + pop ecx + dec ecx + jz end_y_loop + push ecx + + add esi,dword ptr [line] + add edi,dword ptr [ext] + + mov ecx,dword ptr [wid_64] +x_loop_2: + push ecx + + mov eax,dword ptr [esi+4] // read all 8 pixels + bswap eax + mov edx,eax + + // 1st dword { + xor ecx,ecx + shr eax,28 // 0xF0000000 -> 0x0000000F + or ecx,eax + shl eax,4 + or ecx,eax + + mov eax,edx // 0x0F000000 -> 0x00000F00 + shr eax,16 + and eax,0x00000F00 + or ecx,eax + shl eax,4 + or ecx,eax + + mov eax,edx + shr eax,4 // 0x00F00000 -> 0x000F0000 + and eax,0x000F0000 + or ecx,eax + shl eax,4 + or ecx,eax + + mov eax,edx + shl eax,8 // 0x000F0000 -> 0x0F000000 + and eax,0x0F000000 + or ecx,eax + shl eax,4 + or ecx,eax + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword { + xor ecx,ecx + mov eax,edx + shr eax,12 // 0x0000F000 -> 0x0000000F + and eax,0x0000000F + or ecx,eax + shl eax,4 + or ecx,eax + + mov eax,edx // 0x00000F00 -> 0x00000F00 + and eax,0x00000F00 + or ecx,eax + shl eax,4 + or ecx,eax + + mov eax,edx + shl eax,12 // 0x000000F0 -> 0x000F0000 + and eax,0x000F0000 + or ecx,eax + shl eax,4 + or ecx,eax + + shl edx,24 // 0x0000000F -> 0x0F000000 + and edx,0x0F000000 + or ecx,edx + shl edx,4 + or ecx,edx + + mov dword ptr [edi],ecx + add edi,4 + // } + + // * copy + mov eax,dword ptr [esi] // read all 8 pixels + bswap eax + add esi,8 + mov edx,eax + + // 1st dword { + xor ecx,ecx + shr eax,28 // 0xF0000000 -> 0x0000000F + or ecx,eax + shl eax,4 + or ecx,eax + + mov eax,edx // 0x0F000000 -> 0x00000F00 + shr eax,16 + and eax,0x00000F00 + or ecx,eax + shl eax,4 + or ecx,eax + + mov eax,edx + shr eax,4 // 0x00F00000 -> 0x000F0000 + and eax,0x000F0000 + or ecx,eax + shl eax,4 + or ecx,eax + + mov eax,edx + shl eax,8 // 0x000F0000 -> 0x0F000000 + and eax,0x0F000000 + or ecx,eax + shl eax,4 + or ecx,eax + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword { + xor ecx,ecx + mov eax,edx + shr eax,12 // 0x0000F000 -> 0x0000000F + and eax,0x0000000F + or ecx,eax + shl eax,4 + or ecx,eax + + mov eax,edx // 0x00000F00 -> 0x00000F00 + and eax,0x00000F00 + or ecx,eax + shl eax,4 + or ecx,eax + + mov eax,edx + shl eax,12 // 0x000000F0 -> 0x000F0000 + and eax,0x000F0000 + or ecx,eax + shl eax,4 + or ecx,eax + + shl edx,24 // 0x0000000F -> 0x0F000000 + and edx,0x0F000000 + or ecx,edx + shl edx,4 + or ecx,edx + + mov dword ptr [edi],ecx + add edi,4 + // } + // * + + pop ecx + dec ecx + jnz x_loop_2 + + add esi,dword ptr [line] + add edi,dword ptr [ext] + + pop ecx + dec ecx + jnz y_loop + +end_y_loop: + } +#elif !defined(NO_ASM) + //printf("Load4bI\n"); + int lTempX, lTempY, lHeight = (int) height; + asm volatile ( + "1: \n" // y_loop3 + "mov %[c], %[tempy] \n" + + "mov %[wid_64], %%ecx \n" + "2: \n" // x_loop3 + "mov %[c], %[tempx] \n" + + "mov (%[src]), %%eax \n" // read all 8 pixels + "bswap %%eax \n" + "add $4, %[src] \n" + "mov %%eax, %%edx \n" + + // 1st dword { + "xor %%ecx, %%ecx \n" + "shr $28, %%eax \n" // 0xF0000000 -> 0x0000000F + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%edx, %%eax \n" // 0x0F000000 -> 0x00000F00 + "shr $16, %%eax \n" + "and $0x00000F00, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $4, %%eax \n" // 0x00F00000 -> 0x000F0000 + "and $0x000F0000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%edx, %%eax \n" + "shl $8, %%eax \n" // 0x000F0000 -> 0x0F000000 + "and $0x0F000000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword { + "xor %%ecx, %%ecx \n" + "mov %%edx, %%eax \n" + "shr $12, %%eax \n" // 0x0000F000 -> 0x0000000F + "and $0x0000000F, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%edx, %%eax \n" // 0x00000F00 -> 0x00000F00 + "and $0x00000F00, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%edx, %%eax \n" + "shl $12, %%eax \n" // 0x000000F0 -> 0x000F0000 + "and $0x000F0000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "shl $24, %%edx \n" // 0x0000000F -> 0x0F000000 + "and $0x0F000000, %%edx \n" + "or %%edx, %%ecx \n" + "shl $4, %%edx \n" + "or %%edx, %%ecx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // * copy + "mov (%[src]), %%eax \n" // read all 8 pixels + "bswap %%eax \n" + "add $4, %[src] \n" + "mov %%eax, %%edx \n" + + // 1st dword { + "xor %%ecx, %%ecx \n" + "shr $28, %%eax \n" // 0xF0000000 -> 0x0000000F + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%edx, %%eax \n" // 0x0F000000 -> 0x00000F00 + "shr $16, %%eax \n" + "and $0x00000F00, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $4, %%eax \n" // 0x00F00000 -> 0x000F0000 + "and $0x000F0000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%edx, %%eax \n" + "shl $8, %%eax \n" // 0x000F0000 -> 0x0F000000 + "and $0x0F000000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword { + "xor %%ecx, %%ecx \n" + "mov %%edx, %%eax \n" + "shr $12, %%eax \n" // 0x0000F000 -> 0x0000000F + "and $0x0000000F, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%edx, %%eax \n" // 0x00000F00 -> 0x00000F00 + "and $0x00000F00, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%edx, %%eax \n" + "shl $12, %%eax \n" // 0x000000F0 -> 0x000F0000 + "and $0x000F0000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "shl $24, %%edx \n" // 0x0000000F -> 0x0F000000 + "and $0x0F000000, %%edx \n" + "or %%edx, %%ecx \n" + "shl $4, %%edx \n" + "or %%edx, %%ecx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + // * + + "mov %[tempx], %[c] \n" + "dec %%ecx \n" + "jnz 2b \n" // x_loop3 + + "mov %[tempy], %[c] \n" + "dec %%ecx \n" + "jz 4f \n" // end_y_loop3 + "mov %[c], %[tempy] \n" + + "add %[line], %[src] \n" + "add %[ext], %[dst] \n" + + "mov %[wid_64], %%ecx \n" + "3: \n" // x_loop_23 + "mov %[c], %[tempx] \n" + + "mov 4(%[src]), %%eax \n" // read all 8 pixels + "bswap %%eax \n" + "mov %%eax, %%edx \n" + + // 1st dword { + "xor %%ecx, %%ecx \n" + "shr $28, %%eax \n" // 0xF0000000 -> 0x0000000F + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%edx, %%eax \n" // 0x0F000000 -> 0x00000F00 + "shr $16, %%eax \n" + "and $0x00000F00, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $4, %%eax \n" // 0x00F00000 -> 0x000F0000 + "and $0x000F0000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%edx, %%eax \n" + "shl $8, %%eax \n" // 0x000F0000 -> 0x0F000000 + "and $0x0F000000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword { + "xor %%ecx, %%ecx \n" + "mov %%edx, %%eax \n" + "shr $12, %%eax \n" // 0x0000F000 -> 0x0000000F + "and $0x0000000F, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%edx, %%eax \n" // 0x00000F00 -> 0x00000F00 + "and $0x00000F00, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%edx, %%eax \n" + "shl $12, %%eax \n" // 0x000000F0 -> 0x000F0000 + "and $0x000F0000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "shl $24, %%edx \n" // 0x0000000F -> 0x0F000000 + "and $0x0F000000, %%edx \n" + "or %%edx, %%ecx \n" + "shl $4, %%edx \n" + "or %%edx, %%ecx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // * copy + "mov (%[src]), %%eax \n" // read all 8 pixels + "bswap %%eax \n" + "add $8, %[src] \n" + "mov %%eax, %%edx \n" + + // 1st dword { + "xor %%ecx, %%ecx \n" + "shr $28, %%eax \n" // 0xF0000000 -> 0x0000000F + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%edx, %%eax \n" // 0x0F000000 -> 0x00000F00 + "shr $16, %%eax \n" + "and $0x00000F00, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $4, %%eax \n" // 0x00F00000 -> 0x000F0000 + "and $0x000F0000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%edx, %%eax \n" + "shl $8, %%eax \n" // 0x000F0000 -> 0x0F000000 + "and $0x0F000000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword { + "xor %%ecx, %%ecx \n" + "mov %%edx, %%eax \n" + "shr $12, %%eax \n" // 0x0000F000 -> 0x0000000F + "and $0x0000000F, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%edx, %%eax \n" // 0x00000F00 -> 0x00000F00 + "and $0x00000F00, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%edx, %%eax \n" + "shl $12, %%eax \n" // 0x000000F0 -> 0x000F0000 + "and $0x000F0000, %%eax \n" + "or %%eax, %%ecx \n" + "shl $4, %%eax \n" + "or %%eax, %%ecx \n" + + "shl $24, %%edx \n" // 0x0000000F -> 0x0F000000 + "and $0x0F000000, %%edx \n" + "or %%edx, %%ecx \n" + "shl $4, %%edx \n" + "or %%edx, %%ecx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + // * + + "mov %[tempx], %[c] \n" + "dec %%ecx \n" + "jnz 3b \n" // x_loop_23 + + "add %[line], %[src] \n" + "add %[ext], %[dst] \n" + + "mov %[tempy], %[c] \n" + "dec %%ecx \n" + "jnz 1b \n" // y_loop3 + + "4: \n" // end_y_loop3 + : [tempx]"=m"(lTempX), [tempy]"=m"(lTempY), [src] "+S"(src), [dst] "+D"(dst), [c]"+c"(lHeight) + : [wid_64] "g" (wid_64), [line] "g" ((uintptr_t)line), [ext] "g" ((uintptr_t)ext) + : "memory", "cc", "eax", "edx" + ); +#endif + + return /*(0 << 16) | */GR_TEXFMT_ALPHA_INTENSITY_44; +} + +//**************************************************************** +// Size: 0, Format: 0 + +DWORD 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); +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/TexLoad8b.h b/libmupen64plus/mupen64plus-video-glide64/src/TexLoad8b.h new file mode 100644 index 0000000000..fa05fc5636 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/TexLoad8b.h @@ -0,0 +1,1227 @@ +/* +* 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 +// +//**************************************************************** + +DWORD Load8bCI (unsigned char * dst, unsigned char * 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 << 3)) << 1; + unsigned short * pal = rdp.pal_8; + + if (rdp.tlut_mode == 2) + { +#if !defined(__GNUC__) && !defined(NO_ASM) + __asm { + mov ebx,dword ptr [pal] + + mov esi,dword ptr [src] + mov edi,dword ptr [dst] + + mov ecx,dword ptr [height] +y_loop: + push ecx + + mov ecx,dword ptr [wid_64] +x_loop: + push ecx + + mov eax,dword ptr [esi] // read all 4 pixels + bswap eax + add esi,4 + mov edx,eax + + // 1st dword output { + shr eax,15 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + mov eax,edx + shr eax,23 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword output { + mov eax,edx + shl eax,1 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + shr edx,7 + and edx,0x1FE + mov cx,word ptr [ebx+edx] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // * copy + mov eax,dword ptr [esi] // read all 4 pixels + bswap eax + add esi,4 + mov edx,eax + + // 1st dword output { + shr eax,15 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + mov eax,edx + shr eax,23 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword output { + mov eax,edx + shl eax,1 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + shr edx,7 + and edx,0x1FE + mov cx,word ptr [ebx+edx] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + // * + + pop ecx + + dec ecx + jnz x_loop + + pop ecx + dec ecx + jz end_y_loop + push ecx + + add esi,dword ptr [line] + add edi,dword ptr [ext] + + mov ecx,dword ptr [wid_64] +x_loop_2: + push ecx + + mov eax,dword ptr [esi+4] // read all 4 pixels + bswap eax + mov edx,eax + + // 1st dword output { + shr eax,15 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + mov eax,edx + shr eax,23 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword output { + mov eax,edx + shl eax,1 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + shr edx,7 + and edx,0x1FE + mov cx,word ptr [ebx+edx] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // * copy + mov eax,dword ptr [esi] // read all 4 pixels + bswap eax + add esi,8 + mov edx,eax + + // 1st dword output { + shr eax,15 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + mov eax,edx + shr eax,23 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword output { + mov eax,edx + shl eax,1 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,1 + shl ecx,16 + + shr edx,7 + and edx,0x1FE + mov cx,word ptr [ebx+edx] + ror cx,1 + + mov dword ptr [edi],ecx + add edi,4 + // } + // * + + pop ecx + + dec ecx + jnz x_loop_2 + + add esi,dword ptr [line] + add edi,dword ptr [ext] + + pop ecx + dec ecx + jnz y_loop + +end_y_loop: + } +#elif !defined(NO_ASM) + //printf("Load8bCI1\n"); + long lTempX, lTempY, lHeight = (long) height; + intptr_t fake_eax, fake_edx; + asm volatile ( + "1: \n" // y_loop4 + "mov %[c], %[tempy] \n" + + "mov %[wid_64], %%ecx \n" + "2: \n" // x_loop4 + "mov %[c], %[tempx] \n" + + "mov (%[src]), %%eax \n" // read all 4 pixels + "bswap %%eax \n" + "add $4, %[src] \n" + "mov %%eax, %%edx \n" + + // 1st dword output { + "shr $15, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $23, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword output { + "mov %%edx, %%eax \n" + "shl $1, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + "shl $16, %%ecx \n" + + "shr $7, %%edx \n" + "and $0x1FE, %%edx \n" + "mov (%[pal],%[d]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // * copy + "mov (%[src]), %%eax \n" // read all 4 pixels + "bswap %%eax \n" + "add $4, %[src] \n" + "mov %%eax, %%edx \n" + + // 1st dword output { + "shr $15, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $23, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword output { + "mov %%edx, %%eax \n" + "shl $1, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + "shl $16, %%ecx \n" + + "shr $7, %%edx \n" + "and $0x1FE, %%edx \n" + "mov (%[pal],%[d]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + // * + + "mov %[tempx], %[c] \n" + + "dec %%ecx \n" + "jnz 2b \n" // x_loop4 + + "mov %[tempy], %[c] \n" + "dec %%ecx \n" + "jz 4f \n" // end_y_loop4 + "mov %[c], %[tempy] \n" + + "add %[line], %[src] \n" + "add %[ext], %[dst] \n" + + "mov %[wid_64], %%ecx \n" + "3: \n" // x_loop_24 + "mov %[c], %[tempx] \n" + + "mov 4(%[src]), %%eax \n" // read all 4 pixels + "bswap %%eax \n" + "mov %%eax, %%edx \n" + + // 1st dword output { + "shr $15, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $23, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword output { + "mov %%edx, %%eax \n" + "shl $1, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + "shl $16, %%ecx \n" + + "shr $7, %%edx \n" + "and $0x1FE, %%edx \n" + "mov (%[pal],%[d]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // * copy + "mov (%[src]), %%eax \n" // read all 4 pixels + "bswap %%eax \n" + "add $8, %[src] \n" + "mov %%eax, %%edx \n" + + // 1st dword output { + "shr $15, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $23, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword output { + "mov %%edx, %%eax \n" + "shl $1, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $1, %%cx \n" + "shl $16, %%ecx \n" + + "shr $7, %%edx \n" + "and $0x1FE, %%edx \n" + "mov (%[pal],%[d]), %%cx \n" + "ror $1, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + // * + + "mov %[tempx], %[c] \n" + "dec %%ecx \n" + "jnz 3b \n" // x_loop_24 + + "add %[line], %[src] \n" + "add %[ext], %[dst] \n" + + "mov %[tempy], %[c] \n" + "dec %%ecx \n" + "jnz 1b \n" // y_loop4 + + "4: \n" // end_y_loop4 + : [tempx]"=m"(lTempX), [tempy]"=m"(lTempY), [a] "=&a" (fake_eax), [d] "=&d" (fake_edx), [src]"+S"(src), [dst]"+D"(dst), [c]"+c"(lHeight) + : [pal] "r" (pal), [wid_64] "g" (wid_64), [line] "g" ((uintptr_t)line), [ext] "g" ((uintptr_t)ext) + : "memory", "cc" + ); +#endif + return (1 << 16) | GR_TEXFMT_ARGB_1555; + } + else + { +#if !defined(__GNUC__) && !defined(NO_ASM) + __asm { + mov ebx,dword ptr [pal] + + mov esi,dword ptr [src] + mov edi,dword ptr [dst] + + mov ecx,dword ptr [height] +ia_y_loop: + push ecx + + mov ecx,dword ptr [wid_64] +ia_x_loop: + push ecx + + mov eax,dword ptr [esi] // read all 4 pixels + bswap eax + add esi,4 + mov edx,eax + + // 1st dword output { + shr eax,15 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + mov eax,edx + shr eax,23 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword output { + mov eax,edx + shl eax,1 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + shr edx,7 + and edx,0x1FE + mov cx,word ptr [ebx+edx] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // * copy + mov eax,dword ptr [esi] // read all 4 pixels + bswap eax + add esi,4 + mov edx,eax + + // 1st dword output { + shr eax,15 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + mov eax,edx + shr eax,23 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword output { + mov eax,edx + shl eax,1 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + shr edx,7 + and edx,0x1FE + mov cx,word ptr [ebx+edx] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + // * + + pop ecx + + dec ecx + jnz ia_x_loop + + pop ecx + dec ecx + jz ia_end_y_loop + push ecx + + add esi,dword ptr [line] + add edi,dword ptr [ext] + + mov ecx,dword ptr [wid_64] +ia_x_loop_2: + push ecx + + mov eax,dword ptr [esi+4] // read all 4 pixels + bswap eax + mov edx,eax + + // 1st dword output { + shr eax,15 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + mov eax,edx + shr eax,23 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword output { + mov eax,edx + shl eax,1 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + shr edx,7 + and edx,0x1FE + mov cx,word ptr [ebx+edx] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // * copy + mov eax,dword ptr [esi] // read all 4 pixels + bswap eax + add esi,8 + mov edx,eax + + // 1st dword output { + shr eax,15 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + mov eax,edx + shr eax,23 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + + // 2nd dword output { + mov eax,edx + shl eax,1 + and eax,0x1FE + mov cx,word ptr [ebx+eax] + ror cx,8 + shl ecx,16 + + shr edx,7 + and edx,0x1FE + mov cx,word ptr [ebx+edx] + ror cx,8 + + mov dword ptr [edi],ecx + add edi,4 + // } + // * + + pop ecx + + dec ecx + jnz ia_x_loop_2 + + add esi,dword ptr [line] + add edi,dword ptr [ext] + + pop ecx + dec ecx + jnz ia_y_loop + +ia_end_y_loop: + } +#elif !defined(NO_ASM) + //printf("Load8bCI1\n"); + long lTempX, lTempY, lHeight = (long) height; + intptr_t fake_eax, fake_edx; + asm volatile ( + "1: \n" // ia_y_loop2 + "mov %[c], %[tempy] \n" + + "mov %[wid_64], %%ecx \n" + "2: \n" // ia_x_loop2 + "mov %[c], %[tempx] \n" + + "mov (%[src]), %%eax \n" // read all 4 pixels + "bswap %%eax \n" + "add $4, %[src] \n" + "mov %%eax, %%edx \n" + + // 1st dword output { + "shr $15, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $23, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword output { + "mov %%edx, %%eax \n" + "shl $1, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + "shl $16, %%ecx \n" + + "shr $7, %%edx \n" + "and $0x1FE, %%edx \n" + "mov (%[pal],%[d]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // * copy + "mov (%[src]), %%eax \n" // read all 4 pixels + "bswap %%eax \n" + "add $4, %[src] \n" + "mov %%eax, %%edx \n" + + // 1st dword output { + "shr $15, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $23, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword output { + "mov %%edx, %%eax \n" + "shl $1, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + "shl $16, %%ecx \n" + + "shr $7, %%edx \n" + "and $0x1FE, %%edx \n" + "mov (%[pal],%[d]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + // * + + "mov %[tempx], %[c] \n" + "dec %%ecx \n" + "jnz 2b \n" // ia_x_loop2 + + "mov %[tempy], %[c] \n" + "dec %%ecx \n" + "jz 4f \n" // ia_end_y_loop2 + "mov %[c], %[tempy] \n" + + "add %[line], %[src] \n" + "add %[ext], %[dst] \n" + + "mov %[wid_64], %%ecx \n" + "3: \n" // ia_x_loop_22 + "mov %[c], %[tempx] \n" + + "mov 4(%[src]), %%eax \n" // read all 4 pixels + "bswap %%eax \n" + "mov %%eax, %%edx \n" + + // 1st dword output { + "shr $15, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $23, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword output { + "mov %%edx, %%eax \n" + "shl $1, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + "shl $16, %%ecx \n" + + "shr $7, %%edx \n" + "and $0x1FE, %%edx \n" + "mov (%[pal],%[d]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // * copy + "mov (%[src]), %%eax \n" // read all 4 pixels + "bswap %%eax \n" + "add $8, %[src] \n" + "mov %%eax, %%edx \n" + + // 1st dword output { + "shr $15, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + "shl $16, %%ecx \n" + + "mov %%edx, %%eax \n" + "shr $23, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + + // 2nd dword output { + "mov %%edx, %%eax \n" + "shl $1, %%eax \n" + "and $0x1FE, %%eax \n" + "mov (%[pal],%[a]), %%cx \n" + "ror $8, %%cx \n" + "shl $16, %%ecx \n" + + "shr $7, %%edx \n" + "and $0x1FE, %%edx \n" + "mov (%[pal],%[d]), %%cx \n" + "ror $8, %%cx \n" + + "mov %%ecx, (%[dst]) \n" + "add $4, %[dst] \n" + // } + // * + + "mov %[tempx], %[c] \n" + "dec %%ecx \n" + "jnz 3b \n" // ia_x_loop_22 + + "add %[line], %[src] \n" + "add %[ext], %[dst] \n" + + "mov %[tempy], %[c] \n" + "dec %%ecx \n" + "jnz 1b \n" // ia_y_loop2 + + "4: \n" // ia_end_y_loop2 + : [tempx]"=m"(lTempX), [tempy]"=m"(lTempY), [a] "=&a" (fake_eax), [d] "=&d" (fake_edx), [src]"+S"(src), [dst]"+D"(dst), [c]"+c"(lHeight) + : [pal] "r" (pal), [wid_64] "g" (wid_64), [line] "g" ((uintptr_t)line), [ext] "g" ((uintptr_t)ext) + : "memory", "cc" + ); +#endif + return (1 << 16) | GR_TEXFMT_ALPHA_INTENSITY_88; + } + + return 0; +} + +//**************************************************************** +// Size: 1, Format: 3 +// +// ** by Gugaman ** + +DWORD Load8bIA (unsigned char * dst, unsigned char * 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 !defined(__GNUC__) && !defined(NO_ASM) + __asm { + mov esi,dword ptr [src] + mov edi,dword ptr [dst] + + mov ecx,dword ptr [height] +y_loop: + push ecx + + mov ecx,dword ptr [wid_64] +x_loop: + mov eax,dword ptr [esi] // read all 4 pixels + add esi,4 + + xor ebx,ebx + mov edx,eax + shr eax,4//all alpha + and eax,0x0F0F0F0F + or ebx,eax + mov eax,edx//intensity + shl eax,4 + and eax,0xF0F0F0F0 + or ebx,eax + + mov dword ptr [edi],ebx // save dword + add edi,4 + + mov eax,dword ptr [esi] // read all 4 pixels + add esi,4 + + xor ebx,ebx + mov edx,eax + shr eax,4//all alpha + and eax,0x0F0F0F0F + or ebx,eax + mov eax,edx//intensity + shl eax,4 + and eax,0xF0F0F0F0 + or ebx,eax + + mov dword ptr [edi],ebx // save dword + add edi,4 + // * + + dec ecx + jnz x_loop + + pop ecx + dec ecx + jz end_y_loop + push ecx + + add esi,dword ptr [line] + add edi,dword ptr [ext] + + mov ecx,dword ptr [wid_64] +x_loop_2: + mov eax,dword ptr [esi+4] // read both pixels + + xor ebx,ebx + mov edx,eax + shr eax,4//all alpha + and eax,0x0F0F0F0F + or ebx,eax + mov eax,edx//intensity + shl eax,4 + and eax,0xF0F0F0F0 + or ebx,eax + + mov dword ptr [edi],ebx //save dword + add edi,4 + + mov eax,dword ptr [esi] // read both pixels + add esi,8 + + xor ebx,ebx + mov edx,eax + shr eax,4//all alpha + and eax,0x0F0F0F0F + or ebx,eax + mov eax,edx//intensity + shl eax,4 + and eax,0xF0F0F0F0 + or ebx,eax + + mov dword ptr [edi],ebx //save dword + add edi,4 + // * + + dec ecx + jnz x_loop_2 + + add esi,dword ptr [line] + add edi,dword ptr [ext] + + pop ecx + dec ecx + jnz y_loop + +end_y_loop: + } +#elif !defined(NO_ASM) + //printf("Load8bIA\n"); + int lTemp, lHeight = (int) height; + asm volatile ( + "1: \n" // y_loop5 + "mov %[wid_64], %%eax \n" + "mov %%eax, %[temp] \n" + "2: \n" // x_loop5 + "mov (%[src]), %%eax \n" // read all 4 pixels + "add $4, %[src] \n" + + "xor %%ecx, %%ecx \n" + "mov %%eax, %%edx \n" + "shr $4, %%eax \n"//all alpha + "and $0x0F0F0F0F, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n"//intensity + "shl $4, %%eax \n" + "and $0xF0F0F0F0, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%ecx, (%[dst]) \n" // save dword + "add $4, %[dst] \n" + + "mov (%[src]), %%eax \n" // read all 4 pixels + "add $4, %[src] \n" + + "xor %%ecx, %%ecx \n" + "mov %%eax, %%edx \n" + "shr $4, %%eax \n"//all alpha + "and $0x0F0F0F0F, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n"//intensity + "shl $4, %%eax \n" + "and $0xF0F0F0F0, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%ecx, (%[dst]) \n" // save dword + "add $4, %[dst] \n" + + "decl %[temp] \n" + "jnz 2b \n" // x_loop5 + + "decl %[height] \n" + "jz 4f \n" // end_y_loop5 + + "add %[line], %[src] \n" + "add %[ext], %[dst] \n" + + "mov %[wid_64], %%eax \n" + "mov %%eax, %[temp] \n" + "3: \n" // x_loop_25 + "mov 4(%[src]), %%eax \n" // read both pixels + + "xor %%ecx, %%ecx \n" + "mov %%eax, %%edx \n" + "shr $4, %%eax \n"//all alpha + "and $0x0F0F0F0F, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n"//intensity + "shl $4, %%eax \n" + "and $0xF0F0F0F0, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%ecx, (%[dst]) \n" //save dword + "add $4, %[dst] \n" + + "mov (%[src]), %%eax \n" // read both pixels + "add $8, %[src] \n" + + "xor %%ecx, %%ecx \n" + "mov %%eax, %%edx \n" + "shr $4, %%eax \n"//all alpha + "and $0x0F0F0F0F, %%eax \n" + "or %%eax, %%ecx \n" + "mov %%edx, %%eax \n"//intensity + "shl $4, %%eax \n" + "and $0xF0F0F0F0, %%eax \n" + "or %%eax, %%ecx \n" + + "mov %%ecx, (%[dst]) \n" //save dword + "add $4, %[dst] \n" + // * + + "decl %[temp] \n" + "jnz 3b \n" // x_loop_25 + + "add %[line], %[src] \n" + "add %[ext], %[dst] \n" + + "decl %[height] \n" + "jnz 1b \n" // y_loop5 + + "4: \n" // end_y_loop5 + : [temp]"=m"(lTemp), [src] "+S"(src), [dst] "+D"(dst), [height] "+g"(lHeight) + : [wid_64] "g" (wid_64), [line] "g" ((uintptr_t)line), [ext] "g" ((uintptr_t)ext) + : "memory", "cc", "eax", "edx", "ecx" + ); +#endif + return /*(0 << 16) | */GR_TEXFMT_ALPHA_INTENSITY_44; +} + +//**************************************************************** +// Size: 1, Format: 4 +// +// ** by Gugaman ** + +DWORD Load8bI (unsigned char * dst, unsigned char * 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 !defined(__GNUC__) && !defined(NO_ASM) + __asm { + mov esi,dword ptr [src] + mov edi,dword ptr [dst] + + mov ecx,dword ptr [height] +y_loop: + push ecx + + mov ecx,dword ptr [wid_64] +x_loop: + mov eax,dword ptr [esi] // read all 4 pixels + add esi,4 + + mov dword ptr [edi],eax // save dword + add edi,4 + + mov eax,dword ptr [esi] // read all 4 pixels + add esi,4 + + mov dword ptr [edi],eax // save dword + add edi,4 + // * + + dec ecx + jnz x_loop + + pop ecx + dec ecx + jz end_y_loop + push ecx + + add esi,dword ptr [line] + add edi,dword ptr [ext] + + mov ecx,dword ptr [wid_64] +x_loop_2: + mov eax,dword ptr [esi+4] // read both pixels + + mov dword ptr [edi],eax //save dword + add edi,4 + + mov eax,dword ptr [esi] // read both pixels + add esi,8 + + mov dword ptr [edi],eax //save dword + add edi,4 + // * + + dec ecx + jnz x_loop_2 + + add esi,dword ptr [line] + add edi,dword ptr [ext] + + pop ecx + dec ecx + jnz y_loop + +end_y_loop: + } +#elif !defined(NO_ASM) + //printf("Load8bI\n"); + int lTemp, lHeight = (int) height; + asm volatile ( + "1: \n" // y_loop6 + "mov %[wid_64], %%eax \n" + "mov %%eax, %[temp] \n" + "2: \n" // x_loop6 + "mov (%[src]), %%eax \n" // read all 4 pixels + "add $4, %[src] \n" + + "mov %%eax, (%[dst]) \n" // save dword + "add $4, %[dst] \n" + + "mov (%[src]), %%eax \n" // read all 4 pixels + "add $4, %[src] \n" + + "mov %%eax, (%[dst]) \n" // save dword + "add $4, %[dst] \n" + // * + + "decl %[temp] \n" + "jnz 2b \n" // x_loop6 + + "decl %[height] \n" + "jz 4f \n" // end_y_loop6 + + "add %[line], %[src] \n" + "add %[ext], %[dst] \n" + + "mov %[wid_64], %%eax \n" + "mov %%eax, %[temp] \n" + "3: \n" // x_loop_26 + "mov 4(%[src]), %%eax \n" // read both pixels + + "mov %%eax, (%[dst]) \n" //save dword + "add $4, %[dst] \n" + + "mov (%[src]), %%eax \n" // read both pixels + "add $8, %[src] \n" + + "mov %%eax, (%[dst]) \n" //save dword + "add $4, %[dst] \n" + + "decl %[temp] \n" + "jnz 3b \n" // x_loop_26 + + "add %[line], %[src] \n" + "add %[ext], %[dst] \n" + + "decl %[height] \n" + "jnz 1b \n" // y_loop6 + + "4: \n" // end_y_loop6 + : [temp]"=m"(lTemp), [src]"+S"(src), [dst]"+D"(dst), [height]"+g"(lHeight) + : [wid_64] "g" (wid_64), [line] "g" ((uintptr_t)line), [ext] "g" ((uintptr_t)ext) + : "memory", "cc", "eax", "edx" + ); +#endif + return /*(0 << 16) | */GR_TEXFMT_ALPHA_8; +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/TexMod.h b/libmupen64plus/mupen64plus-video-glide64/src/TexMod.h new file mode 100644 index 0000000000..6f436a74ee --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/TexMod.h @@ -0,0 +1,571 @@ +/* +* 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 = min(15, (BYTE)((1.0f-percent_r) * cr0 + percent_r * cr1)); + g = min(15, (BYTE)((1.0f-percent_g) * cg0 + percent_g * cg1)); + b = min(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; + } +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/TexModCI.h b/libmupen64plus/mupen64plus-video-glide64/src/TexModCI.h new file mode 100644 index 0000000000..affcc276ec --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/TexModCI.h @@ -0,0 +1,438 @@ +/* +* 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 +#define min(a,b) ((a) < (b) ? (a) : (b)) +#define max(a,b) ((a) > (b) ? (a) : (b)) +#endif // _WIN32 + +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)(min(255, percent_i * r + percent * cr)); + g = (BYTE)(min(255, percent_i * g + percent * cg)); + b = (BYTE)(min(255, 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)(min(255, percent_r_i * r + percent_r * cr)); + g = (BYTE)(min(255, percent_g_i * g + percent_g * cg)); + b = (BYTE)(min(255, 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 = max(0, ca - a); + r = max(0, cr - r); + g = max(0, cg - g); + b = 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)(min((1.0f-percent_r) * cr0 + percent_r * cr1, 255)); + g = (BYTE)(min((1.0f-percent_g) * cg0 + percent_g * cg1, 255)); + b = (BYTE)(min((1.0f-percent_b) * cb0 + percent_b * cb1, 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_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)(min(base + percent_r * r, 255)); + g = (BYTE)(min(base + percent_g * g, 255)); + b = (BYTE)(min(base + percent_b * b, 255)); + 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 = min(cr + r, 255); + g = min(cg + g, 255); + b = 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 = max(r - cr, 0); + g = max(g - cg, 0); + b = 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)(min(255, percent_r * r + percent_r_i * cr)); + g = (BYTE)(min(255, percent_g * g + percent_g_i * cg)); + b = (BYTE)(min(255, 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: + ; + } +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/Tmem.h b/libmupen64plus/mupen64plus-video-glide64/src/Tmem.h new file mode 100644 index 0000000000..ab95c56856 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/Tmem.h @@ -0,0 +1,44 @@ +/* +* 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 (); + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/Ucode00.h b/libmupen64plus/mupen64plus-video-glide64/src/Ucode00.h new file mode 100644 index 0000000000..3da4c74969 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/Ucode00.h @@ -0,0 +1,1081 @@ +/* +* 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 ++; + } +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/UcodeFB.h b/libmupen64plus/mupen64plus-video-glide64/src/UcodeFB.h new file mode 100644 index 0000000000..8eb896401d --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/UcodeFB.h @@ -0,0 +1,1067 @@ +/* +* 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 = 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 + } +}; + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/Util.cpp b/libmupen64plus/mupen64plus-video-glide64/src/Util.cpp new file mode 100644 index 0000000000..ec682ecac0 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/Util.cpp @@ -0,0 +1,1949 @@ +/* +* 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 max(a,b) ((a) > (b) ? (a) : (b)) +#define min(a,b) ((a) < (b) ? (a) : (b)) + +#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 = min((int)vtx[0]->u0,(int)vtx[1]->u0); // bah, don't put two mins on one line + min_256 = min(min_256,(int)vtx[2]->u0) >> 8; // or it will be calculated twice + + max_256 = max((int)vtx[0]->u0,(int)vtx[1]->u0); // not like it makes much difference + max_256 = 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 = 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 = 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/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) max(min((rdp.scissor_o.ul_x * rdp.scale_x + rdp.offset_x + 0.01f),settings.res_x),0); + rdp.scissor.lr_x = (DWORD) max(min((rdp.scissor_o.lr_x * rdp.scale_x + rdp.offset_x + 0.01f),settings.res_x),0); + rdp.scissor.ul_y = (DWORD) max(min((rdp.scissor_o.ul_y * rdp.scale_y + rdp.offset_y + 0.01f),settings.res_y),0); + rdp.scissor.lr_y = (DWORD) max(min((rdp.scissor_o.lr_y * rdp.scale_y + rdp.offset_y + 0.01f),settings.res_y),0); + 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) max(rdp.view_trans[0] - scale_x, 0); + DWORD min_y = (DWORD) max(rdp.view_trans[1] - scale_y, 0); + DWORD max_x = (DWORD) min(rdp.view_trans[0] + scale_x + 1, settings.res_x); + DWORD max_y = (DWORD) min(rdp.view_trans[1] + scale_y + 1, 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; + } + } + } +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/Util.h b/libmupen64plus/mupen64plus-video-glide64/src/Util.h new file mode 100644 index 0000000000..0606e60127 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/Util.h @@ -0,0 +1,95 @@ +/* +* 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 "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; \ + } + +#endif // ifndef Util_H + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/compiletex.c b/libmupen64plus/mupen64plus-video-glide64/src/compiletex.c new file mode 100644 index 0000000000..4ac128b7b9 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/compiletex.c @@ -0,0 +1,43 @@ +/* +* 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; +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/cursor.h b/libmupen64plus/mupen64plus-video-glide64/src/cursor.h new file mode 100644 index 0000000000..c2fbcd3a64 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/cursor.h @@ -0,0 +1,2049 @@ +unsigned 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}; diff --git a/libmupen64plus/mupen64plus-video-glide64/src/cursor.tex b/libmupen64plus/mupen64plus-video-glide64/src/cursor.tex new file mode 100644 index 0000000000..9e4362ec27 Binary files /dev/null and b/libmupen64plus/mupen64plus-video-glide64/src/cursor.tex differ diff --git a/libmupen64plus/mupen64plus-video-glide64/src/font.h b/libmupen64plus/mupen64plus-video-glide64/src/font.h new file mode 100644 index 0000000000..d1ab60889b --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/font.h @@ -0,0 +1,2049 @@ +unsigned 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}; diff --git a/libmupen64plus/mupen64plus-video-glide64/src/font.tex b/libmupen64plus/mupen64plus-video-glide64/src/font.tex new file mode 100644 index 0000000000..4d935ce925 Binary files /dev/null and b/libmupen64plus/mupen64plus-video-glide64/src/font.tex differ diff --git a/libmupen64plus/mupen64plus-video-glide64/src/gpl.txt b/libmupen64plus/mupen64plus-video-glide64/src/gpl.txt new file mode 100644 index 0000000000..fa6cc9f74a --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/gpl.txt @@ -0,0 +1,340 @@ + 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. diff --git a/libmupen64plus/mupen64plus-video-glide64/src/m64p.h b/libmupen64plus/mupen64plus-video-glide64/src/m64p.h new file mode 100644 index 0000000000..153258a459 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/m64p.h @@ -0,0 +1,87 @@ +/****************************************************************************** + * Glide64 - Glide video plugin for Nintendo 64 emulators. + * http://bitbucket.org/wahrhaft/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 0x016305 +#define VIDEO_PLUGIN_API_VERSION 0x020100 +#define CONFIG_API_VERSION 0x020000 +#define VIDEXT_API_VERSION 0x020000 + +#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_GL_GetProcAddress CoreVideo_GL_GetProcAddress; +extern ptr_VidExt_GL_SetAttribute CoreVideo_GL_SetAttribute; +extern ptr_VidExt_GL_SwapBuffers CoreVideo_GL_SwapBuffers; + +#endif diff --git a/libmupen64plus/mupen64plus-video-glide64/src/osal_dynamiclib.h b/libmupen64plus/mupen64plus-video-glide64/src/osal_dynamiclib.h new file mode 100644 index 0000000000..c24377b178 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/osal_dynamiclib.h @@ -0,0 +1,38 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus-core - osal/dynamiclib.h * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * 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 */ + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/osal_dynamiclib_unix.c b/libmupen64plus/mupen64plus-video-glide64/src/osal_dynamiclib_unix.c new file mode 100644 index 0000000000..b3b7ba52dc --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/osal_dynamiclib_unix.c @@ -0,0 +1,37 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus-core - osal/dynamiclib_unix.c * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * 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); +} + + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/osal_dynamiclib_win32.c b/libmupen64plus/mupen64plus-video-glide64/src/osal_dynamiclib_win32.c new file mode 100644 index 0000000000..4455cee52b --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/osal_dynamiclib_win32.c @@ -0,0 +1,74 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus-ui-console - osal_dynamiclib_win32.c * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * 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; +} diff --git a/libmupen64plus/mupen64plus-video-glide64/src/rdp.cpp b/libmupen64plus/mupen64plus-video-glide64/src/rdp.cpp new file mode 100644 index 0000000000..335cd1acf3 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/rdp.cpp @@ -0,0 +1,3860 @@ +/* +* 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 + +#if defined(__GNUC__) + #define bswap32(x) __builtin_bswap32(x) +#elif 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 + +// 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)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)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)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)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)max(rdp.frame_buffers[rdp.main_ci_index].width, rdp.ci_width); + float scale_y = (float)settings.scr_res_y / rdp.vi_height;//(float)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 = min(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 = min(max(ul_x, rdp.scissor_o.ul_x), rdp.scissor_o.lr_x); + lr_x = min(max(lr_x, rdp.scissor_o.ul_x), rdp.scissor_o.lr_x); + ul_y = min(max(ul_y, rdp.scissor_o.ul_y), rdp.scissor_o.lr_y); + lr_y = min(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 = (DWORD)min(max(ul_x * rdp.scale_x + rdp.offset_x + 0.01f, rdp.scissor.ul_x), rdp.scissor.lr_x); + DWORD s_lr_x = (DWORD)min(max(lr_x * rdp.scale_x + rdp.offset_x + 0.01f, rdp.scissor.ul_x), rdp.scissor.lr_x); + DWORD s_ul_y = (DWORD)min(max(ul_y * rdp.scale_y + rdp.offset_y + 0.01f, rdp.scissor.ul_y), rdp.scissor.lr_y); + DWORD s_lr_y = (DWORD)min(max(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 = 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 = 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 = min(d_ul_x, shift_l%rdp.ci_width); + d_ul_y = min(d_ul_y, shift_l/rdp.ci_width); + d_lr_x = max(d_lr_x, shift_r%rdp.ci_width); + d_lr_y = 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 = min(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: *** + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/rdp.h b/libmupen64plus/mupen64plus-video-glide64/src/rdp.h new file mode 100644 index 0000000000..2a51053855 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/rdp.h @@ -0,0 +1,768 @@ +/* +* 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 + +#ifdef _WIN32 +#include +#else // _WIN32 +#include "winlnxdefs.h" +#endif // _WIN32 +#include "glide.h" + +//#ifdef GCC +#define max(a,b) ((a) > (b) ? (a) : (b)) +#define min(a,b) ((a) < (b) ? (a) : (b)) +//#endif + +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 = min(255.0f, 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 + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/ucode.h b/libmupen64plus/mupen64plus-video-glide64/src/ucode.h new file mode 100644 index 0000000000..e58214e7ff --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/ucode.h @@ -0,0 +1,714 @@ +/* +* 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 + }, +}; + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/ucode01.h b/libmupen64plus/mupen64plus-video-glide64/src/ucode01.h new file mode 100644 index 0000000000..a84ccc89b5 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/ucode01.h @@ -0,0 +1,299 @@ +/* +* 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; + } +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/ucode02.h b/libmupen64plus/mupen64plus-video-glide64/src/ucode02.h new file mode 100644 index 0000000000..017b12a4bf --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/ucode02.h @@ -0,0 +1,852 @@ +/* +* 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; + register 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; +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/ucode03.h b/libmupen64plus/mupen64plus-video-glide64/src/ucode03.h new file mode 100644 index 0000000000..f68cebc46c --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/ucode03.h @@ -0,0 +1,253 @@ +/* +* 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 ++; + } +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/ucode04.h b/libmupen64plus/mupen64plus-video-glide64/src/ucode04.h new file mode 100644 index 0000000000..95d7fd7bfb --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/ucode04.h @@ -0,0 +1,192 @@ +/* +* 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 ++; + } +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/ucode05.h b/libmupen64plus/mupen64plus-video-glide64/src/ucode05.h new file mode 100644 index 0000000000..99b7b81084 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/ucode05.h @@ -0,0 +1,389 @@ +/* +* 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; +} + } +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/ucode06.h b/libmupen64plus/mupen64plus-video-glide64/src/ucode06.h new file mode 100644 index 0000000000..b4e14364dc --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/ucode06.h @@ -0,0 +1,2094 @@ +/* +* 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 + +#define max(a,b) ((a) > (b) ? (a) : (b)) +#define min(a,b) ((a) < (b) ? (a) : (b)) + +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 = min(int(src_width*scale_x_dst), (int)settings.scr_res_x); + int dst_height = 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 = min (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 = min (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 = min((int)vtx[0]->u0,(int)vtx[1]->u0); // bah, don't put two mins on one line + min_256 = min(min_256,(int)vtx[2]->u0) >> 8; // or it will be calculated twice + + max_256 = max((int)vtx[0]->u0,(int)vtx[1]->u0); // not like it makes much difference + max_256 = 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; + } +} + + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/ucode07.h b/libmupen64plus/mupen64plus-video-glide64/src/ucode07.h new file mode 100644 index 0000000000..da49310079 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/ucode07.h @@ -0,0 +1,174 @@ +/* +* 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++; + } +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/ucode08.h b/libmupen64plus/mupen64plus-video-glide64/src/ucode08.h new file mode 100644 index 0000000000..03a9fd41ad --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/ucode08.h @@ -0,0 +1,537 @@ +/* +* 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 ++; + } +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/video_api_export.ver b/libmupen64plus/mupen64plus-video-glide64/src/video_api_export.ver new file mode 100644 index 0000000000..557b0092f9 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/video_api_export.ver @@ -0,0 +1,21 @@ +{ global: +PluginStartup; +PluginShutdown; +PluginGetVersion; +ChangeWindow; +InitiateGFX; +MoveScreen; +ProcessDList; +ProcessRDPList; +RomClosed; +RomOpen; +ShowCFB; +UpdateScreen; +ViStatusChanged; +ViWidthChanged; +ReadScreen2; +SetRenderingCallback; +FBRead; +FBWrite; +FBGetFrameBufferInfo; +local: *; }; diff --git a/libmupen64plus/mupen64plus-video-glide64/src/winlnxdefs.h b/libmupen64plus/mupen64plus-video-glide64/src/winlnxdefs.h new file mode 100644 index 0000000000..dffcc140dc --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/winlnxdefs.h @@ -0,0 +1,67 @@ +/** + * Glide64 Video Plugin - winlnxdefs.h + * Copyright (C) 2002 Dave2001 + * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ + * + * 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 + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/wrapper/2xsai.cpp b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/2xsai.cpp new file mode 100644 index 0000000000..0b271917aa --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/2xsai.cpp @@ -0,0 +1,218 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus - glide64/wrapper/2xsai.cpp * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * 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)); + } +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/wrapper/2xsai.h b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/2xsai.h new file mode 100644 index 0000000000..32193a9eb2 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/2xsai.h @@ -0,0 +1,27 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus - glide64/wrapper/2xsai.h * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * 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); + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/wrapper/3dfx.h b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/3dfx.h new file mode 100644 index 0000000000..e2f50fdfc1 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/3dfx.h @@ -0,0 +1,136 @@ +/* +** 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__ */ + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/wrapper/COPYING b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/COPYING new file mode 100644 index 0000000000..e8b53febde --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/COPYING @@ -0,0 +1,255 @@ +3DFX 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. + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/wrapper/combiner.cpp b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/combiner.cpp new file mode 100644 index 0000000000..484a880f4a --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/combiner.cpp @@ -0,0 +1,3796 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus - glide64/wrapper/combiner.cpp * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * 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]); + } +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/wrapper/config.cpp b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/config.cpp new file mode 100644 index 0000000000..6d8a7291e1 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/config.cpp @@ -0,0 +1,76 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus - glide64/wrapper/config.cpp * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * 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; +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/wrapper/filter.cpp b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/filter.cpp new file mode 100644 index 0000000000..9df70ca4ff --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/filter.cpp @@ -0,0 +1,368 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus - glide64/wrapper/filter.cpp * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * 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; + char mx[3*3] = {-1, 0, 1, -2, 0, 2, -1, 0, 1}; + 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__ */ + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/wrapper/geometry.cpp b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/geometry.cpp new file mode 100644 index 0000000000..7a3336ee80 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/geometry.cpp @@ -0,0 +1,859 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus - glide64/wrapper/geometry.cpp * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * 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(); +} + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/wrapper/glide.h b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/glide.h new file mode 100644 index 0000000000..06046a0610 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/glide.h @@ -0,0 +1,947 @@ +/* +** 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__ */ + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/wrapper/glidesys.h b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/glidesys.h new file mode 100644 index 0000000000..6d3be8f281 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/glidesys.h @@ -0,0 +1,162 @@ +/* +** 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__ */ + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/wrapper/glideutl.h b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/glideutl.h new file mode 100644 index 0000000000..9a738c23b6 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/glideutl.h @@ -0,0 +1,154 @@ +/* +** 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__ */ + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/wrapper/hq2x.cpp b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/hq2x.cpp new file mode 100644 index 0000000000..446927aedd --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/hq2x.cpp @@ -0,0 +1,3016 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus - hq2x.cpp * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * 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) != 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 + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/wrapper/sst1vid.h b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/sst1vid.h new file mode 100644 index 0000000000..6e9a723954 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/sst1vid.h @@ -0,0 +1,149 @@ +/* +** 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__ */ + diff --git a/libmupen64plus/mupen64plus-video-glide64/src/wrapper/textures.cpp b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/textures.cpp new file mode 100644 index 0000000000..9ae934a427 --- /dev/null +++ b/libmupen64plus/mupen64plus-video-glide64/src/wrapper/textures.cpp @@ -0,0 +1,810 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus - glide64/wrapper/textures.cpp * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * 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); + } +} +