Glide Plugin GLES2 port from mupen64plus-ae, but with special FrameSkip code
authorptitSeb <sebastien.chev@gmail.com>
Sat, 12 Oct 2013 09:33:40 +0000 (11:33 +0200)
committerptitSeb <sebastien.chev@gmail.com>
Sat, 12 Oct 2013 09:33:40 +0000 (11:33 +0200)
138 files changed:
source/gles2glide64/.hgignore [new file with mode: 0644]
source/gles2glide64/INSTALL [new file with mode: 0644]
source/gles2glide64/LICENSES [new file with mode: 0644]
source/gles2glide64/Makefile [new file with mode: 0755]
source/gles2glide64/RELEASE [new file with mode: 0644]
source/gles2glide64/data/Glide64mk2.ini [new file with mode: 0755]
source/gles2glide64/doc/fxt1-license [new file with mode: 0644]
source/gles2glide64/doc/gpl-license [new file with mode: 0644]
source/gles2glide64/pandora.diff [new file with mode: 0644]
source/gles2glide64/projects/android/Android.mk [new file with mode: 0644]
source/gles2glide64/projects/msvc11/mupen64plus-video-glide64mk2.vcxproj [new file with mode: 0644]
source/gles2glide64/projects/msvc11/mupen64plus-video-glide64mk2.vcxproj.filters [new file with mode: 0644]
source/gles2glide64/projects/unix/Makefile [new file with mode: 0755]
source/gles2glide64/src/Glide64/3dmath.cpp [new file with mode: 0755]
source/gles2glide64/src/Glide64/3dmath.h [new file with mode: 0755]
source/gles2glide64/src/Glide64/3dmathneon.cpp [new file with mode: 0755]
source/gles2glide64/src/Glide64/CRC.cpp [new file with mode: 0755]
source/gles2glide64/src/Glide64/CRC.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/Combine.cpp [new file with mode: 0644]
source/gles2glide64/src/Glide64/Combine.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/Config.cpp [new file with mode: 0755]
source/gles2glide64/src/Glide64/Config.h [new file with mode: 0755]
source/gles2glide64/src/Glide64/Debugger.cpp [new file with mode: 0644]
source/gles2glide64/src/Glide64/Debugger.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/DepthBufferRender.cpp [new file with mode: 0755]
source/gles2glide64/src/Glide64/DepthBufferRender.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/FBtoScreen.cpp [new file with mode: 0755]
source/gles2glide64/src/Glide64/FBtoScreen.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/FrameSkipper.cpp [new file with mode: 0755]
source/gles2glide64/src/Glide64/FrameSkipper.h [new file with mode: 0755]
source/gles2glide64/src/Glide64/Gfx_1.3.h [new file with mode: 0755]
source/gles2glide64/src/Glide64/GlideExtensions.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/Help/Glide64 Known Issues.html [new file with mode: 0644]
source/gles2glide64/src/Glide64/Help/Glide64 Readme.html [new file with mode: 0644]
source/gles2glide64/src/Glide64/Help/Glide64 compatibility list.html [new file with mode: 0644]
source/gles2glide64/src/Glide64/Ini.cpp [new file with mode: 0755]
source/gles2glide64/src/Glide64/Ini.h [new file with mode: 0755]
source/gles2glide64/src/Glide64/Keys.cpp [new file with mode: 0644]
source/gles2glide64/src/Glide64/Keys.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/Main.cpp [new file with mode: 0755]
source/gles2glide64/src/Glide64/MiClWr16b.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/MiClWr32b.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/MiClWr8b.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/TexBuffer.cpp [new file with mode: 0755]
source/gles2glide64/src/Glide64/TexBuffer.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/TexCache.cpp [new file with mode: 0644]
source/gles2glide64/src/Glide64/TexCache.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/TexConv.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/TexLoad.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/TexLoad16b.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/TexLoad32b.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/TexLoad4b.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/TexLoad8b.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/TexMod.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/TexModCI.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/Util.cpp [new file with mode: 0755]
source/gles2glide64/src/Glide64/Util.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/cursor.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/font.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/m64p.h [new file with mode: 0755]
source/gles2glide64/src/Glide64/osal_dynamiclib.h [new file with mode: 0755]
source/gles2glide64/src/Glide64/osal_dynamiclib_unix.c [new file with mode: 0755]
source/gles2glide64/src/Glide64/osal_dynamiclib_win32.c [new file with mode: 0755]
source/gles2glide64/src/Glide64/rdp.cpp [new file with mode: 0755]
source/gles2glide64/src/Glide64/rdp.h [new file with mode: 0755]
source/gles2glide64/src/Glide64/ticks.c [new file with mode: 0644]
source/gles2glide64/src/Glide64/ticks.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/turbo3D.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/ucode.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/ucode00.h [new file with mode: 0755]
source/gles2glide64/src/Glide64/ucode01.h [new file with mode: 0755]
source/gles2glide64/src/Glide64/ucode02.h [new file with mode: 0755]
source/gles2glide64/src/Glide64/ucode03.h [new file with mode: 0755]
source/gles2glide64/src/Glide64/ucode04.h [new file with mode: 0755]
source/gles2glide64/src/Glide64/ucode05.h [new file with mode: 0755]
source/gles2glide64/src/Glide64/ucode06.h [new file with mode: 0755]
source/gles2glide64/src/Glide64/ucode07.h [new file with mode: 0755]
source/gles2glide64/src/Glide64/ucode08.h [new file with mode: 0755]
source/gles2glide64/src/Glide64/ucode09.h [new file with mode: 0755]
source/gles2glide64/src/Glide64/ucode09rdp.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/ucodeFB.h [new file with mode: 0644]
source/gles2glide64/src/Glide64/winlnxdefs.h [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/Ext_TxFilter.cpp [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/Ext_TxFilter.h [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/README.txt [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TextureFilters.cpp [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TextureFilters.h [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TextureFilters_2xsai.cpp [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TextureFilters_2xsai.h [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TextureFilters_hq2x.cpp [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TextureFilters_hq2x.h [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TextureFilters_hq4x.cpp [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TextureFilters_hq4x.h [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TextureFilters_lq2x.h [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TxCache.cpp [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TxCache.h [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TxDbg.cpp [new file with mode: 0755]
source/gles2glide64/src/GlideHQ/TxDbg.h [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TxFilter.cpp [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TxFilter.h [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TxFilterExport.cpp [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TxHiResCache.cpp [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TxHiResCache.h [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TxImage.cpp [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TxImage.h [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TxInternal.h [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TxQuantize.cpp [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TxQuantize.h [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TxReSample.cpp [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TxReSample.h [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TxTexCache.cpp [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TxTexCache.h [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TxUtil.cpp [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/TxUtil.h [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/tc-1.1+/dxtn.c [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/tc-1.1+/dxtn.h [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/tc-1.1+/fxt1.c [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/tc-1.1+/fxt1.h [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/tc-1.1+/internal.h [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/tc-1.1+/texstore.c [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/tc-1.1+/types.h [new file with mode: 0644]
source/gles2glide64/src/GlideHQ/tc-1.1+/wrapper.c [new file with mode: 0644]
source/gles2glide64/src/Glitch64/combiner.cpp [new file with mode: 0755]
source/gles2glide64/src/Glitch64/geometry.cpp [new file with mode: 0755]
source/gles2glide64/src/Glitch64/glState.cpp [new file with mode: 0644]
source/gles2glide64/src/Glitch64/glitchmain.cpp [new file with mode: 0755]
source/gles2glide64/src/Glitch64/inc/3dfx.h [new file with mode: 0644]
source/gles2glide64/src/Glitch64/inc/g3ext.h [new file with mode: 0644]
source/gles2glide64/src/Glitch64/inc/glide.h [new file with mode: 0644]
source/gles2glide64/src/Glitch64/inc/glidesys.h [new file with mode: 0644]
source/gles2glide64/src/Glitch64/inc/glideutl.h [new file with mode: 0644]
source/gles2glide64/src/Glitch64/inc/sst1vid.h [new file with mode: 0644]
source/gles2glide64/src/Glitch64/m64p.h [new file with mode: 0644]
source/gles2glide64/src/Glitch64/main.h [new file with mode: 0644]
source/gles2glide64/src/Glitch64/textures.cpp [new file with mode: 0755]
source/gles2glide64/src/Glitch64/textures.cpp.sav [new file with mode: 0755]
source/gles2glide64/src/video_api_export.ver [new file with mode: 0644]
source/gles2glide64/todo!.txt [new file with mode: 0644]

diff --git a/source/gles2glide64/.hgignore b/source/gles2glide64/.hgignore
new file mode 100644 (file)
index 0000000..60b3ba8
--- /dev/null
@@ -0,0 +1,4 @@
+syntax: regexp
+
+^projects/unix/_obj/
+^projects/unix/mupen64plus-video-glide64mk2.so$
diff --git a/source/gles2glide64/INSTALL b/source/gles2glide64/INSTALL
new file mode 100644 (file)
index 0000000..7529bb6
--- /dev/null
@@ -0,0 +1,26 @@
+Mupen64Plus-Video-Glide64mk2 INSTALL
+------------------------------------
+
+This text file was written to explain the installation process of the
+Mupen64Plus-Video-Glide64mk2 module.
+
+If this module is part of a Mupen64Plus source code bundle, the user should run
+the "m64p_install.sh" script in the root of the unzipped bundle to install all
+of the included modules in the bundle.
+
+If this module is a standalone source code release, you should build the library
+from source code and install it via the makefile, like this:
+
+$ cd projects/unix
+$ make all
+$ sudo make install
+
+If you want to build the Mupen64Plus-Video-Glide64mk2 module for installation in a
+home folder for a single user, you may build it like this (replacing
+<my-folder> with your desired local installation path):
+
+$ cd projects/unix
+$ make all
+$ make install LIBDIR=<my-folder> SHAREDIR=<my-folder>
+
+
diff --git a/source/gles2glide64/LICENSES b/source/gles2glide64/LICENSES
new file mode 100644 (file)
index 0000000..fdb70c2
--- /dev/null
@@ -0,0 +1,356 @@
+Mupen64Plus-video-glide64mk2 LICENSE
+------------------------------------
+
+Mupen64Plus-video-glide64mk2 is licensed under the GNU General Public License version 2.
+
+The authors of Mupen64Plus-video-glide64mk2 are:
+  * Sven Eckelmann
+  * Wahrhaft
+  * Riley Labrecque
+  * and others.
+
+Mupen64Plus-video-glide64mk2 is based on the 10th anniversary release of the Glide64
+plugin, which is GPL-licensed and was originally written by Gonetz and others.
+
+                   GNU GENERAL PUBLIC LICENSE  
+                      Version 2, June 1991  
+  
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.  
+                          675 Mass Ave, Cambridge, MA 02139, 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  
+
+
+       Appendix: 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.  
+  
+    <one line to give the program's name and a brief idea of what it does.>  
+    Copyright (C) 19yy  <name of author>  
+  
+    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., 675 Mass Ave, Cambridge, MA 02139, 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) 19yy 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.  
+  
+  <signature of Ty Coon>, 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/source/gles2glide64/Makefile b/source/gles2glide64/Makefile
new file mode 100755 (executable)
index 0000000..ee2e96b
--- /dev/null
@@ -0,0 +1,165 @@
+PIC ?= 1
+NO_ASM := 1
+CFLAGS += -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -mtune=cortex-a8 -fsigned-char -DNO_ASM -DPAULSCODE -Ofast
+CFLAGS += -I ../../../../mupen64plus-bundle-src-2.0/source/mupen64plus-core/src/api/
+CFLAGS += `sdl-config --cflags`
+
+SHARED = -shared
+SRCDIR := src
+
+MODULE := gles2glide64
+SHARED_LIBRARIES := SDL core
+STATIC_LIBRARIES := png
+ARM_MODE := arm
+
+C_INCLUDES :=         \
+    $(M64P_API_INCLUDES)    \
+    $(SDL_INCLUDES)         \
+
+SOURCE :=                  \
+    $(SRCDIR)/Glitch64/combiner.cpp             \
+    $(SRCDIR)/Glitch64/geometry.cpp             \
+    $(SRCDIR)/Glitch64/glitchmain.cpp           \
+    $(SRCDIR)/Glitch64/textures.cpp             \
+    $(SRCDIR)/Glide64/osal_dynamiclib_unix.c    \
+    $(SRCDIR)/Glide64/3dmath.cpp                \
+    $(SRCDIR)/Glide64/Combine.cpp               \
+    $(SRCDIR)/Glide64/Config.cpp                \
+    $(SRCDIR)/Glide64/CRC.cpp                   \
+    $(SRCDIR)/Glide64/Debugger.cpp              \
+    $(SRCDIR)/Glide64/DepthBufferRender.cpp     \
+    $(SRCDIR)/Glide64/FBtoScreen.cpp            \
+    $(SRCDIR)/Glide64/FrameSkipper.cpp          \
+    $(SRCDIR)/Glide64/Ini.cpp                   \
+    $(SRCDIR)/Glide64/Keys.cpp                  \
+    $(SRCDIR)/Glide64/Main.cpp                  \
+    $(SRCDIR)/Glide64/rdp.cpp                   \
+    $(SRCDIR)/Glide64/TexBuffer.cpp             \
+    $(SRCDIR)/Glide64/TexCache.cpp              \
+    $(SRCDIR)/Glide64/ticks.c                   \
+    $(SRCDIR)/Glide64/Util.cpp                  \
+       
+CFLAGS +=         \
+    $(COMMON_CFLAGS)    \
+    -D__CRC_OPT         \
+    -D__HASHMAP_OPT     \
+    -D__TRIBUFFER_OPT   \
+    -D__VEC4_OPT        \
+    -DUSE_SDL           \
+    -fsigned-char       \
+    #-DSDL_NO_COMPAT     \
+    
+ifeq ($(PIC), 1)
+  CFLAGS += -fPIC
+else
+  CFLAGS += -fno-PIC
+endif
+
+CPPFLAGS := $(CPPFLAGS)
+    
+LDLIBS :=         \
+    -lGLESv2           \
+       -lEGL                   \
+       -lrt                    \
+
+# Use for ARM7a:
+CFLAGS += -DARM_ASM
+CFLAGS += -D__NEON_OPT
+
+LDFLAGS += $(SHARED)
+
+include $(BUILD_SHARED_LIBRARY)
+
+# 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) -gdwarf-2 -c
+COMPILE.cc = $(Q_CXX)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -gdwarf-2 -c
+LINK.o = $(Q_LD)$(CXX) $(CXXFLAGS) $(LDFLAGS) $(TARGET_ARCH) -gdwarf-2
+
+# 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
+
+OBJDIR = _obj$(POSTFIX)
+
+# 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-gles2n64.so
+
+targets:
+       @echo "Mupen64plus-video-rice N64 Graphics plugin makefile. "
+       @echo "  Targets:"
+       @echo "    all           == Build Mupen64plus-video-rice plugin"
+       @echo "    clean         == remove object files"
+       @echo "    rebuild       == clean and re-build all"
+       @echo "    install       == Install Mupen64Plus-video-rice plugin"
+       @echo "    uninstall     == Uninstall Mupen64Plus-video-rice 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 "    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)"
+
+uninstall:
+       $(RM) "$(DESTDIR)$(PLUGINDIR)/$(TARGET)"
+
+clean:
+       $(RM) -r $(OBJDIR) $(TARGET)
+
+rebuild: clean all
+
+# build dependency files
+CFLAGS += -MD
+-include $(OBJECTS:.o=.d)
+
+CXXFLAGS += $(CFLAGS)
+
+# standard build rules
+$(OBJDIR)/%.o: $(SRCDIR)/%.c
+       $(COMPILE.c) -o $@ $<
+
+$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
+       $(COMPILE.cc) -o $@ $<
+
+$(TARGET): $(OBJECTS)
+       $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
+
+.PHONY: all clean install uninstall targets
diff --git a/source/gles2glide64/RELEASE b/source/gles2glide64/RELEASE
new file mode 100644 (file)
index 0000000..dc4f5a6
--- /dev/null
@@ -0,0 +1,13 @@
+Mupen64Plus-Video-Glide64mk2 RELEASE
+-------------------------------------
+
+Mupen64Plus-Video-Glide64mk2 v2.0 - July 4, 2013
+------------------------------------------------
+ - lots of bug fixing and cleanup
+ - remove wxwidgets dependencies
+ - ported old 32-bit x86 assembly language code to C for other platforms/CPUs
+ - add Visual Studio 2012 project files
+ - convert to Mupen64Plus build system and API
+ - merged wahrhaft's Glide64 and Glitch64 changes from earlier porting effort
+ - ported later changes from Mudlord's repository
+ - add initial source code from Gonetz's google code repo "10th anniversary Glide64 release"
diff --git a/source/gles2glide64/data/Glide64mk2.ini b/source/gles2glide64/data/Glide64mk2.ini
new file mode 100755 (executable)
index 0000000..045c849
--- /dev/null
@@ -0,0 +1,1776 @@
+;_____________________________________________________________________
+; SETTINGS:
+; This section contains the plugin settings, such as
+; resolution.
+;
+; resolution - specifies which resolution to use
+;  Resolutions are as follows:
+; 0  - 320, 200
+; 1  - 320, 240
+; 2  - 400, 256
+; 3  - 512, 384
+; 4  - 640, 200
+; 5  - 640, 350
+; 6  - 640, 400
+; 7  - 640, 480
+; 8  - 800, 600
+; 9  - 960, 720
+; 10 - 856, 480
+; 11 - 512, 256
+; 12 - 1024, 768
+; 13 - 1280, 1024
+; 14 - 1600, 1200
+; 15 - 400, 300
+; 16 - 1152, 864
+; 17 - 1280, 960
+; 18 - 1600, 1024
+; 19 - 1792, 1344
+; 20 - 1856, 1392
+; 21 - 1920, 1440
+; 22 - 2048, 1536
+; 23 - 2048, 2048
+; Note: some video cards or monitors do not support all
+; resolutions!
+;
+; Note#2:For compatibility issues always distribute this
+; file with the resolution: 640, 480 (7)  
+;
+
+[SETTINGS]
+card_id = 0
+resolution=8
+filter_cache = 0
+autodetect_ucode = 1
+ucode = 2
+wireframe = 0
+wfmode=1
+filtering = 1
+depthmode = 0
+fog = 1
+buff_clear = 1
+vsync = 1
+swapmode = 1
+run_in_window = 0
+show_fps = 0
+clock = 0
+clock_24_hr = 0
+wrap_big_tex = 0
+custom_ini = 1
+hotkeys = 1
+ssformat=1
+logging = 0
+log_clear = 0
+unk_as_red = 0
+log_unk = 0
+unk_clear = 0
+new_swap = 1
+hires_motionblur = 0
+flame_corona = 0
+fb_smart = 1
+fb_read_always = 0
+fb_clear = 0
+fb_hires = 1
+fb_depth_clear = 0
+motionblur = 1
+elogging = 0
+lodmode = 0
+fb_get_info = 0
+fb_render = 1
+detect_cpu_write = 0
+fillrec_depth_compare = 0
+tex_wrap_hack = 0
+read_back_to_screen = 0
+advanced_options = 0
+texenh_options = 0
+ghq_fltr = 0
+ghq_cmpr = 0
+ghq_enht = 0
+ghq_hirs = 0
+ghq_enht_cmpr = 0
+ghq_enht_tile = 0
+ghq_enht_f16bpp = 0
+ghq_enht_gz = 1
+ghq_enht_nobg=0
+ghq_hirs_cmpr = 0
+ghq_hirs_tile = 0
+ghq_hirs_f16bpp = 0
+ghq_hirs_gz = 1
+ghq_hirs_altcrc = 1
+ghq_cache_save = 1
+ghq_cache_size=0
+ghq_hirs_let_texartists_fly = 0
+ghq_hirs_dump = 0
+wrpResolution=0
+wrpVRAM=0
+wrpFBO=0
+wrpAnisotropic=0
+
+; 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=0
+0bf36d36=9
+0d7bbffb=-1 
+0d7cbffb=5
+0ff79527=2
+0ff795bf=-1 
+1118b3e0=1
+1517a281=1
+168e9cd5=2
+1a1e18a0=2
+1a1e1920=2
+1a62dbaf=2
+1a62dc2f=2
+1de712ff=1
+1ea9e30f=6
+1f120bbb=21
+21f91834=2
+21f91874=2
+22099872=2
+24cd885b=1
+26a7879a=1
+299d5072=6
+2b291027=2
+2b5a89c2=6
+2c7975d6=1
+2d3fe3f1=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
+832fcb99=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
+d67c2f8b=0
+d802ec04=1
+da13ab96=2
+de7d67d4=2
+e1290fa2=2
+e41ec47e=0
+e65cb4ad=2
+e89c2b92=1
+e9231df2=1
+ec040469=1
+ee47381b=1
+ef54ee35=1
+f9893f70=21
+fb816260=1
+ff372492=21
+
+
+
+; 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.
+
+[DEFAULT]
+filtering = 0
+fog = 1
+buff_clear = 1
+swapmode = 1
+lodmode = 0
+fb_smart = 0
+fb_hires = 1
+fb_get_info = 0
+fb_read_always = 0
+fb_render = 1
+fb_crc_mode = 1
+read_back_to_screen = 0
+detect_cpu_write = 0
+alt_tex_size = 0
+use_sts1_only = 0
+PPL = 0
+fast_crc = 1
+force_microcheck = 0
+force_quad3d = 0
+texrect_zbuf = 0
+fix_tex_coord = 0
+optimize_texrect = 1
+optimize_write = 0
+hires_buf_clear = 1
+depthmode = 1
+fb_clear = 0
+fb_read_alpha = 0
+ignore_previous = 0
+soft_depth_compare = 0
+force_depth_compare = 0
+force_calc_sphere = 0
+texrect_compare_less = 0
+texture_correction = 1
+fillcolor_fix = 0
+depth_bias = 20
+increase_texrect_edge = 0
+decrease_fillrect_edge = 0
+stipple_mode = 2
+stipple_pattern = 1041204192
+clip_zmax = 1
+clip_zmin = 0
+adjust_aspect = 1
+correct_viewport = 0
+aspect = 0
+zmode_compare_less = 0
+old_style_adither = 0
+n64_z_scale = 0
+
+[1080 SNOWBOARDING]
+optimize_texrect = 1
+alt_tex_size = 1
+depthmode = 0
+swapmode = 2
+fb_smart = 1
+fb_hires = 1
+fb_clear = 1
+
+[A Bug's Life]
+depthmode = 0
+
+[AERO FIGHTERS ASSAUL]
+clip_zmin = 1
+
+[AIDYN_CHRONICLES]
+depthmode = 1
+
+[All-Star Baseball 20] 
+force_depth_compare = 1 
+
+[All-Star Baseball 99]
+force_depth_compare = 1
+depthmode = 1
+buff_clear = 0
+
+[All Star Baseball 99]
+force_depth_compare = 1
+depthmode = 1
+buff_clear = 0
+
+[All-Star Baseball '0]
+force_depth_compare = 1
+depthmode = 0
+fb_smart = 1
+fb_hires = 1
+
+[ARMYMENAIRCOMBAT]
+increase_texrect_edge = 1
+depthmode = 1
+
+[BURABURA POYON]
+fix_tex_coord = 1
+depthmode = 0
+
+;Bakushou Jinsei 64 - Mezease! Resort Ou.
+[ÊÞ¸¼®³¼Þݾ²64]
+fb_info_disable = 1
+depthmode = 0
+
+[BAKU-BOMBERMAN]
+depthmode = 0
+fb_smart = 1
+fb_hires = 1
+
+[BAKUBOMB2]
+filtering = 1
+depthmode = 0
+
+[BANGAIOH]
+depthmode = 1
+
+[Banjo-Kazooie]
+filtering = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+
+[BANJO KAZOOIE 2]
+filtering = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+
+[BANJO TOOIE]
+filtering = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+
+[BASS HUNTER 64]
+fix_tex_coord = 1
+depthmode = 1
+buff_clear = 0
+swapmode = 2
+
+[BATTLEZONE]
+force_depth_compare = 1
+depthmode = 1
+
+[BEETLE ADVENTURE JP]
+wrap_big_tex = 1
+n64_z_scale = 1
+filtering = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+
+[Beetle Adventure Rac]
+wrap_big_tex = 1
+n64_z_scale = 1
+filtering = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+
+[Big Mountain 2000]
+depthmode = 1
+
+[BIOFREAKS]
+depthmode = 0
+buff_clear = 0
+fb_smart = 1
+fb_hires = 1
+
+[BioHazard II]
+detect_cpu_write = 1
+adjust_aspect = 0
+n64_z_scale = 1
+fix_tex_coord = 128
+depthmode = 0
+swapmode = 2
+fb_smart = 1
+fb_hires = 1
+
+[Blast Corps]
+depthmode = 1
+swapmode = 0
+fb_smart = 1
+fb_hires = 1
+fb_read_alpha = 1
+
+[Blastdozer]
+depthmode = 1
+swapmode = 0
+fb_smart = 1
+fb_hires = 1
+fb_read_alpha = 1
+
+[blitz2k]
+lodmode = 2
+
+[Body Harvest]
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+
+[BOMBERMAN64E]
+depthmode = 0
+fb_smart = 1
+fb_hires = 1
+
+[BOMBERMAN64U]
+depthmode = 0
+fb_smart = 1
+fb_hires = 1
+
+[BOMBERMAN64U2]
+filtering = 1
+depthmode = 0
+
+[Bottom of the 9th]
+optimize_texrect = 0
+filtering = 1
+depthmode = 0
+fb_smart = 1
+fb_hires = 1
+
+[BRUNSWICKBOWLING]
+depthmode = 0
+buff_clear = 0
+swapmode = 0
+
+[Bust A Move 3 DX]
+filtering = 2
+depthmode = 1
+
+[Bust A Move '99]
+filtering = 2
+depthmode = 1
+
+[Bust A Move 2]
+fix_tex_coord = 1
+filtering = 2
+depthmode = 1
+fog = 0
+
+[CARMAGEDDON64]
+wrap_big_tex = 1
+filtering = 1
+depthmode = 1
+
+[CASTLEVANIA]
+depthmode = 0
+fb_clear = 1
+old_style_adither = 1
+
+[CASTLEVANIA2]
+depthmode = 0
+fb_clear = 1
+
+[CENTRE COURT TENNIS]
+soft_depth_compare = 1
+depthmode = 0
+
+[Chameleon Twist2]
+filtering = 1
+depthmode = 0
+
+[CHOPPER_ATTACK]
+filtering = 1
+depthmode = 0
+
+[CITY TOUR GP]
+force_microcheck = 1
+filtering = 1
+depthmode = 1
+
+[Command&Conquer]
+fix_tex_coord = 1
+aspect = 2
+filtering = 1
+depthmode = 1
+fog = 0
+
+[CONKER BFD]
+optimize_texrect = 1
+ignore_previous = 1
+lodmode = 1
+filtering = 1
+depthmode = 0
+fb_smart = 1
+fb_hires = 1
+fb_clear = 1
+
+[Cruis'n USA]
+filtering = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+fb_clear = 1
+
+[CruisnExotica]
+filtering = 1
+depthmode = 1
+buff_clear = 0
+swapmode = 0
+
+[custom robo]
+depthmode = 0
+fb_smart = 1
+fb_hires = 1
+
+[CUSTOMROBOV2]
+depthmode = 0
+fb_smart = 1
+fb_hires = 1
+
+[CyberTiger]
+fix_tex_coord = 16
+depthmode = 0
+
+[DAFFY DUCK STARRING]
+depthmode = 1
+wrap_big_tex = 1
+
+[DARK RIFT]
+force_microcheck = 1
+
+[DeadlyArts]
+soft_depth_compare = 1
+depthmode = 0
+fb_smart = 1
+fb_hires = 1
+clip_zmin = 1
+
+[DERBYSTALLION 64]
+fix_tex_coord = 1
+depthmode = 0
+
+[D K DISPLAY]
+depthmode = 1
+fb_clear = 1
+
+[Donald Duck Goin' Qu]
+detect_cpu_write = 1
+depthmode = 0
+
+[Donald Duck Quack At]
+detect_cpu_write = 1
+depthmode = 0
+
+[DONKEY KONG 64]
+lodmode = 1
+depth_bias = 64
+depthmode = 1
+fb_clear = 1
+
+[Doom64]
+fillcolor_fix = 1
+depthmode = 1
+
+;Doraemon - Mittsu no Seireiseki (J)
+[ÄÞ×´ÓݠЯÂɾ²Ú²¾·]
+read_back_to_screen = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+
+;Doraemon 3 - Nobita no Machi SOS! (J)
+[ÄÞ×´ÓÝ3 ÉËÞÀÉÏÁSOS!]
+clip_zmin = 1
+
+[DR.MARIO 64]
+fix_tex_coord = 256
+optimize_write = 1
+read_back_to_screen = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 0
+
+[DRACULA MOKUSHIROKU]
+depthmode = 0
+fb_clear = 1
+
+[DRACULA MOKUSHIROKU2]
+depthmode = 0
+fb_clear = 1
+
+[Dual heroes JAPAN]
+filtering = 1
+depthmode = 0
+swapmode = 0
+
+[Dual heroes PAL]
+filtering = 1
+depthmode = 0
+swapmode = 0
+
+[Dual heroes USA]
+filtering = 1
+depthmode = 0
+swapmode = 0
+
+[DUKE NUKEM]
+increase_primdepth = 1
+depthmode = 0
+
+[EARTHWORM JIM 3D]
+increase_primdepth = 1
+filtering = 1
+depthmode = 0
+buff_clear = 0
+
+;Eikou no Saint Andrew
+[´²º³É¾ÝıÝÄÞØ­°½]
+correct_viewport = 1
+
+[Eltail]
+filtering = 2
+depthmode = 1
+
+[EVANGELION]
+depthmode = 1
+
+[EXCITEBIKE64]
+depthmode = 0
+fb_smart = 1
+fb_hires = 1
+
+[extreme_g]
+depthmode = 0
+fb_smart = 1
+fb_hires = 1
+
+[extremeg]
+depthmode = 0
+fb_smart = 1
+fb_hires = 1
+
+[´¸½ÄØ°ÑG2]
+depthmode = 0
+fb_smart = 1
+fb_hires = 1
+fb_clear = 1
+
+[Extreme G 2]
+depthmode = 0
+fb_smart = 1
+fb_hires = 1
+fb_clear = 1
+
+[F1 POLE POSITION 64]
+clip_zmin = 1
+filtering = 2
+depthmode = 1
+
+[F1RacingChampionship]
+depthmode = 0
+buff_clear = 0
+swapmode = 0
+
+[F1 WORLD GRAND PRIX]
+soft_depth_compare = 1
+wrap_big_tex = 1
+depthmode = 0
+buff_clear = 0
+
+[F1 WORLD GRAND PRIX2]
+wrap_big_tex = 1
+soft_depth_compare = 1
+depthmode = 0
+buff_clear = 0
+
+[F-ZERO X]
+depthmode = 1
+
+;Fushigi no Dungeon - Furai no Shiren 2 (J) 
+[F3 Ì³×²É¼ÚÝ2]
+decrease_fillrect_edge = 1
+depthmode = 0
+
+[Fighting Force]
+depthmode = 1
+
+[G.A.S.P!!Fighters'NE]
+soft_depth_compare = 1
+depthmode = 0
+fb_smart = 1
+fb_hires = 1
+clip_zmin = 1
+
+[GANBAKE GOEMON]
+optimize_texrect = 0
+alt_tex_size = 1
+filtering = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+
+;Ganbare Goemon - Neo Momoyama Bakufu no Odori
+[¶ÞÝÊÞÚ\ ºÞ´ÓÝ]
+optimize_texrect = 0
+alt_tex_size = 1
+filtering = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+
+[GAUNTLET LEGENDS]
+depthmode = 1
+swapmode = 2
+
+[Getter Love!!]
+zmode_compare_less = 1
+texrect_compare_less = 1
+filtering = 2
+depthmode = 1
+
+[Gex 3 Deep Cover Gec]
+filtering = 1
+depthmode = 0
+
+[GEX: ENTER THE GECKO]
+filtering = 1
+depthmode = 0
+
+[Glover]
+filtering = 1
+depthmode = 0
+
+[GOEMON2 DERODERO]
+filtering = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+
+[GOEMONS GREAT ADV]
+filtering = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+
+[GOLDENEYE]
+lodmode = 1
+depth_bias = 40
+filtering = 1
+depthmode = 0
+fb_smart = 1
+fb_hires = 1
+
+[GOLDEN NUGGET 64]
+filtering = 2
+depthmode = 1
+
+[GT64]
+force_microcheck = 1
+filtering = 1
+depthmode = 1
+
+; Hamster Monogatori
+[ÊѽÀ°ÓɶÞÀØ64]
+force_microcheck = 1
+depthmode = 0
+
+[HARVESTMOON64]
+zmode_compare_less = 1
+depthmode = 0
+fog = 0
+
+; Harvest Moon 64 JAP
+[ÎÞ¸¼Þ®³ÓɶÞÀØ2]
+zmode_compare_less = 1
+depthmode = 0
+fog = 0
+
+; Heiwa Pachinko World
+[HEIWA ÊßÁݺ Ü°ÙÄÞ64]
+depthmode = 0
+fog = 0
+swapmode = 2
+fb_smart = 1
+fb_hires = 1
+
+[HEXEN]
+detect_cpu_write = 1
+filtering = 1
+depthmode = 1
+buff_clear = 0
+swapmode = 2
+
+[HSV ADVENTURE RACING]
+wrap_big_tex = 1
+n64_z_scale = 1
+filtering = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+
+[Holy Magic Century]
+filtering = 2
+depthmode = 1
+
+[HUMAN GRAND PRIX]
+filtering = 2
+depthmode = 0
+
+[·×¯Ä¶²¹Â 64ÀÝòÀÞÝ]
+filtering = 1
+depthmode = 0
+buff_clear = 0
+
+[Iggy's Reckin' Balls]
+fix_tex_coord = 512
+depthmode = 0
+
+[I S S 64]
+depthmode = 1
+swapmode = 2
+old_style_adither = 1
+
+[I.S.S.2000]
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+
+[ITF 2000]
+filtering = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+
+[IT&F SUMMERGAMES]
+filtering = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+
+[J_league 1997]
+fix_tex_coord = 1
+depthmode = 1
+swapmode = 0
+
+;J.League Eleven Beat 1997
+[JØ°¸Þ\ ²ÚÌÞÝËÞ°Ä1997]
+fb_smart=1
+fb_hires=1
+
+[J LEAGUE LIVE 64]
+wrap_big_tex = 1
+depthmode = 1
+
+[J WORLD SOCCER3]
+depthmode = 1
+swapmode = 2
+
+[JEREMY MCGRATH SUPER]
+depthmode = 0
+swapmode = 0
+
+[JET FORCE GEMINI]
+read_back_to_screen = 1
+decrease_fillrect_edge = 1
+alt_tex_size = 1
+depthmode = 1
+swapmode = 2
+fb_smart = 1
+fb_hires = 1
+
+[J F G DISPLAY]
+read_back_to_screen = 1
+decrease_fillrect_edge = 1
+alt_tex_size = 1
+depthmode = 1
+swapmode = 2
+fb_smart = 1
+fb_hires = 1
+
+[KEN GRIFFEY SLUGFEST]
+read_back_to_screen = 2
+depthmode = 1
+swapmode = 0
+fb_smart = 1
+fb_hires = 1
+
+[Kirby64]
+filtering = 1
+depthmode = 0
+buff_clear = 0
+swapmode = 0
+
+[Killer Instinct Gold]
+filtering = 1
+depthmode = 0
+fog = 0
+buff_clear = 0
+
+[KNIFE EDGE]
+wrap_big_tex = 1
+fast_crc = 0
+filtering = 1
+depthmode = 1
+
+[Knockout Kings 2000]
+fb_info_disable = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+fb_clear = 1
+fb_read_alpha = 1
+
+[LAMBORGHINI]
+use_sts1_only = 1
+
+[LCARS - WT_Riker]
+depthmode = 1
+
+[LEGORacers]
+detect_cpu_write = 1
+depthmode = 1
+buff_clear = 0
+fb_smart = 1
+fb_hires = 1
+fb_read_alpha = 1
+
+[LET'S SMASH]
+soft_depth_compare = 1
+depthmode = 0
+
+[Lode Runner 3D] 
+swapmode = 0
+
+[LT DUCK DODGERS]
+wrap_big_tex = 1
+depthmode = 1
+
+[MACE]
+fix_tex_coord = 8
+filtering = 1
+depthmode = 1
+
+[MAGICAL TETRIS]
+force_microcheck = 1
+depthmode = 1
+fog = 0
+
+;Mahjong Master (J)
+[Ï°¼Þ¬Ý Ï½À°]
+n64_z_scale = 1
+texrect_compare_less = 1
+zmode_compare_less = 1
+
+[MAJORA'S MASK]
+wrap_big_tex = 1
+filtering = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+fb_clear = 1
+fb_crc_mode = 0
+
+[MARIOKART64]
+fast_crc = 0
+stipple_mode = 1
+stipple_pattern = 4286595040
+depthmode = 1
+
+[MarioGolf64]
+fb_info_disable = 1
+ignore_aux_copy = 1
+buff_clear = 0
+depthmode = 0
+fb_smart = 1
+fb_hires = 1
+fb_clear = 1
+
+[MarioParty]
+clip_zmin = 1
+depthmode = 0
+swapmode = 2
+
+[MarioParty2]
+depthmode = 0
+swapmode = 2
+
+[MarioParty3]
+fix_tex_coord = 1
+depthmode = 0
+
+[MARIO STORY]
+useless_is_useless = 1
+hires_buf_clear = 0
+optimize_texrect = 0
+filtering = 1
+depthmode = 1
+swapmode = 2
+fb_smart = 1
+fb_hires = 1
+fb_read_alpha = 1
+
+[MASTERS'98]
+wrap_big_tex = 1
+depthmode = 0
+fb_smart = 1
+fb_hires = 1
+
+[Mega Man 64]
+increase_texrect_edge = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+
+[MGAH VOL1]
+force_microcheck = 1
+depthmode = 1
+zmode_compare_less = 1
+fb_smart = 1
+
+[Mia Hamm Soccer 64]
+buff_clear = 0
+
+[MICKEY USA]
+alt_tex_size = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+fb_clear = 1
+
+[MICKEY USA PAL]
+alt_tex_size = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+fb_clear = 1
+
+[MICROMACHINES64TURBO]
+depthmode = 0
+
+[Mini Racers]
+force_microcheck = 1
+buff_clear = 0
+fb_smart = 1
+fb_hires = 1
+swapmode = 0
+
+[MISCHIEF MAKERS]
+tex_wrap_hack = 0
+depthmode = 1
+fog = 0
+
+[MLB FEATURING K G JR]
+read_back_to_screen = 2
+depthmode = 1
+
+[MK_MYTHOLOGIES]
+depthmode = 1
+
+[MO WORLD LEAGUE SOCC]
+buff_clear = 0
+
+[Monaco GP Racing 2]
+depthmode = 0
+buff_clear = 0
+
+[Monaco Grand Prix]
+depthmode = 0
+buff_clear = 0
+
+;Morita Shogi 64
+[ÓØÀ¼®³·Þ64]
+correct_viewport = 1
+
+[MortalKombatTrilogy]
+filtering = 2
+depthmode = 1
+
+[MS. PAC-MAN MM]
+detect_cpu_write = 1
+depthmode = 1
+
+[MYSTICAL NINJA]
+alt_tex_size = 1
+optimize_texrect = 0
+filtering = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+
+[MYSTICAL NINJA2 SG]
+alt_tex_size = 1
+optimize_texrect = 0
+filtering = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+
+[NASCAR 99]
+depthmode = 0
+buff_clear = 0
+swapmode = 0
+
+[NASCAR 2000]
+depthmode = 0
+buff_clear = 0
+swapmode = 0
+
+[NBA Courtside 2]
+depthmode = 0
+buff_clear = 0
+swapmode = 0
+
+[NBA JAM 2000]
+buff_clear = 0
+
+[NBA JAM 99]
+buff_clear = 0
+
+[NBA LIVE 2000]
+adjust_aspect = 0
+
+[NBA Live 99]
+swapmode = 0
+adjust_aspect = 0
+
+[NEWTETRIS]
+pal230 = 1
+fix_tex_coord = 1
+increase_texrect_edge = 1
+depthmode = 0
+fog = 0
+
+[NFL BLITZ]
+lodmode = 2
+
+[NFL BLITZ 2001]
+lodmode = 2
+
+[NFL BLITZ SPECIAL ED]
+lodmode = 2
+
+[NFL QBC '99]
+force_depth_compare = 1
+wrap_big_tex = 1
+depthmode = 0
+
+[NFL QBC 2000]
+wrap_big_tex = 1
+depthmode = 0
+swapmode = 0
+
+[NFL Quarterback Club]
+wrap_big_tex = 1
+depthmode = 0
+swapmode = 0
+
+[NINTAMAGAMEGALLERY64]
+force_microcheck = 1
+depthmode = 0
+
+[NITRO64] 
+fb_smart = 1 
+fb_hires = 1
+
+[NUCLEARSTRIKE64]
+buff_clear = 0
+
+; Nushi Zuri 64
+[ǼÂÞØ64]
+force_microcheck = 1
+wrap_big_tex = 0
+depthmode = 0
+buff_clear = 0
+
+[OgreBattle64]
+fb_info_disable = 1
+force_depth_compare = 1
+depthmode = 1
+
+[PACHINKO365NICHI]
+correct_viewport = 1
+
+[PAPER MARIO]
+useless_is_useless = 1
+hires_buf_clear = 0
+optimize_texrect = 0
+filtering = 1
+depthmode = 1
+swapmode = 2
+fb_smart = 1
+fb_hires = 1
+fb_read_alpha = 1
+
+[Parlor PRO 64]
+force_microcheck = 1
+filtering = 1
+depthmode = 1
+
+[Perfect Dark]
+useless_is_useless = 1
+decrease_fillrect_edge = 1
+optimize_texrect = 0
+filtering = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+fb_clear = 1
+
+[PERFECT STRIKER]
+depthmode = 1
+swapmode = 2
+
+[Pilot Wings64]
+depthmode = 1
+buff_clear = 0
+
+[PUZZLE LEAGUE N64]
+PPL = 1
+force_microcheck = 1
+fix_tex_coord = 1
+filtering = 2
+depthmode = 1
+fog = 0
+buff_clear = 0
+fb_smart = 1
+fb_hires = 0
+fb_read_alpha = 1
+
+[PUZZLE LEAGUE]
+PPL = 1
+force_microcheck = 1
+fix_tex_coord = 1
+filtering = 2
+depthmode = 1
+fog = 0
+buff_clear = 0
+fb_smart = 1
+fb_hires = 0
+fb_read_alpha = 1
+
+[POKEMON SNAP]
+fast_crc = 0
+depthmode = 1
+fb_smart = 1
+fb_hires = 0
+fb_clear = 1
+
+[POKEMON STADIUM]
+optimize_texrect = 0
+depthmode = 1
+fast_crc = 0
+buff_clear = 0
+fb_smart = 1
+fb_hires = 0
+fb_read_alpha = 1
+fb_crc_mode = 2
+
+[POKEMON STADIUM 2]
+optimize_texrect = 0
+swapmode = 2
+depthmode = 1
+fast_crc = 0
+buff_clear = 0
+fb_smart = 1
+fb_hires = 1
+fb_read_alpha = 1
+fb_crc_mode = 2
+
+[POKEMON STADIUM G&S]
+optimize_texrect = 0
+depthmode = 1
+fast_crc = 0
+buff_clear = 0
+fb_smart = 1
+fb_hires = 0
+fb_read_alpha = 1
+fb_crc_mode = 2
+
+[POLARISSNOCROSS]
+fix_tex_coord = 5
+depthmode = 1
+
+[PowerLeague64]
+force_quad3d = 1
+
+[Quake]
+force_microcheck = 1
+swapmode = 2
+buff_clear = 0
+
+[QUAKE II]
+fb_smart = 1
+fb_hires = 1
+
+[quarterback_club_98]
+optimize_texrect = 0
+hires_buf_clear = 0
+filtering = 1
+depthmode = 1
+swapmode = 0
+buff_clear = 0
+fb_smart = 1
+fb_hires = 1
+fb_read_alpha = 1
+
+[Quest 64]
+depthmode = 1
+
+[Racing Simulation 2] 
+depthmode = 0
+buff_clear = 0
+
+[RAINBOW SIX]
+increase_texrect_edge = 1
+depthmode = 1
+
+[Rally'99]
+filtering = 1
+depthmode = 1
+buff_clear = 0
+fb_smart = 1
+fb_hires = 1
+
+[RALLY CHALLENGE]
+filtering = 1
+depthmode = 1
+buff_clear = 0
+fb_smart = 1
+fb_hires = 1
+
+[Rayman 2]
+depthmode = 0
+detect_cpu_write = 1
+
+[READY 2 RUMBLE]
+fix_tex_coord = 64
+depthmode = 0
+
+[Ready to Rumble]
+fix_tex_coord = 1
+depthmode = 0
+
+[Resident Evil II]
+detect_cpu_write = 1
+adjust_aspect = 0
+n64_z_scale = 1
+fix_tex_coord = 128
+depthmode = 0
+swapmode = 2
+fb_smart = 1
+fb_hires = 1
+
+[Re-Volt]
+texture_correction = 0
+depthmode = 1
+
+[RIDGE RACER 64]
+force_calc_sphere = 1
+depthmode = 0
+fb_smart = 1
+fb_hires = 1
+
+[ROAD RASH 64]
+depthmode = 0
+swapmode = 2
+
+[Robopon64]
+depthmode = 0
+fb_smart = 1
+fb_hires = 1
+
+[ROCKETROBOTONWHEELS]
+clip_zmin = 1
+
+[RockMan Dash]
+increase_texrect_edge = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+
+[RONALDINHO SOCCER]
+depthmode = 1
+swapmode = 2
+old_style_adither = 1
+
+[RTL WLS2000]
+buff_clear = 0
+
+[RUGRATS IN PARIS]
+depthmode = 1
+
+[RUSH 2049]
+force_texrect_zbuf = 1
+filtering = 1
+depthmode = 0
+
+[SCARS]
+filtering = 1
+depthmode = 0
+
+[SD HIRYU STADIUM]
+force_microcheck = 1
+depthmode = 0
+
+[Shadow of the Empire]
+swapmode = 2
+
+[Shadowman]
+depthmode = 0
+
+[Silicon Valley]
+filtering = 1
+depthmode = 0
+
+[Snobow Kids 2]
+swapmode = 0
+filtering = 1
+
+[SNOWBOARD KIDS2]
+swapmode = 0
+filtering = 1
+
+[South Park: Chef's L]
+fix_tex_coord = 4
+filtering = 2
+depthmode = 1
+fog = 0
+buff_clear = 0
+
+[South Park Chef's Lu]
+fix_tex_coord = 4
+filtering = 1
+depthmode = 1
+fog = 0
+buff_clear = 0
+
+[SPACE DYNAMITES] 
+force_microcheck = 1
+
+[SPIDERMAN]
+fast_crc = 0
+
+[STARCRAFT 64]
+detect_cpu_write = 1
+aspect = 2
+filtering = 2
+depthmode = 1
+fog = 0
+
+[STAR SOLDIER]
+force_microcheck = 1
+filtering = 1
+depthmode = 1
+swapmode = 0
+
+[STAR TWINS]
+read_back_to_screen = 1
+decrease_fillrect_edge = 1
+alt_tex_size = 1
+depthmode = 1
+swapmode = 2
+fb_smart = 1
+fb_hires = 1
+
+[STAR WARS EP1 RACER]
+swapmode = 2
+
+[SUPERROBOTSPIRITS]
+aspect = 2
+
+;Super Robot Taisen 64 (J)
+[½°Êß°ÛÎÞ¯ÄÀ²¾Ý64]
+fast_crc = 0
+use_sts1_only = 1
+fb_smart = 1
+fb_hires = 1
+
+[Supercross]
+depthmode = 1
+buff_clear = 0
+
+[SUPER MARIO 64]
+depth_bias = 32
+lodmode = 1
+filtering = 1
+depthmode = 1
+
+[SUPERMARIO64]
+depth_bias = 32
+lodmode = 1
+filtering = 1
+depthmode = 1
+
+[SUPERMAN]
+detect_cpu_write = 1
+
+;Susume! Taisen Puzzle Dama Toukon! Marumata Chou (J) 
+[½½Ò!À²¾ÝÊß½ÞÙÀÞÏ]
+force_microcheck = 1
+depthmode = 1
+fog = 0
+swapmode = 0
+
+;Tamagotchi World 64 (J) 
+[ÐÝÅÃÞÀϺޯÁÜ°ÙÄÞ]
+use_sts1_only = 1
+depthmode = 0
+fog = 0
+
+[Taz Express]
+filtering = 1
+depthmode = 0
+buff_clear = 0
+
+[TELEFOOT SOCCER 2000]
+buff_clear = 0
+
+[TETRISPHERE]
+alt_tex_size = 1
+use_sts1_only = 1
+increase_texrect_edge = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+fb_crc_mode = 2
+
+[TG RALLY 2]
+filtering = 1
+depthmode = 1
+buff_clear = 0
+swapmode = 2
+
+[THE LEGEND OF ZELDA]
+depth_bias = 60
+filtering = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+fb_clear = 1
+
+[THE MASK OF MUJURA]
+wrap_big_tex = 1
+filtering = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+fb_clear = 1
+fb_crc_mode = 0
+
+[THPS2]
+filtering = 1
+depthmode = 0
+
+[THPS3]
+filtering = 1
+depthmode = 0
+
+[Tigger's Honey Hunt]
+zmode_compare_less = 1
+depthmode = 0
+buff_clear = 0
+
+[TOM AND JERRY]
+depth_bias = 2
+filtering = 1
+depthmode = 0
+
+[Tonic Trouble]
+depthmode = 0
+detect_cpu_write = 1
+
+[TONY HAWK PRO SKATER]
+filtering = 1
+depthmode = 0
+
+[TONY HAWK SKATEBOARD]
+filtering = 1
+depthmode = 0
+
+[Top Gear Hyper Bike]
+fb_info_disable = 1
+swapmode = 2
+depthmode = 0
+fb_smart = 1
+fb_hires = 1
+fb_clear = 1
+
+[Top Gear Overdrive]
+fb_info_disable = 1
+depthmode = 0
+buff_clear = 0
+
+[TOP GEAR RALLY]
+depth_bias = 64
+fillcolor_fix = 1
+depthmode = 0
+
+[TOP GEAR RALLY 2]
+filtering = 1
+depthmode = 1
+buff_clear = 0
+swapmode = 2
+
+[TRIPLE PLAY 2000]
+wrap_big_tex = 1
+depthmode = 0
+fb_smart = 1
+fb_hires = 1
+
+[TROUBLE MAKERS]
+mischief_tex_hack = 0
+depthmode = 1
+fog = 0
+
+[TSUMI TO BATSU]
+filtering = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+fb_clear = 1
+
+[TSUWAMONO64]
+force_microcheck = 1
+depthmode = 0
+
+[TWINE]
+filtering = 1
+depthmode = 0
+
+[TWISTED EDGE]
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+fb_clear = 1
+
+[Ultraman Battle JAPA]
+depthmode = 0
+
+[Virtual Pool 64]
+depthmode = 1
+buff_clear = 0
+
+[V-RALLY]
+fix_tex_coord = 3
+filtering = 1
+depthmode = 0
+buff_clear = 0
+swapmode = 0
+
+[Waialae Country Club]
+wrap_big_tex = 1
+depthmode = 0
+fb_smart = 1
+fb_hires = 1
+
+[WAVE RACE 64]
+pal230 = 1
+
+[WILD CHOPPERS]
+filtering = 1
+depthmode = 0
+
+[Wipeout 64]
+filtering = 1
+depthmode = 0
+swapmode = 2
+
+[WONDER PROJECT J2]
+depthmode = 0
+buff_clear = 0
+swapmode = 0
+
+[World Cup 98] 
+depthmode = 0
+swapmode = 0
+fb_smart = 1
+fb_hires = 1
+
+[WRESTLEMANIA 2000]
+depthmode = 0
+
+[YAKOUTYUU2]
+depthmode = 0
+
+[YOSHI STORY]
+fix_tex_coord = 32
+filtering = 1
+depthmode = 1
+fog = 0
+
+[ZELDA MAJORA'S MASK]
+wrap_big_tex = 1
+filtering = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+fb_clear = 1
+fb_crc_mode = 0
+
+[ZELDA MASTER QUEST]
+depth_bias = 60
+filtering = 1
+depthmode = 1
+fb_smart = 1
+fb_hires = 1
+fb_clear = 1
+
+[MUPEN64PLUS]
+
+;End Of Original File
diff --git a/source/gles2glide64/doc/fxt1-license b/source/gles2glide64/doc/fxt1-license
new file mode 100644 (file)
index 0000000..234c6c6
--- /dev/null
@@ -0,0 +1,244 @@
+3DFX FXT1 Source Code General Public License
+
+
+1. PREAMBLE
+
+       This license is for software that provides texture compression and 
+       decompression, particularly in the context of video games. 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 FXT1 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 FXT1 Source Code General 
+       Public License. 
+
+       2.2 The term "Program" as used in this Agreement refers to 3DFX's 
+       FXT1 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 texture compression and decompression. 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 FXT1 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) 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) 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. SEE THE 3DFX FXT1 GENERAL PUBLIC LICENSE
+       FOR A FULL TEXT OF THE DISTRIBUTION AND NON-WARRANTY PROVISIONS 
+       (REQUEST COPY FROM INFO@3DFX.COM)."
+
+               (g) 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 FXT1 GENERAL PUBLIC LICENSE. 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 FXT1 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 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/source/gles2glide64/doc/gpl-license b/source/gles2glide64/doc/gpl-license
new file mode 100644 (file)
index 0000000..d511905
--- /dev/null
@@ -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.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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.
+
+  <signature of Ty Coon>, 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/source/gles2glide64/pandora.diff b/source/gles2glide64/pandora.diff
new file mode 100644 (file)
index 0000000..b1a10fe
--- /dev/null
@@ -0,0 +1,1500 @@
+diff -Naur ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glide64/3dmath.cpp ./Glide64/3dmath.cpp
+--- ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glide64/3dmath.cpp     2013-09-06 22:05:28.000000000 +0200
++++ ./Glide64/3dmath.cpp       2013-09-14 09:41:13.000000000 +0200
+@@ -202,15 +202,109 @@
+   }
+ }
++#ifdef __ARM_NEON__
++void MultMatrix_neon( float m0[4][4], float m1[4][4], float dest[4][4])
++{
++    asm volatile (
++      "vld1.32                {d0, d1}, [%1]!                 \n\t"   //q0 = m1
++      "vld1.32                {d2, d3}, [%1]!         \n\t"   //q1 = m1+4
++      "vld1.32                {d4, d5}, [%1]!         \n\t"   //q2 = m1+8
++      "vld1.32                {d6, d7}, [%1]          \n\t"   //q3 = m1+12
++      "vld1.32                {d16, d17}, [%0]!               \n\t"   //q8 = m0
++      "vld1.32                {d18, d19}, [%0]!       \n\t"   //q9 = m0+4
++      "vld1.32                {d20, d21}, [%0]!       \n\t"   //q10 = m0+8
++      "vld1.32                {d22, d23}, [%0]        \n\t"   //q11 = m0+12
++
++      "vmul.f32               q12, q8, d0[0]                  \n\t"   //q12 = q8 * d0[0]
++      "vmul.f32               q13, q8, d2[0]              \n\t"       //q13 = q8 * d2[0]
++      "vmul.f32               q14, q8, d4[0]              \n\t"       //q14 = q8 * d4[0]
++      "vmul.f32               q15, q8, d6[0]                  \n\t"   //q15 = q8 * d6[0]
++      "vmla.f32               q12, q9, d0[1]                  \n\t"   //q12 = q9 * d0[1]
++      "vmla.f32               q13, q9, d2[1]              \n\t"       //q13 = q9 * d2[1]
++      "vmla.f32               q14, q9, d4[1]              \n\t"       //q14 = q9 * d4[1]
++      "vmla.f32               q15, q9, d6[1]              \n\t"       //q15 = q9 * d6[1]
++      "vmla.f32               q12, q10, d1[0]                 \n\t"   //q12 = q10 * d0[0]
++      "vmla.f32               q13, q10, d3[0]                 \n\t"   //q13 = q10 * d2[0]
++      "vmla.f32               q14, q10, d5[0]                 \n\t"   //q14 = q10 * d4[0]
++      "vmla.f32               q15, q10, d7[0]                 \n\t"   //q15 = q10 * d6[0]
++      "vmla.f32               q12, q11, d1[1]                 \n\t"   //q12 = q11 * d0[1]
++      "vmla.f32               q13, q11, d3[1]                 \n\t"   //q13 = q11 * d2[1]
++      "vmla.f32               q14, q11, d5[1]                 \n\t"   //q14 = q11 * d4[1]
++      "vmla.f32               q15, q11, d7[1]             \n\t"       //q15 = q11 * d6[1]
++
++      "vst1.32                {d24, d25}, [%2]!               \n\t"   //d = q12
++      "vst1.32                {d26, d27}, [%2]!           \n\t"       //d+4 = q13
++      "vst1.32                {d28, d29}, [%2]!           \n\t"       //d+8 = q14
++      "vst1.32                {d30, d31}, [%2]            \n\t"       //d+12 = q15
++
++      :"+r"(m0), "+r"(m1), "+r"(dest):
++    : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
++    "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
++    "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
++    "memory"
++      );
++}
++
++void Normalize_neon(float v[3])
++{
++      asm volatile (
++      "vld1.32                {d4}, [%0]!                     \n\t"   //d4={x,y}
++      "flds                   s10, [%0]               \n\t"   //d5[0] = z
++      "sub                    %0, %0, #8              \n\t"   //d5[0] = z
++      "vmul.f32               d0, d4, d4                              \n\t"   //d0= d4*d4
++      "vpadd.f32              d0, d0, d0                              \n\t"   //d0 = d[0] + d[1]
++    "vmla.f32                 d0, d5, d5                              \n\t"   //d0 = d0 + d5*d5
++
++      "vmov.f32               d1, d0                                  \n\t"   //d1 = d0
++      "vrsqrte.f32    d0, d0                                  \n\t"   //d0 = ~ 1.0 / sqrt(d0)
++      "vmul.f32               d2, d0, d1                              \n\t"   //d2 = d0 * d1
++      "vrsqrts.f32    d3, d2, d0                              \n\t"   //d3 = (3 - d0 * d2) / 2
++      "vmul.f32               d0, d0, d3                              \n\t"   //d0 = d0 * d3
++      "vmul.f32               d2, d0, d1                              \n\t"   //d2 = d0 * d1
++      "vrsqrts.f32    d3, d2, d0                              \n\t"   //d3 = (3 - d0 * d3) / 2
++      "vmul.f32               d0, d0, d3                              \n\t"   //d0 = d0 * d4
++
++      "vmul.f32               q2, q2, d0[0]                   \n\t"   //d0= d2*d4
++      "vst1.32                {d4}, [%0]!                     \n\t"   //d2={x0,y0}, d3={z0, w0}
++      "fsts                   s10, [%0]                       \n\t"   //d2={x0,y0}, d3={z0, w0}
++
++      :"+r"(v) :
++    : "d0", "d1", "d2", "d3", "d4", "d5", "memory"
++      );
++}
++
++float DotProduct_neon( float v0[3], float v1[3] )
++{
++    float dot;
++      asm volatile (
++      "vld1.32                {d8}, [%1]!                     \n\t"   //d8={x0,y0}
++      "vld1.32                {d10}, [%2]!            \n\t"   //d10={x1,y1}
++      "flds                   s18, [%1, #0]       \n\t"       //d9[0]={z0}
++      "flds                   s22, [%2, #0]       \n\t"       //d11[0]={z1}
++      "vmul.f32               d12, d8, d10            \n\t"   //d0= d2*d4
++      "vpadd.f32              d12, d12, d12           \n\t"   //d0 = d[0] + d[1]
++      "vmla.f32               d12, d9, d11            \n\t"   //d0 = d0 + d3*d5
++    "fmrs             %0, s24                 \n\t"   //r0 = s0
++      : "=r"(dot), "+r"(v0), "+r"(v1):
++    : "d8", "d9", "d10", "d11", "d12"
++
++      );
++    return dot;
++}
++
++#endif
++
+ // 2008.03.29 H.Morii - added SSE 3DNOW! 3x3 1x3 matrix multiplication
+ //                      and 3DNOW! 4x4 4x4 matrix multiplication
+ // 2011-01-03 Balrog - removed because is in NASM format and not 64-bit compatible
+ // This will need fixing.
++#ifndef __ARM_NEON__
+ MULMATRIX MulMatrices = MulMatricesC;
+ TRANSFORMVECTOR TransformVector = TransformVectorC;
+ TRANSFORMVECTOR InverseTransformVector = InverseTransformVectorC;
+ DOTPRODUCT DotProduct = DotProductC;
+ NORMALIZEVECTOR NormalizeVector = NormalizeVectorC;
++#endif
+ void MulMatricesSSE(float m1[4][4],float m2[4][4],float r[4][4])
+ {
+@@ -361,6 +455,7 @@
+   void math_init()
+   {
++#ifndef __ARM_NEON__
+ #ifndef _DEBUG
+     int IsSSE = FALSE;
+ #if defined(__GNUC__) && !defined(NO_ASM) && !defined(NOSSE)
+@@ -429,4 +524,5 @@
+       }
+ #endif //_DEBUG
++#endif        //__ARM_NEON__
+     }
+diff -Naur ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glide64/3dmath.h ./Glide64/3dmath.h
+--- ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glide64/3dmath.h       2013-09-06 22:05:28.000000000 +0200
++++ ./Glide64/3dmath.h 2013-09-14 19:01:12.000000000 +0200
+@@ -42,7 +42,22 @@
+ void calc_sphere (VERTEX *v);
+ void math_init();
++#ifdef __ARM_NEON__
++float DotProductC(register float *v1, register float *v2);
++void NormalizeVectorC(float *v);
++void TransformVectorC(float *src, float *dst, float mat[4][4]);
++void InverseTransformVectorC (float *src, float *dst, float mat[4][4]);
++void MulMatricesC(float m1[4][4],float m2[4][4],float r[4][4]);
++void MultMatrix_neon( float m0[4][4], float m1[4][4], float dest[4][4]);
++void Normalize_neon(float v[3]);
++float DotProduct_neon( float v0[3], float v1[3] );
++#define MulMatrices                           MulMatricesC            //MultMatrix_neon
++#define TransformVector                       TransformVectorC
++#define InverseTransformVector        InverseTransformVectorC
++#define DotProduct                            DotProductC                     //DotProduct_neon
++#define NormalizeVector                       NormalizeVectorC        //Normalize_neon
++#else
+ typedef void (*MULMATRIX)(float m1[4][4],float m2[4][4],float r[4][4]); 
+ extern MULMATRIX MulMatrices;
+ typedef void (*TRANSFORMVECTOR)(float *src,float *dst,float mat[4][4]); 
+@@ -52,3 +67,4 @@
+ extern DOTPRODUCT DotProduct;
+ typedef void (*NORMALIZEVECTOR)(float *v);
+ extern NORMALIZEVECTOR NormalizeVector;
++#endif
+diff -Naur ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glide64/3dmathneon.cpp ./Glide64/3dmathneon.cpp
+--- ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glide64/3dmathneon.cpp 1970-01-01 01:00:00.000000000 +0100
++++ ./Glide64/3dmathneon.cpp   2013-09-13 23:05:47.000000000 +0200
+@@ -0,0 +1,133 @@
++#include "3dmath.h"
++
++static void MultMatrix_neon( float m0[4][4], float m1[4][4], float dest[4][4])
++{
++    asm volatile (
++      "vld1.32                {d0, d1}, [%1]!                 \n\t"   //q0 = m1
++      "vld1.32                {d2, d3}, [%1]!         \n\t"   //q1 = m1+4
++      "vld1.32                {d4, d5}, [%1]!         \n\t"   //q2 = m1+8
++      "vld1.32                {d6, d7}, [%1]          \n\t"   //q3 = m1+12
++      "vld1.32                {d16, d17}, [%0]!               \n\t"   //q8 = m0
++      "vld1.32                {d18, d19}, [%0]!       \n\t"   //q9 = m0+4
++      "vld1.32                {d20, d21}, [%0]!       \n\t"   //q10 = m0+8
++      "vld1.32                {d22, d23}, [%0]        \n\t"   //q11 = m0+12
++
++      "vmul.f32               q12, q8, d0[0]                  \n\t"   //q12 = q8 * d0[0]
++      "vmul.f32               q13, q8, d2[0]              \n\t"       //q13 = q8 * d2[0]
++      "vmul.f32               q14, q8, d4[0]              \n\t"       //q14 = q8 * d4[0]
++      "vmul.f32               q15, q8, d6[0]                  \n\t"   //q15 = q8 * d6[0]
++      "vmla.f32               q12, q9, d0[1]                  \n\t"   //q12 = q9 * d0[1]
++      "vmla.f32               q13, q9, d2[1]              \n\t"       //q13 = q9 * d2[1]
++      "vmla.f32               q14, q9, d4[1]              \n\t"       //q14 = q9 * d4[1]
++      "vmla.f32               q15, q9, d6[1]              \n\t"       //q15 = q9 * d6[1]
++      "vmla.f32               q12, q10, d1[0]                 \n\t"   //q12 = q10 * d0[0]
++      "vmla.f32               q13, q10, d3[0]                 \n\t"   //q13 = q10 * d2[0]
++      "vmla.f32               q14, q10, d5[0]                 \n\t"   //q14 = q10 * d4[0]
++      "vmla.f32               q15, q10, d7[0]                 \n\t"   //q15 = q10 * d6[0]
++      "vmla.f32               q12, q11, d1[1]                 \n\t"   //q12 = q11 * d0[1]
++      "vmla.f32               q13, q11, d3[1]                 \n\t"   //q13 = q11 * d2[1]
++      "vmla.f32               q14, q11, d5[1]                 \n\t"   //q14 = q11 * d4[1]
++      "vmla.f32               q15, q11, d7[1]             \n\t"       //q15 = q11 * d6[1]
++
++      "vst1.32                {d24, d25}, [%2]!               \n\t"   //d = q12
++      "vst1.32                {d26, d27}, [%2]!           \n\t"       //d+4 = q13
++      "vst1.32                {d28, d29}, [%2]!           \n\t"       //d+8 = q14
++      "vst1.32                {d30, d31}, [%2]            \n\t"       //d+12 = q15
++
++      :"+r"(m0), "+r"(m1), "+r"(dest):
++    : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
++    "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
++    "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
++    "memory"
++      );
++}
++
++static void TransformVectorNormalize_neon(float vec[3], float mtx[4][4])
++{
++      asm volatile (
++      "vld1.32                {d0}, [%1]                      \n\t"   //Q0 = v
++      "flds                   s2, [%1, #8]                    \n\t"   //Q0 = v
++      "vld1.32                {d18, d19}, [%0]!               \n\t"   //Q1 = m
++      "vld1.32                {d20, d21}, [%0]!           \n\t"       //Q2 = m+4
++      "vld1.32                {d22, d23}, [%0]            \n\t"       //Q3 = m+8
++
++      "vmul.f32               q2, q9, d0[0]                   \n\t"   //q2 = q9*Q0[0]
++      "vmla.f32               q2, q10, d0[1]                  \n\t"   //Q5 += Q1*Q0[1]
++      "vmla.f32               q2, q11, d1[0]                  \n\t"   //Q5 += Q2*Q0[2]
++
++    "vmul.f32                 d0, d4, d4                              \n\t"   //d0 = d0*d0
++      "vpadd.f32              d0, d0, d0                              \n\t"   //d0 = d[0] + d[1]
++    "vmla.f32                 d0, d5, d5                              \n\t"   //d0 = d0 + d1*d1
++
++      "vmov.f32               d1, d0                                  \n\t"   //d1 = d0
++      "vrsqrte.f32    d0, d0                                  \n\t"   //d0 = ~ 1.0 / sqrt(d0)
++      "vmul.f32               d2, d0, d1                              \n\t"   //d2 = d0 * d1
++      "vrsqrts.f32    d3, d2, d0                              \n\t"   //d3 = (3 - d0 * d2) / 2
++      "vmul.f32               d0, d0, d3                              \n\t"   //d0 = d0 * d3
++      "vmul.f32               d2, d0, d1                              \n\t"   //d2 = d0 * d1
++      "vrsqrts.f32    d3, d2, d0                              \n\t"   //d3 = (3 - d0 * d3) / 2
++      "vmul.f32               d0, d0, d3                              \n\t"   //d0 = d0 * d4
++
++      "vmul.f32               q2, q2, d0[0]                   \n\t"   //d0= d2*d4
++
++      "vst1.32                {d4}, [%1]                  \n\t"       //Q4 = m+12
++      "fsts                   s10, [%1, #8]           \n\t"   //Q4 = m+12
++      : "+r"(mtx): "r"(vec)
++    : "d0","d1","d2","d3","d18","d19","d20","d21","d22", "d23", "memory"
++      );
++}
++
++static void Normalize_neon(float v[3])
++{
++      asm volatile (
++      "vld1.32                {d4}, [%0]!                     \n\t"   //d4={x,y}
++      "flds                   s10, [%0]               \n\t"   //d5[0] = z
++      "sub                    %0, %0, #8              \n\t"   //d5[0] = z
++      "vmul.f32               d0, d4, d4                              \n\t"   //d0= d4*d4
++      "vpadd.f32              d0, d0, d0                              \n\t"   //d0 = d[0] + d[1]
++    "vmla.f32                 d0, d5, d5                              \n\t"   //d0 = d0 + d5*d5
++
++      "vmov.f32               d1, d0                                  \n\t"   //d1 = d0
++      "vrsqrte.f32    d0, d0                                  \n\t"   //d0 = ~ 1.0 / sqrt(d0)
++      "vmul.f32               d2, d0, d1                              \n\t"   //d2 = d0 * d1
++      "vrsqrts.f32    d3, d2, d0                              \n\t"   //d3 = (3 - d0 * d2) / 2
++      "vmul.f32               d0, d0, d3                              \n\t"   //d0 = d0 * d3
++      "vmul.f32               d2, d0, d1                              \n\t"   //d2 = d0 * d1
++      "vrsqrts.f32    d3, d2, d0                              \n\t"   //d3 = (3 - d0 * d3) / 2
++      "vmul.f32               d0, d0, d3                              \n\t"   //d0 = d0 * d4
++
++      "vmul.f32               q2, q2, d0[0]                   \n\t"   //d0= d2*d4
++      "vst1.32                {d4}, [%0]!                     \n\t"   //d2={x0,y0}, d3={z0, w0}
++      "fsts                   s10, [%0]                       \n\t"   //d2={x0,y0}, d3={z0, w0}
++
++      :"+r"(v) :
++    : "d0", "d1", "d2", "d3", "d4", "d5", "memory"
++      );
++}
++
++static float DotProduct_neon( float v0[3], float v1[3] )
++{
++    float dot;
++      asm volatile (
++      "vld1.32                {d8}, [%1]!                     \n\t"   //d8={x0,y0}
++      "vld1.32                {d10}, [%2]!            \n\t"   //d10={x1,y1}
++      "flds                   s18, [%1, #0]       \n\t"       //d9[0]={z0}
++      "flds                   s22, [%2, #0]       \n\t"       //d11[0]={z1}
++      "vmul.f32               d12, d8, d10            \n\t"   //d0= d2*d4
++      "vpadd.f32              d12, d12, d12           \n\t"   //d0 = d[0] + d[1]
++      "vmla.f32               d12, d9, d11            \n\t"   //d0 = d0 + d3*d5
++    "fmrs             %0, s24                 \n\t"   //r0 = s0
++      : "=r"(dot), "+r"(v0), "+r"(v1):
++    : "d8", "d9", "d10", "d11", "d12"
++
++      );
++    return dot;
++}
++
++void MathInitNeon()
++{
++    MulMatrices = MultMatrix_neon;
++    //TransformVectorNormalize = TransformVectorNormalize_neon;
++    NormalizeVector = Normalize_neon;
++    DotProduct = DotProduct_neon;
++}
+diff -Naur ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glide64/Config.cpp ./Glide64/Config.cpp
+--- ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glide64/Config.cpp     2013-09-06 22:05:29.000000000 +0200
++++ ./Glide64/Config.cpp       2013-09-07 10:51:27.000000000 +0200
+@@ -89,7 +89,7 @@
+   { 640, 480 },
+   { 800, 600 },
+   { 960, 720 },
+-  { 856, 480 },
++  { 800, 480 },
+   { 512, 256 },
+   { 1024, 768 },
+   { 1280, 1024 },
+diff -Naur ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glide64/CRC.cpp ./Glide64/CRC.cpp
+--- ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glide64/CRC.cpp        2013-09-06 22:05:28.000000000 +0200
++++ ./Glide64/CRC.cpp  2013-09-08 13:12:00.000000000 +0200
+@@ -43,6 +43,7 @@
+ //
+ //****************************************************************
+ //*
++
+ #define CRC32_POLYNOMIAL     0x04C11DB7
+ unsigned int CRCTable[ 256 ];
+@@ -140,3 +141,4 @@
+    return Crc32;
+ }
+ //*/
++
+diff -Naur ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glide64/FBtoScreen.cpp ./Glide64/FBtoScreen.cpp
+--- ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glide64/FBtoScreen.cpp 2013-09-06 22:05:29.000000000 +0200
++++ ./Glide64/FBtoScreen.cpp   2013-09-08 11:57:33.000000000 +0200
+@@ -165,12 +165,15 @@
+     for (wxUint32 w = 0; w < 256; w++)
+     {
+       col = *(src++);
+-      r = (wxUint8)((col >> 24)&0xFF);
++      r = (wxUint8)((col >> (24+3))&0x1F);
++      g = (wxUint8)((col >> (16+2))&0x3F);
++      b = (wxUint8)((col >>  (8+3))&0x1F);
++/*      r = (wxUint8)((col >> 24)&0xFF);
+       r = (wxUint8)((float)r / 255.0f * 31.0f);
+       g = (wxUint8)((col >> 16)&0xFF);
+       g = (wxUint8)((float)g / 255.0f * 63.0f);
+       b = (wxUint8)((col >>  8)&0xFF);
+-      b = (wxUint8)((float)b / 255.0f * 31.0f);
++      b = (wxUint8)((float)b / 255.0f * 31.0f);*/     //*SEB*
+       *(dst++) = (r << 11) | (g << 5) | b;
+     }
+     src += (fb_info.width - 256);
+@@ -261,12 +264,15 @@
+             if (idx >= bound)
+               break;
+             c32 = src32[idx];
+-            r = (wxUint8)((c32 >> 24)&0xFF);
++            r = (wxUint8)((c32 >> (24+3))&0x1F);
++            g = (wxUint8)((c32 >> (16+2))&0x3F);
++            b = (wxUint8)((c32 >>  (8+3))&0x1F);
++/*            r = (wxUint8)((c32 >> 24)&0xFF);
+             r = (wxUint8)((float)r / 255.0f * 31.0f);
+             g = (wxUint8)((c32 >> 16)&0xFF);
+             g = (wxUint8)((float)g / 255.0f * 63.0f);
+             b = (wxUint8)((c32 >>  8)&0xFF);
+-            b = (wxUint8)((float)b / 255.0f * 31.0f);
++            b = (wxUint8)((float)b / 255.0f * 31.0f);*/       //*SEB*
+             a = (c32&0xFF) ? 1 : 0;
+             *(dst++) = (a<<15) | (r << 10) | (g << 5) | b;
+           }
+diff -Naur ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glide64/Gfx_1.3.h ./Glide64/Gfx_1.3.h
+--- ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glide64/Gfx_1.3.h      2013-09-06 22:05:29.000000000 +0200
++++ ./Glide64/Gfx_1.3.h        2013-09-08 16:22:57.000000000 +0200
+@@ -106,6 +106,8 @@
+ // ** 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 EXT_LOGGING
++//#define PERFORMANCE
+ //#define LOG_UCODE
+@@ -120,15 +122,15 @@
+ #define FPS                                   // fps counter able? (not enabled necessarily)
+-#define LOGNOTKEY                      // Log if not pressing:
+-#define LOGKEY                0x11 // this key (CONTROL)
++//#define LOGNOTKEY                    // Log if not pressing:
++//#define LOGKEY              0x11 // this key (CONTROL)
+ //#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
++//#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 _ENDUSER_RELEASE_
+@@ -144,7 +146,7 @@
+ // Usually enabled
+-#define LARGE_TEXTURE_HANDLING        // allow large-textured objects to be split?
++//#define LARGE_TEXTURE_HANDLING      // allow large-textured objects to be split?
+ #ifdef ALTTAB_FIX
+ extern HHOOK hhkLowLevelKybd;
+@@ -189,7 +191,6 @@
+ int CheckKeyPressed(int key, int mask);
+-//#define PERFORMANCE
+ #ifdef PERFORMANCE
+ extern int64 perf_cur;
+ extern int64 perf_next;
+diff -Naur ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glide64/Main.cpp ./Glide64/Main.cpp
+--- ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glide64/Main.cpp       2013-09-06 22:05:29.000000000 +0200
++++ ./Glide64/Main.cpp 2013-09-15 17:06:29.000000000 +0200
+@@ -170,7 +170,7 @@
+ // 60=0x0, 70=0x1, 72=0x2, 75=0x3, 80=0x4, 90=0x5, 100=0x6, 85=0x7, 120=0x8, none=0xff
+ #ifdef PAULSCODE
+-#include "ae_bridge.h"
++//#include "ae_bridge.h"
+ #include "FrameSkipper.h"
+ FrameSkipper frameSkipper;
+ #endif
+@@ -1768,12 +1768,13 @@
+ EXPORT void CALL RomClosed (void)
+ {
+   VLOG ("RomClosed ()\n");
++printf("RomClosed ()\n");
+   CLOSE_RDP_LOG ();
+   CLOSE_RDP_E_LOG ();
+   rdp.window_changed = TRUE;
+   romopen = FALSE;
+-  if (fullscreen && evoodoo)
++//  if (fullscreen && evoodoo)//*SEB*
+     ReleaseGfx ();
+ }
+@@ -1973,9 +1974,6 @@
+ wxUint32 update_screen_count = 0;
+ EXPORT void CALL UpdateScreen (void)
+ {
+-#ifdef PAULSCODE
+-  frameSkipper.update();
+-#endif
+ #ifdef LOG_KEY
+   if (CheckKeyPressed(G64_VK_SPACE, 0x0001))
+   {
+@@ -2020,6 +2018,9 @@
+     no_dlist = true;
+     ClearCache ();
+     UpdateScreen();
++#ifdef PAULSCODE
++  frameSkipper.update();
++#endif
+     return;
+   }
+   //*/
+@@ -2035,11 +2036,17 @@
+       rdp.updatescreen = 1;
+       newSwapBuffers ();
+     }
++#ifdef PAULSCODE
++  frameSkipper.update();
++#endif
+     return;
+   }
+   //*/
+   if (settings.swapmode == 0)
+     newSwapBuffers ();
++#ifdef PAULSCODE
++  frameSkipper.update();
++#endif
+ }
+ static void DrawWholeFrameBufferToScreen()
+diff -Naur ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glide64/rdp.cpp ./Glide64/rdp.cpp
+--- ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glide64/rdp.cpp        2013-09-06 22:05:29.000000000 +0200
++++ ./Glide64/rdp.cpp  2013-09-13 22:23:52.000000000 +0200
+@@ -56,6 +56,10 @@
+ extern FrameSkipper frameSkipper;
+ #endif
++#ifdef PERFORMANCE
++#include "ticks.h"
++#endif
++
+ /*
+ const int NumOfFormats = 3;
+ SCREEN_SHOT_FORMAT ScreenShotFormats[NumOfFormats] = { {wxT("BMP"), wxT("bmp"), wxBITMAP_TYPE_BMP}, {wxT("PNG"), wxT("png"), wxBITMAP_TYPE_PNG}, {wxT("JPEG"), wxT("jpeg"), wxBITMAP_TYPE_JPEG} };
+@@ -633,18 +637,21 @@
+ EXPORT void CALL ProcessDList(void)
+ {
+-  SoftLocker lock(mutexProcessDList);
++//  SoftLocker lock(mutexProcessDList);
+ #ifdef PAULSCODE
+-  if (frameSkipper.willSkipNext() || !lock.IsOk()) //mutex is busy
++  if (frameSkipper.willSkipNext() /*|| !lock.IsOk()*/) //mutex is busy
+ #else
+-  if (!lock.IsOk()) //mutex is busy
++  if (/*!lock.IsOk()*/0) //mutex is busy
+ #endif
+   {
++// printf("Frameskip, reason=%s\n", (lock.IsOk())?"lock":"frameskip");
+     if (!fullscreen)
+       drawNoFullscreenMessage();
+     // Set an interrupt to allow the game to continue
+     *gfx.MI_INTR_REG |= 0x20;
+     gfx.CheckInterrupts();
++      *gfx.MI_INTR_REG |= 0x01;
++      gfx.CheckInterrupts();
+     return;
+   }
+@@ -717,7 +724,18 @@
+     unimp.close();
+   }
+ #endif
+-
++/*
++#ifdef PAULSCODE
++  if (frameSkipper.willSkipNext())
++  {
++      *gfx.MI_INTR_REG |= 0x20;
++      gfx.CheckInterrupts();
++      *gfx.MI_INTR_REG |= 0x01;
++      gfx.CheckInterrupts();
++      return;
++  }
++#endif
++*/
+   //* Set states *//
+   if (settings.swapmode > 0)
+     SwapOK = TRUE;
+@@ -818,7 +836,7 @@
+         rdp.pc[rdp.pc_i] = (a+8) & BMASK;
+ #ifdef PERFORMANCE
+-        perf_cur = wxDateTime::UNow();
++        perf_cur = ticksGetTicks();
+ #endif
+         // Process this instruction
+         gfx_instruction[settings.ucode][rdp.cmd0>>24] ();
+@@ -837,9 +855,13 @@
+         }
+ #ifdef PERFORMANCE
+-        perf_next = wxDateTime::UNow();
+-        sprintf (out_buf, "perf %08lx: %016I64d\n", a-8, (perf_next-perf_cur).Format(_T("%l")).mb_str());
++        perf_next = ticksGetTicks();
++        sprintf (out_buf, "perf %08x: %lli\n", a-8, (perf_next-perf_cur));
++#ifdef RDP_LOGGING
+         rdp_log << out_buf;
++#else
++              printf(out_buf);
++#endif
+ #endif
+       } while (!rdp.halt);
+diff -Naur ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glide64/Util.cpp ./Glide64/Util.cpp
+--- ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glide64/Util.cpp       2013-09-06 22:05:29.000000000 +0200
++++ ./Glide64/Util.cpp 2013-09-08 12:39:52.000000000 +0200
+@@ -289,29 +289,29 @@
+   deltaZ = dzdx = 0;
+   if (linew == 0 && (fb_depth_render_enabled || (rdp.rm & 0xC00) == 0xC00))
+   {
+-    double X0 = vtx[0]->sx / rdp.scale_x;
+-    double Y0 = vtx[0]->sy / rdp.scale_y;
+-    double X1 = vtx[1]->sx / rdp.scale_x;
+-    double Y1 = vtx[1]->sy / rdp.scale_y;
+-    double X2 = vtx[2]->sx / rdp.scale_x;
+-    double Y2 = vtx[2]->sy / rdp.scale_y;
+-    double diffy_02 = Y0 - Y2;
+-    double diffy_12 = Y1 - Y2;
+-    double diffx_02 = X0 - X2;
+-    double diffx_12 = X1 - X2;
+-
+-    double denom = (diffx_02 * diffy_12 - diffx_12 * diffy_02);
+-    if(denom*denom > 0.0)
+-    {
+-      double diffz_02 = vtx[0]->sz - vtx[2]->sz;
+-      double diffz_12 = vtx[1]->sz - vtx[2]->sz;
+-      double fdzdx = (diffz_02 * diffy_12 - diffz_12 * diffy_02) / denom;
++    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 diffy_02 = Y0 - Y2;
++    float diffy_12 = Y1 - Y2;
++    float diffx_02 = X0 - X2;
++    float diffx_12 = X1 - X2;
++
++    float denom = (diffx_02 * diffy_12 - diffx_12 * diffy_02);
++    if(denom*denom > 0.0f)
++    {
++      float diffz_02 = vtx[0]->sz - vtx[2]->sz;
++      float diffz_12 = vtx[1]->sz - vtx[2]->sz;
++      float fdzdx = (diffz_02 * diffy_12 - diffz_12 * diffy_02) / denom;
+       if ((rdp.rm & 0xC00) == 0xC00) {
+         // Calculate deltaZ per polygon for Decal z-mode
+-        double fdzdy = (diffz_02 * diffx_12 - diffz_12 * diffx_02) / denom;
+-        double fdz = fabs(fdzdx) + fabs(fdzdy);
++        float fdzdy = (diffz_02 * diffx_12 - diffz_12 * diffx_02) / denom;
++        float fdz = fabs(fdzdx) + fabs(fdzdy);
+         if ((settings.hacks & hack_Zelda) && (rdp.rm & 0x800))
+-          fdz *= 4.0;  // Decal mode in Zelda sometimes needs mutiplied deltaZ to work correct, e.g. roads
++          fdz *= 4.0f;  // Decal mode in Zelda sometimes needs mutiplied deltaZ to work correct, e.g. roads
+         deltaZ = max(8, (int)fdz);
+       }
+       dzdx = (int)(fdzdx * 65536.0);
+@@ -881,12 +881,12 @@
+ //*/
+ typedef struct {
+-  double d;
+-  double x;
+-  double y;
++  float d;            //*SEB* was doubles
++  float x;
++  float y;
+ } LineEuqationType;
+-static double EvaLine(LineEuqationType &li, double x, double y)
++static float EvaLine(LineEuqationType &li, float x, float y)  //*SEB* all double before
+ {
+   return li.x*x+li.y*y+li.d;
+ }
+@@ -906,7 +906,7 @@
+ }
+-__inline double interp3p(float a, float b, float c, double r1, double r2)
++__inline float interp3p(float a, float b, float c, float r1, float r2)        //*SEB* r1 and r2 and function was double
+ {
+   return (a)+(((b)+((c)-(b))*(r2))-(a))*(r1);
+ }
+@@ -915,34 +915,34 @@
+   (a+(((b)+((c)-(b))*(r2))-(a))*(r1))
+ */
+-static void InterpolateColors3(VERTEX &v1, VERTEX &v2, VERTEX &v3, VERTEX &out)
++static void InterpolateColors3(VERTEX &v1, VERTEX &v2, VERTEX &v3, VERTEX &out)       //*SEB* all double before
+ {
+   LineEuqationType line;
+   Create1LineEq(line, v2, v3, v1);
+-  double aDot = (out.x*line.x + out.y*line.y);
+-  double bDot = (v1.sx*line.x + v1.sy*line.y);
++  float aDot = (out.x*line.x + out.y*line.y);
++  float bDot = (v1.sx*line.x + v1.sy*line.y);
+-  double scale1 = ( - line.d - aDot) / ( bDot - aDot );
++  float scale1 = ( - line.d - aDot) / ( bDot - aDot );
+-  double tx = out.x + scale1 * (v1.sx - out.x);
+-  double ty = out.y + scale1 * (v1.sy - out.y);
++  float tx = out.x + scale1 * (v1.sx - out.x);
++  float ty = out.y + scale1 * (v1.sy - out.y);
+-  double s1 = 101.0, s2 = 101.0;
+-  double den = tx - v1.sx;
+-  if (fabs(den) > 1.0)
++  float s1 = 101.0, s2 = 101.0;
++  float den = tx - v1.sx;
++  if (fabsf(den) > 1.0)
+     s1 = (out.x-v1.sx)/den;
+   if (s1 > 100.0f)
+     s1 = (out.y-v1.sy)/(ty-v1.sy);
+   den = v3.sx - v2.sx;
+-  if (fabs(den) > 1.0)
++  if (fabsf(den) > 1.0)
+     s2 = (tx-v2.sx)/den;
+   if (s2 > 100.0f)
+     s2 =(ty-v2.sy)/(v3.sy-v2.sy);
+-  double w = 1.0/interp3p(v1.oow,v2.oow,v3.oow,s1,s2);
++  float w = 1.0/interp3p(v1.oow,v2.oow,v3.oow,s1,s2);
+   out.r = real_to_char(interp3p(v1.r*v1.oow,v2.r*v2.oow,v3.r*v3.oow,s1,s2)*w);
+   out.g = real_to_char(interp3p(v1.g*v1.oow,v2.g*v2.oow,v3.g*v3.oow,s1,s2)*w);
+@@ -976,8 +976,8 @@
+   */
+   float deltaS, deltaT;
+   float deltaX, deltaY;
+-  double deltaTexels, deltaPixels, lodFactor = 0;
+-  double intptr;
++  float deltaTexels, deltaPixels, lodFactor = 0;      //*SEB* double before
++  float intptr;                                                                               //*SEB* double before
+   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)
+@@ -1019,7 +1019,7 @@
+   float lod_fraction = 1.0f;
+   if (lod_tile < rdp.cur_tile + rdp.mipmap_level)
+   {
+-      lod_fraction = max((float)modf(lodFactor / pow(2.,lod_tile),&intptr), rdp.prim_lodmin / 255.0f);
++      lod_fraction = max((float)modff(lodFactor / powf(2.,lod_tile),&intptr), (float)rdp.prim_lodmin / 255.0f);
+   }
+   float detailmax;
+   if (cmb.dc0_detailmax < 0.5f)
+diff -Naur ../../../../git/mupen64plus-ae/jni/gles2glide64/src/GlideHQ/TxDbg.cpp ./GlideHQ/TxDbg.cpp
+--- ../../../../git/mupen64plus-ae/jni/gles2glide64/src/GlideHQ/TxDbg.cpp      2013-09-06 22:05:30.000000000 +0200
++++ ./GlideHQ/TxDbg.cpp        2013-09-07 12:06:11.000000000 +0200
+@@ -28,6 +28,8 @@
+ #include <stdarg.h>
+ #include <string>
++#define _GLIBCXX_HAVE_BROKEN_VSWPRINTF        1
++
+ TxDbg::TxDbg()
+ {
+   _level = DBG_LEVEL;
+diff -Naur ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glitch64/combiner.cpp ./Glitch64/combiner.cpp
+--- ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glitch64/combiner.cpp  2013-09-06 22:05:30.000000000 +0200
++++ ./Glitch64/combiner.cpp    2013-09-14 10:16:36.000000000 +0200
+@@ -29,6 +29,8 @@
+ #include "glide.h"
+ #include "main.h"
++#define GLchar        char
++
+ void vbo_draw();
+ static int fct[4], source0[4], operand0[4], source1[4], operand1[4], source2[4], operand2[4];
+@@ -117,10 +119,11 @@
+ // 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"
++" \n"
++/*"  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"
++"                               (dithy-32.0*floor(dithy/32.0))/32.0)).a > 0.5) discard; \n"*/
+ ;
+ static const char* fragment_shader_default =
+@@ -165,11 +168,16 @@
+ "}                               \n"
+ ;
++static const char* fragment_shader_alt_end =
++"                                \n"
++"}                               \n"
++;
++
+ static const char* vertex_shader =
+ SHADER_HEADER
+ "#define Z_MAX 65536.0                                          \n"
+ "attribute highp vec4 aVertex;                                  \n"
+-"attribute highp vec4 aColor;                                   \n"
++"attribute mediump vec4 aColor;                                   \n" //*SEB* highp -> lowp
+ "attribute highp vec4 aMultiTexCoord0;                          \n"
+ "attribute highp vec4 aMultiTexCoord1;                          \n"
+ "attribute float aFog;                                          \n"
+@@ -245,7 +253,7 @@
+   // 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);
++  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 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);
+@@ -286,7 +294,7 @@
+     strlen(fragment_shader_end)+1);
+   strcpy(fragment_shader, fragment_shader_header);
+   strcat(fragment_shader, fragment_shader_default);
+-  strcat(fragment_shader, fragment_shader_end);
++  strcat(fragment_shader, fragment_shader_end);       /*SEB*/
+   glShaderSource(fragment_shader_object, 1, (const GLchar**)&fragment_shader, NULL);
+   free(fragment_shader);
+@@ -408,6 +416,7 @@
+   int dither_enabled;
+   int blackandwhite0;
+   int blackandwhite1;
++  int alpha_test;                     //*SEB*
+   GLuint fragment_shader_object;
+   GLuint program_object;
+   int texture0_location;
+@@ -489,6 +498,8 @@
+   int i;
+   int chroma_color_location;
+   int log_length;
++  
++  int noalpha;
+   need_to_compile = 0;
+@@ -502,6 +513,7 @@
+       prog.texture0_combinera == texture0_combinera_key &&
+       prog.texture1_combinera == texture1_combinera_key &&
+       prog.fog_enabled == fog_enabled &&
++        prog.alpha_test == alpha_test &&                              //*SEB*
+       prog.chroma_enabled == chroma_enabled &&
+       prog.dither_enabled == dither_enabled &&
+       prog.blackandwhite0 == blackandwhite0 &&
+@@ -514,11 +526,13 @@
+     }
+   }
+-  if(shader_programs != NULL)
+-    shader_programs = (shader_program_key*)realloc(shader_programs, (number_of_programs+1)*sizeof(shader_program_key));
++  if(shader_programs != NULL) {
++      if ((number_of_programs+1)>1024)
++              shader_programs = (shader_program_key*)realloc(shader_programs, (number_of_programs+1)*sizeof(shader_program_key));
++  }
+   else
+-    shader_programs = (shader_program_key*)malloc(sizeof(shader_program_key));
+-  //printf("number of shaders %d\n", number_of_programs);
++    shader_programs = (shader_program_key*)malloc(sizeof(shader_program_key)*1024);
++      //printf("number of shaders %d\n", number_of_programs);
+   shader_programs[number_of_programs].color_combiner = color_combiner_key;
+   shader_programs[number_of_programs].alpha_combiner = alpha_combiner_key;
+@@ -531,6 +545,7 @@
+   shader_programs[number_of_programs].dither_enabled = dither_enabled;
+   shader_programs[number_of_programs].blackandwhite0 = blackandwhite0;
+   shader_programs[number_of_programs].blackandwhite1 = blackandwhite1;
++  shader_programs[number_of_programs].alpha_test = alpha_test;                //*SEB*
+   if(chroma_enabled)
+   {
+@@ -557,7 +572,10 @@
+   strcat(fragment_shader, fragment_shader_color_combiner);
+   strcat(fragment_shader, fragment_shader_alpha_combiner);
+   if(fog_enabled) strcat(fragment_shader, fragment_shader_fog);
+-  strcat(fragment_shader, fragment_shader_end);
++  if (alpha_test)
++              strcat(fragment_shader, fragment_shader_end);
++  else
++              strcat(fragment_shader, fragment_shader_alt_end);               //*SEB*
+   if(chroma_enabled) strcat(fragment_shader, fragment_shader_chroma);
+   shader_programs[number_of_programs].fragment_shader_object = glCreateShader(GL_FRAGMENT_SHADER);
+@@ -1719,7 +1737,7 @@
+   glActiveTexture(GL_TEXTURE2);
+   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);
++  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 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);
+diff -Naur ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glitch64/geometry.cpp ./Glitch64/geometry.cpp
+--- ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glitch64/geometry.cpp  2013-09-06 22:05:30.000000000 +0200
++++ ./Glitch64/geometry.cpp    2013-09-12 22:13:33.000000000 +0200
+@@ -34,7 +34,7 @@
+ #define VERTEX_SIZE sizeof(VERTEX) //Size of vertex struct
+ #ifdef PAULSCODE
+-#include "ae_bridge.h"
++//#include "ae_bridge.h"
+ static float polygonOffsetFactor;
+ static float polygonOffsetUnits;
+ #endif
+@@ -338,8 +338,11 @@
+ void FindBestDepthBias()
+ {
+ #ifdef PAULSCODE
+-  int hardwareType = Android_JNI_GetHardwareType();
+-  Android_JNI_GetPolygonOffset(hardwareType, 1, &polygonOffsetFactor, &polygonOffsetUnits);
++/*  int hardwareType = Android_JNI_GetHardwareType();
++  Android_JNI_GetPolygonOffset(hardwareType, 1, &polygonOffsetFactor, &polygonOffsetUnits);*/
++//  glPolygonOffset(0.2f, 0.2f);
++      polygonOffsetFactor=0.2f;
++      polygonOffsetUnits=0.2f;
+ #else
+   float f, bestz = 0.25f;
+   int x;
+@@ -386,7 +389,11 @@
+   if (level)
+   {
+     #ifdef PAULSCODE
+-    glPolygonOffset(polygonOffsetFactor, polygonOffsetUnits);
++//    glPolygonOffset(polygonOffsetFactor, polygonOffsetUnits);
++    if(w_buffer_mode)
++      glPolygonOffset(1.0f, -(float)level*polygonOffsetUnits);
++    else
++      glPolygonOffset(0, (float)level*3.0f);
+     #else
+     if(w_buffer_mode)
+       glPolygonOffset(1.0f, -(float)level*zscale/255.0f);
+@@ -408,13 +415,13 @@
+ grDrawTriangle( const void *a, const void *b, const void *c )
+ {
+   LOG("grDrawTriangle()\r\n\t");
+-  
++/*  
+   if(nvidia_viewport_hack && !render_to_texture)
+   {
+     glViewport(0, viewport_offset, viewport_width, viewport_height);
+     nvidia_viewport_hack = 0;
+   }
+-
++*/
+   reloadTexture();
+   if(need_to_compile) compile_shader();
+@@ -588,13 +595,13 @@
+ {
+   void **pointers = (void**)pointers2;
+   LOG("grDrawVertexArray(%d,%d)\r\n", mode, Count);
+-
++/*
+   if(nvidia_viewport_hack && !render_to_texture)
+   {
+     glViewport(0, viewport_offset, viewport_width, viewport_height);
+     nvidia_viewport_hack = 0;
+   }
+-
++*/
+   reloadTexture();
+   if(need_to_compile) compile_shader();
+@@ -612,13 +619,13 @@
+ grDrawVertexArrayContiguous(FxU32 mode, FxU32 Count, void *pointers, FxU32 stride)
+ {
+   LOG("grDrawVertexArrayContiguous(%d,%d,%d)\r\n", mode, Count, stride);
+-
++/*
+   if(nvidia_viewport_hack && !render_to_texture)
+   {
+     glViewport(0, viewport_offset, viewport_width, viewport_height);
+     nvidia_viewport_hack = 0;
+   }
+-
++*/
+   if(stride != 156)
+   {
+         LOGINFO("Incompatible stride\n");
+diff -Naur ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glitch64/glitchmain.cpp ./Glitch64/glitchmain.cpp
+--- ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glitch64/glitchmain.cpp        2013-09-06 22:05:30.000000000 +0200
++++ ./Glitch64/glitchmain.cpp  2013-09-15 17:13:49.000000000 +0200
+@@ -656,6 +656,9 @@
+ #ifdef _WIN32
+   glCompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)wglGetProcAddress("glCompressedTexImage2DARB");
+ #endif
++/*SEB*/
++  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
++  glPixelStorei(GL_PACK_ALIGNMENT, 1);
+ #ifdef _WIN32
+@@ -806,6 +809,7 @@
+     fullscreen = 0;
+   }
+ #else
++  CoreVideo_Quit();
+   //SDL_QuitSubSystem(SDL_INIT_VIDEO);
+   //sleep(2);
+ #endif
+@@ -823,7 +827,7 @@
+   int i;
+   static int fbs_init = 0;
+-  //printf("grTextureBufferExt(%d, %d, %d, %d, %d, %d, %d)\r\n", tmu, startAddress, lodmin, lodmax, aspect, fmt, evenOdd);
++      //printf("grTextureBufferExt(%d, %d, %d, %d, %d, %d, %d)\r\n", tmu, startAddress, lodmin, lodmax, aspect, fmt, evenOdd);
+   LOG("grTextureBufferExt(%d, %d, %d, %d %d, %d, %d)\r\n", tmu, startAddress, lodmin, lodmax, aspect, fmt, evenOdd);
+   if (lodmin != lodmax) display_warning("grTextureBufferExt : loading more than one LOD");
+   if (!use_fbo) {
+@@ -907,8 +911,8 @@
+       tmu_usage[rtmu].min = pBufferAddress;
+     if ((unsigned int) 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);
++      //printf("tmu %d usage now %gMb - %gMb\n",
++    //      rtmu, tmu_usage[rtmu].min/1024.0f, tmu_usage[rtmu].max/1024.0f);
+     width = pBufferWidth;
+@@ -927,14 +931,14 @@
+     texbufs[i].fmt = fmt;
+     if (i == texbuf_i)
+       texbuf_i = (texbuf_i+1)&(NB_TEXBUFS-1);
+-    //printf("texbuf %x fmt %x\n", pBufferAddress, fmt);
++      //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);
++      //printf("viewport %dx%d\n", width, height);
+     if (height > screen_height) {
+       glViewport( 0, viewport_offset + screen_height - height, width, height);
+     } else
+@@ -1009,7 +1013,6 @@
+         }
+       }
+     }
+-
+     remove_tex(pBufferAddress, pBufferAddress + width*height*2/*grTexFormatSize(fmt)*/);
+     //create new FBO
+     glGenFramebuffers( 1, &(fbs[nb_fb].fbid) );
+@@ -1768,6 +1771,7 @@
+           GrLfbInfo_t *info )
+ {
+   LOG("grLfbLock(%d,%d,%d,%d,%d)\r\n", type, buffer, writeMode, origin, pixelPipeline);
++//printf("grLfbLock(%d,%d,%d,%d,%d)\r\n", type, buffer, writeMode, origin, pixelPipeline);
+   if (type == GR_LFB_WRITE_ONLY)
+   {
+     display_warning("grLfbLock : write only");
+@@ -1792,12 +1796,32 @@
+     if(buffer != GR_BUFFER_AUXBUFFER)
+     {
+       if (writeMode == GR_LFBWRITEMODE_888) {
++/*SEB*/
++        buf = (unsigned char*)malloc(width*height*4);
+         //printf("LfbLock GR_LFBWRITEMODE_888\n");
+         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);
++        glReadPixels(0, viewport_offset, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buf);
++
++/*SEB*/
++          unsigned char *p=buf;
++        for (j=0; j<height; j++)
++        {
++          short unsigned int *f=frameBuffer+(height-j-1)*width;
++          for (i=0; i<width; i++)
++          {
++            *(f++) =
++              (*(p)   <<24) |
++              (*(p+1) <<16) |
++              (*(p+2) << 8) |
++                (0xff);
++              p+=4;
++          }
++        }
++        free(buf);
+       } else {
+         buf = (unsigned char*)malloc(width*height*4);
+@@ -1807,14 +1831,22 @@
+         info->origin = origin;
+         glReadPixels(0, viewport_offset, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buf);
++/*SEB*/
++          unsigned char *p=buf;
+         for (j=0; j<height; j++)
+         {
++            short unsigned int *f=frameBuffer+(height-j-1)*width;
+           for (i=0; i<width; i++)
+           {
+-            frameBuffer[(height-j-1)*width+i] =
++/*            frameBuffer[(height-j-1)*width+i] =
+               ((buf[j*width*4+i*4+0] >> 3) << 11) |
+               ((buf[j*width*4+i*4+1] >> 2) <<  5) |
+-              (buf[j*width*4+i*4+2] >> 3);
++              (buf[j*width*4+i*4+2] >> 3);*/
++            *(f++) =
++              ((*(p)   >> 3) << 11) |
++              ((*(p+1) >> 2) <<  5) |
++              (*(p+2)  >> 3);
++              p+=4;
+           }
+         }
+         free(buf);
+@@ -1826,6 +1858,7 @@
+       info->strideInBytes = width*2;
+       info->writeMode = GR_LFBWRITEMODE_ZA16;
+       info->origin = origin;
++      //*SEB* *TODO* check alignment
+       glReadPixels(0, viewport_offset, width, height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, depthBuffer);
+     }
+   }
+@@ -1855,6 +1888,7 @@
+   unsigned short *frameBuffer = (unsigned short*)dst_data;
+   unsigned short *depthBuffer = (unsigned short*)dst_data;
+   LOG("grLfbReadRegion(%d,%d,%d,%d,%d,%d)\r\n", src_buffer, src_x, src_y, src_width, src_height, dst_stride);
++//printf("grLfbReadRegion(%d,%d,%d,%d,%d,%d)\r\n", src_buffer, src_x, src_y, src_width, src_height, dst_stride);
+   switch(src_buffer)
+   {
+@@ -1876,15 +1910,22 @@
+     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<src_height; j++)
+     {
++/*SEB*/
++      unsigned char *p=buf+(src_height-j-1)*src_width*4;
++      unsigned short *f=frameBuffer+(j*dst_stride/2);
+       for (i=0; i<src_width; i++)
+       {
+-        frameBuffer[j*(dst_stride/2)+i] =
++/*        frameBuffer[j*(dst_stride/2)+i] =
+           ((buf[(src_height-j-1)*src_width*4+i*4+0] >> 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);
++          (buf[(src_height-j-1)*src_width*4+i*4+2] >> 3);*/
++        *(f++) =
++          ((*(p) >> 3) << 11) |
++          ((*(p+1) >> 2) <<  5) |
++          (*(p+2) >> 3);
++        p+=4;
+       }
+     }
+     free(buf);
+@@ -1892,15 +1933,19 @@
+   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);
++//*SEB read in buf, not depthBuffer.
++    glReadPixels(src_x, (viewport_offset)+height-src_y-src_height, src_width, src_height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, buf);
+     for (j=0;j<src_height; j++)
+     {
++//*SEB*
++      unsigned short *d=depthBuffer+j*dst_stride/2;
++      unsigned short *p=(unsigned short*)buf+(src_height-j-1)*src_width; //orignal look fishy. why *4???
+       for (i=0; i<src_width; i++)
+       {
+-        depthBuffer[j*(dst_stride/2)+i] =
+-          ((unsigned short*)buf)[(src_height-j-1)*src_width*4+i*4];
++/*        depthBuffer[j*(dst_stride/2)+i] =
++          ((unsigned short*)buf)[(src_height-j-1)*src_width*4+i*4];*/
++        *(d++) = *(p++); //why *4 (prob. GL_PACK was=4), plus transcoding to short, that make *8 ???
+       }
+     }
+     free(buf);
+@@ -1923,6 +1968,7 @@
+   int texture_number;
+   unsigned int tex_width = 1, tex_height = 1;
+   LOG("grLfbWriteRegion(%d,%d,%d,%d,%d,%d,%d,%d)\r\n",dst_buffer, dst_x, dst_y, src_format, src_width, src_height, pixelPipeline, src_stride);
++//printf("grLfbWriteRegion(%d,%d,%d,%d,%d,%d,%d,%d)\r\n",dst_buffer, dst_x, dst_y, src_format, src_width, src_height, pixelPipeline, src_stride);
+   //glPushAttrib(GL_ALL_ATTRIB_BITS);
+@@ -1949,6 +1995,12 @@
+     glActiveTexture(texture_number);
+     const unsigned int half_stride = src_stride / 2;
++
++    const int comp_stride = half_stride - src_width;
++    const int comp_tex = (tex_width - src_width)*4;
++    unsigned short *f=frameBuffer;
++    unsigned char *p=buf;
++
+     switch(src_format)
+     {
+     case GR_LFB_SRC_FMT_1555:
+@@ -1956,12 +2008,20 @@
+       {
+         for (i=0; i<src_width; i++)
+         {
+-          const unsigned int col = frameBuffer[j*half_stride+i];
++/*          const unsigned int col = frameBuffer[j*half_stride+i];
+           buf[j*tex_width*4+i*4+0]=((col>>10)&0x1F)<<3;
+           buf[j*tex_width*4+i*4+1]=((col>>5)&0x1F)<<3;
+           buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3;
+-          buf[j*tex_width*4+i*4+3]= (col>>15) ? 0xFF : 0;
++          buf[j*tex_width*4+i*4+3]= (col>>15) ? 0xFF : 0;*/
++          const unsigned int col = *(f++);
++          *(p)=((col>>10)&0x1F)<<3;
++          *(p+1)=((col>>5)&0x1F)<<3;
++          *(p+2)=((col>>0)&0x1F)<<3;
++          *(p+3)= (col>>15) ? 0xFF : 0;
++        p+=4;
+         }
++      p+=comp_tex;
++      f+=comp_stride;
+       }
+       break;
+     case GR_LFBWRITEMODE_555:
+@@ -1969,12 +2029,20 @@
+       {
+         for (i=0; i<src_width; i++)
+         {
+-          const unsigned int col = frameBuffer[j*half_stride+i];
++/*          const unsigned int col = frameBuffer[j*half_stride+i];
+           buf[j*tex_width*4+i*4+0]=((col>>10)&0x1F)<<3;
+           buf[j*tex_width*4+i*4+1]=((col>>5)&0x1F)<<3;
+           buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3;
+-          buf[j*tex_width*4+i*4+3]=0xFF;
++          buf[j*tex_width*4+i*4+3]=0xFF;*/
++          const unsigned int col = *(f++);
++          *(p)=((col>>10)&0x1F)<<3;
++          *(p+1)=((col>>5)&0x1F)<<3;
++          *(p+2)=((col>>0)&0x1F)<<3;
++          *(p+3)=0xFF;
++        p+=4;
+         }
++      p+=comp_tex;
++      f+=comp_stride;
+       }
+       break;
+     case GR_LFBWRITEMODE_565:
+@@ -1982,12 +2050,20 @@
+       {
+         for (i=0; i<src_width; i++)
+         {
+-          const unsigned int col = frameBuffer[j*half_stride+i];
++/*          const unsigned int col = frameBuffer[j*half_stride+i];
+           buf[j*tex_width*4+i*4+0]=((col>>11)&0x1F)<<3;
+           buf[j*tex_width*4+i*4+1]=((col>>5)&0x3F)<<2;
+           buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3;
+-          buf[j*tex_width*4+i*4+3]=0xFF;
++          buf[j*tex_width*4+i*4+3]=0xFF;*/
++          const unsigned int col = *(f++);
++          *(p)=((col>>11)&0x1F)<<3;
++          *(p+1)=((col>>5)&0x3F)<<2;
++          *(p+2)=((col>>0)&0x1F)<<3;
++          *(p+3)=0xFF;
++        p+=4;
+         }
++      p+=comp_tex;
++      f+=comp_stride;
+       }
+       break;
+     default:
+@@ -2006,7 +2082,7 @@
+ #endif
+     glBindTexture(GL_TEXTURE_2D, default_texture);
+-    glTexImage2D(GL_TEXTURE_2D, 0, 4, tex_width, tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
++    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
+     free(buf);
+     set_copy_shader();
+diff -Naur ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glitch64/textures.cpp ./Glitch64/textures.cpp
+--- ../../../../git/mupen64plus-ae/jni/gles2glide64/src/Glitch64/textures.cpp  2013-09-06 22:05:31.000000000 +0200
++++ ./Glitch64/textures.cpp    2013-09-13 11:32:50.000000000 +0200
+@@ -26,6 +26,7 @@
+ #include "glide.h"
+ #include "main.h"
+ #include <stdio.h>
++#include <string.h>
+ /* Napalm extensions to GrTextureFormat_t */
+ #define GR_TEXFMT_ARGB_CMP_FXT1           0x11
+@@ -107,7 +108,7 @@
+   }
+   glDeleteTextures(n, t);
+   free(t);
+-  //printf("RMVTEX nbtex is now %d (%06x - %06x)\n", nbTex, idmin, idmax);
++//printf("RMVTEX nbtex is now %d (%06x - %06x)\n", nbTex, idmin, idmax);
+ }
+@@ -115,7 +116,7 @@
+ {
+   texlist *aux = list;
+   texlist *aux2;
+-  //printf("ADDTEX nbtex is now %d (%06x)\n", nbTex, id);
++//printf("ADDTEX nbtex is now %d (%06x)\n", nbTex, id);
+   if (list == NULL || id < list->id)
+   {
+     nbTex++;
+@@ -435,8 +436,11 @@
+     factor = -1;
+   else
+     factor = grTexFormat2GLPackedFmt(info->format, &gltexfmt, &glpixfmt, &glpackfmt);
+-
++//printf("grTexDownloadMipmap, id=%x, size=%ix%i, format=%x\n", startAddress+1, width, height, info->format);
+   if (factor < 0) {
++    gltexfmt = GL_RGBA;
++    glpixfmt = GL_RGBA;
++    glpackfmt = GL_UNSIGNED_BYTE;
+     // 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
+@@ -444,7 +448,7 @@
+     switch(info->format)
+     {
+     case GR_TEXFMT_ALPHA_8:
+-      for (i=0; i<height; i++)
++ /*     for (i=0; i<height; i++)
+       {
+         for (j=0; j<width; j++)
+         {
+@@ -457,10 +461,25 @@
+         }
+       }
+       factor = 1;
+-      glformat = GL_RGBA;
++      glformat = GL_RGBA;*/
++
++     for (i=0; i<height; i++)
++      {
++        for (j=0; j<width; j++)
++        {
++          unsigned short texel = (unsigned short)((unsigned char*)info->data)[m];
++          ((unsigned short*)texture)[n] = texel|(texel<<8);
++          m++;
++          n++;
++        }
++      }
++
++      glformat = gltexfmt = glpixfmt = GL_LUMINANCE_ALPHA;
++      glpackfmt = GL_UNSIGNED_BYTE;
++      factor = 1;
+       break;
+     case GR_TEXFMT_INTENSITY_8: // I8 support - H.Morii
+-      for (i=0; i<height; i++)
++/*      for (i=0; i<height; i++)
+       {
+         for (j=0; j<width; j++)
+         {
+@@ -470,9 +489,13 @@
+           m++;
+           n++;
+         }
+-      }
++      }*/
++      factor = 1;
++//      glformat = GL_ALPHA;
++      memcpy(texture, info->data, width*height);
++      glformat = gltexfmt = glpixfmt = GL_LUMINANCE;
++      glpackfmt = GL_UNSIGNED_BYTE;
+       factor = 1;
+-      glformat = GL_ALPHA;
+       break;
+     case GR_TEXFMT_ALPHA_INTENSITY_44:
+ #if 1
+@@ -480,9 +503,9 @@
+       {
+         for (j=0; j<width; j++)
+         {
+-          unsigned int texel = (unsigned int)((unsigned char*)info->data)[m];
++/*          unsigned int texel = (unsigned int)((unsigned char*)info->data)[m];
+ #if 1
+-          /* accurate conversion */
++          // accurate conversion
+           unsigned int texel_hi = (texel & 0x000000F0) << 20;
+           unsigned int texel_low = texel & 0x0000000F;
+           texel_low |= (texel_low << 4);
+@@ -493,61 +516,90 @@
+           texel_hi |= ((texel_low << 16) | (texel_low << 8) | texel_low);
+ #endif
+           ((unsigned int*)texture)[n] = texel_hi;
++*/
++        unsigned char texel = ((unsigned char*)info->data)[m];
++          unsigned short texel_hi = (texel & 0x000000F0) << 4;
++          unsigned short texel_low = texel & 0x0000000F;
++          texel_low |= (texel_low << 4);
++          texel_hi |= ((texel_hi << 4) | (texel_low));
++        ((unsigned short*)texture)[n] = texel_hi;
+           m++;
+           n++;
+         }
+       }
+       factor = 1;
+-      glformat = GL_LUMINANCE_ALPHA;
++      glformat = gltexfmt = glpixfmt = GL_LUMINANCE_ALPHA;
++      glpackfmt = GL_UNSIGNED_BYTE;
++//      glformat = GL_LUMINANCE_ALPHA;
+ #endif
+       break;
+     case GR_TEXFMT_RGB_565:
+-      for (i=0; i<height; i++)
++/*      for (i=0; i<height; i++)
+       {
+         for (j=0; j<width; j++)
+-        {
+-          unsigned int texel = (unsigned int)((unsigned short*)info->data)[m];
++        {*/
++/*          unsigned int texel = (unsigned int)((unsigned short*)info->data)[m];
+           unsigned int B = texel & 0x0000F800;
+           unsigned int G = texel & 0x000007E0;
+           unsigned int R = texel & 0x0000001F;
+ #if 0
+-          /* accurate conversion */
++          // accurate conversion 
+           ((unsigned int*)texture)[n] = 0xFF000000 | (R << 19) | ((R >> 2) << 16) | (G << 5) | ((G >> 9) << 8) | (B >> 8) | (B >> 13);
+ #else
+           ((unsigned int*)texture)[n] = 0xFF000000 | (R << 19) | (G << 5) | (B >> 8);
+ #endif
++*/
++/*      const unsigned short texel = ((unsigned short*)info->data)[m];
++          const unsigned short B = (texel & 0xF800)>>11;
++          const unsigned short G = texel & 0x07E0;
++          const unsigned short R = (texel & 0x001F)<<11;
++          ((unsigned short*)texture)[n] = R|G|B;
+           m++;
+           n++;
+         }
+-      }
++      }*/
++      memcpy(texture, info->data, width*height*2);
+       factor = 2;
+-      glformat = GL_RGB;
++//      glformat = GL_RGB;
++      glformat = gltexfmt = glpixfmt = GL_RGB;
++      glpackfmt = GL_UNSIGNED_SHORT_5_6_5;
+       break;
+     case GR_TEXFMT_ARGB_1555:
+       for (i=0; i<height; i++)
+       {
+         for (j=0; j<width; j++)
+         {
+-          unsigned int texel = (unsigned int)((unsigned short*)info->data)[m];
++/*          unsigned int texel = (unsigned int)((unsigned short*)info->data)[m];
+           unsigned int A = texel & 0x00008000 ? 0xFF000000 : 0;
+           unsigned int B = texel & 0x00007C00;
+           unsigned int G = texel & 0x000003E0;
+           unsigned int R = texel & 0x0000001F;
+ #if 0
+-          /* accurate conversion */
++          // accurate conversion
+           ((unsigned int*)texture)[n] = A | (R << 19) | ((R >> 2) << 16) | (G << 6) | ((G >> 8) << 8) | (B >> 7) | (B >> 12);
+ #else
+           ((unsigned int*)texture)[n] = A | (R << 19) | (G << 6) | (B >> 7);
+ #endif
++*/
++          unsigned short texel = ((unsigned short*)info->data)[m];
++          unsigned short A = (texel & 0x8000)>>15;
++        ((unsigned short*)texture)[n] = A|(texel&0x7fff)<<1;
++/*
++          unsigned short B = (texel & 0x7C00)>>9;
++          unsigned short G = texel & 0x03E0<<1;
++          unsigned short R = (texel & 0x001F)<<11;
++          ((unsigned short*)texture)[n] = A|R|G|B;*/
+           m++;
+           n++;
+         }
+       }
+       factor = 2;
+-      glformat = GL_RGBA;
++//      glformat = GL_RGBA;
++      glformat = gltexfmt = glpixfmt = GL_RGBA;
++      glpackfmt = GL_UNSIGNED_SHORT_5_5_5_1;
+       break;
+     case GR_TEXFMT_ALPHA_INTENSITY_88:
+-      for (i=0; i<height; i++)
++/*      for (i=0; i<height; i++)
+       {
+         for (j=0; j<width; j++)
+         {
+@@ -557,9 +609,12 @@
+           m++;
+           n++;
+         }
+-      }
++      }*/
++      memcpy(texture, info->data, width*height*2);
+       factor = 2;
+       glformat = GL_LUMINANCE_ALPHA;
++      glformat = gltexfmt = glpixfmt = GL_LUMINANCE_ALPHA;
++      glpackfmt = GL_UNSIGNED_BYTE;
+       break;
+     case GR_TEXFMT_ARGB_4444:
+@@ -567,23 +622,29 @@
+       {
+         for (j=0; j<width; j++)
+         {
+-          unsigned int texel = (unsigned int)((unsigned short*)info->data)[m];
++/*          unsigned int texel = (unsigned int)((unsigned short*)info->data)[m];
+           unsigned int A = texel & 0x0000F000;
+           unsigned int B = texel & 0x00000F00;
+           unsigned int G = texel & 0x000000F0;
+           unsigned int R = texel & 0x0000000F;
+ #if 0
+-          /* accurate conversion */
++          // accurate conversion
+           ((unsigned int*)texture)[n] = (A << 16) | (A << 12) | (R << 20) | (R << 16) | (G << 8) | (G << 4) | (B >> 4) | (B >> 8);
+ #else
+           ((unsigned int*)texture)[n] = (A << 16) | (R << 20) | (G << 8) | (B >> 4);
+ #endif
++*/
++          unsigned short texel = ((unsigned short*)info->data)[m];
++          unsigned int A = (texel & 0xF000)>>12;
++          ((unsigned short*)texture)[n] = A|(texel&0x0fff)<<4;
+           m++;
+           n++;
+         }
+       }
+       factor = 2;
+       glformat = GL_RGBA;
++      glformat = gltexfmt = glpixfmt = GL_RGBA;
++      glpackfmt = GL_UNSIGNED_SHORT_4_4_4_4;
+       break;
+     case GR_TEXFMT_ARGB_8888:
+       for (i=0; i<height; i++)
+@@ -650,7 +711,9 @@
+   if (largest_supported_anisotropy > 1.0f)
+     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy);
+-  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
++//*SEB*  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
++//printf("new texture, id=%x, size=%ix%i, fmt=%x/%x\n", startAddress+1, width, height, gltexfmt, glpackfmt);
++  glTexImage2D(GL_TEXTURE_2D, 0, gltexfmt, width, height, 0, glpixfmt, glpackfmt, texture);
+ /*
+   switch(info->format)
+   {
diff --git a/source/gles2glide64/projects/android/Android.mk b/source/gles2glide64/projects/android/Android.mk
new file mode 100644 (file)
index 0000000..a405191
--- /dev/null
@@ -0,0 +1,96 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+SRCDIR := ../../src
+
+LOCAL_MODULE := gles2glide64
+LOCAL_SHARED_LIBRARIES := ae-imports SDL2 core
+LOCAL_STATIC_LIBRARIES := png
+LOCAL_ARM_MODE := arm
+
+LOCAL_C_INCLUDES :=                             \
+    $(LOCAL_PATH)/$(SRCDIR)/Glitch64/inc        \
+    $(M64P_API_INCLUDES)                        \
+    $(PNG_INCLUDES)                             \
+    $(SDL_INCLUDES)                             \
+    $(AE_BRIDGE_INCLUDES)                       \
+
+LOCAL_SRC_FILES :=                              \
+    $(SRCDIR)/Glitch64/combiner.cpp             \
+    $(SRCDIR)/Glitch64/geometry.cpp             \
+    $(SRCDIR)/Glitch64/glitchmain.cpp           \
+    $(SRCDIR)/Glitch64/textures.cpp             \
+    $(SRCDIR)/Glide64/osal_dynamiclib_unix.c    \
+    $(SRCDIR)/Glide64/3dmath.cpp                \
+    $(SRCDIR)/Glide64/Combine.cpp               \
+    $(SRCDIR)/Glide64/Config.cpp                \
+    $(SRCDIR)/Glide64/CRC.cpp                   \
+    $(SRCDIR)/Glide64/Debugger.cpp              \
+    $(SRCDIR)/Glide64/DepthBufferRender.cpp     \
+    $(SRCDIR)/Glide64/FBtoScreen.cpp            \
+    $(SRCDIR)/Glide64/FrameSkipper.cpp          \
+    $(SRCDIR)/Glide64/Ini.cpp                   \
+    $(SRCDIR)/Glide64/Keys.cpp                  \
+    $(SRCDIR)/Glide64/Main.cpp                  \
+    $(SRCDIR)/Glide64/rdp.cpp                   \
+    $(SRCDIR)/Glide64/TexBuffer.cpp             \
+    $(SRCDIR)/Glide64/TexCache.cpp              \
+    $(SRCDIR)/Glide64/ticks.c                   \
+    $(SRCDIR)/Glide64/Util.cpp                  \
+#    $(SRCDIR)/GlideHQ/Ext_TxFilter.cpp          \
+#    $(SRCDIR)/GlideHQ/TxFilterExport.cpp        \
+#    $(SRCDIR)/GlideHQ/TxFilter.cpp              \
+#    $(SRCDIR)/GlideHQ/TxCache.cpp               \
+#    $(SRCDIR)/GlideHQ/TxTexCache.cpp            \
+#    $(SRCDIR)/GlideHQ/TxHiResCache.cpp          \
+#    $(SRCDIR)/GlideHQ/TxQuantize.cpp            \
+#    $(SRCDIR)/GlideHQ/TxUtil.cpp                \
+#    $(SRCDIR)/GlideHQ/TextureFilters.cpp        \
+#    $(SRCDIR)/GlideHQ/TextureFilters_2xsai.cpp  \
+#    $(SRCDIR)/GlideHQ/TextureFilters_hq2x.cpp   \
+#    $(SRCDIR)/GlideHQ/TextureFilters_hq4x.cpp   \
+#    $(SRCDIR)/GlideHQ/TxImage.cpp               \
+#    $(SRCDIR)/GlideHQ/TxReSample.cpp            \
+#    $(SRCDIR)/GlideHQ/TxDbg.cpp                 \
+#    $(SRCDIR)/GlideHQ/tc-1.1+/fxt1.c            \
+#    $(SRCDIR)/GlideHQ/tc-1.1+/dxtn.c            \
+#    $(SRCDIR)/GlideHQ/tc-1.1+/wrapper.c         \
+#    $(SRCDIR)/GlideHQ/tc-1.1+/texstore.c        \
+
+LOCAL_CFLAGS :=         \
+    $(COMMON_CFLAGS)    \
+    -DANDROID           \
+    -DNOSSE             \
+    -DNO_ASM            \
+    -DPAULSCODE         \
+    -fsigned-char       \
+    
+LOCAL_CPPFLAGS := $(COMMON_CPPFLAGS)
+    
+LOCAL_CPP_FEATURES := exceptions
+
+LOCAL_LDFLAGS := -Wl,-version-script,$(LOCAL_PATH)/$(SRCDIR)/video_api_export.ver
+
+LOCAL_LDLIBS :=         \
+    -ldl                \
+    -lGLESv2            \
+    -llog               \
+    -lz                 \
+
+ifeq ($(TARGET_ARCH_ABI), armeabi-v7a)
+    # Use for ARM7a:
+    LOCAL_CFLAGS += -mfpu=vfp
+    LOCAL_CFLAGS += -mfloat-abi=softfp
+    
+else ifeq ($(TARGET_ARCH_ABI), armeabi)
+    # Use for pre-ARM7a:
+    
+else ifeq ($(TARGET_ARCH_ABI), x86)
+    # TODO: set the proper flags here
+    
+else
+    # Any other architectures that Android could be running on?
+    
+endif
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/source/gles2glide64/projects/msvc11/mupen64plus-video-glide64mk2.vcxproj b/source/gles2glide64/projects/msvc11/mupen64plus-video-glide64mk2.vcxproj
new file mode 100644 (file)
index 0000000..701a97c
--- /dev/null
@@ -0,0 +1,203 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{A4D13408-A794-4199-8FC7-4A9A32505005}</ProjectGuid>
+    <RootNamespace>n64Glide</RootNamespace>
+    <ProjectName>mupen64plus-video-glide64mk2</ProjectName>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseOfMfc>false</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseOfMfc>false</UseOfMfc>
+    <CharacterSet>MultiByte</CharacterSet>
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings" />
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+    <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</GenerateManifest>
+    <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">F:\Code\Third Party\boost;$(IncludePath)</IncludePath>
+    <LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">F:\Code\Third Party\boost\stage\lib;$(LibraryPath)</LibraryPath>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Midl>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MkTypLibCompatible>true</MkTypLibCompatible>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <TargetEnvironment>Win32</TargetEnvironment>
+      <TypeLibraryName>.\Debug/n64Glide.tlb</TypeLibraryName>
+      <HeaderFileName>
+      </HeaderFileName>
+    </Midl>
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>..\..\src\Glitch64\inc;..\..\..\mupen64plus-win32-deps\boost-1.53.0\;..\..\..\mupen64plus-core\src\api;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\include;..\..\..\mupen64plus-win32-deps\libpng-1.2.37\include;..\..\..\mupen64plus-win32-deps\zlib-1.2.3\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_VARIADIC_MAX=10;_CRT_SECURE_NO_WARNINGS;__MSC__;WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <ExceptionHandling>Async</ExceptionHandling>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <PrecompiledHeaderOutputFile>.\Debug/n64Glide.pch</PrecompiledHeaderOutputFile>
+      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
+      <ObjectFileName>.\Debug/</ObjectFileName>
+      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
+      <WarningLevel>Level3</WarningLevel>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+    </ClCompile>
+    <ResourceCompile>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <Culture>0x0409</Culture>
+    </ResourceCompile>
+    <Link>
+      <AdditionalDependencies>opengl32.lib;glu32.lib;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\lib\SDL.lib;..\..\..\mupen64plus-win32-deps\libpng-1.2.37\lib\libpng.lib;..\..\..\mupen64plus-win32-deps\zlib-1.2.3\lib\zlib.lib;winmm.lib;comctl32.lib;rpcrt4.lib;wsock32.lib;msvcrtd.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <AdditionalLibraryDirectories>..\lib;..\..\..\mupen64plus-win32-deps\boost-1.53.0\boost\libs;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <ProgramDatabaseFile>.\Debug/Glide64.pdb</ProgramDatabaseFile>
+      <ImportLibrary>.\Debug/Glide64.lib</ImportLibrary>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+    <Bscmake>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <OutputFile>.\Debug/n64Glide.bsc</OutputFile>
+    </Bscmake>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Midl>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MkTypLibCompatible>true</MkTypLibCompatible>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <TargetEnvironment>Win32</TargetEnvironment>
+      <TypeLibraryName>.\Release/n64Glide.tlb</TypeLibraryName>
+      <HeaderFileName>
+      </HeaderFileName>
+    </Midl>
+    <ClCompile>
+      <Optimization>MaxSpeed</Optimization>
+      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+      <EnableFiberSafeOptimizations>false</EnableFiberSafeOptimizations>
+      <AdditionalIncludeDirectories>..\..\..\mupen64plus-win32-deps\boost-1.53.0\;..\..\..\mupen64plus-core\src\api;..\..\src\Glide64;..\..\src\Glide64\inc;..\..\src\GlideHQ;..\..\src\GlideHQ\tc-1.1+;..\..\src\Glitch64;..\..\src\Glitch64\inc;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\include;..\..\..\mupen64plus-win32-deps\zlib-1.2.3\include;..\..\..\mupen64plus-win32-deps\libpng-1.2.37\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_VARIADIC_MAX=10;_CRT_SECURE_NO_WARNINGS;__MSC__;WIN32;__VISUALC__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <StringPooling>true</StringPooling>
+      <ExceptionHandling>Async</ExceptionHandling>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
+      <PrecompiledHeaderOutputFile>.\Release/n64Glide.pch</PrecompiledHeaderOutputFile>
+      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
+      <ObjectFileName>.\Release/</ObjectFileName>
+      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
+      <WarningLevel>Level3</WarningLevel>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+    </ClCompile>
+    <ResourceCompile>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <Culture>0x0409</Culture>
+    </ResourceCompile>
+    <Link>
+      <AdditionalDependencies>SDL.lib;zlib.lib;libpng.lib;opengl32.lib;winmm.lib;comctl32.lib;rpcrt4.lib;wsock32.lib;msvcrt.lib;LIBCMT.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <AdditionalLibraryDirectories>..\..\..\mupen64plus-win32-deps\boost-1.53.0\boost\libs;..\..\..\mupen64plus-win32-deps\libpng-1.2.37\lib;..\..\..\mupen64plus-win32-deps\zlib-1.2.3\lib;..\..\..\mupen64plus-win32-deps\SDL-1.2.14\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
+      <ImportLibrary>
+      </ImportLibrary>
+      <TargetMachine>MachineX86</TargetMachine>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+    <Bscmake>
+      <SuppressStartupBanner>true</SuppressStartupBanner>
+      <OutputFile>.\Release/n64Glide.bsc</OutputFile>
+    </Bscmake>
+    <MASM>
+      <EnableMASM51Compatibility>true</EnableMASM51Compatibility>
+    </MASM>
+    <PostBuildEvent>
+      <Message>Copying shared data and libraries to build directory...</Message>
+      <Command>copy ..\..\data\* "$(OutDir)"</Command>
+    </PostBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\src\Glide64\3dmath.cpp" />
+    <ClCompile Include="..\..\src\Glide64\Combine.cpp" />
+    <ClCompile Include="..\..\src\Glide64\Config.cpp" />
+    <ClCompile Include="..\..\src\Glide64\CRC.cpp" />
+    <ClCompile Include="..\..\src\Glide64\Debugger.cpp" />
+    <ClCompile Include="..\..\src\Glide64\DepthBufferRender.cpp" />
+    <ClCompile Include="..\..\src\Glide64\FBtoScreen.cpp" />
+    <ClCompile Include="..\..\src\Glide64\Ini.cpp" />
+    <ClCompile Include="..\..\src\Glide64\Keys.cpp" />
+    <ClCompile Include="..\..\src\Glide64\Main.cpp" />
+    <ClCompile Include="..\..\src\Glide64\osal_dynamiclib_win32.c" />
+    <ClCompile Include="..\..\src\Glide64\rdp.cpp" />
+    <ClCompile Include="..\..\src\Glide64\TexBuffer.cpp" />
+    <ClCompile Include="..\..\src\Glide64\TexCache.cpp" />
+    <ClCompile Include="..\..\src\Glide64\Util.cpp" />
+    <ClCompile Include="..\..\src\GlideHQ\Ext_TxFilter.cpp" />
+    <ClCompile Include="..\..\src\GlideHQ\tc-1.1+\dxtn.c" />
+    <ClCompile Include="..\..\src\GlideHQ\tc-1.1+\fxt1.c" />
+    <ClCompile Include="..\..\src\GlideHQ\tc-1.1+\texstore.c" />
+    <ClCompile Include="..\..\src\GlideHQ\tc-1.1+\wrapper.c" />
+    <ClCompile Include="..\..\src\GlideHQ\TextureFilters.cpp" />
+    <ClCompile Include="..\..\src\GlideHQ\TextureFilters_2xsai.cpp" />
+    <ClCompile Include="..\..\src\GlideHQ\TextureFilters_hq2x.cpp" />
+    <ClCompile Include="..\..\src\GlideHQ\TextureFilters_hq4x.cpp" />
+    <ClCompile Include="..\..\src\GlideHQ\TxCache.cpp" />
+    <ClCompile Include="..\..\src\GlideHQ\TxDbg.cpp" />
+    <ClCompile Include="..\..\src\GlideHQ\TxFilter.cpp" />
+    <ClCompile Include="..\..\src\GlideHQ\TxFilterExport.cpp" />
+    <ClCompile Include="..\..\src\GlideHQ\TxHiResCache.cpp" />
+    <ClCompile Include="..\..\src\GlideHQ\TxImage.cpp" />
+    <ClCompile Include="..\..\src\GlideHQ\TxQuantize.cpp" />
+    <ClCompile Include="..\..\src\GlideHQ\TxReSample.cpp" />
+    <ClCompile Include="..\..\src\GlideHQ\TxTexCache.cpp" />
+    <ClCompile Include="..\..\src\GlideHQ\TxUtil.cpp" />
+    <ClCompile Include="..\..\src\Glitch64\combiner.cpp" />
+    <ClCompile Include="..\..\src\Glitch64\geometry.cpp" />
+    <ClCompile Include="..\..\src\Glitch64\glitchmain.cpp">
+      <ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release/%(Filename)1.obj</ObjectFileName>
+      <XMLDocumentationFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)%(Filename)1.xdc</XMLDocumentationFileName>
+    </ClCompile>
+    <ClCompile Include="..\..\src\Glitch64\textures.cpp" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets" />
+</Project>
\ No newline at end of file
diff --git a/source/gles2glide64/projects/msvc11/mupen64plus-video-glide64mk2.vcxproj.filters b/source/gles2glide64/projects/msvc11/mupen64plus-video-glide64mk2.vcxproj.filters
new file mode 100644 (file)
index 0000000..f1875f0
--- /dev/null
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Glitch64">
+      <UniqueIdentifier>{44b9ea4e-bb1f-45ef-9b11-c93aace0416c}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="GlideHQ">
+      <UniqueIdentifier>{daabfc00-53db-4996-9c67-80f7092cb54f}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="GlideHQ\tc-1.1+">
+      <UniqueIdentifier>{8e81e299-f474-448c-a104-5149bffd92f4}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Glide64">
+      <UniqueIdentifier>{d0e07863-9ec2-4409-a91e-bddc436aa16b}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Glide64\Windows">
+      <UniqueIdentifier>{c6ba9864-aee3-4434-954b-8c5679c2959c}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\src\Glitch64\geometry.cpp">
+      <Filter>Glitch64</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\Glitch64\textures.cpp">
+      <Filter>Glitch64</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\Glitch64\combiner.cpp">
+      <Filter>Glitch64</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\GlideHQ\TextureFilters_hq4x.cpp">
+      <Filter>GlideHQ</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\GlideHQ\TxCache.cpp">
+      <Filter>GlideHQ</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\GlideHQ\TxDbg.cpp">
+      <Filter>GlideHQ</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\GlideHQ\TxFilter.cpp">
+      <Filter>GlideHQ</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\GlideHQ\TxFilterExport.cpp">
+      <Filter>GlideHQ</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\GlideHQ\TxHiResCache.cpp">
+      <Filter>GlideHQ</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\GlideHQ\TxImage.cpp">
+      <Filter>GlideHQ</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\GlideHQ\TxQuantize.cpp">
+      <Filter>GlideHQ</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\GlideHQ\TxReSample.cpp">
+      <Filter>GlideHQ</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\GlideHQ\TxTexCache.cpp">
+      <Filter>GlideHQ</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\GlideHQ\TxUtil.cpp">
+      <Filter>GlideHQ</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\GlideHQ\Ext_TxFilter.cpp">
+      <Filter>GlideHQ</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\GlideHQ\TextureFilters.cpp">
+      <Filter>GlideHQ</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\GlideHQ\TextureFilters_2xsai.cpp">
+      <Filter>GlideHQ</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\GlideHQ\TextureFilters_hq2x.cpp">
+      <Filter>GlideHQ</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\GlideHQ\tc-1.1+\texstore.c">
+      <Filter>GlideHQ\tc-1.1+</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\GlideHQ\tc-1.1+\wrapper.c">
+      <Filter>GlideHQ\tc-1.1+</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\GlideHQ\tc-1.1+\dxtn.c">
+      <Filter>GlideHQ\tc-1.1+</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\GlideHQ\tc-1.1+\fxt1.c">
+      <Filter>GlideHQ\tc-1.1+</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\Glide64\Util.cpp">
+      <Filter>Glide64</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\Glide64\3dmath.cpp">
+      <Filter>Glide64</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\Glide64\Combine.cpp">
+      <Filter>Glide64</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\Glide64\Config.cpp">
+      <Filter>Glide64</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\Glide64\CRC.cpp">
+      <Filter>Glide64</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\Glide64\Debugger.cpp">
+      <Filter>Glide64</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\Glide64\DepthBufferRender.cpp">
+      <Filter>Glide64</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\Glide64\FBtoScreen.cpp">
+      <Filter>Glide64</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\Glide64\Ini.cpp">
+      <Filter>Glide64</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\Glide64\Keys.cpp">
+      <Filter>Glide64</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\Glide64\Main.cpp">
+      <Filter>Glide64</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\Glide64\rdp.cpp">
+      <Filter>Glide64</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\Glide64\TexBuffer.cpp">
+      <Filter>Glide64</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\Glide64\TexCache.cpp">
+      <Filter>Glide64</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\Glide64\osal_dynamiclib_win32.c">
+      <Filter>Glide64\Windows</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\Glitch64\glitchmain.cpp">
+      <Filter>Glitch64</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/source/gles2glide64/projects/unix/Makefile b/source/gles2glide64/projects/unix/Makefile
new file mode 100755 (executable)
index 0000000..f813c02
--- /dev/null
@@ -0,0 +1,467 @@
+#/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+# *   Mupen64plus-video-glide64mk2 - 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 Glide64mk2 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
+  BOOST_SUFFIX = -mt
+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
+  BOOST_SUFFIX = -mt
+  CPPFLAGS += -DNO_FILTER_THREAD
+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 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
+    CFLAGS += -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -mtune=cortex-a8 -fsigned-char -fno-strict-aliasing -fno-strict-overflow -fsingle-precision-constant
+    CFLAGS += -DNOSSE -DNO_ASM -DANDROID
+       CFLAGS += -DPAULSCODE 
+#      HIRES := 0
+#    CXXFLAGS += -std=c++11
+    $(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 ?= -Ofast -ffast-math
+WARNFLAGS ?= -Wall
+CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -ffast-math -fno-strict-aliasing -fvisibility=hidden -I../../src -I../../src/Glitch64/inc -DGCC
+CXXFLAGS += -fvisibility-inlines-hidden -std=gnu++0x
+LDFLAGS += $(SHARED)
+BOOST_SUFFIX ?=
+
+ifeq ($(CPU), X86)
+  CFLAGS +=  -mmmx -msse
+endif
+
+# Since we are building a shared library, we must compile with -fPIC on some architectures
+# On 32-bit x86 systems we do not want to use -fPIC because we don't have to and it has a big performance penalty on this arch
+ifeq ($(PIC), 1)
+  CFLAGS += -fPIC
+else
+  CFLAGS += -fno-PIC
+endif
+
+ifeq ($(BIG_ENDIAN), 1)
+  CFLAGS += -DM64P_BIG_ENDIAN
+endif
+
+# tweak flags for 32-bit build on 64-bit system
+ifeq ($(ARCH_DETECTED), 64BITS_32)
+  ifeq ($(OS), FREEBSD)
+    $(error Do not use the BITS=32 option with FreeBSD, use -m32 and -m elf_i386)
+  endif
+  CFLAGS += -m32
+  LDFLAGS += -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
+
+  CXXFLAGS += -std=c++11 -stdlib=libc++
+  ifeq ($(CPU), X86)
+    LDFLAGS += -bundle -L/opt/local/lib
+    LDLIBS += -ldl
+    ifeq ($(ARCH_DETECTED), 64BITS)
+      CFLAGS += -pipe -arch x86_64 -mmacosx-version-min=$(OSX_SDK) -isysroot $(OSX_SYSROOT)/MacOSX$(OSX_SDK).sdk
+    else
+      CFLAGS += -pipe -mmmx -msse -fomit-frame-pointer -arch i686 -mmacosx-version-min=$(OSX_SDK) -isysroot $(OSX_SYSROOT)/MacOSX$(OSX_SDK).sdk
+    endif
+  endif
+endif
+ifeq ($(OS), FREEBSD)
+  LDLIBS += -lc
+endif
+
+ifeq ($(origin PKG_CONFIG), undefined)
+  PKG_CONFIG = $(CROSS_COMPILE)pkg-config
+  ifeq ($(shell which $(PKG_CONFIG) 2>/dev/null),)
+    $(error $(PKG_CONFIG) not found)
+  endif
+endif
+
+ifeq ($(OS), OSX) # use system zlib on OSX
+  ZLIB_LDLIBS += -lz
+endif
+
+ifeq ($(origin ZLIB_CFLAGS) $(origin ZLIB_LDLIBS), undefined undefined)
+  ifeq ($(shell $(PKG_CONFIG) --modversion zlib 2>/dev/null),)
+    $(error No zlib development libraries found!)
+  endif
+  ZLIB_CFLAGS += $(shell $(PKG_CONFIG) --cflags zlib)
+  ZLIB_LDLIBS +=  $(shell $(PKG_CONFIG) --libs zlib)
+endif
+CFLAGS += $(ZLIB_CFLAGS)
+LDLIBS += $(ZLIB_LDLIBS)
+
+ifeq ($(origin LIBPNG_CFLAGS) $(origin LIBPNG_LDLIBS), undefined undefined)
+  ifeq ($(shell $(PKG_CONFIG) --modversion libpng 2>/dev/null),)
+    $(error No libpng development libraries found!)
+  endif
+  LIBPNG_CFLAGS += $(shell $(PKG_CONFIG) --cflags libpng)
+  LIBPNG_LDLIBS +=  $(shell $(PKG_CONFIG) --libs libpng)
+endif
+CFLAGS += $(LIBPNG_CFLAGS)
+LDLIBS += $(LIBPNG_LDLIBS)
+
+
+# search for OpenGL libraries
+ifeq ($(OS), OSX)
+  GL_LDLIBS = -framework OpenGL
+endif
+ifeq ($(OS), MINGW)
+  GL_LDLIBS = -lopengl32
+endif
+ifeq ($(origin GL_CFLAGS) $(origin GL_LDLIBS), undefined undefined)
+  ifeq ($(shell $(PKG_CONFIG) --modversion gl 2>/dev/null),)
+    $(error No OpenGL development libraries found!)
+  endif
+#  GL_CFLAGS += $(shell $(PKG_CONFIG) --cflags gl)
+#  GL_LDLIBS +=  $(shell $(PKG_CONFIG) --libs gl)
+  GL_CFLAGS += -I/mnt/utmp/codeblocks/usr/include/GLES2
+  GL_LDLIBS += -lGLESv2 -lrt
+endif
+CFLAGS += $(GL_CFLAGS)
+LDLIBS += $(GL_LDLIBS)
+
+# test for presence of SDL
+ifeq ($(origin SDL_CFLAGS) $(origin SDL_LDLIBS), undefined undefined)
+  SDL_CONFIG = $(CROSS_COMPILE)sdl-config
+  ifeq ($(shell which $(SDL_CONFIG) 2>/dev/null),)
+    $(error No SDL development libraries found!)
+  endif
+  ifeq ($(OS),OSX)
+    SDL_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
+    SDL_LDLIBS += -L/usr/local/lib -lSDL -Wl,-framework,Cocoa
+  else
+    SDL_CFLAGS  += $(shell $(SDL_CONFIG) --cflags)
+    SDL_LDLIBS += $(shell $(SDL_CONFIG) --libs)
+  endif
+endif
+CFLAGS += $(SDL_CFLAGS)
+LDLIBS += $(SDL_LDLIBS)
+
+ifneq ($(OS), MINGW)
+  CPPFLAGS += -D__unix__
+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) $(CXXFLAGS) $(LDFLAGS) $(TARGET_ARCH)
+
+# set special flags for given Makefile parameters
+ifeq ($(DEBUG),1)
+  CFLAGS += -g -gdwarf-2 -pg
+  INSTALL_STRIP_FLAG ?= 
+else
+  ifneq ($(OS),OSX)
+    INSTALL_STRIP_FLAG ?= -s
+  endif
+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)/Glitch64/combiner.cpp \
+       $(SRCDIR)/Glitch64/geometry.cpp \
+       $(SRCDIR)/Glitch64/glitchmain.cpp \
+       $(SRCDIR)/Glitch64/textures.cpp \
+       $(SRCDIR)/Glide64/3dmath.cpp \
+       $(SRCDIR)/Glide64/Combine.cpp \
+       $(SRCDIR)/Glide64/Config.cpp \
+       $(SRCDIR)/Glide64/CRC.cpp \
+       $(SRCDIR)/Glide64/Debugger.cpp \
+       $(SRCDIR)/Glide64/DepthBufferRender.cpp \
+    $(SRCDIR)/Glide64/FrameSkipper.cpp          \
+       $(SRCDIR)/Glide64/FBtoScreen.cpp \
+       $(SRCDIR)/Glide64/Ini.cpp \
+       $(SRCDIR)/Glide64/Keys.cpp \
+       $(SRCDIR)/Glide64/Main.cpp \
+       $(SRCDIR)/Glide64/rdp.cpp \
+       $(SRCDIR)/Glide64/TexBuffer.cpp \
+       $(SRCDIR)/Glide64/TexCache.cpp \
+    $(SRCDIR)/Glide64/ticks.c                   \
+       $(SRCDIR)/Glide64/Util.cpp
+
+ifneq ($(HIRES), 0)
+SOURCE += \
+       $(SRCDIR)/GlideHQ/Ext_TxFilter.cpp \
+       $(SRCDIR)/GlideHQ/TxFilterExport.cpp \
+       $(SRCDIR)/GlideHQ/TxFilter.cpp \
+       $(SRCDIR)/GlideHQ/TxCache.cpp \
+       $(SRCDIR)/GlideHQ/TxTexCache.cpp \
+       $(SRCDIR)/GlideHQ/TxHiResCache.cpp \
+       $(SRCDIR)/GlideHQ/TxQuantize.cpp \
+       $(SRCDIR)/GlideHQ/TxUtil.cpp \
+       $(SRCDIR)/GlideHQ/TextureFilters.cpp \
+       $(SRCDIR)/GlideHQ/TextureFilters_2xsai.cpp \
+       $(SRCDIR)/GlideHQ/TextureFilters_hq2x.cpp \
+       $(SRCDIR)/GlideHQ/TextureFilters_hq4x.cpp \
+       $(SRCDIR)/GlideHQ/TxImage.cpp \
+       $(SRCDIR)/GlideHQ/TxReSample.cpp \
+       $(SRCDIR)/GlideHQ/TxDbg.cpp \
+       $(SRCDIR)/GlideHQ/tc-1.1+/fxt1.c \
+       $(SRCDIR)/GlideHQ/tc-1.1+/dxtn.c \
+       $(SRCDIR)/GlideHQ/tc-1.1+/wrapper.c \
+       $(SRCDIR)/GlideHQ/tc-1.1+/texstore.c
+
+CPPFLAGS += -DTEXTURE_FILTER # -DDUMP_CACHE
+LDLIBS += -lboost_filesystem$(BOOST_SUFFIX) -lboost_system$(BOOST_SUFFIX)
+endif
+
+ifeq ($(OS),MINGW)
+SOURCE += $(SRCDIR)/Glide64/osal_dynamiclib_win32.c
+else
+SOURCE += $(SRCDIR)/Glide64/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-glide64mk2$(POSTFIX).$(SO_EXTENSION)
+
+targets:
+       @echo "Mupen64plus-video-glide64mk2 N64 Graphics plugin makefile. "
+       @echo "  Targets:"
+       @echo "    all           == Build Mupen64plus-video-glide64mk2 plugin"
+       @echo "    clean         == remove object files"
+       @echo "    rebuild       == clean and re-build all"
+       @echo "    install       == Install Mupen64Plus-video-glide64mk2 plugin"
+       @echo "    uninstall     == Uninstall Mupen64Plus-video-glide64mk2 plugin"
+       @echo "  Options:"
+       @echo "    BITS=32       == build 32-bit binaries on 64-bit machine"
+       @echo "    NO_ASM=1      == build without inline assembly code (x86 MMX/SSE)"
+       @echo "    APIDIR=path   == path to find Mupen64Plus Core headers"
+       @echo "    OPTFLAGS=flag == compiler optimization (default: -O3 -flto)"
+       @echo "    WARNFLAGS=flag == compiler warning levels (default: -Wall)"
+       @echo "    PIC=(1|0)     == Force enable/disable of position independent code"
+       @echo "    POSTFIX=name  == String added to the name of the the build (default: '')"
+       @echo "    HIRES=(1|0)   == Enables/Disables support for hires textures and texture filters (default: 1)"
+       @echo "  Install Options:"
+       @echo "    PREFIX=path   == install/uninstall prefix (default: /usr/local)"
+       @echo "    SHAREDIR=path == path to install shared data files (default: PREFIX/share/mupen64plus)"
+       @echo "    LIBDIR=path   == library prefix (default: PREFIX/lib)"
+       @echo "    PLUGINDIR=path == path to install plugin libraries (default: LIBDIR/mupen64plus)"
+       @echo "    DESTDIR=path  == path to prepend to all installation paths (only for packagers)"
+       @echo "  Debugging Options:"
+       @echo "    DEBUG=1       == add debugging symbols"
+       @echo "    V=1           == show verbose compiler output"
+
+all: $(TARGET)
+
+install: $(TARGET)
+       $(INSTALL) -d "$(DESTDIR)$(PLUGINDIR)"
+       $(INSTALL) -m 0644 $(INSTALL_STRIP_FLAG) $(TARGET) "$(DESTDIR)$(PLUGINDIR)"
+       $(INSTALL) -d "$(DESTDIR)$(SHAREDIR)"
+       $(INSTALL) -m 0644 "../../data/Glide64mk2.ini" "$(DESTDIR)$(SHAREDIR)"
+
+uninstall:
+       $(RM) "$(DESTDIR)$(PLUGINDIR)/$(TARGET)"
+       $(RM) "$(DESTDIR)$(SHAREDIR)/Glide64mk2.ini"
+
+clean:
+       $(RM) -r $(OBJDIR) $(TARGET)
+
+rebuild: clean all
+
+# build dependency files
+CFLAGS += -MD
+-include $(OBJECTS:.o=.d)
+
+CXXFLAGS += $(CFLAGS)
+
+# standard build rules
+$(OBJDIR)/%.o: $(SRCDIR)/%.c
+       $(COMPILE.c) -o $@ $<
+
+$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
+       $(COMPILE.cc) -o $@ $<
+
+$(TARGET): $(OBJECTS)
+       $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
+
+.PHONY: all clean install uninstall targets
diff --git a/source/gles2glide64/src/Glide64/3dmath.cpp b/source/gles2glide64/src/Glide64/3dmath.cpp
new file mode 100755 (executable)
index 0000000..c56cbec
--- /dev/null
@@ -0,0 +1,552 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+#include "Gfx_1.3.h"
+extern "C" {
+#ifndef NOSSE
+#include <xmmintrin.h>
+#endif
+}
+
+#include <math.h>
+#include "3dmath.h"
+
+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 (wxUint32 l=0; l<rdp.num_lights; l++)
+  {
+    light_intensity = DotProduct (rdp.light_vector[l], v->vec);
+    
+    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 = (wxUint8)(color[0]*255.0f);
+  v->g = (wxUint8)(color[1]*255.0f);
+  v->b = (wxUint8)(color[2]*255.0f);
+}
+
+//*
+void calc_linear (VERTEX *v)
+{
+  if (settings.force_calc_sphere)
+  {
+    calc_sphere(v);
+    return;
+  }
+  DECLAREALIGN16VAR(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 (x > 1.0f)
+    x = 1.0f;
+  else if (x < -1.0f)
+    x = -1.0f;
+  if (y > 1.0f)
+    y = 1.0f;
+  else if (y < -1.0f)
+    y = -1.0f;
+  
+  if (rdp.cur_cache[0])
+  {
+    // scale >> 6 is size to map to
+    v->ou = (acosf(x)/3.141592654f) * (rdp.tiles[rdp.cur_tile].org_s_scale >> 6);
+    v->ov = (acosf(y)/3.141592654f) * (rdp.tiles[rdp.cur_tile].org_t_scale >> 6);
+  }
+  v->uv_scaled = 1;
+#ifdef EXTREME_LOGGING
+  FRDP ("calc linear u: %f, v: %f\n", v->ou, v->ov);
+#endif
+}
+
+void calc_sphere (VERTEX *v)
+{
+//  LRDP("calc_sphere\n");
+  DECLAREALIGN16VAR(vec[3]);
+  int s_scale, t_scale;
+  if (settings.hacks&hack_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, y;
+  if (!rdp.use_lookat)
+  {
+    x = vec[0];
+    y = vec[1];
+  }
+  else
+  {
+    x = DotProduct (rdp.lookat[0], vec);
+    y = DotProduct (rdp.lookat[1], vec);
+  }
+  v->ou = (x * 0.5f + 0.5f) * s_scale;
+  v->ov = (y * 0.5f + 0.5f) * t_scale;
+  v->uv_scaled = 1;
+#ifdef EXTREME_LOGGING
+  FRDP ("calc sphere u: %f, v: %f\n", v->ou, v->ov);
+#endif
+}
+
+float DotProductC(register float *v1, register float *v2)
+{
+    register float result;
+    result = v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
+    return(result);
+}
+
+void NormalizeVectorC(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;
+    }
+}
+
+void TransformVectorC(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 InverseTransformVectorC (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 MulMatricesC(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];
+    }
+  }
+}
+*/
+void MulMatricesC(float m1[4][4],float m2[4][4],float r[4][4])
+{
+  for (int j=0; j<4; j++)
+  {
+      r[0][j] = m1[0][0] * m2[0][j] +
+                m1[0][1] * m2[1][j] +
+                m1[0][2] * m2[2][j] +
+                m1[0][3] * m2[3][j];
+      r[1][j] = m1[1][0] * m2[0][j] +
+                m1[1][1] * m2[1][j] +
+                m1[1][2] * m2[2][j] +
+                m1[1][3] * m2[3][j];
+      r[2][j] = m1[2][0] * m2[0][j] +
+                m1[2][1] * m2[1][j] +
+                m1[2][2] * m2[2][j] +
+                m1[2][3] * m2[3][j];
+      r[3][j] = m1[3][0] * m2[0][j] +
+                m1[3][1] * m2[1][j] +
+                m1[3][2] * m2[2][j] +
+                m1[3][3] * m2[3][j];
+  }
+}
+
+#ifdef __ARM_NEON__
+void MultMatrix_neon( float m0[4][4], float m1[4][4], float dest[4][4])
+{
+    asm volatile (
+       "vld1.32                {d0, d1}, [%1]!                 \n\t"   //q0 = m1
+       "vld1.32                {d2, d3}, [%1]!         \n\t"   //q1 = m1+4
+       "vld1.32                {d4, d5}, [%1]!         \n\t"   //q2 = m1+8
+       "vld1.32                {d6, d7}, [%1]          \n\t"   //q3 = m1+12
+       "vld1.32                {d16, d17}, [%0]!               \n\t"   //q8 = m0
+       "vld1.32                {d18, d19}, [%0]!       \n\t"   //q9 = m0+4
+       "vld1.32                {d20, d21}, [%0]!       \n\t"   //q10 = m0+8
+       "vld1.32                {d22, d23}, [%0]        \n\t"   //q11 = m0+12
+
+       "vmul.f32               q12, q8, d0[0]                  \n\t"   //q12 = q8 * d0[0]
+       "vmul.f32               q13, q8, d2[0]              \n\t"       //q13 = q8 * d2[0]
+       "vmul.f32               q14, q8, d4[0]              \n\t"       //q14 = q8 * d4[0]
+       "vmul.f32               q15, q8, d6[0]                  \n\t"   //q15 = q8 * d6[0]
+       "vmla.f32               q12, q9, d0[1]                  \n\t"   //q12 = q9 * d0[1]
+       "vmla.f32               q13, q9, d2[1]              \n\t"       //q13 = q9 * d2[1]
+       "vmla.f32               q14, q9, d4[1]              \n\t"       //q14 = q9 * d4[1]
+       "vmla.f32               q15, q9, d6[1]              \n\t"       //q15 = q9 * d6[1]
+       "vmla.f32               q12, q10, d1[0]                 \n\t"   //q12 = q10 * d0[0]
+       "vmla.f32               q13, q10, d3[0]                 \n\t"   //q13 = q10 * d2[0]
+       "vmla.f32               q14, q10, d5[0]                 \n\t"   //q14 = q10 * d4[0]
+       "vmla.f32               q15, q10, d7[0]                 \n\t"   //q15 = q10 * d6[0]
+       "vmla.f32               q12, q11, d1[1]                 \n\t"   //q12 = q11 * d0[1]
+       "vmla.f32               q13, q11, d3[1]                 \n\t"   //q13 = q11 * d2[1]
+       "vmla.f32               q14, q11, d5[1]                 \n\t"   //q14 = q11 * d4[1]
+       "vmla.f32               q15, q11, d7[1]             \n\t"       //q15 = q11 * d6[1]
+
+       "vst1.32                {d24, d25}, [%2]!               \n\t"   //d = q12
+       "vst1.32                {d26, d27}, [%2]!           \n\t"       //d+4 = q13
+       "vst1.32                {d28, d29}, [%2]!           \n\t"       //d+8 = q14
+       "vst1.32                {d30, d31}, [%2]            \n\t"       //d+12 = q15
+
+       :"+r"(m1), "+r"(m0), "+r"(dest):
+    : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
+    "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
+    "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
+    "memory"
+       );
+}
+
+void Normalize_neon(float v[3])
+{
+       asm volatile (
+       "vld1.32                {d4}, [%0]!                     \n\t"   //d4={x,y}
+       "flds                   s10, [%0]               \n\t"   //d5[0] = z
+       "sub                    %0, %0, #8              \n\t"   //d5[0] = z
+       "vmul.f32               d0, d4, d4                              \n\t"   //d0= d4*d4
+       "vpadd.f32              d0, d0, d0                              \n\t"   //d0 = d[0] + d[1]
+    "vmla.f32          d0, d5, d5                              \n\t"   //d0 = d0 + d5*d5
+
+       "vmov.f32               d1, d0                                  \n\t"   //d1 = d0
+       "vrsqrte.f32    d0, d0                                  \n\t"   //d0 = ~ 1.0 / sqrt(d0)
+       "vmul.f32               d2, d0, d1                              \n\t"   //d2 = d0 * d1
+       "vrsqrts.f32    d3, d2, d0                              \n\t"   //d3 = (3 - d0 * d2) / 2
+       "vmul.f32               d0, d0, d3                              \n\t"   //d0 = d0 * d3
+       "vmul.f32               d2, d0, d1                              \n\t"   //d2 = d0 * d1
+       "vrsqrts.f32    d3, d2, d0                              \n\t"   //d3 = (3 - d0 * d3) / 2
+       "vmul.f32               d0, d0, d3                              \n\t"   //d0 = d0 * d4
+
+       "vmul.f32               q2, q2, d0[0]                   \n\t"   //d0= d2*d4
+       "vst1.32                {d4}, [%0]!                     \n\t"   //d2={x0,y0}, d3={z0, w0}
+       "fsts                   s10, [%0]                       \n\t"   //d2={x0,y0}, d3={z0, w0}
+
+       :"+r"(v) :
+    : "d0", "d1", "d2", "d3", "d4", "d5", "memory"
+       );
+}
+
+float DotProduct_neon( float v0[3], float v1[3] )
+{
+    float dot;
+       asm volatile (
+       "vld1.32                {d8}, [%1]!                     \n\t"   //d8={x0,y0}
+       "vld1.32                {d10}, [%2]!            \n\t"   //d10={x1,y1}
+       "flds                   s18, [%1, #0]       \n\t"       //d9[0]={z0}
+       "flds                   s22, [%2, #0]       \n\t"       //d11[0]={z1}
+       "vmul.f32               d12, d8, d10            \n\t"   //d0= d2*d4
+       "vpadd.f32              d12, d12, d12           \n\t"   //d0 = d[0] + d[1]
+       "vmla.f32               d12, d9, d11            \n\t"   //d0 = d0 + d3*d5
+    "fmrs              %0, s24                 \n\t"   //r0 = s0
+       : "=r"(dot), "+r"(v0), "+r"(v1):
+    : "d8", "d9", "d10", "d11", "d12"
+
+       );
+    return dot;
+}
+
+#endif
+
+// 2008.03.29 H.Morii - added SSE 3DNOW! 3x3 1x3 matrix multiplication
+//                      and 3DNOW! 4x4 4x4 matrix multiplication
+// 2011-01-03 Balrog - removed because is in NASM format and not 64-bit compatible
+// This will need fixing.
+#ifndef __ARM_NEON__
+MULMATRIX MulMatrices = MulMatricesC;
+TRANSFORMVECTOR TransformVector = TransformVectorC;
+TRANSFORMVECTOR InverseTransformVector = InverseTransformVectorC;
+DOTPRODUCT DotProduct = DotProductC;
+NORMALIZEVECTOR NormalizeVector = NormalizeVectorC;
+#endif
+
+void MulMatricesSSE(float m1[4][4],float m2[4][4],float r[4][4])
+{
+#if defined(__GNUC__) && !defined(NO_ASM) && !defined(NOSSE)
+   /* [row][col]*/
+  typedef float v4sf __attribute__ ((vector_size (16)));
+  v4sf row0 = _mm_loadu_ps(m2[0]);
+  v4sf row1 = _mm_loadu_ps(m2[1]);
+  v4sf row2 = _mm_loadu_ps(m2[2]);
+  v4sf row3 = _mm_loadu_ps(m2[3]);
+
+  for (int i = 0; i < 4; ++i)
+  {
+    v4sf leftrow = _mm_loadu_ps(m1[i]);
+
+    // Fill tmp with four copies of leftrow[0]
+    v4sf tmp = leftrow;
+    tmp = _mm_shuffle_ps (tmp, tmp, 0);
+    // Calculate the four first summands
+    v4sf destrow = tmp * row0;
+
+    // Fill tmp with four copies of leftrow[1]
+    tmp = leftrow;
+    tmp = _mm_shuffle_ps (tmp, tmp, 1 + (1 << 2) + (1 << 4) + (1 << 6));
+    destrow += tmp * row1;
+
+    // Fill tmp with four copies of leftrow[2]
+    tmp = leftrow;
+    tmp = _mm_shuffle_ps (tmp, tmp, 2 + (2 << 2) + (2 << 4) + (2 << 6));
+    destrow += tmp * row2;
+
+    // Fill tmp with four copies of leftrow[3]
+    tmp = leftrow;
+    tmp = _mm_shuffle_ps (tmp, tmp, 3 + (3 << 2) + (3 << 4) + (3 << 6));
+    destrow += tmp * row3;
+
+    __builtin_ia32_storeups(r[i], destrow);
+  }
+ #elif !defined(NO_ASM) && !defined(NOSSE)
+  __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
+  }
+
+
+
+  void math_init()
+  {
+#ifndef __ARM_NEON__
+#ifndef _DEBUG
+    int IsSSE = FALSE;
+#if defined(__GNUC__) && !defined(NO_ASM) && !defined(NOSSE)
+    int edx, eax;
+    GLIDE64_TRY
+    {
+  #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
+    }
+    GLIDE64_CATCH
+      { return; }
+    // Check for SSE
+    if (edx & (1 << 25))
+      IsSSE = TRUE;
+#elif !defined(NO_ASM) && !defined(NOSSE)
+    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;
+        LOG("3DNOW! detected.\n");
+      }
+
+#endif //_DEBUG
+#endif //__ARM_NEON__
+    }
diff --git a/source/gles2glide64/src/Glide64/3dmath.h b/source/gles2glide64/src/Glide64/3dmath.h
new file mode 100755 (executable)
index 0000000..55e828d
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+void calc_light (VERTEX *v);
+void calc_linear (VERTEX *v);
+void calc_sphere (VERTEX *v);
+
+void math_init();
+#ifdef __ARM_NEON__
+float DotProductC(register float *v1, register float *v2);
+void NormalizeVectorC(float *v);
+void TransformVectorC(float *src, float *dst, float mat[4][4]);
+void InverseTransformVectorC (float *src, float *dst, float mat[4][4]);
+void MulMatricesC(float m1[4][4],float m2[4][4],float r[4][4]);
+void MultMatrix_neon( float m0[4][4], float m1[4][4], float dest[4][4]);
+void Normalize_neon(float v[3]);
+float DotProduct_neon( float v0[3], float v1[3] );
+
+#define MulMatrices                            MultMatrix_neon         //MulMatricesC
+#define TransformVector                        TransformVectorC
+#define InverseTransformVector InverseTransformVectorC
+#define DotProduct                             DotProductC                     //DotProduct_neon
+#define NormalizeVector                        Normalize_neon  //NormalizeVectorC
+#else
+typedef void (*MULMATRIX)(float m1[4][4],float m2[4][4],float r[4][4]); 
+extern MULMATRIX MulMatrices;
+typedef void (*TRANSFORMVECTOR)(float *src,float *dst,float mat[4][4]); 
+extern TRANSFORMVECTOR TransformVector;
+extern TRANSFORMVECTOR InverseTransformVector;
+typedef float (*DOTPRODUCT)(register float *v1, register float *v2);
+extern DOTPRODUCT DotProduct;
+typedef void (*NORMALIZEVECTOR)(float *v);
+extern NORMALIZEVECTOR NormalizeVector;
+#endif
diff --git a/source/gles2glide64/src/Glide64/3dmathneon.cpp b/source/gles2glide64/src/Glide64/3dmathneon.cpp
new file mode 100755 (executable)
index 0000000..9d69a8c
--- /dev/null
@@ -0,0 +1,133 @@
+#include "3dmath.h"
+
+static void MultMatrix_neon( float m0[4][4], float m1[4][4], float dest[4][4])
+{
+    asm volatile (
+       "vld1.32                {d0, d1}, [%1]!                 \n\t"   //q0 = m1
+       "vld1.32                {d2, d3}, [%1]!         \n\t"   //q1 = m1+4
+       "vld1.32                {d4, d5}, [%1]!         \n\t"   //q2 = m1+8
+       "vld1.32                {d6, d7}, [%1]          \n\t"   //q3 = m1+12
+       "vld1.32                {d16, d17}, [%0]!               \n\t"   //q8 = m0
+       "vld1.32                {d18, d19}, [%0]!       \n\t"   //q9 = m0+4
+       "vld1.32                {d20, d21}, [%0]!       \n\t"   //q10 = m0+8
+       "vld1.32                {d22, d23}, [%0]        \n\t"   //q11 = m0+12
+
+       "vmul.f32               q12, q8, d0[0]                  \n\t"   //q12 = q8 * d0[0]
+       "vmul.f32               q13, q8, d2[0]              \n\t"       //q13 = q8 * d2[0]
+       "vmul.f32               q14, q8, d4[0]              \n\t"       //q14 = q8 * d4[0]
+       "vmul.f32               q15, q8, d6[0]                  \n\t"   //q15 = q8 * d6[0]
+       "vmla.f32               q12, q9, d0[1]                  \n\t"   //q12 = q9 * d0[1]
+       "vmla.f32               q13, q9, d2[1]              \n\t"       //q13 = q9 * d2[1]
+       "vmla.f32               q14, q9, d4[1]              \n\t"       //q14 = q9 * d4[1]
+       "vmla.f32               q15, q9, d6[1]              \n\t"       //q15 = q9 * d6[1]
+       "vmla.f32               q12, q10, d1[0]                 \n\t"   //q12 = q10 * d0[0]
+       "vmla.f32               q13, q10, d3[0]                 \n\t"   //q13 = q10 * d2[0]
+       "vmla.f32               q14, q10, d5[0]                 \n\t"   //q14 = q10 * d4[0]
+       "vmla.f32               q15, q10, d7[0]                 \n\t"   //q15 = q10 * d6[0]
+       "vmla.f32               q12, q11, d1[1]                 \n\t"   //q12 = q11 * d0[1]
+       "vmla.f32               q13, q11, d3[1]                 \n\t"   //q13 = q11 * d2[1]
+       "vmla.f32               q14, q11, d5[1]                 \n\t"   //q14 = q11 * d4[1]
+       "vmla.f32               q15, q11, d7[1]             \n\t"       //q15 = q11 * d6[1]
+
+       "vst1.32                {d24, d25}, [%2]!               \n\t"   //d = q12
+       "vst1.32                {d26, d27}, [%2]!           \n\t"       //d+4 = q13
+       "vst1.32                {d28, d29}, [%2]!           \n\t"       //d+8 = q14
+       "vst1.32                {d30, d31}, [%2]            \n\t"       //d+12 = q15
+
+       :"+r"(m0), "+r"(m1), "+r"(dest):
+    : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
+    "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
+    "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
+    "memory"
+       );
+}
+
+static void TransformVectorNormalize_neon(float vec[3], float mtx[4][4])
+{
+       asm volatile (
+       "vld1.32                {d0}, [%1]                      \n\t"   //Q0 = v
+       "flds                   s2, [%1, #8]                    \n\t"   //Q0 = v
+       "vld1.32                {d18, d19}, [%0]!               \n\t"   //Q1 = m
+       "vld1.32                {d20, d21}, [%0]!           \n\t"       //Q2 = m+4
+       "vld1.32                {d22, d23}, [%0]            \n\t"       //Q3 = m+8
+
+       "vmul.f32               q2, q9, d0[0]                   \n\t"   //q2 = q9*Q0[0]
+       "vmla.f32               q2, q10, d0[1]                  \n\t"   //Q5 += Q1*Q0[1]
+       "vmla.f32               q2, q11, d1[0]                  \n\t"   //Q5 += Q2*Q0[2]
+
+    "vmul.f32          d0, d4, d4                              \n\t"   //d0 = d0*d0
+       "vpadd.f32              d0, d0, d0                              \n\t"   //d0 = d[0] + d[1]
+    "vmla.f32          d0, d5, d5                              \n\t"   //d0 = d0 + d1*d1
+
+       "vmov.f32               d1, d0                                  \n\t"   //d1 = d0
+       "vrsqrte.f32    d0, d0                                  \n\t"   //d0 = ~ 1.0 / sqrt(d0)
+       "vmul.f32               d2, d0, d1                              \n\t"   //d2 = d0 * d1
+       "vrsqrts.f32    d3, d2, d0                              \n\t"   //d3 = (3 - d0 * d2) / 2
+       "vmul.f32               d0, d0, d3                              \n\t"   //d0 = d0 * d3
+       "vmul.f32               d2, d0, d1                              \n\t"   //d2 = d0 * d1
+       "vrsqrts.f32    d3, d2, d0                              \n\t"   //d3 = (3 - d0 * d3) / 2
+       "vmul.f32               d0, d0, d3                              \n\t"   //d0 = d0 * d4
+
+       "vmul.f32               q2, q2, d0[0]                   \n\t"   //d0= d2*d4
+
+       "vst1.32                {d4}, [%1]                  \n\t"       //Q4 = m+12
+       "fsts                   s10, [%1, #8]           \n\t"   //Q4 = m+12
+       : "+r"(mtx): "r"(vec)
+    : "d0","d1","d2","d3","d18","d19","d20","d21","d22", "d23", "memory"
+       );
+}
+
+static void Normalize_neon(float v[3])
+{
+       asm volatile (
+       "vld1.32                {d4}, [%0]!                     \n\t"   //d4={x,y}
+       "flds                   s10, [%0]               \n\t"   //d5[0] = z
+       "sub                    %0, %0, #8              \n\t"   //d5[0] = z
+       "vmul.f32               d0, d4, d4                              \n\t"   //d0= d4*d4
+       "vpadd.f32              d0, d0, d0                              \n\t"   //d0 = d[0] + d[1]
+    "vmla.f32          d0, d5, d5                              \n\t"   //d0 = d0 + d5*d5
+
+       "vmov.f32               d1, d0                                  \n\t"   //d1 = d0
+       "vrsqrte.f32    d0, d0                                  \n\t"   //d0 = ~ 1.0 / sqrt(d0)
+       "vmul.f32               d2, d0, d1                              \n\t"   //d2 = d0 * d1
+       "vrsqrts.f32    d3, d2, d0                              \n\t"   //d3 = (3 - d0 * d2) / 2
+       "vmul.f32               d0, d0, d3                              \n\t"   //d0 = d0 * d3
+       "vmul.f32               d2, d0, d1                              \n\t"   //d2 = d0 * d1
+       "vrsqrts.f32    d3, d2, d0                              \n\t"   //d3 = (3 - d0 * d3) / 2
+       "vmul.f32               d0, d0, d3                              \n\t"   //d0 = d0 * d4
+
+       "vmul.f32               q2, q2, d0[0]                   \n\t"   //d0= d2*d4
+       "vst1.32                {d4}, [%0]!                     \n\t"   //d2={x0,y0}, d3={z0, w0}
+       "fsts                   s10, [%0]                       \n\t"   //d2={x0,y0}, d3={z0, w0}
+
+       :"+r"(v) :
+    : "d0", "d1", "d2", "d3", "d4", "d5", "memory"
+       );
+}
+
+static float DotProduct_neon( float v0[3], float v1[3] )
+{
+    float dot;
+       asm volatile (
+       "vld1.32                {d8}, [%1]!                     \n\t"   //d8={x0,y0}
+       "vld1.32                {d10}, [%2]!            \n\t"   //d10={x1,y1}
+       "flds                   s18, [%1, #0]       \n\t"       //d9[0]={z0}
+       "flds                   s22, [%2, #0]       \n\t"       //d11[0]={z1}
+       "vmul.f32               d12, d8, d10            \n\t"   //d0= d2*d4
+       "vpadd.f32              d12, d12, d12           \n\t"   //d0 = d[0] + d[1]
+       "vmla.f32               d12, d9, d11            \n\t"   //d0 = d0 + d3*d5
+    "fmrs              %0, s24                 \n\t"   //r0 = s0
+       : "=r"(dot), "+r"(v0), "+r"(v1):
+    : "d8", "d9", "d10", "d11", "d12"
+
+       );
+    return dot;
+}
+
+void MathInitNeon()
+{
+    MulMatrices = MultMatrix_neon;
+    //TransformVectorNormalize = TransformVectorNormalize_neon;
+    NormalizeVector = Normalize_neon;
+    DotProduct = DotProduct_neon;
+}
diff --git a/source/gles2glide64/src/Glide64/CRC.cpp b/source/gles2glide64/src/Glide64/CRC.cpp
new file mode 100755 (executable)
index 0000000..aadf78e
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+//
+// CRC32 calculation functions 
+//
+// Created by Gonetz, 2004
+//
+//****************************************************************
+//*
+
+#define CRC32_POLYNOMIAL     0x04C11DB7
+
+unsigned int CRCTable[ 256 ];
+
+unsigned int Reflect( unsigned int 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 );
+    }
+}
+//*/
+//*
+unsigned int CRC32( unsigned int crc, void *buffer, unsigned int count )
+{
+  unsigned int orig = crc;
+  unsigned char * p = reinterpret_cast<unsigned char*>(buffer);
+  while (count--)
+    crc = (crc >> 8) ^ CRCTable[(crc & 0xFF) ^ *p++];
+  return crc ^ orig;
+}
+//*/
+
+/*
+wxUint32 CRC_Calculate( wxUint32 crc, void *buffer, wxUint32 count )
+{
+  wxUint32 Crc32=crc;
+  __asm {
+                       mov     esi, buffer
+                       mov     ecx, count
+                       mov     edx, crc
+                       xor eax, eax
+
+loop1:
+                       inc     esi
+                       mov     al, dl
+                       xor     al, byte ptr [esi]
+                       shr     edx, 8
+                       mov     ebx, [CRCTable+eax*4]
+                       xor     edx, ebx
+
+                       loop loop1
+
+                       xor     Crc32, edx
+   }
+   return Crc32;
+}
+*/
+
+/*
+unsigned int CRC_Calculate( unsigned int crc, void *buffer, unsigned int count )
+{
+  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;
+}
+//*/
+
diff --git a/source/gles2glide64/src/Glide64/CRC.h b/source/gles2glide64/src/Glide64/CRC.h
new file mode 100644 (file)
index 0000000..2bc5177
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+//
+// CRC32 calculation functions 
+//
+// Created by Gonetz, 2004
+//
+//****************************************************************
+
+void CRC_BuildTable();
+
+unsigned int CRC32( unsigned int crc, void *buffer, unsigned int count );
diff --git a/source/gles2glide64/src/Glide64/Combine.cpp b/source/gles2glide64/src/Glide64/Combine.cpp
new file mode 100644 (file)
index 0000000..62cffae
--- /dev/null
@@ -0,0 +1,16692 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+#include "Gfx_1.3.h"
+#include "Util.h"
+#include "Combine.h"
+
+#define FASTSEARCH  // Enable fast combine mode searching algorithm
+
+float percent_org, percent, r, g, b;
+wxUint32 lod_frac;
+
+wxUint32 cc_lookup[257];
+wxUint32 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 (voodoo.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 (voodoo.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_T1_SUB_T0() \
+  cmb.tex |= 3, \
+  cmb.tmu1_a_func = GR_COMBINE_FUNCTION_LOCAL, \
+  cmb.tmu0_a_func = GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_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(color) cmb.ccolor=(color)&0xFFFFFF00
+#define CC_BYTE(byte) { cmb.ccolor=(byte<<8)|(byte<<16)|(byte<<24); }
+#define CC_C1MULC2(color1, color2) { \
+  cmb.ccolor=(wxUint8)( ((color1 & 0xFF000000) >> 24) * (((color2 & 0xFF000000) >> 24) /255.0f) ) <<  24 | \
+  (wxUint8)( ((color1 & 0x00FF0000) >> 16) * (((color2 & 0x00FF0000) >> 16) /255.0f) ) <<  16 | \
+  (wxUint8)( ((color1 & 0x0000FF00) >>  8) * (((color2 & 0x0000FF00) >>  8) /255.0f) ) <<   8 ; \
+}
+#define CC_C1SUBC2(color1, color2) { \
+  cmb.ccolor=(wxUint8)( max(0, (int)((color1 & 0xFF000000) >> 24) - (int)((color2 & 0xFF000000) >> 24)) ) << 24 | \
+  (wxUint8)( max(0, (int)((color1 & 0x00FF0000) >> 16) - (int)((color2 & 0x00FF0000) >> 16)) ) << 16 | \
+  (wxUint8)( max(0, (int)((color1 & 0x0000FF00) >>  8) - (int)((color2 & 0x0000FF00) >>  8)) ) <<  8 ; \
+}
+#define CC_COLMULBYTE(color, byte) { \
+    float factor = byte/255.0f; \
+    cmb.ccolor = (wxUint8)( ((color & 0xFF000000) >> 24) * factor ) <<  24 | \
+      (wxUint8)( ((color & 0x00FF0000) >> 16) * factor ) <<  16 | \
+      (wxUint8)( ((color & 0x0000FF00) >>  8) * factor ) <<   8 ; \
+}
+#define CC_PRIM() CC(rdp.prim_color)
+#define CC_ENV() CC(rdp.env_color)
+#define CC_1SUBPRIM() CC((~rdp.prim_color))
+#define CC_1SUBENV() CC((~rdp.env_color))
+#define CC_PRIMA() CC_BYTE((rdp.prim_color&0xFF))
+#define CC_ENVA() CC_BYTE((rdp.env_color&0xFF))
+#define CC_1SUBPRIMA() CC_BYTE(((~rdp.prim_color)&0xFF))
+#define CC_1SUBENVA() CC_BYTE(((~rdp.env_color)&0xFF))
+#define CC_PRIMLOD() CC_BYTE(rdp.prim_lodfrac)
+#define CC_K5() CC_BYTE(rdp.K5)
+#define CC_PRIMMULENV() CC_C1MULC2(rdp.prim_color, rdp.env_color)
+#define CC_PRIMSUBENV() CC_C1SUBC2(rdp.prim_color, rdp.env_color)
+
+#define XSHADE(color, flag) { \
+  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 |= flag; \
+}
+#define XSHADE1M(color, flag) { \
+  rdp.col[0] *= 1.0f-((float)((color & 0xFF000000) >> 24)/255.0f); \
+  rdp.col[1] *= 1.0f-((float)((color & 0x00FF0000) >> 16)/255.0f); \
+  rdp.col[2] *= 1.0f-((float)((color & 0x0000FF00) >> 8)/255.0f); \
+  rdp.cmb_flags |= flag; \
+}
+#define XSHADEC1MC2(color1, color2, flag) { \
+  rdp.col[0] *= (float)( max(0, (int)((color1 & 0xFF000000) >> 24) - (int)((color2 & 0xFF000000) >> 24)) )/255.0f; \
+  rdp.col[1] *= (float)( max(0, (int)((color1 & 0x00FF0000) >> 16) - (int)((color2 & 0x00FF0000) >> 16)) )/255.0f; \
+  rdp.col[2] *= (float)( max(0, (int)((color1 & 0x0000FF00) >> 8)  - (int)((color2 & 0x0000FF00) >> 8)) )/255.0f; \
+  rdp.cmb_flags |= flag; \
+}
+#define XSHADE_BYTE(byte, flag) { \
+  float tmpcol = (float)byte / 255.0f; \
+  rdp.col[0] *= tmpcol; \
+  rdp.col[1] *= tmpcol; \
+  rdp.col[2] *= tmpcol; \
+  rdp.cmb_flags |= flag; \
+}
+#define MULSHADE(color) XSHADE(color, CMB_MULT)
+#define MULSHADE_PRIM() MULSHADE(rdp.prim_color)
+#define MULSHADE_ENV() MULSHADE(rdp.env_color)
+#define MULSHADE_1MPRIM() XSHADE1M(rdp.prim_color, CMB_MULT)
+#define MULSHADE_1MENV() XSHADE1M(rdp.env_color, CMB_MULT)
+#define MULSHADE_PRIMSUBENV() XSHADEC1MC2(rdp.prim_color, rdp.env_color, CMB_MULT)
+#define MULSHADE_ENVSUBPRIM() XSHADEC1MC2(rdp.env_color, rdp.prim_color, CMB_MULT)
+#define MULSHADE_BYTE(byte) XSHADE_BYTE(byte, CMB_MULT)
+#define MULSHADE_PRIMA() MULSHADE_BYTE((rdp.prim_color & 0xFF))
+#define MULSHADE_ENVA() MULSHADE_BYTE((rdp.env_color & 0xFF))
+#define MULSHADE_1MENVA() MULSHADE_BYTE(((~rdp.env_color) & 0xFF))
+#define MULSHADE_PRIMLOD() MULSHADE_BYTE((rdp.prim_lodfrac & 0xFF))
+#define MULSHADE_K5() MULSHADE_BYTE(rdp.K5)
+
+#define SETSHADE(color) XSHADE(color, CMB_SET)
+#define SETSHADE_PRIM() SETSHADE(rdp.prim_color)
+#define SETSHADE_ENV() SETSHADE(rdp.env_color)
+#define SETSHADE_BYTE(byte) XSHADE_BYTE(byte, CMB_SET)
+#define SETSHADE_PRIMA() SETSHADE_BYTE((rdp.prim_color & 0xFF))
+#define SETSHADE_ENVA() SETSHADE_BYTE((rdp.env_color & 0xFF))
+#define SETSHADE_1MPRIMA() SETSHADE_BYTE(((~rdp.prim_color) & 0xFF))
+#define SETSHADE_PRIMLOD() SETSHADE_BYTE((rdp.prim_lodfrac & 0xFF))
+#define SETSHADE_1MPRIMLOD() SETSHADE_BYTE(((~rdp.prim_lodfrac) & 0xFF))
+
+#define SETSHADE_1MPRIM() XSHADE1M(rdp.prim_color, CMB_SET)
+#define SETSHADE_1MENV() XSHADE1M(rdp.env_color, CMB_SET)
+#define SETSHADE_PRIMSUBENV() XSHADEC1MC2(rdp.prim_color, rdp.env_color, CMB_SET)
+#define SETSHADE_ENVSUBPRIM() XSHADEC1MC2(rdp.env_color, rdp.prim_color, CMB_SET)
+#define SETSHADE_SHADE_A() { \
+  rdp.cmb_flags = CMB_SETSHADE_SHADEALPHA; \
+}
+
+#define XSHADEADD(color, flag) { \
+  rdp.coladd[0] *= (float)((color & 0xFF000000) >> 24) / 255.0f; \
+  rdp.coladd[1] *= (float)((color & 0x00FF0000) >> 16) / 255.0f; \
+  rdp.coladd[2] *= (float)((color & 0x0000FF00) >> 8) / 255.0f; \
+  rdp.cmb_flags |= flag; \
+}
+#define XSHADEC1MC2ADD(color1, color2, flag) { \
+  rdp.coladd[0] *= (float)( max(0, (int)((color1 & 0xFF000000) >> 24) - (int)((color2 & 0xFF000000) >> 24)) )/255.0f; \
+  rdp.coladd[1] *= (float)( max(0, (int)((color1 & 0x00FF0000) >> 16) - (int)((color2 & 0x00FF0000) >> 16)) )/255.0f; \
+  rdp.coladd[2] *= (float)( max(0, (int)((color1 & 0x0000FF00) >> 8)  - (int)((color2 & 0x0000FF00) >> 8)) )/255.0f; \
+  rdp.cmb_flags |= flag; \
+}
+#define SUBSHADE_PRIM() XSHADEADD(rdp.prim_color, CMB_SUB)
+#define SUBSHADE_ENV() XSHADEADD(rdp.env_color, CMB_SUB)
+#define SUBSHADE_PRIMSUBENV() XSHADEC1MC2ADD(rdp.prim_color, rdp.env_color, CMB_SUB)
+#define ADDSHADE_PRIM() XSHADEADD(rdp.prim_color, CMB_ADD)
+#define ADDSHADE_ENV() XSHADEADD(rdp.env_color, CMB_ADD)
+#define ADDSHADE_PRIMSUBENV() XSHADEC1MC2ADD(rdp.prim_color, rdp.env_color, CMB_ADD)
+#define SUBSHADE_PRIMMULENV() { \
+  rdp.coladd[0] *= (float)( ((rdp.prim_color & 0xFF000000) >> 24) * ((rdp.env_color & 0xFF000000) >> 24) )/255.0f/255.0f; \
+  rdp.coladd[1] *= (float)( ((rdp.prim_color & 0x00FF0000) >> 16) * ((rdp.env_color & 0x00FF0000) >> 16) )/255.0f/255.0f; \
+  rdp.coladd[2] *= (float)( ((rdp.prim_color & 0x0000FF00) >> 8) * ((rdp.env_color & 0x0000FF00) >> 8) )/255.0f/255.0f; \
+  rdp.cmb_flags |= CMB_SUB; \
+}
+
+#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 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 MULSHADE_SHADEA() rdp.cmb_flags |= CMB_MULT_OWN_ALPHA;
+
+#define CA(color) cmb.ccolor|=(color)&0xFF
+#define CA_PRIM() CA(rdp.prim_color)
+#define CA_ENV() CA(rdp.env_color)
+#define CA_INVPRIM() cmb.ccolor|=0xFF-(rdp.prim_color&0xFF)
+#define CA_INVENV() cmb.ccolor|=0xFF-(rdp.env_color&0xFF)
+#define CA_ENV1MPRIM() cmb.ccolor|= (wxUint32)(((rdp.env_color&0xFF)/255.0f) * (((~(rdp.prim_color&0xFF)) & 0xff)/255.0f) * 255.0f);
+#define CA_PRIMENV() cmb.ccolor |= (wxUint32)(((rdp.env_color&0xFF)/255.0f) * ((rdp.prim_color&0xFF)/255.0f) * 255.0f);
+#define CA_PRIMLOD() cmb.ccolor |= rdp.prim_lodfrac;
+#define CA_PRIM_MUL_PRIMLOD() cmb.ccolor |= (int)(((rdp.prim_color&0xFF) * rdp.prim_lodfrac) / 255.0f);
+#define CA_ENV_MUL_PRIMLOD() cmb.ccolor |= (int)(((rdp.env_color&0xFF) * rdp.prim_lodfrac) / 255.0f);
+
+#define XSHADE_A(color, flag) { \
+  rdp.col[3] *= (float)(color & 0xFF) / 255.0f; \
+  rdp.cmb_flags |= flag; \
+}
+#define XSHADE1M_A(color, flag) { \
+  rdp.col[3] *= 1.0f-((float)(color & 0xFF) / 255.0f); \
+  rdp.cmb_flags |= flag; \
+}
+#define XSHADEC1MC2_A(color1, color2, flag) { \
+  rdp.col[3] *= (float)( max(0, (int)(color1 & 0xFF) - (int)(color2 & 0xFF)) ) / 255.0f; \
+  rdp.cmb_flags |= flag; \
+}
+#define MULSHADE_A_PRIM() XSHADE_A(rdp.prim_color, CMB_A_MULT)
+#define MULSHADE_A_1MPRIM() XSHADE1M_A(rdp.prim_color, CMB_A_MULT)
+#define MULSHADE_A_ENV() XSHADE_A(rdp.env_color, CMB_A_MULT)
+#define MULSHADE_A_PRIMSUBENV() XSHADEC1MC2_A(rdp.prim_color, rdp.env_color, CMB_A_MULT)
+#define MULSHADE_A_ENVSUBPRIM() XSHADEC1MC2_A(rdp.env_color, rdp.prim_color, CMB_A_MULT)
+#define SETSHADE_A(color) XSHADE_A(color, CMB_A_SET)
+#define SETSHADE_A_PRIM() SETSHADE_A(rdp.prim_color)
+#define SETSHADE_A_ENV() SETSHADE_A(rdp.env_color)
+#define SETSHADE_A_PRIMSUBENV() XSHADEC1MC2_A(rdp.prim_color, rdp.env_color, CMB_A_SET)
+#define SETSHADE_A_INVENV() XSHADE1M_A(rdp.env_color, CMB_A_SET)
+
+#define XSHADEADD_A(color, flag) { \
+  rdp.coladd[3] *= (float)(color & 0xFF) / 255.0f; \
+  rdp.cmb_flags |= flag; \
+}
+#define SUBSHADE_A_PRIM() XSHADEADD_A(rdp.prim_color, CMB_A_SUB)
+#define SUBSHADE_A_ENV() XSHADEADD_A(rdp.env_color, CMB_A_SUB)
+#define ADDSHADE_A_PRIM() XSHADEADD_A(rdp.prim_color, CMB_A_ADD)
+#define ADDSHADE_A_ENV() XSHADEADD_A(rdp.env_color, 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 ()
+{
+  if ((rdp.othermode_l & 0x4000) && (rdp.cycle_mode < 2))
+  {
+    wxUint32 blend_mode = (rdp.othermode_l >> 16);
+    if (blend_mode == 0xa500)
+    {
+      CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+        GR_COMBINE_FACTOR_ONE,
+        GR_COMBINE_LOCAL_CONSTANT,
+        GR_COMBINE_OTHER_TEXTURE);
+      float fog = (rdp.fog_color&0xFF)/255.0f;
+      wxUint32 R = (wxUint32)(((rdp.blend_color>>24)&0xFF)*fog);
+      wxUint32 G = (wxUint32)(((rdp.blend_color>>16)&0xFF)*fog);
+      wxUint32 B = (wxUint32)(((rdp.blend_color>> 8)&0xFF)*fog);
+      CC((R<<24)|(G<<16)|(B<<8));
+    }
+    else if (blend_mode == 0x55f0) //cmem*afog + cfog*1ma
+    {
+      CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+        GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA,
+        GR_COMBINE_LOCAL_NONE,
+        GR_COMBINE_OTHER_CONSTANT);
+      CC(rdp.fog_color);
+      A_USE_T0 ();
+    }
+    else
+    {
+      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,
+      GR_COMBINE_FACTOR_ONE,
+      GR_COMBINE_LOCAL_NONE,
+      GR_COMBINE_OTHER_TEXTURE);
+  }
+  USE_T0 ();
+}
+
+static void cc_t0a ()
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_TEXTURE_ALPHA,
+    GR_COMBINE_LOCAL_NONE,
+    GR_COMBINE_OTHER_CONSTANT);
+  USE_T0 ();
+  A_USE_T0 ();
+  CC (0xFFFFFF00);
+}
+
+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__env_inter_t0_using_k5__using_t1a ()
+{
+CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+GR_COMBINE_FACTOR_ONE,
+GR_COMBINE_LOCAL_NONE,
+GR_COMBINE_OTHER_TEXTURE);
+wxUint32 col1 = (rdp.K5<<24) | (rdp.K5<<16) | (rdp.K5<<8);
+MOD_0 (TMOD_COL_INTER_TEX_USING_COL1);
+MOD_0_COL (rdp.env_color & 0xFFFFFF00);
+MOD_0_COL1 (col1 & 0xFFFFFF00);
+rdp.best_tex = 0;
+cmb.tex |= 3;
+cmb.tmu1_func = GR_COMBINE_FUNCTION_LOCAL;
+cmb.tmu1_a_func = GR_COMBINE_FUNCTION_LOCAL;
+cmb.tmu0_func = GR_COMBINE_FUNCTION_BLEND;
+cmb.tmu0_fac = GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA;
+}
+*/
+
+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_scale ()
+{
+  CCMB (GR_COMBINE_FUNCTION_LOCAL,
+    GR_COMBINE_FACTOR_NONE,
+    GR_COMBINE_LOCAL_CONSTANT,
+    GR_COMBINE_OTHER_NONE);
+  CC (rdp.SCALE);
+}
+
+static void cc_shade ()
+{
+  CCMB (GR_COMBINE_FUNCTION_LOCAL,
+    GR_COMBINE_FACTOR_NONE,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_NONE);
+}
+
+static void cc_one_mul_shade ()
+{
+  if ((settings.hacks&hack_Knockout) && (rdp.aTBuffTex[0] || rdp.aTBuffTex[1] || rdp.cur_image)) //hack for boxer shadow
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+      GR_COMBINE_FACTOR_LOCAL,
+      GR_COMBINE_LOCAL_CONSTANT,
+      GR_COMBINE_OTHER_TEXTURE);
+    CC (0x20202000);
+    USE_T0 ();
+  }
+  else
+  {
+    cc_shade ();
+  }
+}
+
+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 ();
+  if ((rdp.cycle1 & 0xFFFF) == (rdp.cycle2 & 0xFFFF)) // 1 cycle, use t0
+  {
+    USE_T0 ();
+  }
+  else
+  {
+    USE_T1 ();
+  }
+}
+
+static void cc_t0a_mul_prim ()
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_TEXTURE_ALPHA,
+    GR_COMBINE_LOCAL_NONE,
+    GR_COMBINE_OTHER_CONSTANT);
+  CC_PRIM ();
+  A_USE_T0 ();
+}
+
+//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 ();
+  wxUint8 factor = (wxUint8)(rdp.env_color&0xFF);
+  T1_INTER_T0_USING_FACTOR (factor);
+}
+
+static void cc__t0_inter_one_using_t1__mul_prim ()
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_LOCAL,
+    GR_COMBINE_LOCAL_CONSTANT,
+    GR_COMBINE_OTHER_TEXTURE);
+  CC_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_ONE_MINUS_LOCAL;
+}
+
+static void cc__t0_inter_one_using_primlod__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)
+  {
+    T0CCMBEXT(GR_CMBX_OTHER_TEXTURE_RGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ONE_MINUS_X,
+      GR_CMBX_DETAIL_FACTOR, 0,
+      GR_CMBX_B, 0);
+    cmb.tex |= 1;
+    percent = (float)lod_frac / 255.0f;
+    cmb.dc0_detailmax = cmb.dc1_detailmax = percent;
+  }
+  else
+  {
+    MOD_0 (TMOD_TEX_INTER_COLOR_USING_FACTOR);
+    MOD_0_COL (0xFFFFFF00);
+    MOD_0_FAC (lod_frac);
+    USE_T0 ();
+  }
+}
+
+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 ();
+  }
+}
+
+static void cc__t1_inter_one_using_enva__mul_t0 ()
+{
+  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_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);
+    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_ZERO, 0);
+    cmb.tex |= 3;
+    cmb.tex_ccolor = 0xFFFFFF00 | (rdp.env_color&0xFF);
+  }
+  else
+  {
+    if ((rdp.env_color&0xFF) == 0xFF)
+    {
+      USE_T0 ();
+    }
+    else
+    {
+      T0_MUL_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_scale ()
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_LOCAL,
+    GR_COMBINE_LOCAL_CONSTANT,
+    GR_COMBINE_OTHER_TEXTURE);
+  CC (rdp.SCALE);
+  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_f1_sky ()
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL,
+    GR_COMBINE_FACTOR_TEXTURE_ALPHA,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_CONSTANT);
+  MULSHADE_SHADEA ();
+  MULSHADE_ENVSUBPRIM ();
+  ADDSHADE_PRIM();
+  CC(0xFFFFFFFF);
+}
+
+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 ();
+}
+
+static void cc__t0_mul_shade__add__t1_mul_shade ()
+{
+  //combiner is used in Spiderman. It seems that t0 is used instead of t1
+  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_ITRGB, 0,
+      GR_CMBX_ZERO, 0);
+    cmb.tex |= 1;
+    CCMBEXT(GR_CMBX_ITRGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X,
+      GR_CMBX_ZERO, 1,
+      GR_CMBX_B, 0);
+  }
+  else
+  {
+    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_prim__inter_env_using_enva ()
+{
+  wxUint32 enva  = rdp.env_color&0xFF;
+  if (enva == 0xFF)
+    cc_env ();
+  else if (enva == 0)
+    cc_t0_mul_prim ();
+  else 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, 0,
+      GR_CMBX_ZERO, 0);
+    cmb.tex |= 1;
+    cmb.tex_ccolor = rdp.prim_color;
+    CCMBEXT(GR_CMBX_ITRGB, GR_FUNC_MODE_X,
+      GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_CONSTANT_COLOR, 0,
+      GR_CMBX_B, 0);
+    SETSHADE_ENV();
+    CC_ENVA();
+  }
+  else
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+      GR_COMBINE_FACTOR_LOCAL,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+    SETSHADE_PRIM();
+    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__t1_inter_t0_using_t1__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_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X,
+      GR_CMBX_OTHER_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_B, 0,
+      GR_CMBX_B, 0);
+    cmb.tex |= 3;
+  }
+  else
+  {
+    T0_INTER_T1_USING_FACTOR (0x7F);
+  }
+}
+
+//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);
+  wxUint8 factor = (wxUint8)(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_one_using_prim__mul_shade ()
+{
+  // (1-t0)*prim+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_ZERO,
+      GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_ONE_MINUS_X,
+      GR_CMBX_LOCAL_TEXTURE_RGB, 0,
+      GR_CMBX_B, 0);
+    cmb.tex |= 1;
+    cmb.tex_ccolor = rdp.prim_color;
+  }
+  else
+  {
+    USE_T0 ();
+    MOD_0 (TMOD_TEX_INTER_COL_USING_COL1);
+    MOD_0_COL (0xFFFFFF00);
+    MOD_0_COL1 (rdp.prim_color & 0xFFFFFF00);
+  }
+}
+
+static void cc__t0_inter_one_using_primlod__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_OTHER_TEXTURE_RGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ONE_MINUS_X,
+      GR_CMBX_DETAIL_FACTOR, 0,
+      GR_CMBX_B, 0);
+    cmb.tex |= 1;
+    percent = (float)lod_frac / 255.0f;
+    cmb.dc0_detailmax = cmb.dc1_detailmax = percent;
+  }
+  else
+  {
+    MOD_0 (TMOD_TEX_INTER_COLOR_USING_FACTOR);
+    MOD_0_COL (0xFFFFFF00);
+    MOD_0_FAC (lod_frac);
+    USE_T0 ();
+  }
+}
+
+//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);
+  }
+}
+
+//Added by Gonetz
+static void cc__t0_inter_env_using_shadea__mul_shade ()
+{
+  // (env-t0)*shade_a+t0, (cmb-0)*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_ITALPHA, 0,
+      GR_CMBX_B, 0);
+    cmb.tex |= 1;
+    cmb.tex_ccolor = rdp.env_color;
+    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
+  {
+    cc_t0_mul_shade ();
+  }
+}
+
+static void cc__t0_mul_prim_add_env__mul_shade ()
+{
+  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 |= 1;
+    cmb.tex_ccolor = rdp.prim_color;
+    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_ENV ();
+  }
+  else
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+      GR_COMBINE_FACTOR_LOCAL,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+    MOD_0 (TMOD_TEX_SCALE_COL_ADD_COL);
+    MOD_0_COL (rdp.prim_color & 0xFFFFFF00);
+    MOD_0_COL1 (rdp.env_color & 0xFFFFFF00);
+       USE_T0 ();
+  }
+}
+
+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__one_sub_shade_mul_t0_add_shade__mul_shade ()
+{
+  if (cmb.combine_ext)
+  {
+    T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_ITRGB, GR_FUNC_MODE_ONE_MINUS_X,
+      GR_CMBX_LOCAL_TEXTURE_RGB, 0,
+      GR_CMBX_B, 0);
+    cmb.tex |= 1;
+    CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X,
+         GR_CMBX_ZERO, GR_FUNC_MODE_ZERO,
+      GR_CMBX_ITRGB, 0,
+      GR_CMBX_ZERO, 0);
+  }
+  else
+  {
+    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__t0_sub_prim_mul_t1_add_t1__mul_shade ()
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_LOCAL,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_TEXTURE);
+  if (rdp.prim_color & 0xFFFFFF00)
+  {
+    MOD_0 (TMOD_TEX_SUB_COL);
+    MOD_0_COL (rdp.prim_color & 0xFFFFFF00);
+  }
+  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_OTHER_TEXTURE_RGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_LOCAL_TEXTURE_RGB, 0,
+      GR_CMBX_B, 0);
+    cmb.tex |= 3;
+  }
+  else
+  {
+    T0_MUL_T1 ();
+  }
+}
+
+static void cc__t1_sub_env_mul_t0_add_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_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.env_color;
+    cmb.tex |= 3;
+  }
+  else
+  {
+    MOD_1 (TMOD_TEX_SUB_COL);
+    MOD_1_COL (rdp.env_color & 0xFFFFFF00);
+    T0_MUL_T1_ADD_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__t0_inter_prim_using_prima__inter_env_using_enva ()
+{
+  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;
+    CCMBEXT(GR_CMBX_ITRGB, GR_FUNC_MODE_X,
+      GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_CONSTANT_COLOR, 0,
+      GR_CMBX_B, 0);
+    CC_ENVA ();
+    SETSHADE_ENV ();
+  }
+  else
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+      GR_COMBINE_FACTOR_TEXTURE_RGB,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_CONSTANT);
+    CC_1SUBENVA ();
+    SETSHADE_ENV ();
+    SETSHADE_ENVA ();
+    MOD_0 (TMOD_TEX_INTER_COLOR_USING_FACTOR);
+    MOD_0_COL (rdp.prim_color & 0xFFFFFF00);
+    MOD_0_FAC (rdp.prim_color & 0xFF);
+    USE_T0 ();
+  }
+}
+
+static void cc_prim_inter_t1_mul_shade_using_texa ()
+{
+  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_ITRGB, 0,
+      GR_CMBX_ZERO, 0);
+    cmb.tex |= 3;
+    CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X,
+      GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_TEXTURE_ALPHA, 0,
+      GR_CMBX_B, 0);
+  }
+  else
+  {
+    cc_t1_mul_shade ();
+  }
+}
+
+static void cc__prim_inter_t0_using_t0a__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_NEGATIVE_X,
+      GR_CMBX_LOCAL_TEXTURE_ALPHA, 0,
+      GR_CMBX_B, 0);
+    cmb.tex_ccolor = rdp.prim_color;
+    cmb.tex |= 1;
+  }
+  else
+  {
+    MOD_0 (TMOD_COL_INTER_TEX_USING_TEXA);
+    MOD_0_COL (rdp.prim_color & 0xFFFFFF00);
+    USE_T0 ();
+  }
+}
+
+static void cc__prim_inter_t0_using_t0a__inter_env_using_enva ()
+{
+  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_LOCAL_TEXTURE_ALPHA, 0,
+      GR_CMBX_B, 0);
+    cmb.tex_ccolor = rdp.prim_color;
+    cmb.tex |= 1;
+    CCMBEXT(GR_CMBX_ITRGB, GR_FUNC_MODE_X,
+      GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_CONSTANT_COLOR, 0,
+      GR_CMBX_B, 0);
+    CC_ENVA ();
+    SETSHADE_ENV ();
+  }
+  else
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+      GR_COMBINE_FACTOR_TEXTURE_RGB,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_CONSTANT);
+    CC_1SUBENVA ();
+    SETSHADE_ENV ();
+    SETSHADE_ENVA ();
+    MOD_0 (TMOD_COL_INTER_TEX_USING_TEXA);
+    MOD_0_COL (rdp.prim_color & 0xFFFFFF00);
+    USE_T0 ();
+  }
+}
+
+// ** A*B **
+
+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 ();
+}
+
+static void cc_t0_sub_shade_mul_shadea_add_shade ();
+static void cc__shade_inter_t0_using_shadea__mul_shade ()
+{
+  if (cmb.combine_ext)
+  {
+    T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X,
+      GR_CMBX_ITRGB, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_ITALPHA, 0,
+      GR_CMBX_B, 0);
+    cmb.tex |= 1;
+    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
+  {
+    cc_t0_sub_shade_mul_shadea_add_shade ();
+  }
+}
+
+static void cc__prim_inter_env_using_enva__mul_shade ()
+{
+  const float ea = ((float)(rdp.env_color&0xFF)) / 255.0f;
+  const float ea_i = 1.0f - ea;
+  wxUint32 pr = (rdp.prim_color >> 24)&0xFF;
+  wxUint32 pg = (rdp.prim_color >> 16)&0xFF;
+  wxUint32 pb = (rdp.prim_color >>  8)&0xFF;
+  wxUint32 er = (rdp.env_color >> 24)&0xFF;
+  wxUint32 eg = (rdp.env_color >> 16)&0xFF;
+  wxUint32 eb = (rdp.env_color >>  8)&0xFF;
+  wxUint32 r = min(255, (wxUint32)(er*ea + pr*ea_i));
+  wxUint32 g = min(255, (wxUint32)(eg*ea + pg*ea_i));
+  wxUint32 b = min(255, (wxUint32)(eb*ea + pb*ea_i));
+  wxUint32 col = (r << 24) | (g << 16) | (b << 8) | 0xFF;
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_LOCAL,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_CONSTANT);
+  CC (col);
+}
+
+//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 ();
+}
+
+static void cc_scale_mul_shade ()
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_LOCAL,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_CONSTANT);
+  CC (rdp.SCALE);
+}
+
+// ** A+B **
+
+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_mul_t1__add_env_mul__t0_mul_t1__add_env ()
+{
+  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_ZERO,
+      GR_CMBX_LOCAL_TEXTURE_RGB, 0,
+      GR_CMBX_B, 0);
+    cmb.tex_ccolor = rdp.env_color;
+    cmb.tex |= 3;
+    CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X,
+      GR_CMBX_ZERO, GR_FUNC_MODE_ZERO,
+      GR_CMBX_TEXTURE_RGB, 0,
+      GR_CMBX_ZERO, 0);
+  }
+  else
+    cc__t0_mul_t1__add_env();
+}
+
+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__t0_mul_t1__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);
+  T0_MUL_T1 ();
+}
+
+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 ();
+}
+
+static void cc_shade_add_shade () //Aded by Gonetz
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+    GR_COMBINE_FACTOR_ONE,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_ITERATED);
+}
+
+// ** 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 ();
+  wxUint8 factor = (wxUint8)(rdp.env_color&0xFF);
+  T0_INTER_T1_USING_FACTOR (factor);
+}
+
+static void cc_t0_sub__shade_mul_center ()
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL,
+    GR_COMBINE_FACTOR_ONE,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_TEXTURE);
+  MULSHADE(rdp.CENTER);
+  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 ();
+    SETSHADE_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_env_sub__t0_mul_scale_add_env__mul_prim ()
+{
+  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.SCALE;
+    cmb.tex |= 1;
+    CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_ITRGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_CONSTANT_COLOR, 0,
+      GR_CMBX_B, 0);
+    SETSHADE_ENV ();
+    CC_PRIM ();
+  }
+  else
+    cc_t0_add_env ();
+}
+
+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;
+  wxUint8 r = (wxUint8)(rdp.env_color >> 24) & 0xFF;
+  r = (wxUint8)(r*scale);
+  wxUint8 g = (wxUint8)(rdp.env_color >> 16) & 0xFF;
+  g = (wxUint8)(g*scale);
+  wxUint8 b = (wxUint8)(rdp.env_color >>  8) & 0xFF;
+  b = (wxUint8)(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;
+}
+
+static void cc__t0_sub_env_mul_enva__add_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_DETAIL_FACTOR, 0,
+      GR_CMBX_ZERO, 0);
+    cmb.tex_ccolor = rdp.env_color;
+    cmb.tex |= 1;
+    percent = (float)(rdp.env_color&0xFF) / 255.0f;
+    cmb.dc0_detailmax = cmb.dc1_detailmax = percent;
+
+    CCMBEXT(GR_CMBX_ITRGB, GR_FUNC_MODE_X,
+      GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_CONSTANT_COLOR, 0,
+      GR_CMBX_B, 0);
+    CC_PRIM ();
+  }
+  else {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+         GR_COMBINE_FACTOR_ONE,
+         GR_COMBINE_LOCAL_ITERATED,
+         GR_COMBINE_OTHER_TEXTURE);
+    MULSHADE_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 ();
+  }
+}
+
+// ** 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_shirt ()
+{
+  // (t1-0)*prim+0, (1-t0)*t1+cmb
+  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_X,
+    GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO,
+    GR_CMBX_TMU_CCOLOR, 0,
+    GR_CMBX_ZERO, 0);
+    //*/
+    //*
+    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_LOCAL_TEXTURE_RGB, 1,
+      GR_CMBX_B, 0);
+    cmb.tex |= 3;
+    cmb.tex_ccolor = rdp.prim_color;
+  }
+  else
+  {
+    MOD_1 (TMOD_TEX_MUL_COL);
+    MOD_1_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)
+  {
+    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__sub_prim_mul_env_add_shade ()
+{
+  if (cmb.combine_ext)
+  {
+    T1CCMBEXT(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);
+    T0CCMBEXT(GR_CMBX_OTHER_TEXTURE_RGB, GR_FUNC_MODE_X,
+      GR_CMBX_ITRGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_LOCAL_TEXTURE_RGB, 0,
+      GR_CMBX_B, 0);
+    cmb.tex_ccolor = rdp.env_color;
+    cmb.tex |= 3;
+    CCMBEXT(GR_CMBX_ITRGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_ZERO, 1,
+      GR_CMBX_TEXTURE_RGB, 0);
+    CC_PRIMMULENV ();
+  }
+  else
+  {
+    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_sub_prim_mul_t1_add_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 ();
+  if (rdp.prim_color & 0xFFFFFF00)
+  {
+    MOD_0 (TMOD_TEX_SUB_COL);
+    MOD_0_COL (rdp.prim_color & 0xFFFFFF00);
+  }
+  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_OTHER_TEXTURE_RGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_LOCAL_TEXTURE_RGB, 0,
+      GR_CMBX_B, 0);
+    cmb.tex |= 3;
+  }
+  else
+  {
+    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 ();
+}
+
+static void cc__t0_mul_shadea_add_env__mul_shade_add_prim ()
+{
+  if (cmb.combine_ext)
+  {
+    T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X,
+      GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_ZERO,
+      GR_CMBX_ITALPHA, 0,
+      GR_CMBX_B, 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_ZERO,
+      GR_CMBX_ITRGB, 0,
+      GR_CMBX_B, 0);
+    CC_PRIM ();
+  }
+  else
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+      GR_COMBINE_FACTOR_TEXTURE_RGB,
+      GR_COMBINE_LOCAL_CONSTANT,
+      GR_COMBINE_OTHER_ITERATED);
+    MULSHADE_SHADEA ();
+    CC_PRIM ();
+    USE_T0 ();
+  }
+}
+
+static void cc__t0_mul_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_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 ();
+}
+
+static void cc__t0_inter_t1_using_enva__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 ();
+  wxUint8 factor = (wxUint8)(rdp.env_color&0xFF);
+  T0_INTER_T1_USING_FACTOR (factor);
+}
+
+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 ();
+  wxUint8 factor = (wxUint8)(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 ();
+}
+
+static void cc__t0_mul_primlod__add__prim_mul_shade ()
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+    GR_COMBINE_FACTOR_TEXTURE_RGB,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_CONSTANT);
+  MULSHADE_PRIM ();
+  CC_PRIMLOD ();
+  USE_T0 ();
+}
+
+//Added by Gonetz
+static void cc_t0_mul_primlod_add_prim_mul_shade_add_env ()
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+    GR_COMBINE_FACTOR_TEXTURE_RGB,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_CONSTANT);
+  MULSHADE_PRIM ();
+  ADDSHADE_ENV ();
+  CC_PRIMLOD ();
+  USE_T0 ();
+}
+
+//Added by Gonetz
+static void cc_t1_mul_primlod_add_prim_mul_shade_add_env ()
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+    GR_COMBINE_FACTOR_TEXTURE_RGB,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_CONSTANT);
+  MULSHADE_PRIM ();
+  ADDSHADE_ENV ();
+  CC_PRIMLOD ();
+  USE_T1 ();
+}
+
+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);
+}
+
+static void cc__t1_inter_t0_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 ();
+  T1_INTER_T0_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 ();
+}
+
+static void cc_t0_mul_scale_add_prim ()
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+    GR_COMBINE_FACTOR_TEXTURE_RGB,
+    GR_COMBINE_LOCAL_CONSTANT,
+    GR_COMBINE_OTHER_ITERATED);
+  SETSHADE (rdp.SCALE);
+  CC_PRIM ();
+  USE_T0 ();
+}
+
+//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_scale__mul_env_sub_center_add_prim ()
+{
+  // (t1-0)*scale+t0, (env-center)*cmb+prim
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+    GR_COMBINE_FACTOR_TEXTURE_RGB,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_CONSTANT);
+  CC_C1SUBC2(rdp.env_color, rdp.CENTER);
+  SETSHADE_PRIM ();
+  MOD_1 (TMOD_TEX_MUL_COL);
+  MOD_1_COL (rdp.SCALE & 0xFFFFFF00);
+  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__t0_mul_enva_add_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 ();
+  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_t0_mul_shade_add_prima ()
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+    GR_COMBINE_FACTOR_TEXTURE_RGB,
+    GR_COMBINE_LOCAL_CONSTANT,
+    GR_COMBINE_OTHER_ITERATED);
+  CC_PRIMA ();
+  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_prim__mul_shade_add_t0 ()
+{
+  if (cmb.combine_ext)
+  {
+    CCMBEXT(GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_X,
+      GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X,
+      GR_CMBX_ITRGB, 0,
+      GR_CMBX_B, 0);
+    CC_PRIM ();
+  }
+  else
+  {
+    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_add_prim__mul_shade_add_t1 ()
+{
+  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_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_ZERO,
+      GR_CMBX_ITRGB, 0,
+      GR_CMBX_B, 0);
+    CC_PRIM ();
+  }
+  else
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+      GR_COMBINE_FACTOR_ONE,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+    MULSHADE_PRIM ();
+    T0_ADD_T1 ();
+  }
+}
+
+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);
+    wxUint32 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_t0 ()
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+    GR_COMBINE_FACTOR_ONE,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_TEXTURE);
+  MULSHADE_PRIM ();
+  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_t1__mul_prim_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_PRIM ();
+  T0_MUL_T1 ();
+}
+
+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);
+  CC_COLMULBYTE (rdp.prim_color, rdp.prim_lodfrac);
+  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_t1_mul__one_sub_prim_mul_shade_add_prim ()
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_LOCAL,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_TEXTURE);
+  MULSHADE_1MPRIM ();
+  ADDSHADE_PRIM ();
+  USE_T1 ();
+}
+
+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_scale_mul_shade ()
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_LOCAL,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_TEXTURE);
+  MULSHADE (rdp.SCALE);
+  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__t0_mul_prim_add_shade__mul_env ()
+{
+  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 |= 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_ZERO, 0);
+    CC_ENV ();
+  }
+  else
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+      GR_COMBINE_FACTOR_ONE,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+    MULSHADE_ENV ();
+    MOD_0 (TMOD_TEX_MUL_COL);
+    CC_PRIMMULENV ();
+    MOD_0_COL (cmb.ccolor & 0xFFFFFF00);
+    USE_T0 ();
+  }
+}
+
+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 ();
+}
+
+static void cc__prim_mul_shade_add_env__mul_shade () //Aded by Gonetz
+{
+  if (!cmb.combine_ext)
+  {
+    cc_prim_mul_shade_add_env ();
+    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_ZERO, 0);
+  cmb.tex |= 1;
+  cmb.tex_ccolor = rdp.prim_color;
+  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_ENV ();
+}
+
+// ** A*B*C+D*E **
+//Added by Gonetz
+static void cc__t0_sub_t1__mul_prim_mul_shade_add_prim_mul_env ()
+{
+  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_ZERO, 1,
+      GR_CMBX_ZERO, 0);
+    cmb.tex |= 3;
+  }
+  else
+  {
+    USE_T0 ();
+  }
+
+  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 ();
+}
+
+static void cc__t0_mul_prim_mul_env__add__prim_mul_shade ()
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+    GR_COMBINE_FACTOR_TEXTURE_RGB,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_CONSTANT);
+  CC_PRIMMULENV ();
+  MULSHADE_PRIM ();
+  USE_T0 ();
+}
+
+static void cc__t1_mul_prim_mul_env__add__prim_mul_shade ()
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+    GR_COMBINE_FACTOR_TEXTURE_RGB,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_CONSTANT);
+  CC_PRIMMULENV ();
+  MULSHADE_PRIM ();
+  USE_T1 ();
+}
+
+//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 ();
+  wxUint8 fac = 255 - (wxUint8)(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 ( ((wxUint8)(col[0]*fac))<<24 | ((wxUint8)(col[1]*fac))<<16 | ((wxUint8)(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_mul_scale_add_prim__mul_shade () //Aded by Gonetz
+{
+  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 |= 1;
+    cmb.tex_ccolor = rdp.SCALE;
+    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,
+      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_t1_add_prim__mul_shade () //Aded by Gonetz
+{
+  if (cmb.combine_ext)
+  {
+    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,
+      GR_COMBINE_FACTOR_LOCAL,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+    MULSHADE_PRIM ();
+  }
+  T0_MUL_T1 ();
+}
+
+static void cc_t0_mul__prim_add_env ()
+{
+  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_t0_mul__prim_mul_primlod_add_env () //Aded by Gonetz
+{
+  // forest behind window, Dobutsu no Mori.
+  // (prim-0)*prim_lod+env, (t1-0)*cmb+0
+  //actually, the game uses t0 instead of t1 here. t1 does not set at all this moment.
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_LOCAL,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_TEXTURE);
+  float prim_lod = rdp.prim_lodfrac / 65025.0f;
+  rdp.col[0] *= ((rdp.prim_color & 0xFF000000) >> 24) * prim_lod;
+  rdp.col[1] *= ((rdp.prim_color & 0x00FF0000) >> 16) * prim_lod;
+  rdp.col[2] *= ((rdp.prim_color & 0x0000FF00) >> 8) * prim_lod;
+  rdp.cmb_flags = CMB_SET;
+  ADDSHADE_ENV ();
+  USE_T0 ();
+}
+
+// ** (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_prim_mul_shadea ()  //Aded by Gonetz
+{
+  // * not guaranteed to work if another iterated alpha is set
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL,
+    GR_COMBINE_FACTOR_LOCAL_ALPHA,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_TEXTURE);
+  SETSHADE_PRIM ();
+  USE_T0 ();
+}
+
+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_prim_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_PRIM ();
+  }
+  else
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+      GR_COMBINE_FACTOR_LOCAL,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+    if (rdp.prim_color & 0xFFFFFF00)
+    {
+      MOD_0 (TMOD_TEX_SUB_COL);
+      MOD_0_COL (rdp.prim_color & 0xFFFFFF00);
+    }
+  }
+  USE_T0 ();
+}
+
+static void cc__t0_mul_t1__sub_prim_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_PRIM ();
+  }
+  else
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+      GR_COMBINE_FACTOR_LOCAL,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+  }
+  T0_MUL_T1 ();
+}
+
+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__t0_mul_prima_add_t0__sub_center_mul_scale ()
+{
+  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_B, 0);
+    wxUint32 prima = rdp.prim_color&0xFF;
+    cmb.tex_ccolor = (prima<<24)|(prima<<16)|(prima<<8)|prima;
+    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(rdp.CENTER);
+    SETSHADE(rdp.SCALE);
+  }
+  else
+  {
+    cc_t0_mul_prima();
+  }
+}
+
+static void cc__t1_inter_t0_using_primlod__sub_shade_mul_prim ()
+{
+  if (cmb.combine_ext)
+  {
+    CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X,
+      GR_CMBX_ITRGB, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_CONSTANT_COLOR, 0,
+      GR_CMBX_ZERO, 0);
+    CC_PRIM ();
+  }
+  else
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL,
+      GR_COMBINE_FACTOR_ONE,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+    MULSHADE_PRIM ();
+  }
+  T1_INTER_T0_USING_FACTOR (lod_frac);
+}
+
+static void cc__t0_inter_t1_using_enva__sub_shade_mul_prim ()
+{
+  if (cmb.combine_ext)
+  {
+    CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X,
+      GR_CMBX_ITRGB, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_CONSTANT_COLOR, 0,
+      GR_CMBX_ZERO, 0);
+    CC_PRIM ();
+  }
+  else
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL,
+      GR_COMBINE_FACTOR_ONE,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+    MULSHADE_PRIM ();
+  }
+  wxUint8 factor = (wxUint8)(rdp.env_color&0xFF);
+  T0_INTER_T1_USING_FACTOR (factor);
+}
+
+static void cc_t0_sub_shade_mul_shadea ()  //Aded by Gonetz
+{
+  // * not guaranteed to work if another iterated alpha is set
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL,
+    GR_COMBINE_FACTOR_LOCAL_ALPHA,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_TEXTURE);
+  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_one_sub_prim_mul_prima () //Added by Gonetz
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_LOCAL,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_CONSTANT);
+  CC (~rdp.prim_color);
+  SETSHADE_PRIMA ();
+}
+
+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_shade_sub_env_mul_prim () //Aded by Gonetz
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_LOCAL,
+    GR_COMBINE_LOCAL_CONSTANT,
+    GR_COMBINE_OTHER_ITERATED);
+  CC_PRIM();
+  SUBSHADE_ENV ();
+}
+
+static void cc_shade_sub__prim_mul_prima () //Aded by Gonetz
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL,
+    GR_COMBINE_FACTOR_ONE,
+    GR_COMBINE_LOCAL_CONSTANT,
+    GR_COMBINE_OTHER_ITERATED);
+  CC_C1MULC2 (rdp.prim_color, (rdp.prim_color&0xFF));
+}
+
+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__t0_mul_shadea__mul_shade () //Aded by Gonetz
+{
+  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_ITALPHA, 0,
+      GR_CMBX_ZERO, 0);
+    cmb.tex |= 1;
+
+    CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_ONE_MINUS_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);
+    USE_T0 ();
+    cmb.tmu0_invert = TRUE;
+  }
+}
+
+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_prim () //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 ();
+  SETSHADE_PRIM ();
+}
+
+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);
+    cmb.tex |= 3;
+    CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X,
+      GR_CMBX_ITRGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_ZERO, 1,
+      GR_CMBX_ZERO, 0);
+    MULSHADE_PRIM ();
+  }
+  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_t1_add_shade ()  //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_TMU_CCOLOR, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_OTHER_TEXTURE_RGB, 0,
+      GR_CMBX_ZERO, 0);
+    cmb.tex |= 3;
+    cmb.tex_ccolor = rdp.prim_color;
+    CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X,
+      GR_CMBX_ITRGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_ZERO, 1,
+      GR_CMBX_B, 0);
+  }
+  else
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+      GR_COMBINE_FACTOR_ONE,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+    MOD_0 (TMOD_TEX_SUB_COL);
+    MOD_0_COL (rdp.prim_color & 0xFFFFFF00);
+    T0_MUL_T1 ();
+  }
+}
+
+static void cc_t0_sub_prim_mul_primlod_add_prim ()  //Aded by Gonetz
+{
+  if (cmb.combine_ext)
+  {
+    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);
+    SETSHADE_PRIM ();
+    CC_PRIMLOD ();
+  }
+  else
+  {
+    // * 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_1MPRIMLOD ();
+    CC_PRIMLOD ();
+  }
+  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 Gonetz41
+{
+  if (cmb.combine_ext)
+  {
+    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);
+    SETSHADE_PRIM ();
+    CC_ENVA ();
+  }
+  else
+  {
+    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.prim_color & 0xFFFFFF00);
+    MOD_0_FAC (rdp.env_color & 0xFF);
+  }
+  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
+{
+  if ( (rdp.prim_color & 0xFFFFFF00) == 0xFFFFFF00 && (rdp.env_color & 0xFFFFFF00) == 0xFFFFFF00)
+  {
+    CCMB (GR_COMBINE_FUNCTION_BLEND_LOCAL,
+      GR_COMBINE_FACTOR_TEXTURE_RGB,
+      GR_COMBINE_LOCAL_CONSTANT,
+      GR_COMBINE_OTHER_NONE);
+    CC_PRIM ();
+  }
+  else
+  {
+    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 ();
+  wxUint8 factor = (wxUint8)(rdp.env_color&0xFF);
+  T1_INTER_T0_USING_FACTOR (factor);
+}
+
+static void cc_t0_sub_prim_mul_shade_add_env ()
+{
+  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_CONSTANT_COLOR, GR_FUNC_MODE_ZERO,
+      GR_CMBX_ITRGB, 0,
+      GR_CMBX_B, 0);
+    CC_ENV ();
+  }
+  else
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+      GR_COMBINE_FACTOR_TEXTURE_RGB,
+      GR_COMBINE_LOCAL_CONSTANT,
+      GR_COMBINE_OTHER_ITERATED);
+    CC_ENV ();
+    MOD_0 (TMOD_TEX_SUB_COL);
+    MOD_0_COL (rdp.prim_color & 0xFFFFFF00);
+    USE_T0 ();
+  }
+}
+
+static void cc_t1_sub_prim_mul_shade_add_env ()
+{
+  if (cmb.combine_ext)
+  {
+    T1CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X,
+      GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_ZERO, 1,
+      GR_CMBX_ZERO, 0);
+    T0CCMBEXT(GR_CMBX_OTHER_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 |= 2;
+    cmb.tex_ccolor = rdp.prim_color;
+    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_ENV ();
+  }
+  else
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+      GR_COMBINE_FACTOR_TEXTURE_RGB,
+      GR_COMBINE_LOCAL_CONSTANT,
+      GR_COMBINE_OTHER_ITERATED);
+    CC_ENV ();
+    MOD_1 (TMOD_TEX_SUB_COL);
+    MOD_1_COL (rdp.prim_color & 0xFFFFFF00);
+    USE_T1 ();
+  }
+}
+
+static void cc_t1_sub_k4_mul_prima_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, 1,
+      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 |= 3;
+    CC_BYTE (rdp.K4);
+    cmb.tex_ccolor = cmb.ccolor;
+    percent = (float)(rdp.prim_color&0xFF) / 255.0f;
+    cmb.dc0_detailmax = cmb.dc1_detailmax = percent;
+    CCMBEXT(GR_CMBX_TEXTURE_ALPHA, GR_FUNC_MODE_X,
+      GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_CONSTANT_COLOR, 0,
+      GR_CMBX_B, 0);
+  }
+  else
+  {
+    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_sub_prim_mul_shade_add_env__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 |= 1;
+    cmb.tex_ccolor = rdp.prim_color;
+    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_ENV ();
+  }
+  else
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+      GR_COMBINE_FACTOR_TEXTURE_RGB,
+      GR_COMBINE_LOCAL_CONSTANT,
+      GR_COMBINE_OTHER_ITERATED);
+    CC_ENV ();
+    MOD_0 (TMOD_TEX_SUB_COL);
+    MOD_0_COL (rdp.prim_color & 0xFFFFFF00);
+    USE_T0 ();
+  }
+}
+
+static void cc__t0_sub_prim_mul_shade_add_env__mul_shadea ()
+{
+  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 |= 1;
+    cmb.tex_ccolor = rdp.prim_color;
+    CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X,
+      GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_X,
+      GR_CMBX_ITALPHA, 0,
+      GR_CMBX_ZERO, 0);
+    CC_ENV ();
+  }
+  else
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+      GR_COMBINE_FACTOR_TEXTURE_RGB,
+      GR_COMBINE_LOCAL_CONSTANT,
+      GR_COMBINE_OTHER_ITERATED);
+    MULSHADE_SHADEA();
+    CC_ENV ();
+    MOD_0 (TMOD_TEX_SUB_COL);
+    MOD_0_COL (rdp.prim_color & 0xFFFFFF00);
+    USE_T0 ();
+  }
+}
+
+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_sub_k4_mul_k5_add_t0 ()  //Aded by Gonetz
+{
+  if (cmb.combine_ext)
+  {
+    CCMBEXT(GR_CMBX_ITRGB, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X,
+      GR_CMBX_CONSTANT_COLOR, 0,
+      GR_CMBX_B, 0);
+    wxUint32 temp = rdp.prim_lodfrac;
+    rdp.prim_lodfrac = rdp.K4;
+    SETSHADE_PRIMLOD ();
+    rdp.prim_lodfrac = temp;
+    CC_K5 ();
+    USE_T0 ();
+  }
+  else
+  {
+    cc_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();
+    T0_INTER_T1_USING_T0 ();
+  }
+  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 ();
+    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_prima_add_env ()  //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_DETAIL_FACTOR, 0,
+      GR_CMBX_B, 0);
+    cmb.tex |= 1;
+    percent = (rdp.prim_color&0xFF) / 255.0f;
+    cmb.dc0_detailmax = cmb.dc1_detailmax = percent;
+  }
+  else
+  {
+    MOD_0 (TMOD_COL_INTER_TEX_USING_COL1);
+    MOD_0_COL (rdp.env_color & 0xFFFFFF00);
+    wxUint32 prima = rdp.prim_color & 0xFF;
+    MOD_0_COL1 ((prima<<24)|(prima|16)|(prima<<8));
+    USE_T0 ();
+  }
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_ONE,
+    GR_COMBINE_LOCAL_NONE,
+    GR_COMBINE_OTHER_TEXTURE);
+}
+
+static void cc_t0_sub_env_mul_k5_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&0xFFFFFF00) | rdp.K5;
+  USE_T0 ();
+}
+
+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 ();
+  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.env_color;
+  }
+  else
+  {
+    MOD_0 (TMOD_TEX_SUB_COL);
+    MOD_0_COL (rdp.env_color & 0xFFFFFF00);
+    USE_T0 ();
+  }
+}
+
+static void cc__t0_sub_t1_mul_enva_add_shade__sub_env_mul_prim ()
+// (t0-t1)*env_a+shade, (cmb-env)*prim+0
+{
+  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_TMU_CCOLOR, 0,
+      GR_CMBX_ITRGB, 0);
+    cmb.tex |= 3;
+    CC_COLMULBYTE(rdp.prim_color, (rdp.env_color&0xFF));
+    cmb.tex_ccolor = cmb.ccolor;
+    CCMBEXT(GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_ITRGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_ZERO, 1,
+      GR_CMBX_TEXTURE_RGB, 0);
+    MULSHADE_PRIM ();
+    CC_PRIMMULENV ();
+  }
+  else
+  {
+    cc_t0_sub_env_mul_prim_add_shade();
+  }
+}
+
+static void cc__t0_inter_t1_using_primlod__sub_env_mul_shade_add_prim ()  //Aded by Gonetz
+{
+  if (!(rdp.env_color&0xFFFFFF00))
+  {
+    cc__t0_inter_t1_using_primlod__mul_shade_add_prim ();
+    return;
+  }
+  if (!(rdp.prim_color&0xFFFFFF00))
+  {
+    if (!cmb.combine_ext)
+    {
+      cc_t0_sub_env_mul_shade ();
+      return;
+    }
+    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 ();
+    T0_INTER_T1_USING_FACTOR (lod_frac);
+    return;
+  }
+  cc__t0_inter_t1_using_primlod__mul_shade_add_prim ();
+}
+
+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_sub_env_mul_shade_add_prim__mul_shadea ()  //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_ZERO,
+    GR_CMBX_ITRGB, 0,
+    GR_CMBX_B, 0);
+  cmb.tex_ccolor = rdp.prim_color;
+  cmb.tex |= 1;
+  MOD_0 (TMOD_TEX_SUB_COL);
+  MOD_0_COL (rdp.env_color & 0xFFFFFF00);
+
+  CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X,
+    GR_CMBX_ITRGB, GR_FUNC_MODE_ZERO,
+    GR_CMBX_ITALPHA, 0,
+    GR_CMBX_ZERO, 0);
+}
+
+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 ();
+  wxUint8 factor = (wxUint8)(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_t0a_add_prim ()
+{
+  if (cmb.combine_ext)
+  {
+    CCMBEXT(GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_ONE_MINUS_X,
+      GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_ZERO,
+      GR_CMBX_TEXTURE_ALPHA, 0,
+      GR_CMBX_B, 0);
+    CC_PRIM ();
+  } else {
+    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);
+    MOD_0_COL (rdp.prim_color & 0xFFFFFF00);
+    MOD_0_COL1 (0xFFFFFF00);
+  }
+  USE_T0 ();
+}
+
+static void cc_one_sub_prim_mul__t0_inter_t1_using_primlod__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 ();
+  T0_INTER_T1_USING_FACTOR (lod_frac);
+}
+
+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_shade_mul__t0_inter_t1_using_primlod__add_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);
+  T0_INTER_T1_USING_FACTOR (lod_frac);
+}
+
+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_t0_sub_prim_mul_shade_add_shade ()  //Aded by Gonetz
+{
+  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_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);
+    if (rdp.prim_color & 0xFFFFFF00)
+    {
+      MOD_0 (TMOD_TEX_SUB_COL);
+      MOD_0_COL (rdp.prim_color & 0xFFFFFF00);
+    }
+  }
+  USE_T0 ();
+}
+
+static void cc__t0_mul_t0__sub_prim_mul_shade_add_shade ()  //Aded by Gonetz
+{
+  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_LOCAL_TEXTURE_RGB, 0,
+      GR_CMBX_ZERO, 0);
+    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_sub_prim_mul_shade_add_shade();
+}
+
+static void cc__t0_mul_t1__sub_prim_mul_shade_add_shade ()  //Aded by Gonetz
+{
+  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_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_MUL_T1 ();
+}
+
+static void cc__t0_mul_t1__sub_env_mul_shade_add_shade ()  //Aded by Gonetz
+{
+  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_ITRGB, 0);
+    CC_ENV ();
+  }
+  else
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+      GR_COMBINE_FACTOR_LOCAL,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+  }
+  T0_MUL_T1 ();
+}
+
+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 ()
+{
+  //(env-t0)*env_a+t0
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_ONE,
+    GR_COMBINE_LOCAL_NONE,
+    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_ccolor = rdp.env_color;
+    cmb.tex |= 1;
+  }
+  else
+  {
+    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 = RDP::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 = RDP::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_mul_t1__add__prim_mul_shade ()
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+    GR_COMBINE_FACTOR_TEXTURE_RGB,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_CONSTANT);
+  CC_1SUBPRIM ();
+  MULSHADE_PRIM ();
+  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 ();
+  wxUint8 factor = (wxUint8)(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 ();
+  CC_C1MULC2 (rdp.prim_color, cmb.ccolor);
+}
+
+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 ();
+  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__t0_mul_t1_add_env__mul_shadea_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_TMU_CCOLOR, GR_FUNC_MODE_ZERO,
+      GR_CMBX_LOCAL_TEXTURE_RGB, 0,
+      GR_CMBX_B, 0);
+    cmb.tex_ccolor = rdp.env_color;
+    cmb.tex |= 3;
+  }
+  else
+  {
+    T0_MUL_T1 ();
+  }
+  // * not guaranteed to work if another iterated alpha is set
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+    GR_COMBINE_FACTOR_LOCAL_ALPHA,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_TEXTURE);
+}
+
+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_t0_mul_t1_add_t0 ()  //Aded by Gonetz
+{
+  if (!cmb.combine_ext)
+  {
+    cc_t0_mul_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_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X,
+    GR_CMBX_OTHER_TEXTURE_RGB, 0,
+    GR_CMBX_B, 0);
+  cmb.tex_ccolor = rdp.prim_color;
+  cmb.tex |= 3;
+  CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_ZERO,
+    GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_ZERO,
+    GR_CMBX_ZERO, 0,
+    GR_CMBX_B, 0);
+}
+
+static void cc_env_sub_t0_mul_prim_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_1SUBPRIM ();
+  SETSHADE_PRIM ();
+  SETSHADE_ENV ();
+  USE_T0 ();
+  //(env-t0)*prim+t0 == prim*env + t0*(1-prim)
+}
+
+static void cc_env_sub_t0_mul_shade_add_t0 ()  //Aded by Gonetz
+{
+  if (!cmb.combine_ext)
+  {
+    cc_t0_mul_shade ();
+    return;
+  }
+  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 ();
+  USE_T0 ();
+}
+
+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_add_env__add_primlod ()
+{
+  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_ZERO,
+    GR_CMBX_ITRGB, 0,
+    GR_CMBX_B, 0);
+  cmb.tex_ccolor = rdp.env_color;
+  cmb.tex |= 1;
+  SETSHADE_PRIMSUBENV ();
+  CCMBEXT(GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_X,
+    GR_CMBX_ITRGB, GR_FUNC_MODE_ZERO,
+    GR_CMBX_ZERO, 1,
+    GR_CMBX_TEXTURE_RGB, 0);
+  CC_PRIMLOD ();
+}
+
+static void cc__prim_sub_env_mul_t0_add_env__add_shadea ()
+{
+  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_ZERO,
+    GR_CMBX_ITRGB, 0,
+    GR_CMBX_B, 0);
+  cmb.tex_ccolor = rdp.env_color;
+  cmb.tex |= 1;
+  SETSHADE_PRIMSUBENV ();
+  CCMBEXT(GR_CMBX_ITALPHA, GR_FUNC_MODE_X,
+    GR_CMBX_ITRGB, GR_FUNC_MODE_ZERO,
+    GR_CMBX_ZERO, 1,
+    GR_CMBX_TEXTURE_RGB, 0);
+}
+
+static void cc_prim_sub_env_mul__t0_mul_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 ();
+  T0_MUL_T1A ();
+}
+
+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__one_sub_t0_mul_primlod_add_prim__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)
+  {
+    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;
+    cmb.dc0_detailmax = cmb.dc1_detailmax = (float)lod_frac / 255.0f;
+  }
+  else
+  {
+    USE_T0 ();
+  }
+}
+
+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 ()
+{
+  //(t1-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__t1_sub_prim_mul_prima_add_t0__add_env ()
+{
+  // (t1-prim)*prim_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)
+  {
+    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_DETAIL_FACTOR, 0,
+      GR_CMBX_B, 0);
+    cmb.tex_ccolor = rdp.prim_color;
+    cmb.tex |= 3;
+    cmb.dc0_detailmax = cmb.dc1_detailmax = (float)(rdp.prim_color&0xFF) / 255.0f;
+  }
+  else
+  {
+    MOD_1 (TMOD_TEX_SUB_COL_MUL_FAC);
+    MOD_1_COL (rdp.prim_color & 0xFFFFFF00);
+    MOD_1_FAC (rdp.prim_color & 0xFF);
+    T0_ADD_T1 ();
+  }
+}
+
+static void cc__prim_sub_env_mul_t0_add_env__mul_primlod ()
+{
+  CCMB (GR_COMBINE_FUNCTION_BLEND,
+    GR_COMBINE_FACTOR_TEXTURE_RGB,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_CONSTANT);
+  float factor = (float)rdp.prim_lodfrac / 255.0f;
+  wxUint8 r = (wxUint8)((rdp.prim_color >> 24) & 0xFF);
+  r = (wxUint8)((float)r * factor);
+  wxUint8 g = (wxUint8)((rdp.prim_color >> 16) & 0xFF);
+  g = (wxUint8)((float)g * factor);
+  wxUint8 b = (wxUint8)((rdp.prim_color >>  8) & 0xFF);
+  b = (wxUint8)((float)b * factor);
+  CC ((r<<24) | (g<<16) | (b<<8));
+  SETSHADE_ENV ();
+  MULSHADE_PRIMLOD ();
+  USE_T0 ();
+}
+
+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;
+  wxUint8 r = (wxUint8)((rdp.prim_color >> 24) & 0xFF);
+  r = (wxUint8)((float)r * factor);
+  wxUint8 g = (wxUint8)((rdp.prim_color >> 16) & 0xFF);
+  g = (wxUint8)((float)g * factor);
+  wxUint8 b = (wxUint8)((rdp.prim_color >>  8) & 0xFF);
+  b = (wxUint8)((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 ();
+  if (rdp.cycle_mode == 0 || ((settings.hacks&hack_KI) && (rdp.cycle2 & 0x0FFFFFFF) == 0x01FF1FFF))
+  {
+    USE_T0 ();
+  }
+  else
+  {
+    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 ();
+}
+
+static void cc_prim_sub_env_mul_t0a_add_t0 ()
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_ONE,
+    GR_COMBINE_LOCAL_NONE,
+    GR_COMBINE_OTHER_TEXTURE);
+  CC_PRIMSUBENV ();
+  if (cmb.combine_ext)
+  {
+    T0CCMBEXT(GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_X,
+      GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_LOCAL_TEXTURE_ALPHA, 0,
+      GR_CMBX_B, 0);
+    cmb.tex_ccolor = cmb.ccolor;
+    cmb.tex |= 1;
+  }
+  else
+  {
+    MOD_0 (TMOD_COL_MUL_TEXA_ADD_TEX);
+    MOD_0_COL (cmb.ccolor & 0xFFFFFF00);
+    USE_T0 ();
+  }
+}
+
+//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 ();
+  SETSHADE_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
+  {
+    SETSHADE_PRIMSUBENV ();
+    MULSHADE_SHADEA ();
+    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;
+  }
+  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);
+  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)
+  {
+    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 ();
+  }
+  else
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+      GR_COMBINE_FACTOR_ONE,
+      GR_COMBINE_LOCAL_NONE,
+      GR_COMBINE_OTHER_TEXTURE);
+    T0_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 ();
+  wxUint8 factor = (wxUint8)(rdp.env_color&0xFF);
+  T0_INTER_T1_USING_FACTOR (factor);
+  A_T0_INTER_T1_USING_FACTOR (factor);
+}
+
+//Added by Gonetz
+static void cc__env_inter_prim_using_t0__sub_shade_mul_t0a_add_shade ()
+{
+  if (!cmb.combine_ext)
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL,
+      GR_COMBINE_FACTOR_TEXTURE_ALPHA,
+      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 ();
+    A_USE_T0 ();
+  }
+  else
+  {
+    T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X,
+      GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_ZERO,
+      GR_CMBX_DETAIL_FACTOR, 0,
+      GR_CMBX_B, 0);
+    CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X,
+      GR_CMBX_ITRGB, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_TEXTURE_ALPHA, 0,
+      GR_CMBX_B, 0);
+    cmb.tex_ccolor = rdp.env_color;
+    cmb.tex |= 1;
+    wxUint32 pse = (rdp.prim_color>>24) - (rdp.env_color>>24);
+    percent = (float)(pse) / 255.0f;
+    cmb.dc0_detailmax = cmb.dc1_detailmax = percent;
+  }
+}
+
+//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 ()
+{
+  if (rdp.prim_color != 0x000000ff)
+  {
+    if (cmb.combine_ext)
+    {
+      CCMBEXT(GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_X,
+        GR_CMBX_ITRGB, GR_FUNC_MODE_NEGATIVE_X,
+        GR_CMBX_CONSTANT_ALPHA, 0,
+        GR_CMBX_TEXTURE_RGB, 0);
+      CC_PRIM ();
+      SETSHADE_ENV ();
+    }
+    else
+    {
+      CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+        GR_COMBINE_FACTOR_ONE,
+        GR_COMBINE_LOCAL_ITERATED,
+        GR_COMBINE_OTHER_TEXTURE);
+      SETSHADE_PRIMSUBENV ();
+      SETSHADE_PRIMA ();
+    }
+  }
+  else if ((rdp.prim_color&0xFFFFFF00) - (rdp.env_color&0xFFFFFF00) == 0)
+  {
+    cc_t0 ();
+    return;
+  }
+  else
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL,
+      GR_COMBINE_FACTOR_ONE,
+      GR_COMBINE_LOCAL_CONSTANT,
+      GR_COMBINE_OTHER_TEXTURE);
+    CC_ENV ();
+  }
+  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 ();
+  wxUint8 factor = (wxUint8)(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 ();
+  wxUint8 factor = (wxUint8)(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 ();
+  wxUint8 factor = (wxUint8)(rdp.env_color&0xFF);
+  T0_INTER_T1_USING_FACTOR (factor);
+}
+
+static void cc_prim_sub_center_mul__t0_inter_t1_using_enva__add_env ()
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+    GR_COMBINE_FACTOR_TEXTURE_RGB,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_CONSTANT);
+  CC_C1SUBC2 (rdp.prim_color, rdp.CENTER);
+  SETSHADE_ENV ();
+  wxUint8 factor = (wxUint8)(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 ();
+  wxUint8 factor = (wxUint8)(rdp.env_color&0xFF);
+  T1_INTER_T0_USING_FACTOR (factor);
+}
+
+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();
+  CC_COLMULBYTE(cmb.ccolor, rdp.prim_lodfrac);
+  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_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__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 ()
+{
+  if (cmb.combine_ext)
+  {
+    CCMBEXT(GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_X,
+      GR_CMBX_ITRGB, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_CONSTANT_COLOR, 0,
+      GR_CMBX_B, 0);
+    SETSHADE_ENV();
+    CC_PRIM ();
+  }
+  else
+  {
+    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 ();
+  }
+}
+
+static void cc_prim_sub_env_mul_primlod_add_env ()
+{
+  if (cmb.combine_ext)
+  {
+    T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_ZERO,
+      GR_CMBX_ZERO, 0,
+      GR_CMBX_B, 0);
+    cmb.tex |= 1;
+    CC_PRIMLOD ();
+    cmb.tex_ccolor = cmb.ccolor;
+    CCMBEXT(GR_CMBX_ITRGB, GR_FUNC_MODE_X,
+      GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_TEXTURE_RGB, 0,
+      GR_CMBX_B, 0);
+    SETSHADE_PRIM();
+    CC_ENV ();
+  }
+  else
+  {
+    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 ();
+  }
+}
+
+//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);
+  SETSHADE_PRIMSUBENV ();
+  SETSHADE_ENVA ();
+  USE_T0 ();
+}
+
+static void cc_prim_sub_env_mul_enva_add_env ()
+{
+  if (cmb.combine_ext)
+  {
+    T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_ZERO,
+      GR_CMBX_ZERO, 0,
+      GR_CMBX_B, 0);
+    cmb.tex |= 1;
+    CC_ENVA ();
+    cmb.tex_ccolor = cmb.ccolor;
+    CCMBEXT(GR_CMBX_ITRGB, GR_FUNC_MODE_X,
+      GR_CMBX_CONSTANT_COLOR, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_TEXTURE_RGB, 0,
+      GR_CMBX_B, 0);
+    SETSHADE_PRIM();
+    CC_ENV ();
+  }
+  else
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+      GR_COMBINE_FACTOR_ONE,
+      GR_COMBINE_LOCAL_CONSTANT,
+      GR_COMBINE_OTHER_ITERATED);
+    SETSHADE_PRIMSUBENV ();
+    SETSHADE_ENVA ();
+    CC_ENV ();
+  }
+}
+
+//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__t0a_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 ();
+  T0A_MUL_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 ();
+  wxUint8 factor = (wxUint8)(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__t0a_mul_t1a__add_prim ()
+{
+  CCMB (GR_COMBINE_FUNCTION_BLEND,
+    GR_COMBINE_FACTOR_TEXTURE_ALPHA,
+    GR_COMBINE_LOCAL_CONSTANT,
+    GR_COMBINE_OTHER_ITERATED);
+  CC_PRIM ();
+  SETSHADE_ENV ();
+  A_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__t0_sub_env_mul_shade__sub_prim_mul_shade_add_prim ()
+{
+  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_B, 0);
+    CC_PRIM ();
+  }
+  else
+  {
+    cc_t0_mul_shade ();
+  }
+}
+
+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 ();
+  SETSHADE_ENVSUBPRIM ();
+  MULSHADE_SHADEA ();
+}
+
+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 ();
+  wxUint8 factor = (wxUint8)(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 ()
+{
+  //  cc_prim_mul_shade();
+  //  return;
+  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_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_t0_add_shade__mul_prim ()
+{
+  if (cmb.combine_ext)
+  {
+    T0CCMBEXT(GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_X,
+      GR_CMBX_ITRGB, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_LOCAL_TEXTURE_RGB, 0,
+      GR_CMBX_B, 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_ZERO, 0);
+    CC_PRIM() ;
+  }
+  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 ();
+    MULSHADE_PRIM ();
+    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;
+}
+
+//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__t0_mul_shade_mul_shadea__add__t1_mul_one_sub_shadea ()
+{
+  // (t0-0)*shade+0, (cmb-t0)*shadea+t0
+  if (cmb.combine_ext)
+  {
+    T1CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X,
+      GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_ITALPHA, 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_ITRGB, 0,
+      GR_CMBX_B, 0);
+    MULSHADE_SHADEA ();
+    cmb.tex |= 3;
+    CCMBEXT(GR_CMBX_ITRGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_ITALPHA, GR_FUNC_MODE_ZERO,
+      GR_CMBX_ZERO, 0,
+      GR_CMBX_TEXTURE_RGB, 0);
+  }
+  else
+  {
+    cc_t0_mul_shade ();
+  }
+}
+
+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 ();
+}
+
+//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 ();
+  wxUint32 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);
+  wxUint8 factor = (wxUint8)(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);
+  wxUint8 factor = (wxUint8)(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);
+  wxUint8 factor = (wxUint8)(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;
+}
+
+//Added by Gonetz
+static void cc_t0_inter_t1_using_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_ITRGB, 0,
+      GR_CMBX_B, 0);
+    cmb.tex |= 3;
+    CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X,
+      GR_CMBX_ITRGB, 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);
+    T0_INTER_T1_USING_FACTOR (0x7F);
+  }
+}
+
+//Added by Gonetz
+static void cc_t1_inter_t0_using_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_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);
+    cmb.tex |= 3;
+    CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X,
+      GR_CMBX_ITRGB, 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);
+    T0_INTER_T1_USING_FACTOR (0x7F);
+  }
+}
+
+//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_t0a ()
+{
+  if (cmb.combine_ext)
+  {
+    CCMBEXT(GR_CMBX_ITRGB, GR_FUNC_MODE_X,
+      GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_TEXTURE_ALPHA, 0,
+      GR_CMBX_B, 0);
+    USE_T0();
+    A_USE_T0();
+  }
+  else
+  {
+    //(shade-t0)*t0a+t0 = t0*(1-t0a)+shade*t0a
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+      GR_COMBINE_FACTOR_ONE,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+    rdp.best_tex = 1;
+    cmb.tex = 1;
+    cmb.tmu0_func = GR_COMBINE_FUNCTION_BLEND_LOCAL;
+    cmb.tmu0_fac = GR_COMBINE_FACTOR_LOCAL_ALPHA;
+  }
+}
+
+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_t0_using_shadea__mul_shade ()
+{
+  //((t0-env)*shadea+env)*shade
+  if (!cmb.combine_ext)
+  {
+    cc_t0_mul_shade ();
+    return;
+  }
+  T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X,
+    GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_NEGATIVE_X,
+    GR_CMBX_ITALPHA, 0,
+    GR_CMBX_B, 0);
+  cmb.tex_ccolor = rdp.env_color;
+  cmb.tex |= 1;
+  CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X,
+    GR_CMBX_ZERO, GR_FUNC_MODE_ZERO,
+    GR_CMBX_ITRGB, 0,
+    GR_CMBX_ZERO, 0);
+}
+
+//Added by Gonetz
+static void cc_env_inter_prim_using_primlod ()
+{
+  if (rdp.prim_color&0xFFFFFF00)
+  {
+    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 ();
+  }
+  else
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL,
+      GR_COMBINE_FACTOR_ONE,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_CONSTANT);
+    SETSHADE_ENV ();
+    SETSHADE_PRIMLOD ();
+    CC_ENV ();
+  }
+}
+
+static void cc_prim_inter__t0_mul_t1_add_env__using_shadea ()
+{
+  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_ZERO,
+      GR_CMBX_LOCAL_TEXTURE_RGB, 0,
+      GR_CMBX_B, 0);
+    cmb.tex_ccolor = rdp.env_color;
+    cmb.tex |= 3;
+  }
+  else
+  {
+    T0_MUL_T1 ();
+  }
+  // * 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_PRIM ();
+}
+
+static void cc_env_inter__prim_inter_shade_using_t0__using_shadea ()
+{
+  if (!cmb.combine_ext)
+  {
+    cc_shade_sub_prim_mul_t0_add_prim ();
+    return;
+  }
+  T0CCMBEXT(GR_CMBX_ITRGB, GR_FUNC_MODE_X,
+    GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_NEGATIVE_X,
+    GR_CMBX_LOCAL_TEXTURE_RGB, 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_ITALPHA, 0,
+    GR_CMBX_B, 0);
+  CC_ENV ();
+}
+
+static void cc_shade_inter__prim_inter_shade_using_t0__using_shadea ()
+{
+  if (!cmb.combine_ext)
+  {
+    cc_shade_sub_prim_mul_t0_add_prim ();
+    return;
+  }
+  T0CCMBEXT(GR_CMBX_ITRGB, GR_FUNC_MODE_X,
+    GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_NEGATIVE_X,
+    GR_CMBX_LOCAL_TEXTURE_RGB, 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_ITRGB, GR_FUNC_MODE_NEGATIVE_X,
+    GR_CMBX_ITALPHA, 0,
+    GR_CMBX_B, 0);
+}
+
+// ** (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-B)*C+D)*E **
+static void cc_t0_sub_env_mul_prim_mul_shade_add_prim_mul_shade () //Aded by Gonetz
+{
+  //(t0-env)*shade+shade, (cmb-0)*prim+0
+  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_ITRGB, GR_FUNC_MODE_X,
+      GR_CMBX_CONSTANT_COLOR, 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);
+    if (rdp.env_color & 0xFFFFFF00)
+    {
+      MOD_0 (TMOD_TEX_SUB_COL);
+      MOD_0_COL (rdp.env_color & 0xFFFFFF00);
+    }
+    MULSHADE_PRIM ();
+    USE_T0 ();
+  }
+}
+
+static void cc__t1_sub_prim_mul_t0_add_env__mul_shade () //Aded by Gonetz
+{
+  // (t1-prim)*t0+env, (cmb-0)*shade+0
+  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;
+    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_ENV ();
+  }
+  else
+  {
+    CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+      GR_COMBINE_FACTOR_LOCAL,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+    if (rdp.prim_color & 0xFFFFFF00)
+    {
+      MOD_1 (TMOD_TEX_SUB_COL);
+      MOD_1_COL (rdp.prim_color & 0xFFFFFF00);
+    }
+    T0_MUL_T1 ();
+  }
+}
+
+// ** (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);
+  wxUint8 factor = (wxUint8)(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);
+  wxUint8 factor = (wxUint8)(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);
+  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);
+  wxUint8 factor = (wxUint8)(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);
+  wxUint8 factor = (wxUint8)(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);
+  wxUint8 factor = (wxUint8)(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 ();
+  wxUint8 factor = (wxUint8)(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 ();
+  wxUint8 factor = (wxUint8)(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__one_sub_shade_mul_t0_add_shade__mul_prim ()
+{
+  if (cmb.combine_ext)
+  {
+    T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_ITRGB, GR_FUNC_MODE_ONE_MINUS_X,
+      GR_CMBX_LOCAL_TEXTURE_RGB, 0,
+      GR_CMBX_B, 0);
+    cmb.tex |= 1;
+    CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X,
+         GR_CMBX_ZERO, 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_MINUS_LOCAL,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+    USE_T0 ();
+  }
+}
+
+static void cc__one_sub_shade_mul_t0_add_shade__mul_env ()
+{
+  if (cmb.combine_ext)
+  {
+    T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_ITRGB, GR_FUNC_MODE_ONE_MINUS_X,
+      GR_CMBX_LOCAL_TEXTURE_RGB, 0,
+      GR_CMBX_B, 0);
+    cmb.tex |= 1;
+    CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X,
+         GR_CMBX_ZERO, GR_FUNC_MODE_ZERO,
+         GR_CMBX_CONSTANT_COLOR, 0,
+      GR_CMBX_ZERO, 0);
+       CC_ENV ();
+  }
+  else
+  {
+    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__t1_inter_t0_using_prim__mul_shade ()
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_LOCAL,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_TEXTURE);
+  T1_INTER_T0_USING_PRIM ();
+}
+
+static void cc__t0_inter_t1_using_primlod__mul_shade ()
+{
+  //*
+  if (rdp.LOD_en && (rdp.mipmap_level == 0) && !(settings.hacks&hack_Fifa98))
+  {
+    cc_t0_mul_shade ();
+    return;
+  }
+  //*/
+  if (settings.ucode == 7)
+    lod_frac = rdp.prim_lodfrac;
+  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 ();
+    return;
+  }
+  //(prim-env)*t0+env, (shade-0)*cmb+0
+  MOD_0 (TMOD_COL_INTER_COL1_USING_TEX);
+  MOD_0_COL (rdp.env_color & 0xFFFFFF00);
+  MOD_0_COL1 (rdp.prim_color & 0xFFFFFF00);
+  USE_T0 ();
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_LOCAL,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_TEXTURE);
+}
+
+static void cc__env_inter_one_using_t0__mul_shade ()
+{
+  //(one-env)*t0+env, (cmb-0)*shade+0
+  if (cmb.combine_ext)
+  {
+    T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_ONE_MINUS_X,
+      GR_CMBX_LOCAL_TEXTURE_RGB, 0,
+      GR_CMBX_B, 0);
+    cmb.tex_ccolor = rdp.env_color&0xFFFFFF00;
+    cmb.tex |= 1;
+  }
+  else
+  {
+    MOD_0 (TMOD_COL_INTER_COL1_USING_TEX);
+    MOD_0_COL (rdp.env_color & 0xFFFFFF00);
+    MOD_0_COL1 (0xFFFFFF00);
+    USE_T0 ();
+  }
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_LOCAL,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_TEXTURE);
+}
+
+static void cc_env_inter_one_using__one_sub_t0_mul_primlod ()
+{
+  if (cmb.combine_ext)
+  {
+    // (noise-t0)*primlod+0, (1-env)*cmb+env
+    T0CCMBEXT(GR_CMBX_TMU_CCOLOR, 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_ccolor = rand()&0xFFFFFF00;
+    cmb.tex |= 1;
+    percent = (float)(lod_frac) / 255.0f;
+    cmb.dc0_detailmax = cmb.dc1_detailmax = percent;
+    cmb.tex |= 1;
+  }
+  else
+  {
+    USE_T0 ();
+  }
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+    GR_COMBINE_FACTOR_ONE_MINUS_LOCAL,
+    GR_COMBINE_LOCAL_CONSTANT,
+    GR_COMBINE_OTHER_TEXTURE);
+  CC_ENV ();
+}
+
+static void cc__env_inter_prim_using_prima__mul_shade ()
+{
+  int primr = (rdp.prim_color>>24)&0xFF;
+  int primg = (rdp.prim_color>>16)&0xFF;
+  int primb = (rdp.prim_color>>8)&0xFF;
+  int prima = rdp.prim_color&0xFF;
+  int envr = (rdp.env_color>>24)&0xFF;
+  int envg = (rdp.env_color>>16)&0xFF;
+  int envb = (rdp.env_color>>8)&0xFF;
+  int r = (((primr-envr)*prima)/256)+envr;
+  int g = (((primg-envg)*prima)/256)+envg;
+  int b = (((primb-envb)*prima)/256)+envb;
+  cmb.ccolor = (r<<24) | (g<<16) | (b<<8);
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_LOCAL,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_CONSTANT);
+}
+
+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 ();
+  }
+  else 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.env_color & 0xFFFFFF00;
+    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);
+    wxUint32 onesubenv = ~rdp.env_color;
+    CC_C1MULC2(rdp.prim_color, onesubenv);
+  }
+  else
+  {
+    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__one_inter_prim_using_t1__mul_shade ()
+{
+  if (cmb.combine_ext)
+  {
+    if ((settings.hacks&hack_BAR) && rdp.cur_tile == 1)
+    {
+      T0CCMBEXT(GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_X,
+        GR_CMBX_TMU_CALPHA, GR_FUNC_MODE_NEGATIVE_X,
+        GR_CMBX_LOCAL_TEXTURE_RGB, 0,
+        GR_CMBX_ZERO, 1);
+      cmb.tex |= 1;
+    }
+    else
+    {
+      T1CCMBEXT(GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_X,
+        GR_CMBX_TMU_CALPHA, GR_FUNC_MODE_NEGATIVE_X,
+        GR_CMBX_LOCAL_TEXTURE_RGB, 0,
+        GR_CMBX_ZERO, 1);
+      T0CCMBEXT(GR_CMBX_OTHER_TEXTURE_RGB, GR_FUNC_MODE_ZERO,
+        GR_CMBX_OTHER_TEXTURE_RGB, GR_FUNC_MODE_ZERO,
+        GR_CMBX_ZERO, 0,
+        GR_CMBX_B, 0);
+      cmb.tex |= 2;
+    }
+    cmb.tex_ccolor = rdp.prim_color | 0xFF;
+    CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X,
+      GR_CMBX_ITRGB, 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);
+    if ((settings.hacks&hack_BAR) && rdp.cur_tile == 1)
+    {
+      MOD_0 (TMOD_COL_INTER_COL1_USING_TEX);
+      MOD_0_COL (0xFFFFFF00);
+      MOD_0_COL1 (rdp.prim_color & 0xFFFFFF00);
+      USE_T0 ();
+    }
+    else
+    {
+      MOD_1 (TMOD_COL_INTER_COL1_USING_TEX);
+      MOD_1_COL (0xFFFFFF00);
+      MOD_1_COL1 (rdp.prim_color & 0xFFFFFF00);
+      USE_T1 ();
+    }
+  }
+}
+
+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);
+    wxUint8 prima = (wxUint8)(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__prim_inter_one_using_env__mul_shade ()
+{
+  // (one-prim)*env+prim, (cmb-0)*shade+0
+  if ((rdp.prim_color&0xFFFFFF00) == 0)
+  {
+    cc_env_mul_shade ();
+    return;
+  }
+  if ((rdp.env_color&0xFFFFFF00) == 0)
+  {
+    cc_prim_mul_shade ();
+    return;
+  }
+  if ((rdp.prim_color&0xFFFFFF00) == 0xFFFFFF00 || (rdp.env_color&0xFFFFFF00) == 0xFFFFFF00)
+  {
+    cc_shade ();
+    return;
+  }
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_LOCAL,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_CONSTANT);
+  CC_1SUBPRIM ();
+  CC_C1MULC2 (cmb.ccolor, rdp.env_color);
+  cmb.ccolor=(wxUint8)( min(255, (int)((cmb.ccolor & 0xFF000000) >> 24) + (int)((rdp.prim_color & 0xFF000000) >> 24)) ) << 24 |
+  (wxUint8)( min(255, (int)((cmb.ccolor & 0x00FF0000) >> 16) + (int)((rdp.prim_color & 0x00FF0000) >> 16)) ) << 16 |
+  (wxUint8)( min(255, (int)((cmb.ccolor & 0x0000FF00) >>  8) + (int)((rdp.prim_color & 0x0000FF00) >>  8)) ) <<  8 ;
+}
+
+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_t0a__mul_prim ()
+{
+  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_TEXA);
+  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_TMU_CCOLOR, GR_FUNC_MODE_ZERO,
+      GR_CMBX_DETAIL_FACTOR, 0,
+      GR_CMBX_B, 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_MINUS_LOCAL_ADD_LOCAL,
+      GR_COMBINE_FACTOR_TEXTURE_RGB,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_CONSTANT);
+    CC_PRIM ();
+    SETSHADE_ENV ();
+  }
+  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__env_inter_t0_using_prima__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_COL1);
+  MOD_0_COL (rdp.env_color & 0xFFFFFF00);
+  wxUint32 prima = rdp.prim_color & 0xFF;
+  MOD_0_COL1 ((prima<<24)|(prima|16)|(prima<<8));
+  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 **
+  wxUint32 enva  = rdp.env_color&0xFF;
+  if (enva == 0xFF)
+    cc_env ();
+  else if (enva == 0)
+    cc_t0_mul_shade ();
+  else if (cmb.combine_ext)
+  {
+    T0CCMBEXT(GR_CMBX_LOCAL_TEXTURE_RGB, GR_FUNC_MODE_X,
+      GR_CMBX_TMU_CCOLOR, GR_FUNC_MODE_ZERO,
+      GR_CMBX_ITRGB, 0,
+      GR_CMBX_B, 0);
+    cmb.tex |= 1;
+    CCMBEXT(GR_CMBX_TEXTURE_RGB, GR_FUNC_MODE_X,
+      GR_CMBX_ITRGB, GR_FUNC_MODE_ZERO,
+      GR_CMBX_ZERO, 1,
+      GR_CMBX_ZERO, 0);
+    MULSHADE_1MENVA ();
+    CC_COLMULBYTE(rdp.env_color, (rdp.env_color&0xFF));
+    cmb.tex_ccolor = cmb.ccolor;
+  }
+  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_enva ()
+{
+  CCMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+    GR_COMBINE_FACTOR_TEXTURE_RGB,
+    GR_COMBINE_LOCAL_CONSTANT,
+    GR_COMBINE_OTHER_ITERATED);
+  CC_ENVA ();
+  MULSHADE_1MENVA ();
+  USE_T0 ();
+}
+
+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 cc__prim_mul_shade__inter_env_using_enva ()
+{
+  CCMB (GR_COMBINE_FUNCTION_BLEND,
+    GR_COMBINE_FACTOR_LOCAL_ALPHA,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_CONSTANT);
+  CC_ENV ();
+  MULSHADE_PRIM ();
+  SETSHADE_A_ENV ();
+}
+
+static void cc__prim_mul_shade__inter_env_using__prim_mul_shade_alpha ()
+{
+  CCMB (GR_COMBINE_FUNCTION_BLEND,
+    GR_COMBINE_FACTOR_LOCAL_ALPHA,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_CONSTANT);
+  CC_ENV ();
+  MULSHADE_PRIM ();
+  MULSHADE_A_PRIM ();
+}
+
+
+//****************************************************************
+
+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 ()
+{
+  if ((rdp.othermode_l & 0x4000) && (rdp.cycle_mode < 2))
+  {
+    wxUint32 blend_mode = (rdp.othermode_l >> 16);
+    if (blend_mode == 0x0550)
+    {
+      ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+        GR_COMBINE_FACTOR_LOCAL,
+        GR_COMBINE_LOCAL_CONSTANT,
+        GR_COMBINE_OTHER_TEXTURE);
+      CA(rdp.fog_color);
+    }
+    else if (blend_mode == 0x55f0) //cmem*afog + cfog*1ma
+    {
+      ACMB (GR_COMBINE_FUNCTION_LOCAL,
+        GR_COMBINE_FACTOR_ONE,
+        GR_COMBINE_LOCAL_CONSTANT,
+        GR_COMBINE_OTHER_NONE);
+      CA(~rdp.fog_color);
+    }
+    else
+    {
+      ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+        GR_COMBINE_FACTOR_ONE,
+        GR_COMBINE_LOCAL_NONE,
+        GR_COMBINE_OTHER_TEXTURE);
+    }
+  }
+  else
+  {
+    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.hacks&hack_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_t0 ()
+{
+    ACMB (GR_COMBINE_FUNCTION_BLEND_LOCAL,
+      GR_COMBINE_FACTOR_TEXTURE_ALPHA,
+      GR_COMBINE_LOCAL_CONSTANT,
+      GR_COMBINE_OTHER_NONE);
+    CA (0xFF);
+    A_USE_T0 ();
+}
+
+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 if ((rdp.prim_color&0xFF) == 0xFF)
+  {
+    ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+      GR_COMBINE_FACTOR_ONE,
+      GR_COMBINE_LOCAL_NONE,
+      GR_COMBINE_OTHER_TEXTURE);
+    A_T1_MUL_PRIMLOD_ADD_T0();
+  }
+  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
+{
+  ACMB (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
+{
+  ACMB (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_t1 ()
+{
+  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_ZERO,
+      GR_CMBX_OTHER_TEXTURE_ALPHA, GR_FUNC_MODE_X,
+      GR_CMBX_LOCAL_TEXTURE_ALPHA, 0,
+      GR_CMBX_B, 0);
+    cmb.tex |= 3;
+  }
+  else
+  {
+    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 ();
+  if (rdp.cycle_mode == 0)
+    A_USE_T0 ();
+  else
+    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
+  {
+    wxUint8 factor = (wxUint8)(rdp.env_color&0xFF);
+    A_T0_INTER_T1_USING_FACTOR (factor);
+  }
+}
+
+static void ac__t1_sub_t0_mul_primlod__mul_env_add_prim ()
+{
+  ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+    GR_COMBINE_FACTOR_ONE,
+    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_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_TMU_CALPHA, 0,
+      GR_CMBX_ZERO, 0);
+    cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (wxUint32)((float)(rdp.env_color&0xFF)*(float)rdp.prim_lodfrac/255.0f);
+  }
+  else
+  {
+    cmb.tmu1_a_func = GR_COMBINE_FUNCTION_LOCAL;
+    cmb.tmu0_a_func = GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL;
+    cmb.tmu0_a_fac = GR_COMBINE_FACTOR_DETAIL_FACTOR;
+    percent = (rdp.prim_lodfrac * (rdp.env_color&0xFF)) / 65025.0f;
+    cmb.dc0_detailmax = cmb.dc1_detailmax = percent; \
+  }
+  cmb.tex |= 3;
+}
+
+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 ();
+  //  if ((settings.hacks&hack_Powerpuff) && (rdp.last_tile == 0))
+  if (rdp.cycle_mode == 0)
+    A_USE_T0 ();
+  else
+    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__t0_mul_primlod_add_t0__mul_shade ()
+{
+  ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_LOCAL,
+    GR_COMBINE_LOCAL_ITERATED,
+    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 ();
+  }
+}
+
+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_t0_mul_prim_add_t0 ()
+{
+  if (cmb.combine_ext)
+  {
+    ACMBEXT(GR_CMBX_TEXTURE_ALPHA, GR_FUNC_MODE_X,
+      GR_CMBX_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO,
+      GR_CMBX_CONSTANT_ALPHA, 0,
+      GR_CMBX_B, 0);
+    CA_PRIM ();
+    A_USE_T0 ();
+  }
+  else
+    ac_t0();
+}
+
+static void ac_t1_mul_prim_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 ();
+}
+
+static void ac__t0_inter_t1_using_t1a__mul_prim_add__t0_inter_t1_using_t1a ()
+{
+  if (cmb.combine_ext)
+  {
+    ACMBEXT(GR_CMBX_TEXTURE_ALPHA, GR_FUNC_MODE_X,
+      GR_CMBX_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO,
+      GR_CMBX_CONSTANT_ALPHA, 0,
+      GR_CMBX_B, 0);
+    CA_PRIM ();
+  }
+  else
+  {
+    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 ();
+}
+
+static void ac__t1_inter_t0_using_t0a__mul_prim_add__t1_inter_t0_using_t0a ()
+{
+  if (cmb.combine_ext)
+  {
+    ACMBEXT(GR_CMBX_TEXTURE_ALPHA, GR_FUNC_MODE_X,
+      GR_CMBX_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO,
+      GR_CMBX_CONSTANT_ALPHA, 0,
+      GR_CMBX_B, 0);
+    CA_PRIM ();
+  }
+  else
+  {
+    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 ();
+}
+
+//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 ();
+  wxUint8 factor = (wxUint8)(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 ();
+}
+
+static void ac_t0_mul_primlod_add_env ()
+{
+  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_ENV ();
+  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 ();
+}
+
+static void ac_one_sub_prim_mul__t0_mul_t1__add__prim_mul_shade ()
+{
+  ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+    GR_COMBINE_FACTOR_TEXTURE_ALPHA,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_CONSTANT);
+  CA_INVPRIM ();
+  MULSHADE_A_PRIM ();
+  A_T0_MUL_T1 ();
+}
+
+// ** 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)*D **
+static void ac__t0_mul_primlod_add_shade__mul_shade ()
+{
+  if (cmb.combine_ext)
+  {
+    T0ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_X,
+      GR_CMBX_ITALPHA, GR_FUNC_MODE_ZERO,
+      GR_CMBX_DETAIL_FACTOR, 0,
+      GR_CMBX_B, 0);
+    cmb.tex |= 1;
+    percent = (float)lod_frac / 255.0f;
+    cmb.dc0_detailmax = cmb.dc1_detailmax = percent;
+    ACMBEXT(GR_CMBX_TEXTURE_ALPHA, GR_FUNC_MODE_X,
+      GR_CMBX_ZERO, GR_FUNC_MODE_ZERO,
+      GR_CMBX_ITALPHA, 0,
+      GR_CMBX_ZERO, 0);
+  }
+  else
+  {
+    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_primlod_add_shade__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_B, 0);
+    T0ACMBEXT(GR_CMBX_OTHER_TEXTURE_ALPHA, GR_FUNC_MODE_X,
+      GR_CMBX_ITALPHA, GR_FUNC_MODE_ZERO,
+      GR_CMBX_DETAIL_FACTOR, 0,
+      GR_CMBX_B, 0);
+    cmb.tex |= 2;
+    percent = (float)lod_frac / 255.0f;
+    cmb.dc0_detailmax = cmb.dc1_detailmax = percent;
+    ACMBEXT(GR_CMBX_TEXTURE_ALPHA, GR_FUNC_MODE_X,
+      GR_CMBX_ZERO, GR_FUNC_MODE_ZERO,
+      GR_CMBX_ITALPHA, 0,
+      GR_CMBX_ZERO, 0);
+  }
+  else
+  {
+    ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+      GR_COMBINE_FACTOR_LOCAL,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+    A_USE_T1 ();
+  }
+}
+
+// ** ((A-B)*C+D)+E **
+static void ac__t0_sub_t1_mul_prim_add_shade__mul_shade ()
+ //(t0-t1)*prim+shade, (cmb-0)*shade+0
+{
+  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_TMU_CALPHA, 0,
+      GR_CMBX_ZERO, 0);
+    cmb.tex |= 3;
+    cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (rdp.prim_color&0xFF);
+    ACMBEXT(GR_CMBX_TEXTURE_ALPHA, GR_FUNC_MODE_X,
+      GR_CMBX_ITALPHA, GR_FUNC_MODE_X,
+      GR_CMBX_ITALPHA, 0,
+      GR_CMBX_ZERO, 0);
+  }
+  else
+  {
+    ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA,
+      GR_COMBINE_FACTOR_TEXTURE_ALPHA,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_CONSTANT);
+    CA_PRIM ();
+    A_T1_SUB_T0 ();
+  }
+}
+
+static void ac__t1_sub_t0_mul_prim_add_shade__mul_shade ()
+ //(t1-t0)*prim+shade, (cmb-0)*shade+0
+{
+  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_OTHER_TEXTURE_ALPHA, GR_FUNC_MODE_X,
+      GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_TMU_CALPHA, 0,
+      GR_CMBX_ZERO, 0);
+    cmb.tex |= 3;
+    cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (rdp.prim_color&0xFF);
+    ACMBEXT(GR_CMBX_TEXTURE_ALPHA, GR_FUNC_MODE_X,
+      GR_CMBX_ITALPHA, GR_FUNC_MODE_X,
+      GR_CMBX_ITALPHA, 0,
+      GR_CMBX_ZERO, 0);
+  }
+  else
+  {
+    ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA,
+      GR_COMBINE_FACTOR_TEXTURE_ALPHA,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_CONSTANT);
+    CA_PRIM ();
+    A_T1_SUB_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 ();
+  if (voodoo.sup_large_tex || rdp.tiles[1].lr_s < 256) //hack for RR64 pause screen
+  {
+    A_T0_MUL_T1 ();
+  }
+  else
+  {
+    A_USE_T0 ();
+  }
+}
+
+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 ();
+}
+
+static void ac__t0_add_prim_mul_shade__mul_shade ()
+{
+  // (shade-0)*prim+t0, (cmb-0)*shade+0
+  if (cmb.combine_ext)
+  {
+    T0ACMBEXT(GR_CMBX_ITALPHA, GR_FUNC_MODE_X,
+      GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO,
+      GR_CMBX_TMU_CALPHA, 0,
+      GR_CMBX_B, 0);
+    cmb.tex |= 1;
+    cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (rdp.prim_color&0xFF);
+    ACMBEXT(GR_CMBX_TEXTURE_ALPHA, GR_FUNC_MODE_X,
+      GR_CMBX_ZERO, GR_FUNC_MODE_ZERO,
+      GR_CMBX_ITALPHA, 0,
+      GR_CMBX_ZERO, 0);
+  }
+  else
+  {
+    ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+      GR_COMBINE_FACTOR_ONE,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+    MULSHADE_A_PRIM ();
+    A_USE_T0();
+  }
+}
+
+//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 ();
+  SETSHADE_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 |= (wxUint32)(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 ()
+{
+  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_ZERO, 0);
+    cmb.tex |= 1;
+    cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (rdp.prim_color&0xFF);
+    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_MINUS_LOCAL,
+      GR_COMBINE_FACTOR_ONE,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+    MULSHADE_A_PRIM ();
+    A_USE_T0 ();
+  }
+}
+
+static void ac_t0_sub_prim_mul_shade_mul_env ()
+{
+  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_ZERO, 0);
+    cmb.tex |= 1;
+    cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (rdp.prim_color&0xFF);
+    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);
+    CA_ENV ();
+  } else {
+    ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL,
+      GR_COMBINE_FACTOR_ONE,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+    MULSHADE_A_PRIM ();
+    MULSHADE_A_ENV ();
+    A_USE_T0 ();
+  }
+}
+
+static void ac_t0_sub_shade_mul_prim ()
+{
+  if (cmb.combine_ext)
+  {
+    T0ACMBEXT(GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_X,
+      GR_CMBX_ITALPHA, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_TMU_CALPHA, 0,
+      GR_CMBX_ZERO, 0);
+    cmb.tex |= 1;
+    cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (rdp.prim_color&0xFF);
+    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_MINUS_LOCAL,
+      GR_COMBINE_FACTOR_ONE,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+    MULSHADE_A_PRIM ();
+    A_USE_T0 ();
+  }
+}
+
+static void ac__t0_mul_t1__sub_prim_mul_shade ()  //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_PRIM();
+  }
+  else
+  {
+    ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+      GR_COMBINE_FACTOR_LOCAL,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+  }
+  A_T0_MUL_T1 ();
+}
+
+static void ac__one_sub_t1_mul_t0_add_shade__sub_prim_mul_shade ()  //Aded by Gonetz
+{
+  // (1-t1)*t0+shade, (cmb-prim)*shade+0
+  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_OTHER_TEXTURE_ALPHA, GR_FUNC_MODE_ONE_MINUS_X,
+      GR_CMBX_ITALPHA, GR_FUNC_MODE_ZERO,
+      GR_CMBX_LOCAL_TEXTURE_ALPHA, 0,
+      GR_CMBX_B, 0);
+    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_PRIM();
+  }
+  else
+  {
+    ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+      GR_COMBINE_FACTOR_LOCAL,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+    A_T0_MUL_T1 ();
+  }
+}
+
+static void ac__t1_mul_primlod_add_t0__sub_prim_mul_shade ()
+{
+  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_PRIM ();
+  }
+  else
+  {
+    ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+      GR_COMBINE_FACTOR_LOCAL,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+  }
+  A_T1_MUL_PRIMLOD_ADD_T0 ();
+}
+
+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__t1_mul_prima_add_t0__sub_env_mul_shade ()  //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 ();
+  }
+  else
+  {
+    ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+      GR_COMBINE_FACTOR_LOCAL,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+  }
+  A_T1_MUL_PRIMA_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.aTBuffTex[0] || rdp.aTBuffTex[1])
+  {
+    ACMB (GR_COMBINE_FUNCTION_BLEND_LOCAL,
+      GR_COMBINE_FACTOR_TEXTURE_ALPHA,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_NONE);
+    A_USE_T0 ();
+  }
+  else
+    ac_zero();
+}
+
+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_one_sub_shade_mul_env ()  //Aded by Gonetz
+{
+  ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_ONE_MINUS_LOCAL,
+    GR_COMBINE_LOCAL_ITERATED,
+    GR_COMBINE_OTHER_CONSTANT);
+  CA_ENV ();
+}
+
+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_prim_sub_shade_mul_prim ()  //Aded by Gonetz
+{
+  if (cmb.combine_ext)
+  {
+    ACMBEXT(GR_CMBX_CONSTANT_ALPHA, GR_FUNC_MODE_X,
+      GR_CMBX_ITALPHA, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_CONSTANT_ALPHA, 0,
+      GR_CMBX_ZERO, 0);
+    CA_PRIM();
+  }
+  else
+  {
+    if (!(rdp.prim_color & 0xFF))
+    {
+      ac_zero();
+    }
+    else
+    {
+      ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL,
+        GR_COMBINE_FACTOR_ONE,
+        GR_COMBINE_LOCAL_ITERATED,
+        GR_COMBINE_OTHER_CONSTANT);
+      CA_PRIM();
+    }
+  }
+}
+
+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_one_plus_env_mul_prim_mul_shade ()
+{
+  if (cmb.combine_ext)
+  {
+    ACMBEXT(GR_CMBX_ZERO, GR_FUNC_MODE_ONE_MINUS_X,
+      GR_CMBX_CONSTANT_ALPHA, GR_FUNC_MODE_X,
+      GR_CMBX_ITALPHA, 0,
+      GR_CMBX_ZERO, 0);
+    MULSHADE_A_PRIM ();
+    CA_ENV();
+  }
+  else
+    ac_prim_mul_shade ();
+}
+
+// ** (A-B)*C+A **
+static void ac__t0_mul_t1__sub_env_mul_prim_add__t0_mul_t1 ()  //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_TEXTURE_ALPHA, 0);
+    CA_ENV();
+    SETSHADE_A_PRIM ();
+  }
+  else
+  {
+    ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+      GR_COMBINE_FACTOR_ONE,
+      GR_COMBINE_LOCAL_NONE,
+      GR_COMBINE_OTHER_TEXTURE);
+  }
+  A_T0_MUL_T1 ();
+}
+
+// ** (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_t1_mul_env_add_env ()  //Aded by Gonetz
+{
+    ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+      GR_COMBINE_FACTOR_LOCAL,
+      GR_COMBINE_LOCAL_CONSTANT,
+      GR_COMBINE_OTHER_TEXTURE);
+    CA_ENV();
+    A_T0_SUB_T1 ();
+}
+
+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
+{
+  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_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;
+    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_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_t0_sub_env_mul_shadea_add_env ()  //Aded by Gonetz
+{
+  if (!cmb.combine_ext)
+  {
+    ac_t0_mul_shade ();
+    return;
+  }
+  T0ACMBEXT(GR_CMBX_LOCAL_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 |= 1;
+  ACMBEXT(GR_CMBX_TEXTURE_ALPHA, GR_FUNC_MODE_X,
+    GR_CMBX_CONSTANT_ALPHA, GR_FUNC_MODE_NEGATIVE_X,
+    GR_CMBX_ITALPHA, 0,
+    GR_CMBX_B, 0);
+  CA_ENV ();
+}
+
+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 ();
+}
+
+static void ac_prim_sub_env_mul_t0_add_one ()
+{
+  ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+    GR_COMBINE_FACTOR_TEXTURE_ALPHA,
+    GR_COMBINE_LOCAL_CONSTANT,
+    GR_COMBINE_OTHER_ITERATED);
+  CA (0xFF);
+  SETSHADE_A_PRIMSUBENV ();
+  A_USE_T0 ();
+}
+
+//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_one_sub_t1_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_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_X,
+      GR_CMBX_OTHER_TEXTURE_ALPHA, GR_FUNC_MODE_ZERO,
+      GR_CMBX_TMU_CALPHA, 0,
+      GR_CMBX_B, 1);
+    cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (rdp.env_color&0xFF);
+    cmb.tex |= 3;
+    ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+      GR_COMBINE_FACTOR_ONE,
+      GR_COMBINE_LOCAL_NONE,
+      GR_COMBINE_OTHER_TEXTURE);
+  }
+  else
+  {
+    ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER,
+      GR_COMBINE_FACTOR_LOCAL,
+      GR_COMBINE_LOCAL_CONSTANT,
+      GR_COMBINE_OTHER_TEXTURE);
+    CA_ENV ();
+    A_T0_ADD_T1();
+    cmb.tmu1_a_invert = FXTRUE;
+  }
+}
+
+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 ();
+}
+
+static void ac_shade_sub_t0_mul_primlod_add_prim ()
+{
+  if (cmb.combine_ext)
+  {
+    T0ACMBEXT(GR_CMBX_ITALPHA, GR_FUNC_MODE_X,
+      GR_CMBX_LOCAL_TEXTURE_ALPHA, GR_FUNC_MODE_NEGATIVE_X,
+      GR_CMBX_TMU_CALPHA, 0,
+      GR_CMBX_ZERO, 0);
+    cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (lod_frac&0xFF);
+    cmb.tex |= 1;
+    ACMBEXT(GR_CMBX_CONSTANT_ALPHA, GR_FUNC_MODE_X,
+      GR_CMBX_ITALPHA, GR_FUNC_MODE_ZERO,
+      GR_CMBX_ZERO, 1,
+      GR_CMBX_TEXTURE_ALPHA, 0);
+    CA_PRIM ();
+  }
+  else
+    ac_t0();
+}
+
+static void ac_shade_sub_env_mul_t0_add_prim ()
+{
+  ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
+    GR_COMBINE_FACTOR_TEXTURE_ALPHA,
+    GR_COMBINE_LOCAL_CONSTANT,
+    GR_COMBINE_OTHER_ITERATED);
+  SUBSHADE_A_ENV ();
+  CA_PRIM ();
+  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);
+  wxUint8 factor = (wxUint8)(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);
+  wxUint8 factor = (wxUint8)(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);
+  wxUint8 factor = (wxUint8)(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);
+  wxUint8 factor = (wxUint8)(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 ()
+{
+  if (settings.hacks & hack_Makers)
+  {
+    //rolling rock issue - it has zero shade alpha and thus rejected by alpha compare
+    ac_t0_inter_t1_using_primlod();
+    return;
+  }
+  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 ();
+  wxUint8 factor = (wxUint8)(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_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_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 ();
+  wxUint8 factor = (wxUint8)(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);
+  wxUint8 factor = (wxUint8)(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);
+  wxUint8 factor = (wxUint8)(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 ();
+  wxUint8 factor = (wxUint8)(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
+  {
+    wxUint8 factor = (wxUint8)(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 ();
+  wxUint8 factor = (wxUint8)(rdp.env_color&0xFF);
+  A_T0_INTER_T1_USING_FACTOR (factor);
+}
+
+static void ac__t1_mul_enva_add_t0__sub_prim_mul_shade ()
+{
+  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_PRIM ();
+  }
+  else
+  {
+    ACMB (GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL,
+      GR_COMBINE_FACTOR_LOCAL,
+      GR_COMBINE_LOCAL_ITERATED,
+      GR_COMBINE_OTHER_TEXTURE);
+    MULSHADE_A_PRIM ();
+  }
+  A_T1_MUL_ENVA_ADD_T0 ();
+}
+
+//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 ();
+}
+
+static void ac__t0_inter_t1_using_t1a__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_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 ();
+}
+
+static void ac__t0_inter_t1_using_primlod__sub_env_mul_shade_add_shade ()
+{
+  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_ALOCAL, 0);
+    CA_ENV ();
+    A_T0_INTER_T1_USING_FACTOR (lod_frac);
+  }
+  else
+    ac__t0_inter_t1_using_primlod__mul_shade ();
+}
+
+//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);
+  wxUint8 factor = (wxUint8)(rdp.env_color&0xFF);
+  A_T0_INTER_T1_USING_FACTOR (factor);
+}
+
+static void ac__t0_inter_t1_using_primlod__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);
+  CA_ENV ();
+  SETSHADE_A_PRIM ();
+  A_T0_INTER_T1_USING_FACTOR (lod_frac);
+}
+
+//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__one_inter_t0_using_prim__mul_env ()
+{
+  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_DETAIL_FACTOR, 0,
+      GR_CMBX_B, 0);
+    cmb.tex_ccolor = (cmb.tex_ccolor&0xFFFFFF00) | (0xFF) ;
+    cmb.tex |= 1;
+    cmb.dc0_detailmax = cmb.dc1_detailmax = (float)(rdp.prim_color&0xFF) / 255.0f;
+    ACMBEXT(GR_CMBX_TEXTURE_ALPHA, GR_FUNC_MODE_X,
+      GR_CMBX_CONSTANT_ALPHA, GR_FUNC_MODE_ZERO,
+      GR_CMBX_CONSTANT_ALPHA, 0,
+      GR_CMBX_ZERO, 0);
+    CA_ENV ();
+  }
+  else
+  {
+       ac_t0_mul_prim_add_env ();
+  }
+}
+
+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
+  {
+    wxUint8 factor = (wxUint8)(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]
+//****************************************************************
+
+typedef void (*cmb_func)();
+typedef struct {
+  wxUint32 key;
+  cmb_func func;
+} COMBINER;
+
+static COMBINER color_cmb_list[] = {
+  // { #CCSTART }
+  // intro, Aidyn Chronicles. Added by Gonetz
+  // (0-cmb)*env+cmb, (t1-t0)*0+t0
+  {0x05083812, cc_t0},
+  //terminal, Spacestation Silicon Valley. Added by Gonetz
+  // (0-0)*0+cmb, (0-0)*0+prim
+  {0x1fff7fff, cc_prim},
+  //chip in Spacestation Silicon Valley intro. Added by Gonetz
+  // (0-0)*0+cmb, (prim-0)*shade+0
+  {0x1fffe4f3, cc_prim_mul_shade},
+  // car, beetle adventure racing. Added by Gonetz
+  // (t1-t0)*t0+t0, (cmb-shade)*prima+shade **can work incorrect**
+  {0x21128a40, cc__t0_inter_t1_using_t0__sub_shade_mul_prima_add_shade},
+  // Treasure opening, zelda
+  // (t1-prim)*t0+t0, (prim-env)*cmb+env
+  {0x2132a053, cc_prim_sub_env_mul__t1_sub_prim_mul_t0_add_t0__add_env},
+  // yellow carpet, Pokemon Stadium 2
+  // (t1-env)*t0+t0, (cmb-0)*shade+0
+  {0x2152e4f0, cc__t1_sub_env_mul_t0_add_t0__mul_shade},
+  // Water, doubut no mori
+  // (t1-0)*t0+t0, (prim-0)*shade+cmb
+  {0x21f204f3, 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, 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, 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, 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, cc_prim_sub_env_mul__t0_inter_t1_using_t1__add_env},
+  // pokemon fainted, Pokemon Stadium 2
+  // (prim-t0)*t1+t0
+  {0x22132213, cc_prim_sub_t0_mul_t1_add_t0},
+  // attack, Ogre Battle 64
+  // (1-t0)*t1+t0, (cmb-0)*prim+0
+  {0x2216e3f0, cc__t0_inter_one_using_t1__mul_prim},
+  // Some gannon spell, zelda
+  // (t1-0)*t1+t0, (prim-0)*cmb+0
+  {0x22f2e0f3, cc__t1_mul_t1_add_t0__mul_prim},
+  // battle tanks 2 [Ogy]
+  // (1-0)*t1+t0, (env-prim)*cmb+prim
+  {0x22f66035, cc_env_sub_prim_mul__t0_add_t1__add_prim},
+  // GASP Fighters
+  // (1-0)*t1+t0, (shade-0)*cmb+0
+  {0x22f6e0f4, 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, cc__t0_add_t1__mul_shade},
+  // ???, zelda
+  // (noise-0)*t1+t0, (prim-env)*cmb+env
+  {0x22f7a053, 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, cc__t0_inter_t1_using_prim__inter_env_using_enva},
+  // ground, zelda2. Added by Gonetz
+  // (t1-t0)*prim+t0, (cmb-0)*shade+0
+  {0x2312e4f0, cc__t0_inter_t1_using_prim__mul_shade},
+  // wwf rules
+  // (env-t0)*prim+t0
+  {0x23152315, cc_t0_inter_env_using_prim},
+  // Paper Mario
+  // (1-t0)*prim+t0, (1-t0)*t0+cmb ** INC **
+  {0x23160116, cc_t0_add_prim_mul_one_sub_t0_add_t0},
+  // intro, castlevania. Added by Gonetz
+  // (1-t0)*prim+t0
+  {0x23162316, cc_one_sub_t0_mul_prim_add_t0},
+  // Explosions, aerofighter's assault
+  // (1-t0)*prim+t0, (shade-0)*cmb+0
+  {0x2316e0f4, cc_t0_mul_shade},
+  //beetle adventure racing. Added by Gonetz
+  // (1-t0)*prim+t0, (cmb-0)*shade+0  **INC**
+  {0x2316e4f0, cc__t0_inter_one_using_prim__mul_shade},
+  // Unknown player background, smash bros
+  // (noise-t0)*prim+t0   ** INC **
+  //    {0x23172317, cc_t0},
+  {0x23172317, cc_t0_inter_noise_using_prim},
+  // paper mario. Added by Gonetz
+  // (noise-prim)*prim+t0   ** INC **
+  {0x23372337, cc_t0_add_prim},
+  // strange mirror in stone temple, zelda 2. Added by Gonetz
+  // (prim-env)*prim+t0, (cmb-0)*prim+0  ** INC **
+  {0x2353e3f0, 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, 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, cc__t0_add_prim_mul_shade__mul_shade},
+  // menu, Mischief Makers. Added by Gonetz
+  // (0-env)*prim+t0, (cmb-0)*shade+0
+  {0x235f235f, cc_t0_sub__prim_mul_env},
+  // Deadly Arts logo. Added by Gonetz
+  // (t0-0)*prim+t0
+  {0x23f123f1, cc_t0_mul_prim},
+  // pokemon attack, Pokemon Stadium 2. Added by Gonetz
+  // (shade-0)*prim+t0, (cmb-0)*shade+0  ** INC **
+  {0x23f4e4f0, cc_t0_mul_shade},
+  // Mischief Makers logo. Added by Gonetz
+  // (env-0)*prim+t0
+  {0x23f523f5, cc_prim_mul_env_add_t0},
+  // Taken out bomb, zelda
+  // (1-0)*prim+t0
+  {0x23f623f6, cc_t0_add_prim},
+  // waterfall,  Dobutsu_no_Mori
+  // (1-0)*prim+t0, (cmb-0)*shade+t0
+  {0x23f624f0, cc__t0_add_prim__mul_shade_add_t0},
+  // waterfall,  Dobutsu_no_Mori
+  // (1-0)*prim+t0, (cmb-0)*shade+t1
+  {0x23f644f0, cc__t0_add_prim__mul_shade_add_t1},
+  // Jabu-Jabu's Belly, zelda
+  // (noise-0)*prim+t0
+  {0x23f723f7, cc_t0_add_prim},
+  // carmagedon
+  // (0-0)*prim+t0
+  {0x23ff23ff, cc_t0},
+  // water, diddy kong racing. Added by Gonetz
+  // (t1-t0)*shade+t0, (env-cmb)*env_a+cmb **INC**
+  {0x24120c05, cc__t0_inter_t1_using_shade__inter_env_using_enva},
+  // Advertisement hoarding, Mia Soccer. Added by Gonetz
+  // (t1-t0)*shade+t0, (1-0)*cmb+0
+  {0x2412e0f6, cc_t0_inter_t1_using_shade},
+  // ground, f-zero x
+  // (prim-t0)*shade+t0 ** INC **
+  {0x24132413, 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, cc_one_sub_t0_mul_shade_add_t0},
+  // Sky, pilotwings
+  // (1-t0)*shade+t0
+  {0x24162416, cc_one_sub_t0_mul_shade_add_t0},
+  // zelda 2 [Ogy]. Added by Gonetz
+  // (prim-env)*shade+t0, (prim-prim)*shade+cmb ** INC ** ?
+  {0x24530433, cc_prim_sub_env_mul_shade_add_t0},
+  // waves, Dr. Mario
+  // (0-center)*shade+t0
+  {0x246f246f, cc_t0_sub__shade_mul_center},
+  // lums, Rayman2. Added by Gonetz
+  // (t0-0)*shade+t0  ** INC **
+  {0x24f124f1, cc_t0}, //this one works better
+  //    {0x24f124f1, cc_t0_mul_shade},
+  // Goemon, mystical ninja. Added by Gonetz
+  // (prim-0)*shade+t0
+  {0x24f324f3, cc_prim_mul_shade_add_t0},
+  // Sky, waverace
+  //z (t1-t0)*env+t0      ** INC **
+  {0x25122512, cc_t0_inter_t1_using_env},
+  // Rare logo, Jet Force. Added by Gonetz
+  // (t1-t0)*env+t0, (cmb-0)*prim+0      ** INC **
+  {0x2512e3f0, 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, cc__t0_inter_t1_using_env__mul_shade},
+  // menu, Mischief Makers. Added by Gonetz
+  //(prim-t0)*env+t0      ** INC **
+  {0x25132513, cc_one_sub_env_mul_t0_add_prim_mul_env},
+  // Battle border, quest64
+  // (1-t0)*env+t0
+  {0x25162516, cc_one_sub_env_mul_t0_add_env},
+  // Paper Mario
+  // (noise-t0)*env+t0
+  {0x25172517, 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, 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, cc_t0_mul_shade_add_prim_mul_env},
+  //    {0x2543e4f0, cc_t0_mul_shade},
+  // mystical ninja. Added by Gonetz
+  // (1-0)*env+t0
+  {0x25f625f6, cc_t0_add_env},
+  // smoke, Starshot. Added by Gonetz
+  // (1-0)*env+t0, (1-0)*cmb+0
+  {0x25f6e0f6, cc_t0_add_env},
+  // mega shock, Paper Mario. Added by Gonetz
+  // (t1-0)*scale+t0, (env-center)*cmb+prim
+  {0x26f26065, cc__t0_add__t1_mul_scale__mul_env_sub_center_add_prim},
+  // character select, Duck Dodgers. Added by Gonetz
+  // (prim-t0)*t0_alpha+t0, (cmb-0)*shade+0   **INC**
+  {0x2813e4f0, cc__t0_inter_prim_using_t0a__mul_shade},
+  // intro, Duck Dodgers. Added by Gonetz
+  // (shade-t0)*t0_alpha+t0   **INC**
+  {0x28142814, cc_t0_inter_shade_using_t0a},
+  // vermilion gym torches, Pokemon Stadium 2.
+  // (prim-env)*t0_a+t0, (cmb-cmb)*cmb+cmb
+  {0x28530000, cc_prim_sub_env_mul_t0a_add_t0},
+  // F1 World Grand Prix. Added by Gonetz
+  // (prim-0)*t0_a+t0, (cmb-0)*shade+0   ** INC **
+  {0x28f3e4f0, cc__t0a_mul_prim_add_t0__mul_shade},
+  // battle tanks 2 [Ogy]
+  // (env-0)*t0_a+t0, (cmb-0)*shade+0
+  {0x28f5e4f0, cc__t0a_mul_env_add_t0__mul_shade},
+  // blastcorps, unimp log. Added by Gonetz
+  // (t1-t0)*t1_alpha+t0
+  {0x29122912, cc_t0_inter_t1_using_t1a},
+  // paper mario. Added by Gonetz
+  // (t1-t0)*t1_alpha+t0, (cmb-env)*env_a+env
+  {0x2912ac50, 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, cc__t0_inter_t1_using_t1a__mul_shade},
+  // ??? in zelda ending, zelda
+  // (1-0)*t1_alpha+t0, (prim-env)*cmb+env
+  {0x29f6a053, cc_prim_sub_env_mul__t0_add_t1a__add_env},
+  // Sky, zelda
+  //z (t1-t0)*prim_a+t0
+  {0x2a122a12, cc_t0_inter_t1_using_prima},
+  // battle tanks [Ogy]
+  // (t1-t0)*prim_a+t0, (env-prim)*cmb+prim
+  {0x2a126035, 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, cc_prim_sub_env_mul__t0_inter_t1_using_prima__add_env},
+  // N64 BIOS
+  // (t1-t0)*prim_a+t0, (cmb-0)*shade+0
+  {0x2a12e0f4, cc__t0_inter_t1_using_prima__mul_shade},
+  // flame, Doraemon 2. Added by Gonetz
+  // (t1-t0)*prim_a+t0, (cmb-0)*prim+0
+  {0x2a12e3f0, cc__t0_inter_t1_using_prima__mul_prim},
+  // logo, PD. Added by Gonetz
+  // (t1-t0)*prim_a+t0, (cmb-0)*shade+0
+  {0x2a12e4f0, cc__t0_inter_t1_using_prima__mul_shade},
+  // Pikachu
+  // (prim-t0)*prim_a+t0, (env-cmb)*enva+cmb
+  {0x2a130c05, cc__t0_inter_prim_using_prima__inter_env_using_enva},
+  // 1080 snowboarding [Ogy] - 7/03/02 fixed by Dave2001. 15 Mar 2005 fixed by Gonetz.
+  // (prim-t0)*prim_a+t0
+  {0x2a132a13, cc_t0_inter_prim_using_prima},
+  // menu background, Paper Mario
+  // (prim-t0)*prim_a+t0, (prim-t1)*prim_a+t1
+  {0x2a134a23, cc_t0_inter_prim_using_prima},
+  //    {0x2a134a23, cc_t0},
+  // Mickey USA
+  // (prim-t0)*prim_a+t0, (cmb-0)*shade+0  ** INC **
+  {0x2a13e4f0, cc_t0_mul_shade},
+  // gunfire, Sin and Punishmen. Added by Gonetz
+  // (env-t0)*prima+t0 **INC**
+  {0x2a152a15, cc_t0_inter_env_using_prima},
+  // Mystical Ninja
+  // (0-t0)*prima+t0, (prim-env)*cmb+env ** INC **
+  {0x2a1fa053, cc_prim_sub_env_mul__t0_sub_t0_mul_prima__add_env},
+  // foresight attack, Pokemon Stadium 2.
+  // (t1-prim)*prim_a+t0, (prim-env)*cmb+env
+  {0x2a32a053, cc_prim_sub_env_mul__t1_sub_prim_mul_prima_add_t0__add_env},
+  // arena, Pokemon Stadium 2. Added by Gonetz
+  // (shade-prim)*prim_a+t0  ** INC **
+  {0x2a342a34, cc_t0_mul_shade},
+  // Torches, Paper Mario
+  // (t1-k4)*prim_a+t0, (t1-k4)*cmb_a+cmb  ** INC **
+  {0x2a720772, cc_t1_sub_k4_mul_prima_add_t0},
+  // GASP Fighters. Added by Gonetz
+  // (t0-0)*prim_a+t0, (cmb-center)*scale+0  ** INC **
+  {0x2af1e660, cc__t0_mul_prima_add_t0__sub_center_mul_scale},
+  // F1 World Grand Prix. Added by Gonetz
+  // (t1-0)*prim_a+t0, (cmb-0)*shade+env
+  {0x2af2a4f0, cc__t1_mul_prima_add_t0__mul_shade_add_env},
+  // tidal wave, Paper Mario. Added by Gonetz
+  // (prim-0)*prim_a+t0
+  {0x2af32af3, cc_prim_mul_prima_add_t0},
+  //Spacestation Silicon Valley intro. Added by Gonetz
+  // (t1-t0)*shade_alpha+t0, (prim-shade)*cmb+shade  ** INC **
+  {0x2b128043, 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, 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, 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, cc__t0_inter_t1_using_shadea__mul_shade},
+  // water, Mickey USA
+  // (t1-t0)*shade_a+t0, (cmb-0)*shade+0  ** INC **
+  {0x2b12e4f0, cc__t0_inter_t1_using_shadea__mul_shade},
+  // Extreme G. Added by Gonetz
+  // (shade-t0)*shade_alpha+t0
+  {0x2b142b14, 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, cc_t0_mul_prim_add_shade_mul_shadea_mul_prim},
+  // V8-2
+  // (env-t0)*shade_alpha+t0, (cmb-0)*shade+0  ** INC **
+  {0x2b15e4f0, cc__t0_inter_env_using_shadea__mul_shade},
+  // Earthquake pokemon attack, Pokemon Stadium 2 [gokuss4]. Added by Gonetz
+  // (t1-0)*shade_alpha+t0, (prim-env)*cmb+env ** INC **
+  {0x2bf2a053, 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, cc_prim_sub_env_mul_t0a_add_env},
+  // paper mario. Added by Gonetz
+  // (t1-t0)*env_a+t0, (1-cmb)*prim+cmb
+  {0x2c120306, 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, cc__t0_inter_t1_using_enva__sub_env},
+  // paper mario. Added by Gonetz
+  // (t1-t0)*env_a+t0
+  {0x2c122c12, cc_t0_inter_t1_using_enva},
+  // paper mario. Added by Gonetz
+  // (t1-t0)*env_a+t0, (1-prim)*cmb+prim
+  {0x2c126036, cc_one_sub_prim_mul__t0_inter_t1_using_enva__add_prim},
+  //Arena, Pokemon Stadium 2
+  // (t1-t0)*env_a+t0, (cmb-0)*shade+prim
+  {0x2c1264f0, cc__t0_inter_t1_using_enva__mul_shade_add_prim},
+  // water, jet force. Added by Gonetz
+  // (t1-t0)*env_a+t0, (prim-shade)*cmb+shade
+  {0x2c128043, 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, 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, cc_prim_sub_center_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, 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, 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, cc_prim_sub_env_mul__t0_inter_t1_using_enva_alpha__add_env},
+  // Arena, pokemon Stadium
+  // (t1-t0)*env_a+t0, (cmb-shade)*prim+0
+  {0x2c12e340, cc__t0_inter_t1_using_enva__sub_shade_mul_prim},
+  // Water in zora's place, zelda
+  // (t1-t0)*env_a+t0, (cmb-0)*prim+0
+  {0x2c12e3f0, cc__t0_inter_t1_using_enva__mul_prim},
+  // Ground, zelda
+  //z (t1-t0)*env_a+t0, (cmb-k5)*shade+cmb_a
+  {0x2c12e4f0, cc__t0_inter_t1_using_enva__mul_shade},
+  // zelda, uninmp log.  Added by Gonetz
+  //(t1-t0)*env_a+t0, (cmb-0)*env+0
+  {0x2c12e5f0, cc__t0_inter_t1_using_enva__mul_env},
+  // Spheres, waverace
+  //z (env-t0)*env_a+t0
+  {0x2c152c15, cc_t0_inter_env_using_enva},//cc_t0},
+  // backgrounds, Mario Golf. Added by Gonetz
+  // (env-t0)*env_a+t0, (shade-0)*cmb+0
+  {0x2c15e0f4, cc__t0_inter_env_using_enva__mul_shade},
+  // ground on Volcano level, DKR, [Raziel64]
+  // (env-t0)*env_a+t0, (cmb-0)*shade+0
+  {0x2c15e4f0, cc__t0_inter_env_using_enva__mul_shade},
+  // Nintendo 'N', zelda
+  //z (t0-prim)*env_a+t0, (prim-env)*cmb+env
+  {0x2c31a053, 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, 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, cc__t1_sub_prim_mul_enva_add_t0__mul_prim_add_env},
+  // star beam, paper mario
+  // (prim-env)*env_a+t0
+  {0x2c532c53, cc_prim_sub_env_mul_enva_add_t0},
+  // Kotake & koume's hair, zelda
+  // (t1-0)*env_a+t0, (prim-env)*cmb+env
+  {0x2cf2a053, 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, cc_t0_mul_prim},
+  // Pilot wings
+  // (t1-t0)*lodf+t0, (one-cmb)*prim+cmb
+  {0x2d120306, cc_one_sub_prim_mul__t0_inter_t1_using_primlod__add_prim},
+  // Pilot wings
+  // (t1-t0)*lodf+t0, (one-cmb)*shade+cmb
+  {0x2d120406, cc_one_sub_shade_mul__t0_inter_t1_using_primlod__add_shade},
+  // Indy Racing 2000. Added by Gonetz
+  // (t1-t0)*lodf+t0, (env-cmb)*prima+cmb  ** INC **
+  {0x2d120a05, cc_t0_inter_t1_using_primlod},
+  // (t1-t0)*lodf+t0
+  {0x2d122d12, cc_t0_inter_t1_using_primlod},
+  //broken wall, beetle adventure racing. Added by Gonetz
+  // (t1-t0)*lodf+t0, (shade-prim)*cmb+prim
+  {0x2d126034, 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, cc_shade_sub_env_mul_t0_add_prim},
+  {0x2d126054, 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, cc_t0_mul_env_add_prim},
+  // sign, CBFD. Added by Gonetz
+  // (t1-t0)*lodf+t0, (cmb-env)*shade+prim ** INC **
+  {0x2d126450, cc__t0_inter_t1_using_primlod__sub_env_mul_shade_add_prim},
+  //    {0x2d126450, cc_t0_sub_env_mul_shade_add_prim},
+  // landscape, Cruis'n Exotica. Added by Gonetz
+  // (t1-t0)*lodf+t0, (cmb-0)*shade+prim
+  {0x2d1264f0, cc__t0_inter_t1_using_primlod__mul_shade_add_prim},
+  // blast corps [Ogy]
+  // (t1-t0)*lodf+t0, (0-0)*0+shade
+  {0x2d129fff, cc__t0_inter_t1_using_primlod__mul_shade},
+  // End of level, zelda
+  // (t1-t0)*lodf+t0, (prim-env)*cmb+env
+  {0x2d12a053, 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, cc_shade_sub_env_mul__t0_inter_t1_using_primlod__add_env},
+  // basket, Fox Sport
+  // (t1-t0)*lodf+t0, (prim-env)*t0+env
+  {0x2d12a153, 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, cc__t0_inter_t1_using_primlod__mul_prim_add_env},
+  // Tony Hawk Pro Skater
+  // (t1-t0)*lodf+t0, (cmb-0)*shade+env
+  {0x2d12a4f0, 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, cc_t0_inter_t1_using_primlod},
+  // Mike Piazza's Strike Zone
+  // (t1-t0)*lodf+t0, (shade-prim)*cmb+0
+  {0x2d12e034, 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, 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, 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, cc__t0_inter_t1_using_primlod__mul_prim},
+  // Rocket Robot in Wheels intro
+  // (t1-t0)*lodf+t0, (shade-0)*cmb+0
+  {0x2d12e0f4, cc__t0_inter_t1_using_primlod__mul_shade},
+  // Pilot wings
+  // (t1-t0)*lodf+t0, (cmb-0)*t0+0 ** INC **
+  {0x2d12e1f0, cc_t0_inter_t1_using_primlod},
+  // cars wheels, SF Rush 2049. Added by Gonetz
+  // (t1-t0)*lodf+t0, (cmb-0)*prim+0
+  {0x2d12e3f0, cc__t0_inter_t1_using_primlod__mul_prim},
+  // Bridge, sf rush
+  // (t1-t0)*lodf+t0, (cmb-0)*shade+0
+  //    {0x2d12e4f0, cc_t0_mul_shade},
+  {0x2d12e4f0, cc__t0_inter_t1_using_primlod__mul_shade},
+  // blast corps [Ogy]
+  // (t1-t0)*lodf+t0, (t0-0)*shade+0
+  {0x2d12e4f1, cc_t0_mul_shade},
+  // field, Mike Piazza's Strike Zone
+  // (t1-t0)*lodf+t0, (cmb-prim)*env+0   ** INC **
+  {0x2d12e530, cc__t0_inter_t1_using_primlod__mul_env},
+  // radar, Perfect Dark
+  // (t1-t0)*lodf+t0, (cmb-0)*env+0
+  {0x2d12e5f0, cc__t0_inter_t1_using_primlod__mul_env},
+  // planet, Blast Corps
+  // (t1-t0)*lodf+t0, (cmb-0)*prima+0
+  {0x2d12eaf0, cc__t0_inter_t1_using_primlod__mul_prima},
+  // zelda 2. Added by Gonetz
+  // (t0-t0)*primlod+t0, (prim-env)*cmb+env
+  {0x2e11a053, cc_prim_sub_env_mul_t0_add_env},
+  // zelda 2. Added by Gonetz
+  // (t1-t0)*primlod+t0, (0-0)*shade+cmb
+  {0x2e1204ff, cc_t0_inter_t1_using_primlod},
+  // zelda 2. Added by Gonetz
+  // (t1-t0)*primlod+t0, (env-prim)*primlod+cmb
+  {0x2e120d35, cc_prim_sub_env_mul_primlod_add__t0_inter_t1_using_primlod},
+  // lamppost, Ridge Racer. Added by Gonetz
+  // (t1-t0)*primlod+t0
+  {0x2e122e12, cc_t0_inter_t1_using_primlod},
+  // Hearts, zelda
+  //z (t1-t0)*primlod+t0, (shade-prim)*cmb+prim
+  {0x2e126034, 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, 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, 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, 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
+  {0x2e127ff0, cc_prim},
+  // arena, Pokemon Stadium 2. Added by Gonetz
+  // (t1-t0)*primlod+t0, (cmb-prim)*shade+shade  ** INC **
+  {0x2e128430, cc__t0_inter_t1_using_primlod__mul_shade},
+  // Pokemon Stadium 2. Added by Gonetz
+  // (t1-t0)*primlod+t0, (cmb-env)*cmb+env  ** INC **
+  {0x2e12a050, cc_t0_inter_t1_using_primlod},
+  // End of level heart, zelda
+  // (t1-t0)*primlod+t0, (prim-env)*cmb+env
+  {0x2e12a053, 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, 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, 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, cc__t0_inter_t1_using_primlod__sub_env_mul_shade_add_env},
+  // Fissure attack, pokemon stadium 2
+  // (t1-t0)*primlod+t0, (prim-env)*cmb_a+env
+  {0x2e12a753, cc_prim_sub_env_mul__t0_inter_t1_using_primlod__add_env},
+  // zelda 2. Added by Gonetz
+  // (t1-t0)*primlod+t0, (cmb-0)*t1+0  ** INC ** ?
+  {0x2e12e2f0, cc_t0_inter_t1_using_primlod},
+  // zelda 2. Added by Gonetz
+  // (t1-t0)*primlod+t0, (cmb-0)*prim+0
+  {0x2e12e3f0, cc__t0_inter_t1_using_primlod__mul_prim},
+  // sky, PGA European Tour
+  // (t1-t0)*primlod+t0, (cmb-env)*shade+0  ** INC **
+  {0x2e12e450, cc__t0_inter_t1_using_primlod__mul_shade},
+  // Kirby's pool, smash bros
+  // (t1-t0)*primlod+t0, (cmb-0)*shade+0
+  {0x2e12e4f0, 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, cc_t0_inter_prim_using_primlod},
+  // explosions, daikatana. Added by Gonetz
+  // (prim-t0)*primlod+t0, (cmb-0)*shade+0  **INC**
+  {0x2e13e4f0, cc_t0_mul_shade},
+  //Mike Piazza's Strike Zone logo. Added by Gonetz
+  // (shade-t0)*primlod+t0
+  {0x2e142e14, cc_t0_inter_shade_using_primlod},
+  // Cartridge color (transfer pak}, Pokemon Stadium 2 [gokuss4]. Added by Gonetz
+  // (1-t0)*primlod+t0
+  {0x2e162e16, cc_one_sub_t0_mul_primlod_add_t0},
+  // pokemon attack, Pokemon Stadium 2. Added by Gonetz
+  // (1-t0)*primlod+t0, (prim-0)*cmb+0
+  {0x2e16e0f3, cc__t0_inter_one_using_primlod__mul_prim},
+  // Spider Web attack, Pokemon Stadium 2.
+  // (1-t0)*primlod+t0, (cmb-0)*prim+0
+  {0x2e16e3f0, cc__t0_inter_one_using_primlod__mul_prim},
+  // pokemon attack, Pokemon Stadium 2. Added by Gonetz
+  // (1-t0)*primlod+t0, (cmb-0)*shade+0
+  {0x2e16e4f0, cc__t0_inter_one_using_primlod__mul_shade},
+  // zelda 2. Added by Gonetz
+  // (t1-t1)*primlod+t0, (prim-env)*cmb+env
+  {0x2e22a053, 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, cc_prim_sub_env_mul_t0_add_env},
+  // Skulltula coin solid, zelda
+  // (t0-prim)*primlod+t0, (prim-env)*cmb+env
+  {0x2e31a053, 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, 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, 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, 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, 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, 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, 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, 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, cc__t1_mul_primlod_add_t0__mul_prim},
+  // zelda 2. Added by Gonetz
+  // (t1-0)*primlod+t0, (cmb-0)*env+0
+  {0x2ef2e5f0, cc__t1_mul_primlod_add_t0__mul_env},
+  // gun, Doom64. Added by Gonetz
+  // (1-0)*primlod+t0, (cmb-0)*prim+env
+  {0x2ef6a3f0, cc__t0_add_primlod__mul_prim_add_env},
+  // walls, Doom64. Added by Gonetz
+  // (1-0)*primlod+t0, (cmb-0)*shade+env
+  {0x2ef6a4f0, cc__t0_add_primlod__mul_shade_add_env},
+  // Pokemon Stadium 2. Added by Gonetz
+  // (noise-0)*primlod+t0, (prim-env)*cmb+env  ** INC **
+  {0x2ef7a053, cc_prim_sub_env_mul_t0_add_env},
+  // Tony Hawk's Pro Skater. Added by Gonetz
+  // (t1-t0)*k5+t0
+  {0x2f122f12, cc_t0_inter_t1_using_k5},
+  // F1 World Grand Prix. Added by Gonetz
+  // (t1-t0)*k5+t0, (cmb-0)*shade+0    **INC**
+  {0x2f12e4f0, cc__t0_inter_t1_using_k5__mul_shade},
+  // Turok 3 [scorpiove]. Added by Gonetz
+  // (t0-k4)*k5+t0
+  {0x2f712f71, cc_t0},
+  // THPS 3
+  // (env-0)*k5+t0,
+  {0x2ff52ff5, cc_t0_add_env_mul_k5},
+  // super bowling
+  // (0-0)*k5+t0,
+  {0x2fff0000, cc_t0},
+  // super bowling
+  // (0-0)*k5+t0
+  {0x2fff2fff, cc_t0},
+  // Moonlight attack, pokemon stadium 2
+  // (t1-t0)*0+t0, (prim-env)*cmb+env
+  {0x3f12a053, cc_prim_sub_env_mul_t0_add_env},
+  //C&C shadows
+  //(1-env)*0+t0
+  {0x3f563f56, cc_t0},
+  // RARE logo, blast corps. Added by Gonetz
+  // (t0-0)*0+t0
+  {0x3ff13ff1, 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, cc_t0_mul_shade},
+  // intro, background, Dezaemon 3D
+  // (1-0)*0+t0
+  {0x3ff63ff6, cc_t0},
+  // intro of WWF WrestleMania 2000
+  // ((0-0)*0+t0, (env-cmb)*prim+cmb
+  {0x3fff0305, cc_env_sub_t0_mul_prim_add_t0},
+  // pistol fire, Turok
+  // ((0-0)*0+t0, (env-cmb)*shade+cmb
+  {0x3fff0405, cc_env_sub_t0_mul_shade_add_t0},
+  // Tony Hawk's Pro Skater. Added by Gonetz
+  // ((0-0)*0+t0, (t1-0)*shade+cmb ** INC **
+  {0x3fff04f2, cc_t0},
+  // Dr. Mario [Ogy]. Added by Gonetz
+  // ((0-0)*0+t0, (prim-cmb)*env+cmb
+  {0x3fff0503, cc_prim_sub_t0_mul_env_add_t0},
+  // Stained glass, quest64
+  // (0-0)*0+t0, (1-0)*env+cmb
+  {0x3fff05f6, cc_t0_add_env},
+  // Health bar, killer instinct gold
+  // (0-0)*0+t0, (prim-env)*prim_a+cmb
+  {0x3fff0a53, 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, cc_t0_inter_env_using_enva},
+  // intro, Mission Impossible. Added by Gonetz
+  // (k5-k5)*0+t0, (0-0)*scale+t0
+  {0x3fff26ff, cc_t0},
+  // V8-2
+  // (0-0)*0+t0, (t0-k4)*k5+t0
+  {0x3fff2f71, cc_t0_sub_k4_mul_k5_add_t0},
+  // TM, mario
+  //z (k5-k5)*0+t0
+  {0x3fff3fff, cc_t0},
+  // Intro, CBFD. Added by Gonetz
+  // ((0-0)*0+t0, (shade-env)*cmb+prim
+  {0x3fff6054, cc_shade_sub_env_mul_t0_add_prim},
+  // Text, Mia Soccer. Added by Gonetz
+  // ((0-0)*0+t0, (0-0)*0+prim
+  {0x3fff7fff, cc_t0},
+  // paper mario. Added by Gonetz
+  // ((0-0)*0+t0, (prim-env)*cmb+env
+  {0x3fffa053, cc_prim_sub_env_mul_t0_add_env},
+  // Objects in arena, pokemon stadium 2
+  // (0-0)*0+t0, (cmb-prim)*shade+env
+  {0x3fffa430, cc_t0_mul_prim},
+  // intro, F1 Racing Championship. Added by Gonetz
+  // (0-0)*0+t0, (shade-env)*cmb+0
+  {0x3fffe054, cc_shade_sub_env_mul_t0},
+  // stands, F1 Racing Championship. Added by Gonetz
+  // (0-0)*0+t0, (1-env)*cmb+0
+  {0x3fffe056, cc_one_sub_env_mul_t0},
+  // ? (from log)
+  // (0-0)*0+t0, (prim-0)*cmb+0
+  {0x3fffe0f3, cc_t0_mul_prim},
+  // background, GASP Fighters
+  // (0-0)*0+t0, (shade-0)*cmb+0
+  {0x3fffe0f4, cc_t0_mul_shade},
+  // zelda 2 [Ogy]. Added by Gonetz
+  // (0-0)*0+t0, (env-0)*cmb+0
+  {0x3fffe0f5, cc_t0_mul_env},
+  // logo, v-rally 99
+  // (0-0)*0+t0, (prim-0)*t0+0
+  {0x3fffe1f3, cc_t0_mul_prim},
+  // target hit, zelda 2. Added by Gonetz
+  // (0-0)*0+t0, (cmb-0)*prim+0
+  {0x3fffe3f0, cc_t0_mul_prim},
+  // Ms. Pac-Man intro background. Added by Gonetz
+  // (0-0)*0+t0, (cmb-0)*shade+0
+  {0x3fffe4f0, cc_t0_mul_shade},
+  //  Wonder Project J2 logo. Added by Gonetz
+  // (0-0)*0+t0, (t0-0)*shade+0
+  {0x3fffe4f1, cc_t0_mul_shade},
+  // tire trace, Monster truck madness. Added by Gonetz
+  // (0-0)*0+t0, (cmb-0)*env+0
+  {0x3fffe5f0, cc_t0_mul_env},
+  // Gauntlet Legends intro. Added by Gonetz
+  // (0-0)*0+t0, (cmb-0)*ecale+0
+  {0x3fffe6f0, cc_t0},
+  // tire trace, beetle adventure racing. Added by Gonetz
+  // (t1-t0)*t0+t1, (cmb-t0)*shade+t1   **INC**
+  {0x41124410, cc__t0_inter_t1_using_t0__mul_shade},
+  // Paper Mario. Added by Gonetz
+  // (t0-t1)*t0+t1   **INC**
+  {0x41214121, cc_t1_inter_t0_using_t0},
+  // Powered Star Beam, Paper Mario. Added by Gonetz
+  // (t0-t1)*t0+t1, (env-prim)*cmb+prim   **INC**
+  {0x41216035, 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, cc_env_sub_prim_mul__t0_mul_t1__add_prim},
+  // SCARS. Added by Gonetz
+  // (t1-t0)*t0+t1, (cmb-t0)*shade+t1   **INC**
+  {0x41250b03, cc__t0_inter_t1_using_half__mul_shade},
+  //beetle adventure racing. Added by Gonetz
+  //(t0-t1)*t1+t1, (cmb-0)*shade+0  **INC**
+  {0x4221e4f0, cc__t1_inter_t0_using_t1__mul_shade},
+  // cianwood gym walls, pokemon stadium 2
+  //(t0-prim)*t1+t1, (cmb-0)*env+shade
+  {0x423185f0, cc__t0_sub_prim_mul_t1_add_t1__mul_env_add_shade},
+  // cianwood gym walls, pokemon stadium 2
+  //(t0-prim)*t1+t1, (cmb-0)*shade+0
+  {0x4231e4f0, cc__t0_sub_prim_mul_t1_add_t1__mul_shade},
+  // paper mario. Added by Gonetz
+  // (t0-t0)*prim+t1, (t1-cmb)*cmb+env  **INC** weird
+  {0x4311a002, cc_env},
+  // background, Wetrix level 1, [Raziel64]. Added by Gonetz
+  // (t0-t1)*prim+t1
+  {0x43214321, cc_t1_inter_t0_using_prim},
+  // Mario Party3 Tidal Toss
+  // (t0-t1)*prim+t1, (cmb-0)*shade+0  **INC**
+  {0x4321e4f0, cc__t1_inter_t0_using_prim__mul_shade},
+  // grass, ISS 2k. Added by Gonetz
+  // (t0-t1)*prim+t1, (cmb-0)*env+0  **INC**
+  {0x4321e5f0, cc__t1_inter_t0_using_prim__mul_env},
+  // intro, Paper Mario
+  // (t0-0)*prim+t1
+  {0x43f143f1, cc_t0_mul_prim_add_t1},
+  // F1 World Grand Prix. Added by Gonetz
+  // (t0-0)*prim+t1, (cmb-0)*shade+env  **INC**
+  {0x43f1a4f0, cc__t0_add_t1__mul_shade_add_env},
+  // field, ISS64. Added by Gonetz
+  // (t0-t1)*shade+t1, (cmb-t1)*prim+t1  ** INC **
+  {0x44214320, cc_t0_sub_t1_mul_prim_mul_shade_add_t1},
+  //    {0x44214320, cc__t0_add_t1__mul_prim},
+  // field, Top gear hyper-bike
+  // (t0-t1)*shade+t1
+  {0x44214421, cc_t1_inter_t0_using_shade},
+  // water, goemon great adventure
+  // (t0-t1)*env+t1 ** INC **
+  {0x45214521, cc_t1_inter_t0_using_env},
+  // characters, Ogre Battle. Added by Gonetz
+  // (1-t1)*env+t1, (1-cmb)*prim+cmb  ** INC **
+  {0x45260306, cc_one_sub_t1_mul_prim_add_t1},
+  // characters, Ogre Battle. Added by Gonetz
+  // (1-t1)*env+t1
+  {0x45264526, cc_one_sub_t1_mul_env_add_t1},
+  // characters, Ogre Battle. Added by Gonetz
+  // (1-t1)*env+t1, (cmb-0)*prim+0  ** INC **
+  {0x4526e3f0, cc__t1_inter_one_using_env__mul_prim},
+  // explosion, body harvest. Added by Gonetz
+  // (t0-t1)*scale+t1, (env-prim)*cmb+prim  ** INC **
+  {0x46216035, 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, cc_t1_inter_t0_using_prima},
+  // flame, castlevania 2. Added by Gonetz
+  // (t0-t1)*prima+t1, (prim-env)*cmb+env
+  {0x4a21a053, 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, cc__t1_inter_t0_using_prima__mul_prim},
+  // menu, Mario Golf. Added by Gonetz
+  // (t0-t1)*prima+t1, (shade-0)*cmb+0
+  {0x4a21e0f4, cc__t1_inter_t0_using_prima__mul_shade},
+  // intro, castlevania 2. Added by Gonetz
+  // (t0-t1)*prima+t1, (cmb-0)*prim+0
+  {0x4a21e3f0, 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, cc__t1_inter_t0_using_prima__mul_shade},
+  // Ice, Paper Mario
+  // (t0-t1)*shade_a+t1
+  {0x4b214b21, cc_t1_inter_t0_using_shadea},
+  // Grass, Beetle Adventure Racing
+  // (t0-t1)*shade_a+t1, (cmb-0)*shade+0
+  {0x4b21e4f0, cc__t1_inter_t0_using_shadea__mul_shade},
+  // Ground at kotake & koume, zelda
+  // (t1-t0)*env_a+t0, (prim-env)*cmb+env
+  {0x4c12a053, 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, cc__t1_inter_t0_using_enva__mul_shade},
+  // bikes, xg2. Added by Gonetz
+  // (t0-t1)*env_a+t1, (cmb-prim)*prima+prim
+  {0x4c216a30, cc__t1_inter_t0_using_enva__sub_prim_mul_prima_add_prim},
+  // Yoshi Story
+  // (t0-t1)*env_a+t1, (prim-env)*cmb+env
+  {0x4c21a053, 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, 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
+  {0x4c26e2f0, cc__t1_inter_one_using_enva__mul_t0},
+  // Zelda opening door, zelda
+  // (t0-prim)*env_a+t1, (prim-env)*t0+env
+  {0x4c31a053, cc_prim_sub_env_mul_t0_add_env},
+  // arena, Pokemon Stadium 2
+  // (t0-0)*env_a+t1, (cmb-0)*shade+prim
+  {0x4cf164f0, cc__t0_mul_enva_add_t1__mul_shade_add_prim},
+  // Kotake & koume magic poof, zelda
+  // (t0-0)*env_a+t1, (prim-env)*cmb+env
+  {0x4cf1a053, 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, 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, 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, cc_t1_inter_t0_using_primlod},
+  // Pokemon backgrounds, pokemon stadium 2
+  // (t0-t1)*primlod+t1, (cmb-0)*shade+prim
+  {0x4e2164f0, cc__t1_inter_t0_using_primlod__mul_shade_add_prim},
+  // Pokemon backgrounds, pokemon stadium 2
+  // (t0-t1)*lodf+t1, (prim-env)*cmb+env
+  {0x4e21a053, 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, cc_env_sub__t0_sub_t1_mul_primlod__mul_prim},
+  // Magnitude, pokemon stadium 2
+  // (t0-t1)*primlod+t1, (prim-env)*cmb_a+env
+  {0x4e21a753, cc_prim_sub_env_mul__t1_inter_t0_using_primlod__add_env},
+  // Arena, pokemon stadium 2
+  // (t0-t1)*primlod+t1, (cmb-shade)*prim+0
+  {0x4e21e340, cc__t1_inter_t0_using_primlod__sub_shade_mul_prim},
+  // zelda 2 [Ogy]. Added by Gonetz
+  // (t0-t1)*primlod+t1, (cmb-0)*shade+0
+  {0x4e21e4f0, 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, cc_lavatex_sub_prim_mul_shade_add_lavatex},
+  // Skulltula coin, zelda
+  // (t0-prim)*primlod+t1, (prim-env)*cmb+env
+  {0x4e31a053, 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, 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, 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, cc__t1_inter_t0_using_k5__mul_shade},
+  // Spiderman. Added by Gonetz
+  //(t0-t1)*k5+t1, (cmb-0)*env+0
+  {0x4f21e5f0, cc_t1_mul_env},
+  // N64 logo, Ogre Battle. Added by Gonetz
+  //(0-0)*0+t1
+  {0x5fff5fff, cc_t1},
+  // reversing light, Monster truck madness. Added by Gonetz
+  //(0-0)*0+t0, (0-0)*0+prim
+  {0x5fff7fff, cc_prim},
+  // battle tanks [Ogy]
+  // (0-0)*0+t1, (env-shade)*cmb+shade
+  {0x5fff8045, cc_env_sub_shade_mul_t1_add_shade},
+  // minigame, pokemon stadium 1. Added by Gonetz
+  // (0-0)*0+t1, (prim-env)*cmb+env
+  {0x5fffa053, cc_prim_sub_env_mul_t1_add_env},
+  // F1 World Grand Prix. Added by Gonetz
+  // (t0-prim)*t0+prim, (cmb-0)*shade
+  {0x6131e4f0, cc__prim_inter_t0_using_t0__mul_shade},
+  // aerofighter's assault [Ogy]
+  // (shade-prim)*t0+prim
+  {0x61346134, cc_shade_sub_prim_mul_t0_add_prim},
+  // pilot wings
+  // (shade-prim)*t0+prim, (cmb-shade)*shadea+shade
+  {0x61348b40, cc_shade_inter__prim_inter_shade_using_t0__using_shadea},
+  // club blow, Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz
+  // (shade-prim)*t0+prim, (cmb-env)*cmb_a+env ** INC **
+  {0x6134a750, cc_shade_sub_prim_mul_t0_add_prim},
+  // sky, Killer Instinct
+  // (shade-prim)*t0+prim, (cmb-env)*shade_a+env ** INC **
+  {0x6134ab50, cc_env_inter__prim_inter_shade_using_t0__using_shadea},
+  // lava, beetle adventure racing
+  // (shade-prim)*t0+prim, (cmb-0)*t1+0 ** INC **
+  {0x6134e2f0, cc_shade_sub_prim_mul_t0_add_prim},
+  // Monster truck madness intro. Added by Gonetz
+  // (env-prim)*t0+prim, (cmb-0)*scale+cmb ** INC **
+  {0x613506f0, cc_env_sub_prim_mul_t0_add_prim},
+  // pokemon attack, Pokemon stadium 1
+  // (env-prim)*t0+prim, (cmb-0)*0+cmb
+  {0x61351ff0, cc_env_sub_prim_mul_t0_add_prim},
+  // Paper Mario, fortune teller spheres
+  // (env-prim)*t0+prim, (cmb-0)*t1+t0  ** INC **
+  {0x613522f0, cc_t0_mul_t1_add_t0},
+  // Later hearts, zelda
+  // (env-prim)*t0+prim
+  {0x61356135, cc_env_sub_prim_mul_t0_add_prim},
+  // Mission Impossible. Added by Gonetz
+  // (env-prim)*t0+prim, (shade-0)*cmb+0  ** INC **
+  {0x6135e0f4, cc__prim_inter_env_using_t0__mul_shade},
+  // crashing other vehicle, Monster truck madness [Raziel64]. Added by Gonetz
+  // (env-prim)*t0+prim, (cmb-0)*t0+0  ** INC **
+  {0x6135e1f0, 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, cc_env_sub_prim_mul_t0_add_prim},
+  // aerofighter's assault [Ogy]
+  // (env-prim)*t0+prim, (cmb-0)*shade+0  ** INC **
+  {0x6135e4f0, 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, cc_one_sub_prim_mul_t0_add_prim},
+  // intro, paper mario. Added by Gonetz
+  // (1-prim)*t0+prim, (cmb-0)*prima+t0  ** INC **
+  {0x61362af0, 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, 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, cc_t0_mul_shade},
+  // F1 World Grand Prix. Added by Gonetz
+  // (1-prim)*t0+prim, (cmb-0)*shade+0 ** INC **
+  {0x6136e4f0, cc_t0_mul_shade},
+  // Xena. Added by Gonetz
+  // (0-prim)*t0+prim
+  {0x613f613f, cc_one_sub_t0_mul_prim},
+  // Kirby64 end [Raziel64]. Added by Gonetz
+  // (prim-env)*t0+prim
+  {0x61536153, cc_prim_sub_env_mul_t0_add_prim},
+  // Xena. Added by Gonetz
+  // (shade-env)*t0+prim
+  {0x61546154, cc_shade_sub_env_mul_t0_add_prim},
+  // Karts, mario kart
+  //z (one-env)*t0+prim
+  {0x61566156, cc_t0_mul_1menv_add_prim},
+  // Famista64. Added by Gonetz
+  //(t0-0)*t0+prim
+  {0x61f161f1, cc_t0_mul_prim},
+  // Pokemon Stadium 2. Added by Gonetz
+  //(shade-0)*t0+prim
+  {0x61f461f4, cc_t0_mul_shade_add_prim},
+  // Doom. Added by Gonetz
+  //(1-0)*t0+prim
+  {0x61f661f6, cc_t0_add_prim},
+  // tire trace, beetle adventure racing. Added by Gonetz
+  // (shade-prim)*t1+prim, (cmb-0)*t1+0  **INC**
+  {0x6234e2f0, cc_shade_sub_prim_mul_t1_add_prim},
+  // Text, turok
+  // (env-prim)*t1+prim
+  {0x62356235, cc_env_sub_prim_mul_t1_add_prim},
+  // Pokemon Stadium 2, [gokuss4]. Added by Gonetz
+  // (env-prim)*t1+prim, (cmb-0)*t1+0
+  // Hack alert!
+  {0x6235e2f0, cc_t1},
+  // bike trace, xg2 intro. Added by Gonetz
+  // (1-prim)*t1+prim
+  {0x62366236, cc_one_sub_prim_mul_t1_add_prim},
+  // aerofighter's assault [Ogy]
+  // (1-prim)*t1+prim, (cmb-0)*0+env
+  {0x6236bff0, cc_one_sub_prim_mul_t1_add_prim},
+  // Tennis court, mario tennis
+  // (t0-0)*t1+prim
+  {0x62f162f1, cc__t0_mul_t1__add_prim},
+  // Arena, Pokemon Stadium 2
+  // (t0-0)*t1+prim, (cmb-0)*shade+0
+  {0x62f1e4f0, cc__t0_mul_t1_add_prim__mul_shade},
+  // Rush2. Added by Gonetz
+  // (prim-prim)*prim+prim
+  {0x63336333, cc_prim},
+  //Bowser in final battle, Paper Mario. Added by Gonetz
+  // (t1-0)*prim+prim
+  {0x63f263f2, cc_t1_mul_prim_add_prim},
+  // wetrix, icelayer, [Raziel64]. Added by Gonetz
+  // (t0-prim)*shade+prim  ** INC **
+  {0x64316431, cc_t0_mul_shade},
+  // KI. Added by Gonetz
+  // (env-prim)*shade+prim
+  {0x64356435, cc_env_sub_prim_mul_shade_add_prim},
+  // xg2. Added by Gonetz
+  // (1-prim)*shade+prim, (t0-0)*cmb+0  ** INC **
+  {0x6436e0f1, cc_t1_mul__one_sub_prim_mul_shade_add_prim},
+  // Intro, CBFD. Added by Gonetz
+  // (t0-env)*shade+prim
+  {0x64516451, 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, cc__t0_sub_env_mul_shade_add_prim__mul_shade},
+  // attack, Pokemon Stadium 2.
+  // (t0-env)*shade+prim, (cmb-0)*shade_a+0 ** INC **
+  {0x6451ebf0, cc__t0_sub_env_mul_shade_add_prim__mul_shadea},
+  // Road Rush. Added by Gonetz
+  // (t0-0)*shade+prim
+  {0x64f164f1, cc_t0_mul_shade_add_prim},
+  // paper mario. Added by Gonetz
+  // (1-0)*shade+prim
+  {0x64f664f6, cc_prim_add_shade},
+  // Character select, smash bros
+  // (t0-prim)*env+prim
+  {0x65316531, cc_t0_sub_prim_mul_env_add_prim},
+  // Clear screen intro, banjo kazooie
+  // (t0-prim)*env+prim, (cmb-0)*shade+0
+  //    {0x6531e4f0, cc_t0_mul_env_mul_shade},
+  {0x6531e4f0, cc__prim_inter_t0_using_env__mul_shade},
+  // Dragonfly feet, banjo kazooie
+  // (1-prim)*env+prim, (cmb-0)*shade+0
+  {0x6536e4f0, cc__prim_inter_one_using_env__mul_shade},
+  // Lava piranha atack, Paper Mario
+  // (t1-k4)*env+prim       ** INC **
+  {0x65726572, cc_t1_mul_env_add_prim},
+  // zelda 2 [Ogy]. Added by Gonetz
+  // (t0-0)*env+prim, (1-t1)*t0a+cmb  ** INC **
+  {0x65f10826, 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, cc_t0_mul_env_add_prim},
+  // Helicopter, Nuclear Strike. Added by Gonetz
+  // (t0-0)*env+prim
+  {0x65f165f1, cc_t0_mul_env_add_prim},
+  // Mystical Ninja
+  // (1-0)*env+prim
+  {0x65f665f6, cc_prim_add_env},
+  // duke nukem: zero hour [Ogy]
+  // (noise-0)*env+prim     ** INC **
+  {0x65f765f7, cc_prim_add_env},
+  // "terminator", CBFD
+  // (0-0)*env+prim
+  {0x65ff65ff, cc_prim},
+  // Cliffs, Taz express. Added by Gonetz
+  // (t0-0)*scale+prim
+  {0x66f166f1, cc_t0_mul_scale_add_prim},
+  // Taz express. Added by Gonetz
+  // (t0-0)*scale+prim, (cmb-0)*shade+0
+  {0x66f1e4f0, cc_t0_mul_scale_add_prim__mul_shade},
+  // NFL Quarterback Club 98 Menu [CpUMasteR]
+  // (prim-0)*scale+prim
+  {0x66f366f3, cc_prim},
+  // Pikachu
+  // (t0-prim)*t0_a+prim, (env-cmb)*enva+cmb
+  {0x68310c05, cc__prim_inter_t0_using_t0a__inter_env_using_enva},
+  // Character, dual heroes
+  // (t0-prim)*t0_a+prim
+  {0x68316831, 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, cc__prim_inter_t0_using_t0a__mul_shade},
+  // text, Sin and Punishmen. Added by Gonetz
+  // (env-prim)*t0_a+prim    ** INC **
+  {0x68356835, cc_env_sub_prim_mul_t0a_add_prim},
+  // arena, Pokemon Stadium 2
+  // (1-prim)*t0_a+prim
+  {0x68366836, cc_one_sub_prim_mul_t0a_add_prim},
+  // menu, PD. Added by Gonetz
+  // (env-prim)*t1_a+prim
+  {0x69356935, cc_env_sub_prim_mul_t1a_add_prim},
+  //    {0x69356935, cc_t1},
+  //xg2. Added by Gonetz
+  // (t0-prim)*prima+prim
+  {0x6a316a31, cc_t0_sub_prim_mul_prima_add_prim},
+  // menu, battle phoenix 64. Added by Gonetz
+  // (env-prim)*prima+prim
+  {0x6a356a35, cc_env_sub_prim_mul_prima_add_prim},
+  // ground, KI. Added by Gonetz
+  // (shade-env)*prima+prim
+  {0x6a546a54, 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, 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, cc__t0_mul_prima_add_prim_mul__shade},
+  // Genie, diddy kong racing
+  // (t0-prim)*shade_alpha+prim, (env-cmb)*shade+cmb
+  //    {0x6b310405, cc_env_sub__prim_inter_t0_using_shadea__mul_shade_add_env},
+  {0x6b310405, cc_t0_mul_shadea},
+  // Extreme G. Added by Gonetz
+  // (t0-prim)*shade_alpha+prim  ** INC **
+  {0x6b316b31, 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, 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, cc__prim_inter_t0_using_shadea__mul_shade},
+  // F1 World Grand Prix sky. Added by Gonetz
+  // (env-prim)*shade_alpha+prim, (shade-cmb)*cmb_a+cmb ** INC **
+  {0x6b350704, cc_f1_sky},
+  // lullaby, Paper Mario. Added by Gonetz
+  // (env-prim)*shade_alpha+prim
+  {0x6b356b35, cc_env_sub_prim_mul_shadea_add_prim},
+  // Some gannon spell, zelda
+  // (noise-t0)*env_a+prim, (0-prim)*cmb+1  ** INC **
+  {0x6c17c03f, cc_one_sub__one_sub_t0_mul_enva_add_prim__mul_prim},
+  //Goldeneye, [Jeremy]. Added by Gonetz
+  // (t0-prim)*env_a+prim
+  {0x6c316c31, cc_t0_sub_prim_mul_enva_add_prim},
+  // button, Sin and Punishmen. Added by Gonetz
+  // (env-prim)*env_a+prim
+  {0x6c356c35, cc_env_sub_prim_mul_enva_add_prim},
+  // frame buffer effect, Glover2
+  // (env-prim)*env_a+prim, (cmb-0)*shade+0
+  {0x6c35e4f0, cc__prim_inter_env_using_enva__mul_shade},
+  // fallen stars at star summit, Paper Mario. Added by Gonetz
+  // (t0-env)*env_a+prim, (1-0)*primlod+cmb
+  {0x6c510ef6, 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, cc_t0_sub_shade_mul_shadea_add_shade},
+  // Ring, pokemon stadium 2
+  // (t0-0)*env_a+prim, (1-0)*cmb+0
+  {0x6cf1e0f6, cc_t0_mul_enva_add_prim},
+  // Jet Force
+  // (noise-0)*env_a+prim
+  {0x6cf76cf7, cc_prim},
+  // snowhead temple, zelda 2. Added by Gonetz
+  // (t1-t0)*primlod+prim, (cmb-0)*shade+shade
+  {0x6e1284f0, 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, cc__t1_sub_t0_mul_primlod_add_prim__mul_shade},
+  // mini games quiz monitor backround, Pokemon Stadium 2
+  // (noise-t0)*primlod+prim, (prim-env)*cmb+env  ** INC **
+  {0x6e17a053, cc_prim_sub_env_mul__one_sub_t0_mul_primlod_add_prim__add_env},
+  // Morning Sun attack, pokemon stadium 2
+  // (t0-prim)*primlod+prim, (prim-env)*0+cmb
+  {0x6e311f53, cc_t0_sub_prim_mul_primlod_add_prim},
+  // sky, daikatana. Added by Gonetz
+  // (t0-prim)*primlod+prim, (cmb-0)*shade+0
+  {0x6e31e4f0, cc_t0_mul_shade},
+  // ball's track, NFL Blitz. Added by Gonetz
+  // (t0-0)*primlod+prim
+  {0x6ef16ef1, 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, cc_t0_mul_primlod_add_prim},
+  // mini games quiz monitor backround, Pokemon Stadium 2
+  // (noise-0)*primlod+prim, (env-cmb)*cmb_a+cmb ** INC **
+  // use cmb_a which is ac_t0_mul_t1
+  {0x6ef70705, cc_env_sub_prim_mul__t0a_mul_t1a__add_prim},
+  // rope, CBFD
+  // (t0-env)*k5+prim
+  {0x6f516f51, cc_t0_sub_env_mul_k5_add_prim},
+  // super bowling
+  // (0-0)*k5+prim
+  {0x6fff6fff, cc_prim},
+  // intro, Aidyn Chronicles. Added by Gonetz
+  // (0-0)*0+prim, (0-0)*0+prim
+  {0x79fb7788, cc_prim},
+  // Encore attack, Pokemon Stadium 2
+  // (t0-0)*0+prim, (cmb-0)*shade+0
+  {0x7ff1e4f0, cc_prim_mul_shade},
+  // Menu, megaman
+  // (1-0)*0+prim
+  {0x7ff67ff6, cc_prim},
+  // sky, PGA European Tour
+  // (0-0)*0+prim, (env-0)*t0+cmb
+  {0x7fff01f5, cc_t1_mul_env_add_prim},
+  // WWF No Mercy?
+  // ((0-0)*0+prim, (env-cmb)*shade+cmb
+  {0x7fff0405, cc_env_sub_prim_mul_shade_add_prim},
+  // sky, Spiderman. Added by Gonetz
+  // (0-0)*0+prim, (t1-0)*shade+cmb
+  {0x7fff04f2, cc_t1_mul_shade_add_prim},
+  // ball's shadow, ISS 2k. Added by Gonetz
+  // (0-0)*0+prim, (1-cmb)*env+cmb
+  {0x7fff0506, cc_one_sub_prim_mul_env_add_prim},
+  // Necklace, quest64
+  // (0-0)*0+prim, (1-0)*env+cmb
+  {0x7fff05f6, cc_prim_add_env},
+  // Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz
+  // (0-0)*0+prim, (1-cmb)*cmba+cmb ** INC **
+  {0x7fff0706, cc_prim},
+  // Dobutsu no Mori. Added by Gonetz
+  //(k5-k5)*0+prim, (cmb-0)*0+cmb
+  {0x7fff1ff0, cc_prim},
+  // Intro background, starfox
+  //z (k5-k5)*0+prim
+  {0x7fff7fff, cc_prim},
+  // train smoke, Dobutsu No Mori. Added by Gonetz
+  //(0-0)*0+prim, (shade-0)*cmb+0
+  {0x7fffe0f4, cc_prim_mul_shade},
+  // Donald Duck intro. Added by Gonetz
+  //(0-0)*0+prim, (cmb-0)*prim+0
+  {0x7fffe3f0, cc_prim_mul_prim},
+  // Ms. Pac-Man intro. Added by Gonetz
+  //(0-0)*0+prim, (cmb-0)*shade+0
+  {0x7fffe4f0, cc_prim_mul_shade},
+  // zelda 2.  Added by Gonetz
+  //(t1-t0)*t0+shade, (cmb-0)*shade+0
+  {0x8112e4f0, cc__t1_sub_t0_mul_t0_add_shade__mul_shade},
+  // branches, Beetle Adventure Racing
+  //(t0-shade)*t0+shade, (t0-cmb)*prim+cmb **INC**
+  {0x81410301, cc_t0_mul_prim},
+  // Namco logo, Famista 64
+  //(prim-shade)*t0+shade, (env-cmb)*t0+cmb **INC**
+  {0x81430105, cc_prim_sub_shade_mul_t0_add_shade},
+  // pikachu, hey you pikachu
+  //(prim-shade)*t0+shade, (env-cmb)*enva+cmb **INC**
+  {0x81430c05, cc_prim_sub_shade_mul_t0_add_shade},
+  // Mario's head, mario //Added by Gonetz
+  //(prim-shade)*t0+shade
+  {0x81438143, cc_prim_sub_shade_mul_t0_add_shade},
+  // Iguana background, turok
+  // (env-shade)*t0+shade
+  {0x81458145, cc_env_sub_shade_mul_t0_add_shade},
+  //attack, Pokemon Stadium 2
+  // (env-shade)*t0+shade, (cmb-0)*prim+0
+  {0x8145e3f0, cc__env_sub_shade_mul_t0_add_shade__mul_prim},
+  // Bubbles in Jabu-Jabu's belly, zelda
+  // (1-shade)*t0+shade
+  {0x81468146, cc_one_sub_shade_mul_t0_add_shade},
+  // saffron city, Pokemon Stadium 2
+  // (1-shade)*t0+shade, (cmb-0)*prim+0
+  {0x8146e3f0, cc__one_sub_shade_mul_t0_add_shade__mul_prim},
+  // duck dodgers intro. Added by Gonetz
+  // (1-shade)*t0+shade, (cmb-0)*shade+0
+  {0x8146e4f0, cc__one_sub_shade_mul_t0_add_shade__mul_shade},
+  // saffron city, Pokemon Stadium 2
+  // (1-shade)*t0+shade, (cmb-0)*prima+0
+  {0x8146eaf0, cc__one_sub_shade_mul_t0_add_shade__mul_env},
+  // intro, Madden Footbal
+  // (1-env)*t0+shade
+  {0x81568156, cc_one_sub_env_mul_t0_add_shade},
+  // sky in doom. Added by Gonetz
+  // (prim-0)*t0+shade, (cmb-0)*primlod+env  **INC**
+  {0x81f3aef0, cc_t0_mul_prim_add_shade},
+  // commercial? in IIS98. Added by Gonetz
+  // (1-0)*t0+shade
+  {0x81f681f6, cc_t0_add_shade},
+  //attack, Pokemon Stadium 2
+  //(t0-prim)*t1+shade
+  {0x82318231, cc_t0_sub_prim_mul_t1_add_shade},
+  //beetle adventure racing. Added by Gonetz
+  //(prim-shade)*t1+shade, (cmb-0)*t1+0  **INC**
+  {0x8243e2f0, cc_prim_sub_shade_mul_t1_add_shade},
+  //Arena, Pokemon Stadium 2
+  //(t0-0)*t1+shade
+  {0x82f182f1, cc__t0_mul_t1__add_shade},
+  //Arena, Pokemon Stadium 2
+  //(t0-0)*t1+shade, (cmb-0)*prim+0
+  {0x82f1e3f0, cc__t0_mul_t1__mul_prim_add_prim_mul_shade},
+  // Scorpion fire breath, MK4 [Jeremy]. Added by Gonetz
+  // (t0-shade)*prim+shade
+  {0x83418341, cc_t0_mul_prim_add_one_sub_prim_mul_shade},
+  // Menu background, wwf no mercy
+  // (env-shade)*prim+shade
+  {0x83458345, cc_prim_mul_env_add_one_sub_prim_mul_shade},
+  // Pokemon selection window background, pokemon stadium 2
+  // (noise-shade)*prim+shade
+  {0x83478347, cc_shade},
+  // crown of king of ikana, zelda 2. Added by Gonetz
+  // (t0-env)*prim+shade
+  {0x83518351, 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, 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, cc_t0_mul_prim_mul_shade},
+  // intro, Madden Footbal
+  // (1-env)*prim+shade
+  {0x83568356, cc_one_sub_env_mul_prim_add_shade},
+  // Buss hunter 64. Added by Gonetz
+  // (t0-0)*prim+shade
+  {0x83f183f1, 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, cc__t0_mul_prim_add_shade__sub_env_mul_shade},
+  // cynnabar gym fire shield, pokemon stadium 2
+  // (t0-0)*prim+shade, (cmb-0)*env+0  ** INC **
+  {0x83f1e5f0, cc__t0_mul_prim_add_shade__mul_env},
+  // 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, cc_t1_mul_prim_add_shade},
+  // Pokemon Stadium 2. Added by Gonetz
+  // (t0-prim)*shade+shade  ** INC **
+  {0x84318431, cc_t0_mul_shade},
+  // big N, Pokemon Stadium 2. Added by Gonetz
+  // (1-prim)*shade+shade  ** INC **
+  {0x84368436, cc_one_sub_prim_mul_shade_add_shade},
+  //Arena, Pokemon Stadium 2
+  //(t0-env)*shade+shade
+  {0x84518451, cc_t0_sub_prim_mul_shade_add_shade},
+  //Arena, Pokemon Stadium 2
+  //(t0-env)*shade+shade, (cmb-0)*prim+0
+  {0x8451e3f0, cc_t0_sub_env_mul_prim_mul_shade_add_prim_mul_shade},
+  // arena, PokemonStadium2, [Raziel64]
+  // (t0-0)*shade+shade, (cmb-0)*prim+0
+  {0x84f1e3f0, cc_t0_mul_prim_mul_shade_add_prim_mul_shade},
+  // Spiderman. Added by Gonetz
+  // (1-0)*shade+shade
+  {0x84f684f6, cc_shade_add_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, cc_t0_sub_prim_mul_env_add_shade},
+  // flower, zelda 2. Added by Gonetz
+  // (t0-prim)*env+shade, (cmb-0)*shade+0  ** INC **
+  {0x8531e4f0, cc_t0_sub_prim_mul_env_add_shade},
+  // Robotron 64, [scorpiove]
+  // (env-shade)*env+shade  ** INC **
+  {0x85458545, cc_one_sub_env_mul_shade_add_env},
+  // Enemy dying, quest64
+  // (1-shade)*env+shade  **changed by Gonetz
+  {0x85468546, cc_one_sub_shade_mul_env_add_shade},
+  // Arena, Pokemon Stadium
+  // (t0-0)*env+shade, (cmb-0)*prim+0
+  {0x85f1e3f0, cc__t0_mul_prim_mul_env__add__prim_mul_shade},
+  // Clouds, Pokemon Stadium
+  // (t1-0)*env+shade, (cmb-0)*prim+0
+  {0x85f2e3f0, cc__t1_mul_prim_mul_env__add__prim_mul_shade},
+  // Sky, Beetle Adventure Racing ** INC **
+  //(t0-shade)*t0_a+shade, (env-cmb)*enva+cmb
+  {0x88410c05, cc_t0_sub_shade_mul_t0a_add_shade},
+  // Mario's eyes, mario
+  //z (t0-shade)*t0_a+shade
+  {0x88418841, cc_t0_sub_shade_mul_t0a_add_shade},
+  //beetle adventure racing. Added by Gonetz
+  // (prim-shade)*t0_a+shade, (t1-0)*cmb+0  **INC**
+  {0x8843e0f2, cc_prim_sub_shade_mul__t0a_mul_t1__add_shade},
+  // blast corps [Ogy]
+  // (prim-shade)*t1_a+shade
+  {0x89438943, 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, cc_t0_sub_shade_mul_prima_add_shade},
+  // menu, battle phoenix 64. Added by Gonetz
+  // (t0-shade)*prima+shade
+  {0x8a418a41, cc_t0_add_shade},
+  // intro, castlevania 2. Added by Gonetz
+  // (prim-shade)*prim_a+shade
+  {0x8a438a43, cc_prim_sub_shade_mul_prima_add_shade},
+  // Pilot wings
+  // (t0-shade)*shade_a+shade, (cmb-0)*shade+0
+  {0x8b41e4f0, cc__shade_inter_t0_using_shadea__mul_shade},
+  // ?
+  // (1-shade)*shade_a+shade
+  {0x8b468b46, cc_one_sub_shade_mul_shadea_add_shade},
+  // Pilot wings, sky in congratulations
+  // (t0-0)*shade_a+shade,
+  {0x8bf18bf1, cc_t0_mul_shadea_add_shade},
+  // arena, Pokemon Stadium. Added by Gonetz
+  // (t0-t1)*env_a+shade, (cmb-env)*prim+0  ** INC **
+  {0x8c21e350, cc__t0_sub_t1_mul_enva_add_shade__sub_env_mul_prim},
+  //diddy kong racing background fill. Added by Gonetz ** Modified by Dave2001
+  // (env-shade)*env_a+shade, (cmb-0)*prim+0
+  {0x8c458c45, 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, cc_prim_mul_shade},
+  // sky, Pokemon Stadium, [Raziel64]
+  // (t0-0)*env_a+shade, (cmb-env)*prim+0  ** INC **
+  {0x8cf1e350, 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, 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, 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, cc_prim_sub_env_mul_shade_add_env},
+  // background on level 3-1, kirby 64 [Raziel64]. Added by Gonetz
+  // (0-env)*0+shade
+  {0x9f5f9f5f, cc_shade},
+  // Spotlight, smash bros
+  // (1-0)*0+shade
+  {0x9ff69ff6, cc_shade},
+  // water, Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz
+  // (0-0)*0+shade, (cmb-cmb)*cmb+cmb
+  {0x9fff0000, cc_shade},
+  // menu, Dr.Mario. Added by Gonetz
+  // (0-0)*0+shade, (prim-cmb)*env+cmb
+  {0x9fff0503, cc_prim_sub_shade_mul_env_add_shade},
+  // pikachu, hey you pikachu. Added by Gonetz
+  // (0-0)*0+shade, (env-cmb)*enva+cmb
+  {0x9fff0c05, cc_env_sub_shade_mul_enva_add_shade},
+  // mega shock, paper mario
+  //(0-0)*0+shade, (env-prim)*cmb+prim
+  {0x9fff6035, cc_env_sub_prim_mul_shade_add_prim},
+  // Super Mario 64 logo background
+  //z (k5-k5)*0+shade
+  {0x9fff9fff, cc_shade},
+  // Zelda 2 final movie. Added by Gonetz
+  // (0-0)*0+shade, (prim-0)*cmb+0
+  {0x9fffe0f3, 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, cc_env_mul_shade},
+  // N64 logo, Aidyn Chronicles. Added by Gonetz
+  // (0-0)*0+shade, (cmb-0)*prim+0
+  {0x9fffe3f0, cc_prim_mul_shade},
+  // Hand, smash bros
+  // (0-0)*0+shade, (cmb-0)*env+0
+  {0x9fffe5f0, cc_env_mul_shade},
+  // Lave piranha atack, Paper Mario
+  // (t1-t0)*t0+env, (cmb-t1)*t0+prim  ** INC **
+  {0xa1126120, cc__t0_mul_t1__mul_env_add_prim},
+  //Arena, Pokemon Stadium 2
+  // (t1-prim)*t0+env, (cmb-0)*shade+0
+  {0xa132e4f0, cc__t1_sub_prim_mul_t0_add_env__mul_shade},
+  // Kirby64 end [Raziel64]. Added by Gonetz
+  // (prim-shade)*t0+env
+  {0xa143a143, cc_prim_sub_shade_mul_t0_add_env},
+  // Superman [scorpiove]. Added by Gonetz
+  // (t0-env)*t0+env
+  {0xa151a151, 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, cc__prim_sub_env_mul_t0_add_env__add_shadea},
+  // pokemon attack, Pokemon Stadium 2. Added by Gonetz
+  // (prim-env)*t0+env, (0-0)*prim_lod+cmb
+  {0xa1530ef6, cc__prim_sub_env_mul_t0_add_env__add_primlod},
+  //attack, Pokemon Stadium 2
+  // (prim-env)*t0+env, (0-0)*prim_lod+cmb
+  {0xa1530eff, cc_prim_sub_env_mul_t0_add_env},
+  // Kotake & koume defeated, going into sky, zelda
+  // (prim-env)*t0+env, (prim-env)*0+cmb
+  {0xa1531f53, cc_prim_sub_env_mul_t0_add_env},
+  // water, Dobutsu no Mori. Added by Gonetz
+  // (prim-env)*t0+env, (cmb-0)*shade+t0
+  {0xa15324f0, cc_t0_add_shade_mul_env},
+  //sky, beetle adventure racing. Added by Gonetz
+  // (prim-env)*t0+env, (cmb-shade)*t1+shade **INC** can't be done in one step
+  {0xa1538240, cc__env_inter_prim_using_t0__sub_shade_mul_t0a_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, 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, 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, cc_t0_mul_env_add_shade},
+  // Getting light arrows for the first time, zelda
+  // (prim-env)*t0+env, (prim-env)*cmb+env  ** INC **
+  {0xa153a053, cc_prim_sub_env_mul_t0_add_env},
+  // Fire, starfox
+  // (prim-env)*t0+env
+  {0xa153a153, 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, 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, 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, cc__env_inter_prim_using_t0__mul_shade},
+  // Start menu, paper mario
+  // (prim-env)*t0+env, (cmb-0)*t0+0
+  {0xa153e1f0, cc_prim_sub_env_mul_t0_add_env},
+  //    {0xa153e0f4, 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, cc__env_inter_prim_using_t0__mul_prim},
+  // Dust, zelda
+  //z (prim-env)*t0+env, (cmb-0)*shade+0   ** INC **
+  {0xa153e4f0, cc__env_inter_prim_using_t0__mul_shade},
+  //{0xa153e4f0, cc_prim_sub_env_mul_t0_add_env},
+  // roof, Kirby 64. Added by Gonetz
+  // (prim-env)*t0+env, (cmb-0)*env+0   ** INC **
+  {0xa153e5f0, cc_prim_sub_env_mul_t0_add_env},
+  // hall of fame, Pokemon Stadium
+  // (prim-env)*t0+env, (cmb-0)*primlod+0
+  {0xa153eef0, cc__prim_sub_env_mul_t0_add_env__mul_primlod},
+  // Something weird in intro, monster truck madness
+  // (prim-env)*t0+env, (cmb-0)*k5+0
+  {0xa153eff0, cc__prim_sub_env_mul_t0_add_env__mul_k5},
+  // clothes, kirby 64. Added by Gonetz
+  // (shade-env)*t0+env
+  {0xa154a154, cc_shade_sub_env_mul_t0_add_env},
+  // field, Derby Stallion
+  // (shade-env)*t0+env, (cmb-0)*prim+0 ** INC **
+  {0xa154e3f0, 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, cc_shade_sub_env_mul_t0_add_env},
+  // pokemon attack, Pokemon Stadium 2. Added by Gonetz
+  // (one-env)*t0+env
+  {0xa156a156, cc_one_sub_env_mul_t0_add_env},
+  // Arena, Pokemon Stadium 2.
+  // (one-env)*t0+env, (cmb-0)*shade+0
+  {0xa156e4f0, cc__env_inter_one_using_t0__mul_shade},
+  //Arena, Pokemon Stadium 2
+  // (t1-0)*t0+env, (cmb-0)*cmb+0  ** INC **
+  {0xa1f2e0f0, cc__t0_mul_t1__add_env_mul__t0_mul_t1__add_env},
+  // quake 2 intro
+  // (prim-0)*t0+env, (prim-0)*primlod+cmb  ** INC **
+  {0xa1f30ef3, cc_t0_mul_prim_add_env},
+  // Kotake or koume's hair, zelda
+  // (prim-0)*t0+env
+  {0xa1f3a1f3, cc_t0_mul_prim_add_env},
+  // track, ridge racer. Added by Gonetz
+  // (t0-env)*t1+env, (cmb-0)*shade+0   ** INC **
+  {0xa251e4f0, cc__t0_mul_t1__mul_shade},
+  // lava, beetle adventure racing
+  // (t0-env)*t1+env, (cmb-0)*enva+0   ** INC **
+  {0xa251ecf0, cc__t0_mul_t1__mul_enva},
+  // Ded Moroz, Paper Mario
+  // (prim-env)*t1+env, (1-cmb)*t1+cmb  ** INC **
+  {0xa2530206, cc_prim_sub_env_mul_t1_add_env},
+  // text, monster truck madness
+  // (prim-env)*t1+env
+  {0xa253a253, 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, 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, cc_prim_sub_env_mul_t1_add_env_mul_t0},
+  // {0xa253e2f0, 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, cc_t1_mul_prim_mul_shade},
+  // Quake 2 intro. Added by Gonetz
+  // (t0-0)*t1+env, (t0-0)*primlod+cmb  ** INC **
+  {0xa2f10ef1, cc__t0_mul_t1__add_env},
+  // silver cave, pokemon stadium 2
+  // (t0-0)*t1+env, (cmb-prim)*shadea+prim
+  {0xa2f16b30, cc_prim_inter__t0_mul_t1_add_env__using_shadea},
+  // silver cave, pokemon stadium 2
+  // (t0-0)*t1+env, (cmb-0)*shadea+shade
+  {0xa2f18bf0, cc__t0_mul_t1_add_env__mul_shadea_add_shade},
+  // Quake64. Added by Gonetz
+  // (t0-0)*t1+env
+  {0xa2f1a2f1, cc__t0_mul_t1__add_env},
+  // Quake II. Added by Gonetz   ** INC **
+  // (t0-0)*t1+env, (cmb-0)*prim+env
+  {0xa2f1a3f0, cc__t0_mul_t1__mul_prim_add_env},
+  // Dr Mario [Ogy]. Added by Gonetz
+  // (t0-env)*prim+env
+  //    {0xa351a351, cc_t0_mul_prim_add_env},
+  {0xa351a351, cc_t0_sub_env_mul_prim_add_env},
+  // menu, Dr.Mario. Added by Gonetz
+  // (prim-env)*prim+env
+  {0xa353a353, 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, cc_shade_sub_env_mul_prim_add_env},
+  // bomberman 64-2 intro. Added by Gonetz
+  // (1-env)*prim+env
+  {0xa356a356, cc_one_sub_env_mul_prim_add_env},
+  // thing that escapes from the well, zelda
+  // (noise-env)*prim+env
+  {0xa357a357, cc_prim_add_env},
+  // Bongo Bongo, zelda
+  // (noise-env)*prim+env, (cmb-0)*shade+0
+  {0xa357e4f0, cc_env_mul_shade},
+  // paper mario. Added by Gonetz
+  // (t0-0)*prim+env
+  {0xa3f1a3f1, cc_t0_mul_prim_add_env},
+  // paper mario. Added by Gonetz
+  // (t0-0)*prim+env, (t0-env)*prim+0
+  {0xa3f1e351, cc_t0_mul_prim_add_env},
+  // paper mario. Added by Gonetz
+  // (t0-0)*prim+env, (t0-0)*prim+0
+  {0xa3f1e3f1, cc_t0_mul_prim},
+  // mahogany town statue, Pokemon Stadium 2
+  // (t0-0)*prim+env, (cmb-0)*shade+0
+  {0xa3f1e4f0, cc__t0_mul_prim_add_env__mul_shade},
+  // squirt, paper mario. Added by Gonetz
+  // (t1-0)*prim+env, (1-cmb)*t1+cmb
+  {0xa3f20206, cc_t1_mul_prim_add_env},
+  // paper mario. Added by Gonetz
+  // (shade-0)*prim+env
+  {0xa3f4a3f4, cc_prim_mul_shade_add_env},
+  // Sharpen attack, pokemon stadium 2
+  // (shade-0)*prim+env, (cmb-0)*shade+0
+  {0xa3f4e4f0, cc__prim_mul_shade_add_env__mul_shade},
+  // Doraemon 2. Added by Gonetz
+  // (1-0)*prim+env
+  {0xa3f6a3f6, cc_prim_add_env},
+  // Pokemon Stadium 2, [Jeremy]. Added by Gonetz
+  // (noise-0)*prim+env  ** INC ** ?
+  {0xa3f7a3f7, cc_prim_add_env},
+  // monsters, Pokemon Stadium. Added by Gonetz
+  // (t0-t1)*shade+env, (cmb-0)*prim+0 ** INC **
+  {0xa421e3f0, cc__t0_sub_t1__mul_prim_mul_shade_add_prim_mul_env},
+  // background, pokemon stadium 2
+  // (t0-prim)*shade+env
+  {0xa431a431, cc_t0_sub_prim_mul_shade_add_env},
+  // Arena, pokemon stadium 2
+  // (t0-prim)*shade+env, (cmb-0)*shade+0
+  {0xa431e4f0, cc__t0_sub_prim_mul_shade_add_env__mul_shade},
+  // Trophy, pokemon stadium 2
+  // (t0-prim)*shade+env, (cmb-0)*shade_a+0
+  {0xa431ebf0, cc__t0_sub_prim_mul_shade_add_env__mul_shadea},
+  // Buildings, pokemon stadium 2
+  // (t1-prim)*shade+env
+  {0xa432a432, cc_t1_sub_prim_mul_shade_add_env},
+  // bomberman 64 [Ogy]
+  // (t0-env)*shade+env
+  {0xa451a451, cc_t0_mul_shade_add_env},
+  // kirby drill, kirby 64. Added by Gonetz
+  // (prim-env)*shade+env
+  {0xa453a453, cc_prim_sub_env_mul_shade_add_env},
+  // ball, ISS98 intro. Added by Gonetz
+  // (t0-0)*shade+env
+  {0xa4f1a4f1, cc_t0_mul_shade_add_env},
+  // waterfall,  Dobutsu_no_Mori
+  // (prim-0)*shade+env, (t0-0)*primlod+cmb
+  {0xa4f30ef1, cc_t0_mul_primlod_add_prim_mul_shade_add_env},
+  // waterfall,  Dobutsu_no_Mori
+  // (prim-0)*shade+env, (t1-0)*primlod+cmb
+  {0xa4f30ef2, cc_t1_mul_primlod_add_prim_mul_shade_add_env},
+  // score, ISS98 intro. Added by Gonetz
+  // (prim-0)*shade+env
+  {0xa4f3a4f3, cc_prim_mul_shade_add_env},
+  // magic fist, Rayman2. Added by Gonetz
+  // (env-0)*shade+env
+  {0xa4f5a4f5, cc_env_mul_shade_add_env},
+  // gunfire, Quake64. Added by Gonetz
+  // (1-0)*shade+env
+  {0xa4f6a4f6, cc_env_add_shade},
+  // flame, Paper Mario. Added by Gonetz
+  // (t0-center)*scale+env, (0-prim)*cmb+env
+  {0xa661a03f, cc_env_sub__t0_mul_scale_add_env__mul_prim},
+  // N64 BIOS
+  // (t0-env)*t0_a+env, cmb*shade
+  {0xa851e0f4, cc__env_inter_t0_using_t0a__mul_shade},
+  // pink car, f-zero x
+  // (t0-env)*t0_a+env, cmb*shade
+  {0xa851e4f0, cc__env_inter_t0_using_t0a__mul_shade},
+  // PokemonStadium1, [Raziel64]
+  // (prim-env)*t0_a+env, (cmb-cmb)*cmb+cmb
+  {0xa8530000, cc_prim_sub_env_mul_t0a_add_env},
+  // N64 logo, Ogre Battle
+  // (prim-env)*t0_a+env
+  {0xa853a853, 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, cc_prim_sub_env_mul_t0a_add_env},
+  // Tree background, mace
+  // (prim-env)*t0_a+env, (cmb-0)*t0+0
+  {0xa853e1f0, cc__env_inter_prim_using_t0a__mul_t0},
+  //attack, Pokemon Stadium 2
+  // (prim-env)*t0_a+env, (cmb-0)*prim+0
+  {0xa853e3f0, cc__env_inter_prim_using_t0a__mul_prim},
+  // logo, Deadly Arts. Added by Gonetz
+  // (prim-env)*t1_a+env
+  {0xa953a953, cc_prim_sub_env_mul_t1a_add_env},
+  // MarioGolf  text "Birdie Put"
+  // (t0-env)*prim_a+env
+  {0xaa51aa51, cc_t0_sub_env_mul_prima_add_env},
+  // N64 BIOS
+  // (t0-env)*prim_a+env, (shade-0)*cmb+0
+  {0xaa51e0f4, cc__env_inter_t0_using_prima__mul_shade},
+  // N64 BIOS
+  // (prim-env)*prima+env, (shade-0)*cmb+0
+  {0xaa53e0f4, cc__env_inter_prim_using_prima__mul_shade},
+  // Girl, PD intro. Added by Gonetz
+  // (t0-env)*shade_alpha+env, (cmb-0)*shade+0 ** INC **
+  {0xab51e4f0, cc__env_inter_t0_using_shadea__mul_shade},
+  // Some gannon spell, zelda
+  // (prim-env)*shade_alpha+env
+  {0xab53ab53, cc_prim_sub_env_mul_shadea_add_env},
+  //Arena, Pokemon Stadium 2
+  // (t0-0)*shade_alpha+env, (cmb-0)*shade+prim
+  {0xabf164f0, cc__t0_mul_shadea_add_env__mul_shade_add_prim},
+  // Boxes, Taz express. Added by Gonetz
+  // (t0-env)*env_a+env
+  {0xac51ac51, cc_t0_sub_env_mul_enva_add_env},
+  // paper mario. Added by Gonetz
+  // (t0-env)*env_a+env, (cmb-0)*shade+0  **INC**
+  {0xac51e4f0, cc_t0_mul_env_mul_shade},
+  // goal, Monster Truck Madness 64
+  // (noise-0)*env_a+env, (cmb-0)*t1+0  **INC**
+  {0xacf7e2f0, cc_t1_mul_env},
+  // sword on forge, zelda 2. Added by Gonetz
+  // (t1-t1)*lodf+env, (t1-t0)*cmb+prim
+  {0xae226012, cc__t1_sub_t0__mul_env_add_prim},
+  // menu background, Pokemon Stadium 2, [Raziel64]
+  // (t0-prim)*lodf+env
+  {0xae31ae31, 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, cc__env_inter_prim_using__t0_sub_shade_mul_primlod_add_env},
+  //    {0xae41a053, 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, cc__env_inter_t0_using_primlod__mul_prim},
+  //Spacestation Silicon Valley intro. Added by Gonetz
+  // (prim-env)*lodf+env
+  {0xae53ae53, cc_env_inter_prim_using_primlod},
+  // Doom, intro. Added by Gonetz
+  // (t0-0)*lodf+env, (t0-0)*lodf+env
+  {0xaef1aef1, cc_t0_add_env},
+  // Dobutsu no Mori. Added by Gonetz
+  // (prim-0)*lodf+env
+  {0xaef3aef3, cc_prim_add_env},
+  // forest behind window, Dobutsu no Mori. Added by Gonetz
+  // (prim-0)*prim_lod+env, (t1-0)*cmb+0
+  {0xaef3e0f2, cc_t0_mul__prim_mul_primlod_add_env },
+  // tony hawks 2 menu
+  // (t0-rnv)*k5+env, (cmb-t1)*t1_a+t1      ** INC ** (correct combiner does not work because of black t1)
+  {0xaf514920, cc_t0_sub_env_mul_k5_add_env},
+  // intro, Mission Impossible. Added by Gonetz
+  // (k5-k5)*0+env, (0-0)*scale+env
+  {0xbfffa6ff, cc_env},
+  // Something blocking the screen, waverace
+  //z (k5-k5)*0+env
+  {0xbfffbfff, cc_env},
+  // Derby Stallion . Added by Gonetz
+  // (0-0)*0+env, (cmb-0)*prim+0
+  {0xbfffe3f0, cc_prim_mul_env},
+  // zelda 2 [Ogy]. Added by Gonetz
+  // (k5-k5)*0+env, ((cmb-0)*shade+0
+  {0xbfffe4f0, cc_env_mul_shade},
+  // flame, paper mario. Added by Gonetz
+  // (t0-t1)*t0+1, (0-prim)*cmb+env  **INC** weird
+  {0xc121a03f, 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, cc_prim_sub_env_mul_t0_mul_shade},
+  // paper mario. Added by Gonetz
+  // (0-env)*t0+1, (prim-cmb)*t0+prim  **INC**
+  {0xc15f6103, cc_env_sub_prim_mul_t0_add_prim},
+  // HAL, smash bros
+  // (0-0)*0+1
+  {0xdfffdfff, cc_one},
+  // arena, Pokemon Stadium 1, [Raziel64]
+  // (0-0)*0+1, (cmb-0)*prim+0
+  {0xdfffe3f0, cc_prim},
+  // skis, Spacestation Silicon Valley. Added by Gonetz
+  // (shade-0)*cmb+0, (t1-t0)*primlod+t0
+  {0xe0f42d12, cc_t0_inter_t1_using_primlod},
+  // paper mario. Added by Gonetz
+  // (1-t1)*t0+0, (env-prim)*cmb+prim  ** INC **
+  {0xe1266035, 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, cc__t1_sub_prim_mul_t0__mul_shade},
+  // carmagedon
+  // (shade-prim)*t0+0
+  {0xe134e134, cc_shade_sub_prim_mul_t0},
+  // skeleton, castlevania 2. Added by Gonetz
+  // (1-prim)*t0+0, (cmb-0)*shade+0
+  {0xe136e4f0, cc_t0_mul_1mprim_mul_shade},
+  // Starshot logo. Added by Gonetz
+  // (shade-env)*t0+0, (1-0)*cmb+cmb
+  {0xe15400f6, cc_shade_sub_env_mul_t0},
+  // Kirby morfing, smash bros. Added by Gonetz
+  // (shade-env)*t0+0
+  {0xe154e154, cc_shade_sub_env_mul_t0},
+  // menu, PGA euro tour. Added by Gonetz
+  // (1-env)*t0+0
+  {0xe156e156, cc_one_sub_env_mul_t0},
+  // paper mario. Added by Gonetz
+  // (t0-0)*t0+0, (1-cmb)*prim+cmb
+  {0xe1f10306, cc_one_sub_t0_mul_prim_add_t0},
+  // F1 World Grand Prix. Added by Gonetz
+  // (t0-0)*t0+0, (shade-prim)*cmb+prim
+  {0xe1f16034, cc_shade_sub_prim_mul_t0_add_prim},
+  // paper mario. Added by Gonetz
+  // (t0-0)*t0+0, (env-prim)*cmb+prim
+  {0xe1f16035, 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, cc_one_sub_prim_mul_t0_add_prim},
+  // rocket team basket, Pokemon Stadium 2
+  // (t0-0)*t0+0, (cmb-prim)*shade+shade
+  {0xe1f18430, cc__t0_mul_t0__sub_prim_mul_shade_add_shade},
+  // Tony Hawk's Pro Skater. Added by Gonetz
+  // (t0-0)*t0+0, (cmb-0)*t0+0
+  {0xe1f1e1f0, cc_t0},
+  // something in upper left corner, mario tennis
+  // (t0-0)*t0+0
+  {0xe1f1e1f1, cc_t0},
+  // zelda 2. Added by Gonetz
+  // (t0-0)*t0+0, (cmb-0)*prim+0
+  {0xe1f1e3f0, cc_t0_mul_prim},
+  // zelda 2 final movie. Added by Gonetz
+  // (t0-0)*t0+0, (cmb-0)*shade+0
+  {0xe1f1e4f0, cc_t0_mul_shade},
+  // paper mario. Added by Gonetz
+  // (t0-t1)*t0+1, (env-cmb)*prima+cmb  ** INC **
+  {0xe1f20a05, cc_t1_mul_prima},
+  // terrain, SCARS. Added by Gonetz
+  // (t1-0)*t0+0, (env-prim)*cmb+prim
+  {0xe1f26035, cc_env_sub_prim_mul__t0_mul_t1__add_prim},
+  // Trees, Zelda 2
+  // (t1-0)*t0+0, (cmb-0)*shade+prim
+  {0xe1f264f0, cc__t0_mul_t1__mul_shade_add_prim},
+  // terrain, SCARS. Added by Gonetz
+  // (t1-0)*t0+0, (env-shade)*cmb+shade
+  {0xe1f28045, 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, cc__t0_mul_t1__sub_prim_mul_shade_add_shade},
+  // arena, Pokemon Stadium 2
+  // (t1-0)*t0+0, (cmb-env)*shade+shade
+  {0xe1f28450, cc__t0_mul_t1__sub_env_mul_shade_add_shade},
+  // Zelda 2, [Ogy]. Added by Gonetz
+  // (t1-0)*t0+0, (cmb-prim)*env+shade  ** INC **
+  {0xe1f28530, cc__t0_mul_t1__sub_prim_mul_env_add_shade},
+  // pokemon attack, Pokemon Stadium 2. Added by Gonetz
+  // (t1-0)*t0+0, (prim-env)*cmb+env
+  {0xe1f2a053, cc_prim_sub_env_mul__t0_mul_t1__add_env},
+  // paper mario. Added by Gonetz
+  // (t1-0)*t0+0, (cmb-0)*prim+env
+  {0xe1f2a3f0, cc__t0_mul_t1__mul_prim_add_env},
+  // Sand, pokemon stadium 2
+  // (t1-0)*t0+0, (cmb-prim)*shade+env  ** INC **
+  {0xe1f2a430, cc__t0_mul_t1__mul_shade},
+  // grass, Mission Impossible. Added by Gonetz
+  // (t1-0)*t0+0, (shade-0)*cmb+0
+  {0xe1f2e0f4, cc__t0_mul_t1__mul_shade},
+  // flag, Monako Grand Prix
+  // (t1-0)*t0+0
+  {0xe1f2e1f2, cc_t0_mul_t1},
+  // lighthouse's beam, zelda 2. Added by Gonetz
+  // (t1-0)*t0+0, (cmb-0)*prim+0
+  {0xe1f2e3f0, cc__t0_mul_t1__mul_prim},
+  // Bottom of wings, pilotwings
+  // (t1-0)*t0+0, (cmb-0)*shade+0
+  {0xe1f2e4f0, cc__t0_mul_t1__mul_shade},
+  // zelda 2. Added by Gonetz
+  // (t1-0)*t0+0, (cmb-0)*prima+0
+  {0xe1f2eaf0, cc__t0_mul_t1__mul_prima},
+  // lava, Roadsters. Added by Gonetz
+  // (prim-0)*t0+0, (1-prim)*t0+cmb
+  {0xe1f30136, cc_t0},
+  // sky, Pokemon Stadium 2. Added by Gonetz
+  // (prim-0)*t0+0, (cmb-0)*shadea+env
+  {0xe1f3abf0, cc_t0_mul_prim_mul_shadea_add_env},
+  // cars, Indy Racing 2000. Added by Gonetz
+  // (prim-0)*t0+0, (shade-0)*cmb+0
+  {0xe1f3e0f4, cc_t0_mul_prim_mul_shade},
+  // Sign shadows, zelda
+  //z (prim-k5)*t0+cmb_a
+  {0xe1f3e1f3, cc_t0_mul_prim},
+  // Table, mace
+  // (prim-0)*t0+0, (cmb-0)*shade+0
+  {0xe1f3e4f0, cc_t0_mul_prim_mul_shade},
+  // Gauntlet Legends intro
+  // (prim-0)*t0+0, (cmb-0)*prima+0
+  {0xe1f3eaf0, cc_t0_mul_prim_mul_prima},
+  // walls, beetle adventure racing. Added by Gonetz
+  // (shade-0)*t0+0, (prim-0)*t0+cmb
+  {0xe1f401f3, cc_t0_mul_shade},
+  // cars, ridge racer. Added by Gonetz
+  // (shade-0)*t0+0, (prim-cmb)*cmb_a+cmb **INC**
+  {0xe1f40703, cc_t0_mul_shade},
+  // water block, Paper Mario. Added by Gonetz
+  // (shade-0)*t0+0, (prim-env)*cmb+env
+  {0xe1f4a053, 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, cc_t0_mul_prim_mul_shade_add_env},
+  // Xena. Added by Gonetz
+  // (shade-0)*t0+0, (env-0)*cmb+0
+  {0xe1f4e0f5, cc_t0_mul_env_mul_shade},
+  // Starshot logo. Added by Gonetz
+  // (shade-0)*t0+0, (1-0)*cmb+0
+  {0xe1f4e0f6, cc_t0_mul_shade},
+  // Duck Dodgers intro. Added by Gonetz
+  // (shade-0)*t0+0
+  {0xe1f4e1f4, cc_t0_mul_shade},
+  // shadow, Mission Impossible. Added by Gonetz
+  // (shade-0)*t0+0, (cmb-0)*prim+0
+  {0xe1f4e3f0, 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, cc__t0_add_t1__mul_shade},
+  // text, tonic trouble. Added by Gonetz
+  // (env-0)*t0+0
+  {0xe1f5e1f5, cc_t0_mul_env},
+  // powder keg, zelda 2. Added by Gonetz
+  // (env-0)*t0+0, (cmb-0)*shade+0
+  {0xe1f5e4f0, cc_t0_mul_env_mul_shade},
+  // Buss rush
+  // (1-0)*t0+0, (0-cmb)*0+cmb
+  {0xe1f61f0f, cc_t0},
+  // water, Starshot. Added by Gonetz
+  // (1-0)*t0+0, (1-0)*cmb+0
+  {0xe1f6e0f6, cc_t0},
+  // bomberman 64 [Ogy]
+  // (1-0)*t0+0
+  {0xe1f6e1f6, cc_t0},
+  // Mermaid attack, Mystical Ninja
+  // (noise-0)*t0+0
+  {0xe1f7e1f7, cc_t0},
+  // paper mario. Added by Gonetz * changed because of odd palette copy
+  // (t0-0)*t1+0, (shade-env)*cmb+cmb  **INC** ?
+  {0xe2f10054, cc_shade_sub_env_mul__t0_mul_t1__add__t0_mul_t1},
+  // Duck Dodgers Starring Daffy Duck text background
+  // (t0-0)*t1+0, (shade-cmb)*prim+cmb
+  {0xe2f10304, cc_one_sub_prim_mul__t0_mul_t1__add__prim_mul_shade},
+  // water, PGA European Tour
+  // (t0-0)*t1+0, (env-cmb)*prim+cmb
+  {0xe2f10305, 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, cc_t0_mul_t1},
+  // xg2, Added by Gonetz
+  // (t0-0)*t1+0, (env-prim)*cmb+prim
+  {0xe2f16035, 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, cc__t0_mul_t1__mul_shade_add_prim},
+  // the champion stage, Pokemon Stadium 2
+  // (t0-0)*t1+0, (cmb-0)*shade+prim
+  {0xe2f164f0, cc__t0_mul_t1__mul_shade_add_prim},
+  // sky, xg2, Added by Gonetz
+  // (t0-0)*t1+0, (cmb-prim)*cmb_a+prim
+  {0xe2f16730, 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, cc_env_sub_prim_mul__t0t1a__add_prim},
+  // cianwood gym walls, pokemon stadium 2
+  // (t0-0)*t1+0, (cmb-prim)*shade+shade
+  {0xe2f18430, cc__t0_mul_t1__sub_prim_mul_shade_add_shade},
+  // light, Ridge Racer. Added by Gonetz
+  // (t0-0)*t1+0, (prim-env)*cmb+env
+  {0xe2f1a053, 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, cc_shade_sub_env_mul__t0_mul_t1__add_env},
+  // Arena, Pokemon Stadium 2 ** INC **
+  // (t0-0)*t1+0, (cmb-prim)*shade+env
+  {0xe2f1a430, cc__t0_mul_t1__mul_shade_add_env},
+  // bikes, xg2
+  // (t0-0)*t1+0, (shade-0)*cmb+0
+  {0xe2f1e0f4, cc__t0_mul_t1__mul_shade},
+  // Sky background, xg2
+  // (t0-0)*t1+0
+  {0xe2f1e2f1, cc_t0_mul_t1},
+  // statistics, Banjo 2. Added by Gonetz
+  // (t0-0)*t1+0, (cmb-0)*prim+0
+  {0xe2f1e3f0, cc__t0_mul_t1__mul_prim},
+  // the champion stage, Pokemon Stadium 2
+  // (t0-0)*t1+0, (cmb-prim)*shade+0
+  {0xe2f1e430, cc__t0_mul_t1__sub_prim_mul_shade},
+  // Water, pilotwings
+  // (t0-0)*t1+0, (cmb-0)*shade+0
+  {0xe2f1e4f0, cc__t0_mul_t1__mul_shade},
+  //beetle adventure racing. A dded by Gonetz
+  // (t0-0)*t1+0, (cmb-0)*env+0
+  {0xe2f1e5f0, cc__t0_mul_t1__mul_env},
+  //fall headwaters, zelda 2. Added by Gonetz
+  // (t1-0)*t1+0, (cmb-0)*shade+0
+  {0xe2f2e4f0, cc_t1_mul_shade},
+  //text, Paper Mario
+  // (prim-0)*t1+0
+  {0xe2f3e2f3, cc_t1_mul_prim},
+  //terrain, Beetle Adventure Racing. Added by Gonetz
+  // (shade-0)*t1+0
+  {0xe2f4e2f4, cc_t1_mul_shade},
+  // Transfer pack, Pokemon Stadium 2
+  // (noise-0)*t1+0, (prim-env)*cmb+env
+  {0xe2f7a053, cc_prim_sub_env_mul_t1_add_env},
+  // lens of truth, zelda 2 [Ogy]. Added by Gonetz
+  // (1-t0)*prim+0
+  {0xe316e316, cc_one_sub_t0_mul_prim},
+  //C&C pointer
+  //(shade-env)*prim+0
+  {0xe354e354, cc_shade_sub_env_mul_prim},
+  //C&C shadows
+  //(1-env)*prim+0
+  {0xe356e356, cc_one_sub_env_mul_prim},
+  // Magnitude, pokemon stadium 2
+  // (t0-0)*prim+0, (t0-0)*env+cmb
+  {0xe3f105f1, cc_t0_mul__prim_add_env},
+  // night vision, jet force gemini
+  // (t0-0)*prim+0, (noise-0)*env+cmb
+  {0xe3f105f7, cc_t0_mul_prim_add_env},
+  // Smoke, diddy kong racing
+  // (t0-0)*prim+0, (env-cmb)*env_alpha+cmb
+  {0xe3f10c05, cc__t0_mul_prim__inter_env_using_enva},
+  // battle menu, Paper Mario. Added by Gonetz
+  // (t0-0)*prim+0, (t0-env)*env_alpha+cmb   ** INC **
+  {0xe3f10c51, cc_t0_mul_prim},
+  // stalactites, Beetle adventure Racing. Added by Gonetz
+  // (t0-0)*prim+0, (cmb-shade)*t1_alpha+shade   ** INC **
+  {0xe3f18940, cc_t0_mul_prim_add_shade },
+  // ? in Jabu-Jabu's belly, submitted by gokuss4
+  // {0xe4f1a053, (t0-0)*prim+0, (prim-env)*cmb+env
+  {0xe3f1a053, 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, cc_t0_mul_prim_mul_shade_add_env},
+  // ? sign, zelda 2. Added by Gonetz
+  // (t0-0)*prim+0, (cmb-0)*cmb+0 ** INC **
+  {0xe3f1e0f0, cc_t0_mul_prim},
+  // vehicle, Star Wars Ep.1 Racer, [Raziel64]. Added by Gonetz
+  // (t0-0)*prim+0, (shade-0)*cmb+0
+  {0xe3f1e0f4, cc_t0_mul_prim_mul_shade},
+  // mini game, Pokemon Stadium 2
+  // (t0-0)*prim+0, (1-0)*cmb+0
+  {0xe3f1e0f6, cc_t0_mul_prim},
+  // magic stuff, buck bumble. Added by Gonetz
+  // (t0-0)*prim+0, (cmb-0)*prim+0
+  {0xe3f1e3f0, cc_t0_mul_prim_mul_prim},
+  // The mario face, mario
+  //z (t0-k5)*prim+cmb_a
+  {0xe3f1e3f1, cc_t0_mul_prim},
+  // Butterflies at Jabu-Jabu's lake, zelda
+  // (t0-0)*prim+0, (cmb-0)*shade+0
+  {0xe3f1e4f0, cc_t0_mul_prim_mul_shade},
+  // Sports shirt, Mia Soccer. Added by Gonetz
+  // (t1-0)*prim+0, (1-t0)*t1+cmb **INC**
+  //    {0xe3f20216, cc_t0_mul_prim_add_t1},
+  {0xe3f20216, cc_shirt},
+  // Sprites, Ogre Battle. Added by Gonetz
+  // (t1-0)*prim+0
+  {0xe3f2e3f2, cc_t1_mul_prim},
+  // F1 World Grand Prix. Added by Gonetz
+  // (t1-0)*prim+0, (cmb-0)*shade+0
+  {0xe3f2e4f0, cc_t1_mul_prim_mul_shade},
+  // intro background, bio freaks. Added by Gonetz
+  // (prim-0)*prim+0
+  {0xe3f3e3f3, cc_prim_mul_prim},
+  // player, Ohzumou2
+  // (shade-0)*prim+0, (env-cmb)*t0+cmb
+  {0xe3f40105, cc_env_sub_primshade_mul_t0_add_primshade},
+  // floor in pyramides, beetle adventure racing.
+  // (shade-0)*prim+0, (t1-0)*cmb+0
+  {0xe3f4e0f2, cc_t1_mul_prim_mul_shade},
+  // Slingshot string, zelda
+  // (shade-0)*prim+0
+  {0xe3f4e3f4, cc_prim_mul_shade},
+  // ?
+  // (shade-0)*prim+0, (cmb-0)*shade+0 ** INC **
+  {0xe3f4e4f0, cc_prim_mul_shade},
+  // ???, zelda
+  // (env-0)*prim+0, (0-0)*0+cmb
+  {0xe3f5e3f5, cc_prim_mul_env},
+  // Option selection, zelda
+  //z (1-0)*prim+0
+  {0xe3f6e3f6, cc_prim},
+  // ranco monster, zelda 2. Added by Gonetz
+  // (noise-0)*prim+0, (cmb-0)*prim_a+prim
+  {0xe3f76af0, cc_prim_mul_prima_add_prim},
+  // F-1_World_Grand_Prix_II, olivieryuyu
+  // (noise-0)*prim+0, (0-cmb)*prim_a+shade
+  {0xe3f78a0f, cc_shade_sub__prim_mul_prima},
+  // zelda 2 [Ogy]. Added by Gonetz
+  // (noise-0)*prim+0
+  {0xe3f7e3f7, cc_prim},
+  // Road rush. Added by Gonetz
+  // (0-0)*prim+0  ** INC ** ?
+  {0xe3ffe3ff, cc_prim},
+  // Letter to Kafei's mom, zelda 2. Added by Gonetz
+  // (0-0)*prim+0, (cmb-0)*shade+0
+  {0xe3ffe4f0, cc_prim_mul_shade},
+  // Jabu-Jabu's Belly, zelda. Added by Gonetz
+  // (1-t0)*shade+0, (cmb-0)*prim+0
+  {0xe416e3f0, cc_one_sub_t0_mul_prim_mul_shade},
+  // Arena, Pokemon Stadium 2
+  // (t0-prim)*shade+0
+  {0xe431e431, cc_t0_sub_prim_mul_shade},
+  // silver cave, pokemon stadium 2
+  // (t0-env)*shade+0, (cmb-prim)*shade+prim
+  {0xe4516430, cc__t0_sub_env_mul_shade__sub_prim_mul_shade_add_prim},
+  // bomb mask, zelda 2. Added by Gonetz
+  // (t0-env)*shade+0, (cmb-prim)*shade+shade ** INC **
+  {0xe4518430, cc__t0_sub_env_mul_shade__sub_prim_mul_shade},
+  // terrain, Top Gear Rally  2. Added by Gonetz
+  // (t0-env)*shade+0
+  {0xe451e451, cc_t0_sub_env_mul_shade},
+  // closes, Nightmire Creatures
+  // (1-env)*shade+0
+  {0xe456e456, 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, cc_t0_mul_shade},
+  // Monster truck madness intro. Added by Gonetz
+  // (t0-0)*shade+0, (1-0)*cmb+cmb    ** INC **
+  {0xe4f100f6, cc_t0_mul_shade},
+  // terrain, SCARS. Added by Gonetz
+  // (t0-0)*shade+0, (prim-cmb)*t0+cmb  ** INC **
+  {0xe4f10103, cc_t0_mul_shade},
+  // Boomerang circle, zelda
+  // (t0-0)*shade+0, (1-cmb)*t0+cmb
+  {0xe4f10106, cc_t0_mul_shade},
+  // THPS3.
+  // (t0-0)*shade+0, (1-0)*t0+cmb
+  {0xe4f101f6, cc_t0_mul_shade},
+  // ???, WWF No Mercy [CpuMaster]
+  // (t0-0)*shade+0, (env-cmb)*prim+cmb
+  {0xe4f10305, 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+cmb
+  {0xe4f104f2, cc__t0_mul_shade__add__t1_mul_shade},
+  // bike select, xg2. Added by Gonetz
+  // (t0-0)*shade+0, (1-cmb)*env+cmb  ** INC **
+  {0xe4f10506, cc_t0_mul_shade},
+  // a bugs life [Ogy]
+  // (t0-0)*shade+0, (cmb-0)*env+cmb
+  //    {0xe4f105f0, cc_t0_mul_env_mul_shade},
+  {0xe4f105f0, cc_t0_mul_shade},
+  // Wall, quest64
+  // (t0-0)*shade+0, (1-0)*env+cmb
+  {0xe4f105f6, cc_t0_mul_shade_add_env},
+  //lava, beetle adventure racing. Added by Gonetz
+  // (t0-0)*shade+0, (prim-cmb)*cmb_a+cmb **INC**
+  {0xe4f10703, cc_t0_mul_shade},
+  // course map, Ridge Racer. Added by Gonetz
+  // (t0-0)*shade+0, (prim-cmb)*prima+cmb **INC**
+  {0xe4f10a03, cc_t0_mul_shade},
+  // arena, custom robo. Added by Gonetz
+  // (t0-0)*shade+0, (noise-cmb)*prima+cmb **INC**
+  {0xe4f10a07, cc_t0_mul_shade},
+  // arena, custom robo 2. Added by Gonetz
+  // (t0-0)*shade+0, (0-cmb)*prima+cmb **INC**
+  {0xe4f10a0f, cc_t0_mul_shade},
+  //floor in a cave, Paper mario. Added by Gonetz
+  // (t0-0)*shade+0, (cmb-prim)*prima+cmb **INC**
+  {0xe4f10a30, cc_t0_mul_shade},
+  //beetle adventure racing. Added by Gonetz
+  // (t0-0)*shade+0, (t1-prim)*prima+cmb **INC**
+  {0xe4f10a32, cc_t0_mul_shade},
+  // Monster truck madness intro. Added by Gonetz
+  // (t0-0)*shade+0, (shade-cmb)*shade_a+cmb    ** INC **
+  {0xe4f10b04, cc_t0_mul_shade},
+  // xg2 intro. Added by Gonetz
+  // (t0-0)*shade+0, (1-cmb)*shade_a+cmb    ** INC **
+  {0xe4f10b06, cc__t0_mul_shade__inter_one_using_shadea},
+  // Link's bomb, smash bros
+  // (t0-0)*shade+0, (env-cmb)*env_a+cmb    ** INC **
+  {0xe4f10c05, cc__t0_mul_shade__inter_env_using_enva},
+  // language selection, Extreme-G XG2 (E)
+  // (t0-0)*shade+0, (1-cmb)*env_a+cmb
+  {0xe4f10c06, cc__t0_mul_shade__inter_one_using_enva},
+  // A Bugs Life, [Raziel64]
+  // (t0-0)*shade+0, (cmb-0)*k5+cmb
+  {0xe4f10ff0, cc_t0_mul_shade},
+  // Bass Rush
+  // (t0-0)*shade+0, (cmb-0)*0+cmb
+  {0xe4f11f0f, cc_t0_mul_shade},
+  // car, Top Gear Rally. Added by Gonetz
+  // (t0-0)*shade+0, (cmb-t0)*t0a+t0  **INC**
+  {0xe4f12810, cc_t0_mul_shade},
+  // logo, SCARS. Added by Gonetz
+  // (t0-0)*shade+0, (cmb-t0)*shadea+t0  **INC**
+  {0xe4f12b10, cc__t0_mul_shade_mul_shadea__add__t1_mul_one_sub_shadea},
+  // ? sign, Spiderman. Added by Gonetz
+  // (t0-0)*shade+0, (0-0)*0+t1
+  {0xe4f15fff, cc_t0_mul_shade},
+  // Major League Baseball Featuring Ken Griffey Jr.
+  // (t0-0)*shade+0, (1-0)*cmb+prim  ** INC **
+  {0xe4f160f6, cc_t0_mul_shade_add_prim},
+  // plants, CBFD. Added by Gonetz
+  // (t0-0)*shade+0, (cmb-env)*shade+prim  ** INC **
+  {0xe4f16450, cc_t0_sub_env_mul_shade_add_prim},
+  // Kirby64. Added by Gonetz
+  // (t0-0)*shade+0, (cmb-prim)*prima+prim
+  {0xe4f16a30, 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, cc_prim},
+  // tire trace, beetle adventure racing. Added by Gonetz
+  // (t0-0)*shade+0, (env-cmb)*t1+shade  **INC**
+  {0xe4f18205, cc_env_sub_shade_mul_t0_add_shade},
+  // Gold Skulltula, zelda
+  // (t0-0)*shade+0, (prim-env)*cmb+env
+  {0xe4f1a053, cc_prim_sub_env_mul_t0_mul_shade_add_env},
+  //    {0xe4f1a053, cc_t0_mul_prim_mul_shade},
+  // fighters, GASP Fighters
+  // (t0-0)*shade+0, (1-env)*cmb+env
+  {0xe4f1a056, cc_t0_mul_one_sub_env_mul_shade_add_env},
+  // Brian, quest64
+  // (t0-0)*shade+0, (cmb-0)*prim+env
+  {0xe4f1a3f0, cc_t0_mul_prim_mul_shade_add_env},
+  // Objects in arena, pokemon stadium 2
+  // (t0-0)*shade+0
+  // (cmb-prim)*shade+env
+  {0xe4f1a430, cc_t0_mul_shade},
+  // Monster truck madness intro. Added by Gonetz
+  // (t0-0)*shade+0, (cmb-env)*shadea+env  **INC**
+  //    {0xe4f1ab50, cc_t0_mul_shade_add_env},
+  {0xe4f1ab50, 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, cc_t0_mul_shade_add_env},
+  // sky in doom. Added by Gonetz
+  // (t0-0)*shade+0, (cmb-0)*primlod+env  **INC**
+  {0xe4f1aef0, cc_t0_mul_shade_add_env},
+  // fighters, GASP Fighters
+  // (t0-0)*shade+0, (1-env)*cmb+0
+  {0xe4f1e056, 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, cc_t0_mul_shade},
+  // Link's face, zelda
+  //z (t0-k5)*shade+cmb_a, (prim-k5)*cmb+cmb_a
+  {0xe4f1e0f3, cc_t0_mul_prim_mul_shade},
+  // Link's suit, zelda
+  //z (t0-k5)*shade+cmb_a, (env-k5)*cmb+cmb_a
+  {0xe4f1e0f5, cc_t0_mul_env_mul_shade},
+  // Window, starfox
+  //z (t0-k5)*shade+cmb_a, (cmb-k5)*prim+cmb_a
+  {0xe4f1e3f0, cc_t0_mul_prim_mul_shade},
+  // crystal, Doraemon 2
+  //(t0-0)*shade+0, (t0-0)*prim+0
+  {0xe4f1e3f1, cc_t0_mul_prim},
+  // Characters, mace
+  // (t0-0)*shade+0, (cmb-0)*shade+0
+  {0xe4f1e4f0, cc_t0_mul_shade},
+  // Super Mario 64 logo
+  //z (t0-k5)*shade+cmb_a
+  {0xe4f1e4f1, cc_t0_mul_shade},
+  // Kokiri's hat, zelda
+  // (t0-0)*shade+0, (cmb-0)*env+0
+  {0xe4f1e5f0, cc_t0_mul_env_mul_shade},
+  // Gauntlet Legends intro
+  // (t0-0)*shade+0, (cmb-0)*scale+0
+  {0xe4f1e6f0, cc_t0_mul_scale_mul_shade},
+  // Something on a tree, Paper Mario. Added by Gonetz
+  // (t0-0)*shade+0, (cmb-0)*prima+0
+  {0xe4f1eaf0, cc_t0_mul_prima_mul_shade},
+  // Course map, Ridge Racer. Added by Gonetz
+  // (t0-0)*shade+0, (cmb-0)*shadea+0
+  {0xe4f1ebf0, cc_t0_mul_shade_mul_shadea},
+  // Dodongo skull's eyes, zelda
+  // (t0-0)*shade+0, (cmb-0)*env_alpha+0
+  {0xe4f1ecf0, cc_t0_mul_enva_mul_shade},
+  // lava, beetle adventure racing. Added by Gonetz
+  // (t1-0)*shade+0, (cmb-prim)*cmb_a+prim  **INC**
+  {0xe4f26730, cc_prim_inter_t1_mul_shade_using_texa},
+  // headlight, beetle adventure racing. Added by Gonetz
+  // (t1-0)*shade+0, (env-cmb)*t0+shade  **INC**
+  {0xe4f28105, cc_one_sub__t0_mul_t1__mul_shade},
+  // bubble, Banjo-Kazooie. Added by Gonetz
+  // (t1-0)*shade+0
+  {0xe4f2e4f2, cc_t1_mul_shade},
+  // water, Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz
+  // (prim-0)*shade+0, (cmb-cmb)*cmb+cmb
+  {0xe4f30000, 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, cc_prim_mul_shade},
+  // Yoshi, mario golf
+  // (prim-0)*shade+0, (env-cmb)*t0+cmb
+  {0xe4f30105, cc_env_sub_primshade_mul_t0_add_primshade},
+  //Spacestation Silicon Valley intro. Added by Gonetz
+  // (prim-0)*shade+0, (env-cmb)*t1+cmb
+  {0xe4f30205, cc_env_sub_primshade_mul_t1_add_primshade},
+  // Tip of brian's hair, quest64
+  // (prim-0)*shade+0, (1-0)*env+cmb
+  {0xe4f305f6, cc_prim_mul_shade_add_env},
+  // V8-2 menu
+  // (prim-0)*shade+0, (env-cmb)*cmb_a+cmb
+  {0xe4f30705, cc__prim_mul_shade__inter_env_using__prim_mul_shade_alpha},
+  // Background circle, xg2
+  // (prim-0)*shade+0, (1-cmb)*shade_a+cmb
+  {0xe4f30b06, cc_prim_mul_shade},
+  // circle, waverace. Added by Gonetz
+  // (prim-0)*shade+0, (t0-cmb)*enva+cmb
+  {0xe4f30c01, cc_t0_sub__prim_mul_shade__mul_enva_add__prim_mul_shade},
+  // enemy hit, Glover2
+  // (prim-0)*shade+0, (env-cmb)*enva+cmb
+  {0xe4f30c05, cc__prim_mul_shade__inter_env_using_enva},
+  // player, super bowling
+  // (prim-0)*shade+0, (0-0)*k5+cmb
+  {0xe4f30fff, cc_prim_mul_shade},
+  //Lure, bass rush
+  // (prim-0)*shade+0, (0-cmb)*0+cmb
+  {0xe4f31f0f, cc_prim_mul_shade},
+  // walls, beetle adventure racing. Added by Gonetz
+  // (prim-0)*shade+0, (cmb-shade)*t1+shade   **INC**
+  {0xe4f38240, cc__one_inter_prim_using_t1__mul_shade},
+  // GASP fighters
+  //(prim-0)*shade+0, (1-env)*cmb+0
+  {0xe4f3e056, cc_prim_mul_one_sub_env_mul_shade},
+  // Flag, mario kart
+  //z (prim-k5)*shade+cmb_a
+  {0xe4f3e4f3, cc_prim_mul_shade},
+  // Characters, smash bros
+  // (prim-0)*shade+0, (cmb-0)*env+0
+  {0xe4f3e5f0, cc_prim_mul_env_mul_shade},
+  // N64 logo, ridge race. Added by Gonetz
+  // (shade-0)*shade+0, (prim-cmb)*prima+cmb **INC**
+  {0xe4f40a03, cc_shade},
+  // fighter, shield mode, bio freaks. Added by Gonetz
+  // (shade-0)*shade+0
+  {0xe4f4e4f4, cc_shade},
+  // truck crush, Monster truck madness. Added by Gonetz
+  // (env-0)*shade+0, (env-0)*shade+cmb
+  {0xe4f504f5, cc_env_mul_shade},
+  // Course map, Ridge Racer. Added by Gonetz
+  // (env-0)*shade+0
+  {0xe4f5e4f5, cc_env_mul_shade},
+  // lava, beetle adventure racing
+  // (1-0)*shade+0, (prim-cmb)*cmb_a+cmb
+  {0xe4f60703, 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, cc_prim_mul_shade},
+  // parts of vehicle, Star Wars Ep.I Racer. Added by Gonetz
+  // (1-0)*shade+0, (cmb-0)*prim+0
+  {0xe4f6e3f0, cc_prim_mul_shade},
+  // Snowflakes???, mario kart. Boxer shadow (fb effect}, Knockout Kings 2000
+  // (1-0)*shade+0, (1-0)*shade+0
+  {0xe4f6e4f6, cc_one_mul_shade},
+  // ???
+  // (noise-0)*shade+0
+  {0xe4f7e4f7, cc_shade},
+  // quest64 [Ogy]
+  // (prim-t0)*env+0, (0-0)*0+prim
+  {0xe5137fff, cc_prim},
+  // field, Mike Piazza's Strike Zone
+  // (t0-prim)*env+0 ** INC **
+  {0xe531e531, cc_t0_mul_env},
+  // Mike Piazza's Strike Zone
+  // (shade-prim)*env+0
+  {0xe534e534, cc_shade_sub_prim_mul_env},
+  // rope, CBFD. Added by Gonetz
+  // (t0-0)*env+0, (1-env)*prim+cmb
+  {0xe5f10356, 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, cc_t0_mul_env_add_prim_mul_shade},
+  // aerofighter's assault [Ogy]
+  // (t0-0)*env+0, (1-t0)*shade+cmb
+  {0xe5f10416, 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, cc_t0_mul_env},
+  // Extreme G2, score.  Added by Gonetz
+  // (t0-0)*env+0, (1-cmb)*enva+cmb  ** INC **
+  {0xe5f10c06, cc_t0_mul_env},
+  // many objects in Tonic Trouble
+  // (t0-0)*env+0, (shade-0)*cmb+0
+  {0xe5f1e0f4, cc_t0_mul_env_mul_shade},
+  // Flying skull's eyes, zelda
+  // (t0-0)*env+0, (cmb-0)*prim+0
+  {0xe5f1e3f0, cc_t0_mul_prim_mul_env},
+  // Rock spell, quest64
+  // (t0-0)*env+0, (cmb-0)*shade+0
+  {0xe5f1e4f0, cc_t0_mul_env_mul_shade},
+  // Text, mario
+  //z (t0-k5)*env+cmb_a
+  {0xe5f1e5f1, cc_t0_mul_env},
+  // kirby 64. Added by Gonetz
+  // (prim-0)*env+0, (cmb-0)*shade+0
+  {0xe5f3e4f0, cc_prim_mul_env_mul_shade},
+  // wings, kirby 64. Added by Gonetz
+  // (prim-0)*env+0
+  {0xe5f3e5f3, cc_prim_mul_env},
+  // Text, xg2
+  // (shade-0)*env+0, (1-cmb)*env_a+cmb
+  {0xe5f40c06, cc_env_mul_shade},
+  // Text box, mario
+  //z (shade-k5)*env+cmb_a
+  {0xe5f4e5f4, cc_env_mul_shade},
+  // bomberman 64 [Ogy]
+  // (1-0)*env+0
+  {0xe5f6e5f6, cc_env},
+  // Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz
+  // (1-t0)*scale+0
+  {0xe616e616, cc_zero},
+  // Gauntlet Legends intro. Added by Gonetz
+  // (t0-0)*scale+0, (cmb-0)*shade+0
+  {0xe6f1e4f0, cc_t0_mul_scale_mul_shade},
+  // shadows, Taz express. Added by Gonetz
+  // (t0-0)*scale+0
+  {0xe6f1e6f1, cc_t0_mul_scale},
+  // shadows, Knockout Kings 2000. Added by Gonetz
+  // (shade-0)*scale+0
+  {0xe6f4e6f4, cc_scale_mul_shade},
+  // bomberman 64 2 [Ogy]. Added by Gonetz
+  // (1-0)*scale+0
+  {0xe6f6e6f6, cc_scale},
+  // walls, beetle adventure racing. Added by Gonetz
+  // (t1-0)*t0_a+0, (1-t1)*cmb+t1  **INC**
+  {0xe8f24026, cc_t1},
+  // house on rancho, zelda2. Added by Gonetz
+  // (t1-0)*t0_a+0, (cmb-0)*prim+0
+  {0xe8f2e3f0, cc__t0a_mul_t1__mul_prim},
+  // zelda2 [Ogy]. Added by Gonetz
+  // (t1-0)*t0_a+0, (cmb-0)*shade+0
+  {0xe8f2e4f0, cc__t0a_mul_t1__mul_shade},
+  // mini quiz, Pokemon Stadium 2
+  // (prim-0)*t0_a+0, (cmb-t1)*primlod+t1 ** INC **
+  {0xe8f34e20, cc_t0},
+  // Major League Baseball Featuring Ken Griffey Jr.
+  // (prim-0)*t0_a+0
+  {0xe8f3e8f3, cc_t0a_mul_prim},
+  // Top Gear Hyper-Bike
+  // (1-0)*t0_a+0
+  {0xe8f6e8f6, cc_t0a},
+  // waterfall,  Dobutsu_no_Mori
+  // (t0-0)*t1_a+0, (prim-env)*cmb+env
+  {0xe9f1a053, cc_prim_sub_env_mul__t0_mul_t1a__add_env},
+  // logo, Deadly Arts. Added by Gonetz
+  // (t0-0)*t1_a+0, (cmb-0)*shade+0
+  {0xe9f1e4f0, cc__t0_mul_t1a__mul_shade},
+  // car, Roadsters. Added by Gonetz
+  // (prim-t0)*prim_a+0, (prim-cmb)*shade+0  ** INC **
+  {0xea13e403, 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, cc_t0_mul_prim},
+  // V8-2
+  // (1-prim)*prim_a+0
+  {0xea36ea36, cc_one_sub_prim_mul_prima},
+  // match start, Mario Tennis. Added by Gonetz
+  // (t0-0)*prim_a+0, (1-t0)*cmb+t0  ** INC **
+  {0xeaf12016, cc_one_sub_t0_mul_prima_add_t0},
+  // blast corps [Ogy]
+  // (t0-0)*prim_a+0
+  {0xeaf1eaf1, cc_t0_mul_prima},
+  // final battle, CBFD. Added by Gonetz
+  // (prim-0)*prim_a+0
+  {0xeaf3eaf3, cc_prim_mul_prima},
+  // flower's stalk, Paper Mario. Added by Gonetz
+  // (shade-0)*prim_a+0
+  {0xeaf4eaf4, cc_shade_mul_prima},
+  // blast corps [Ogy]
+  // (noise-0)*prim_a+0, (t1-0)*shade+cmb   ** INC **
+  {0xeaf704f2, cc_t0_mul_shade_add_prima},
+  // F1 World Grand Prix. Added by Gonetz
+  // (noise-0)*prim_a+0, (t1-0)*env_a+cmb   ** INC **
+  {0xeaf70cf2, cc_t1_mul_enva},
+  // shadows, killer instinct gold
+  // (0-0)*prim_a+0
+  {0xeaffeaff, cc_zero},
+  // background, killer instinct gold
+  // (t0-prim)*shade_a+0
+  {0xeb31eb31, cc_t0_sub_prim_mul_shadea},
+  // ground, C&C
+  // (t0-shade)*shade_a+0
+  {0xeb41eb41, cc_t0_sub_shade_mul_shadea},
+  // Wreslters, WWF No Mercy, [CpUMasteR]
+  // (t0-0)*shade_alpha+0, (env-cmb)*prim+cmb
+  {0xebf10305, 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, 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, cc_t0_mul_shadea_add_shade},
+  // logo, WCW-nWo Revenge
+  // (t0-0)*shade_alpha+0, (cmb-0)*prim+0
+  {0xebf1e3f0, cc_t0_mul_prim_mul_shadea},
+  // sky, pilot wings
+  // (t0-0)*shade_alpha+0, (1-cmb)*shade+0
+  {0xebf1e406, cc_one_sub__t0_mul_shadea__mul_shade},
+  // Wrestlers in Game, WWF No mercy [CpUMasteR]
+  // (t0-0)*shade_alpha+0
+  {0xebf1ebf1, cc_t0_mul_shadea},
+  // flag, top gear overdrive
+  // (prim-0)*shade_alpha+0
+  {0xebf3ebf3, cc_prim_mul_shadea},
+  // Ropes, WWF games
+  // (shade-0)*shade_alpha+0, (env-cmb)*prim+cmb
+  {0xebf40305, cc_shade_mul_shadea},
+  // Ropes, WWF games
+  // (shade-0)*shade_alpha+0
+  {0xebf4ebf4, cc_shade_mul_shadea},
+  // arena, custom robo 2
+  // (noise-0)*shade_alpha+0
+  {0xebf7ebf7, cc_shadea},
+  // Baton Pass attack, Pokemon Stadium 2
+  // (t0-env)*enva+0, (shade-0)*prim+cmb
+  {0xec5103f4, cc__t0_sub_env_mul_enva__add_prim_mul_shade},
+  // Bell, Pokemon Stadium 2. Added by Gonetz
+  // (t0-0)*enva+0, (shade-0)*prim+cmb
+  {0xecf103f4, cc_t0_mul_enva_add_prim_mul_shade},
+  // blastcorps, unimp log. Added by Gonetz
+  // (t0-0)*enva+0
+  {0xecf1ecf1, cc_t0_mul_enva},
+  // car, Top Gear Rally. Added by Gonetz
+  // (env-0)*enva+0
+  {0xecf5ecf5, cc_env_mul_enva},
+  // Sand attack, pokemon Stadium (J)
+  // (noise-0)*enva+0, (prim-env)*cmb+env
+  {0xecf7a053, cc_prim_sub_env_mul_enva_add_env},
+  // Walls of well through lens of truth, zelda
+  // (prim-t0)*primlod+0      ** INC **
+  {0xee13ee13, cc_t0},   // JUST t0 b/c the other combiner handles the subtraction
+  // Pokemon attack, Pokemon Stadium 2
+  // (noise-t0)*primlod+0, (1-env)*cmb+env ** INC **
+  {0xee17a056, cc_env_inter_one_using__one_sub_t0_mul_primlod},
+  // barrage attack, Pokemon Stadium 2
+  // (t0-0)*primlod+0, (prim-0)*shade+cmb
+  {0xeef104f3, cc__t0_mul_primlod__add__prim_mul_shade},
+  // something on a flor in stone temple, zelda 2. Added by Gonetz
+  // (t0-0)*primlod+0, (cmb-0)*prim+0
+  {0xeef1e3f0, 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, 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, cc_prim_sub_env_mul_primlod_add_env},
+  // pokemon attack, Pokemon Stadium 2. Added by Gonetz
+  // (noise-0)*primlod+0, (prim-cmb)*cmb+0  ** INC **
+  {0xeef7e003, cc_zero},
+  // Night trees, Monster truck madness. Added by Gonetz
+  // (t0-0)*k5+0
+  {0xeff1eff1, cc_t0_mul_k5},
+  // submitted by gokuss4
+  // (0-0)*0+0, (0-0)*0+prim
+  {0xfffd5fe6, cc_prim},
+  // intro, Bettle Adventure Racing, [Raziel64]
+  // (0-0)*0+0, (0-0)*0+t0
+  {0xffff3fff, cc_t0},
+  // Conker's face, CBFD
+  // (0-0)*0+0, (shade-env)*k5+prim
+  {0xffff6f54, cc_shade_sub_env_mul_k5_add_prim},
+  // Boost, Beetle Adventure Racing. Added by Gonetz
+  // (0-0)*0+0, (0-0)*0+prim
+  {0xffff7fff, cc_prim},
+  // headlight, beetle adventure racing. Added by Gonetz
+  // (0-0)*0+0, (0-0)*0+shade
+  {0xffff9fff, cc_shade},
+  // intro, Bettle Adventure Racing, [Raziel64]
+  // (0-0)*0+0, (shade-env)*t1+env
+  {0xffffa254, 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, cc_env},
+  // Waterfall, Donkey Kong 64
+  // (0-0)*0+0, (t0-0)*t1+0
+  {0xffffe1f2, cc_t0_mul_t1},
+  // Screen clear, banjo kazooie
+  // (0-0)*0+0
+  {0xffffffff, cc_zero},
+  // { #CCEND }
+};
+
+static COMBINER alpha_cmb_list[] = {
+  // { #ACSTART }
+  //Tony Hawk's Pro Skater. Added by Gonetz
+  // (0-0)*0+0
+  {0x01ff01ff, ac_zero},
+  //terminal, Spacestation Silicon Valley. Added by Gonetz
+  // (0-0)*0+0, (0-0)*0+prim
+  {0x01ff07ff, ac_prim},
+  // kirby drill, kirby 64. Added by Gonetz
+  // (0-0)*0+cmb, (0-0)*0+1
+  {0x01ff0dff, ac_one},
+  //chip in Spacestation Silicon Valley intro. Added by Gonetz
+  // (0-0)*0+cmb, (prim-0)*shade+0
+  {0x01ff0f3b, ac_prim_mul_shade},
+  //Goldeneye, [Jeremy]. Added by Gonetz
+  // (t0-t0)*lodf+t0, (cmb-0)*prim+0
+  {0x02090ef8, ac_t0_mul_prim},
+  // Indy Racing 2000. Added by Gonetz
+  // (t1-t0)*lodf+t0, (env-cmb)*prim+cmb  ** INC **
+  {0x020a00c5, ac_t0_inter_t1_using_primlod},
+  // water, Spacestation Silicon Valley. Added by Gonetz
+  // (t1-t0)*lodf+t0, (0-shade)*0+cmb
+  {0x020a01e7, ac_t0_inter_t1_using_primlod},
+  // Bridge, sf rush
+  //z (t1-t0)*lodf+t0
+  {0x020a020a, ac_t0_inter_t1_using_primlod},
+  // explosion, body harvest. Added by Gonetz
+  //(t1-t0)*lodf+t0, (0-0)*0+t0
+  {0x020a03ff, ac_t0},
+  // cars, PD intro. Added by Gonetz
+  // (t1-t0)*lodf+t0, (cmb-0)*shade+prim
+  {0x020a0738, ac__t0_inter_t1_using_primlod__mul_shade_add_prim},
+  // Rocket Robot in Wheels intro
+  //(t1-t0)*lodf+t0, (0-0)*0+prim
+  {0x020a07ff, ac_prim},
+  // Iguana background ground, turok
+  // (t1-t0)*lodf+t0, (0-0)*0+shade
+  {0x020a09ff, ac_shade},
+  // Ground, monster truck madness
+  // (t1-t0)*lodf+t0, (0-0)*0+env
+  {0x020a0bff, ac_env},
+  // Taz express. Added by Gonetz
+  // (t1-t0)*lodf+t0, (0-0)*0+1
+  {0x020a0dff, ac_one},
+  // Mike Piazza's Strike Zone
+  // (t1-t0)*lodf+t0, (cmb-0)*t0+0
+  {0x020a0e78, ac_t0_inter_t1_using_primlod},
+  // N64 logo, tetrisphere. Added by Gonetz
+  // (t1-t0)*lodf+t0, (cmb-0)*prim+0
+  {0x020a0ef8, ac__t0_inter_t1_using_primlod__mul_prim},
+  // Ground, mace
+  // (t1-t0)*lodf+t0, (cmb-0)*shade+0
+  //    {0x020a0f38, ac_t0_mul_shade},
+  {0x020a0f38, ac__t0_inter_t1_using_primlod__mul_shade},
+  // blast corps [Ogy]
+  // (t1-t0)*lodf+t0, (cmb-0)*env+0
+  {0x020a0f78, ac__t0_inter_t1_using_primlod__mul_env},
+  // blast corps [Ogy]
+  // (t1-t0)*lodf+t0, (t0-0)*env+0
+  {0x020a0f79, ac_t0_mul_env},
+  // blast corps. Added by Gonetz
+  // (t1-t0)*lodf+t0, (shade-0)*env+0
+  {0x020a0f7c, ac_env_mul_shade},
+  // field, Mike Piazza's Strike Zone
+  // (t1-t0)*lodf+t0, (0-0)*0+0
+  {0x020a0fff, ac_t0_inter_t1_using_primlod},
+  // blast corps, unimp log. Added by Gonetz
+  // (t1-t0)*t0+t0
+  {0x024a024a, ac_t0_inter_t1_using_t0a},
+  // zelda 2 [Ogy]. Added by Gonetz
+  // (t1-t0)*t0+t0, (cmb-0)*prim+0    **INC**
+  {0x024a0ef8, 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, ac_t0},
+  // enemy's shot, battle tanks 2
+  // (env-prim)*t0+t0  **INC**
+  {0x025d025d, ac_t0},
+  //Bowser in final battle, Paper Mario. Added by Gonetz
+  // (t1-env)*t0+t0, (cmb-env)*prim+0  ** INC **
+  {0x026a0ee8, ac__t0_mul_t1__mul_prim},
+  // paper mario. Added by Gonetz
+  // (t1-env)*t0+t0, (cmb-0)*prim+0  ** INC **
+  {0x026a0ef8, ac__t0_mul_t1__mul_prim},
+  // V8-2
+  // (prim-0)*t0+t0
+  {0x027b027b, ac_t0_mul_prim_add_t0},
+  // THPS3. Added by Gonetz
+  // (0-0)*t0+t0
+  {0x027f027f, ac_t0},
+  // zelda 2. Added by Gonetz
+  // (0-0)*t0+t0, (cmb-0)*prim+0
+  {0x027f0ef8, ac_t0_mul_prim},
+  // Spider Web attack, Pokemon Stadium 2.
+  // (t1-t0)*t1+t0, (cmb-0)*prim+cmb
+  {0x028a00f8, ac__t0_inter_t1_using_t1a__mul_prim_add__t0_inter_t1_using_t1a},
+  // teleportation, Spacestation Silicon Valley. Added by Gonetz
+  // (t1-t0)*t1+t0
+  {0x028a028a, ac_t0_inter_t1_using_t1a},
+  // mega shock, paper mario. Added by Gonetz
+  // (t1-t0)*t1+t0, (cmb-0)*prim+0
+  {0x028a0ef8, ac__t0_inter_t1_using_t1a__mul_prim},
+  // mini game, Pokemon Stadium 2
+  // (t1-t0)*t1+t0, (cmb-0)*shade+0
+  {0x028a0f38, ac__t0_inter_t1_using_t1a__mul_shade},
+  // Magnitude, pokemon stadium 2
+  // (shade-t0)*t1+t0, (cmb-0)*shade+env
+  {0x028c0b38, ac__t0_mul_t1__mul_shade},
+  // paper mario. Added by Gonetz
+  // (1-t0)*t1+t0, (t1-0)*prim+0  ** INC **
+  {0x028e0efa, ac__one_sub_t0_mul_t1_add_t0__mul_prim},
+  //    {0x028e0efa, ac_t1_mul_prim},
+  // Spider Web attack, Pokemon Stadium 2.
+  // (1-t0)*t1+t0, (cmb-0)*shade+0  ** INC **
+  {0x028e0f38, ac__one_sub_t0_mul_t1_add_t0__mul_prim},
+  // paper mario. Added by Gonetz
+  // (t1-env)*t1+t0, (cmb-0)*shade+0
+  {0x02aa0f38, 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, ac__env_sub_one_mul_t1_add_t0__mul_prim},
+  // first screen, castlevania. Added by Gonetz
+  // (env-0)*t1+t0    **INC**
+  {0x02bd02bd, ac_t0},
+  // enemy's shot, battle tanks 2 [Flash]
+  // (1-0)*t1+t0, (0-0)*0+env
+  {0x02be0bff, ac_env},
+  // battle tanks 2 [Ogy]
+  // (1-0)*t1+t0, (0-0)*0+1
+  {0x02be0dff, ac_one},
+  // menu screen, Rayman2. Added by Gonetz
+  // (1-0)*t1+t0, (cmb-0)*shade+0
+  {0x02be0f38, ac__t0_add_t1__mul_shade},
+  // Sky, zelda
+  //z (t1-t0)*prim+t0
+  {0x02ca02ca, ac_t0_inter_t1_using_prima},
+  // F1 World Grand Prix. Added by Gonetz
+  // (t1-t0)*prim+t0, (0-0)*0+1
+  {0x02ca0dff, ac_t0_inter_t1_using_prima},
+  // logo, PD. Added by Gonetz
+  // (t1-t0)*prim+t0, (cmb-0)*shade+0
+  {0x02ca0f38, ac__t0_inter_t1_using_prima__mul_shade},
+  // battle tanks [Ogy]
+  // (t1-t0)*prim+t0, (cmb-0)*env+0
+  {0x02ca0f78, ac__t0_inter_t1_using_prima__mul_env},
+  // logo, Deadly Arts. Added by Gonetz
+  // (env-t0)*prim+t0
+  {0x02cd02cd, ac_one_sub_prim_mul_t0_add__prim_mul_env},
+  // intro, castlevania 2. Added by Gonetz
+  // (1-t0)*prim+t0
+  {0x02ce02ce, 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, ac_t0_mul_shade},
+  // submitted by Scorpiove, mario party 1
+  // (0-t0)*prim+t0
+  {0x02cf02cf, ac_one_sub_prim_mul_t0},
+  // Pokemon attack, pokemon Stadium (J)
+  // (t1-t1)*prim+t0, (prim-0)*lod_f+env **INC**
+  {0x02d20a3b, ac_env},
+  // Ground, pokemon stadium 2
+  // (t0-0)*prim+t0
+  {0x02f902f9, ac_t0_mul_prim},
+  // GASP Fighters
+  // (t1-0)*prim+t0,  ** INC **
+  {0x02fa02fa, ac_t1_mul_prim_add_t0},
+  // foresight attack, Pokemon Stadium 2
+  // (t1-0)*prim+t0, (cmb-env)*shade+0
+  {0x02fa0f28, ac__t1_mul_prima_add_t0__sub_env_mul_shade},
+  // Earthquake pokemon attack, Pokemon Stadium 2 [gokuss4]. Added by Gonetz
+  // (t1-0)*prim+t0, (cmb-0)*shade+0
+  {0x02fa0f38, ac__t1_mul_prima_add_t0__mul_shade},
+  // Paper Mario, fortune teller
+  // (t1-0)*prim+t0, (cmb-0)*env+0
+  {0x02fa0f78, ac__t1_mul_prima_add_t0__mul_env},
+  // Hydro Pump Attack, Pokemon Stadium.
+  // (shade-0)*prim+t0, (cmb-0)*shade+0
+  {0x02fc0f38, ac__t0_add_prim_mul_shade__mul_shade},
+  // map, Ogre Battle 64. Added by Gonetz
+  // (1-0)*prim+t0
+  {0x02fe02fe, ac_t0_add_prim},
+  // borders, Tony Hawk's Pro Skater 2. Added by Gonetz
+  // (t1-t0)*shade+t0 ** INC **
+  {0x030a030a, ac_t0_inter_t1_using_shadea},
+  // Mickey USA
+  // (t1-t0)*shade+t0, (cmb-0)*prim+0 ** INC **
+  {0x030a0ef8, ac__t0_inter_t1_using_shadea__mul_prim},
+  // Rocket Robot in Wheels intro
+  // (t1-t0)*shade+t0, (cmb-0)*env+0 ** INC **
+  {0x030a0f78, 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, ac_t0_mul_shade},
+  // sky, f-zero x
+  // (0-t0)*shade+t0
+  {0x030f030f, ac_one_sub_shade_mul_t0},
+  // Deku tree from kokiri villiage, zelda
+  //z (t1-t0)*env+t0, (t1-0)*primlod+cmb
+  {0x034a01ba, ac_t0_inter_t1_using_enva},
+  // Hearts, zelda
+  //z (t1-t0)*env+t0
+  {0x034a034a, ac_t0_inter_t1_using_enva},
+  // Faries, zelda
+  //z (t1-t0)*env+t0, (cmb-0)*prim+0
+  {0x034a0ef8, ac__t0_inter_t1_using_enva__mul_prim},
+  // zelda, waterfall. Added by Gonetz
+  //z (t1-t0)*env+t0, (cmb-0)*shade+0
+  {0x034a0f38, ac__t0_inter_t1_using_enva__mul_shade},
+  // pokemon stadium 1. Added by Gonetz
+  //(t1-t0)*env+t0, (cmb-0)*primlod+0
+  {0x034a0fb8, ac__t0_inter_t1_using_enva__mul_primlod},
+  // fruits, Yoshi Story. Added by Gonetz
+  //(prim-t0)*env+t0
+  {0x034b034b, ac_prim_sub_t0_mul_env_add_t0},
+  // window, Rayman2. Added by Gonetz
+  //(1-t0)*env+t0
+  {0x034e034e, ac_one_sub_t0_mul_env_add_t0},
+  // menu, PokemonStadium1, [Raziel64]
+  //(1-t0)*env+t0, (cmb-0)*shade+0  ** INC **
+  {0x034e0f38, ac_t0_mul_shade},
+  // Ganon's sword swinging, zelda
+  // (t0-t1)*env+t0, (cmb-0)*prim+0 ** INC **
+  {0x03510ef8, 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, ac_t0_mul_t1},
+  // Reflected fire at kotake & koume's, zelda
+  // (t0-1)*env+t0, (cmb-0)*prim+0  ** INC **
+  {0x03710ef8, ac__t0_sub_one_mul_enva_add_t0__mul_prim},
+  // thing that escapes from the well, zelda
+  // (t1-1)*env+t0  ** INC **
+  {0x03720372, ac_t1_sub_one_mul_enva_add_t0},
+  // Sword charge, zelda
+  // (t1-1)*env+t0, (cmb-0)*prim+0
+  {0x03720ef8, 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, ac__t1_sub_one_mul_enva_add_t0__mul_shade},
+  // Tony Hawk's Pro Skater 3. Added by Gonetz
+  // (t0-0)*env+t0
+  {0x03790379, ac_t0_mul_env},
+  // paper mario. Added by Gonetz
+  // (t0-0)*env+t0, (cmb-0)*prim+0
+  {0x03790ef8, ac_t0_mul_prim},
+  // pads, Pokemon Stadium 2. Added by Gonetz
+  // (t1-0)*env+t0, (cmb-0)*prim+env ** INC **
+  {0x037a0af8, ac__t0_inter_t1_using_enva__mul_prim_add_env},
+  // attack, Pokemon Stadium 2
+  // (t1-0)*env+t0, (cmb-t0)*prim+0  ** INC **
+  {0x037a0ec8, ac__t1_mul_enva_add_t0__mul_prim},
+  // Ice arrow gfx, zelda
+  // (t1-0)*env+t0, (cmb-0)*prim+0
+  {0x037a0ef8, ac__t1_mul_enva_add_t0__mul_prim},
+  // Scary face move, pokemon stadium 2
+  // (t1-0)*env+t0, (cmb-prim)*shade+0
+  {0x037a0f18, ac__t1_mul_enva_add_t0__sub_prim_mul_shade},
+  // Saria's song, zelda
+  // (t1-0)*env+t0, (cmb-0)*shade+0
+  {0x037a0f38, ac__t1_mul_enva_add_t0__mul_shade},
+  // eye drops bottle, zelda
+  // (t0-t0)*prim_lodfrac+t0
+  {0x03890389, ac_t0},
+  // lighthouse's beam, zelda 2. Added by Gonetz
+  // (t0-t0)*prim_lodfrac+t0, (cmb-0)*prim+0
+  {0x03890ef8, ac_t0_mul_prim},
+  // zelda 2. Added by Gonetz
+  // (t1-t0)*primlod+t0, (cmb-0)*env+cmb  ** INC **
+  {0x038a0178, 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, ac_t0_inter_t1_using_primlod},
+  // Sunny Day, Pokemon Stadium 2
+  // (t1-t0)*primlod+t0, (cmb-0)*0+prim
+  {0x038a07f8, ac_prim},
+  //attack, Pokemon Stadium 2
+  // (t1-t0)*primlod+t0, (cmb-env)*shade+shade ** INC **
+  {0x038a0928, ac__t0_inter_t1_using_primlod__sub_env_mul_shade_add_shade},
+  // blastcorps, unimp log. Added by Gonetz
+  // (t1-t0)*primlod+t0, (0-0)*0+shade  **INC**?
+  {0x038a09ff, ac_t0_inter_t1_using_primlod},
+  // pokemon attack, pokemon monsters (J)
+  // (t1-t0)*primlod+t0, (cmb-0)*prim+env
+  {0x038a0af8, ac__t0_inter_t1_using_primlod__mul_prim_add_env},
+  // sky, PGA European Tour
+  // (t1-t0)*primlod+t0, (0-0)*0+1
+  {0x038a0dff, ac_one},
+  // Ice surrounding enemy, zelda
+  // (t1-t0)*primlod+t0, (env-0)*lodf+0
+  {0x038a0e3d, 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, ac_t0_inter_t1_using_primlod},
+  // zelda 2, [Ogy]. Added by Gonetz
+  // (t1-t0)*primlod+t0, (cmb-0)*t1+0
+  {0x038a0eb8, ac_t0_inter_t1_using_primlod},
+  // Kirby's pool, smash bros
+  // (t1-t0)*primlod+t0, (cmb-0)*prim+0
+  {0x038a0ef8, ac__t0_inter_t1_using_primlod__mul_prim},
+  // Samus stage fire, smash bros
+  // (t1-t0)*primlod+t0, (cmb-0)*shade+0
+  {0x038a0f38, ac__t0_inter_t1_using_primlod__mul_shade},
+  // something about ice, zelda
+  // (t1-t0)*primlod+t0, (cmb-0)*env+0
+  {0x038a0f78, ac__t0_inter_t1_using_primlod__mul_env},
+  // Blast Corps. Added by Gonetz
+  // (t1-t0)*primlod+t0, (shade-0)*env+0
+  {0x038a0f7c, ac_env_mul_shade},
+  // goals, J. League Tactics Soccer. Added by Gonetz
+  // (prim-t0)*primlod+t0  ** INC **
+  {0x038b038b, ac_t0},
+  // zelda 2, [Ogy]. Added by Gonetz
+  // (t0-t1)*primlod+t0, (cmb-0)*prim+0
+  {0x03910ef8, 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, ac_t0_mul_prim},
+  // zelda 2. Added by Gonetz
+  // (t1-prim)*primlod+t0, (cmb-0)*prim+0  ** INC **
+  {0x039a0ef8, 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, ac__t1_sub_shade_mul_primlod_add_t0__mul_shade},
+  // saffron city, Pokemon Stadium 2
+  // (t1-1)*primlod+t0, (cmb-0)*0+cmb
+  {0x03b201f8, ac_t1_sub_one_mul_primlod_add_t0},
+  // Candle flame in ganon's castle, zelda
+  // (t1-1)*primlod+t0
+  {0x03b203b2, ac_t1_sub_one_mul_primlod_add_t0},
+  // Fire, zelda
+  //z (t1-1)*primlod+t0, (cmb-0)*prim+0   ** INC **
+  {0x03b20ef8, 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, ac_t0_mul_prim},
+  // Din's fire, zelda
+  // (t1-1)*prim_lodfrac+t0, (cmb-0)*shade+0  ** INC **
+  {0x03b20f38, ac__t1_sub_one_mul_primlod_add_t0__mul_shade},
+  // Fire cloud, zelda
+  // (t1-1)*prim_lodfrac+t0, (cmb-0)*env+0  ** INC **
+  {0x03b20f78, 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, ac__prim_sub_one_mul_primlod_add_t0__mul_env},
+  // fairy's spirit, zelda oot
+  // (t0-0)*primlod+t0
+  {0x03b903b9, ac_t0_mul_primlod_add_t0},
+  // Scary face, pokemon stadium 2
+  // (t0-0)*primlod+t0, (cmb-0)*prim+0
+  {0x03b90ef8, ac_t0_mul_prim},
+  // Magnitude attack, Pokemon Stadium 2
+  // (t0-0)*primlod+t0, (cmb-0)*shade+0
+  {0x03b90f38, ac__t0_mul_primlod_add_t0__mul_shade},
+  // Leftovers Recovery, Pokemon Stadium 2 [gokuss4]. Added by Gonetz
+  // (t1-0)*prim_lodfrac+t0, (cmb-env)*prim+0  ** INC **
+  {0x03ba0ee8, 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, ac__t1_mul_primlod_add_t0__mul_prim},
+  // Mega punch attack, Pokemon Stadium 2
+  // (t1-0)*prim_lodfrac+t0, (cmb-prim)*shade+0
+  {0x03ba0f18, ac__t1_mul_primlod_add_t0__sub_prim_mul_shade},
+  // zelda 2 [Ogy]. Added by Gonetz
+  // (t1-0)*prim_lodfrac+t0, (cmb-0)*shade+0
+  {0x03ba0f38, 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, ac__t1_mul_primlod_add_t0__mul_env},
+  // Scary face, pokemon stadium 2
+  // (env-0)*primlod+t0, (cmb-0)*prim+0
+  {0x03bd0ef8, ac_t0_mul_prim},
+  // ground, zelda 2. Added by Gonetz
+  // (t1-t0)*0+t0, (cmb-0)*0+cmb
+  {0x03ca01f8, ac_t0},
+  // zelda 2. Added by Gonetz
+  // (t1-t0)*0+t0, (cmb-0)*prim+0
+  {0x03ca0ef8, ac_t0_mul_prim},
+  // smoke in a night, zelda 2. Added by Gonetz
+  // (t1-t0)*0+t0, (cmb-0)*shade+0
+  {0x03ca0f38, 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, ac_t0_mul_env},
+  //something on level 5, Kirby64 [Raziel64]
+  //(t0-0)*0+t0
+  {0x03f903f9, ac_t0},
+  //spider house, zelda 2 [Ogy]. Added by Gonetz
+  //(t0-0)*0+t0, (cmb-0)*prim+0
+  {0x03f90ef8, ac_t0_mul_prim},
+  //Darmani's fire spin, zelda 2 [Ogy]. Added by Gonetz
+  //(t1-0)*0+t0, (cmb-0)*prim+0
+  {0x03fa0ef8, ac_t0_mul_prim},
+  // headlight, beetle adventure racing. Added by Gonetz
+  //(1-0)*0+t0
+  {0x03fe03fe, ac_t0},
+  // player, super bowling
+  // (0-0)*0+t0,
+  {0x03ff0000, ac_t0},
+  // Ghost's lantern, zelda
+  // (0-0)*0+t0, (t1-0)*prim_lod+cmb
+  {0x03ff01ba, ac_t1_mul_primlod_add_t0},
+  // Hand cursor, mario
+  //z (0-0)*0+t0
+  {0x03ff03ff, ac_t0},
+  // Taz express. Added by Gonetz
+  // (0-0)*0+t0, (0-0)*0+t1
+  {0x03ff05ff, ac_t0},
+  // powder keg, zelda2. Added by Gonetz
+  // (0-0)*0+t0, (0-0)*0+prim
+  {0x03ff07ff, ac_t0},
+  // water, Spacestation Silicon Valley. Added by Gonetz
+  // (0-0)*0+t0, (0-0)*0+shade
+  {0x03ff09ff, ac_t0},
+  // Characters, Ogre Battle. Added by Gonetz.
+  // (0-0)*0+t0, (cmb-0)*prim+env
+  {0x03ff0af8, ac_t0_mul_prim_add_env},
+  // Monster truck madness intro. Added by Gonetz
+  // (0-0)*0+t0, (0-0)*0+env
+  {0x03ff0bff, ac_t0},
+  // Battlezone
+  // (0-0)*0+t0, (0-0)*0+1
+  {0x03ff0dff, ac_t0},
+  // Zoras, zelda
+  // (0-0)*0+t0, (env-0)*lodf+0
+  {0x03ff0e3d, ac_env},
+  // logo, v-rally 99
+  // (0-0)*0+t0, (prim-0)*t0+0
+  {0x03ff0e7b, ac_t0_mul_prim},
+  // intro, WWF-War Zone
+  // (0-0)*0+t0, (env-0)*t0+0
+  {0x03ff0e7d, ac_t0_mul_env},
+  // Window, starfox
+  //z (0-0)*0+t0, (cmb-0)*prim+0
+  {0x03ff0ef8, ac_t0_mul_prim},
+  //beetle adventure racing. Added by Gonetz
+  // (0-0)*0+t0, (cmb-0)*shade+0
+  {0x03ff0f38, ac_t0_mul_shade},
+  //  Wonder Project J2 logo. Added by Gonetz
+  // (0-0)*0+t0, (t0-0)*shade+0
+  {0x03ff0f39, ac_t0_mul_shade},
+  // Saria's suit, zelda
+  // (0-0)*0+t0, (cmb-0)*env+0
+  {0x03ff0f78, ac_t0_mul_env},
+  // Pokemon Stadium 2, [Jeremy]. Added by Gonetz
+  // (0-0)*0+t0, (cmb-0)*primlod+0
+  {0x03ff0fb8, ac_t0_mul_primlod},
+  // Tony Hawk's Pro Skater. Added by Gonetz
+  // (0-0)*0+t0, (0-0)*0+0
+  {0x03ff0fff, ac_zero},
+  // Spider Web attack, Pokemon Stadium 2.
+  // (t0-t1)*t0+t1, (cmb-0)*prim+cmb   **INC**
+  {0x045100f8, ac__t1_inter_t0_using_t0a__mul_prim_add__t1_inter_t0_using_t0a},
+  // Powered Star Beam, Paper Mario. Added by Gonetz
+  // (t0-t1)*t0+t1, (cmb-0)*prim+0   **INC**
+  {0x04510ef8, ac__t1_inter_t0_using_t0a__mul_prim},
+  // Deadly Arts logo. Added by Gonetz
+  // (1-0)*t0+t1, (1-0)*prim+cmb
+  {0x047e00fe, ac__t0_add_t1__add_prim},
+  // Spiderman. Added by Gonetz
+  // (1-0)*t0+t1
+  {0x047e047e, ac_t0_add_t1},
+  // water, Dobutsu no Mori. Added by Gonetz
+  // (1-0)*t0+t1, (cmb-0)*primlod+prim
+  {0x047e07b8, ac__t0_add_t1__mul_primlod_add_prim},
+  // paper mario. Added by Gonetz
+  // (1-t0)*t1+t1, (cmb-0)*t1+0  **INC**
+  {0x048e0eb8, ac_t0_mul_t1},
+  // Pokemon Stadium 2. Added by Gonetz
+  // (t0-prim)*t1+t1, (cmb-0)*shade+0  **INC**
+  {0x04990f38, ac_t1_mul_shade},
+  // waterfall, Dobutsu no Mori. Added by Gonetz
+  // (t0-0)*t1+t1
+  {0x04b904b9, ac_t0_mul_t1_add_t1},
+  // light, Dobutsu no Mori. Added by Gonetz
+  // (t0-0)*t1+t1, (cmb-0)*primlod+0  ** INC **
+  {0x04b90fb8, ac__t0_add_t1__mul_primlod},
+  // lava, beetle adventure racing
+  // (t1-0)*t1+t1, (cmb-0)*shade+0  ** INC **
+  {0x04ba0f38, ac__t1_mul_t1_add_t1__mul_shade},
+  // wheels, F1 World Grand Prix. Added by Gonetz
+  // (t0-t1)*prim+t1
+  {0x04d104d1, ac_t1_inter_t0_using_prima},
+  // intro, castlevania 2. Added by Gonetz
+  // (t0-t1)*prim+t1, (cmb-0)*shade+0
+  {0x04d10f38, ac__t1_inter_t0_using_prima__mul_shade},
+  // flame, castlevania 2. Added by Gonetz
+  // (t0-t1)*prim+t1, (cmb-0)*env+0
+  {0x04d10f78, ac__t1_inter_t0_using_prima__mul_env},
+  // walls, beetle adventure racing. Added by Gonetz
+  // (t0-0)*prim+t1  **INC**
+  {0x04f904f9, ac_t0_mul_prim},
+  // Reflect pokemon attack, Pokemon Stadium 2 [gokuss4]. Added by Gonetz
+  // (t0-0)*prim+t1, (cmb-0)*prim+env  **INC**
+  {0x04f90af8, 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, ac__t0_add_t1__mul_shade},
+  // Rayman2. Added by Gonetz
+  // (0-0)*shade+t1, (cmb-0)*env+0
+  {0x053f0f78, ac_t1_mul_env},
+  // Ground at kotake & koume, zelda
+  // (t1-t0)*env+t1, (cmb-0)*prim+0 ** INC **
+  {0x054a0ef8, ac__t1_sub_t0_mul_enva_add_t1__mul_prim},
+  // Tony Hawk's Pro Skater. Added by Gonetz
+  // (t0-t1)*env+t1
+  {0x05510551, ac_t1_inter_t0_using_enva},
+  // Shiek's disappearance, zelda
+  // (t0-1)*env+t1
+  {0x05710571, 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, ac__t0_sub_one_mul_enva_add_t1__mul_prim},
+  // Gauntlet Legends intro
+  // (t0-0)*env+t1, (cmb-0)*prim+0  ** INC **
+  {0x05790ef8, ac__t0_add_t1__mul_prim},
+  // Zelda opening door, zelda
+  // (t0-0)*env+t1, (cmb-0)*shade+0
+  {0x05790f38, ac_t1_mul_shade},
+  // paper mario. Added by Gonetz
+  // (t1-0)*env+t1, (cmb-0)*prim+0  ** INC **
+  {0x057a0ef8, ac_t1_mul_prim},
+  // pokemon attack, Pokemon Stadium 2. Added by Gonetz
+  // (t0-t1)*prim_lod+t1, (cmb-0)*prim+0
+  {0x05910ef8, ac__t1_inter_t0_using_primlod__mul_prim},
+  // Skulltula coin, zelda
+  // (t0-1)*primlod+t1              ** INC **
+  {0x05b105b1, ac_t0_mul_t1},
+  // Bell, Pokemon Stadium 2. Added by Gonetz
+  // (t0-0)*primlod+t1, (cmb-env)*prim  ** INC **
+  {0x05b90ee8, ac__t0_add_t1__mul_prim},
+  // intro, Aidyn Chronicles. Added by Gonetz
+  // (0-cmb)*0+t1, (t1-1)*0+cmb
+  {0x05c701f2, ac_t1},
+  // zelda 2 [Ogy]. Added by Gonetz
+  // (t1-t0)*0+t1, (cmb-0)*prim+0
+  {0x05ca0ef8, ac_t1_mul_prim},
+  // beaver's river, zelda 2. Added by Gonetz
+  // (t1-0)*0+t1, (cmb-0)*prim+0
+  {0x05fa0ef8, ac_t1_mul_prim},
+  // Arena, pokemon stadium 2
+  // (0-0)*0+t1, (0-0)*t0+cmb
+  {0x05ff007f, ac_t1},
+  // Ogre Battle, unimp log. Added by Gonetz
+  // (0-0)*0+t1, (0-0)*0+cmb
+  {0x05ff05ff, ac_t1},
+  // lullaby, Paper Mario. Added by Gonetz
+  // (0-0)*0+t1, (cmb-0)*prim+0
+  {0x05ff0ef8, ac_t1_mul_prim},
+  // aerofighter's assault [Ogy]
+  // (0-0)*0+t1, (cmb-0)*shade+0
+  {0x05ff0f38, ac_t1_mul_shade},
+  // magic fist, Rayman2. Added by Gonetz
+  // (0-0)*0+t1, (cmb-0)*env+0
+  {0x05ff0f78, ac_t1_mul_env},
+  // Pokemon selection background, Pokemon stadium 2
+  // (env-prim)*t0+prim
+  {0x065d065d, ac_env_sub_prim_mul_t0_add_prim},
+  // text background, Ganbare Goemon - Mononoke Sugoroku
+  // (1-prim)*t0+prim
+  {0x065e065e, ac_one_sub_prim_mul_t0_add_prim},
+  // shadows, star wars: ep1 racer
+  // (0-prim)*t0+prim
+  {0x065f065f, ac_zero_sub_prim_mul_t0_add_prim},
+  // lava, beetle adventure racing
+  // (0-1)*t0+prim, (cmb-0)*prim+0  ** INC **
+  {0x06770ef8, ac_t0_mul_prim},
+  // menu, Ganbare Goemon - Mononoke Sugoroku
+  // (t0-0)*t0+prim
+  {0x06790679, ac_t0_add_prim},
+  // Water, pokemon stadium 2
+  // (t1-0)*t0+prim
+  {0x067a067a, ac_t0_mul_t1_add_prim},
+  // Smackdown Mall Menu, WWF No Mercy
+  // (shade-0)*t0+prim
+  {0x067c067c, ac_t0_mul_shade_add_prim},
+  // flag, Top Gear Rally  2. Added by Gonetz
+  // (env-0)*t0+prim
+  {0x067d067d, ac_t0_mul_env_add_prim},
+  // Mario Tennis. Added by Gonetz
+  // (1-0)*t0+prim
+  {0x067e067e, ac_t0_add_prim},
+  // sky, PGA European Tour
+  // (t0-0)*t1+prim
+  {0x06b906b9, ac_t0_mul_t1_add_prim},
+  // lava, beetle adventure racing
+  // (t0-0)*t1+prim, (0-0)*0+1 **INC**?
+  {0x06b90dff, ac_one},
+  // Pokemon Stadium 2, [Jeremy]. Added by Gonetz
+  // (prim-0)*t1+prim
+  {0x06bb06bb, ac_t1_mul_prim_add_prim},
+  // pokemon psyattack, Pokemon Stadium 2. Added by Gonetz
+  // (1-0)*t1+prim, (cmb-0)*env+0
+  {0x06be0f78, ac_t1_add_prim_mul_env},
+  // Rush2 2. Added by Gonetz
+  // (prim-prim)*prim+prim
+  {0x06db06db, ac_prim},
+  //Spacestation Silicon Valley intro. Added by Gonetz
+  // (t1-prim)*shade+prim
+  //    {0x071a071a, ac_t1_mul_shade},
+  {0x071a071a, ac_t1_sub_prim_mul_shade_add_prim},
+  //KI logos. Added by Gonetz
+  // (env-prim)*shade+prim
+  {0x071d071d, ac_env_sub_prim_mul_shade_add_prim},
+  // Deadly Arts, arena. Added by Gonetz
+  // (1-0)*shade+prim
+  {0x073e073e, ac_prim_add_shade},
+  // Phantom Gannon's portal, zelda
+  // (t1-t0)*env+prim, (cmb-0)*shade+0  ** INC **
+  {0x074a0f38, ac__t0_mul_t1__mul_prim_mul_shade},
+  // Road rush. Added by Gonetz
+  // (t0-0)*env+prim
+  {0x07790779, ac_t0_mul_env_add_prim},
+  // arena, Pokemon Stadium 2
+  // (shade-t0)*primlod+prim, (cmb-t0)*shade ** INC **
+  {0x078c0f08, ac_shade_sub_t0_mul_primlod_add_prim},
+  // telescope, zelda 2. Added by Gonetz
+  // (1-t0)*primlod+prim
+  {0x078e078e, ac_one_sub_t0_mul_primlod_add_prim},
+  // zelda 2 [Ogy]. Added by Gonetz
+  // (t0-t1)*primlod+prim, (cmb-0)*t0+0
+  {0x07910e78, ac_t0_inter_t1_using_primlod},
+  // Dobutsu no Mori. Added by Gonetz
+  // (t0-0)*primlod+prim
+  {0x07b907b9, ac_t0_mul_primlod_add_prim},
+  // Lock-On attack, Pokemon Stadium 2
+  // (t1-t0)*0+prim, (cmb-0)*0+cmb
+  {0x07ca01f8, ac_prim},
+  // water, DK64
+  // (0-0)*0+0, (0-t1)*0+prim
+  {0x07d707d7, ac_prim},
+  // Menu, megaman
+  // (1-0)*0+prim
+  {0x07fe07fe, ac_prim},
+  // super bowling
+  //(0-0)*0+prim,
+  {0x07ff0000, ac_prim},
+  // menu, Ganbare Goemon - Mononoke Sugoroku
+  // (0-0)*0+prim, (0-0)*0+t0
+  {0x07ff03ff, ac_t0},
+  // Intro background, starfox
+  //z (0-0)*0+prim
+  {0x07ff07ff, ac_prim},
+  // velva boss, JFG
+  //(0-0)*0+prim, (0-0)*0+env
+  {0x07ff0bff, ac_env},
+  // gem, castlevania 2. Added by Gonetz
+  // (0-0)*0+prim, (cmb-0)*t0+0
+  {0x07ff0e78, ac_t0_mul_prim},
+  // text, Tony Hawk's Pro Skater. Added by Gonetz
+  // (0-0)*0+prim, (cmb-0)*t1+0
+  {0x07ff0eb8, 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, ac_prim_mul_prim},
+  // explosion, Blast Corps. Added by Gonetz
+  // (0-0)*0+prim, (t0-0)*prim+0
+  {0x07ff0ef9, ac_t0_mul_prim},
+  // zelda 2, [Ogy]. Added by Gonetz
+  // (0-0)*0+prim, (cmb-0)*shade+0
+  {0x07ff0f38, ac_prim_mul_shade},
+  // Fox's ears and arms, smash bros
+  // (0-0)*0+prim, (cmb-0)*env+0
+  {0x07ff0f78, ac_prim_mul_env},
+  // monsters, Pokemon Stadium. Added by Gonetz
+  // (0-0)*0+prim, (cmb-0)*primlod+0
+  {0x07ff0fb8, ac_prim_mul_primlod},
+  // Hydro Pump Attack, Pokemon Stadium.
+  // (1-t1)*t0+shade, (cmb-prim)*shade+0
+  {0x08560f18, ac__one_sub_t1_mul_t0_add_shade__sub_prim_mul_shade},
+  // focus, Paper Mario. Added by Gonetz
+  //(t0-shade)*t0+shade, (cmb-0)*prim+0  * INC **
+  {0x08610ef8, ac_t0_mul_prim},
+  // Mario's head, mario //Added by Gonetz
+  //(prim-shade)*t0+shade
+  {0x08630863, ac_prim_sub_shade_mul_t0_add_shade},
+  // Fissure attack, pokemon stadium 2
+  //(t1-t0)*prim+shade, (cmb-0)*shade+0
+  {0x08ca0f38, ac__t1_sub_t0_mul_prim_add_shade__mul_shade},
+  // Earthquake pokemon attack, Pokemon Stadium 2 [gokuss4]. Added by Gonetz
+  //(t0-t1)*prim+shade, (cmb-0)*shade+0 ** INC **
+  {0x08d10f38, ac__t0_sub_t1_mul_prim_add_shade__mul_shade},
+  // ?
+  //(t0-shade)*prim+shade
+  {0x08e108e1, ac_t0_mul_prim_add_shade_mul_one_minus_prim},
+  // Paper Mario
+  // (t0-prim)*shade+shade, (cmb-0)*env+0
+  {0x09190f78, 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, ac_one_sub_t0_mul_prim_mul_shade},
+  // sun rays, Pokemon Stadium 2.
+  // (shade-0)*env+shade, (cmb-0)*prim+0
+  {0x097c0ef8, ac_one_plus_env_mul_prim_mul_shade},
+  // attack, Pokemon Stadium 2.
+  // (t0-0)*primlod+shade, (cmb-0)*shade+0
+  {0x09b90f38, ac__t0_mul_primlod_add_shade__mul_shade},
+  // Huge turtle appearance, zelda 2. Added by Gonetz
+  // (t1-0)*primlod+shade, (cmb-0)*shade+0  ** INC **
+  {0x09ba0f38, ac__t1_mul_primlod_add_shade__mul_shade},
+  // roof, Kirby 64. Added by Gonetz
+  // (t0-0)*0+shade
+  {0x09f909f9, ac_shade},
+  // water, Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz
+  // (0-0)*0+shade, (cmb-cmb)*lodf+cmb
+  {0x09ff0000, ac_shade},
+  // water temple, zelda 2. Added by Gonetz
+  // (0-0)*0+shade, (cmb-0)*prim+cmb
+  {0x09ff00f8, ac_prim_mul_shade_add_shade},
+  // damaged car, SCARS. Added by Gonetz
+  // (0-0)*0+shade, (t0-t1)*primlod+prim  ** INC **
+  {0x09ff0791, ac_t0_mul_primlod_add_prim},
+  // Hyrule castle gate, zelda
+  //z (0-0)*0+shade, (0-0)*0+prim
+  {0x09ff07ff, ac_prim},
+  // Super Mario 64 logo
+  //z (0-0)*0+shade
+  {0x09ff09ff, ac_shade},
+  // terrain, SCARS. Added by Gonetz
+  // (0-0)*0+shade, (0-0)*0+1
+  {0x09ff0dff, ac_one},
+  // terrain, SCARS. Added by Gonetz
+  // (0-0)*0+shade, (t0-0)*t1+0
+  {0x09ff0eb9, ac_t0_mul_t1},
+  // N64 logo, Aidyn Chronicles. Added by Gonetz
+  // (0-0)*0+shade, (cmb-0)*prim+0
+  {0x09ff0ef8, ac_prim_mul_shade},
+  // birds?, custom robo. Added by Gonetz
+  // (0-0)*0+shade, (cmb-0)*shade+0
+  {0x09ff0f38, ac_shade},
+  // sky, Glover, [Raziel64]. Added by Gonetz
+  // (0-0)*0+shade, (t0-0)*shade+0
+  {0x09ff0f39, ac_t0_mul_shade},
+  // Hand, smash bros
+  // (0-0)*0+shade, (cmb-0)*env+0
+  {0x09ff0f78, ac_env_mul_shade},
+  // Conker's helicopter tail, CBFD
+  // (0-0)*0+shade, (shade-0)*env+0
+  {0x09ff0f7c, ac_env_mul_shade},
+  // menu, PokemonStadium1, [Raziel64]
+  // (0-0)*0+shade, (cmb-0)*primlod+0
+  {0x09ff0fb8, ac_primlod_mul_shade},
+  // Link's sword slashing, smash bros
+  // (prim-env)*t0+env
+  {0x0a6b0a6b, 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, ac_t0_mul_prim},
+  // teleporter, Spacestation Silicon Valley. Added by Gonetz
+  // (prim-env)*t0+env, (cmb-0)*shade+0  ** INC **
+  {0x0a6b0f38, ac_t0_mul_shade},
+  // Ridge Racer, unimp log. Added by Gonetz
+  // (prim-env)*t0+env, (cmb-0)*primlod+0
+  {0x0a6b0fb8, ac_prim_sub_env_mul_t0_add_env},
+  // Kotake or koume's hair, zelda
+  // (prim-0)*t0+env
+  {0x0a7b0a7b, ac_t0_mul_prim_add_env},
+  // menu, doubut no mori
+  // (1-0)*t0+env
+  {0x0a7e0a7e, ac_t0_add_env},
+  // Grass, mario golf
+  // (env-shade)*t1+env, (0-0)*0+1
+  {0x0aa50dff, ac_one},
+  // Ridge Racer, cars select. Added by Gonetz
+  // (prim-env)*t1+env
+  {0x0aab0aab, ac_prim_sub_env_mul_t1_add_env},
+  // text, monster truck madness
+  // (prim-env)*t1+env, (cmb-0)*t1+0
+  {0x0aab0eb8, ac_t1_mul_env},
+  // zelda 2 [Ogy]. Added by Gonetz
+  // (1-0)*t1+env, (0-0)*0+cmb
+  //{0x0abe0abe, ac_one},
+  {0x0abe0abe, ac_t1_add_env},
+  // arena, Pokemon Stadium 2. Added by Gonetz
+  // (1-t0)*prim+env, (cmb-0)*shade+0
+  {0x0ace0f38, ac_one_sub_t0_mul_prim_mul_shade},
+  // intro, Bomberman 64 - 2. Added by Gonetz
+  // (t0-env)*prim+env
+  {0x0ae90ae9, ac_t0_sub_env_mul_prim_add_env},
+  // N64 logo, Ogre Battle. Added by Gonetz
+  // (t0-0)*prim+env
+  {0x0af90af9, ac_t0_mul_prim_add_env},
+  // girls, PD intro. Added by Gonetz
+  // (t0-env)*shade+env  ** INC **
+  {0x0b290b29, ac_t0_sub_env_mul_shadea_add_env},
+  // Text, Mia Soccer. Added by Gonetz
+  // (t0-env)*shade+env, (cmb-0)*lod_fraction+0  ** INC **
+  {0x0b290e38, ac_t0_sub_env_mul_shadea_add_env},
+  // shadows, Mario Tennis. Added by Gonetz
+  // (prim-env)*shade+env, (0-cmb)*t1+cmb ** INC **
+  {0x0b2b0087, 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, ac_prim_sub_env_mul_shade_add_env},
+  // ground, zelda2. Added by Gonetz
+  // (1-env)*shade+env, (t1-0)*prim+0
+  {0x0b2e0efa, ac_t1_mul_prim},
+  // GASP Fighters
+  // (t0-0)*shade+env
+  {0x0b390b39, ac_t0_mul_shade_add_env},
+  // destroying stuff, golden eye
+  // (1-0)*shade+env
+  {0x0b3e0b3e, ac_env_add_shade},
+  // Torches, Paper Mario. Added by Gonetz
+  // (t0-t1)*env+env, (0-0)*0+1
+  {0x0b510dff, ac_t0_sub_t1_mul_env_add_env},
+  // Mini Racers
+  // (t0-0)*primlod+env
+  {0x0bb90bb9, ac_t0_mul_primlod_add_env},
+  // International Track and Field 2000. Added by Gonetz
+  // (t0-0)*0+env
+  {0x0bf90bf9, ac_env},
+  // TM, mario
+  //z (0-0)*0+env
+  {0x0bff0bff, ac_env},
+  // rancho monster, zelda2. Added by Gonetz
+  // (0-0)*0+env, (cmb-0)*t1+0
+  {0x0bff0eb8, ac_t1_mul_env},
+  // Rocket Robot in Wheels intro
+  // (0-0)*0+env, (cmb-0)*prim+0
+  {0x0bff0ef8, ac_prim_mul_env},
+  // Background, Pokemon Snap   
+  // (prim-env)*t0+1
+  {0x0c6b0c6b, ac_prim_sub_env_mul_t0_add_one},
+  // Mario Golf
+  // (0-1)*t0+1
+  {0x0c770c77, ac_one_sub_t0},
+  // flame, paper mario. Added by Gonetz
+  // (1-t0)*t1+1, (cmb-t1)*t1+t1
+  {0x0c8e0490, ac_t0_mul_t1},
+  // hall of fame, Pokemon Stadium
+  // (t0-1)*prim+1, (cmb-0)*env+0
+  {0x0cf10f78, ac__one_inter_t0_using_prim__mul_env},
+  // Ring boundary, dual heroes
+  // (0-1)*prim+1
+  {0x0cf70cf7, ac_one_sub_prim},
+  // Kirby64, level 6, [Raziel64]
+  // (0-0)*prim+1
+  {0x0cff0cff, ac_one},
+  // Mystical Ninja
+  // (0-1)*env+1
+  {0x0d770d77, ac_one},
+  // Deku shield in shop, zelda
+  // (1-1)*primlod+1
+  {0x0db60db6, ac_one},
+  // water near gorons willage. Added by Gonetz
+  // (t1-t0)*0+1, (cmb-0)*prim+0
+  {0x0dca0ef8, ac_prim},
+  // background, kirby 64. Added by Gonetz
+  // (t0-0)*0+1
+  {0x0df90df9, ac_one},
+  // kirby 64. Added by Gonetz
+  // (1-0)*0+1
+  {0x0dfe0dfe, ac_one},
+  // background on level 2-1, kirby 64 [Raziel64]. Added by Gonetz
+  // (1-0)*0+1, (0-0)*0+1
+  {0x0dfe0dff, ac_one},
+  // duck dodgers intro. Added by Gonetz
+  // (0-0)*0+1, (cmb-cmb)*primlod+cmb
+  {0x0dff0000, ac_one},
+  // duck dodgers intro. Added by Gonetz
+  // (0-0)*0+1, (0-0)*0+t1 **INC**?
+  {0x0dff05ff, ac_t1},
+  // ?
+  // (0-0)*0+1, (0-0)*0+prim
+  {0x0dff07ff, ac_prim},
+  // arena, custom robo. Added by Gonetz
+  // (0-0)*0+1, (0-0)*0+shade
+  {0x0dff09ff, ac_shade},
+  // field, Mario Golf
+  // (0-0)*0+1, (1-env)*shade+env
+  {0x0dff0b2e, ac_one_sub_env_mul_shade_add_env},
+  // battle tanks 2 [Ogy]
+  // (0-0)*0+1, (0-0)*0+env
+  {0x0dff0bff, ac_env},
+  // helmet, F1 World Grand Prix. Added by Gonetz
+  // (0-0)*0+1, (0-1)*0+1
+  {0x0dff0df7, ac_one},
+  // secret in level 3-4, Kirby64, [Raziel64]
+  // (0-0)*0+1, (cmb-0)*0+1
+  {0x0dff0df8, ac_one},
+  // Menu options, starfox
+  // (0-0)*0+1
+  {0x0dff0dff, ac_one},
+  // Water, zelda
+  //z (0-0)*0+primlod, (cmb-0)*prim+0
+  {0x0dff0ef8, ac_prim},
+  // Desert ground, zelda
+  // (0-0)*0+1, (cmb-0)*shade+0
+  {0x0dff0f38, ac_shade},
+  // Characters, smash bros
+  // (0-0)*0+1, (cmb-0)*env+0
+  {0x0dff0f78, ac_env},
+  // end of level 3-4, Kirby64, [Raziel64]
+  // (0-0)*0+1, (cmb-0)*0+0
+  {0x0dff0ff8, ac_zero},
+  // Kirby64
+  // (0-0)*0+1, (0-0)*0+0
+  {0x0dff0fff, ac_zero},
+  // floor, Spiderman [Raziel64]. Added by Gonetz
+  // (env-t1)*t0+0  ** INC **
+  {0x0e550e55, ac_t0_mul_env},
+  // skeleton, castlevania 2. Added by Gonetz
+  // (1-prim)*t0+0
+  {0x0e5e0e5e, ac_one_sub_prim_mul_t0},
+  // player select, Forsaken [Raziel64]. Added by Gonetz
+  // (prim-shade)*t0+0
+  {0x0e630e63, ac_prim_sub_shade_mul_t0},
+  // castlevania 2 [Ogy]. Added by Gonetz
+  // (1-shade)*t0+0
+  {0x0e660e66, ac_one_sub_shade_mul_t0},
+  // GoldenEye: Helicopter rotors
+  // (shade-env)*t0+0, (1-0)*prim+cmb
+  {0x0e6c00fe, ac_shade_sub_env_mul_t0_add_prim},
+  // background, level3-4, Kirby64, [Raziel64]
+  // (shade-env)*t0+0
+  {0x0e6c0e6c, ac_shade_sub_env_mul_t0},
+  // Goemon, mystical ninja. Added by Gonetz
+  // (1-env)*t0+0
+  {0x0e6e0e6e, 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, ac_t0_inter_t1_using_prima},
+  // Clay Fighter [Ogy]. Added by Gonetz
+  // (t0-0)*t0+0
+  {0x0e790e79, ac_t0_mul_t0},
+  // Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz
+  // (t0-0)*t0+0, (prim-0)*t1+0
+  {0x0e790ebb, ac_t1_mul_prim},
+  // zelda 2 [Ogy]. Added by Gonetz
+  // (t0-0)*t0+0, (cmb-0)*prim+0
+  {0x0e790ef8, ac_t0_mul_prim},
+  // zelda 2. Added by Gonetz
+  // (t0-0)*t0+0, (cmb-0)*shade+0
+  {0x0e790f38, ac_t0_mul_shade},
+  // zelda 2. Added by Gonetz
+  // (t0-0)*t0+0, (cmb-0)*env+0
+  {0x0e790f78, 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, ac_t0_mul_t1},
+  // paper mario. Added by Gonetz
+  // (t1-0)*t0+0, (cmb-env)*prim+env  ** INC **
+  {0x0e7a0ae8, ac_t1_mul_prim},
+  // mini games quiz monitor backround, Pokemon Stadium 2
+  // (t1-0)*t0+0, (0-0)*0+1
+  {0x0e7a0dff, ac_one},
+  // Tony Hawk's Pro Skater. Added by Gonetz
+  // (t1-0)*t0+0, (cmb-0)*t0+0
+  {0x0e7a0e78, ac_t0_mul_t1},
+  // bike trace, xg2. Added by Gonetz
+  // (t1-0)*t0+0
+  {0x0e7a0e7a, ac_t0_mul_t1},
+  // Kotake & koume defeated, zelda
+  // (t1-0)*t0+0, (cmb-0)*prim+0
+  {0x0e7a0ef8, ac__t0_mul_t1__mul_prim},
+  // Magnitude, pokemon stadium 2
+  // (t1-0)*t0+0, (cmb-env)*shade+0
+  {0x0e7a0f28, ac__t0_mul_t1__mul_env_mul_shade},
+  // Bongo Bongo, zelda
+  // (t1-0)*t0+0, (cmb-0)*shade+0
+  {0x0e7a0f38, ac__t0_mul_t1__mul_shade},
+  //  Dobutsu_no_Mori, waterfall
+  // (t1-0)*t0+0, (cmb-0)*prim_lod+0
+  {0x0e7a0fb8, ac__t0_mul_t1__mul_primlod},
+  // Back of doors, megaman
+  // (prim-0)*t0+0, (cmb-0)*lodfrac+0
+  {0x0e7b0e38, ac_t0_mul_prim},
+  // Karts, mario kart
+  //z (prim-0)*t0+0
+  {0x0e7b0e7b, ac_t0_mul_prim},
+  // paper mario. Added by Gonetz
+  // (prim-0)*t0+0, (t0-0)*prim+0
+  {0x0e7b0ef9, ac_t0_mul_prim},
+  // Table, mace
+  // (prim-0)*t0+0, (cmb-0)*shade+0
+  {0x0e7b0f38, 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, ac_t0_mul_shade},
+  // Game logo, Aerofighters Assault [Raziel64]
+  //(shade-0)*t0+0, (0-0)*0+1
+  {0x0e7c0dff, ac_one},
+  // Higher sky, waverace
+  //z (shade-0)*t0+0
+  {0x0e7c0e7c, ac_t0_mul_shade},
+  // duck dodgers, intro. Added by Gonetz
+  // (shade-0)*t0+0, (cmb-0)*prim+0
+  {0x0e7c0ef8, ac_t0_mul_prim_mul_shade},
+  // waterwheel in water temple, zelda 2. Added by Gonetz
+  // (shade-0)*t0+0, (cmb-0)*env+0
+  {0x0e7c0f78, ac_t0_mul_env_mul_shade},
+  // Blowing up mine at bowser's, mario
+  // (env-0)*t0+0
+  {0x0e7d0e7d, ac_t0_mul_env},
+  // castlevania 2, intro. Added by Gonetz
+  // (1-0)*t0+0
+  {0x0e7e0e7e, ac_t0},
+  // moon, castlevania 2. Added by Gonetz
+  // (1-0)*t0+0, (cmb-0)*prim+0
+  {0x0e7e0ef8, ac_t0_mul_prim},
+  //beetle adventure racing. Added by Gonetz
+  // (1-0)*t0+0, (cmb-0)*shade+0
+  {0x0e7e0f38, ac_t0_mul_shade},
+  // lava, beetle adventure racing
+  // (t0-prim)*t1+0, (0-0)*0+shade   ** INC **
+  {0x0e9909ff, ac_shade},
+  // Rain Dance, Pokemon Stadium 2 [gokuss4]. Added by Gonetz
+  // (t0-env)*t1+0, (cmb-0)*0+prim   ** INC **
+  {0x0ea90ef8, ac__t0_mul_t1__mul_prim},
+  // Duck Dodgers Starring Daffy Duck text background
+  // (t0-0)*t1+0, (shade-cmb)*prim+cmb
+  {0x0eb900c4, ac_one_sub_prim_mul__t0_mul_t1__add__prim_mul_shade},
+  // torches, pokemon stadium 2
+  // (t0-0)*t1+0, (cmb-env)*prim+cmb
+  {0x0eb900e8, ac__t0_mul_t1__sub_env_mul_prim_add__t0_mul_t1},
+  // airboarder 64 [Ogy]
+  // (t0-0)*t1+0, (0-0)*0+prim
+  {0x0eb907ff, ac_prim},
+  // explosion, body harvest. Added by Gonetz
+  // (t0-0)*t1+0, (0-0)*0+shade
+  {0x0eb909ff, ac_shade},
+  // Text off top, banjo kazooie
+  // (t0-0)*t1+0
+  {0x0eb90eb9, ac_t0_mul_t1},
+  // smoke, daikatana. Added by Gonetz
+  // (t0-0)*t1+0, (cmb-0)*prim+0
+  {0x0eb90ef8, ac__t0_mul_t1__mul_prim},
+  // Arena, Pokemon Stadium 2.
+  // (t0-0)*t1+0, (cmb-prim)*shade+0
+  {0x0eb90f18, ac__t0_mul_t1__sub_prim_mul_shade},
+  // Water, pilotwings
+  // (t0-0)*t1+0, (cmb-0)*shade+0
+  {0x0eb90f38, ac__t0_mul_t1__mul_shade},
+  // Tony Hawk's Pro Skater. Added by Gonetz
+  // (t0-0)*t1+0, (cmb-0)*env+0
+  {0x0eb90f78, ac__t0_mul_t1__mul_env},
+  // light from window, Dobutsu no Mori. Added by Gonetz
+  // (t0-0)*t1+0, (cmb-0)*primlod+0
+  {0x0eb90fb8, ac__t0_mul_t1__mul_primlod},
+  // chandelier in spider house, zelda 2. Added by Gonetz
+  // (t1-0)*t1+0, (cmb-0)*prim+0
+  {0x0eba0ef8, ac_t1_mul_prim},
+  // cars, ridge racer. Added by Gonetz
+  // (prim-0)*t1+0, (0-0)*0+1
+  {0x0ebb0dff, ac_t1_mul_prim},
+  // aerofighter's assault [Ogy]
+  // (prim-0)*t1+0
+  {0x0ebb0ebb, ac_t1_mul_prim},
+  // tire trace, beetle adventure racing. Added by Gonetz
+  // (shade-0)*t1+0
+  {0x0ebc0ebc, ac_t1_mul_shade},
+  // smoke, Starshot. Added by Gonetz
+  // (env-0)*t1+0
+  {0x0ebd0ebd, ac_t1_mul_env},
+  // lots of things, goldeneye
+  // (1-0)*t1+0, (0-0)*0+shade
+  {0x0ebe09ff, ac_shade},
+  // zelda 2 [Ogy]. Added by Gonetz
+  // (1-0)*t1+0, (cmb-0)*prim+0
+  {0x0ebe0ef8, ac_t1_mul_prim},
+  // walls, perfect dark. Added by Gonetz
+  // (1-0)*t1+0, (cmb-0)*shade+0
+  {0x0ebe0f38, ac_t1_mul_shade},
+  // sand, perfect dark. Added by Gonetz
+  // (1-0)*t1+0, (cmb-0)*env+0
+  {0x0ebe0f78, ac_t1_mul_env},
+  // light, Ridge Racer. Added by Gonetz
+  // (1-t0)*prim+0
+  {0x0ece0ece, ac_one_sub_t0_mul_prim},
+  // exaust, star wars ep1 racer
+  // (1-t0)*prim+0, (cmb-0)*shade+0
+  {0x0ece0f38, ac_one_sub_t0_mul_primshade},
+  // iguana, Forsaken, [Raziel64]. Added by Gonetz
+  // (t0-shade)*prim+0
+  {0x0ee10ee1, ac_t0_sub_shade_mul_prim},
+  // stands, NASCAR 2000
+  // (prim-shade)*prim+0
+  {0x0ee30ee3, ac_prim_sub_shade_mul_prim},
+  // arena, Pokemon Stadium 2. Added by Gonetz
+  // (t0-env)*prim+0    ** INC **
+  {0x0ee90ee9, ac_t0_mul_prim},
+  // lure, bass rush
+  // (t0-0)*prim+0, (cmb-cmb)*lodf+cmb
+  {0x0ef90000, ac_t0_mul_prim},
+  // explosion, body harvest. Added by Gonetz
+  // (t0-0)*prim+0, (t0-0)*env+cmb
+  {0x0ef90179, ac_prim_add_env_mul_t0},
+  // frog's eyes, zelda
+  // (t0-0)*prim+0, (1-1)*prim_lod+cmb
+  {0x0ef901b6, ac_t0_mul_prim},
+  // Monster truck madness intro. Added by Gonetz
+  // (t0-0)*prim+0, (cmb-0)*prim_lod+cmb  ** INC **
+  {0x0ef901b8, ac_t0_mul_prim},
+  // Road, zelda
+  //z (t0-0)*prim+0, (t1-0)*primlod+cmb
+  {0x0ef901ba, ac__t0_mul_prim__add__t1_mul_primlod},
+  // Track, wipeout. Addded by Gonetz
+  // (t0-0)*prim+0, (0-0)*0+prim
+  {0x0ef907ff, ac_t0_mul_prim},
+  // magic stuff, buck bumble. Added by Gonetz
+  // (t0-0)*prim+0, (cmb-0)*prim+0
+  {0x0ef90ef8, ac_t0_mul_prim_mul_prim},
+  // The mario face, mario
+  //z (t0-0)*prim+0
+  {0x0ef90ef9, ac_t0_mul_prim},
+  // paper mario. Added by Gonetz
+  // (t0-0)*prim+0, (cmb-0)*shade+0
+  {0x0ef90f38, ac_t0_mul_prim_mul_shade},
+  // Pikachu's mouth, smash bros
+  // (t0-0)*prim+0, (cmb-0)*env+0
+  {0x0ef90f78, ac_t0_mul_prim_mul_env},
+  // bomb mask, zelda 2. Added by Gonetz
+  // (t0-0)*prim+0, (1-0)*env+0
+  {0x0ef90f7e, ac_t0_mul_prim},
+  // Charmander's tail, pokemon stadium 2
+  // (t0-0)*prim+0, (cmb-0)*primlod+0
+  {0x0ef90fb8, ac_t0_mul_prim_mul_primlod},
+  // stalactites, Beetle adventure Racing. Added by Gonetz
+  // (t1-0)*prim+0, (1-cmb)*shade+cmb
+  {0x0efa0106, ac_one_sub_shade_mul_t1_add_shade},
+  // Sprites, Ogre Battle. Added by Gonetz
+  // (t1-0)*prim+0, (0-0)*0+cmb
+  {0x0efa0efa, ac_t1_mul_prim},
+  // Something about kotake & koume's combined attack, zelda
+  // (t1-0)*prim+0, (cmb-0)*shade+0
+  {0x0efa0f38, ac_t1_mul_prim_mul_shade},
+  // intro background, bio freaks. Added by Gonetz
+  // (prim-0)*prim+0
+  {0x0efb0efb, ac_prim_mul_prim},
+  // sky, xg2. Added by Gonetz
+  // (shade-0)*prim+0, (0-0)*0+1
+  {0x0efc0dff, ac_one},
+  // Zelda, unimp log. Added by Gonetz
+  // (shade-0)*prim+0
+  {0x0efc0efc, ac_prim_mul_shade},
+  // ?
+  // (shade-0)*prim+0, (cmb-0)*shade+0 ** INC **
+  {0x0efc0f38, ac_prim_mul_shade},
+  // Baby mario's hat shadow, mario golf
+  // (env-0)*prim+0
+  {0x0efd0efd, ac_prim_mul_env},
+  // Menu, doom
+  // (1-0)*prim+0
+  {0x0efe0efe, ac_prim},
+  // Peris Song attack, Pokemin Stadium 2
+  // (1-0)*prim+0, (cmb-0)*shade+0
+  {0x0efe0f38, ac_prim_mul_shade},
+  // Conker's shadow, CBFD. Added by Gonetz
+  // (1-t0)*shade+0
+  {0x0f0e0f0e, ac_one_sub_t0_mul_shade},
+  // Rock smash, pokemon stadium 2
+  // (1-t0)*shade+0
+  {0x0f0f0ee8, ac_one_sub_t0_mul_shade},
+  //waterfall, Paper Mario
+  // (t0-t1)*shade+0
+  {0x0f110f11, ac__t0_sub_t1__mul_shade},
+  // mahogany town statue, Pokemon Stadium 2
+  // (t0-prim)*shade+0
+  {0x0f190f19, ac_t0_sub_prim_mul_shade},
+  // silver cave, pokemon stadium 2
+  // (t0-prim)*shade+0, (cmb-0)*env+0
+  {0x0f190f78, ac_t0_sub_prim_mul_shade_mul_env},
+  // Boomerang circle, zelda
+  // (t0-0)*shade+0, (1-cmb)*t0+cmb
+  {0x0f390046, ac_t0_mul_shade},
+  // THPS3
+  // (t0-0)*shade+0, (1-0)*t0+cmb
+  {0x0f39007e, ac_t0_mul_shade},
+  // ???
+  // (t0-0)*shade+0, (env-0)*t1+cmb
+  {0x0f3900bd, ac_t0_mul_shade},
+  // Forest temple doorway, zelda
+  // (t0-0)*shade+0, (t1-0)*primlod+cmb
+  {0x0f3901ba, ac_t0_mul_shade},
+  // skis, Spacestation Silicon Valley. Added by Gonetz
+  // (t0-0)*shade+0, (0-0)*0+t0
+  {0x0f3903ff, ac_t0},
+  // paper mario. Added by Gonetz
+  // (t0-0)*shade+0, (cmb-t0)*prim+0
+  {0x0f390ec8, ac_t0_mul_prim_mul_shade},
+  // House windows, zelda intro
+  //z (t0-0)*shade+0, (cmb-0)*prim+0
+  {0x0f390ef8, ac_t0_mul_prim_mul_shade},
+  // Characters, mace
+  // (t0-0)*shade+0, (cmb-0)*shade+0
+  {0x0f390f38, ac_t0_mul_shade},
+  // Shadows, mario
+  //z (t0-0)*shade+0
+  {0x0f390f39, ac_t0_mul_shade},
+  // Clear screen intro, banjo kazooie
+  // (t0-0)*shade+0, (cmb-0)*env+0
+  {0x0f390f78, ac_t0_mul_env_mul_shade},
+  // ridge racer, unimp log. Added by Gonetz
+  // (t0-0)*shade+0, (cmb-0)*primlod+0  **INC**?
+  {0x0f390fb8, ac_t0_mul_shade},
+  // Reflecting combined attack at kotake & koume's, zelda
+  // (t1-0)*shade+0, (cmb-0)*prim+0
+  {0x0f3a0ef8, ac_t1_mul_prim_mul_shade},
+  // aerofighter's assault [Ogy]
+  // (t1-0)*shade+0
+  {0x0f3a0f3a, ac_t1_mul_shade},
+  //beetle adventure racing. Added by Gonetz
+  //(t1-0)*shade+0, (cmb-0)*env+0
+  {0x0f3a0f78, 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, ac_prim_mul_shade},
+  //chip in Spacestation Silicon Valley intro. Added by Gonetz
+  // (prim-0)*shade+0, (env-cmb)*t1+cmb
+  {0x0f3b0085, ac_env_sub_primshade_mul_t1_add_primshade},
+  // N64 logo, tetrisphere. Added by Gonetz
+  // (prim-0)*shade+0, (prim-0)*shade+0
+  {0x0f3b0f3b, ac_prim_mul_shade},
+  // rays, Fushigi no Dungeon - Furai no Shiren 2. Added by Gonetz
+  // (shade-0)*shade+0, (cmb-0)*prim+0
+  {0x0f3c0ef8, ac_prim_mul_shade},
+  // light, dracula resurrection, castlevania 2. Added by Gonetz
+  // (env-0)*shade+0
+  {0x0f3d0f3d, ac_env_mul_shade},
+  // zelda 2 [Ogy]. Added by Gonetz
+  // (1-0)*shade+0
+  {0x0f3e0f3e, ac_shade},
+  // surf pokemon attack, Pokemon Stadium 2 [gokuss4]. Added by Gonetz
+  // (1-t0)*env+0, (1-cmb)*shade+0  ** INC **
+  {0x0f4e0f06, ac_t0_mul_shade},
+  // GE, boxes
+  // (1-shade)*env+0, (cmb-0)*shade+0 ** INC **
+  {0x0f660f38, ac_one_sub_shade_mul_env},
+  //beetle adventure racing. Added by Gonetz
+  //(t0-0)*env+0, (1-t0)*prim+cmb
+  //{0x0f7900ce, ac_t0_mul_env}, //this one looks better
+  //{0x0f7900ce, ac_env_sub_prim_mul_t0_add_prim},
+  {0x0f7900ce, ac_one_sub_t1_add_t0_mul_env},
+  //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, ac__t0_inter_t1_using_primlod__mul_env},
+  // V8-2 menu
+  // (t0-0)*env+0, (0-0)*0+prim
+  {0x0f7907ff, ac_prim},
+  // Skeleton guy's eyes, zelda
+  // (t0-0)*env+0, (cmb-0)*prim+0
+  {0x0f790ef8, ac_t0_mul_prim_mul_env},
+  // Dust from rock spell, quest64
+  // (t0-0)*env+0, (cmb-0)*shade+0
+  {0x0f790f38, ac_t0_mul_env_mul_shade},
+  // eyes of poe, zelda
+  // (t0-0)*env+0, (cmb-0)*env+0
+  {0x0f790f78, ac_t0_mul_env},
+  // Text, mario
+  //z (t0-0)*env+0
+  {0x0f790f79, ac_t0_mul_env},
+  // Shadows, pokemon stadeom 2
+  // (t0-0)*env+0, (cmb-0)*primlod+0
+  {0x0f790fb8, ac_t0_mul_env_mul_primlod},
+  //gauge, PGA
+  // (t1-0)*env+0, (cmb-0)*t1+0 ** INC **
+  {0x0f7a0eb8, ac_t1_mul_env},
+  //text and shadows, Rayman2. Added by Gonetz
+  // (t1-0)*env+0, (cmb-0)*shade+0
+  {0x0f7a0f38, ac_t1_mul_env_mul_shade},
+  // shadows, tom and jerry. Added by Gonetz
+  // (t1-0)*env+0
+  {0x0f7a0f7a, ac_t1_mul_env},
+  // Bomberman64-2 intro. Added by Gonetz
+  // (prim-0)*env+0
+  {0x0f7b0f7b, ac_prim_mul_env},
+  // Text box, mario
+  //z (shade-0)*env+0
+  {0x0f7c0f7c, ac_env_mul_shade},
+  // Ogre battle 64
+  // (env-0)*env+0
+  {0x0f7d0f7d, ac_env},
+  //Goldeneye, [Jeremy]. Added by Gonetz
+  // (1-0)*env+0, (cmb-0)*shade+0
+  {0x0f7e0f38, ac_env_mul_shade},
+  // Status items, megaman
+  // (1-0)*env+0
+  {0x0f7e0f7e, ac_env},
+  // gun fire, Beast_Wars_Transmetal [Raziel64]
+  // (0-0)*env+0
+  {0x0f7f0f7f, ac_zero},
+  // Pokemon attack, Pokemon stadium (J). Added by Gonetz
+  // (t1-t0)*primlod+0, (cmb-0)*env+prim  ** INC **
+  {0x0f8a0778, ac__t1_sub_t0_mul_primlod__mul_env_add_prim},
+  // Shadow Ball, Pokemon Stadium 2 [gokuss4]. Added by Gonetz
+  // (t1-t0)*primlod+0, (t1-cmb)*prim+0  ** INC **
+  {0x0f8a0ec2, ac_t0_mul_prim},
+  // Walls of well through lens of truth, zelda
+  // (prim-t0)*primlod+0
+  {0x0f8b0f8b, ac_prim_sub_t0},
+  // N64 logo, ridge racer. Added by Gonetz
+  // (1-prim)*primlod+0  **INC**
+  {0x0f9e0f9e, 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, ac_t0_mul_primlod_mul_prim},
+  // zelda 2. Added by Gonetz
+  // (t0-0)*primlod+0
+  {0x0fb90fb9, ac_t0_mul_primlod},
+  // NFL Blitz logo. Added by Gonetz
+  // (t1-0)*primlod+0
+  {0x0fba0fba, ac_t1_mul_primlod}, //causes issues
+  // fallen stars at star summit, Paper Mario. Added by Gonetz
+  // (shade-0)*primlod+0
+  {0x0fbc0fbc, ac_primlod_mul_shade},
+  // expansion pack, Jeremy McGrath Supercross 2000. Added by Gonetz
+  // (1-0)*primlod+0
+  {0x0fbe0fbe, ac_primlod},
+  // intro, Aidyn Chronicles. Added by Gonetz
+  // (0-0)*primlod+0, (prim-env)*t0+prim  **INC**
+  {0x0fbf066b, ac_t0_mul_prim},
+  // sky, Rayman2. Added by Gonetz
+  // (0-shade)*0+0
+  {0x0fe70fe7, ac_zero},
+  // flame, PokemonStadium1 [Raziel64]
+  // (t0-0)*0+0
+  {0x0ff90ff9, ac_zero},
+  //BAR
+  // (0-0)*0+0, (0-0)*0+TEXEL1
+  {0x0fff05ff, ac_t0},
+  // Screen clear, banjo kazooie
+  // (0-0)*0+0
+  {0x0fff0fff, ac_zero},
+  // { #ACEND }
+};
+
+// CountCombine - count the # of entries in the combine lists
+void CountCombine ()
+{
+  int size = sizeof(color_cmb_list) / sizeof(COMBINER);
+  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) / sizeof(COMBINER);
+  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 (!rdp.LOD_en || rdp.cur_tile == rdp.mipmap_level)
+    lod_frac = rdp.prim_lodfrac;
+  else if (settings.lodmode == 0)
+    lod_frac = 0;
+  else
+    lod_frac = 10;
+
+  rdp.noise = RDP::noise_none;
+
+  wxUint32 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;
+  }
+
+  wxUint32 cmb_mode_c = (rdp.cycle1 << 16) | (rdp.cycle2 & 0xFFFF);
+  wxUint32 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;
+  wxUint32 actual_combine, current_combine, color_combine, alpha_combine;
+  int left, right;
+
+  actual_combine = current_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();
+
+  LRDP(" | |- 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.hacks&hack_PMario)) //Paper Mario fortune teller spheres
+  {
+    ac_t0();
+  }
+
+  LRDP(" | |- 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 (fullscreen)
+  {
+    TBUFF_COLOR_IMAGE * aTBuff[2] = {0, 0};
+    if (rdp.aTBuffTex[0])
+      aTBuff[rdp.aTBuffTex[0]->tile] = rdp.aTBuffTex[0];
+    if (rdp.aTBuffTex[1])
+      aTBuff[rdp.aTBuffTex[1]->tile] = rdp.aTBuffTex[1];
+    if (cmb.tex && (aTBuff[0] || aTBuff[1]))
+    {
+      if (aTBuff[0] && (settings.frame_buffer&fb_read_alpha))
+      {
+        if ((settings.hacks&hack_PMario) && aTBuff[0]->width == rdp.ci_width)
+          ;
+        else
+        {
+          grChromakeyValue(0);
+          grChromakeyMode(GR_CHROMAKEY_ENABLE);
+        }
+      }
+      else
+        grChromakeyMode(GR_CHROMAKEY_DISABLE);
+
+      if (aTBuff[0] && aTBuff[0]->info.format == GR_TEXFMT_ALPHA_INTENSITY_88)
+      {
+        if (cmb.tex_cmb_ext_use & TEX_COMBINE_EXT_COLOR)
+        {
+          if (cmb.t0c_ext_a == GR_CMBX_LOCAL_TEXTURE_RGB)
+            cmb.t0c_ext_a = GR_CMBX_LOCAL_TEXTURE_ALPHA;
+          if (cmb.t0c_ext_b == GR_CMBX_LOCAL_TEXTURE_RGB)
+            cmb.t0c_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA;
+          if (cmb.t0c_ext_c == GR_CMBX_LOCAL_TEXTURE_RGB)
+            cmb.t0c_ext_c = GR_CMBX_LOCAL_TEXTURE_ALPHA;
+        }
+        else
+          cmb.tmu0_func = GR_COMBINE_FUNCTION_LOCAL_ALPHA;
+      }
+
+      if (aTBuff[1] && aTBuff[1]->info.format == GR_TEXFMT_ALPHA_INTENSITY_88)
+      {
+        if (cmb.tex_cmb_ext_use & TEX_COMBINE_EXT_COLOR)
+        {
+          if (cmb.t1c_ext_a == GR_CMBX_LOCAL_TEXTURE_RGB)
+            cmb.t1c_ext_a = GR_CMBX_LOCAL_TEXTURE_ALPHA;
+          if (cmb.t1c_ext_b == GR_CMBX_LOCAL_TEXTURE_RGB)
+            cmb.t1c_ext_b = GR_CMBX_LOCAL_TEXTURE_ALPHA;
+          if (cmb.t1c_ext_c == GR_CMBX_LOCAL_TEXTURE_RGB)
+            cmb.t1c_ext_c = GR_CMBX_LOCAL_TEXTURE_ALPHA;
+        }
+        else
+          cmb.tmu1_func = GR_COMBINE_FUNCTION_LOCAL_ALPHA;
+      }
+    }
+    else
+      grChromakeyMode(GR_CHROMAKEY_DISABLE);
+  }
+  cmb.shade_mod_hash = (rdp.cmb_flags + rdp.cmb_flags_2) * (rdp.prim_color + rdp.env_color + rdp.K5);
+
+  LRDP(" | + Combine end\n");
+}
+
+void CombineBlender ()
+{
+  wxUint32 blendmode = rdp.othermode_l >> 16;
+  // Check force-blending
+  if ((rdp.othermode_l & 0x4000) && (rdp.cycle_mode < 2))
+  {
+    switch (blendmode)
+    {
+      // 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:
+      //Sin and Punishment
+    case 0xcb02:
+      // Battlezone
+      // clr_in * a + clr_in * (1-a)
+    case 0xc800:
+    case 0x00c0:
+      //ISS64
+    case 0xc302:
+      A_BLEND (GR_BLEND_ONE, GR_BLEND_ZERO);
+      break;
+
+      //Space Invaders
+    case 0x0448:
+    case 0x055a:
+      A_BLEND (GR_BLEND_ONE, GR_BLEND_ONE);
+      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 0xc410: // Perfect Dark Mauler
+      {
+      MOD_0 (TMOD_TEX_INTER_COLOR_USING_FACTOR);
+      MOD_0_COL (rdp.fog_color & 0xFFFFFF00);
+      MOD_0_FAC (rdp.fog_color & 0xFF);
+      INTERSHADE_2 (rdp.fog_color & 0xFFFFFF00, rdp.fog_color & 0xFF);
+
+      float percent = (rdp.fog_color & 0xFF) / 255.0f;
+      cmb.ccolor =
+      ((wxUint32)(((cmb.ccolor >> 24) & 0xFF) * (1.0f-percent) + ((rdp.fog_color>>24) & 0xFF) * percent) << 24) |
+      ((wxUint32)(((cmb.ccolor >> 16) & 0xFF) * (1.0f-percent) + ((rdp.fog_color>>16) & 0xFF) * percent) << 16) |
+      ((wxUint32)(((cmb.ccolor >> 8) & 0xFF) * (1.0f-percent) + ((rdp.fog_color>>8) & 0xFF) * percent) << 8) |
+      (cmb.ccolor & 0xFF);
+
+      rdp.col[0] = rdp.col[0] * (1.0f-percent) + ((rdp.fog_color>>24) & 0xFF) / 255.0f * percent;
+      rdp.col[1] = rdp.col[1] * (1.0f-percent) + ((rdp.fog_color>>16) & 0xFF) / 255.0f * percent;
+      rdp.col[2] = rdp.col[2] * (1.0f-percent) + ((rdp.fog_color>>8) & 0xFF) / 255.0f * percent;
+      A_BLEND (GR_BLEND_SRC_ALPHA, 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);
+      {
+        wxUint32 prim = rdp.prim_color;
+        rdp.prim_color = rdp.fog_color;
+        cc_prim();
+        ac_prim();
+        rdp.prim_color = prim;
+      }
+      break;
+
+    case 0x0150: //spiderman
+    case 0x0d18: //clr_in * a_fog + clr_mem * (1-a)
+      A_BLEND (GR_BLEND_SRC_ALPHA, GR_BLEND_ONE_MINUS_SRC_ALPHA);
+      if (rdp.cycle_mode == 1 && rdp.cycle2 != 0x01ff1fff)
+      {
+        wxUint32 prim = rdp.prim_color;
+        rdp.prim_color = rdp.fog_color;
+        ac_prim();
+        rdp.prim_color = prim;
+      }
+      break;
+
+    case 0xc912: //40 winks, clr_in * a_fog + clr_mem * 1
+      {
+        wxUint32 prim = rdp.prim_color;
+        rdp.prim_color = rdp.fog_color;
+        ac_prim();
+        rdp.prim_color = prim;
+      }
+      A_BLEND (GR_BLEND_SRC_ALPHA, GR_BLEND_ONE);
+      break;
+
+    default:
+      A_BLEND (GR_BLEND_SRC_ALPHA, GR_BLEND_ONE_MINUS_SRC_ALPHA);
+    }
+  }
+  /*
+  else if (blendmode == 0xc411) // Super Smash Bros, faked fog for flashing characters
+  {
+  MOD_0 (TMOD_TEX_INTER_COLOR_USING_FACTOR);
+  MOD_0_COL (rdp.fog_color & 0xFFFFFF00);
+  MOD_0_FAC (rdp.fog_color & 0xFF);
+  INTERSHADE_2 (rdp.fog_color & 0xFFFFFF00, rdp.fog_color & 0xFF);
+
+  float percent = (rdp.fog_color & 0xFF) / 255.0f;
+  cmb.ccolor =
+  ((wxUint32)(((cmb.ccolor >> 24) & 0xFF) * (1.0f-percent) + ((rdp.fog_color>>24) & 0xFF) * percent) << 24) |
+  ((wxUint32)(((cmb.ccolor >> 16) & 0xFF) * (1.0f-percent) + ((rdp.fog_color>>16) & 0xFF) * percent) << 16) |
+  ((wxUint32)(((cmb.ccolor >> 8) & 0xFF) * (1.0f-percent) + ((rdp.fog_color>>8) & 0xFF) * percent) << 8) |
+  (cmb.ccolor & 0xFF);
+
+  rdp.col[0] = rdp.col[0] * (1.0f-percent) + ((rdp.fog_color>>24) & 0xFF) / 255.0f * percent;
+  rdp.col[1] = rdp.col[1] * (1.0f-percent) + ((rdp.fog_color>>16) & 0xFF) / 255.0f * percent;
+  rdp.col[2] = rdp.col[2] * (1.0f-percent) + ((rdp.fog_color>>8) & 0xFF) / 255.0f * percent;
+  A_BLEND (GR_BLEND_ONE, GR_BLEND_ZERO);
+  }
+  */
+  else if (blendmode == 0x0040) // Mia Soccer Lights
+    A_BLEND (GR_BLEND_SRC_ALPHA, GR_BLEND_ONE_MINUS_SRC_ALPHA);
+  else if ((settings.hacks&hack_Pilotwings) && (rdp.othermode_l & 0x80)) //CLR_ON_CVG without FORCE_BL
+    A_BLEND (GR_BLEND_ZERO, GR_BLEND_ONE);
+  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.hacks&hack_PMario) && (blendmode == 0x5055))
+    {
+      A_BLEND (GR_BLEND_ZERO, GR_BLEND_ONE);
+    }
+    else if (blendmode == 0x4055) // Mario Golf
+    {
+      A_BLEND (GR_BLEND_ZERO, GR_BLEND_ONE);
+    }
+    else
+    {
+      A_BLEND (GR_BLEND_ONE, GR_BLEND_ZERO);
+    }
+  }
+
+  //hack
+  //*
+  if (settings.hacks&hack_ISS64)
+  {
+    if (rdp.othermode_l == 0xff5a6379)
+    {
+      A_BLEND (GR_BLEND_ZERO, GR_BLEND_SRC_ALPHA);
+    }
+    else if (rdp.othermode_l == 0x00504dd9) //players shadows. CVG_DST_WRAP
+    {
+      A_BLEND (GR_BLEND_ZERO, GR_BLEND_ONE);
+    }
+  }
+  else if (settings.hacks&hack_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);
+  if (const char * extstr = strstr(extensions, "COMBINE")) {
+    if (!strncmp(extstr, "COMBINE", 7)) {
+      LOG ("extensions ");
+      char strColorCombineExt[] = "grColorCombineExt";
+      cmb.grColorCombineExt = (GRCOLORCOMBINEEXT) grGetProcAddress(strColorCombineExt);
+      char strAlphaCombineExt[] = "grAlphaCombineExt";
+      cmb.grAlphaCombineExt = (GRCOLORCOMBINEEXT) grGetProcAddress(strAlphaCombineExt);
+      char strTexColorCombineExt[] = "grTexColorCombineExt";
+      cmb.grTexColorCombineExt = (GRTEXCOLORCOMBINEEXT) grGetProcAddress(strTexColorCombineExt);
+      char strTexAlphaCombineExt[] = "grTexAlphaCombineExt";
+      cmb.grTexAlphaCombineExt = (GRTEXCOLORCOMBINEEXT) grGetProcAddress(strTexAlphaCombineExt);
+      char strConstantColorValueExt[] = "grConstantColorValueExt";
+      cmb.grConstantColorValueExt = (GRCONSTANTCOLORVALUEEXT) grGetProcAddress(strConstantColorValueExt);
+      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 ()
+{
+  wxUint32 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 = GR_CMBX_ZERO;
+    ext_local_a = GR_CMBX_ZERO;
+  };
+  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 = GR_CMBX_ZERO;
+    ext_other_a = GR_CMBX_ZERO;
+  };
+  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;
+  default:
+    cmb.c_ext_c = GR_CMBX_ZERO;
+    cmb.c_ext_c_invert = 0;
+  }
+
+  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:
+  default:
+    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 ()
+{
+  wxUint32 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)
+{
+  wxUint32 tc_ext_a, tc_ext_a_mode, tc_ext_b, tc_ext_b_mode, tc_ext_c, tc_ext_d;
+  int  tc_ext_c_invert, tc_ext_d_invert;
+  wxUint32 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 = GR_CMBX_ZERO;
+    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 = 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;
+  }
+
+  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)
+{
+  wxUint32 ta_ext_a, ta_ext_a_mode, ta_ext_b, ta_ext_b_mode, ta_ext_c, ta_ext_d;
+  int  ta_ext_c_invert, ta_ext_d_invert;
+  wxUint32 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 = GR_CMBX_ZERO;
+    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 = 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;
+  }
+
+  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/source/gles2glide64/src/Glide64/Combine.h b/source/gles2glide64/src/Glide64/Combine.h
new file mode 100644 (file)
index 0000000..49f6774
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+#ifndef COMBINE_H
+#define COMBINE_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
+{
+  wxUint32 ccolor;  // constant color to set at the end, color and alpha
+  wxUint32 c_fnc, c_fac, c_loc, c_oth;  // grColorCombine flags
+  wxUint32 a_fnc, a_fac, a_loc, a_oth;  // grAlphaCombine flags
+  wxUint32 tex, tmu0_func, tmu0_fac, tmu0_invert, tmu1_func, tmu1_fac, tmu1_invert;
+  wxUint32 tmu0_a_func, tmu0_a_fac, tmu0_a_invert, tmu1_a_func, tmu1_a_fac, tmu1_a_invert;
+  int   dc0_lodbias, dc1_lodbias;
+  wxUint8  dc0_detailscale, dc1_detailscale;
+  float dc0_detailmax, dc1_detailmax;
+  float lodbias0, lodbias1;
+  wxUint32 abf1, abf2;
+  wxUint32 mod_0, modcolor_0, modcolor1_0, modcolor2_0, modfactor_0;
+  wxUint32 mod_1, modcolor_1, modcolor1_1, modcolor2_1, modfactor_1;
+  //combine extensions
+  wxUint32 c_ext_a, c_ext_a_mode, c_ext_b, c_ext_b_mode, c_ext_c, c_ext_d;
+  int  c_ext_c_invert, c_ext_d_invert;
+  wxUint32 a_ext_a, a_ext_a_mode, a_ext_b, a_ext_b_mode, a_ext_c, a_ext_d;
+  int  a_ext_c_invert, a_ext_d_invert;
+  wxUint32 t0c_ext_a, t0c_ext_a_mode, t0c_ext_b, t0c_ext_b_mode, t0c_ext_c, t0c_ext_d;
+  int  t0c_ext_c_invert, t0c_ext_d_invert;
+  wxUint32 t0a_ext_a, t0a_ext_a_mode, t0a_ext_b, t0a_ext_b_mode, t0a_ext_c, t0a_ext_d;
+  int  t0a_ext_c_invert, t0a_ext_d_invert;
+  wxUint32 t1c_ext_a, t1c_ext_a_mode, t1c_ext_b, t1c_ext_b_mode, t1c_ext_c, t1c_ext_d;
+  int  t1c_ext_c_invert, t1c_ext_d_invert;
+  wxUint32 t1a_ext_a, t1a_ext_a_mode, t1a_ext_b, t1a_ext_b_mode, t1a_ext_c, t1a_ext_d;
+  int  t1a_ext_c_invert, t1a_ext_d_invert;
+  GRCOLORCOMBINEEXT    grColorCombineExt;
+  GRCOLORCOMBINEEXT    grAlphaCombineExt;
+  GRTEXCOLORCOMBINEEXT grTexColorCombineExt;
+  GRTEXCOLORCOMBINEEXT grTexAlphaCombineExt;
+  GRCONSTANTCOLORVALUEEXT grConstantColorValueExt;
+  wxUint32 tex_ccolor;  
+  int combine_ext;
+  wxUint8 cmb_ext_use;
+  wxUint8 tex_cmb_ext_use;
+  wxUint32 shade_mod_hash;  
+} 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/source/gles2glide64/src/Glide64/Config.cpp b/source/gles2glide64/src/Glide64/Config.cpp
new file mode 100755 (executable)
index 0000000..a133070
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+* 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 "Gfx_1.3.h"
+#include "Config.h"
+#include "m64p.h"
+#include "rdp.h"
+
+#ifndef OLDAPI
+
+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-Glide64mk2", &video_glide64_section) != M64ERR_SUCCESS)
+    {
+        ERRLOG("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;
+}
+
+int Config_ReadScreenInt(const char *itemname)
+{
+    return ConfigGetParamInt(video_general_section, itemname);
+}
+
+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;
+}
+
+BOOL Config_ReadInt(const char *itemname, const char *desc, int def_value, int create, int isBoolean)
+{
+    VLOG("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);
+    }
+
+}
+#else
+
+// Resolutions, MUST be in the correct order (SST1VID.H)
+wxUint32 resolutions[0x18][2] = {
+  { 320, 200 },
+  { 320, 240 },
+  { 400, 256 },
+  { 512, 384 },
+  { 640, 200 },
+  { 640, 350 },
+  { 640, 400 },
+  { 640, 480 },
+  { 800, 600 },
+  { 960, 720 },
+  { 800, 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 }
+};
+
+
+BOOL Config_Open()
+{
+  INI_Open();
+  if(INI_FindSection("SETTINGS",FALSE) == FALSE) {
+    INI_Close();
+    ERRLOG("Could not open configuration");
+    return FALSE;
+  }
+  return TRUE;
+}
+
+int Config_ReadScreenInt(const char *itemname) {
+  int res_data = Config_ReadInt("resolution", NULL, 7, FALSE, FALSE);
+  if(!strcmp("ScreenWidth", itemname))
+    return resolutions[res_data][0];
+  else if(!strcmp("ScreenHeight", itemname))
+    return resolutions[res_data][1];
+  else return FALSE;
+}
+
+BOOL Config_ReadInt(const char *itemname, const char *desc, int def_value, int create, int isBoolean) {
+    VLOG("Getting value %s", itemname);
+    int z = INI_ReadInt(itemname, def_value, FALSE);
+    if(isBoolean) z=(z && 1);
+    return z;
+}
+
+#endif
+
+#ifdef TEXTURE_FILTER
+wxUint32 texfltr[] = {
+  NO_FILTER, //"None"
+  SMOOTH_FILTER_1, //"Smooth filtering 1"
+  SMOOTH_FILTER_2, //"Smooth filtering 2"
+  SMOOTH_FILTER_3, //"Smooth filtering 3"
+  SMOOTH_FILTER_4, //"Smooth filtering 4"
+  SHARP_FILTER_1,  //"Sharp filtering 1"
+  SHARP_FILTER_2,  //"Sharp filtering 2"
+};
+
+wxUint32 texenht[] = {
+  NO_ENHANCEMENT,    //"None"
+  NO_ENHANCEMENT,    //"Store"
+  X2_ENHANCEMENT,    //"X2"
+  X2SAI_ENHANCEMENT, //"X2SAI"
+  HQ2X_ENHANCEMENT,  //"HQ2X"
+  HQ2XS_ENHANCEMENT, //"HQ2XS"
+  LQ2X_ENHANCEMENT,  //"LQ2X"
+  LQ2XS_ENHANCEMENT, //"LQ2XS"
+  HQ4X_ENHANCEMENT,  //"HQ4X"
+};
+
+wxUint32 texcmpr[] = {
+  //NO_COMPRESSION,   //"None"
+  //  NCC_COMPRESSION,  //"NCC"
+  S3TC_COMPRESSION, //"S3TC"
+  FXT1_COMPRESSION, //"FXT1"
+};
+
+wxUint32 texhirs[] = {
+  NO_HIRESTEXTURES,   //"Do not use"
+  RICE_HIRESTEXTURES,  //"Rice format"
+  //  GHQ_HIRESTEXTURES, //"GlideHQ format"
+  //  JABO_HIRESTEXTURES, //"Jabo format"
+};
+#endif
+
+
diff --git a/source/gles2glide64/src/Glide64/Config.h b/source/gles2glide64/src/Glide64/Config.h
new file mode 100755 (executable)
index 0000000..eec3efd
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+* 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();
+int Config_ReadScreenInt(const char *itemname);
+PackedScreenResolution Config_ReadScreenSettings();
+BOOL Config_ReadInt(const char *itemname, const char *desc, int def_value, int create=TRUE, BOOL isBoolean=TRUE);
+
+
+#endif /* CONFIG_H */
+
diff --git a/source/gles2glide64/src/Glide64/Debugger.cpp b/source/gles2glide64/src/Glide64/Debugger.cpp
new file mode 100644 (file)
index 0000000..79e5286
--- /dev/null
@@ -0,0 +1,1020 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+#include "Gfx_1.3.h"
+#include "Util.h"
+#include "Debugger.h"
+
+GLIDE64_DEBUGGER _debugger;
+
+#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
+
+int  grid = 0;
+static const char *tri_type[4] = { "TRIANGLE", "TEXRECT", "FILLRECT", "BACKGROUND" };
+
+//Platform-specific stuff
+#ifndef WIN32
+typedef struct dbgPOINT {
+   int x;
+   int y;
+} POINT;
+#endif
+void DbgCursorPos(POINT * pt)
+{
+#ifdef __WINDOWS__
+  GetCursorPos (pt);
+#else //!todo find a way to get cursor position on Unix
+  pt->x = pt->y = 0;
+#endif
+}
+
+//
+// debug_init - initialize the debugger
+//
+
+void debug_init ()
+{
+  _debugger.capture = 0;
+  _debugger.selected = SELECTED_TRI;
+  _debugger.screen = NULL;
+  _debugger.tri_list = NULL;
+  _debugger.tri_last = NULL;
+  _debugger.tri_sel = NULL;
+  _debugger.tmu = 0;
+
+  _debugger.tex_scroll = 0;
+  _debugger.tex_sel = 0;
+
+  _debugger.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 (_debugger.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 (_debugger.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 (wxUint32 x=0; x<16; x++)
+    {
+      wxUint32 y = i+_debugger.tex_scroll;
+      if (x+y*16 >= (wxUint32)rdp.n_cached[_debugger.tmu]) break;
+      CACHE_LUT * cache = voodoo.tex_UMA?rdp.cache[0]:rdp.cache[_debugger.tmu];
+
+      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*cache[x+y*16].scale_x), SY(512+64.0f*i), 1, 1,    255*cache[x+y*16].scale_x, 0, 0, 0, {0, 0, 0, 0} },
+          { SX(x*64.0f), SY(512+64.0f*i+64.0f*cache[x+y*16].scale_y), 1, 1,    0, 255*cache[x+y*16].scale_y, 0, 0, {0, 0, 0, 0} },
+          { SX(x*64.0f+64.0f*cache[x+y*16].scale_x), SY(512+64.0f*i+64.0f*cache[x+y*16].scale_y), 1, 1, 255*cache[x+y*16].scale_x, 255*cache[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(_debugger.tmu,
+        voodoo.tex_min_addr[_debugger.tmu] + cache[x+y*16].tmem_addr,
+        GR_MIPMAPLEVELMASK_BOTH,
+        &cache[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)
+//
+
+void debug_capture ()
+{
+  wxUint32 i,j;
+
+  if (_debugger.tri_list == NULL) goto END;
+  _debugger.tri_sel = _debugger.tri_list;
+  _debugger.selected = SELECTED_TRI;
+
+  // Connect the list
+  _debugger.tri_last->pNext = _debugger.tri_list;
+
+  while (!CheckKeyPressed(G64_VK_INSERT, 0x0001)) //INSERT
+  {
+    // Check for clicks
+    if (CheckKeyPressed(G64_VK_LBUTTON, 0x0001)) //LBUTTON
+    {
+      POINT pt;
+      DbgCursorPos(&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 (_debugger.tri_sel == NULL) tri = _debugger.tri_list, start = _debugger.tri_list;
+        else tri = _debugger.tri_sel->pNext, start = _debugger.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; i<tri->nv; 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
+          {
+            _debugger.tri_sel = tri;
+            break;
+          }
+
+          for (i=0; i<tri->nv; 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
+          {
+            _debugger.tri_sel = tri;
+            break;
+          }
+
+          tri = tri->pNext;
+        } while (tri != start);
+      }
+      else
+      {
+        // on a texture
+        _debugger.tex_sel = (((wxUint32)((pt.y-SY(512))/SY(64))+_debugger.tex_scroll)*16) +
+          (wxUint32)(pt.x/SX(64));
+      }
+    }
+
+    debug_keys ();
+
+    grBufferClear (0, 0, 0xFFFF);
+
+    // Copy the screen capture back to the screen:
+    grLfbWriteRegion(GR_BUFFER_BACKBUFFER,
+      (wxUint32)rdp.offset_x,
+      (wxUint32)rdp.offset_y,
+      GR_LFB_SRC_FMT_565,
+      settings.res_x,
+      settings.res_y,
+      FXFALSE,
+      settings.res_x<<1,
+      _debugger.screen);
+
+    // Do the cacheviewer
+    debug_cacheviewer ();
+
+    // **
+    // 3/16/02: Moved texture viewer out of loop, remade it.  Now it's simpler, and
+    //   supports TMU1. [Dave2001]
+    // Original by Gugaman
+
+    CACHE_LUT * cache = voodoo.tex_UMA?rdp.cache[0]:rdp.cache[_debugger.tmu];
+    if (_debugger.page == PAGE_TEX_INFO)
+    {
+      grTexSource(_debugger.tmu,
+        voodoo.tex_min_addr[_debugger.tmu] + cache[_debugger.tex_sel].tmem_addr,
+        GR_MIPMAPLEVELMASK_BOTH,
+        &cache[_debugger.tex_sel].t_info);
+
+#ifdef SHOW_FULL_TEXVIEWER
+      float scx = 1.0f;
+      float scy = 1.0f;
+#else
+      float scx = cache[_debugger.tex_sel].scale_x;
+      float scy = cache[_debugger.tex_sel].scale_y;
+#endif
+      VERTEX v[4] = {
+              { SX(704.0f), SY(221.0f), 1, 1, 0, 0,  0, 0, {0, 0, 0, 0} },
+              { SX(704.0f+256.0f*scx), SY(221.0f), 1, 1, 255*scx, 0, 255*scx, 0, {0, 0, 0, 0} },
+              { SX(704.0f), SY(221.0f+256.0f*scy), 1, 1, 0, 255*scy, 0, 255*scy, {0, 0, 0, 0} },
+              { SX(704.0f+256.0f*scx), SY(221.0f+256.0f*scy), 1, 1, 255*scx, 255*scy, 255*scx, 255*scy, {0, 0, 0, 0} }
+              };
+      ConvertCoordsConvert (v, 4);
+      VERTEX *varr[4] = { &v[0], &v[1], &v[2], &v[3] };
+      grDrawVertexArray (GR_TRIANGLE_STRIP, 4, varr);
+    }
+
+    // **
+
+    grTexFilterMode (GR_TMU0,
+      GR_TEXTUREFILTER_BILINEAR,
+      GR_TEXTUREFILTER_BILINEAR);
+
+    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 (0x0000FFFF);
+
+    VERTEX *v[8];
+    if (_debugger.tri_sel)
+    {
+      // Draw the outline around the selected triangle
+      for (i=0; i<_debugger.tri_sel->nv; i++)
+      {
+        j=i+1;
+        if (j>=_debugger.tri_sel->nv) j=0;
+
+        grDrawLine (&_debugger.tri_sel->v[i], &_debugger.tri_sel->v[j]);
+
+        v[i] = &_debugger.tri_sel->v[i];
+      }
+    }
+
+    // and the selected texture
+    wxUint32 t_y = ((_debugger.tex_sel & 0xFFFFFFF0) >> 4) - _debugger.tex_scroll;
+    wxUint32 t_x = _debugger.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 (_debugger.tri_sel)
+      grDrawVertexArray (GR_TRIANGLE_FAN, _debugger.tri_sel->nv, &v);
+
+    // Draw the outline of the cacheviewer
+    if (_debugger.page == PAGE_TEX_INFO)
+    {
+      float scx = cache[_debugger.tex_sel].scale_x;
+      float scy = cache[_debugger.tex_sel].scale_y;
+
+      // And the grid
+      if (grid)
+      {
+        grConstantColorValue (COL_GRID);
+
+        float scale_y = (256.0f * scy) / (float)cache[_debugger.tex_sel].height;
+        for (int y=0; y<=(int)cache[_debugger.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)cache[_debugger.tex_sel].width;
+        for (int x=0; x<=(int)cache[_debugger.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
+      voodoo.tex_min_addr[_debugger.tmu]+ offset_font,
+      GR_MIPMAPLEVELMASK_BOTH,
+      &fontTex);
+
+    static const 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 (_debugger.page == PAGE_GENERAL && _debugger.tri_sel)
+    {
+      COL_CATEGORY();
+      OUTPUT ("GENERAL (page 1):",0);
+      COL_TEXT();
+      OUTPUT ("tri #%d", _debugger.tri_sel->tri_n);
+      OUTPUT ("type: %s", tri_type[_debugger.tri_sel->type]);
+      OUTPUT ("geom:   0x%08lx", _debugger.tri_sel->geom_mode);
+      OUTPUT ("othermode_h: 0x%08lx", _debugger.tri_sel->othermode_h);
+      OUTPUT ("othermode_l: 0x%08lx", _debugger.tri_sel->othermode_l);
+      OUTPUT ("flags: 0x%08lx", _debugger.tri_sel->flags);
+      OUTPUT ("",0);
+      COL_CATEGORY();
+      OUTPUT ("COMBINE:",0);
+      COL_TEXT();
+      OUTPUT ("cycle_mode: %s", cycle_mode_s[_debugger.tri_sel->cycle_mode]);
+      OUTPUT ("cycle1: 0x%08lx", _debugger.tri_sel->cycle1);
+      OUTPUT ("cycle2: 0x%08lx", _debugger.tri_sel->cycle2);
+      if (_debugger.tri_sel->uncombined & 1)
+        COL_UCC();
+      else
+        COL_CC();
+      OUTPUT ("a0: %s", Mode0[(_debugger.tri_sel->cycle1)&0x0000000F]);
+      OUTPUT ("b0: %s", Mode1[(_debugger.tri_sel->cycle1>>4)&0x0000000F]);
+      OUTPUT ("c0: %s", Mode2[(_debugger.tri_sel->cycle1>>8)&0x0000001F]);
+      OUTPUT ("d0: %s", Mode3[(_debugger.tri_sel->cycle1>>13)&0x00000007]);
+      if (_debugger.tri_sel->uncombined & 2)
+        COL_UAC();
+      else
+        COL_AC();
+      OUTPUT ("Aa0: %s", Alpha0[(_debugger.tri_sel->cycle1>>16)&0x00000007]);
+      OUTPUT ("Ab0: %s", Alpha1[(_debugger.tri_sel->cycle1>>19)&0x00000007]);
+      OUTPUT ("Ac0: %s", Alpha2[(_debugger.tri_sel->cycle1>>22)&0x00000007]);
+      OUTPUT ("Ad0: %s", Alpha3[(_debugger.tri_sel->cycle1>>25)&0x00000007]);
+      if (_debugger.tri_sel->uncombined & 1)
+        COL_UCC();
+      else
+        COL_CC();
+      OUTPUT ("a1: %s", Mode0[(_debugger.tri_sel->cycle2)&0x0000000F]);
+      OUTPUT ("b1: %s", Mode1[(_debugger.tri_sel->cycle2>>4)&0x0000000F]);
+      OUTPUT ("c1: %s", Mode2[(_debugger.tri_sel->cycle2>>8)&0x0000001F]);
+      OUTPUT ("d1: %s", Mode3[(_debugger.tri_sel->cycle2>>13)&0x00000007]);
+      if (_debugger.tri_sel->uncombined & 2)
+        COL_UAC();
+      else
+        COL_AC();
+      OUTPUT ("Aa1: %s", Alpha0[(_debugger.tri_sel->cycle2>>16)&0x00000007]);
+      OUTPUT ("Ab1: %s", Alpha1[(_debugger.tri_sel->cycle2>>19)&0x00000007]);
+      OUTPUT ("Ac1: %s", Alpha2[(_debugger.tri_sel->cycle2>>22)&0x00000007]);
+      OUTPUT ("Ad1: %s", Alpha3[(_debugger.tri_sel->cycle2>>25)&0x00000007]);
+    }
+    if ((_debugger.page == PAGE_TEX1 || _debugger.page == PAGE_TEX2) && _debugger.tri_sel)
+    {
+      COL_CATEGORY ();
+      OUTPUT1 ("TEXTURE %d (page %d):", _debugger.page-PAGE_TEX1, 2+_debugger.page-PAGE_TEX1);
+      COL_TEXT();
+      int tmu = _debugger.page - PAGE_TEX1;
+      OUTPUT1 ("cur cache: %d,%d", _debugger.tri_sel->t[tmu].cur_cache[tmu]&0x0F, _debugger.tri_sel->t[tmu].cur_cache[tmu]>>4);
+      OUTPUT ("tex_size: %d", _debugger.tri_sel->t[tmu].size);
+      OUTPUT ("tex_format: %d", _debugger.tri_sel->t[tmu].format);
+      OUTPUT ("width: %d", _debugger.tri_sel->t[tmu].width);
+      OUTPUT ("height: %d", _debugger.tri_sel->t[tmu].height);
+      OUTPUT ("palette: %d", _debugger.tri_sel->t[tmu].palette);
+      OUTPUT ("clamp_s: %d", _debugger.tri_sel->t[tmu].clamp_s);
+      OUTPUT ("clamp_t: %d", _debugger.tri_sel->t[tmu].clamp_t);
+      OUTPUT ("mirror_s: %d", _debugger.tri_sel->t[tmu].mirror_s);
+      OUTPUT ("mirror_t: %d", _debugger.tri_sel->t[tmu].mirror_t);
+      OUTPUT ("mask_s: %d", _debugger.tri_sel->t[tmu].mask_s);
+      OUTPUT ("mask_t: %d", _debugger.tri_sel->t[tmu].mask_t);
+      OUTPUT ("shift_s: %d", _debugger.tri_sel->t[tmu].shift_s);
+      OUTPUT ("shift_t: %d", _debugger.tri_sel->t[tmu].shift_t);
+      OUTPUT ("ul_s: %d", _debugger.tri_sel->t[tmu].ul_s);
+      OUTPUT ("ul_t: %d", _debugger.tri_sel->t[tmu].ul_t);
+      OUTPUT ("lr_s: %d", _debugger.tri_sel->t[tmu].lr_s);
+      OUTPUT ("lr_t: %d", _debugger.tri_sel->t[tmu].lr_t);
+      OUTPUT ("t_ul_s: %d", _debugger.tri_sel->t[tmu].t_ul_s);
+      OUTPUT ("t_ul_t: %d", _debugger.tri_sel->t[tmu].t_ul_t);
+      OUTPUT ("t_lr_s: %d", _debugger.tri_sel->t[tmu].t_lr_s);
+      OUTPUT ("t_lr_t: %d", _debugger.tri_sel->t[tmu].t_lr_t);
+      OUTPUT ("scale_s: %f", _debugger.tri_sel->t[tmu].scale_s);
+      OUTPUT ("scale_t: %f", _debugger.tri_sel->t[tmu].scale_t);
+      OUTPUT ("s_mode: %s", str_cm[((_debugger.tri_sel->t[tmu].clamp_s << 1) | _debugger.tri_sel->t[tmu].mirror_s)&3]);
+      OUTPUT ("t_mode: %s", str_cm[((_debugger.tri_sel->t[tmu].clamp_t << 1) | _debugger.tri_sel->t[tmu].mirror_t)&3]);
+    }
+    if (_debugger.page == PAGE_COLORS && _debugger.tri_sel)
+    {
+      COL_CATEGORY();
+      OUTPUT ("COLORS (page 4)", 0);
+      COL_TEXT();
+      OUTPUT ("fill:  %08lx", _debugger.tri_sel->fill_color);
+      OUTPUT ("prim:  %08lx", _debugger.tri_sel->prim_color);
+      OUTPUT ("blend: %08lx", _debugger.tri_sel->blend_color);
+      OUTPUT ("env:   %08lx", _debugger.tri_sel->env_color);
+      OUTPUT ("fog: %08lx", _debugger.tri_sel->fog_color);
+      OUTPUT ("prim_lodmin:  %d", _debugger.tri_sel->prim_lodmin);
+      OUTPUT ("prim_lodfrac: %d", _debugger.tri_sel->prim_lodfrac);
+    }
+    if (_debugger.page == PAGE_FBL && _debugger.tri_sel)
+    {
+      COL_CATEGORY();
+      OUTPUT ("BLENDER", 0);
+      COL_TEXT();
+      OUTPUT ("fbl_a0: %s", FBLa[(_debugger.tri_sel->othermode_l>>30)&0x3]);
+      OUTPUT ("fbl_b0: %s", FBLb[(_debugger.tri_sel->othermode_l>>26)&0x3]);
+      OUTPUT ("fbl_c0: %s", FBLc[(_debugger.tri_sel->othermode_l>>22)&0x3]);
+      OUTPUT ("fbl_d0: %s", FBLd[(_debugger.tri_sel->othermode_l>>18)&0x3]);
+      OUTPUT ("fbl_a1: %s", FBLa[(_debugger.tri_sel->othermode_l>>28)&0x3]);
+      OUTPUT ("fbl_b1: %s", FBLb[(_debugger.tri_sel->othermode_l>>24)&0x3]);
+      OUTPUT ("fbl_c1: %s", FBLc[(_debugger.tri_sel->othermode_l>>20)&0x3]);
+      OUTPUT ("fbl_d1: %s", FBLd[(_debugger.tri_sel->othermode_l>>16)&0x3]);
+      OUTPUT ("", 0);
+      OUTPUT ("fbl:    %08lx", _debugger.tri_sel->othermode_l&0xFFFF0000);
+      OUTPUT ("fbl #1: %08lx", _debugger.tri_sel->othermode_l&0xCCCC0000);
+      OUTPUT ("fbl #2: %08lx", _debugger.tri_sel->othermode_l&0x33330000);
+    }
+    if (_debugger.page == PAGE_OTHERMODE_L && _debugger.tri_sel)
+    {
+      wxUint32 othermode_l = _debugger.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 (_debugger.page == PAGE_OTHERMODE_H && _debugger.tri_sel)
+    {
+      wxUint32 othermode_h = _debugger.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 (_debugger.page == PAGE_TEXELS && _debugger.tri_sel)
+    {
+      // change these to output whatever you need, ou for triangles, or u0 for texrects
+      COL_TEXT();
+      OUTPUT ("n: %d", _debugger.tri_sel->nv);
+      OUTPUT ("",0);
+      for (j=0; j<_debugger.tri_sel->nv; j++)
+      {
+        OUTPUT1 ("v[%d].s0: %f", j, _debugger.tri_sel->v[j].ou);
+        OUTPUT1 ("v[%d].t0: %f", j, _debugger.tri_sel->v[j].ov);
+      }
+      OUTPUT ("",0);
+      for (j=0; j<_debugger.tri_sel->nv; j++)
+      {
+        OUTPUT1 ("v[%d].s1: %f", j, _debugger.tri_sel->v[j].u0);
+        OUTPUT1 ("v[%d].t1: %f", j, _debugger.tri_sel->v[j].v0);
+      }
+    }
+    if (_debugger.page == PAGE_COORDS && _debugger.tri_sel)
+    {
+      COL_TEXT();
+      OUTPUT ("n: %d", _debugger.tri_sel->nv);
+      for (j=0; j<_debugger.tri_sel->nv; j++)
+      {
+        OUTPUT1 ("v[%d].x: %f", j, _debugger.tri_sel->v[j].x);
+        OUTPUT1 ("v[%d].y: %f", j, _debugger.tri_sel->v[j].y);
+        OUTPUT1 ("v[%d].z: %f", j, _debugger.tri_sel->v[j].z);
+        OUTPUT1 ("v[%d].w: %f", j, _debugger.tri_sel->v[j].w);
+        OUTPUT1 ("v[%d].f: %f", j, 1.0f/_debugger.tri_sel->v[j].f);
+        OUTPUT1 ("v[%d].r: %d", j, _debugger.tri_sel->v[j].r);
+        OUTPUT1 ("v[%d].g: %d", j, _debugger.tri_sel->v[j].g);
+        OUTPUT1 ("v[%d].b: %d", j, _debugger.tri_sel->v[j].b);
+        OUTPUT1 ("v[%d].a: %d", j, _debugger.tri_sel->v[j].a);
+      }
+    }
+    if (_debugger.page == PAGE_TEX_INFO && _debugger.tex_sel < (wxUint32)rdp.n_cached[_debugger.tmu])
+    {
+      COL_CATEGORY();
+      OUTPUT ("CACHE (page 0)", 0);
+      COL_TEXT();
+      //OUTPUT ("t_mem: %08lx", rdp.cache[0][_debugger.tex_sel].t_mem);
+      //OUTPUT ("crc: %08lx", rdp.cache[0][_debugger.tex_sel].crc);
+      OUTPUT ("addr: %08lx", cache[_debugger.tex_sel].addr);
+      OUTPUT ("scale_x: %f", cache[_debugger.tex_sel].scale_x);
+      OUTPUT ("scale_y: %f", cache[_debugger.tex_sel].scale_y);
+      OUTPUT ("tmem_addr: %08lx", cache[_debugger.tex_sel].tmem_addr);
+      OUTPUT ("palette: %08lx", cache[_debugger.tex_sel].palette);
+      OUTPUT ("set_by: %08lx", cache[_debugger.tex_sel].set_by);
+      OUTPUT ("texrecting: %d", cache[_debugger.tex_sel].texrecting);
+
+      OUTPUT ("mod: %08lx", cache[_debugger.tex_sel].mod);
+      OUTPUT ("mod_col: %08lx", cache[_debugger.tex_sel].mod_color);
+      OUTPUT ("mod_col1: %08lx", cache[_debugger.tex_sel].mod_color1);
+      i=740;
+      output(800,(float)i,1,"width: %d", cache[_debugger.tex_sel].width);
+      i-=16;
+      output(800,(float)i,1,"height: %d", cache[_debugger.tex_sel].height);
+      i-=16;
+      output(800,(float)i,1,"format: %d", cache[_debugger.tex_sel].format);
+      i-=16;
+      output(800,(float)i,1,"size: %d", cache[_debugger.tex_sel].size);
+      i-=16;
+      output(800,(float)i,1,"crc: %08lx", cache[_debugger.tex_sel].crc);
+      i-=16;
+#ifdef TEXTURE_FILTER
+      output(800,(float)i,1,"RiceCrc: %08lx", (wxUint32)(rdp.cache[_debugger.tmu][_debugger.tex_sel].ricecrc&0xFFFFFFFF));
+      i-=16;
+      output(800,(float)i,1,"RicePalCrc: %08lx", (wxUint32)(rdp.cache[_debugger.tmu][_debugger.tex_sel].ricecrc>>32));
+      i-=16;
+#endif
+      output(800,(float)i,1,"flags: %08lx", cache[_debugger.tex_sel].flags);
+      i-=16;
+      output(800,(float)i,1,"line: %d", cache[_debugger.tex_sel].line);
+      i-=16;
+      output(800,(float)i,1,"mod_factor: %08lx", cache[_debugger.tex_sel].mod_factor);
+      i-=32;
+
+      output(800,(float)i,1,"lod: %s", str_lod[cache[_debugger.tex_sel].lod]);
+      i-=16;
+      output(800,(float)i,1,"aspect: %s", str_aspect[cache[_debugger.tex_sel].aspect + 3]);
+
+//  debug_texture(_debugger.tmu, cache[_debugger.tex_sel].addr, _debugger.tex_sel);
+    }
+
+    // Draw the vertex numbers
+    if (_debugger.tri_sel)
+    {
+      for (i=0; i<_debugger.tri_sel->nv; i++)
+      {
+        grConstantColorValue (0x000000FF);
+        output (_debugger.tri_sel->v[i].x+1, settings.scr_res_y-_debugger.tri_sel->v[i].y+1, 1,
+          "%d", i);
+        grConstantColorValue (0xFFFFFFFF);
+        output (_debugger.tri_sel->v[i].x, settings.scr_res_y-_debugger.tri_sel->v[i].y, 1,
+          "%d", i);
+      }
+    }
+
+    // Draw the cursor
+    debug_mouse ();
+
+    grBufferSwap (1);
+  }
+
+END:
+  // Release all data
+  delete [] _debugger.screen;
+  TRI_INFO *tri;
+  for (tri=_debugger.tri_list; tri != _debugger.tri_last;)
+  {
+    TRI_INFO *tmp = tri;
+    tri = tri->pNext;
+    delete [] tmp->v;
+    delete tmp;
+  }
+  delete [] tri->v;
+  delete tri;
+
+  // Reset all values
+  _debugger.capture = 0;
+  _debugger.selected = SELECTED_TRI;
+  _debugger.screen = NULL;
+  _debugger.tri_list = NULL;
+  _debugger.tri_last = NULL;
+  _debugger.tri_sel = NULL;
+  _debugger.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;
+  DbgCursorPos(&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, 0} },
+    { cx+32,    cy, 1, 1, 255,   0,   0, 0, {0, 0, 0, 0} },
+    { cx,    cy+32, 1, 1,   0, 255,   0, 0, {0, 0, 0, 0} },
+    { cx+32, cy+32, 1, 1, 255, 255,   0, 0, {0, 0, 0, 0} }
+    };
+
+  ConvertCoordsKeep (v, 4);
+
+  grTexSource(GR_TMU0,
+    voodoo.tex_min_addr[GR_TMU0] + offset_cursor,
+    GR_MIPMAPLEVELMASK_BOTH,
+    &cursorTex);
+
+  if (voodoo.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 (voodoo.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 (CheckKeyPressed(G64_VK_RIGHT, 0x0001) && _debugger.tri_sel)
+  {
+    TRI_INFO *start = _debugger.tri_sel;
+
+    while (_debugger.tri_sel->pNext != start)
+      _debugger.tri_sel = _debugger.tri_sel->pNext;
+  }
+
+  if (CheckKeyPressed(G64_VK_LEFT, 0x0001) && _debugger.tri_sel)
+    _debugger.tri_sel = _debugger.tri_sel->pNext;
+
+  // Check for page changes
+  if (CheckKeyPressed(G64_VK_1, 0x0001))
+    _debugger.page = PAGE_GENERAL;
+  if (CheckKeyPressed(G64_VK_2, 0x0001))
+    _debugger.page = PAGE_TEX1;
+  if (CheckKeyPressed(G64_VK_3, 0x0001))
+    _debugger.page = PAGE_TEX2;
+  if (CheckKeyPressed(G64_VK_4, 0x0001))
+    _debugger.page = PAGE_COLORS;
+  if (CheckKeyPressed(G64_VK_5, 0x0001))
+    _debugger.page = PAGE_FBL;
+  if (CheckKeyPressed(G64_VK_6, 0x0001))
+    _debugger.page = PAGE_OTHERMODE_L;
+  if (CheckKeyPressed(G64_VK_7, 0x0001))
+    _debugger.page = PAGE_OTHERMODE_H;
+  if (CheckKeyPressed(G64_VK_8, 0x0001))
+    _debugger.page = PAGE_TEXELS;
+  if (CheckKeyPressed(G64_VK_9, 0x0001))
+    _debugger.page = PAGE_COORDS;
+  if (CheckKeyPressed(G64_VK_0, 0x0001))
+    _debugger.page = PAGE_TEX_INFO;
+  if (CheckKeyPressed(G64_VK_Q, 0x0001))
+    _debugger.tmu = 0;
+  if (CheckKeyPressed(G64_VK_W, 0x0001))
+    _debugger.tmu = 1;
+
+  if (CheckKeyPressed(G64_VK_G, 0x0001))
+    grid = !grid;
+
+  // Go to texture
+  if (CheckKeyPressed(G64_VK_SPACE, 0x0001))
+  {
+    int tile = -1;
+    if (_debugger.page == PAGE_TEX2)
+      tile = 1;
+    else
+      tile = 0;
+    if (tile != -1)
+    {
+      _debugger.tmu = _debugger.tri_sel->t[tile].tmu;
+      _debugger.tex_sel = _debugger.tri_sel->t[tile].cur_cache[_debugger.tmu];
+      _debugger.tex_scroll = (_debugger.tri_sel->t[tile].cur_cache[_debugger.tmu] >> 4) - 1;
+    }
+  }
+
+  // Go to triangle
+  CACHE_LUT * cache = voodoo.tex_UMA?rdp.cache[0]:rdp.cache[_debugger.tmu];
+  if (CheckKeyPressed(G64_VK_CONTROL, 0x0001))
+  {
+    int count = rdp.debug_n - cache[_debugger.tex_sel].uses - 1;
+    if (cache[_debugger.tex_sel].last_used == frame_count)
+    {
+      TRI_INFO *t = _debugger.tri_list;
+      while (count && t) {
+        t = t->pNext;
+        count --;
+      }
+      _debugger.tri_sel = t;
+    }
+    else
+      _debugger.tri_sel = NULL;
+  }
+
+  if (CheckKeyPressed(G64_VK_A, 0x0001))
+    _debugger.draw_mode = 0;  // texture & texture alpha
+  if (CheckKeyPressed(G64_VK_S, 0x0001))
+    _debugger.draw_mode = 1;  // texture
+  if (CheckKeyPressed(G64_VK_D, 0x0001))
+    _debugger.draw_mode = 2;  // texture alpha
+
+  // Check for texture scrolling
+  if (CheckKeyPressed(G64_VK_DOWN, 0x0001))
+    _debugger.tex_scroll ++;
+  if (CheckKeyPressed(G64_VK_UP, 0x0001))
+    _debugger.tex_scroll --;
+}
+
+//
+// output - output debugger text
+//
+
+void output (float x, float y, int scale, const char *fmt, ...)
+{
+  va_list ap;
+  va_start(ap,fmt);
+  vsprintf(out_buf, fmt, ap);
+  va_end(ap);
+
+  wxUint8 c,r;
+  for (wxUint32 i=0; i<strlen(out_buf); i++)
+  {
+    c = ((out_buf[i]-32) & 0x1F) * 8;//<< 3;
+    r = (((out_buf[i]-32) & 0xE0) >> 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/source/gles2glide64/src/Glide64/Debugger.h b/source/gles2glide64/src/Glide64/Debugger.h
new file mode 100644 (file)
index 0000000..131c302
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+#define SELECTED_NONE  0x00000000
+#define SELECTED_TRI   0x00000001
+#define SELECTED_TEX   0x00000002
+
+typedef struct TEX_INFO_t
+{
+       wxUint32 cur_cache[2];  // Current cache #
+       wxUint8 format;
+       wxUint8 size;
+       wxUint32 width, height;
+       wxUint16 line, wid;
+       wxUint8 palette;
+       wxUint8 clamp_s, clamp_t;
+       wxUint8 mirror_s, mirror_t;
+       wxUint8 mask_s, mask_t;
+       wxUint8 shift_s, shift_t;
+       wxUint16 ul_s, ul_t, lr_s, lr_t;
+       wxUint16 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
+{
+       wxUint32        nv;                     // Number of vertices
+       VERTEX  *v;                     // Vertices (2d screen coords) of the triangle, used to outline
+       wxUint32        cycle1, cycle2, cycle_mode;     // Combine mode at the time of rendering
+       wxUint8 uncombined;     // which is uncombined: 0x01=color 0x02=alpha 0x03=both
+       wxUint32        geom_mode;      // geometry mode flags
+       wxUint32        othermode_h;    // setothermode_h flags
+       wxUint32        othermode_l;    // setothermode_l flags
+       wxUint32        tri_n;          // Triangle number
+       wxUint32        flags;
+
+       int             type;   // 0-normal, 1-texrect, 2-fillrect
+
+       // texture info
+       TEX_INFO t[2];
+
+       // colors
+       wxUint32 fog_color;
+       wxUint32 fill_color;
+       wxUint32 prim_color;
+       wxUint32 blend_color;
+       wxUint32 env_color;
+       wxUint32 prim_lodmin, prim_lodfrac;
+
+       TRI_INFO_t      *pNext;
+} TRI_INFO;
+
+typedef struct DEBUGGER_t
+{
+       int capture;    // Capture moment for debugging?
+
+       wxUint32 selected;      // Selected object (see flags above)
+       TRI_INFO *tri_sel;
+
+       wxUint32 tex_scroll;    // texture scrolling
+       wxUint32 tex_sel;
+
+       // CAPTURE INFORMATION
+       wxUint8 *screen;                // Screen capture
+       TRI_INFO *tri_list;     // Triangle information list
+       TRI_INFO *tri_last;     // Last in the list (first in)
+
+       wxUint32 tmu;   // tmu #
+
+       wxUint32 draw_mode;
+
+       // Page number
+       int page;
+
+} GLIDE64_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
+
+extern GLIDE64_DEBUGGER _debugger;
+
+void debug_init ();
+void debug_capture ();
+void debug_cacheviewer ();
+void debug_mouse ();
+void debug_keys ();
+void output (float x, float y, int scale, const char *fmt, ...);
diff --git a/source/gles2glide64/src/Glide64/DepthBufferRender.cpp b/source/gles2glide64/src/Glide64/DepthBufferRender.cpp
new file mode 100755 (executable)
index 0000000..fb357d8
--- /dev/null
@@ -0,0 +1,387 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+//
+// 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 "Gfx_1.3.h"
+#include "rdp.h"
+#include "DepthBufferRender.h"
+
+wxUint16 * zLUT = 0;
+
+void ZLUT_init()
+{
+  if (zLUT)
+    return;
+  zLUT = new wxUint16[0x40000];
+  for(int i=0; i<0x40000; i++)
+  {
+    wxUint32 exponent = 0;
+    wxUint32 testbit = 1 << 17;
+    while((i & testbit) && (exponent < 7))
+    {
+      exponent++;
+      testbit = 1 << (17 - exponent);
+    }
+    
+    wxUint32 mantissa = (i >> (6 - (6 < exponent ? 6 : exponent))) & 0x7ff;
+    zLUT[i] = (wxUint16)(((exponent << 11) | mantissa) << 2);
+  }
+}
+
+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
+
+#ifdef HAVE_GLES
+// using float should be faster than int in fact, especialy if using NEON
+static float right_height, left_height;
+static float right_x, right_dxdy, left_x, left_dxdy;
+static float left_z, left_dzdy;
+
+__inline float iceil(int x)
+{
+       return cellf((float)x*(1.0f/65536.0f));
+}
+__inline float i2float(int x)
+{
+       return (float)x*(1.0f/65536.0f);
+}
+__inline int float2i(float x)
+{
+       return x*65536.0f;
+}
+
+#else
+
+static int right_height, left_height;
+static int right_x, right_dxdy, left_x, left_dxdy;
+static int left_z, left_dzdy;
+
+__inline int imul16(int x, int y)        // (x * y) >> 16
+{
+    return (((long long)x) * ((long long)y)) >> 16;
+}
+
+__inline int imul14(int x, int y)        // (x * y) >> 14
+{
+    return (((long long)x) * ((long long)y)) >> 14;
+}
+__inline int idiv16(int x, int y)        // (x << 16) / y
+{
+    //x = (((long long)x) << 16) / ((long long)y);
+ /*   
+  eax = x;
+  ebx = y;
+  edx = x;
+  (x << 16) | ()
+   */ 
+#if !defined(__GNUC__) && !defined(NO_ASM)
+  __asm {
+        mov   eax, x
+        mov   ebx, y
+        mov   edx,eax   
+        sar   edx,16
+        shl   eax,16    
+        idiv  ebx  
+        mov   x, eax
+    }
+#elif !defined(NO_ASM)
+    int reminder;
+    asm ("idivl %[divisor]"
+          : "=a" (x), "=d" (reminder)
+          : [divisor] "g" (y), "d" (x >> 16), "a" (x << 16));
+#else
+       x = (((long long)x) << 16) / ((long long)y);
+#endif
+    return x;
+}
+
+__inline int iceil(int x)
+{
+  x +=  0xffff;
+  return (x >> 16);
+}
+#endif
+
+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
+  
+  #ifdef HAVE_GLES
+  right_dxdy  = i2float(v2->x - v1->x)/i2float(v2->y - v1->y);
+  #else
+  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);
+  }
+  #endif
+  
+  // Prestep initial values
+  
+  #ifdef HAVE_GLES
+  float prestep = iceil(v1->y) - i2float(v1->y);
+  right_x = i2float(v1->x) + prestep*right_dxdy;
+  #else
+  int prestep = (iceil(v1->y) << 16) - v1->y;
+  right_x = v1->x + imul16(prestep, right_dxdy);
+  #endif
+}
+
+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
+  
+  #ifdef HAVE_GLES
+  float invheight = 1.0f/i2float(v2->y - v1->y)
+  left_dxdy  = i2float(v2->x - v1->x)*invheight;
+  left_dzdy  = i2float(v2->z - v1->z)*invheight;
+  #else
+  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);
+  }
+  #endif
+  
+  // Prestep initial values
+  
+  #ifdef HAVE_GLES
+  float prestep = iceil(v1->y) - i2float(v1->y);
+  left_x = i2float(v1->x) + prestep*left_dxdy;
+  left_z = i2float(v1->z) + prestep*left_dzdy;
+  #else
+  int prestep = (iceil(v1->y) << 16) - v1->y;
+  left_x = v1->x + imul16(prestep, left_dxdy);
+  left_z = v1->z + imul16(prestep, left_dzdy);
+  #endif
+}
+
+
+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; n<vertices; n++) {
+    if(vtx->y < 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);
+  
+  wxUint16 * destptr = (wxUint16*)(gfx.RDRAM+rdp.zimg);
+  int y1 = iceil(min_y);
+  if (y1 >= (int)rdp.scissor_o.lr_y) return;
+  int shift;
+  
+  for(;;)
+  {
+    int x1 = iceil(left_x);
+    if (x1 < (int)rdp.scissor_o.ul_x)
+      x1 = rdp.scissor_o.ul_x;
+    int width = iceil(right_x) - x1;
+    if (x1+width >= (int)rdp.scissor_o.lr_x)
+      width = rdp.scissor_o.lr_x - x1 - 1;
+
+    if(width > 0 && y1 >= (int)rdp.scissor_o.ul_y) {
+  
+        
+      // Prestep initial z
+      
+         #ifdef HAVE_GLES
+      float z = left_z + (x1 - left_x)*dzdx;
+         #else
+      int prestep = (x1 << 16) - left_x;
+      int z = left_z + imul16(prestep, dzdx);
+         #endif
+      
+      shift = x1 + y1*rdp.zi_width;
+      //draw to depth buffer
+      int trueZ;
+      int idx;
+      wxUint16 encodedZ;
+      for (int x = 0; x < width; x++)
+      {
+               #ifdef HAVE_GLES
+               trueZ = (int)(z*8.0f);
+               #else
+        trueZ = z/8192;
+               #endif
+        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++;
+    if (y1 >= (int)rdp.scissor_o.lr_y) return;
+    
+    // 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/source/gles2glide64/src/Glide64/DepthBufferRender.h b/source/gles2glide64/src/Glide64/DepthBufferRender.h
new file mode 100644 (file)
index 0000000..3f0eb84
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+//
+// Software rendering to N64 depth buffer
+// Created by Gonetz, Dec 2004
+//
+//****************************************************************
+
+#ifndef DEPTH_BUFFER_RENDER_H
+#define DEPTH_BUFFER_RENDER_H
+
+struct vertexi
+{
+    int x,y;       // Screen position in 16:16 bit fixed point
+    int z;         // z value in 16:16 bit fixed point
+};
+
+extern wxUint16 * zLUT;
+void ZLUT_init();
+void ZLUT_release();
+
+void Rasterize(vertexi * vtx, int vertices, int dzdx);
+
+#endif //DEPTH_BUFFER_RENDER_H
diff --git a/source/gles2glide64/src/Glide64/FBtoScreen.cpp b/source/gles2glide64/src/Glide64/FBtoScreen.cpp
new file mode 100755 (executable)
index 0000000..46c06fa
--- /dev/null
@@ -0,0 +1,665 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+//
+// Draw N64 frame buffer to screen.
+// Created by Gonetz, 2007
+//
+//****************************************************************
+
+
+#include "Gfx_1.3.h"
+#include "FBtoScreen.h"
+#include "TexCache.h"
+
+static int SetupFBtoScreenCombiner(wxUint32 texture_size, wxUint32 opaque)
+{
+  int tmu;
+  if (voodoo.tmem_ptr[GR_TMU0]+texture_size < voodoo.tex_max_addr[0])
+  {
+    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
+  {
+    if (voodoo.tmem_ptr[GR_TMU1]+texture_size >= voodoo.tex_max_addr[1])
+      ClearCache ();
+    tmu = GR_TMU1;
+    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 );
+  }
+  int filter = (rdp.filter_mode!=2)?GR_TEXTUREFILTER_POINT_SAMPLED:GR_TEXTUREFILTER_BILINEAR;
+  grTexFilterMode (tmu, filter, filter);
+  grTexClampMode (tmu,
+        GR_TEXTURECLAMP_CLAMP,
+        GR_TEXTURECLAMP_CLAMP);
+//  grConstantColorValue (0xFFFFFFFF);
+  grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_ONE,
+    GR_COMBINE_LOCAL_NONE,
+    GR_COMBINE_OTHER_TEXTURE,
+//    GR_COMBINE_OTHER_CONSTANT,
+    FXFALSE);
+  grAlphaCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_ONE,
+    GR_COMBINE_LOCAL_NONE,
+    GR_COMBINE_OTHER_TEXTURE,
+    FXFALSE);
+  if (opaque)
+  {
+    grAlphaTestFunction (GR_CMP_ALWAYS);
+    grAlphaBlendFunction( GR_BLEND_ONE,
+      GR_BLEND_ZERO,
+      GR_BLEND_ONE,
+      GR_BLEND_ZERO);
+  }
+  else
+  {
+    grAlphaBlendFunction( GR_BLEND_SRC_ALPHA,
+      GR_BLEND_ONE_MINUS_SRC_ALPHA,
+      GR_BLEND_ONE,
+      GR_BLEND_ZERO);
+  }
+  grDepthBufferFunction (GR_CMP_ALWAYS);
+  grCullMode(GR_CULL_DISABLE);
+  grDepthMask (FXFALSE);
+  rdp.update |= UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE;
+  return tmu;
+}
+
+static void DrawRE2Video(FB_TO_SCREEN_INFO & fb_info, float scale)
+{
+  float scale_y = (float)fb_info.width/rdp.vi_height;
+  float height = settings.scr_res_x/scale_y;
+  float ul_x = 0.5f;
+  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 = (fb_info.width - 1)*scale;
+  float lr_v = (fb_info.height - 1)*scale;
+  VERTEX v[4] = {
+    { ul_x, ul_y, 1, 1, 0.5f, 0.5f, 0.5f, 0.5f, {0.5f, 0.5f, 0.5f, 0.5f} },
+    { lr_x, ul_y, 1, 1, lr_u, 0.5f, lr_u, 0.5f, {lr_u, 0.5f, lr_u, 0.5f} },
+    { ul_x, lr_y, 1, 1, 0.5f, lr_v, 0.5f, lr_v, {0.5f, lr_v, 0.5f, lr_v} },
+    { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
+  };
+  grDrawTriangle (&v[0], &v[2], &v[1]);
+  grDrawTriangle (&v[2], &v[3], &v[1]);
+}
+
+static void DrawRE2Video256(FB_TO_SCREEN_INFO & fb_info)
+{
+  FRDP("DrawRE2Video256. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx\n", fb_info.ul_x, fb_info.ul_y, fb_info.lr_x, fb_info.lr_y, fb_info.size, fb_info.addr);
+  wxUint32 * src = (wxUint32*)(gfx.RDRAM+fb_info.addr);
+  GrTexInfo t_info;
+  t_info.smallLodLog2 = GR_LOD_LOG2_256;
+  t_info.largeLodLog2 = GR_LOD_LOG2_256;
+  t_info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
+  wxUint16 * tex = (wxUint16*)texture_buffer;
+  wxUint16 * dst = tex;
+  wxUint32 col;
+  wxUint8 r, g, b;
+  fb_info.height = min(256, fb_info.height);
+  for (wxUint32 h = 0; h < fb_info.height; h++)
+  {
+    for (wxUint32 w = 0; w < 256; w++)
+    {
+      col = *(src++);
+      r = (wxUint8)((col >> (24+3))&0x1F);
+      g = (wxUint8)((col >> (16+2))&0x3F);
+      b = (wxUint8)((col >>  (8+3))&0x1F);
+/*      r = (wxUint8)((col >> 24)&0xFF);
+      r = (wxUint8)((float)r / 255.0f * 31.0f);
+      g = (wxUint8)((col >> 16)&0xFF);
+      g = (wxUint8)((float)g / 255.0f * 63.0f);
+      b = (wxUint8)((col >>  8)&0xFF);
+      b = (wxUint8)((float)b / 255.0f * 31.0f);*/      //*SEB*
+      *(dst++) = (r << 11) | (g << 5) | b;
+    }
+    src += (fb_info.width - 256);
+  }
+  t_info.format = GR_TEXFMT_RGB_565;
+  t_info.data = tex;
+  int tmu = SetupFBtoScreenCombiner(grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &t_info), fb_info.opaque);
+  grTexDownloadMipMap (tmu,
+    voodoo.tex_min_addr[tmu]+voodoo.tmem_ptr[tmu],
+    GR_MIPMAPLEVELMASK_BOTH,
+    &t_info);
+  grTexSource (tmu,
+      voodoo.tex_min_addr[tmu]+voodoo.tmem_ptr[tmu],
+      GR_MIPMAPLEVELMASK_BOTH,
+      &t_info);
+  DrawRE2Video(fb_info, 1.0f);
+}
+
+static void DrawFrameBufferToScreen256(FB_TO_SCREEN_INFO & fb_info)
+{
+  if (settings.hacks&hack_RE2)
+  {
+    DrawRE2Video256(fb_info);
+    return;
+  }
+  FRDP("DrawFrameBufferToScreen256. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx\n", fb_info.ul_x, fb_info.ul_y, fb_info.lr_x, fb_info.lr_y, fb_info.size, fb_info.addr);
+  wxUint32 width = fb_info.lr_x - fb_info.ul_x + 1;
+  wxUint32 height = fb_info.lr_y - fb_info.ul_y + 1;
+  GrTexInfo t_info;
+  wxUint8 * image = gfx.RDRAM+fb_info.addr;
+  wxUint32 width256 = ((width-1) >> 8) + 1;
+  wxUint32 height256 = ((height-1) >> 8) + 1;
+  t_info.smallLodLog2 = t_info.largeLodLog2 = GR_LOD_LOG2_256;
+  t_info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
+  t_info.format = GR_TEXFMT_ARGB_1555;
+  wxUint16 * tex = (wxUint16*)texture_buffer;
+  t_info.data = tex;
+  wxUint32 tex_size = grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, &t_info);
+  int tmu = SetupFBtoScreenCombiner(tex_size*width256*height256, fb_info.opaque);
+  wxUint16 * src = (wxUint16*)image;
+  src += fb_info.ul_x + fb_info.ul_y * fb_info.width;
+  wxUint32 * src32 = (wxUint32*)image;
+  src32 += fb_info.ul_x + fb_info.ul_y * fb_info.width;
+  wxUint32 w_tail = width%256;
+  wxUint32 h_tail = height%256;
+  wxUint16 c;
+  wxUint32 c32;
+  wxUint32 idx;
+  wxUint32 bound = BMASK+1-fb_info.addr;
+  bound = fb_info.size == 2 ? bound >> 1 : bound >> 2;
+  wxUint8 r, g, b, a;
+  wxUint32 cur_width, cur_height, cur_tail;
+  wxUint32 tex_adr = voodoo.tex_min_addr[tmu]+voodoo.tmem_ptr[tmu];
+  if ((voodoo.tmem_ptr[tmu] < TEXMEM_2MB_EDGE) && (voodoo.tmem_ptr[tmu]+tex_size*width256*height256 > TEXMEM_2MB_EDGE))
+  {
+    tex_adr = TEXMEM_2MB_EDGE;
+  }
+  for (wxUint32 h = 0; h < height256; h++)
+  {
+    for (wxUint32 w = 0; w < width256; w++)
+    {
+      cur_width = (256*(w+1) < width) ? 256 : w_tail;
+      cur_height = (256*(h+1) < height) ? 256 : h_tail;
+      cur_tail = 256 - cur_width;
+      wxUint16 * dst = tex;
+      if (fb_info.size == 2)
+      {
+        for (wxUint32 y=0; y < cur_height; y++)
+        {
+          for (wxUint32 x=0; x < cur_width; x++)
+          {
+            idx = (x+256*w+(y+256*h)*fb_info.width)^1;
+            if (idx >= bound)
+              break;
+            c = src[idx];
+            *(dst++) = (c >> 1) | ((c&1)<<15);
+          }
+          dst += cur_tail;
+        }
+      }
+      else
+      {
+        for (wxUint32 y=0; y < cur_height; y++)
+        {
+          for (wxUint32 x=0; x < cur_width; x++)
+          {
+            idx = (x+256*w+(y+256*h)*fb_info.width);
+            if (idx >= bound)
+              break;
+            c32 = src32[idx];
+            r = (wxUint8)((c32 >> (24+3))&0x1F);
+            g = (wxUint8)((c32 >> (16+2))&0x3F);
+            b = (wxUint8)((c32 >>  (8+3))&0x1F);
+/*            r = (wxUint8)((c32 >> 24)&0xFF);
+            r = (wxUint8)((float)r / 255.0f * 31.0f);
+            g = (wxUint8)((c32 >> 16)&0xFF);
+            g = (wxUint8)((float)g / 255.0f * 63.0f);
+            b = (wxUint8)((c32 >>  8)&0xFF);
+            b = (wxUint8)((float)b / 255.0f * 31.0f);*/        //*SEB*
+            a = (c32&0xFF) ? 1 : 0;
+            *(dst++) = (a<<15) | (r << 10) | (g << 5) | b;
+          }
+          dst += cur_tail;
+        }
+      }
+      grTexDownloadMipMap (tmu, tex_adr, GR_MIPMAPLEVELMASK_BOTH, &t_info);
+      grTexSource (tmu, tex_adr, GR_MIPMAPLEVELMASK_BOTH, &t_info);
+      tex_adr += tex_size;
+      float ul_x = (float)(fb_info.ul_x + 256*w);
+      float ul_y = (float)(fb_info.ul_y + 256*h);
+      float lr_x = (ul_x + (float)(cur_width)) * rdp.scale_x;
+      float lr_y = (ul_y + (float)(cur_height)) * rdp.scale_y;
+      ul_x *= rdp.scale_x;
+      ul_y *= rdp.scale_y;
+      ul_x += rdp.offset_x;
+      ul_y += rdp.offset_y;
+      lr_x += rdp.offset_x;
+      lr_y += rdp.offset_y;
+
+      float lr_u = (float)(cur_width-1);
+      float lr_v = (float)(cur_height-1);
+      // Make the vertices
+      VERTEX v[4] = {
+        { ul_x, ul_y, 1, 1, 0.5f, 0.5f, 0.5f, 0.5f, {0.5f, 0.5f, 0.5f, 0.5f} },
+        { lr_x, ul_y, 1, 1, lr_u, 0.5f, lr_u, 0.5f, {lr_u, 0.5f, lr_u, 0.5f} },
+        { ul_x, lr_y, 1, 1, 0.5f, lr_v, 0.5f, lr_v, {0.5f, lr_v, 0.5f, lr_v} },
+        { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
+      };
+      grDrawTriangle (&v[0], &v[2], &v[1]);
+      grDrawTriangle (&v[2], &v[3], &v[1]);
+    }
+  }
+}
+
+bool DrawFrameBufferToScreen(FB_TO_SCREEN_INFO & fb_info)
+{
+  if (fb_info.width < 200 || fb_info.size < 2)
+    return false;
+  wxUint32 width = fb_info.lr_x - fb_info.ul_x + 1;
+  wxUint32 height = fb_info.lr_y - fb_info.ul_y + 1;
+  wxUint32 max_size = min(voodoo.max_tex_size, 512);
+  if (width > (wxUint32)max_size || height > (wxUint32)max_size)
+  {
+    DrawFrameBufferToScreen256(fb_info);
+    return true;
+  }
+  FRDP("DrawFrameBufferToScreen. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx\n", fb_info.ul_x, fb_info.ul_y, fb_info.lr_x, fb_info.lr_y, fb_info.size, fb_info.addr);
+  GrTexInfo t_info;
+  wxUint8 * image = gfx.RDRAM+fb_info.addr;
+  wxUint32 texwidth;
+  float scale;
+  if (width <= 256)
+  {
+    texwidth = 256;
+    scale = 1.0f;
+    t_info.smallLodLog2 = t_info.largeLodLog2 = GR_LOD_LOG2_256;
+  }
+  else
+  {
+    texwidth = 512;
+    scale = 0.5f;
+    t_info.smallLodLog2 = t_info.largeLodLog2 = GR_LOD_LOG2_512;
+  }
+
+  if (height <= (texwidth>>1))
+  {
+    t_info.aspectRatioLog2 = GR_ASPECT_LOG2_2x1;
+  }
+  else
+  {
+    t_info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
+  }
+
+  if (fb_info.size == 2)
+  {
+    wxUint16 * tex = (wxUint16*)texture_buffer;
+    wxUint16 * dst = tex;
+    wxUint16 * src = (wxUint16*)image;
+    src += fb_info.ul_x + fb_info.ul_y * fb_info.width;
+    wxUint16 c;
+    wxUint32 idx;
+    const wxUint32 bound = (BMASK+1-fb_info.addr) >> 1;
+    bool empty = true;
+    for (wxUint32 y=0; y < height; y++)
+    {
+      for (wxUint32 x=0; x < width; x++)
+      {
+        idx = (x+y*fb_info.width)^1;
+        if (idx >= bound)
+          break;
+        c = src[idx];
+        if (c) empty = false;
+        *(dst++) = (c >> 1) | ((c&1)<<15);
+      }
+      dst += texwidth-width;
+    }
+    if (empty)
+      return false;
+    t_info.format = GR_TEXFMT_ARGB_1555;
+    t_info.data = tex;
+  }
+  else
+  {
+    wxUint32 * tex = (wxUint32*)texture_buffer;
+    wxUint32 * dst = tex;
+    wxUint32 * src = (wxUint32*)image;
+    src += fb_info.ul_x + fb_info.ul_y * fb_info.width;
+    wxUint32 col;
+    wxUint32 idx;
+    const wxUint32 bound = (BMASK+1-fb_info.addr) >> 2;
+    for (wxUint32 y=0; y < height; y++)
+    {
+      for (wxUint32 x=0; x < width; x++)
+      {
+        idx = x+y*fb_info.width;
+        if (idx >= bound)
+          break;
+        col = src[idx];
+        *(dst++) = (col >> 8) | 0xFF000000;
+      }
+      dst += texwidth-width;
+    }
+    t_info.format = GR_TEXFMT_ARGB_8888;
+    t_info.data = tex;
+  }
+
+  int tmu = SetupFBtoScreenCombiner(grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &t_info), fb_info.opaque);
+  grTexDownloadMipMap (tmu,
+    voodoo.tex_min_addr[tmu]+voodoo.tmem_ptr[tmu],
+    GR_MIPMAPLEVELMASK_BOTH,
+    &t_info);
+  grTexSource (tmu,
+    voodoo.tex_min_addr[tmu]+voodoo.tmem_ptr[tmu],
+    GR_MIPMAPLEVELMASK_BOTH,
+    &t_info);
+  if (settings.hacks&hack_RE2)
+  {
+    DrawRE2Video(fb_info, scale);
+  }
+  else
+  {
+    float ul_x = fb_info.ul_x * rdp.scale_x + rdp.offset_x;
+    float ul_y = fb_info.ul_y * rdp.scale_y + rdp.offset_y;
+    float lr_x = fb_info.lr_x * rdp.scale_x + rdp.offset_x;
+    float lr_y = fb_info.lr_y * rdp.scale_y + rdp.offset_y;
+    float lr_u = (width-1)*scale;
+    float lr_v = (height-1)*scale;
+    // Make the vertices
+    VERTEX v[4] = {
+      { ul_x, ul_y, 1, 1, 0.5f, 0.5f, 0.5f, 0.5f, {0.5f, 0.5f, 0.5f, 0.5f} },
+      { lr_x, ul_y, 1, 1, lr_u, 0.5f, lr_u, 0.5f, {lr_u, 0.5f, lr_u, 0.5f} },
+      { ul_x, lr_y, 1, 1, 0.5f, lr_v, 0.5f, lr_v, {0.5f, lr_v, 0.5f, lr_v} },
+      { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
+    };
+    grDrawTriangle (&v[0], &v[2], &v[1]);
+    grDrawTriangle (&v[2], &v[3], &v[1]);
+  }
+  return true;
+}
+
+static void DrawDepthBufferToScreen256(FB_TO_SCREEN_INFO & fb_info)
+{
+  FRDP("DrawDepthBufferToScreen256. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx\n", fb_info.ul_x, fb_info.ul_y, fb_info.lr_x, fb_info.lr_y, fb_info.size, fb_info.addr);
+  wxUint32 width = fb_info.lr_x - fb_info.ul_x + 1;
+  wxUint32 height = fb_info.lr_y - fb_info.ul_y + 1;
+  GrTexInfo t_info;
+  wxUint8 * image = gfx.RDRAM+fb_info.addr;
+  wxUint32 width256 = ((width-1) >> 8) + 1;
+  wxUint32 height256 = ((height-1) >> 8) + 1;
+  t_info.smallLodLog2 = t_info.largeLodLog2 = GR_LOD_LOG2_256;
+  t_info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
+  t_info.format = GR_TEXFMT_ALPHA_INTENSITY_88;
+  wxUint16 * tex = (wxUint16*)texture_buffer;
+  t_info.data = tex;
+  wxUint32 tex_size = grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, &t_info);
+  int tmu = SetupFBtoScreenCombiner(tex_size*width256*height256, fb_info.opaque);
+  grConstantColorValue (rdp.fog_color);
+  grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_ONE,
+    GR_COMBINE_LOCAL_NONE,
+    GR_COMBINE_OTHER_CONSTANT,
+    FXFALSE);
+  wxUint16 * src = (wxUint16*)image;
+  src += fb_info.ul_x + fb_info.ul_y * fb_info.width;
+  wxUint32 w_tail = width%256;
+  wxUint32 h_tail = height%256;
+  wxUint32 cur_width, cur_height, cur_tail;
+  wxUint32 tex_adr = voodoo.tex_min_addr[tmu]+voodoo.tmem_ptr[tmu];
+  if ((voodoo.tmem_ptr[tmu] < TEXMEM_2MB_EDGE) && (voodoo.tmem_ptr[tmu]+tex_size*width256*height256 > TEXMEM_2MB_EDGE))
+  {
+    tex_adr = TEXMEM_2MB_EDGE;
+  }
+  for (wxUint32 h = 0; h < height256; h++)
+  {
+    for (wxUint32 w = 0; w < width256; w++)
+    {
+      cur_width = (256*(w+1) < width) ? 256 : w_tail;
+      cur_height = (256*(h+1) < height) ? 256 : h_tail;
+      cur_tail = 256 - cur_width;
+      wxUint16 * dst = tex;
+      for (wxUint32 y=0; y < cur_height; y++)
+      {
+        for (wxUint32 x=0; x < cur_width; x++)
+        {
+          *(dst++) = rdp.pal_8[src[(x+256*w+(y+256*h)*fb_info.width)^1]>>8];
+        }
+        dst += cur_tail;
+      }
+      grTexDownloadMipMap (tmu, tex_adr, GR_MIPMAPLEVELMASK_BOTH, &t_info);
+      grTexSource (tmu, tex_adr, GR_MIPMAPLEVELMASK_BOTH, &t_info);
+      tex_adr += tex_size;
+      float ul_x = (float)(fb_info.ul_x + 256*w);
+      float ul_y = (float)(fb_info.ul_y + 256*h);
+      float lr_x = (ul_x + (float)(cur_width)) * rdp.scale_x + rdp.offset_x;
+      float lr_y = (ul_y + (float)(cur_height)) * rdp.scale_y + rdp.offset_y;
+      ul_x = ul_x * rdp.scale_x + rdp.offset_x;
+      ul_y = ul_y * rdp.scale_y + rdp.offset_y;
+      float lr_u = (float)(cur_width-1);
+      float lr_v = (float)(cur_height-1);
+      // Make the vertices
+      VERTEX v[4] = {
+        { ul_x, ul_y, 1, 1, 0.5f, 0.5f, 0.5f, 0.5f, {0.5f, 0.5f, 0.5f, 0.5f} },
+        { lr_x, ul_y, 1, 1, lr_u, 0.5f, lr_u, 0.5f, {lr_u, 0.5f, lr_u, 0.5f} },
+        { ul_x, lr_y, 1, 1, 0.5f, lr_v, 0.5f, lr_v, {0.5f, lr_v, 0.5f, lr_v} },
+        { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
+      };
+      grDrawTriangle (&v[0], &v[2], &v[1]);
+      grDrawTriangle (&v[2], &v[3], &v[1]);
+    }
+  }
+}
+
+static void DrawHiresDepthBufferToScreen(FB_TO_SCREEN_INFO & fb_info)
+{
+  FRDP("DrawHiresDepthBufferToScreen. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx\n", fb_info.ul_x, fb_info.ul_y, fb_info.lr_x, fb_info.lr_y, fb_info.size, fb_info.addr);
+  GrTexInfo t_info;
+  float scale = 0.25f;
+  GrLOD_t LOD = GR_LOD_LOG2_1024;
+  if (settings.scr_res_x > 1024)
+  {
+    scale = 0.125f;
+    LOD = GR_LOD_LOG2_2048;
+  }
+  t_info.format = GR_TEXFMT_ALPHA_INTENSITY_88;
+  t_info.smallLodLog2 = t_info.largeLodLog2 = LOD;
+  t_info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
+  grConstantColorValue (rdp.fog_color);
+  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);
+  grAlphaBlendFunction( GR_BLEND_SRC_ALPHA,
+    GR_BLEND_ONE_MINUS_SRC_ALPHA,
+    GR_BLEND_ONE,
+    GR_BLEND_ZERO);
+  grDepthBufferFunction (GR_CMP_ALWAYS);
+  grDepthMask (FXFALSE);
+  grCullMode (GR_CULL_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);
+//  grAuxBufferExt( GR_BUFFER_AUXBUFFER );
+  grTexSource( rdp.texbufs[0].tmu, rdp.texbufs[0].begin, GR_MIPMAPLEVELMASK_BOTH, &(t_info) );
+  float ul_x = (float)rdp.scissor.ul_x;
+  float ul_y = (float)rdp.scissor.ul_y;
+  float lr_x = (float)rdp.scissor.lr_x;
+  float lr_y = (float)rdp.scissor.lr_y;
+  float ul_u = (float)rdp.scissor.ul_x * scale;
+  float ul_v = (float)rdp.scissor.ul_y * scale;
+  float lr_u = (float)rdp.scissor.lr_x * scale;
+  float lr_v = (float)rdp.scissor.lr_y * scale;
+  // Make the vertices
+  VERTEX v[4] = {
+    { ul_x, ul_y, 1, 1, ul_u, ul_v, ul_u, ul_v, {ul_u, ul_v, ul_u, ul_v} },
+    { lr_x, ul_y, 1, 1, lr_u, ul_v, lr_u, ul_v, {lr_u, ul_v, lr_u, ul_v} },
+    { ul_x, lr_y, 1, 1, ul_u, lr_v, ul_u, lr_v, {ul_u, lr_v, ul_u, lr_v} },
+    { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
+  };
+  grDrawTriangle (&v[0], &v[2], &v[1]);
+  grDrawTriangle (&v[2], &v[3], &v[1]);
+//  grAuxBufferExt( GR_BUFFER_TEXTUREAUXBUFFER_EXT );
+  rdp.update |= UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE;
+}
+
+void DrawDepthBufferToScreen(FB_TO_SCREEN_INFO & fb_info)
+{
+  wxUint32 width = fb_info.lr_x - fb_info.ul_x + 1;
+  wxUint32 height = fb_info.lr_y - fb_info.ul_y + 1;
+  if (width > (wxUint32)voodoo.max_tex_size || height > (wxUint32)voodoo.max_tex_size || width > 512)
+  {
+    DrawDepthBufferToScreen256(fb_info);
+    return;
+  }
+  if (fb_hwfbe_enabled && !evoodoo)
+  {
+    DrawHiresDepthBufferToScreen(fb_info);
+    return;
+  }
+  FRDP("DrawDepthBufferToScreen. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx\n", fb_info.ul_x, fb_info.ul_y, fb_info.lr_x, fb_info.lr_y, fb_info.size, fb_info.addr);
+  GrTexInfo t_info;
+  wxUint8 * image = gfx.RDRAM+fb_info.addr;
+  wxUint32 texwidth;
+  float scale;
+  if (width <= 256)
+  {
+    texwidth = 256;
+    scale = 1.0f;
+    t_info.smallLodLog2 = t_info.largeLodLog2 = GR_LOD_LOG2_256;
+  }
+  else
+  {
+    texwidth = 512;
+    scale = 0.5f;
+    t_info.smallLodLog2 = t_info.largeLodLog2 = GR_LOD_LOG2_512;
+  }
+
+  if (height <= (texwidth>>1))
+  {
+    t_info.aspectRatioLog2 = GR_ASPECT_LOG2_2x1;
+  }
+  else
+  {
+    t_info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
+  }
+
+  wxUint16 * tex = (wxUint16*)texture_buffer;
+  wxUint16 * dst = tex;
+  wxUint16 * src = (wxUint16*)image;
+  src += fb_info.ul_x + fb_info.ul_y * fb_info.width;
+  for (wxUint32 y=0; y < height; y++)
+  {
+    for (wxUint32 x=0; x < width; x++)
+    {
+      *(dst++) = rdp.pal_8[src[(x+y*fb_info.width)^1]>>8];
+    }
+    dst += texwidth-width;
+  }
+  t_info.format = GR_TEXFMT_ALPHA_INTENSITY_88;
+  t_info.data = tex;
+
+  int tmu = SetupFBtoScreenCombiner(grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &t_info), fb_info.opaque);
+  grConstantColorValue (rdp.fog_color);
+  grColorCombine (GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_ONE,
+    GR_COMBINE_LOCAL_NONE,
+    GR_COMBINE_OTHER_CONSTANT,
+    FXFALSE);
+  grTexDownloadMipMap (tmu,
+    voodoo.tex_min_addr[tmu]+voodoo.tmem_ptr[tmu],
+    GR_MIPMAPLEVELMASK_BOTH,
+    &t_info);
+  grTexSource (tmu,
+    voodoo.tex_min_addr[tmu]+voodoo.tmem_ptr[tmu],
+    GR_MIPMAPLEVELMASK_BOTH,
+    &t_info);
+  float ul_x = fb_info.ul_x * rdp.scale_x + rdp.offset_x;
+  float ul_y = fb_info.ul_y * rdp.scale_y + rdp.offset_y;
+  float lr_x = fb_info.lr_x * rdp.scale_x + rdp.offset_x;
+  float lr_y = fb_info.lr_y * rdp.scale_y + rdp.offset_y;
+  float lr_u = (width-1)*scale;
+  float lr_v = (height-1)*scale;
+  float zero = scale*0.5f;
+  // Make the vertices
+  VERTEX v[4] = {
+    { ul_x, ul_y, 1, 1, zero, zero, zero, zero, {zero, zero, zero, zero} },
+    { lr_x, ul_y, 1, 1, lr_u, zero, lr_u, zero, {lr_u, zero, lr_u, zero} },
+    { ul_x, lr_y, 1, 1, zero, lr_v, zero, lr_v, {zero, lr_v, zero, lr_v} },
+    { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
+  };
+  grDrawTriangle (&v[0], &v[2], &v[1]);
+  grDrawTriangle (&v[2], &v[3], &v[1]);
+}
diff --git a/source/gles2glide64/src/Glide64/FBtoScreen.h b/source/gles2glide64/src/Glide64/FBtoScreen.h
new file mode 100644 (file)
index 0000000..e4180b4
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+//
+// Render N64 frame buffer to screen
+// Created by Gonetz, 2007
+//
+//****************************************************************
+#ifndef FBtoSCREEN_H
+#define FBtoSCREEN_H
+
+typedef struct 
+{
+  wxUint32 addr;   //color image address
+  wxUint32 size;   
+  wxUint32 width;
+  wxUint32 height;
+  wxUint32 ul_x;
+  wxUint32 ul_y;
+  wxUint32 lr_x;
+  wxUint32 lr_y;
+  wxUint32 opaque;
+} FB_TO_SCREEN_INFO;
+
+bool DrawFrameBufferToScreen(FB_TO_SCREEN_INFO & fb_info);
+void DrawDepthBufferToScreen(FB_TO_SCREEN_INFO & fb_info);
+
+#endif  // #ifndef FBtoSCREEN_H
diff --git a/source/gles2glide64/src/Glide64/FrameSkipper.cpp b/source/gles2glide64/src/Glide64/FrameSkipper.cpp
new file mode 100755 (executable)
index 0000000..7bd81e9
--- /dev/null
@@ -0,0 +1,142 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *   Copyright (C) 2011 yongzh (freeman.yong@gmail.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 "FrameSkipper.h"
+#include "ticks.h"
+#include <stdio.h>
+
+FrameSkipper::FrameSkipper()
+       : skipType(AUTO), maxSkips(2), targetFPS(60)
+{
+}
+
+void FrameSkipper::start()
+{
+       initialTicks = 0;
+       virtualCount = 0;
+       skipCounter = 0;
+       oldSkip = 0;
+}
+#if 0
+bool FrameSkipper::hasSkipped()
+{
+       oldSkip = skipCounter;
+       
+       if (skipType == MANUAL) {
+               if (++skipCounter > maxSkips)
+                       skipCounter = 0;
+//printf("frameskipper(Manual): oldSkip=%i, skipCounter=%i, countVI=%i\n", oldSkip, skipCounter, countVI);
+               countVI = 0;
+               return (oldSkip>0);
+       }
+
+       unsigned int elapsed = ticksGetTicks()/* - initialTicks*/;
+       int realCount = (elapsed-initialTicks - 4) * targetFPS; // 4ms tolerance
+       if ((realCount > countVI*1000) && (skipCounter < maxSkips) && (countVI<10)) {
+               skipCounter++;
+//printf("Skip frame elapsed=%u realCount=%u countVI=%u skipCounter=%i\n", elapsed-initialTicks, realCount, countVI, skipCounter);
+       } else {
+//printf(" Ok  frame elapsed=%u realCount=%u countVI=%u skipCounter=%i\n", elapsed-initialTicks, realCount, countVI, skipCounter);
+               skipCounter = 0;
+               initialTicks=elapsed;
+               virtualCount=0;
+               countVI=0;
+       }
+//printf("frameskipper(Auto): oldSkip=%i, skipCounter=%i, countVI=%i, realCount=%u\n", oldSkip, skipCounter, countVI, realCount);
+       return (oldSkip>0);
+}
+#else
+void FrameSkipper::newFrame()
+{
+       oldSkip = skipCounter;
+       
+       if (skipType == MANUAL) {
+               if (++skipCounter > maxSkips)
+                       skipCounter = 0;
+//printf("frameskipper(Manual): oldSkip=%i, skipCounter=%i, countVI=%i\n", oldSkip, skipCounter, countVI);
+               countVI = 0;
+               return;
+       }
+
+       unsigned int elapsed = ticksGetTicks()/* - initialTicks*/;
+       int realCount = (elapsed-initialTicks - 4) * targetFPS; // 4ms tolerance
+       if ((realCount > countVI*1000) && (skipCounter < maxSkips) && (countVI<10)) {
+               skipCounter++;
+//printf("Skip frame elapsed=%u realCount=%u countVI=%u skipCounter=%i\n", elapsed-initialTicks, realCount, countVI, skipCounter);
+       } else {
+//printf(" Ok  frame elapsed=%u realCount=%u countVI=%u skipCounter=%i\n", elapsed-initialTicks, realCount, countVI, skipCounter);
+               skipCounter = 0;
+               initialTicks=elapsed;
+               virtualCount=0;
+               countVI=0;
+       }
+//printf("frameskipper(Auto): oldSkip=%i, skipCounter=%i, countVI=%i, realCount=%u\n", oldSkip, skipCounter, countVI, realCount);
+       return;
+}
+#endif
+
+void FrameSkipper::update()
+{
+#if 1
+       if (initialTicks == 0) {
+               initialTicks = ticksGetTicks();
+       }
+       countVI++;
+       
+       if (countVI>20) {
+               skipCounter=0;          // failsafe...
+       }
+#else
+       // for the first frame
+       if (initialTicks == 0) {
+               initialTicks = ticksGetTicks();
+               return;
+       }
+       
+       oldSkip=skipCounter;
+       
+       if (skipType == MANUAL) {
+               if (++skipCounter > maxSkips)
+                       skipCounter = 0;
+               return;
+       }
+
+       unsigned int elapsed = ticksGetTicks()/* - initialTicks*/;
+       unsigned int realCount = (elapsed-initialTicks) * targetFPS;
+
+       virtualCount+=1000;
+//     if (realCount >= virtualCount) {
+               if (realCount > virtualCount+100 &&
+                               /*skipType == AUTO &&*/ skipCounter < maxSkips) {
+                       skipCounter++;
+//printf("Skip frame elapsed=%u initialTicks=%u realCount=%u virtualCound=%u skipCounter=%i\n", elapsed, initialTicks, realCount, virtualCount, skipCounter);
+               } else {
+//                     virtualCount = realCount;
+//                     if (skipType == AUTO)
+                               skipCounter = 0;
+                       initialTicks=elapsed;
+                       virtualCount=0;
+               }
+/*     } else {
+               skipCounter = 0;
+               initialTicks=elapsed;
+               virtualCount=0;
+       }*/
+#endif
+}
diff --git a/source/gles2glide64/src/Glide64/FrameSkipper.h b/source/gles2glide64/src/Glide64/FrameSkipper.h
new file mode 100755 (executable)
index 0000000..2ae0dab
--- /dev/null
@@ -0,0 +1,64 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *   Copyright (C) 2011 yongzh (freeman.yong@gmail.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.          *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#ifndef FRAME_SKIPPER_H
+#define FRAME_SKIPPER_H
+
+class FrameSkipper {
+public:
+       enum { AUTO, MANUAL };
+
+       FrameSkipper();
+
+       void setSkips(int type, int max) {
+               skipType = type;
+               maxSkips = max;
+       }
+
+       void setTargetFPS(int fps) {
+               targetFPS = fps;
+       }
+       bool willSkipNext() {
+               return (skipCounter > 0);
+       }
+       
+#if 0
+       bool hasSkipped();
+#else
+       bool hasSkipped() {
+               return (oldSkip > 0);
+       }
+       void newFrame();
+#endif
+       void start();
+       void update();
+
+private:
+       int skipType;
+       int     oldSkip;
+       int maxSkips;
+       int targetFPS;
+       int skipCounter;
+       int     countVI;
+       unsigned int initialTicks;
+       unsigned int virtualCount;
+};
+
+#endif
+
diff --git a/source/gles2glide64/src/Glide64/Gfx_1.3.h b/source/gles2glide64/src/Glide64/Gfx_1.3.h
new file mode 100755 (executable)
index 0000000..a0216dd
--- /dev/null
@@ -0,0 +1,682 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+/**********************************************************************************
+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 "winlnxdefs.h"
+#include "m64p.h"
+
+#include <stdio.h>
+#include <SDL_mutex.h>
+#include <fstream>
+#include <stdlib.h>
+#include <stddef.h>            // offsetof
+#include <string.h>
+#include <stdarg.h>
+#include <glide.h>
+#include "GlideExtensions.h"
+#include "rdp.h"
+#include "Keys.h"
+
+#include <iostream>
+#include <fstream>
+
+#if defined __VISUALC__
+#define GLIDE64_TRY __try
+#define GLIDE64_CATCH __except (EXCEPTION_EXECUTE_HANDLER)
+#else
+#define GLIDE64_TRY try
+#define GLIDE64_CATCH catch (...)
+#endif
+
+#ifndef WIN32
+typedef int HWND;
+#endif
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define _ENDUSER_RELEASE_
+
+//********
+// 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 EXT_LOGGING
+//#define PERFORMANCE
+
+//#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:
+//#define LOGKEY               0x11 // this key (CONTROL)
+
+//#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 _ENDUSER_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",std::ios::app); extlog << x; extlog.close();
+#else
+#define EXT(x)
+#endif
+
+#ifndef _ENDUSER_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 fps_last;
+extern LARGE_INTEGER fps_next;
+extern float             fps;
+extern wxUint32          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 wxUint32 update_screen_count;
+extern wxUint32 resolutions[0x18][2];
+
+int CheckKeyPressed(int key, int mask);
+
+#ifdef PERFORMANCE
+extern int64 perf_cur;
+extern int64 perf_next;
+#endif
+
+//#ifdef LOGGING
+//extern std::ofstream loga;
+//#define LOG(X) loga.open("log.txt",std::ios::app); loga << (...); loga.flush(); loga.close();
+
+//#else
+  #ifndef OLD_API
+    #define LOG(...) WriteLog(M64MSG_INFO, __VA_ARGS__)
+    #define VLOG(...) WriteLog(M64MSG_VERBOSE, __VA_ARGS__)
+    #define WARNLOG(...) WriteLog(M64MSG_WARNING, __VA_ARGS__)
+    #define ERRLOG(...) WriteLog(M64MSG_ERROR, __VA_ARGS__)
+#else
+    #define LOG(...) printf(__VA_ARGS__)
+    #define VLOG(...)
+     #define WARNLOG(...) printf(__VA_ARGS__)
+    #define ERRLOG(X, ...) str.Printf(_T(X), __VA_ARGS__); wxMessageBox(str, _T("Error"), wxOK | wxICON_EXCLAMATION, GFXWindow)
+    #define ERRLOG(X) str.Printf(_T(X)); wxMessageBox(str, _T("Error"), wxOK | wxICON_EXCLAMATION, GFXWindow)
+#endif
+
+
+#ifdef RDP_LOGGING
+extern int log_open;
+extern std::ofstream rdp_log;
+#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 LRDP(x) EXT("RDP (...)\n"); if (settings.logging && log_open) { if (!CheckKeyPressed(LOGKEY,0x8000)) { rdp_log << x; rdp_log.flush(); } }
+#else
+#define LRDP(x) EXT("RDP (...)\n"); if (settings.logging && log_open) { rdp_log << x; rdp_log.flush(); }
+#endif
+
+#else
+#define OPEN_RDP_LOG()
+#define CLOSE_RDP_LOG()
+#define LRDP(x)
+#endif
+
+
+#ifdef RDP_ERROR_LOG
+extern int elog_open;
+extern std::ofstream rdp_err;
+#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 (settings.elogging) { FRDP_E (x); }
+#else
+#define OPEN_RDP_E_LOG()
+#define CLOSE_RDP_E_LOG()
+#define RDP_E(x)
+#endif
+
+__inline void FRDP (const char *fmt, ...)
+{
+#ifdef RDP_LOGGING
+       if (!settings.logging || !log_open) return;
+
+#ifdef LOGNOTKEY
+       if (CheckKeyPressed(LOGKEY,0x8000)) return;
+#endif
+
+       va_list ap;
+       va_start(ap, fmt);
+       vsprintf(out_buf, fmt, ap);
+       LRDP (out_buf);
+       va_end(ap);
+#endif
+}
+__inline void FRDP_E (const char *fmt, ...)
+{
+#ifdef RDP_ERROR_LOG
+       if (!settings.elogging || !elog_open) return;
+
+#ifdef LOGNOTKEY
+       if (CheckKeyPressed(LOGKEY,0x8000)) return;
+#endif
+
+       sprintf (out_buf, "%08lx: (%08lx, %08lx) ", 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();
+       va_end(ap2);
+#endif
+}
+
+extern int fullscreen;
+extern int romopen;
+extern int to_fullscreen;
+extern int debugging;
+
+extern int evoodoo;
+extern int ev_fullscreen;
+
+extern SDL_sem *mutexProcessDList;
+extern int exception;
+
+// extern wxMutex *mutexProcessDList;
+
+int InitGfx (int);
+void ReleaseGfx ();
+
+// The highest 8 bits are the segment # (1-16), and the lower 24 bits are the offset to
+// add to it.
+__inline wxUint32 segoffset (wxUint32 so)
+{
+       return (rdp.segment[(so>>24)&0x0f] + (so&BMASK))&BMASK;
+}
+
+/* Plugin types */
+#define PLUGIN_TYPE_GFX                                2
+
+// this is already defined in API
+/*
+#ifdef __WINDOWS__
+#define EXPORT                                 __declspec(dllexport)
+#define CALL                                           _cdecl
+#else
+#define EXPORT                                 extern
+#define CALL                                           
+#endif
+*/
+/***** Structures *****/
+typedef struct {
+       wxUint16 Version;        /* Set to 0x0103 */
+       wxUint16 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 */
+       int NormalMemory;    /* a normal wxUint8 array */
+       int MemoryBswaped;  /* a normal wxUint8 array where the memory has been pre
+                                 bswap on a dword (32 bits) boundry */
+} PLUGIN_INFO;
+
+/*
+typedef struct {
+// <removed, already defined in API>
+} GFX_INFO;
+*/
+extern GFX_INFO gfx;
+// extern wxWindow * GFXWindow;
+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)(FxI32, FxI32, FxBool, FxBool);
+
+typedef GrScreenResolution_t (FX_CALL *GRWRAPPERFULLSCREENRESOLUTIONEXT)(wxUint32*, wxUint32*);
+
+typedef char ** (FX_CALL *GRQUERYRESOLUTIONSEXT)(FxI32*);
+
+typedef int (*GETTEXADDR)(int tmu, int texsize);
+
+extern GRTEXBUFFEREXT       grTextureBufferExt;
+extern GRTEXBUFFEREXT       grTextureAuxBufferExt;
+extern GRAUXBUFFEREXT       grAuxBufferExt;
+extern GRSTIPPLE            grStippleModeExt;
+extern GRSTIPPLE            grStipplePatternExt;
+extern GETTEXADDR           GetTexAddr;
+
+#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);
+void WriteSettings (bool saveEmulationSettings = false);
+
+#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 int 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 = wxUint8, 2 = wxUint16, 4 = wxUint32
+  output:   none
+*******************************************************************/
+EXPORT void CALL FBWrite(wxUint32, wxUint32);
+
+typedef struct
+{
+       wxUint32 addr;
+       wxUint32 val;
+       wxUint32 size;                          // 1 = wxUint8, 2 = wxUint16, 4=wxUint32
+} 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, wxUint32 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 = wxUint8, 2 = wxUint16, 4 = wxUint32
+  output:   none
+*******************************************************************/
+EXPORT void CALL FBRead(wxUint32 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);
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+#endif //_GFX_H_INCLUDED__
diff --git a/source/gles2glide64/src/Glide64/GlideExtensions.h b/source/gles2glide64/src/Glide64/GlideExtensions.h
new file mode 100644 (file)
index 0000000..52e026e
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#define GR_BUFFER_TEXTUREBUFFER_EXT       0x6
+#define GR_BUFFER_TEXTUREAUXBUFFER_EXT    0x7
+
+typedef FxU32 GrPixelFormat_t;
+#define GR_PIXFMT_RGB_565                 0x03
+#define GR_PIXFMT_ARGB_1555               0x0004
+#define GR_PIXFMT_ARGB_8888               0x0005
+
+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
+
+#define GR_TEXFMT_ARGB_8888               0x12
+
+#define GR_LOD_LOG2_2048                  0xb
+#define GR_LOD_LOG2_1024                  0xa
+#define GR_LOD_LOG2_512                   0x9
+
+#define GR_TEXTURE_UMA_EXT                0x06
diff --git a/source/gles2glide64/src/Glide64/Help/Glide64 Known Issues.html b/source/gles2glide64/src/Glide64/Help/Glide64 Known Issues.html
new file mode 100644 (file)
index 0000000..b6d0f52
--- /dev/null
@@ -0,0 +1,1399 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!-- saved from url=(0042)http://www.eluni.net/glide64_known_issues/ -->
+<html xmlns:v="urn:schemas-microsoft-com:vml"
+xmlns:o="urn:schemas-microsoft-com:office:office"
+xmlns:x="urn:schemas-microsoft-com:office:excel"
+xmlns="http://www.w3.org/TR/REC-html40">
+
+<head>
+<meta http-equiv=Content-Type content="text/html; charset=windows-1252">
+<meta name=ProgId content=Excel.Sheet>
+<meta name=Generator content="Microsoft Excel 11">
+<link rel=File-List href="Glide64%20Known%20Issues_fichiers/filelist.xml">
+<link rel=Edit-Time-Data href="Glide64%20Known%20Issues_fichiers/editdata.mso">
+<link rel=OLE-Object-Data href="Glide64%20Known%20Issues_fichiers/oledata.mso">
+<title>Glide64 Known Issues</title>
+<!--[if gte mso 9]><xml>
+ <o:DocumentProperties>
+  <o:LastAuthor>Olivier</o:LastAuthor>
+  <o:Created>2007-06-19T06:39:39Z</o:Created>
+  <o:LastSaved>2009-07-06T05:26:51Z</o:LastSaved>
+  <o:Version>11.5606</o:Version>
+ </o:DocumentProperties>
+ <o:OfficeDocumentSettings>
+  <o:DownloadComponents/>
+  <o:LocationOfComponents HRef="/"/>
+ </o:OfficeDocumentSettings>
+</xml><![endif]-->
+<style>
+<!--
+A:hover {
+       COLOR: #745e4c; TEXT-DECORATION: underline
+}
+A:hover {
+       COLOR: #745e4c; TEXT-DECORATION: underline
+}
+table
+       {mso-displayed-decimal-separator:"\,";
+       mso-displayed-thousand-separator:" ";}
+@page
+       {margin:1.0in .75in 1.0in .75in;
+       mso-header-margin:.5in;
+       mso-footer-margin:.5in;}
+.font5
+       {color:windowtext;
+       font-size:8.0pt;
+       font-weight:400;
+       font-style:normal;
+       text-decoration:none;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;}
+.font7
+       {color:red;
+       font-size:12.0pt;
+       font-weight:700;
+       font-style:normal;
+       text-decoration:none;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;}
+.font8
+       {color:gray;
+       font-size:12.0pt;
+       font-weight:700;
+       font-style:normal;
+       text-decoration:none;
+       font-family:Arial, sans-serif;
+       mso-font-charset:0;}
+.font12
+       {color:windowtext;
+       font-size:8.0pt;
+       font-weight:700;
+       font-style:normal;
+       text-decoration:none;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;}
+.font19
+       {color:gray;
+       font-size:8.0pt;
+       font-weight:700;
+       font-style:normal;
+       text-decoration:none;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;}
+tr
+       {mso-height-source:auto;}
+col
+       {mso-width-source:auto;}
+br
+       {mso-data-placement:same-cell;}
+.style0
+       {mso-number-format:General;
+       text-align:general;
+       vertical-align:bottom;
+       white-space:nowrap;
+       mso-rotate:0;
+       mso-background-source:auto;
+       mso-pattern:auto;
+       color:windowtext;
+       font-size:10.0pt;
+       font-weight:400;
+       font-style:normal;
+       text-decoration:none;
+       font-family:Arial;
+       mso-generic-font-family:auto;
+       mso-font-charset:0;
+       border:none;
+       mso-protection:locked visible;
+       mso-style-name:Normal;
+       mso-style-id:0;}
+td
+       {mso-style-parent:style0;
+       padding-top:1px;
+       padding-right:1px;
+       padding-left:1px;
+       mso-ignore:padding;
+       color:windowtext;
+       font-size:10.0pt;
+       font-weight:400;
+       font-style:normal;
+       text-decoration:none;
+       font-family:Arial;
+       mso-generic-font-family:auto;
+       mso-font-charset:0;
+       mso-number-format:General;
+       text-align:general;
+       vertical-align:bottom;
+       border:none;
+       mso-background-source:auto;
+       mso-pattern:auto;
+       mso-protection:locked visible;
+       white-space:nowrap;
+       mso-rotate:0;}
+.xl24
+       {mso-style-parent:style0;
+       font-size:8.0pt;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;}
+.xl25
+       {mso-style-parent:style0;
+       font-size:8.0pt;
+       font-weight:700;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;}
+.xl26
+       {mso-style-parent:style0;
+       font-size:8.0pt;
+       font-weight:700;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       white-space:normal;}
+.xl27
+       {mso-style-parent:style0;
+       color:green;
+       font-size:8.0pt;
+       font-weight:700;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;}
+.xl28
+       {mso-style-parent:style0;
+       color:green;
+       font-size:8.0pt;
+       font-weight:700;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:none;
+       border-bottom:1.0pt solid green;
+       border-left:none;
+       white-space:normal;}
+.xl29
+       {mso-style-parent:style0;
+       color:green;
+       font-size:8.0pt;
+       font-weight:700;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       border-top:1.0pt solid green;
+       border-right:none;
+       border-bottom:1.0pt solid green;
+       border-left:none;}
+.xl30
+       {mso-style-parent:style0;
+       color:green;
+       font-size:8.0pt;
+       font-weight:700;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:none;
+       border-bottom:1.0pt solid green;
+       border-left:none;}
+.xl31
+       {mso-style-parent:style0;
+       color:#FF9900;
+       font-size:8.0pt;
+       font-weight:700;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:none;
+       border-bottom:1.0pt solid #FF9900;
+       border-left:none;
+       white-space:normal;}
+.xl32
+       {mso-style-parent:style0;
+       color:#FF6600;
+       font-size:8.0pt;
+       font-weight:700;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       border-top:1.0pt solid #FF9900;
+       border-right:none;
+       border-bottom:1.0pt solid #FF9900;
+       border-left:none;}
+.xl33
+       {mso-style-parent:style0;
+       color:#FF6600;
+       font-size:8.0pt;
+       font-weight:700;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:none;
+       border-bottom:1.0pt solid #FF9900;
+       border-left:none;}
+.xl34
+       {mso-style-parent:style0;
+       color:#FF9900;
+       font-size:8.0pt;
+       font-weight:700;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       white-space:normal;}
+.xl35
+       {mso-style-parent:style0;
+       color:purple;
+       font-size:8.0pt;
+       font-weight:700;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:none;
+       border-bottom:1.0pt solid green;
+       border-left:none;
+       white-space:normal;}
+.xl36
+       {mso-style-parent:style0;
+       color:red;
+       font-size:8.0pt;
+       font-weight:700;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:none;
+       border-bottom:1.0pt solid black;
+       border-left:none;
+       white-space:normal;}
+.xl37
+       {mso-style-parent:style0;
+       color:red;
+       font-size:8.0pt;
+       font-weight:700;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:none;
+       border-bottom:1.0pt solid windowtext;
+       border-left:none;}
+.xl38
+       {mso-style-parent:style0;
+       color:gray;
+       font-size:8.0pt;
+       font-weight:700;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:none;
+       border-bottom:1.0pt solid #969696;
+       border-left:none;
+       white-space:normal;}
+.xl39
+       {mso-style-parent:style0;
+       color:#993300;
+       font-size:8.0pt;
+       font-weight:700;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:none;
+       border-bottom:1.0pt solid #969696;
+       border-left:none;
+       white-space:normal;}
+.xl40
+       {mso-style-parent:style0;
+       color:#993300;
+       font-size:8.0pt;
+       font-weight:700;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:none;
+       border-bottom:1.0pt solid maroon;
+       border-left:none;
+       white-space:normal;}
+.xl41
+       {mso-style-parent:style0;
+       font-size:8.0pt;
+       font-weight:700;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:none;
+       border-bottom:1.0pt solid black;
+       border-left:none;
+       white-space:normal;}
+.xl42
+       {mso-style-parent:style0;
+       color:#993366;
+       font-size:12.0pt;
+       font-weight:700;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       text-align:left;
+       white-space:normal;}
+.xl43
+       {mso-style-parent:style0;
+       font-size:7.5pt;
+       font-weight:700;
+       font-family:Arial, sans-serif;
+       mso-font-charset:0;
+       text-align:right;
+       white-space:normal;}
+.xl44
+       {mso-style-parent:style0;
+       font-size:8.0pt;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       text-align:left;
+       white-space:normal;}
+.xl45
+       {mso-style-parent:style0;
+       font-size:14.0pt;
+       font-style:italic;
+       font-family:"Arial Black", sans-serif;
+       mso-font-charset:0;
+       text-align:center;
+       white-space:normal;}
+.xl46
+       {mso-style-parent:style0;
+       font-size:8.0pt;
+       font-style:italic;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       white-space:normal;}
+.xl47
+       {mso-style-parent:style0;
+       font-size:8.0pt;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:none;
+       border-bottom:1.0pt solid green;
+       border-left:none;}
+.xl48
+       {mso-style-parent:style0;
+       font-size:8.0pt;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       border-top:1.0pt solid green;
+       border-right:none;
+       border-bottom:none;
+       border-left:none;}
+.xl49
+       {mso-style-parent:style0;
+       font-size:8.0pt;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       text-align:center;
+       white-space:normal;}
+.xl50
+       {mso-style-parent:style0;
+       font-size:18.0pt;
+       font-weight:700;
+       font-style:italic;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       text-align:center;
+       white-space:normal;}
+.xl51
+       {mso-style-parent:style0;
+       font-size:8.0pt;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       white-space:normal;}
+.xl52
+       {mso-style-parent:style0;
+       font-size:8.0pt;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:none;
+       border-bottom:1.0pt solid #FF9900;
+       border-left:none;}
+.xl53
+       {mso-style-parent:style0;
+       font-size:8.0pt;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       text-align:center;
+       border-top:1.0pt solid #FF9900;
+       border-right:none;
+       border-bottom:none;
+       border-left:none;
+       white-space:normal;}
+.xl54
+       {mso-style-parent:style0;
+       font-size:18.0pt;
+       font-weight:700;
+       font-style:italic;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       white-space:normal;}
+.xl55
+       {mso-style-parent:style0;
+       font-size:8.0pt;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:none;
+       border-bottom:1.0pt solid purple;
+       border-left:none;}
+.xl56
+       {mso-style-parent:style0;
+       font-size:8.0pt;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       text-align:center;
+       border-top:1.0pt solid purple;
+       border-right:none;
+       border-bottom:none;
+       border-left:none;
+       white-space:normal;}
+.xl57
+       {mso-style-parent:style0;
+       font-size:8.0pt;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:none;
+       border-bottom:1.0pt solid black;
+       border-left:none;}
+.xl58
+       {mso-style-parent:style0;
+       font-size:8.0pt;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       text-align:center;
+       border-top:1.0pt solid black;
+       border-right:none;
+       border-bottom:none;
+       border-left:none;
+       white-space:normal;}
+.xl59
+       {mso-style-parent:style0;
+       font-size:8.0pt;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:none;
+       border-bottom:1.0pt solid #969696;
+       border-left:none;}
+.xl60
+       {mso-style-parent:style0;
+       font-size:8.0pt;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       text-align:center;
+       border-top:1.0pt solid #969696;
+       border-right:none;
+       border-bottom:none;
+       border-left:none;
+       white-space:normal;}
+.xl61
+       {mso-style-parent:style0;
+       font-size:8.0pt;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:none;
+       border-bottom:1.0pt solid maroon;
+       border-left:none;}
+.xl62
+       {mso-style-parent:style0;
+       font-size:8.0pt;
+       font-family:Verdana, sans-serif;
+       mso-font-charset:0;
+       text-align:center;
+       border-top:1.0pt solid maroon;
+       border-right:none;
+       border-bottom:none;
+       border-left:none;
+       white-space:normal;}
+-->
+</style>
+<!--[if gte mso 9]><xml>
+ <x:ExcelWorkbook>
+  <x:ExcelWorksheets>
+   <x:ExcelWorksheet>
+    <x:Name>Glide64 Known Issues</x:Name>
+    <x:WorksheetOptions>
+     <x:DefaultRowHeight>210</x:DefaultRowHeight>
+     <x:DefaultColWidth>10</x:DefaultColWidth>
+     <x:Print>
+      <x:ValidPrinterInfo/>
+      <x:PaperSizeIndex>9</x:PaperSizeIndex>
+      <x:HorizontalResolution>600</x:HorizontalResolution>
+      <x:VerticalResolution>600</x:VerticalResolution>
+     </x:Print>
+     <x:Selected/>
+     <x:DoNotDisplayGridlines/>
+     <x:Panes>
+      <x:Pane>
+       <x:Number>3</x:Number>
+       <x:ActiveRow>10</x:ActiveRow>
+      </x:Pane>
+     </x:Panes>
+     <x:ProtectContents>False</x:ProtectContents>
+     <x:ProtectObjects>False</x:ProtectObjects>
+     <x:ProtectScenarios>False</x:ProtectScenarios>
+    </x:WorksheetOptions>
+   </x:ExcelWorksheet>
+  </x:ExcelWorksheets>
+  <x:WindowHeight>8580</x:WindowHeight>
+  <x:WindowWidth>15180</x:WindowWidth>
+  <x:WindowTopX>120</x:WindowTopX>
+  <x:WindowTopY>45</x:WindowTopY>
+  <x:ProtectStructure>False</x:ProtectStructure>
+  <x:ProtectWindows>False</x:ProtectWindows>
+ </x:ExcelWorkbook>
+</xml><![endif]--><!--[if gte mso 9]><xml>
+ <o:shapedefaults v:ext="edit" spidmax="1025"/>
+</xml><![endif]-->
+</head>
+
+<body link=gray vlink=gray class=xl24>
+
+<table x:str border=0 cellpadding=0 cellspacing=0 width=960 style='border-collapse:
+ collapse;table-layout:fixed;width:720pt'>
+ <col class=xl24 width=373 style='mso-width-source:userset;mso-width-alt:13641;
+ width:280pt'>
+ <col class=xl24 width=435 style='mso-width-source:userset;mso-width-alt:15908;
+ width:326pt'>
+ <col class=xl24 width=152 style='mso-width-source:userset;mso-width-alt:5558;
+ width:114pt'>
+ <col class=xl24 width=64 span=253 style='mso-width-source:userset;mso-width-alt:
+ 2340;width:48pt'>
+ <tr height=14 style='height:10.5pt'>
+  <td height=14 class=xl24 width=373 style='height:10.5pt;width:280pt'></td>
+  <td class=xl24 width=435 style='width:326pt'></td>
+  <td class=xl24 width=152 style='width:114pt'></td>
+ </tr>
+ <tr height=20 style='mso-height-source:userset;height:15.0pt'>
+  <td colspan=2 height=20 class=xl42 width=808 style='height:15.0pt;width:606pt'>Current
+  Version:<font class="font7"> 9.07 </font><font class="font8">(year: 2009,
+  month: 07)</font></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td colspan=2 height=14 class=xl43 width=808 style='height:10.5pt;width:606pt'></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=17 style='mso-height-source:userset;height:12.75pt'>
+  <td colspan=2 height=17 style='height:12.75pt'></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td colspan=2 height=14 class=xl44 width=808 style='height:10.5pt;width:606pt'></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=26 style='mso-height-source:userset;height:19.5pt'>
+  <td colspan=2 height=26 class=xl45 width=808 style='height:19.5pt;width:606pt'>Known
+  issues</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td colspan=2 height=14 class=xl46 width=808 style='height:10.5pt;width:606pt'></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td height=14 class=xl26 width=373 style='height:10.5pt;width:280pt'>Game</td>
+  <td class=xl26 width=435 style='width:326pt'>Description</td>
+  <td class=xl25 x:str="Correct with ">Correct with<span
+  style='mso-spacerun:yes'> </span></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td colspan=2 rowspan=2 height=29 class=xl24 style='border-bottom:1.0pt solid green;
+  height:21.75pt'></td>
+  <td class=xl25><span style='mso-spacerun:yes'> </span>following plugin:</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl24 style='height:11.25pt'></td>
+ </tr>
+ <tr height=29 style='height:21.75pt'>
+  <td height=29 class=xl28 width=373 style='height:21.75pt;width:280pt'>64 de
+  Hakken!! Tamagotchi Minna de Tamagotchi World</td>
+  <td class=xl28 width=435 style='width:326pt'>Missing or wrong textures
+  everywhere</td>
+  <td class=xl29>Ziggy LLE</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>All-Star
+  Baseball '99</td>
+  <td class=xl28 width=435 style='width:326pt'>Missing gfx in menu</td>
+  <td class=xl30>Rice, Jabo</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Bio
+  Freaks</td>
+  <td class=xl28 width=435 style='width:326pt'>Missing transition effects
+  during intro</td>
+  <td class=xl30>None</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Blast
+  Corps</td>
+  <td class=xl28 width=435 style='width:326pt'
+  x:str="missing 2d gfx in menu and game; missing noise effects ">missing 2d
+  gfx in menu and game; missing noise effects<span
+  style='mso-spacerun:yes'> </span></td>
+  <td class=xl30>Jabo software</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Command
+  &amp; Conquer</td>
+  <td class=xl28 width=435 style='width:326pt'>Briefing menu error. Intro
+  texture errors.</td>
+  <td class=xl30>(Intro only )Ziggy LLE</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Derby
+  Stallion 64</td>
+  <td class=xl28 width=435 style='width:326pt'>textures problem during demo</td>
+  <td class=xl30>Rice</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Donkey
+  kong 64</td>
+  <td class=xl28 width=435 style='width:326pt'>Wide screen doesn t work</td>
+  <td class=xl30>&nbsp;</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Excitebike
+  64</td>
+  <td class=xl28 width=435 style='width:326pt'>sky textures sliced in
+  multiplayer</td>
+  <td class=xl30>to check</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Extreme-G</td>
+  <td class=xl28 width=435 style='width:326pt'>Wrong title: the blue square
+  must not appear (coverage?)</td>
+  <td class=xl30>NONE</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'
+  x:str="FX-Zero: ">FX-Zero:<span style='mso-spacerun:yes'> </span></td>
+  <td class=xl28 width=435 style='width:326pt'>Wrong or missing (fb ?) effects
+  in menu</td>
+  <td class=xl30>Jabo Software</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Gauntlet
+  Legends 64</td>
+  <td class=xl28 width=435 style='width:326pt'>Missing status bar, flickering
+  (fb+core issue ?)</td>
+  <td class=xl30>NONE</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Gex 3,
+  Deep Cover Gecko</td>
+  <td class=xl28 width=435 style='width:326pt'>Bad water</td>
+  <td class=xl30>NONE</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Glover</td>
+  <td class=xl28 width=435 style='width:326pt'>strange blue line in sky
+  sometimes</td>
+  <td class=xl30>Ziggy LLE</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Harvest
+  Moon 64 (Bokujo Monogatari 2)</td>
+  <td class=xl28 width=435 style='width:326pt'>Problem with shadows</td>
+  <td class=xl30>Ziggy LLE</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Hey
+  You, Pikachu</td>
+  <td class=xl28 width=435 style='width:326pt'>Missing gfx</td>
+  <td class=xl30>Rice</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Jet
+  force gemini</td>
+  <td class=xl28 width=435 style='width:326pt'>Coronas behave slighly
+  incorrectly</td>
+  <td class=xl30>Wonder++</td>
+ </tr>
+ <tr height=20 style='mso-height-source:userset;height:15.0pt'>
+  <td height=20 class=xl28 width=373 style='height:15.0pt;width:280pt'>Kuiki-Uhabi-Suigo</td>
+  <td class=xl28 width=435 style='width:326pt'>Missing jigsaw (microcode issue
+  ? )</td>
+  <td class=xl30>Ziggy LLE</td>
+ </tr>
+ <tr height=29 style='height:21.75pt'>
+  <td height=29 class=xl28 width=373 style='height:21.75pt;width:280pt'>Mahjong
+  Master</td>
+  <td class=xl28 width=435 style='width:326pt'>Pictures of the character are
+  wrong. Menu doesn't show the japanese letters</td>
+  <td class=xl30>Rice/SP8</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Major
+  League Baseball Featuring Ken Griffey Jr</td>
+  <td class=xl28 width=435 style='width:326pt'>Wrong textures in game</td>
+  <td class=xl30>Jabo soft/Rice</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Mario
+  Tennis</td>
+  <td class=xl28 width=435 style='width:326pt'>Gfx errors</td>
+  <td class=xl30>to check</td>
+ </tr>
+ <tr height=29 style='height:21.75pt'>
+  <td height=29 class=xl28 width=373 style='height:21.75pt;width:280pt'>Mia
+  Hamm Soccer/Michael Owens WLS/Telefoot/RTL World League Soccer</td>
+  <td class=xl28 width=435 style='width:326pt'>Missing title; wrong transition
+  effect</td>
+  <td class=xl30>None</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Midway's
+  Greatest Arcade Hits Volume 1</td>
+  <td class=xl28 width=435 style='width:326pt'>gfx errors in lot of mini games</td>
+  <td class=xl30>to check</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Mission
+  Impossible</td>
+  <td class=xl28 width=435 style='width:326pt'>missing dithering color alpha
+  effect in menu</td>
+  <td class=xl30>NONE</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Monster
+  Truck Madness 64</td>
+  <td class=xl28 width=435 style='width:326pt'>Letters have some very small gfx
+  issue</td>
+  <td class=xl30>to check</td>
+ </tr>
+ <tr height=18 style='mso-height-source:userset;height:13.5pt'>
+  <td height=18 class=xl28 width=373 style='height:13.5pt;width:280pt'>Nascar
+  2000</td>
+  <td class=xl28 width=435 style='width:326pt'>Split screen in multiplayer
+  doesn't work correctly.</td>
+  <td class=xl30>Jabo Software</td>
+ </tr>
+ <tr height=19 style='mso-height-source:userset;height:14.25pt'>
+  <td height=19 class=xl28 width=373 style='height:14.25pt;width:280pt'>Nushi
+  Zuri 64 - Shiokaze ni Notte</td>
+  <td class=xl28 width=435 style='width:326pt'>Missing gfx in game (blender ?)</td>
+  <td class=xl30>Direct64, LLE</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Operation
+  WinBack</td>
+  <td class=xl28 width=435 style='width:326pt'>A gray square sometimes appear
+  on the screen; missing sky</td>
+  <td class=xl30>Ziggy LLE</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>OgreBattle
+  64</td>
+  <td class=xl28 width=435 style='width:326pt'>the shadows in menu are wrong</td>
+  <td class=xl30>NONE</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Parlor!
+  Pro 64 Pachinko Jikki Simulation Game</td>
+  <td class=xl28 width=435 style='width:326pt'>small texture issue in game</td>
+  <td class=xl30>Rice</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>PGA
+  European Tour</td>
+  <td class=xl28 width=435 style='width:326pt'>colors seems wrong / jauge doesn
+  t work</td>
+  <td class=xl30>Jabo</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Pikachu
+  Genki Dech</td>
+  <td class=xl28 width=435 style='width:326pt'>Missing and stretched textures</td>
+  <td class=xl30>Rice</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Pilotwings</td>
+  <td class=xl28 width=435 style='width:326pt'>Wrong shadows (coverage?)</td>
+  <td class=xl30>None</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Space
+  Silicon Valley</td>
+  <td class=xl28 width=435 style='width:326pt'>Missing on TV dithering color
+  alpha (noise)</td>
+  <td class=xl30>NONE</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Starfox
+  64</td>
+  <td class=xl28 width=435 style='width:326pt'>Missing dithering color alpha
+  (noise) at logo</td>
+  <td class=xl30>NONE</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Super
+  Bowling 64</td>
+  <td class=xl28 width=435 style='width:326pt'>In game, the two part of the
+  screen is mixed</td>
+  <td class=xl30>Rice (hack)</td>
+ </tr>
+ <tr height=43 style='height:32.25pt'>
+  <td height=43 class=xl28 width=373 style='height:32.25pt;width:280pt'>Super
+  Robot Spirit</td>
+  <td class=xl28 width=435 style='width:326pt'>In menu, just before beginning a
+  new game there is a problem in this screen: it's seems that there is only
+  half of the screen for the flames ( checked on real system)</td>
+  <td class=xl30>Rice</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Super
+  Speed Race 64</td>
+  <td class=xl28 width=435 style='width:326pt'>Sliced textures in menu</td>
+  <td class=xl30>Rice</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Top
+  Gear Hyper-Bike</td>
+  <td class=xl28 width=435 style='width:326pt'>wrong texture, problem of
+  framebuffer effect</td>
+  <td class=xl30>NONE</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Top
+  Gear Overdrive</td>
+  <td class=xl28 width=435 style='width:326pt'>Resolution change causes gfx
+  glitches in menu</td>
+  <td class=xl30>NONE</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Turok 2</td>
+  <td class=xl28 width=435 style='width:326pt'>Flashlight doesn't work</td>
+  <td class=xl30>Ziggy LLE</td>
+ </tr>
+ <tr height=29 style='height:21.75pt'>
+  <td height=29 class=xl28 width=373 style='height:21.75pt;width:280pt'>Twine</td>
+  <td class=xl28 width=435 style='width:326pt'>title screen during demo is
+  wrong; shadow at entrance of 1st level should be displayed</td>
+  <td class=xl30>Jabo</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Twisted
+  Edge Extreme Snowboarding</td>
+  <td class=xl28 width=435 style='width:326pt'>wrong background in game</td>
+  <td class=xl30>to check</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Vigilante
+  8</td>
+  <td class=xl28 width=435 style='width:326pt'>No menus, missing textures and
+  many gfx errors</td>
+  <td class=xl30>Jabo software</td>
+ </tr>
+ <tr height=29 style='height:21.75pt'>
+  <td height=29 class=xl28 width=373 style='height:21.75pt;width:280pt'>Vigilante
+  8 - 2nd Offense</td>
+  <td class=xl28 width=435 style='width:326pt'>No menus, depth problem, missing
+  textures and many gfx errors</td>
+  <td class=xl30>Jabo software</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Wipeout
+  64</td>
+  <td class=xl28 width=435 style='width:326pt'>wrong sky in some particular
+  places, ok with jabo</td>
+  <td class=xl30>Jabo</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl28 width=373 style='height:11.25pt;width:280pt'>Yoshi's
+  Story</td>
+  <td class=xl28 width=435 style='width:326pt'>cut textures</td>
+  <td class=xl30>Jabo</td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td colspan=2 height=14 class=xl48 style='height:10.5pt'>&nbsp;</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td colspan=2 height=14 class=xl49 width=808 style='height:10.5pt;width:606pt'></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td colspan=2 height=14 class=xl24 style='height:10.5pt'></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td colspan=2 height=14 class=xl49 width=808 style='height:10.5pt;width:606pt'></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=30 style='mso-height-source:userset;height:22.5pt'>
+  <td colspan=2 height=30 class=xl50 width=808 style='height:22.5pt;width:606pt'>Framebuffer
+  issues</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td colspan=2 height=14 class=xl49 width=808 style='height:10.5pt;width:606pt'></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='mso-height-source:userset;height:10.5pt'>
+  <td colspan=2 height=14 class=xl44 width=808 style='height:10.5pt;width:606pt'>NOTE:
+  HWFBE or fb notification with Mupen is correct solution in terms of speed and
+  quality. Only when REFB is needed or when the fb effect</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='mso-height-source:userset;height:10.5pt'>
+  <td colspan=2 height=14 class=xl44 width=808 style='height:10.5pt;width:606pt'>is
+  not emulated that it is considered as an issue.</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td colspan=2 height=14 class=xl51 width=808 style='height:10.5pt;width:606pt'></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td height=14 class=xl26 width=373 style='height:10.5pt;width:280pt'>Game</td>
+  <td class=xl26 width=435 style='width:326pt'>Description</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td colspan=2 rowspan=2 height=29 class=xl24 style='border-bottom:1.0pt solid #FF9900;
+  height:21.75pt'></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl25 style='height:11.25pt'></td>
+ </tr>
+ <tr height=29 style='height:21.75pt'>
+  <td height=29 class=xl31 width=373 style='height:21.75pt;width:280pt'>Akumajou
+  Dracula Makushiroku: Real Action Adventure</td>
+  <td class=xl31 width=435 style='width:326pt'>REFB needed to get motion blur
+  in intro and correct gfx in menu</td>
+  <td class=xl32>Jabo</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl31 width=373 style='height:11.25pt;width:280pt'>All-Star
+  Baseball 2000, 2001</td>
+  <td class=xl31 width=435 style='width:326pt'>Monitors requires REFB.</td>
+  <td class=xl33>NONE</td>
+ </tr>
+ <tr height=39 style='mso-height-source:userset;height:29.25pt'>
+  <td height=39 class=xl31 width=373 style='height:29.25pt;width:280pt'>Bakushou
+  Jinsei 64 - Mezase</td>
+  <td class=xl31 width=435 style='width:326pt'>Needs REFB to be playable (or
+  background will be missing) (Mupen doesn t handle fb effect
+  correctly=disabled)</td>
+  <td class=xl33>NONE</td>
+ </tr>
+ <tr height=29 style='height:21.75pt'>
+  <td height=29 class=xl31 width=373 style='height:21.75pt;width:280pt'>Beetle
+  Adventure Racing</td>
+  <td class=xl31 width=435 style='width:326pt'>Unemulated fb effects in menu
+  (scrolling effect); shadows on cars needs REFB</td>
+  <td class=xl33>Ziggy LLE</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl31 width=373 style='height:11.25pt;width:280pt'>Blast
+  Corps</td>
+  <td class=xl31 width=435 style='width:326pt'>wrong depth with shadows with
+  HWFBE</td>
+  <td class=xl33>to check</td>
+ </tr>
+ <tr height=29 style='height:21.75pt'>
+  <td height=29 class=xl31 width=373 style='height:21.75pt;width:280pt'>Bottom
+  of the 9th</td>
+  <td class=xl31 width=435 style='width:326pt'>needs REFB for correct intro;
+  With HWFBE only one of the 2 of the player heads are displayed in game</td>
+  <td class=xl33>NONE</td>
+ </tr>
+ <tr height=15 style='mso-height-source:userset;height:11.25pt'>
+  <td height=15 class=xl31 width=373 style='height:11.25pt;width:280pt'>Castlevania
+  - Legacy of Darkness</td>
+  <td class=xl31 width=435 style='width:326pt'>REFB needed to get motion blur
+  in intro and correct gfx in menu</td>
+  <td class=xl33>Jabo</td>
+ </tr>
+ <tr height=16 style='mso-height-source:userset;height:12.0pt'>
+  <td height=16 class=xl31 width=373 style='height:12.0pt;width:280pt'>Dobutsu
+  no Mori (Animal Forest)</td>
+  <td class=xl31 width=435 style='width:326pt'>The character menu is uncorrect
+  due to an unhandeld fb effect</td>
+  <td class=xl33>Direct64</td>
+ </tr>
+ <tr height=29 style='height:21.75pt'>
+  <td height=29 class=xl31 width=373 style='height:21.75pt;width:280pt'>Donkey
+  Kong 64</td>
+  <td class=xl31 width=435 style='width:326pt'>The zipper screen issue is a
+  framebuffer effects (needs REFB) (Mupen doesn t support this game)</td>
+  <td class=xl33>NONE</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl31 width=373 style='height:11.25pt;width:280pt'>Extreme-G</td>
+  <td class=xl31 width=435 style='width:326pt'>Missing transfer effects in
+  after select the car</td>
+  <td class=xl33>Direct64</td>
+ </tr>
+ <tr height=29 style='height:21.75pt'>
+  <td height=29 class=xl31 width=373 style='height:21.75pt;width:280pt'
+  x:str="iss98/2000/Jikkyou World Cup France '98/J. League Perfect Striker ">iss98/2000/Jikkyou
+  World Cup France '98/J. League Perfect Striker<span
+  style='mso-spacerun:yes'> </span></td>
+  <td class=xl31 width=435 style='width:326pt'>Missing fb effect when a goal is
+  scored</td>
+  <td class=xl33>GLN64 0.41</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl31 width=373 style='height:11.25pt;width:280pt'>The New
+  tetris</td>
+  <td class=xl31 width=435 style='width:326pt'>Missing fb effect in menu
+  (partially working with HWBFE)</td>
+  <td class=xl33>Direct64</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl31 width=373 style='height:11.25pt;width:280pt'>Micromachines
+  64</td>
+  <td class=xl31 width=435 style='width:326pt'>Missing shadows for some
+  elements of the environment</td>
+  <td class=xl33>Jabo software</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl31 width=373 style='height:11.25pt;width:280pt'>Ogre
+  Battle 64 - Person of Lordly Caliber</td>
+  <td class=xl31 width=435 style='width:326pt'>Screen transition effects
+  requires REFB.</td>
+  <td class=xl33>to check</td>
+ </tr>
+ <tr height=29 style='height:21.75pt'>
+  <td height=29 class=xl31 width=373 style='height:21.75pt;width:280pt'>Tonic
+  Trouble</td>
+  <td class=xl31 width=435 style='width:326pt'>texts for the screen just before
+  going in game needs REFB (side effect of cpu gfx effect ?)</td>
+  <td class=xl33>NONE</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl31 width=373 style='height:11.25pt;width:280pt'>WWF
+  WrestleMania 2000 /Virtual Pro Wrestling 2</td>
+  <td class=xl31 width=435 style='width:326pt'>REFB is needed to get motion
+  blur in intro</td>
+  <td class=xl33>Ziggy LLE</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl34 width=373 style='height:11.25pt;width:280pt'>Yoshi's
+  Story</td>
+  <td class=xl34 width=435 style='width:326pt'><span
+  style='mso-spacerun:yes'> </span>Transition &quot;page&quot; level needs REFB</td>
+  <td class=xl33>to check</td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td colspan=2 height=14 class=xl53 width=808 style='height:10.5pt;width:606pt'>&nbsp;</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=30 style='mso-height-source:userset;height:22.5pt'>
+  <td colspan=2 height=30 class=xl50 width=808 style='height:22.5pt;width:606pt'>Pending
+  investigation</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=30 style='height:22.5pt'>
+  <td colspan=2 height=30 class=xl54 width=808 style='height:22.5pt;width:606pt'></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td height=14 class=xl26 width=373 style='height:10.5pt;width:280pt'>Game</td>
+  <td class=xl26 width=435 style='width:326pt'>Description</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td colspan=2 rowspan=2 height=29 class=xl24 style='border-bottom:1.0pt solid purple;
+  height:21.75pt'></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl24 style='height:11.25pt'></td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl35 width=373 style='height:11.25pt;width:280pt'>F1 Pole
+  position 64</td>
+  <td class=xl35 width=435 style='width:326pt'>Wrong use of dithering alpha for
+  texts ?</td>
+  <td class=xl27></td>
+ </tr>
+ <tr height=30 style='mso-height-source:userset;height:22.5pt'>
+  <td colspan=2 height=30 class=xl56 width=808 style='height:22.5pt;width:606pt'>&nbsp;</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=30 style='height:22.5pt'>
+  <td colspan=2 height=30 class=xl50 width=808 style='height:22.5pt;width:606pt'>Non-working
+  games</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=30 style='height:22.5pt'>
+  <td colspan=2 height=30 class=xl54 width=808 style='height:22.5pt;width:606pt'></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td height=14 class=xl26 width=373 style='height:10.5pt;width:280pt'>Game</td>
+  <td class=xl26 width=435 style='width:326pt'>Description</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td colspan=2 rowspan=2 height=29 class=xl24 style='border-bottom:1.0pt solid black;
+  height:21.75pt'></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl24 style='height:11.25pt'></td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl36 width=373 style='height:11.25pt;width:280pt'>Indiana
+  Jones and the Infernal Machine</td>
+  <td class=xl36 width=435 style='width:326pt'>Unimplemented microcode</td>
+  <td class=xl37>Jabo/ Ziggy LLE</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl36 width=373 style='height:11.25pt;width:280pt'>Last
+  Legion U</td>
+  <td class=xl36 width=435 style='width:326pt'>Unimplemented microcode</td>
+  <td class=xl37>Jabo/ Ziggy LLE</td>
+ </tr>
+ <tr height=17 style='mso-height-source:userset;height:12.75pt'>
+  <td height=17 class=xl36 width=373 style='height:12.75pt;width:280pt'>Star
+  Wars - Rogue Squadron</td>
+  <td class=xl36 width=435 style='width:326pt'>Unimplemented microcode</td>
+  <td class=xl37>Jabo/ Ziggy LLE</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl36 width=373 style='height:11.25pt;width:280pt'>Star
+  Wars Episode I - Battle for Naboo</td>
+  <td class=xl36 width=435 style='width:326pt'>Unimplemented microcode</td>
+  <td class=xl37>Jabo/ Ziggy LLE</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl36 width=373 style='height:11.25pt;width:280pt'>Toukon
+  Road - Brave Spirits</td>
+  <td class=xl36 width=435 style='width:326pt'>Unimplemented microcode</td>
+  <td class=xl37>Jabo/ Ziggy LLE</td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl36 width=373 style='height:11.25pt;width:280pt'>Toukon
+  Roads - The Next Generation</td>
+  <td class=xl36 width=435 style='width:326pt'>Unimplemented microcode</td>
+  <td class=xl37>Jabo/ Ziggy LLE</td>
+ </tr>
+ <tr height=30 style='mso-height-source:userset;height:22.5pt'>
+  <td colspan=2 height=30 class=xl58 width=808 style='height:22.5pt;width:606pt'>&nbsp;</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=30 style='height:22.5pt'>
+  <td colspan=2 height=30 class=xl50 width=808 style='height:22.5pt;width:606pt'>Emu
+  issues</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=30 style='height:22.5pt'>
+  <td colspan=2 height=30 class=xl54 width=808 style='height:22.5pt;width:606pt'></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td height=14 class=xl26 width=373 style='height:10.5pt;width:280pt'>Game</td>
+  <td class=xl26 width=435 style='width:326pt'>Description</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td colspan=2 rowspan=2 height=29 class=xl24 style='border-bottom:1.0pt solid #969696;
+  height:21.75pt'></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl24 style='height:11.25pt'></td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl38 width=373 style='height:11.25pt;width:280pt'>Ai
+  Shougi 3</td>
+  <td class=xl38 width=435 style='width:326pt'>Textures are completely
+  distorted (use 1964!)</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl38 width=373 style='height:11.25pt;width:280pt'>Banjo
+  Tooie</td>
+  <td class=xl38 width=435 style='width:326pt'>Random crashes</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl38 width=373 style='height:11.25pt;width:280pt'>Dobutsu
+  no Mori</td>
+  <td class=xl38 width=435 style='width:326pt'>NES games crash emulation</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl38 width=373 style='height:11.25pt;width:280pt'>Hoshi
+  no Kirby 64</td>
+  <td class=xl38 width=435 style='width:326pt'>Minor gfx errors with the status
+  bar (use Mupen!)</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl38 width=373 style='height:11.25pt;width:280pt'>Kirby
+  64 - The Crystal Shards</td>
+  <td class=xl38 width=435 style='width:326pt'>Minor gfx errors with the status
+  bar (use Mupen!)</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl38 width=373 style='height:11.25pt;width:280pt'>Mario
+  No Photopie</td>
+  <td class=xl38 width=435 style='width:326pt'>Special card issues</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=29 style='height:21.75pt'>
+  <td height=29 class=xl38 width=373 style='height:21.75pt;width:280pt'>NBA
+  Courtside 2 - Featuring Kobe Bryant&nbsp;&nbsp;&nbsp;&nbsp;</td>
+  <td class=xl39 width=435 style='width:326pt'>CPU gfx effect issue &gt;&gt; <font
+  class="font19">Missing intro. (TIP: set &quot;Frame Buffer R/W: Yes&quot;
+  with 1964 : got some gfx but broken)</font></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl38 width=373 style='height:11.25pt;width:280pt'>Yakouchuu
+  II - Satsujun Kouru:&nbsp;</td>
+  <td class=xl39 width=435 style='width:326pt'>CPU gfx effect issue &gt;&gt; <font
+  class="font19">Missing movies</font></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=30 style='mso-height-source:userset;height:22.5pt'>
+  <td colspan=2 height=30 class=xl60 width=808 style='height:22.5pt;width:606pt'>&nbsp;</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=30 style='height:22.5pt'>
+  <td colspan=2 height=30 class=xl50 width=808 style='height:22.5pt;width:606pt'>Wrapper
+  issues</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=30 style='height:22.5pt'>
+  <td colspan=2 height=30 class=xl54 width=808 style='height:22.5pt;width:606pt'></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td height=14 class=xl26 width=373 style='height:10.5pt;width:280pt'>Game</td>
+  <td class=xl26 width=435 style='width:326pt'>Description</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td colspan=2 rowspan=2 height=29 class=xl24 style='border-bottom:1.0pt solid maroon;
+  height:21.75pt'></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl24 style='height:11.25pt'></td>
+ </tr>
+ <tr height=43 style='height:32.25pt'>
+  <td height=43 class=xl40 width=373 style='height:32.25pt;width:280pt'>Depth
+  issue when using HWFBE, mostly with fbo:International Track and Field Summer
+  Games, NFL98 TV screen (?), others</td>
+  <td class=xl40 width=435 style='width:326pt'>&nbsp;</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=30 style='mso-height-source:userset;height:22.5pt'>
+  <td colspan=2 height=30 class=xl62 width=808 style='height:22.5pt;width:606pt'>&nbsp;</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=30 style='height:22.5pt'>
+  <td colspan=2 height=30 class=xl50 width=808 style='height:22.5pt;width:606pt'>Unknown
+  issues</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=30 style='height:22.5pt'>
+  <td colspan=2 height=30 class=xl54 width=808 style='height:22.5pt;width:606pt'></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td height=14 class=xl26 width=373 style='height:10.5pt;width:280pt'>Game</td>
+  <td class=xl26 width=435 style='width:326pt'>Description</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td colspan=2 rowspan=2 height=29 class=xl24 style='border-bottom:1.0pt solid black;
+  height:21.75pt'></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl24 style='height:11.25pt'></td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl41 width=373 style='height:11.25pt;width:280pt'>Stunt
+  Racer 64</td>
+  <td class=xl41 width=435 style='width:326pt'>Microcode issue and core issues</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=15 style='height:11.25pt'>
+  <td height=15 class=xl41 width=373 style='height:11.25pt;width:280pt'>World
+  Driver Championship</td>
+  <td class=xl41 width=435 style='width:326pt'>Microcode issue and core issues</td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td height=14 colspan=3 class=xl24 style='height:10.5pt;mso-ignore:colspan'></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td height=14 colspan=3 class=xl24 style='height:10.5pt;mso-ignore:colspan'></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td height=14 class=xl25 style='height:10.5pt'>Credits :)<font class="font5">
+  Current list's maintainer: Olivieryuyu</font></td>
+  <td class=xl25></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td height=14 colspan=3 class=xl24 style='height:10.5pt;mso-ignore:colspan'></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td height=14 class=xl24 style='height:10.5pt'>A BIG thanks to:</td>
+  <td colspan=2 class=xl24 style='mso-ignore:colspan'></td>
+ </tr>
+ <tr height=28 style='mso-height-source:userset;height:21.0pt'>
+  <td colspan=2 height=28 class=xl26 width=808 style='height:21.0pt;width:606pt'>Raziel64<font
+  class="font5">, </font><font class="font12">MasterPhW</font><font
+  class="font5">, </font><font class="font12">Noxious Ninja</font><font
+  class="font5">, </font><font class="font12">TRS</font><font class="font5">, </font><font
+  class="font12">Straight</font><font class="font5">, </font><font
+  class="font12">Knuckles</font><font class="font5">, </font><font
+  class="font12">Flash</font><font class="font5">, </font><font class="font12">Milen</font><font
+  class="font5">, </font><font class="font12">Jelta</font><font class="font5">,
+  </font><font class="font12">Federelli</font><font class="font5">, </font><font
+  class="font12">Clements</font><font class="font5">, </font><font
+  class="font12">Doomulation</font><font class="font5">, etc.</font></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td height=14 class=xl24 style='height:10.5pt'>They are issues' hunters :D
+  (so am i, hehe)</td>
+  <td colspan=2 class=xl24 style='mso-ignore:colspan'></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td height=14 colspan=3 class=xl24 style='height:10.5pt;mso-ignore:colspan'></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td height=14 class=xl24 style='height:10.5pt'>And a Very special thanks to:</td>
+  <td colspan=2 class=xl24 style='mso-ignore:colspan'></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td height=14 class=xl25 colspan=2 style='height:10.5pt;mso-ignore:colspan'>Dave2001<font
+  class="font5"> for starting, </font><font class="font12">Gugaman</font><font
+  class="font5"> and </font><font class="font12">Gonetz</font><font
+  class="font5"> (^_^ He is tha man! ^_^ Thks a lot pal :) ) for enhancing and
+  fixing</font></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td height=14 class=xl24 colspan=2 style='height:10.5pt;mso-ignore:colspan'>the
+  best video plugin and showing the true power of <font class="font12">3DFX</font><font
+  class="font5"> and Glide. And to the N64 emulators' authors &amp;
+  betatesters!</font></td>
+  <td class=xl24></td>
+ </tr>
+ <tr height=14 style='height:10.5pt'>
+  <td height=14 class=xl25 colspan=2 style='height:10.5pt;mso-ignore:colspan'>Hacktarux,
+  Mulord and Ziggy<font class="font5"> for making the best Glide Wrapper out
+  there.</font></td>
+  <td class=xl24></td>
+ </tr>
+ <![if supportMisalignedColumns]>
+ <tr height=0 style='display:none'>
+  <td width=373 style='width:280pt'></td>
+  <td width=435 style='width:326pt'></td>
+  <td width=152 style='width:114pt'></td>
+ </tr>
+ <![endif]>
+</table>
+
+</body>
+
+</html>
diff --git a/source/gles2glide64/src/Glide64/Help/Glide64 Readme.html b/source/gles2glide64/src/Glide64/Help/Glide64 Readme.html
new file mode 100644 (file)
index 0000000..254ea10
--- /dev/null
@@ -0,0 +1,311 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML><HEAD><TITLE></TITLE><META http-equiv=Content-Type content="text/html; charset=UTF-8"><META content="MSHTML 6.00.2900.5512" name=GENERATOR><STYLE type=text/css>BODY {
+       FONT-FAMILY: verdana, arial, sans-serif
+}</STYLE></HEAD><BODY>
+<H1>
+<P align=center>Glide64</P><BR></H1>
+<H2 align=center>International Emulation Project <BR></H2>
+<H3 align=center>Version: "Napalm WX"</H3>
+<H4 align=center>Author: <A href="mailto:gonetz@ngs.ru">Sergey 'Gonetz' Lipski 
+</A>(Russia)<BR><BR></H4>
+<H4 align=left>Disclaimer:</H4>
+<H5 align=left>Neither I, nor anyone who is working with me, will take ANY 
+responsibility for your actions or if this program causes harm to anything, 
+including you and your computer, in any way, physically or 
+mentally.<BR><BR></H5>
+<H4 align=left>Table of Contents:</H4>
+<H4 align=left>
+<OL>
+  <LI>
+  <H5 align=left><A href="#What is Glide64">What is Glide64</A>?</H5>
+  <LI>
+  <H5 align=left><A href="#Quick Start">The Very Quick Start</A></H5>
+  <LI>
+  <H5 align=left><A href="#Common Settings">Common Settings</A></H5>
+  <LI>
+  <H5 align=left><A href="#Emulation settings">Emulation settings</A>
+  </H5><LI>
+  <H5 align=left><A href="#HWFBE">About hardware frame buffer emulation</A></H5>
+  <LI>
+  <H5 align=left><A href="#Texture_enhancement">Texture enhancement and 
+  hi-resolution textures</A></H5><LI><H5 align=left><A href="#Hotkeys">Hotkeys</A></H5><LI><H5 align=left><A href="#Specific Game Settings">Specific Game Settings</A></H5></LI></OL></H4>
+<H4 align=left>&nbsp;</H4><H4 align=left>1. <A name="What is Glide64">What is Glide64</A>?</H4>
+<P align=left>Glide64 is a graphics plugin for Nintendo 64 emulators. It can run 
+natively on 3dfx cards, or via a OpenGL-based wrapper&nbsp;for modern video 
+cards. The project started on 29 December 2001 by <STRONG>David 'Dave2001' 
+Forrester </STRONG>(USA). <STRONG>Gugaman</STRONG> (Brazil) and <STRONG>Sergey 
+'Gonetz' Lipski</STRONG> (that is me) joined him at February 2002. We worked 
+together until the autumn of 2002. Then, Dave2001 and Gugaman left the project. 
+Since that time I'm the only developer of the plugin. However, I'm not the only 
+one, who works on this project. The Glide64 project includes two additional 
+libraries beside the plugin itself. The first one is the library known as the 
+'Glitch64' wrapper, previously known as "Hacktarux's glide wrapper", named after 
+its original author, <STRONG>Hacktarux</STRONG> (France). It then was heavily 
+modified&nbsp;&amp; improved by <STRONG>Vincent 'ziggy' 
+Penne</STRONG>&nbsp;(France) and <STRONG>Brad 'mudlord' 
+Miller</STRONG>&nbsp;(Australia). The second library is a texture enhancement 
+module named 'GlideHQ', created by <STRONG>Hiroshi 'KoolSmoky' Morii</STRONG> 
+(Japan). Beside that, lots of people from around the world helped me to test the 
+plugin and gave me valuable advices on how to improve it. The main tester of 
+this version is <STRONG>Olivieryuyu </STRONG>(France); and&nbsp;additional 
+testing, advices and friendly support was provided by <STRONG>Wes 'Legend' 
+McDaniel&nbsp;</STRONG>(USA). <BR></P>
+<H4>2. <A name="Quick Start">The Very Quick Start<BR></A></H4>
+<P align=left>To install Glide64:
+  </P><OL><LI><DIV align=left><SPAN lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: Verdana; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA">Open archive and c</SPAN>opy everything from the <EM>'Plugin'</EM> folder into the 
+  folder where all your N64 plugins are stored (this is usually the 
+  '<EM>Plugin</EM>' folder in your emulator's folder, e.g. 
+  Project64\Plugin).</DIV>
+  <LI>
+  <DIV align=left><SPAN lang=EN-US style="FONT-SIZE: 12pt; COLOR: #00b050; LINE-HEIGHT: 115%; FONT-FAMILY: Verdana; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"><FONT color=#000000>If you don’t have a Voodoo card, make sure you</FONT> </SPAN>copy the glide3x.dll file from the 
+  '<EM>Wrapper</EM>' folder into your emulator's folder.</DIV></LI></OL>
+<P align=left>To setup Glide64:<BR></P>
+<OL>
+  <LI>
+  <DIV align=left>Launch your emulator.</DIV>
+  <LI>
+  <DIV align=left>Select Glide64 as your graphics plugin.</DIV>
+  <LI>
+  <DIV align=left>Select <EM>'Configure graphics plugin'</EM></DIV>
+  <LI>
+  <DIV align=left>In Glide64 configuration dialog, on the <EM>'Common 
+  settings'</EM> tab, in the "Rendering" section, select your desired windowed 
+  and full screen resolution.&nbsp;</DIV></LI></OL>
+<P align=left>Glide64 is now ready to use. If you're a novice in N64 emulation, 
+you may skip the rest of this document, start your favorite games and enjoy! If 
+you are an experienced emu fan, or a curious person, read further for 
+explanation for other options and various tips and tricks.<BR></P>
+<H4><A name="Common Settings">3. Common Settings</A></H4><H5>3.1 Rendering</H5><P>Rendering related settings described here.</P><H5>3.1.1 Common </H5><P><EM>'Windowed or 3dfx card resolution'</EM> - This option selects the fullscreen resolution for 3dfx cards and windowed resolution for other cards. Note: for 3dfx cards the plugin must be in fullscreen mode to see anything.</P><P><EM>'Vertical sync'</EM> - This option will enable the vertical sync, which will prevent tearing. Note: this option will ONLY have effect if vsync is set to <EM>"Software Controlled".</EM></P><H5>3.1.2 OpenGL settings</H5><P><EM>'Anisotropic filtering'</EM>&nbsp; -&nbsp; This filter sharpens and brings out the details of textures that recede into the distance. When activated, it will use the max anisotropy your video card supports. However, this will override native way of texture filtering and may cause visual artifacts in some games.</P><P><EM>'Autodetect VRAM Size'</EM> - If checked, plugin will try to autodetect VRAM size. But if this appears wrong, please uncheck and set it to correct value. Currently VRAM autodetection is implemented only for Windows.</P><P><EM><A name=Use_FBO>'Use Frame buffer objects'</A></EM> - Changes the way frame buffer effects are rendered - with or without usage of the OpenGL Frame Buffer Objects (FBO) extension. The choice depends on game and your video card. FBO off is good for NVIDIA cards, while for ATI cards, it's usually best that FBOs are turned on. Also, some FB effects work only with one of the methods, no matter which card you have. On the whole, with FBO off, compatibility/accuracy is a bit better (which is the case for Resident Evil 2). However, with FBO on with some systems, it can actually be a bit faster in cases.</P><H5>3.2 On screen display</H5><P>These settings are located in&nbsp;<EM>'Common settings'</EM> tab -&nbsp;in the <EM>'On screen display'</EM> section. You may select them with no worries - these settings do not impact the emulation. </P><P>Select any or all options in the <EM>'Speed'</EM> option group to see how fast the game is running.<EM> 'FPS counter'</EM> will show you the actual frames per second (FPS) for the current game. This number depends on the running game. The<EM> 'VI/s counter'</EM> will show you the number of visual interrupts per second received by the plugin. This number must be 50 for PAL games and 60 for NTSC games.&nbsp; <EM>'% spe</EM>ed' will show you, how fast your game is emulated; 100% means that the currently emulated game runs at perfect speed. <EM>'FPS transparent'</EM> option makes the&nbsp;background of the counter(s) transparent. </P><P>Select <EM>'Clock enabled'</EM> in the <EM>'Time'</EM> group to see the current&nbsp; time. Select <EM>'Clock is 24-hour'</EM> to see the time in 24-hour format. Time information will be displayed in the lower right corner of the screen. </P><H5>3.3 Other</H5><P>All other common settings are grouped in the <EM>'Other'</EM> section.</P><P><EM>'Show advanced emulation options'</EM> - Enable <EM>'Emulation settings'</EM> tab. Read more in <A href="#Emulation settings">'Emulation settings'</A> section.</P><P><EM>'Show texture enhancement options'</EM> - Enable <EM>'Texture enhancement'</EM> tab. Read more in <A href="#Texture_enhancement">'Texture enhancement and hi-resolution textures'</A> section.</P><P><EM>'Screenshot format'</EM> - Format, in which screen shots will be saved. Currently you may choose <EM>'BMP', 'PNG'</EM> or <EM>'JPEG'</EM>.</P><P><EM>'Glide card #'</EM> - This option is only for users with multiple 3dfx cards installed in one machine. This selects the glide card number to use. If you only have one glide card installed in your system, set this option to #1. Otherwise, select the number that corresponds to the glide card you want to use.</P><P align=left></P><H4>4.&nbsp;<A name="Emulation settings">Emulation settings</A></H4>
+<P align=left><U>Warning</U>: The plugin already has optimal settings for all 
+games. Changing these settings is dangerous: it can cause glitches and 
+instability. Access to emulation settings is disabled by default.</P>
+<P align=left>To enable <EM>'Emulation settings'</EM> tab, check <EM>'Show advanced emulation 
+options'</EM> on the <EM>'Common settings tab'</EM> and close the configuration 
+dialog.&nbsp;Open&nbsp;configuration dialog again and&nbsp;the <EM>'Emulation 
+settings'</EM> tab will now be available.<BR><BR><U>Important</U>: <EM>'Emulation settings'</EM> tab operates in 2 different ways depending on whether or not a game is running.</P>
+<UL>
+  <LI>
+  <DIV align=left>When no game is running, you may change <EM>"default"</EM> emulation 
+  settings.&nbsp;The plugin uses these settings when&nbsp;a game does not 
+  have&nbsp;corresponding custom settings. Again, it is strongly recommended to not touch anything here.</DIV>
+  <LI>
+  <DIV align=left>When a game&nbsp;<STRONG>IS</STRONG> running, this tab shows emulation settings the 
+  game is using. Any changes will be applied immediately after you close the configuration dialog. You will be asked - save the changes in the ini file or use them in the current session only. If you choose 'Yes',&nbsp;your changes will&nbsp;be saved in the custom section of the ini file and will be used permanently. Otherwise, new setting will be used until the game stops or new save state loaded.</DIV></LI></UL>
+<H5>4.1 General options</H5>
+<P align=left><EM><A name="Filtering mode">'Filtering mode'</A></EM> - you may set <EM>'Force bilinear', 
+'Automatic'</EM> or <EM>'Force point-sampled'</EM> mode. You also may easily 
+switch between filtering modes during game play by pressing the&nbsp;backspace 
+button. </P>
+<P align=left><EM>'Buffer swapping modes'</EM> - It's hard to explain the 
+difference between these modes. Just select any available option. If a game suffers from flickering, select another buffer swapping mode and see if that fixes the problem.<BR><BR><EM>'LOD calculation'</EM>. 
+The N64 uses a very special way to implement mip-mapping, which is not available on PC hardware. Glide64 implements a rough approximation of N64 
+mip-mapping, which can be enabled by setting <EM>'LOD calculation'</EM> option 
+to <EM>'fast'</EM> or <EM>'precise'</EM>. The result is not always good 
+though.</P><P align=left><EM>'Aspect ratio'</EM> - Most N64 games use 4:3 aspect ratio, but some support widescreen too. You may select appropriate aspect here and set widescreen mode in game settings. In <EM>'Stretch'</EM> mode the output will be stretched to the entire screen, other modes may add black boarders if necessary.</P>
+<P align=left><EM>'Fog'</EM> - Sets fog emulation on/off. </P>
+<P align=left><EM>'Buffer clear on every frame'</EM> - Forces the frame buffer to be cleared every frame drawn. Usually frame buffer clear is controlled by the game. However, in some cases it is not well emulated, and some garbage may be left on the screen. In such cases, this option must be set on.</P>
+<H4>
+<H5>4.2. Frame buffer emulation</H5></H4>
+<P align=left>N64 games often use auxiliary frame buffers to implement special 
+game effects like motion blur or for optimization purposes. The console can 
+allocate as many auxiliary frame buffers as needed and then use them as usual 
+textures. PC video cards usually use only one buffer per frame, thus emulation 
+of frame buffer effects is always a hard problem. Glide64 implements lot of 
+methods of frame buffer emulation, to support as many effects as possible. Most 
+games will work fine with&nbsp;pre-defined settings, but some effects require 
+additional options to be set. Known cases are described in the <A href="Glide64 compatibility list.html">Compatibility List</A> and in the <A href="#Specific Game Settings">Specific Game Settings</A>. You may set the following 
+options:</P>
+<P align=left><EM>'Enable frame buffer emulation'</EM> - When this option is on, the plugin will try to detect frame buffer effects usage and emulate them. This option is off by default, but for all games, which use frame buffer effects,&nbsp;it will be automatically turned on. </P>
+<P align=left><EM><A name=Use_HWFBE>'Hardware frame buffer emulation'</A></EM> - Enables hardware 
+frame buffer emulation. Usually, this must be set on, except some rare cases, 
+mentioned in the <A href="Glide64 compatibility list.html">Compatibility 
+List</A>. Read <A href="#HWFBE">next chapter </A>for explanation of hardware 
+frame buffer emulation.</P>
+<P align=left><EM><A name="Motion blur">'Motion blur'</A></EM> - Enables motion blur emulation. Motion blur 
+works slow without hardware frame buffer emulation, so it is made optional. This 
+option usually must be on, because most of cards support hardware frame buffer 
+emulation. You may also switch it on/off during game play by pressing ALT-B.</P>
+<P align=left><EM><A name="Read every frame">'Read every frame'</A></EM> - In some cases,&nbsp; Glide64 cannot 
+detect frame buffer usage by the game. In this case the only way to emulate 
+frame buffer effects, is to read every rendered frame from video memory and put 
+it into the emulated RDRAM. Reading from video memory is usually slow, so this 
+method of frame buffer emulation is optional. You may also switch it on/off 
+during game play by pressing ALT-V.</P>
+<P align=left><EM><A name=Get_FBI>'Get frame buffer info'</A></EM> - This is another way to emulate 
+frame buffer effects, which the plugin cannot detect. This option allows the 
+plugin to get notification about frame buffer usage from the emulator and thus 
+emulate frame buffer effects without slowdown. Currently it works only with 
+Mupen64 (and even Mupen is not 100% reliable with this). Do not enable this option with 1964, otherwise the emulator will 
+crash.</P>
+<P align=left><EM><A name=RenderN64FB>'Render N64 frame buffer as texture'</A></EM>. The N64 
+architecture allows the CPU to write directly into the frame buffer. Sometimes 
+N64 games uses this ability, which may lead to graphics lost during emulation, 
+since graphics plugin does not know, that some graphics are already written in 
+the N64 frame buffer by the CPU. Some examples of this are: falling pills in 
+Dr.Mario and rain in Jet Force Gemini. When this option is enabled, content of 
+each N64 frame buffer is rendered as a texture over the current rendered frame. 
+This prevents graphics loss, but may cause slowdowns and various glitches in 
+some games. </P>
+<P align=left><EM>'Detect CPU write to N64 frame buffer'</EM>- This option works 
+as the previous options, but the plugin is trying to detect, when a game uses 
+CPU writes to the N64 frame buffer. The N64 frame buffer is rendered only when 
+CPU writes is detected. Use this option for those games, in which you see still 
+image or no image at all for some time with no reason.</P>
+<H4>
+<H5>4.3. <A name="Depth buffer emulation">Depth buffer emulation</A></H5></H4>
+<P align=left>Sometimes N64 games use values in the depth buffer to decide, when 
+to render some particular object or not. This is often used for coronas, which 
+must be rendered only if they are not covered by other objects in the 3D scene. 
+To emulate it properly, the N64 depth buffer must be filled with correct values. 
+Glide64 uses software rendering to fill the N64 depth buffer. It is enabled by 
+default. If you experience performance issues, set the <EM>'Software depth 
+buffer rendering'</EM> option off.</P>
+<H4>5. <A name=HWFBE>About hardware frame buffer emulation</A></H4>
+<P align=left>The usual method of frame buffer emulation, which theoretically 
+should always work, is to render auxiliary frame buffers into the main video 
+buffer and then read it from video memory into main memory, and put into the 
+structure representing N64 memory (RDRAM). This approach has 2 main 
+disadvantages:</P>
+<P align=left>1) auxiliary frame buffers may be visible when they should
+n't be.</P>
+<P align=left>2) reading from video memory is a very slow operation, thus many 
+frame buffer effects will be slow.</P>
+<P align=left>Also, image taken from video memory must be scaled down to N64 
+native resolution (usually 320x240), thus quality lost is inevitable. To avoid 
+these problems, Glide64 uses the Glide3x extension, which allows it to create 
+auxiliary frame buffers right into video memory, like the N64 does. This allows 
+the plugin to run frame buffer effects without speed&nbsp;hits or quality loss. 
+Hardware frame buffer emulation (HWFBE) greatly improves many games, but it has 
+some restrictions:</P>
+<P align=left>1) HWFBE is in fact a hack - auxiliary frame buffers are not put 
+into N64 memory. When a game uses a texture located in RDRAM corresponding to an 
+auxiliary frame buffer, the plugin uses the texture located in video memory 
+instead. The game may use this area in RDRAM for different textures later, but 
+the plugin will use it's auxiliary buffer anyway, which leads to serious 
+glitches. I have tried to reduce the probability of this situation, but it is 
+still possible. If you encounter it, switch to windowed mode, and then back to 
+full screen again.</P>
+<P align=left>2) The Glide extension used for HWFBE is fully supported by Voodoo 
+4/5 only. Banshee and Voodoo3 cards also support it, but only for small 
+auxiliary frame buffers (e.g. shadows). Other Voodoo cards do not support it at 
+all! </P>
+<P align=left>3) HWFBE may not work for Voodoo4/5 if the anti-aliasing option is 
+set to "fastest performance". Use any other option there.</P>
+<P align=left>4) Anti-aliasing is not applicable to auxiliary frame buffers.</P>
+<P align=left>5) The wrapper support HWFBE almost fully, but it has its peculiarities. Two ways of hardware frame buffer emulation are implemented in the wrapper - with, and without usage of the OpenGL Frame Buffer Objects (FBO) extension. The method with FBO's works fast on any card, which supports FBO's, but it may cause depth issues, since framebuffer objects use their own depth buffer. The method without FBO's works on almost any card, has no problems with depth buffer usage, but it may work slowly on ATI cards. To switch between these methods set the <EM><A href="#Use_FBO">'Use frame buffer objects'</A></EM> option on/off.&nbsp;</P>
+<H4>6. <A name=Texture_enhancement>Texture enhancement and hi-resolution 
+textures</A></H4>
+<P align=left>Texture enhancement is done via GlideHQ - a real-time texture enhancer library with hi-resolution texture pack support. GlideHQ is an independent DLL, which dynamically loaded by Glide64, when it is needed. GlideHQ itself has no user interface; all its settings are placed on the <EM>'Texture enhancement'</EM> tab. This tab is disabled by default. To enable it, check <EM>'Show texture enhancement options'</EM> on the<EM> 'Common settings'</EM> tab and close the configuration dialog. Open configuration dialog again and switch to <EM>'Texture enhancement'</EM> tab.</P><H5 align=left>6.1. Texture enhancement</H5><P align=left>GlideHQ uses variety of methods to enhance the original N64 textures.</P><P align=left><EM>'Filter'</EM> - Apply a filter to either smooth or sharpen textures. There are 4 different smoothing filters and 2 different sharpening filters. The higher the number, the stronger the effect, i.e. <EM>'Smoothing filter 4'</EM> will have a much more noticeable effect than <EM>'Smoothing filter 1'</EM>. Be aware that performance may have an impact depending on the game and/or the PC.</P><P align=left><EM>'Enhancement'</EM> - 7 different filters are selectable here, each one with a distinctive look. Be aware of possible performance impacts. <BR><U>Important</U>: <EM>'Store'</EM> mode - saves textures in cache "as is". It can improve performance in games, which load many textures. Disable <A href="#Ignore backgrounds"><EM>'Ignore backgrounds'</EM></A> option for better result.</P><P align=left><EM>'Texture cache'</EM> - Enhanced and filtered textures are cached for later use. This helps boost performance if there are subsequent requests for the same texture, which is the case for most games. Normally, 128MB should be more than enough but there is a sweet spot for each game. 32MB will be enough for Super Mario, but Conker's BFD streams a lot of textures so setting 256MB or more will boost performance.</P><P align=left><EM>'Compress texture cache'</EM> - Memory will be compressed so that more textures can be held in the texture cache. The compression ratio varies with each texture, but 1/5 of the original size would be a modest approximation. They will be decompressed on-the-fly, before being downloaded to the gfx hardware. This option will still help save memory space even when using texture compressions such as FXT1 and S3TC.</P><P align=left><EM>'Apply texture compression'</EM> - Textures will be compressed using selected texture compression method. The overall compression ratio is about 1/6 for FXT1 and 1/4 for S3TC. In addition to saving space on the texture cache, the space occupied on the GFX hardware's texture RAM, by the enhanced textures, will be greatly reduced. This minimizes texture RAM usage, decreasing the number of texture swaps to the GFX hardware leading to performance gains. However, due to the nature of lossy compression of FXT1 and S3TC, using this option can sometimes lead to quality degradtion of small size textures and color banding of gradient colored textures.</P><P align=left><EM><A name="Ignore backgrounds">'Ignore backgrounds'</A></EM> - It is used to skip enhancement for wide narrow textures, usually used for backgrounds. This may save texture memory greatly and increase performance.</P><H5 align=left>6.2 Hi-resolution textures</H5><P align=left>GlideHQ supports hi-resolution texture packs, and texture dumping/editing.</P><P align=left><EM>'Format'</EM> - Chose which method is to be used for loading Hi-res texture packs. Only Rice's format is available currently. Leave on <EM>'None'</EM> if you will not be needing to load hi-res packs.</P><P align=left><EM>'Alternative CRC calculation'</EM> - This option enables emulation of a palette CRC calculation bug in RiceVideo. If some textures are not loaded, try to set this option on/off. This option is disabled in texture dumping mode.</P><P align=left><EM>'Texture dumping/editing mode'</EM> - In this mode, you have that ability to dump textures on screen to the appropriate folder. You can also reload textures while the game is running to see how they look instantly - big time saver! <U>Hotkeys</U>: <EM>"R"</EM> reloads hires textures from texture pack - <EM>"D"</EM> toggles texture dumps on/off.</P><P align=left><EM>'Use alpha channel fully'</EM> - When this option is off, 16bit rgba textures will be loaded using RiceVideo style - with 1bit for alpha channel. When it is on, GlideHQ will check, how alpha channel is used by the hires texture, and select most appropriate format for it. This gives texture designers freedom to play with alpha, as they need, regardless of format of original N64 texture. For older and badly designed texture packs it may cause unwanted black borders.</P><P align=left><EM>'Compress texture cache'</EM>&nbsp; - When game started, plugin loads all its hi-resolution textures into PC memory. Since hi-resolution textures are usually large, the whole pack can take hundreds megabytes of memory. Cache compression allows to save memory space greatly. Textures will be decompressed on-the-fly, before being downloaded to the gfx hardware. This option will still help save memory space even when using texture compression.</P><P align=left><EM>'Apply texture compression'</EM> - Textures will be compressed using selected texture compression method. The overall compression ratio is about 1/6 for FXT1 and 1/4 for S3TC. In addition to saving space on the texture cache, the space occupied on the GFX hardware's texture RAM, by the enhanced textures, will be greatly reduced. This minimizes texture RAM usage, decreasing the number of texture swaps to the GFX hardware leading to performance gains. However, due to the nature of lossy compression of FXT1 and S3TC, using this option can sometimes lead to quality degradtion of small size textures and color banding of gradient colored textures.</P><P align=left><EM>'Force 16bpp textures'</EM> - The color of the textures will be reduced to 16bpp. This is another space saver and performance enhancer. This halves the space used on the texture cache and the GFX hardware's texture RAM. Color reduction is done so that the original quality is preserved as much as possible. Depending on the texture, this usually is hardly noticeable. Sometimes though, it can be: skies are a good example.</P><P align=left><EM>'Tile textures'</EM> - When on, wide texture will be split on several tiles to fit in one 256-width texture. This tiled texture takes much less video memory space and thus overall performance will increase. However, corresponding polygons must be split too, and this is not polished yet- various issues are possible, including black lines and polygons distortions.</P><H5 align=left>6.3 Common</H5><P align=left><EM>'Texture compression method'</EM> - Select the method for texture compression. 3dfx cards support both FXT1 and S3TC, other cards can use S3TC only.</P><P align=left><EM>'Save texture cache to hard disk'</EM> - <U>For enhanced textures cache</U>: this will save <STRONG>all</STRONG> previously loaded and enhanced textures to the hard drive. So upon next game launch, all the textures will be instantly loaded, resulting in smoother performance for all your games. <U>For high-resolution textures cache</U>: After creation, loading hi-res texture will take only a few seconds upon game launch, as opposed to the 5 - 60 seconds a pack can take to load without this cache file. The only downside here is upon any changes to the pack, the cache file will need to be manually deleted. Saved cache files go into a folder called <EM>"Cache"</EM> within the<EM> "Plugins</EM>" folder.</P><H4 align=left>7. <A name=Hotkeys>Hotkeys</A></H4><P align=left>Glide64 uses the following hotkeys:</P><P align=left><EM>"BACKSPACE"</EM> - Cycle between <A href="#Filtering mode">texture filtering modes</A>. Currently selected mode will be shown in the status line on the bottom of the screen for a short time.</P><P align=left><EM>"Alt"+"V"</EM> - Toggles <A href="#Read every frame">read every frame</A> on/off. Current status of this option will be shown in the status line on the bottom of the screen for a short time.</P><P align=left><EM>"Alt"+"B"</EM> - Toggles <A href="#Motion blur">motion blur</A> on/off. Current status of this option will be shown in the status line on the bottom of the screen for a short time.</P><P align=left>GlideHQ uses the following hotkeys:</P><P align=left><EM>"D"</EM> - toggles texture dumps on/off.</P><P align=left><EM>"R"</EM> - reloads hires textures from the texture pack.</P><H4 align=left>
+&nbsp;8. <A name="Specific Game Settings">Specific Game Settings</A></H4><SPAN lang=EN-US style="mso-ansi-language: EN-US"><FONT face="Times New Roman"><H5 class=MsoNormal style="MARGIN: 0cm 0cm 0pt">
+<DIV class=MsoNormal style="MARGIN: 0cm 0cm 0pt">
+<H4>
+<UL>
+  <DIV class=MsoNormal style="MARGIN: 0cm 0cm 0pt">
+  <H3>
+  <LI>
+  </FONT><H5 class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><A href="#Banjo-Kazooie">Banjo-Kazooie</A></H5><FONT face="Times New Roman">
+  <LI>
+  </FONT><H5 class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><A href="#Beetle Adventure Racing">Beetle Adventure Racing / HSV Adventure Racing</A></H5><FONT face="Times New Roman">
+  <LI>
+  </FONT><H5 class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><A href="#Resident Evil 2">Bio Hazard 2 / Resident Evil 2</A></H5><FONT face="Times New Roman">
+  <LI>
+  </FONT><H5 class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><A href="#Conker's Bad Fur Day">Conker's Bad Fur Day</A></H5><FONT face="Times New Roman">
+  <LI>
+  </FONT><H5 class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><A href="#Fushigi no Dungeon">Fushigi no Dungeon - Furai no Shiren 2 (J)</A></H5><FONT face="Times New Roman">
+  <LI>
+  </FONT><H5 class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><A href="#The - Majora's Mask">Legend of Zelda, The - Majora's Mask</A></H5><FONT face="Times New Roman">
+  <LI>
+  </FONT><H5 class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><A href="#Paper Mario">Mario Story / Paper Mario</A></H5><FONT face="Times New Roman">
+  <LI>
+  </FONT><H5 class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><A href="#Perfect Dark">Perfect Dark</A></H5></H3></LI></DIV></UL></H4></DIV></H5></SPAN>
+
+<H5><A name=Banjo-Kazooie>Banjo-Kazooie</A></H5>
+<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="mso-ansi-language: EN-US"><FONT face="Times New Roman"><FONT face=Verdana>The puzzle effect 
+is not emulated by default. To see it, either set <EM><A href="#Read every frame">'Read every frame'</A></EM> 
+option on or set <EM><A href="#Get_FBI">'Get frame buffer info'</A></EM> and run this game with 
+Mupen64</FONT>.</FONT></SPAN><O:P></O:P></P>
+<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="mso-ansi-language: EN-US"><FONT face="Times New Roman"><O:P></O:P></FONT></SPAN></P><SPAN lang=EN-US style="mso-ansi-language: EN-US"><FONT face="Times New Roman">
+</FONT><H5><SPAN lang=EN-US style="mso-ansi-language: EN-US"><A name="Beetle Adventure Racing">Beetle Adventure 
+Racing</A> / HSV Adventure Racing</SPAN></H5><FONT face="Times New Roman">
+<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><O:P></O:P></FONT></SPAN></P>
+<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="mso-ansi-language: EN-US"><FONT face="Times New Roman"><O:P></O:P></FONT></SPAN></P>
+<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="mso-ansi-language: EN-US"><STRONG>Fog.</STRONG> The fog in this game is 
+implemented&nbsp;in a&nbsp;very specific way. When rendering of the current 
+frame is finished, the depth buffer, filled during rendering of this frame, is 
+used as a texture and blended with the color buffer. As the result, the frame 
+becomes fogged, and the fog is thicker where depth values are higher. Glide64 
+implements two ways to emulate this effect, software and hardware ones. 
+<O:P></O:P></SPAN></P>
+<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="mso-ansi-language: EN-US">Software emulation 
+uses software depth buffer rendering. It works on all cards, but has two 
+disadvantages:<O:P></O:P></SPAN></P>
+<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="mso-ansi-language: EN-US"><SPAN style="mso-spacerun: yes">&nbsp;</SPAN>- Alpha testing is not used during 
+software depth buffer rendering. As the result, the pixels, which would normally 
+be rejected by alpha testing, are stored in the depth buffer. This causes 
+artifacts in the produced fog.<O:P></O:P></SPAN></P>
+<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="mso-ansi-language: EN-US">- The software 
+depth buffer has original (that is low) N64 resolution output. When it is used 
+as a&nbsp;texture, blended with the high-resolution frame buffer, aliasing is 
+visible.<O:P></O:P></SPAN></P>
+<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="mso-ansi-language: EN-US">Hardware emulation 
+produces perfect fog, but currently it works only on 3dfx Voodoo 4/5's. These 
+cards use the same depth buffer format, as the N64, and they can allocate the 
+depth buffer right in the texture memory, so it can be easily used as a texture, 
+as on N64 hardware. </SPAN><SPAN lang=EN-US style="mso-ansi-language: EN-US">In both cases, the 
+<EM><A href="#Depth buffer emulation">'Software depth buffer rendering'</A></EM> option must be on.</SPAN></P><P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="mso-ansi-language: EN-US"></SPAN><SPAN lang=EN-US style="mso-ansi-language: EN-US"><BR><STRONG>On car reflection.</STRONG> Your car (the car 
+you drive) should reflect the environment in this game. That is, various 
+objects, which you roll by, should be reflected on your car. This is implemented 
+via the usage of frame buffer content. Emulation of this effect implies frame 
+buffer emulation. Unfortunately, this can't be done in hardware, because the 
+texture, which is used as a reflection, is not a part of the frame buffer - it 
+is the result of frame buffer post processing, made on the N64 CPU. Thus, the 
+only way to emulate this effect is to use the <EM><A href="#Read every frame">'Read every frame'</A></EM> 
+option. If your hardware allows you to use this option without slowdown, you are 
+lucky.<O:P></O:P></SPAN></P>
+<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="mso-ansi-language: EN-US"><FONT face="Times New Roman"><O:P></O:P></FONT></SPAN></P><SPAN lang=EN-US style="mso-ansi-language: EN-US"><FONT face="Times New Roman">
+</FONT><H5><SPAN lang=EN-US style="mso-ansi-language: EN-US">Bio Hazard 2 / <A name="Resident Evil 2">Resident Evil 
+2</A></SPAN></H5><FONT face="Times New Roman">
+<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><O:P></O:P></FONT></SPAN></P>
+<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="mso-ansi-language: EN-US">This game uses 
+pre-rendered depth buffers, which are stored in the game's ROM, and are loaded 
+into the depth buffer memory area each frame before rendering is started. This 
+is hard to emulate, and especially hard to emulate efficiently. The following 
+options must be set:<O:P></O:P></SPAN></P>
+<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="mso-ansi-language: EN-US"><EM><A href="#Use_HWFBE">'Hardware frame buffer emulation'</A></EM> - on<O:P></O:P></SPAN></P>
+<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="mso-ansi-language: EN-US"><EM><A href="#Depth buffer emulation">'Software depth buffer rendering'</A></EM> - on<O:P></O:P></SPAN></P>
+<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="mso-ansi-language: EN-US"><EM><A href="#Use_FBO">'Use Framebuffer Objects'</A></EM> - off<O:P></O:P></SPAN></P>
+<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="mso-ansi-language: EN-US"><FONT face="Times New Roman"><FONT face=Verdana>To get good sound 
+in this game, use Mupen64 with Azimer's HLE sound plugin v.056. However, the 
+game may flicker in some places with Mupen64.</FONT>&nbsp;</FONT></SPAN><SPAN lang=EN-US style="mso-ansi-language: EN-US"><FONT face="Times New Roman">&nbsp;<O:P></O:P></FONT></SPAN></P><SPAN lang=EN-US style="mso-ansi-language: EN-US"><FONT face="Times New Roman">
+</FONT><H5><SPAN lang=EN-US style="mso-ansi-language: EN-US"><A name="Conker's Bad Fur Day">Conker's Bad Fur 
+Day</A></SPAN></H5><FONT face="Times New Roman">
+<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"></FONT></SPAN><SPAN lang=EN-US style="mso-ansi-language: EN-US"><FONT face="Times New Roman"><FONT face=Verdana>The game is well 
+emulated with default settings. However, there are two special effects in this 
+game, which require special settings: the black-and-white "It's war" cut-scene, 
+and the Uga-Buga pixilated effect. To see these effects, set the following 
+options:<BR><EM><A href="#Read every frame">'Read every frame'</A></EM> - on<BR><EM><A href="#RenderN64FB">'Render N64 frame buffer as texture' </A></EM>- on<BR>The game is not 
+playable with these settings, so use them only to see these particular effects. 
+<BR><BR>Note for ATI users: you must&nbsp;set <EM><A href="#Use_FBO">'Use Framebuffer Objects'</A></EM> 
+option on, otherwise the game will work very 
+slow.</FONT></P>
+</FONT><H5><A name="Fushigi no Dungeon">Fushigi no Dungeon</A> - Furai no Shiren 2 
+(J)</H5><FONT face="Times New Roman">
+<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"></FONT></SPAN><SPAN lang=EN-US style="mso-ansi-language: EN-US">To see correct 
+background in menus, either set <A href="#Read every frame"><EM>'Read every frame'</EM></A> option on or set <EM><A href="#Get_FBI">'Get frame buffer info'</A></EM> and run this game with Mupen64.</SPAN></P><SPAN lang=EN-US style="mso-ansi-language: EN-US"><FONT face="Times New Roman">
+</FONT><H5><SPAN lang=EN-US style="mso-ansi-language: EN-US">Legend of Zelda, <A name="The - Majora's Mask">The - 
+Majora's Mask</A></SPAN><SPAN lang=EN-US style="mso-ansi-language: EN-US"></H5></SPAN><FONT face="Times New Roman">
+<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"></FONT></SPAN><SPAN lang=EN-US style="mso-ansi-language: EN-US"><FONT face="Times New Roman"><FONT face=Verdana>Lens of&nbsp; 
+Truth may not work, if <EM><A href="#Use_FBO">'Use Framebuffer Objects'</A></EM> option set off
+. <BR>Also, when Lens of Truth is used, some 
+objects outside of the lens can be cut. This is not a bug - depth buffer copy 
+must be emulated to&nbsp;fully emulate Lens of Truth. It is currently supported 
+only by 3dfx Voodoo 4/5 cards.</FONT> <BR></FONT></SPAN></P><SPAN lang=EN-US style="mso-ansi-language: EN-US"><FONT face="Times New Roman"><SPAN lang=EN-US style="mso-ansi-language: EN-US"><FONT face="Times New Roman">
+</FONT></FONT><H5>Mario Story / <A name="Paper Mario">Paper Mario</A></H5></SPAN><FONT face="Times New Roman">
+<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"></FONT></SPAN><SPAN lang=EN-US style="mso-ansi-language: EN-US">To see correct 
+background in the menu subscreen, either set the <EM><A href="#Read every frame">'Read every frame'</A></EM> 
+option on or set <EM><A href="#Get_FBI">'Get frame buffer info'</A></EM> and run this game with 
+Mupen64.</SPAN><SPAN lang=EN-US style="mso-ansi-language: EN-US"><FONT face="Times New Roman">&nbsp;</P></FONT></SPAN><SPAN lang=EN-US style="mso-ansi-language: EN-US"><H5><A name="Perfect Dark">Perfect Dark</A></H5><FONT face="Times New Roman">
+<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"></FONT></SPAN><SPAN lang=EN-US style="mso-ansi-language: EN-US"><FONT face="Times New Roman"><FONT face=Verdana>Frame buffer 
+emulation must be disabled in multiplayer mode to avoid flickering. Most of the 
+special effects used will not work without frame buffer emulation, but it's 
+not&nbsp;that important for multiplayer.</FONT></FONT></SPAN></P><P><SPAN lang=EN-US style="mso-ansi-language: EN-US"><FONT face="Times New Roman"><FONT face=Verdana>For settings for other games check the <A href="Glide64 compatibility list.html">Compatibility List</A>.</FONT></P><P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><BR></P></FONT></SPAN>
+</BODY></HTML>
\ No newline at end of file
diff --git a/source/gles2glide64/src/Glide64/Help/Glide64 compatibility list.html b/source/gles2glide64/src/Glide64/Help/Glide64 compatibility list.html
new file mode 100644 (file)
index 0000000..c06ffe6
--- /dev/null
@@ -0,0 +1,6153 @@
+<html xmlns:o="urn:schemas-microsoft-com:office:office"
+xmlns:x="urn:schemas-microsoft-com:office:excel"
+xmlns="http://www.w3.org/TR/REC-html40">
+
+<head>
+<meta http-equiv=Content-Type content="text/html; charset=iso-8859-1">
+<meta name=ProgId content=Excel.Sheet>
+<meta name=Generator content="Microsoft Excel 11">
+<link rel=File-List href="Glide64%20compatibility%20list_fichiers/filelist.xml">
+<link rel=Edit-Time-Data
+href="Glide64%20compatibility%20list_fichiers/editdata.mso">
+<link rel=OLE-Object-Data
+href="Glide64%20compatibility%20list_fichiers/oledata.mso">
+<title>.::Glide64 compatibility list::.</title>
+<!--[if gte mso 9]><xml>
+ <o:DocumentProperties>
+  <o:LastAuthor>Olivier</o:LastAuthor>
+  <o:Created>2008-04-01T20:59:16Z</o:Created>
+  <o:LastSaved>2009-07-22T17:34:08Z</o:LastSaved>
+  <o:Version>11.5606</o:Version>
+ </o:DocumentProperties>
+</xml><![endif]-->
+<style>
+<!--@page SECTION1
+       {margin-bottom:72pt;
+       margin-left:90pt;
+       margin-right:90pt;
+       margin-top:72pt;
+       mso-footer-margin:35.4pt;
+       mso-header-margin:35.4pt;
+       mso-paper-source-first-page:0;
+       mso-paper-source-other-pages:0;
+       size:612pt 792pt;}
+table
+       {mso-displayed-decimal-separator:"\,";
+       mso-displayed-thousand-separator:" ";}
+@page
+       {margin:.98in .79in .98in .79in;
+       mso-header-margin:.49in;
+       mso-footer-margin:.49in;}
+.font10
+       {color:windowtext;
+       font-size:12.0pt;
+       font-weight:400;
+       font-style:normal;
+       text-decoration:none;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;}
+.font11
+       {color:black;
+       font-size:12.0pt;
+       font-weight:400;
+       font-style:normal;
+       text-decoration:none;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;}
+tr
+       {mso-height-source:auto;}
+col
+       {mso-width-source:auto;}
+br
+       {mso-data-placement:same-cell;}
+.style0
+       {mso-number-format:General;
+       text-align:general;
+       vertical-align:bottom;
+       white-space:nowrap;
+       mso-rotate:0;
+       mso-background-source:auto;
+       mso-pattern:auto;
+       color:windowtext;
+       font-size:10.0pt;
+       font-weight:400;
+       font-style:normal;
+       text-decoration:none;
+       font-family:Arial;
+       mso-generic-font-family:auto;
+       mso-font-charset:0;
+       border:none;
+       mso-protection:locked visible;
+       mso-style-name:Normal;
+       mso-style-id:0;}
+td
+       {mso-style-parent:style0;
+       padding-top:1px;
+       padding-right:1px;
+       padding-left:1px;
+       mso-ignore:padding;
+       color:windowtext;
+       font-size:10.0pt;
+       font-weight:400;
+       font-style:normal;
+       text-decoration:none;
+       font-family:Arial;
+       mso-generic-font-family:auto;
+       mso-font-charset:0;
+       mso-number-format:General;
+       text-align:general;
+       vertical-align:bottom;
+       border:none;
+       mso-background-source:auto;
+       mso-pattern:auto;
+       mso-protection:locked visible;
+       white-space:nowrap;
+       mso-rotate:0;}
+.xl24
+       {mso-style-parent:style0;
+       background:white;
+       mso-pattern:auto none;}
+.xl25
+       {mso-style-parent:style0;
+       color:#993300;
+       font-size:12.0pt;
+       font-weight:700;
+       text-decoration:underline;
+       text-underline-style:single;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       border:.5pt solid black;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+.xl26
+       {mso-style-parent:style0;
+       color:#993300;
+       font-size:12.0pt;
+       font-weight:700;
+       text-decoration:underline;
+       text-underline-style:single;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       border-top:.5pt solid black;
+       border-right:.5pt solid black;
+       border-bottom:.5pt solid black;
+       border-left:none;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+.xl27
+       {mso-style-parent:style0;
+       color:green;
+       font-size:12.0pt;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:.5pt solid black;
+       border-bottom:.5pt solid black;
+       border-left:.5pt solid black;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+.xl28
+       {mso-style-parent:style0;
+       color:green;
+       font-size:12.0pt;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:.5pt solid black;
+       border-bottom:.5pt solid black;
+       border-left:none;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+.xl29
+       {mso-style-parent:style0;
+       color:#FF6600;
+       font-size:12.0pt;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:.5pt solid black;
+       border-bottom:.5pt solid black;
+       border-left:.5pt solid black;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+.xl30
+       {mso-style-parent:style0;
+       color:#FF6600;
+       font-size:12.0pt;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:.5pt solid black;
+       border-bottom:.5pt solid black;
+       border-left:none;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+.xl31
+       {mso-style-parent:style0;
+       color:green;
+       font-size:12.0pt;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:.5pt solid black;
+       border-bottom:none;
+       border-left:.5pt solid black;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+.xl32
+       {mso-style-parent:style0;
+       color:green;
+       font-size:12.0pt;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:.5pt solid black;
+       border-bottom:none;
+       border-left:none;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+.xl33
+       {mso-style-parent:style0;
+       color:green;
+       font-size:12.0pt;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       border:.5pt solid black;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+.xl34
+       {mso-style-parent:style0;
+       color:green;
+       font-size:12.0pt;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       border-top:.5pt solid black;
+       border-right:.5pt solid black;
+       border-bottom:.5pt solid black;
+       border-left:none;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+.xl35
+       {mso-style-parent:style0;
+       color:red;
+       font-size:12.0pt;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:.5pt solid black;
+       border-bottom:.5pt solid black;
+       border-left:.5pt solid black;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+.xl36
+       {mso-style-parent:style0;
+       color:red;
+       font-size:12.0pt;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:.5pt solid black;
+       border-bottom:.5pt solid black;
+       border-left:none;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+.xl37
+       {mso-style-parent:style0;
+       font-size:12.0pt;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       background:white;
+       mso-pattern:auto none;}
+.xl38
+       {mso-style-parent:style0;
+       font-size:12.0pt;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:.5pt solid black;
+       border-bottom:.5pt solid black;
+       border-left:.5pt solid black;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+.xl39
+       {mso-style-parent:style0;
+       font-size:12.0pt;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:.5pt solid black;
+       border-bottom:.5pt solid black;
+       border-left:none;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+.xl40
+       {mso-style-parent:style0;
+       color:black;
+       font-size:12.0pt;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:.5pt solid black;
+       border-bottom:.5pt solid black;
+       border-left:.5pt solid black;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+.xl41
+       {mso-style-parent:style0;
+       color:black;
+       font-size:12.0pt;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:.5pt solid black;
+       border-bottom:.5pt solid black;
+       border-left:none;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+.xl42
+       {mso-style-parent:style0;
+       color:blue;
+       font-size:12.0pt;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:.5pt solid black;
+       border-bottom:none;
+       border-left:.5pt solid black;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+.xl43
+       {mso-style-parent:style0;
+       color:blue;
+       font-size:12.0pt;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:.5pt solid black;
+       border-bottom:none;
+       border-left:none;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+.xl44
+       {mso-style-parent:style0;
+       color:black;
+       font-size:12.0pt;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       border:.5pt solid black;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+.xl45
+       {mso-style-parent:style0;
+       color:black;
+       font-size:12.0pt;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       border-top:.5pt solid black;
+       border-right:.5pt solid black;
+       border-bottom:.5pt solid black;
+       border-left:none;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+.xl46
+       {mso-style-parent:style0;
+       color:blue;
+       font-size:12.0pt;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:.5pt solid black;
+       border-bottom:.5pt solid black;
+       border-left:.5pt solid black;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+.xl47
+       {mso-style-parent:style0;
+       color:blue;
+       font-size:12.0pt;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       border-top:none;
+       border-right:.5pt solid black;
+       border-bottom:.5pt solid black;
+       border-left:none;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+.xl48
+       {mso-style-parent:style0;
+       color:green;
+       font-size:12.0pt;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       vertical-align:top;
+       border-top:none;
+       border-right:.5pt solid black;
+       border-bottom:.5pt solid black;
+       border-left:none;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+.xl49
+       {mso-style-parent:style0;
+       color:red;
+       font-size:26.0pt;
+       font-weight:700;
+       text-decoration:underline;
+       text-underline-style:single;
+       font-family:"Times New Roman", serif;
+       mso-font-charset:0;
+       text-align:center;
+       background:white;
+       mso-pattern:auto none;
+       white-space:normal;}
+-->
+</style>
+<!--[if gte mso 9]><xml>
+ <x:ExcelWorkbook>
+  <x:ExcelWorksheets>
+   <x:ExcelWorksheet>
+    <x:Name>Glide64 compatibility list</x:Name>
+    <x:WorksheetOptions>
+     <x:DefaultColWidth>10</x:DefaultColWidth>
+     <x:Print>
+      <x:ValidPrinterInfo/>
+      <x:PaperSizeIndex>9</x:PaperSizeIndex>
+      <x:HorizontalResolution>600</x:HorizontalResolution>
+      <x:VerticalResolution>600</x:VerticalResolution>
+     </x:Print>
+     <x:Selected/>
+     <x:DoNotDisplayGridlines/>
+     <x:LeftColumnVisible>1</x:LeftColumnVisible>
+     <x:Panes>
+      <x:Pane>
+       <x:Number>3</x:Number>
+       <x:RangeSelection>$A$1:$E$1</x:RangeSelection>
+      </x:Pane>
+     </x:Panes>
+     <x:ProtectContents>False</x:ProtectContents>
+     <x:ProtectObjects>False</x:ProtectObjects>
+     <x:ProtectScenarios>False</x:ProtectScenarios>
+    </x:WorksheetOptions>
+   </x:ExcelWorksheet>
+  </x:ExcelWorksheets>
+  <x:WindowHeight>9375</x:WindowHeight>
+  <x:WindowWidth>15195</x:WindowWidth>
+  <x:WindowTopX>0</x:WindowTopX>
+  <x:WindowTopY>45</x:WindowTopY>
+  <x:ProtectStructure>False</x:ProtectStructure>
+  <x:ProtectWindows>False</x:ProtectWindows>
+ </x:ExcelWorkbook>
+</xml><![endif]--><u1:SmartTagType namespaceuri="urn:schemas-microsoft-com:office:smarttags" name="PlaceType"/><u1:SmartTagType namespaceuri="urn:schemas-microsoft-com:office:smarttags" name="PlaceName"/><u1:SmartTagType namespaceuri="urn:schemas-microsoft-com:office:smarttags" name="PersonName"/><u1:SmartTagType namespaceuri="urn:schemas-microsoft-com:office:smarttags" name="country-region"/><u1:SmartTagType namespaceuri="urn:schemas-microsoft-com:office:smarttags" name="State"/><u1:SmartTagType namespaceuri="urn:schemas-microsoft-com:office:smarttags" name="City"/><u1:SmartTagType namespaceuri="urn:schemas-microsoft-com:office:smarttags" name="place"/>
+</head>
+
+<body link="#003366" vlink=purple class=xl24 lang=EN-GB style='tab-interval:
+36pt'>
+
+<table x:str border=0 cellpadding=0 cellspacing=0 width=973 style='border-collapse:
+ collapse;table-layout:fixed;width:729pt'>
+ <col class=xl24 width=183 style='mso-width-source:userset;mso-width-alt:6692;
+ width:137pt'>
+ <col class=xl24 width=107 style='mso-width-source:userset;mso-width-alt:3913;
+ width:80pt'>
+ <col class=xl24 width=87 style='mso-width-source:userset;mso-width-alt:3181;
+ width:65pt'>
+ <col class=xl24 width=76 style='mso-width-source:userset;mso-width-alt:2779;
+ width:57pt'>
+ <col class=xl24 width=520 style='mso-width-source:userset;mso-width-alt:19017;
+ width:390pt'>
+ <tr height=44 style='mso-height-source:userset;height:33.0pt'>
+  <td colspan=5 height=44 class=xl49 width=973 style='height:33.0pt;width:729pt'
+  x:str="Compatibility List ">Compatibility List<span
+  style='mso-spacerun:yes'> </span></td>
+ </tr>
+ <tr height=44 style='mso-height-source:userset;height:33.0pt'>
+  <td colspan=5 height=44 class=xl49 width=973 style='height:33.0pt;width:729pt'>for
+  Glide64 1.0<span lang=EN-US style='mso-ansi-language:EN-US'><u1:p></u1:p></span></td>
+ </tr>
+ <tr height=17 style='height:12.75pt'>
+  <td height=17 colspan=5 class=xl24 style='height:12.75pt;mso-ignore:colspan'>&nbsp;</td>
+ </tr>
+ <tr height=42 style='height:31.5pt'>
+  <td height=42 class=xl25 width=183 style='height:31.5pt;width:137pt'
+  x:str="Game Name: "><span lang=NL style='mso-ansi-language:NL'>Game
+  Name:<span style='mso-spacerun:yes'> </span></span></td>
+  <td class=xl26 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=NL style='mso-ansi-language:NL'>RSP Microcode</span></td>
+  <td class=xl26 width=87 style='width:65pt;padding-bottom:0cm;padding-top:
+  0cm'>Playability Level</td>
+  <td class=xl26 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Relative speed</td>
+  <td class=xl26 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Comments</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:1'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>007 - The World is Not Enough</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:2'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>1080 Snowboarding</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; option to see correct TV
+  monitors (slow)</td>
+ </tr>
+ <tr height=21 style='height:15.75pt'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt'>40
+  Winks</td>
+  <td class=xl28 width=107 style='width:80pt'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt'>Normal</td>
+  <td class=xl28 width=520 style='width:390pt'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:3'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>64 Oozumou</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:4'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>64 Oozumou 2</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=43 style='mso-height-source:userset;height:32.25pt;mso-yfti-irow:
+  5'>
+  <td height=43 class=xl27 width=183 style='height:32.25pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>64 Trump Collection - Alice no Wakuwaku
+  Trump World<st1:place u2:st="on"><st1:City u2:st="on"></st1:City></st1:place></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:6'>
+  <td height=42 class=xl29 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><span lang=NL style='mso-ansi-language:
+  NL'>64 de Hakken!! Tamagotchi Minna de Tamagotchi World</span></td>
+  <td class=xl30 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm' x:str="F3DTEX/A ">F3DTEX/A<span style='mso-spacerun:yes'> </span></td>
+  <td class=xl30 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>3</td>
+  <td class=xl30 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl30 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Major gfx errors</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:7'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>AI Shogi 3</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use 1964</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:8'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Aerofighter's Assault</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:9'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>AeroGauge</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:10'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Aidyn Chronicles - The First Mage</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:11'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm' x:str="Airboarder 64 ">Airboarder 64<span
+  style='mso-spacerun:yes'> </span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='mso-height-source:userset;height:31.5pt;mso-yfti-irow:
+  12'>
+  <td height=42 class=xl31 width=183 style='height:31.5pt;width:137pt'>Akumajou
+  Dracula Makushiroku - Real Action Adventure</td>
+  <td class=xl32 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl32 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl32 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl32 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; option to see correct menu
+  (slow)</td>
+ </tr>
+ <tr height=63 style='height:47.25pt;mso-yfti-irow:13'>
+  <td height=63 class=xl33 width=183 style='height:47.25pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Akumajou Dracula Makushiroku-Legend of
+  Cornell</td>
+  <td class=xl34 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl34 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl34 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl34 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Enable hi-res mode for correct menus</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:14'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>All Star Tennis '99</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:15'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>All-Star Baseball 99</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Get frame buffer info&quot; option with Mupen or
+  use &quot;Read every frame&quot; option to see correct TV monitors (slow).
+  Minor gfx errors</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:16'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>All-Star Baseball 2000</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use Nemu 0.8. Use &quot;Read every frame&quot; option to see
+  correct TV monitors (slow)</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:17'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>All-Star Baseball 2001</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use Nemu 0.8. Use &quot;Read every frame&quot; option to see
+  correct TV monitors (slow)</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:18'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Armorines - Project S.W.A.R.M.</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:19'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Army Men - Air Combat</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:20'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Army Men - Sarge's Heroes</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:21'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Army Men - Sarge's Heroes 2</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:22'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Asteroids Hyper 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:23'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Automobili Lamborghini</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Minor gfx errors</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:24'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><st1:City u2:st="on"><st1:place u2:st="on">Baku
+  Bomberman</st1:place></st1:City></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Get frame buffer info&quot; option with Mupen or
+  use &quot;Read every frame&quot; option to see intro correctly (slow)</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:25'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><st1:City u2:st="on"><st1:place u2:st="on">Baku
+  Bomberman 2</st1:place></st1:City></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:26'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Bakuretsu Muteki Bangaioh</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:27'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Bakushou Jinsei 64 - Mezase! (Game of
+  Life)</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; option to have correct gfx
+  in game</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:28'>
+  <td height=42 class=xl31 width=183 style='height:31.5pt;width:137pt'>Banjo to
+  Kazooie no Dai Bouken</td>
+  <td class=xl32 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl32 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl32 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl32 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; option (slow) or &quot;Get
+  frame buffer info&quot; option with Mupen to see puzzle effect &nbsp;&nbsp;</td>
+ </tr>
+ <tr height=21 style='mso-height-source:userset;height:15.75pt;mso-yfti-irow:
+  29'>
+  <td height=21 class=xl33 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Banjo to Kazooie no Dai Bouken 2</td>
+  <td class=xl34 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl34 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl34 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl34 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:30'>
+  <td height=42 class=xl31 width=183 style='height:31.5pt;width:137pt'>Banjo-Kazooie</td>
+  <td class=xl32 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl32 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl32 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl32 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; option (slow) or &quot;Get
+  frame buffer info&quot; option to see puzzle effect with
+  Mupen&nbsp;&nbsp;&nbsp;</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:31'>
+  <td height=21 class=xl33 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Banjo-Tooie</td>
+  <td class=xl34 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl34 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl34 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl34 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:32'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Bass Hunter 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:33'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Bass Rush - ECOGEAR PowerWorm
+  Championship</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:34'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Bass Tsuri No.1 - Shigesato Itoi's Bass
+  Fishing</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:35'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Bassmasters 2000</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:36'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Batman Beyond - Return of the Joker</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:37'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>BattleTanx</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:38'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>BattleTanx - Global Assault</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:39'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Battlezone - Rise of the Black Dogs<u1:p></u1:p></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX<u1:p></u1:p></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5<u1:p></u1:p></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Normal<u1:p></u1:p></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible<u1:p></u1:p></td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:40'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Beetle Adventure Racing</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:41'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Big Mountain 2000</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:42'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Bio F.R.E.A.K.S.</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:43'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Bio Hazard 2</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:44'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Blast Corps</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use PJ64. Minor gfx errors</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:45'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Blast Dozer</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use PJ64. Minor gfx errors</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:46'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Blues Brothers 2000</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:47'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Body Harvest</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; option (slow) or &quot;Get
+  frame buffer info&quot; with Mupen to have correct menu</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:48'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Bokujo Monogatari 2</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:49'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Bomberman 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Get frame buffer info&quot; option with Mupen or
+  use &quot;Read every frame&quot; option to see intro correctly (slow)</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:50'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Bomberman64 - The Second Attack</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:51'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Bomberman Hero</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm' x:str="Compatible. ">Compatible.<span style='mso-spacerun:yes'> </span></td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:52'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Bottom of the 9th</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; option (slow) to see
+  correct intro</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:53'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><st1:place u2:st="on"><st1:City u2:st="on">Brunswick
+  Circuit Pro Bowling</st1:City></st1:place><u1:p></u1:p></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX<u1:p></u1:p></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5<u1:p></u1:p></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast<u1:p></u1:p></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible<u1:p></u1:p></td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:54'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Buck Bumble</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:55'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Bug's Life, A</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:56'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Bust-A-Move '99</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:57'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Bust-A-Move 2 - Arcade Edition<st1:place u2:st="on"></st1:place></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:58'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Bust-A-Move 3 DX</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:59'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><st1:State u2:st="on"><st1:place u2:st="on">California
+  Speed</st1:place></st1:State></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:60'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Carmageddon 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:61'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt'>Castlevania</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; option to see correct menu
+  (slow)</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:62'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Castlevania - Legacy of Darkness</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Enable hi-res mode for correct menus</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:63'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Centre Court Tennis</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:64'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Chameleon Twist</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:65'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Chameleon Twist 2</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:66'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Charlie Blast's Territory</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:67'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Chopper Attack</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:68'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Choro Q 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:69'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Choro Q 64 II</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; option (slow) or &quot;Get
+  frame buffer info&quot; option with Mupen to see correct menu</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:70'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Chou Kuukan Night Pro Yakyuu King</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:71'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Chou Kuukan Night Pro Yakyuu King 2</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:72'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Chou Snobow Kids</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Compatible</span></td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:73'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>City-Tour GP - Zennihon GT Senshuken</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:74'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Clay Fighter - Sculptor's Cut</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:75'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Clay Fighter 63 1-3</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:76'>
+  <td height=21 class=xl29 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Command &amp; Conquer</td>
+  <td class=xl30 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl30 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>3</span></td>
+  <td class=xl30 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl30 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Not playable</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:77'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Conker's Bad Fur Day</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEXGB2.08</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; option (slow) to get black
+  and white effect during &#8220;It&#8217;s war&#8221; cut scene and Buga
+  pixellisation effect</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:78'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Cruis'n Exotica</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:79'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Cruis'n USA<st1:country-region u2:st="on"><st1:place u2:st="on"></st1:place></st1:country-region></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:80'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Cruis'n World</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:81'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Custom Robo</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:82'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Custom Robo V2</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:83'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm' x:str="CyberTiger ">CyberTiger<span
+  style='mso-spacerun:yes'> </span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:84'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Dance Dance Revolution - Disney Dancing
+  Museum</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:85'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Dark Rift</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>TURBO3D</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt'>Normal</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:86'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Deadly Arts</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:87'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Défi au Tetris Magique</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>S2DEX.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:88'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Densha de GO! 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use 1964</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:89'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><st1:City u2:st="on"><st1:place u2:st="on">Derby
+  Stallion</st1:place></st1:City></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use Nemu 0.8</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:90'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Destruction Derby 64<st1:City u2:st="on"><st1:place u2:st="on"></st1:place></st1:City></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:91'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Dezaemon 3D</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:92'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Diddy Kong Racing</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=NL style='mso-ansi-language:NL'>RSP SW DKR</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:93'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Disney's Donald Duck - Goin' Quackers</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; option to see correct
+  transition effects in menu</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:94'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Disney's Tarzan</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:place u2:st="on"><st1:City u2:st="on">Normal</st1:City></st1:place></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use PJ64</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:95'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Donald Duck - Quack Attack</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; option to see correct
+  transition effect in menu</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:96'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Donkey Kong 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use PJ64</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:97'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Doom 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Compatible</span></td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:98'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><span lang=DE style='mso-ansi-language:
+  DE'>Doraemon - Mittsu no Seireiseki</span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:99'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Doraemon 2 - Hikari no Shinden</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Compatible</span></td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:100'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><span lang=DE style='mso-ansi-language:
+  DE'>Doraemon 3 - Nobi Dai no Machi SOS!</span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm' x:str="Compatible. Use 1964 "><span lang=DE style='mso-ansi-language:
+  DE'>Compatible. Use 1964<span style='mso-spacerun:yes'> </span></span></td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:101'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><span lang=DE style='mso-ansi-language:
+  DE'>Doubutsu no Mori</span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Normal</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:102'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Dr. Mario 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:103'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Dual Heroes</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:104'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Duck Dodgers Starring Daffy Duck</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Compatible</span></td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:105'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><span lang=DE style='mso-ansi-language:
+  DE'>Duke Nukem - ZER0 H0UR</span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:106'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Duke Nukem 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSPSW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Minor gfx errors</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:107'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>ECW Hardcore Revolution</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:108'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Earthworm Jim 3D</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:109'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Eikou no Saint Andrew</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>2</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible, Use &quot;Read every frame&quot; option (slow) or &quot;Get
+  frame buffer info&quot; with Mupen to have correct background in game</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:110'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Elmo's Letter Adventure</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:111'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Elmo's Number Journey</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:112'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Eltale Monsters</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:113'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Excitebike 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:114'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Extreme-G</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm' x:str="Compatible. Minor gfx errors ">Compatible. Minor gfx errors<span
+  style='mso-spacerun:yes'> </span></td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:115'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Extreme-G XG2</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:116'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>F-1 Pole Position 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; option (slow) or &quot;Get
+  frame buffer info&quot; with Mupen to have correct menu</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:117'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>F-1 World Grand Prix</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:118'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>F-1 World Grand Prix II</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:119'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>F-Zero X</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:120'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>F1 Racing Championship</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use Mupen</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:121'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>FIFA - Road to World Cup 98</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:122'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>FIFA 99</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:123'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>FIFA Soccer 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use 1964</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:124'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Famista 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; option (slow) or &quot;Get
+  frame buffer info&quot; with Mupen to have ground in game</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:125'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Fighter Destiny 2</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:126'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Fighter's Destiny</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:127'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Fighting Cup</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:128'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Fighting Force 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:129'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Fire Electric Pen</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:130'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Flying Dragon</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Minor gfx errors</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:131'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Forsaken 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt'>Frogger
+  2 (Alpha)</td>
+  <td class=xl28 width=107 style='width:80pt'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:132'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>FoxSportsCollege Hoops &#8216;99</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:133'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Fushigi no Dungeon - Fuurai no Shiren 2</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'
+  x:str="Compatible. Use &quot;Read every frame&quot; option (slow) or &quot;Get frame buffer info&quot; with Mupen to have backgrounds in menus ">Compatible.
+  Use &quot;Read every frame&quot; option (slow) or &quot;Get frame buffer
+  info&quot; with Mupen to have backgrounds in menus<span
+  style='mso-spacerun:yes'> </span></td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:134'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>G.A.S.P! Fighter's NEXTream</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use (J) version or use Mupen</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:135'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>GT 64 - Championship Edition</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=63 style='height:47.25pt;mso-yfti-irow:136'>
+  <td height=63 class=xl27 width=183 style='height:47.25pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><span lang=NL style='mso-ansi-language:
+  NL'>Ganbare Goemon - Derudero Douchuu Obake Tenkomori</span><span lang=DE
+  style='mso-ansi-language:DE'><u1:p></u1:p></span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=NL style='mso-ansi-language:NL'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=NL style='mso-ansi-language:NL'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=NL style='mso-ansi-language:NL'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:137'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Ganbare Goemon - Mononoke Sugoroku</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=63 style='height:47.25pt;mso-yfti-irow:138'>
+  <td height=63 class=xl27 width=183 style='height:47.25pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Ganbare Goemon - Neo Momoyama Bakufu no
+  Odori</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:139'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Ganbare Nippon Olympics 2000</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:140'>
+  <td height=21 class=xl35 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Gauntlet Legends</td>
+  <td class=xl36 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl36 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>2</td>
+  <td class=xl36 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl36 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Missing gfx. Flickerings. Use PJ64</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:141'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Getter Love !! Cho Renai Party Game</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:142'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Gex 3 - Deep Cover Gecko</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:143'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Gex 64 - Enter the Gecko</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:144'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Glover</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible (For (E) version use Mupen)</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:145'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Goemon's Great Adventure</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:146'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Golden Nugget 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use 1964 or Mupen</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:147'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>GoldenEye 007</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0G</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:148'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>HVS Adventure Racing</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use PJ64 Audio Fix Edition</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:149'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Hamster Monogatari 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>S2DEX.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:150'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Hanafuda 64 - Tenshi no Yakusoku</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use 1964</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:151'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Harukanaru Augusta Masters 98</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:152'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Harvest Moon 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:153'>
+  <td height=21 class=xl29 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Heiwa Pachinko World 64</td>
+  <td class=xl30 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl30 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>3</td>
+  <td class=xl30 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl30 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Gfx errors</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:154'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Hercules - The Legendary Journeys</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Minor gfx errors</td>
+ </tr>
+ <tr height=22 style='mso-height-source:userset;height:16.5pt;mso-yfti-irow:
+  155'>
+  <td height=22 class=xl27 width=183 style='height:16.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Hexen</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; option (slow) to see texts
+  at objectives screen</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:156'>
+  <td height=21 class=xl29 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Hey You, Pikachu!</td>
+  <td class=xl30 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl30 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>3</td>
+  <td class=xl30 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl30 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Gfx errors (needs voice pak)</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:157'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Hiryuu no Ken Twin</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Minor gfx errors</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:158'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Holy Magic Century</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:159'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Hoshi no Kirby 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use Mupen for correct status bar</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:160'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Hot Wheels Turbo Racing</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:161'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Human Grand Prix - New Generation</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; option (slow) or &quot;Get
+  frame buffer info&quot; with Mupen to have correct menu</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:162'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Hybrid Heaven</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:163'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Hydro Thunder</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use PJ64</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:164'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Ide Yosuke no Mahjong Juku</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm' x:str="Normal "><st1:City u2:st="on"><st1:place u2:st="on">Normal<span
+  style='mso-spacerun:yes'> </span></st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use Nemu 0.8 (disable audio HLE)</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:165'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Iggy's Reckin' Balls</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:166'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Iggy-kun no Bura Bura Poyon</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:167'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>In-Fisherman Bass Hunter 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:168'>
+  <td height=42 class=xl38 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><st1:place u2:st="on"><st1:State u2:st="on">Indiana
+  Jones and the Infernal Machine</st1:State></st1:place></td>
+  <td class=xl39 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>?</td>
+  <td class=xl39 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>0</td>
+  <td class=xl39 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>?</td>
+  <td class=xl39 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Unsupported.<font class="font11"> Microcode not implemented</font></td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:169'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Indy Racing 2000</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:170'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>International Superstar Soccer '98</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'
+  x:str="Compatible. Use &#8220;Read every frame&#8221; option to see correct effects after scoring a goal  ">Compatible.
+  Use &#8220;Read every frame&#8221; option to see correct effects after
+  scoring a goal<span style='mso-spacerun:yes'>  </span></td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:171'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>International Superstar Soccer 2000</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'
+  x:str="Compatible. Use &#8220;Read every frame&#8221; option to see correct effects after scoring a goal  ">Compatible.
+  Use &#8220;Read every frame&#8221; option to see correct effects after
+  scoring a goal<span style='mso-spacerun:yes'>  </span></td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:172'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>International Superstar Soccer 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Minor gfx errors</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:173'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>International Track &amp;&nbsp; Field
+  2000</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:174'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>International Track &amp; Field Summer
+  Games</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:175'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>J. League Dynamite Soccer 64<u1:p></u1:p></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX<u1:p></u1:p></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5<u1:p></u1:p></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City><u1:p></u1:p></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible<u1:p></u1:p></td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:176'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>J. League Eleven Beat 1997</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:177'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>J. League Live 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:178'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>J. League Tactics Soccer</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:179'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Jangou Simulation Mahjong Do 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:180'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Jeopardy!</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:181'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Jeremy McGrath Supercross 2000</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:182'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Jet Force Gemini</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW RARE4<st1:place u2:st="on"></st1:place></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:183'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Jikkyou G1 Stable</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:184'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Jikkyou J. League 1999 - Perfect Striker
+  2</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'
+  x:str="Compatible. Use &#8220;Read every frame&#8221; option to see correct effects after scoring a goal  ">Compatible.
+  Use &#8220;Read every frame&#8221; option to see correct effects after
+  scoring a goal<span style='mso-spacerun:yes'>  </span></td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:185'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Jikkyou J. League Perfect Striker</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'
+  x:str="Compatible. Use &#8220;Read every frame&#8221; option to see correct effects after scoring a goal  ">Compatible.
+  Use &#8220;Read every frame&#8221; option to see correct effects after
+  scoring a goal<span style='mso-spacerun:yes'>  </span></td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:186'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Jikkyou Powerful Pro Yakyuu - Basic Han
+  2001</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:187'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Jikkyou Powerful Pro Yakyuu 2000</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:188'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Jikkyou Powerful Pro Yakyuu 4</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:189'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Jikkyou Powerful Pro Yakyuu 5</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:190'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Jikkyou Powerful Pro Yakyuu 6</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:191'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Jikkyou World Cup France '98</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'
+  x:str="Compatible. Use &#8220;Read every frame&#8221; option to see correct effects after scoring a goal  ">Compatible.
+  Use &#8220;Read every frame&#8221; option to see correct effects after
+  scoring a goal<span style='mso-spacerun:yes'>  </span></td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:192'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Jikkyou World Soccer 3</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:193'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Jinsei Game 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:194'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>John Romero's Daikatana</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:195'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Kakutou Denshou - F-Cup Maniax</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:196'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><span lang=DE style='mso-ansi-language:
+  DE'>Ken Griffey Jr.'s Slugfest</span><span lang=DE style='mso-ansi-language:
+  DE'><u1:p></u1:p></span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:197'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Killer Instinct Gold</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='mso-height-source:userset;height:15.75pt;mso-yfti-irow:
+  198'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>King Hill 64 - Extreme Snowboarding</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Minor gfx errors.</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:199'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Kiratto Kaiketsu! 64 Tanteidan</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:200'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Kirby 64 - The Crystal Shards<st1:City u2:st="on"><st1:place u2:st="on"></st1:place></st1:City></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use Mupen for correct status bar</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:201'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Knife Edge - Nose Gunner</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:202'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Knockout Kings 2000</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use 1964. Minor gfx errors</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:203'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><st1:place u2:st="on"><st1:City u2:st="on">Kobe
+  Bryant NBA Courtside</st1:City></st1:place></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:204'>
+  <td height=21 class=xl35 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Kuiki-Uhabi-Suigo</td>
+  <td class=xl36 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl36 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>2</td>
+  <td class=xl36 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl36 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Gfx errors</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:205'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>LEGO Racers</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Depends</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:206'>
+  <td height=21 class=xl40 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Last Legion UX</td>
+  <td class=xl39 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>?</td>
+  <td class=xl39 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>0</td>
+  <td class=xl39 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>?</td>
+  <td class=xl41 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Unsupported<font class="font10">.</font><font class="font11"> Microcode
+  not implemented</font></td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:207'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Legend of Zelda, The - Ocarina of Time</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX 2.06H</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>*Mostly* Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:208'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Legend of Zelda 2, The - Majora's Mask</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='mso-height-source:userset;height:15.75pt;mso-yfti-irow:
+  209'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Legend of Zelda, The - Ocarina of Time -
+  Master Quest</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX 2.06H</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>*Mostly* Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:210'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Les Razmoket - La Chasse aux Trésors<st1:PersonName ProductID="La Chasse" u2:st="on"></st1:PersonName></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:211'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Let's Smash Tennis</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:212'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Lode Runner 3-D</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:213'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Looney Tunes - Duck Dodgers</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:214'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Lylat Wars</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:215'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>MRC - Multi Racing Championship</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:216'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Mace - The Dark Age</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible.</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:217'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Madden Football 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:218'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Madden NFL 2000</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:219'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Madden NFL 2001</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:220'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Madden NFL 2002</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:221'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Madden NFL 99</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:222'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Magical Tetris Challenge</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:223'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Mahjong 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:224'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Mahjong Hourouki Classic</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:225'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Mahjong Master</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Minors gfx errors</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:226'>
+  <td height=42 class=xl29 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Major League Baseball Featuring Ken
+  Griffey Jr.</td>
+  <td class=xl30 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl30 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>3</td>
+  <td class=xl30 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl30 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Gfx errors</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:227'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Mario Golf</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:228'>
+  <td height=42 class=xl31 width=183 style='height:31.5pt;width:137pt'>Mario
+  Kart 64</td>
+  <td class=xl32 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl32 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl32 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl32 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &#8220;Read every frame&#8221; option (slow) or use
+  &quot;Get frame buffer info&quot; with Mupen to see correct billboards</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:229'>
+  <td height=21 class=xl33 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Mario Party</td>
+  <td class=xl34 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl34 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl34 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl34 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:230'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Mario Party 2</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:231'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Mario Party 3</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:232'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Mario Story</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:233'>
+  <td height=21 class=xl42 width=183 style='height:15.75pt;width:137pt'>Mario
+  Tennis</td>
+  <td class=xl43 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl43 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>4</td>
+  <td class=xl43 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Unstable</td>
+  <td class=xl43 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Various gfx errors.</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:234'>
+  <td height=21 class=xl44 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Mario No Photopie</td>
+  <td class=xl45 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>?</td>
+  <td class=xl45 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>0</td>
+  <td class=xl45 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>?</td>
+  <td class=xl45 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Unsupported</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:235'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Mega Man 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:236'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Mia Hamm Soccer</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>ZSortp 0.33</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt'><span lang=DE style='mso-ansi-language:
+  DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Minors gfx errors</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:237'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><span lang=NL style='mso-ansi-language:
+  NL'>Michael Owens WLS 2000</span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>ZSortp 0.33</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt'><span lang=DE style='mso-ansi-language:
+  DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Minors gfx errors</td>
+ </tr>
+ <tr height=21 style='mso-height-source:userset;height:15.75pt;mso-yfti-irow:
+  238'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Mickey no Racing Challenge USA<st1:place u2:st="on"><st1:country-region u2:st="on"></st1:country-region></st1:place></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW RARE4<st1:place u2:st="on"></st1:place></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='mso-height-source:userset;height:15.75pt;mso-yfti-irow:
+  239'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Mickey's Speedway USA<st1:City u2:st="on"></st1:City><st1:place u2:st="on"><st1:country-region u2:st="on"></st1:country-region></st1:place></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW RARE4<st1:place u2:st="on"></st1:place></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:240'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Micro Machines 64 Turbo</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:241'>
+  <td height=42 class=xl29 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Midway's Greatest Arcade Hits Volume 1<st1:place u2:st="on"></st1:place></td>
+  <td class=xl30 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl30 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>3</td>
+  <td class=xl30 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl30 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Only few games are fully playable</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:242'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Mike Piazza's Strike Zone</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:243'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><st1:place u2:st="on">Milo's Astro Lanes</st1:place></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:244'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Mischief Makers</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:245'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><st1:City u2:st="on"><st1:place u2:st="on">Mission
+  Impossible</st1:place></st1:City></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:246'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><st1:country-region u2:st="on"><st1:place u2:st="on">Monaco
+  Grand Prix</st1:place></st1:country-region></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use Mupen64</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:247'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><st1:country-region u2:st="on"><st1:place u2:st="on">Monaco
+  Grand Prix - Racing Simulation 2</st1:place></st1:country-region></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use 1964</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:248'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Monopoly</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:249'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Monster Truck Madness 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:250'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Morita Shougi 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:251'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Mortal Kombat 4</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Scene dependent</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:252'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Mortal Kombat Mythologies - Sub-Zero</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Compatible</span></td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:253'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><span lang=DE style='mso-ansi-language:
+  DE'>Mortal Kombat Trilogy</span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>RSP SW 0.2X</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Compatible</span></td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:254'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Ms. Pac-Man - Maze Madness</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Normal</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Compatible</span></td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:255'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'
+  x:str="Mystical Ninja 2 - Starring Goemon ">Mystical Ninja 2 - Starring
+  Goemon<span style='mso-spacerun:yes'> </span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:256'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Mystical Ninja - Starring Goemon</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:257'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NASCAR 99</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:258'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NASCAR 2000</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:259'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NBA Courtside 2 - Featuring Kobe Bryant<st1:place u2:st="on"><st1:City u2:st="on"></st1:City></st1:place></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:260'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NBA Hangtime</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:261'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NBA In the Zone '98</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:262'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NBA In the Zone '99</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:263'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NBA In the Zone 2</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:264'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NBA In the Zone 2000</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:265'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NBA Jam 2000</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:266'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NBA Jam 99</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:267'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NBA Live 2000</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:268'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NBA Live 99</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:269'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NBA Showtime - NBA on NBC</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use PJ64</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:270'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><span lang=DE style='mso-ansi-language:
+  DE'>NFL Blitz</span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:271'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NFL Blitz - Special Edition</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:272'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NFL Blitz 2000</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:273'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NFL Blitz 2001</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:274'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NFL Quarterback Club 2000</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use Nemu 0.8</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:275'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NFL Quarterback Club 2001</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use Nemu 0.8</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:276'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NFL Quarterback Club 98</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use Mupen</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:277'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NFL Quarterback Club 99</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use Nemu 0.8</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:278'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NHL 99</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:279'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NHL Blades of Steel '99</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:280'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NHL Breakaway 98</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:281'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NHL Breakaway 99</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:282'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>NHL Pro 99</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:283'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><st1:City u2:st="on"><st1:place u2:st="on">Nagano
+  Winter Olympics '98</st1:place></st1:City></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:284'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><st1:place u2:st="on"><st1:PlaceName u2:st="on">Namco
+  Museum 64</st1:PlaceName><st1:PlaceType u2:st="on"></st1:PlaceType></st1:place></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:285'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Neon Genesis Evangelion</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:286'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>New Tetris, The</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'
+  x:str="Compatible. Use Mupen&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ">Compatible.
+  Use
+  Mupen&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span
+  style='mso-spacerun:yes'> </span></td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:287'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Nightmare Creatures</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use PJ64</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:288'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Nintama Rantarou Gallery 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>S2DEX.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:289'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Nintendo All-Star! Dairantou Smash
+  Brothers</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:290'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Nuclear Strike 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:291'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Nushi Zuri 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &#8220;Read every frame&#8221; option (slow) or use
+  &quot;Get frame buffer info&quot; with Mupen to have backgrounds in game</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:292'>
+  <td height=42 class=xl35 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Nushi Zuri 64 - Shiokaze ni Notte</td>
+  <td class=xl36 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl36 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>2</td>
+  <td class=xl36 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl36 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Missing gfx in game</td>
+ </tr>
+ <tr height=21 style='height:15.75pt'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt'>O.D.T</td>
+  <td class=xl28 width=107 style='width:80pt'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt'>Normal</td>
+  <td class=xl28 width=520 style='width:390pt'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:293'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Off Road Challenge</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=63 style='height:47.25pt;mso-yfti-irow:294'>
+  <td height=63 class=xl27 width=183 style='height:47.25pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Ogre Battle 64 - Person of Lordly Caliber<st1:place u2:st="on"><st1:City u2:st="on"></st1:City></st1:place></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use PJ64 or 1964 0.8.5 (Win9X users must use 1964 0.8.5 or
+  Nemu 0.8, to get backgrounds). Use &quot;Read every frame&quot; option to see
+  screen transition effects (slow)</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:295'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Olympic Hockey Nagano '98</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:296'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Onegai Monster</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:297'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Operation WinBack</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible, but a gray square sometimes appear on the screen. Missing
+  sky</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:298'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>PD Ultraman Battle Collection 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:299'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>PGA European Tour</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Minor gfx errors</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:300'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Pachinko 365 Nichi</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>2</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:301'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Paper Mario</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Minor gfx errors</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:302'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Paperboy</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:303'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Parlor! Pro 64 Pachinko Jikki Simulation
+  Game</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>S2DEX.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:304'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Penny Racers</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=47 style='mso-height-source:userset;height:35.45pt;mso-yfti-irow:
+  305'>
+  <td height=47 class=xl27 width=183 style='height:35.45pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Perfect Dark</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW PD</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; (slow) or &quot;Get frame
+  buffer info&quot; with Mupen to get correct pause menu in game</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:306'>
+  <td height=21 class=xl29 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Pikachu Genki Dechu</td>
+  <td class=xl30 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl30 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>3</td>
+  <td class=xl30 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl30 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Gfx errors (needs voice pak)</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:307'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Pilot Wings<u1:p></u1:p></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX<u1:p></u1:p></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5<u1:p></u1:p></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast<u1:p></u1:p></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible<u1:p></u1:p></td>
+ </tr>
+ <tr class=xl24 height=21 style='mso-height-source:userset;height:15.75pt;
+  mso-yfti-irow:308'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt'>Pocket
+  Monsters Snap</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; option when selecting shots
+  for professor Oak</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:309'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Pokemon Puzzle League</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>S2DEX.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=22 style='mso-height-source:userset;height:16.5pt;mso-yfti-irow:
+  310'>
+  <td height=22 class=xl27 width=183 style='height:16.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Pokemon Snap</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; option when selecting shots
+  for professor Oak</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:311'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><span lang=DE style='mso-ansi-language:
+  DE'>Pokemon Stadium</span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:312'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><span lang=DE style='mso-ansi-language:
+  DE'>Pokemon Stadium 2</span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Normal</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:313'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Polaris SnoCross</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:314'>
+  <td height=21 class=xl28 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Power League Baseball 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>4</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:315'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Power Rangers - Lightspeed Rescue</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:316'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Powerpuff Girls, The - Chemical
+  X-traction<u1:p></u1:p></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX<u1:p></u1:p></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5<u1:p></u1:p></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City><u1:p></u1:p></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible<u1:p></u1:p></td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:317'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><span lang=DE style='mso-ansi-language:
+  DE'>Premier Manager 64</span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:318'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Pro Mahjong Kiwame 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:319'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Pro Majhong Tsuwamono 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>S2DEX.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:320'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Puyo Puyo 4 - Puyo Puyo Party</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>S2DEX.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:321'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Puyo Puyo Sun 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:322'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Puzzle Bobble 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:323'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Quake 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:324'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Quake II</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible, Use &quot;Read every frame&quot; (slow) or &quot;Get frame
+  buffer info&quot; with Mupen to get correct pause menu in game</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:325'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Quest 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:326'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>RR64 - Ridge Racer 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Pause menu doesn't work correctly with Voodoo 1-3</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:327'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>RTL World League Soccer 2000</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>ZSortp 0.33</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt'><span lang=DE style='mso-ansi-language:
+  DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Minor gfx errors</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:328'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Racing Simulation 2</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use 1964. Minor gfx errors</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:329'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Rakuga Kids</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:330'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Rally '99</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:331'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Rally Challenge 2000</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:332'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Rampage - World Tour</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:333'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Rampage 2 - Universal Tour</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:334'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Rat Attack</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:335'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Rayman 2 - The Great Escape</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; option to see correct
+  transition effects in game</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:336'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Razor Freestyle Scooter</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:337'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Re-Volt</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use PJ64</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:338'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Ready 2 Rumble Boxing</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:339'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Ready 2 Rumble Boxing Round 2</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:340'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Resident Evil 2</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:341'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm' x:str="Road Rash 64 ">Road Rash 64<span
+  style='mso-spacerun:yes'> </span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:342'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Roadsters</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt'>Robotech
+  - Crystal Dreams (Beta)</td>
+  <td class=xl28 width=107 style='width:80pt'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt'>Normal</td>
+  <td class=xl28 width=520 style='width:390pt'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:343'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Robot Ponkottsu 64 - Caramel of the 7
+  Seas</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:344'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Robotron 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:345'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Rocket - Robot on Wheels</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:346'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Rockman Dash</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:347'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Rugrats - Scavenger Hunt</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:348'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Rugrats - Treasure Hunt</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:349'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Rugrats in Paris - The Movie<st1:place u2:st="on"><st1:City u2:st="on"></st1:City></st1:place></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Compatible</span></td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:350'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm' x:str="Rush 2 - Extreme Racing USA "><span
+  lang=DE style='mso-ansi-language:DE'>Rush 2 - Extreme Racing USA<span
+  style='mso-spacerun:yes'> </span></span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Normal</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Compatible</span></td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:351'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><span lang=DE style='mso-ansi-language:
+  DE'>S.C.A.R.S.</span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:352'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>SD Hiryuu no Ken Densetsu</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Minor gfx errors</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:353'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>San Francisco Rush - Extreme Racing</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:354'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>San Francisco Rush 2049</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:355'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Scooby-Doo - Classic Creep Capers</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Sky in game doesn't work correctly with Voodoo 1-3</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:356'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm' x:str="Shadow Man ">Shadow Man<span
+  style='mso-spacerun:yes'> </span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; option (slow) or &quot;Get
+  frame buffer info&quot; with Mupen to have correct pause menu in game</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:357'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Shadowgate 64 - Trials of the Four Towers<st1:place u2:st="on"><st1:PlaceName u2:st="on"></st1:PlaceName><st1:PlaceType u2:st="on"></st1:PlaceType></st1:place></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:358'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Sim City 2000</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>S2DEX.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:359'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Snow Speeders</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:360'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Snowboard Kids</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:361'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Snowboard Kids 2</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:362'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Sonic Wings Assault</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:363'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><st1:place u2:st="on"><st1:PlaceName u2:st="on">South
+  Park</st1:PlaceName><st1:PlaceType u2:st="on"></st1:PlaceType></st1:place></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:364'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>SouthPark - Chef's Luv Shack</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:365'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><st1:place u2:st="on"><st1:PlaceName u2:st="on">South
+  Park Rally</st1:PlaceName><st1:PlaceType u2:st="on"></st1:PlaceType></st1:place></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:366'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Space Dynamites</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>TURBO3D</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt'>Normal</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:367'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm' x:str="Space Invaders ">Space
+  Invaders<span style='mso-spacerun:yes'> </span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Compatible</span></td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:368'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><span lang=DE style='mso-ansi-language:
+  DE'>Space Station Silicon Valley</span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Normal</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Compatible</span></td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:369'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm' x:str="Spider-Man "><span lang=DE
+  style='mso-ansi-language:DE'>Spider-Man<span
+  style='mso-spacerun:yes'> </span></span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Compatible</span></td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:370'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><span lang=DE style='mso-ansi-language:
+  DE'>Star Fox 64</span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:371'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Star Soldier - Vanishing Earth</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:372'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Star Twins</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW RARE4<st1:place u2:st="on"></st1:place></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Get frame buffer info&quot; option with Mupen or
+  use &#8220;Read every frame&#8221; option (slow) to see correct TV</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:373'>
+  <td height=42 class=xl38 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Star Wars - Rogue Squadron</td>
+  <td class=xl39 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>?</td>
+  <td class=xl39 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>0</td>
+  <td class=xl39 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>?</td>
+  <td class=xl39 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Unsupported.<font class="font11"> Microcode not implemented</font></td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:374'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Star Wars - Shadows of the Empire</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0D EXT</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:375'>
+  <td height=42 class=xl38 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Star Wars Episode I - Battle for Naboo</td>
+  <td class=xl39 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>?</td>
+  <td class=xl39 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>0</td>
+  <td class=xl39 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>?</td>
+  <td class=xl39 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Unsupported.<font class="font11"> Microcode not implemented</font></td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:376'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Star Wars Episode I - Racer</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:377'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm' x:str="StarCraft 64 ">StarCraft 64<span
+  style='mso-spacerun:yes'> </span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:378'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Starshot - Space Circus Fever</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:379'>
+  <td height=21 class=xl38 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Stunt Racer 64</td>
+  <td class=xl39 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>?</td>
+  <td class=xl39 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>0</td>
+  <td class=xl39 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>?</td>
+  <td class=xl39 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Unsupported</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:380'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Super B-Daman - Battle Phoenix 64<st1:City u2:st="on"></st1:City><st1:place u2:st="on"><st1:City u2:st="on"></st1:City></st1:place></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:381'>
+  <td height=21 class=xl29 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Super Bowling 64</td>
+  <td class=xl30 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl30 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>3</td>
+  <td class=xl30 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl30 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Gfx errors</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:382'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm' x:str="Super Mario 64 ">Super Mario
+  64<span style='mso-spacerun:yes'> </span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:383'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Super Robot Spirits</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:384'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Super Robot Taisen 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:385'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Super Smash Bros.</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:386'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Super Speed Race 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:387'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Supercross 2000<u1:p></u1:p></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX<u1:p></u1:p></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5<u1:p></u1:p></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City><u1:p></u1:p></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible<u1:p></u1:p></td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:388'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm' x:str="Superman ">Superman<span
+  style='mso-spacerun:yes'> </span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:389'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Susume! taisen puzzle dama toukon !
+  Marumata Chou</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>S2DEX.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:390'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Taz Express</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm' x:str="Compatible. Use Mupen 0.4 ">Compatible. Use Mupen 0.4<span
+  style='mso-spacerun:yes'> </span></td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:391'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Telefoot Soccer 2000</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>ZSortp 0.33</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Minor gfx errors</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:392'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Tetris 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:393'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Tetrisphere</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:394'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Tigger's Honey Hunt</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:395'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Tom Clancy's Rainbow Six</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:396'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Tom and Jerry in Fists of Furry</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:397'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Tonic Trouble</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; option to see correct
+  transition effects for pause menu in game</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:398'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Tony Hawk's Pro Skater</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use PJ64</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:399'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Tony Hawk's Pro Skater 2</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:400'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Tony Hawk's Pro Skater 3</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt'>Toon
+  Panic</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt'><span lang=DE style='mso-ansi-language:
+  DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:401'>
+  <td height=21 class=xl35 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Top Gear Hyper-Bike</td>
+  <td class=xl36 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl36 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>2</td>
+  <td class=xl36 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl36 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Major gfx errors. Use Mupen</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:402'>
+  <td height=21 class=xl46 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Top Gear Overdrive</td>
+  <td class=xl47 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl47 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>4</td>
+  <td class=xl47 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl47 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Gfx errors. Use Mupen</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:403'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Top Gear Rally</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:404'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Top Gear Rally 2</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:405'>
+  <td height=21 class=xl40 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Toukon Roads</td>
+  <td class=xl41 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>?</td>
+  <td class=xl41 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>0</td>
+  <td class=xl41 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>?</td>
+  <td class=xl41 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Unsupported<font class="font10">.</font><font class="font11"> Microcode
+  not implemented</font></td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:406'>
+  <td height=21 class=xl40 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Toukon Roads 2</td>
+  <td class=xl41 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>?</td>
+  <td class=xl41 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>0</td>
+  <td class=xl41 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>?</td>
+  <td class=xl41 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Unsupported<font class="font10">.</font><font class="font11"> Microcode
+  not implemented</font></td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:407'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm' x:str="Toy Story 2 ">Toy Story 2<span
+  style='mso-spacerun:yes'> </span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:408'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Transformers - Beast Wars Metals 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:409'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Transformers - Beast Wars Transmetal</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:410'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm' x:str="Triple Play 2000 ">Triple Play
+  2000<span style='mso-spacerun:yes'> </span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Get frame buffer info&quot; option with Mupen or
+  use &quot;Read every frame&quot; option to see correct TV monitors (slow)</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:411'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Tsumi to Batsu - Chikyuu no Keishousha</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:412'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><span lang=DE style='mso-ansi-language:
+  DE'>Turok - Dinosaur Hunter</span></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:413'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Turok - Rage Wars</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:414'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Turok 2 - Seeds of Evil</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:415'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Turok 3 - Shadow of Oblivion</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='mso-height-source:userset;height:15.75pt;mso-yfti-irow:
+  416'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Twisted Edge Extreme Snowboarding</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Minor gfx errors</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:417'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>V-Rally Edition 99</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Minor gfx errors</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:418'>
+  <td height=21 class=xl35 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm' x:str="Vigilante 8 ">Vigilante 8<span
+  style='mso-spacerun:yes'> </span></td>
+  <td class=xl36 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl36 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>2</td>
+  <td class=xl36 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl36 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Many gfx errors</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:419'>
+  <td height=21 class=xl35 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Vigilante 8 - 2nd Offense</td>
+  <td class=xl36 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl36 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>2</td>
+  <td class=xl36 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl36 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Many gfx errors</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:420'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Virtual Chess 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:421'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Virtual Pool 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:422'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Virtual Pro Wrestling 2&nbsp; - Oudou
+  Keishou</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; option to see motion blur
+  effects during intro</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:423'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Virtual Pro Wrestling 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:424'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>WCW Backstage Assault</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:425'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>WCW Mayhem</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:426'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>WCW Nitro</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:427'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>WCW vs. nWo - World Tour</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:428'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>WCW-nWo Revenge</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:429'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>WWF - War Zone</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Get frame buffer info&quot; option with Mupen or
+  use &quot;Read every frame&quot; option to see correct TV monitors (slow)</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:430'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>WWF Attitude</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:431'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>WWF No Mercy</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:432'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>WWF WrestleMania 2000</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Use &quot;Read every frame&quot; option to see motion blur
+  effects during intro</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:433'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Waialae Country Club - True Golf Classics</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible. Minor gfx errors</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:434'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>War Gods</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:435'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Wave Race 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0D EXT</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:436'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Wave Race 64 Shindou Edition</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:437'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Wayne Gretzky's 3D Hockey '98</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX1.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:438'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Wetrix</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:439'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Wheel of Fortune</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Slow</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:440'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Wild Choppers</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:441'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>WinBack - Covert Operations</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible, but a gray square sometimes appear on the screen. Missing
+  sky</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:442'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Wipeout 64</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:443'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Wonder Project J2</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:444'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>World Cup 98</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:445'>
+  <td height=21 class=xl38 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>World Driver Championship</td>
+  <td class=xl39 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>?</td>
+  <td class=xl39 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>0</td>
+  <td class=xl39 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>?</td>
+  <td class=xl39 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Unsupported</td>
+ </tr>
+ <tr height=21 style='height:15.75pt;mso-yfti-irow:446'>
+  <td height=21 class=xl27 width=183 style='height:15.75pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'><st1:City u2:st="on"><st1:place u2:st="on">Worms
+  - Armageddon</st1:place></st1:City></td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:447'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Xena Warrior Princess - Talisman of Fate</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>F3DEX2.XX</span></td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num><span lang=DE style='mso-ansi-language:DE'>5</span></td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><span lang=DE style='mso-ansi-language:DE'>Fast</span></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:448'>
+  <td height=42 class=xl46 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Yakouchuu II - Satsujun Kouru</td>
+  <td class=xl47 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl47 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>4</td>
+  <td class=xl47 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl47 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Use Nemu 0.8 (disable audio HLE). No movies</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:449'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Yoshi's Story</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>S2DEX.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'
+  x:str="Compatible. Minor texture errors. Use &quot;Read every frame&quot; option to see transition effects ">Compatible.
+  Minor texture errors. Use &quot;Read every frame&quot; option to see
+  transition effects<span style='mso-spacerun:yes'> </span></td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:450'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Yuke Yuke!! Trouble Makers</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>RSP SW 2.0X</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:451'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Zelda no Densetsu 2 - Mujura no Kamen</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX2.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl48 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:452'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Zelda no Densetsu - Toki no Ocarina</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX 2.06H</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'>*Mostly* Fast</td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=42 style='height:31.5pt;mso-yfti-irow:453;mso-yfti-lastrow:yes'>
+  <td height=42 class=xl27 width=183 style='height:31.5pt;width:137pt;
+  padding-bottom:0cm;padding-top:0cm'>Zool - Majou Tsukai Densetsu</td>
+  <td class=xl28 width=107 style='width:80pt;padding-bottom:0cm;padding-top:
+  0cm'>F3DEX1.XX</td>
+  <td class=xl28 align=right width=87 style='width:65pt;padding-bottom:0cm;
+  padding-top:0cm' x:num>5</td>
+  <td class=xl28 width=76 style='width:57pt;padding-bottom:0cm;padding-top:
+  0cm'><st1:City u2:st="on"><st1:place u2:st="on">Normal</st1:place></st1:City></td>
+  <td class=xl28 width=520 style='width:390pt;padding-bottom:0cm;padding-top:
+  0cm'>Compatible</td>
+ </tr>
+ <tr height=21 style='height:15.75pt'>
+  <td height=21 class=xl37 style='height:15.75pt'><span lang=FR
+  style='mso-ansi-language:FR'>&nbsp;<u1:p></u1:p></span></td>
+  <td colspan=4 class=xl24 style='mso-ignore:colspan'>&nbsp;</td>
+ </tr>
+ <![if supportMisalignedColumns]>
+ <tr height=0 style='display:none'>
+  <td width=183 style='width:137pt'></td>
+  <td width=107 style='width:80pt'></td>
+  <td width=87 style='width:65pt'></td>
+  <td width=76 style='width:57pt'></td>
+  <td width=520 style='width:390pt'></td>
+ </tr>
+ <![endif]>
+</table>
+
+</body>
+
+</html>
diff --git a/source/gles2glide64/src/Glide64/Ini.cpp b/source/gles2glide64/src/Glide64/Ini.cpp
new file mode 100755 (executable)
index 0000000..b6ab0b0
--- /dev/null
@@ -0,0 +1,621 @@
+/*
+*   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
+
+#include "m64p.h"
+
+#include "Ini.h"
+#include "Gfx_1.3.h"
+#include <limits.h>
+#ifndef _WIN32
+#include <unistd.h>
+#include <string.h>
+#include <dirent.h>
+#include <stdlib.h>
+#else
+#include <io.h>
+#endif // _WIN32
+
+#include <errno.h>
+#ifndef _WIN32
+#include <sys/resource.h>
+#endif
+
+#ifdef _WIN32
+  #define PATH_MAX _MAX_PATH
+  #define stricmp _stricmp
+#endif
+
+FILE *ini;
+int sectionstart;
+int last_line;      // last good line
+int last_line_ret;  // last line ended in return?
+wxUint16 cr = 0x0A0D;
+static char configdir[PATH_MAX] = {0};
+
+
+//TODO: move INI_xxxx() function code into class and clean up
+Ini *Ini::singleton = 0;
+
+Ini::Ini()
+{
+       if (!INI_Open())
+       {
+               printf("Could not find INI file!");
+               exit(1);
+       }
+}
+
+Ini *Ini::OpenIni()
+{
+       if (!singleton)
+               singleton = new Ini();
+       return singleton;
+}
+
+void Ini::SetPath(const char *path)
+{
+       if (!INI_FindSection(path, false))
+       {
+               printf("Could not find [%s] section in INI file!", path);
+       }
+}
+
+
+bool Ini::Read(const char *key, int *l)
+{
+       int undef = 0xDEADBEEF;
+       int tmpVal = INI_ReadInt(key, undef, false);
+       if (tmpVal == undef)
+       {
+               return false;
+       }
+       else
+       {
+               *l = tmpVal;
+               return true;
+       }
+}
+
+bool Ini::Read(const char *key, int *l, int defaultVal)
+{
+       *l = INI_ReadInt(key, defaultVal, false);
+       return true;
+}
+
+int Ini::Read(const char *key, int defaultVal)
+{
+       return INI_ReadInt(key, defaultVal, false);
+}
+
+
+BOOL INI_Open ()
+{
+       //TODO: use ConfigGetSharedDataFilepath
+       
+    // 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 (NULL, 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, "Glide64mk2.ini", PATH_MAX - strlen(path));
+    LOG("opening %s\n", path);
+    // Open the file
+    ini = fopen (path, "rb");
+    if (ini == NULL)
+    {
+        ERRLOG("Could not find Glide64mk2.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)
+{
+  printf("Inserting space, space to insert is %d\n", 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);
+    if (ftruncate(file, t2+space) != 0)
+        ERRLOG("Failed to truncate .ini file to %i bytes", 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);
+        if (fread(chunk,1,len,ini) != (size_t) len)
+            ERRLOG("Failed to read %i bytes from .ini file", len);
+        fseek (ini,-len+space,SEEK_CUR);
+        if (fwrite(chunk,1,len,ini) != (size_t) len)
+            ERRLOG("Failed to write %i bytes to .ini file", len);
+        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);
+    if (ftruncate(file, t2+space) != 0)
+        ERRLOG("Failed to truncate .ini file to %i bytes", t2+space);
+     }
+#endif // _WIN32
+}
+
+BOOL INI_FindSection (const char *sectionname, BOOL create)
+{
+    if (ini == NULL)
+        return FALSE;
+/*    static char cached_secion[200]="\0";
+    static BOOL cached_result;
+    if (!strcasecmp(section,sectionname))
+       return cached_result;*/
+
+
+//    printf("INI_FindSection trying to find name for %s\n", sectionname);
+
+    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;
+        if (fgets(line,255,ini) == NULL)
+            break;
+
+        // 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)
+            if (fwrite(&cr, 1, 2, ini) != 2)
+                ERRLOG("Failed to write <CR><LF> to .ini file");
+        sprintf (section, "[%s]", sectionname);
+        if (fwrite(&cr, 1, 2, ini) != 2 ||
+            fwrite(section, 1, strlen(section), ini) != strlen(section) ||
+            fwrite(&cr, 1, 2, ini) != 2)
+            ERRLOG("Failed to write Section line to .ini file");
+        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;
+        if (fgets(line,255,ini) == NULL)
+            break;
+
+        // 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)
+            if (fwrite(&cr, 1, 2, ini) != 2)
+                ERRLOG("Failed to write <CR><LF> to .ini file");
+        sprintf (line, "%s = %s", itemname, def_value);
+        if (fwrite(line, 1, strlen(line), ini) != strlen(line) ||
+            fwrite(&cr, 1, 2, ini) != 2)
+            ERRLOG("Failed to write key,value line to .ini file");
+        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;
+        if (fgets(line,255,ini) == NULL) break;
+
+        // 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);
+            if (fwrite(line, 1, strlen(line), ini) != strlen(line) ||
+                fwrite(&cr, 1, 2, ini) != 2)
+            {
+                ERRLOG("Failed to write line '%s' to .ini file", line);
+            }
+            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);
+    sprintf (line, "%s = %s", itemname, value);
+    if (!last_line_ret)
+        if (fwrite(&cr, 1, 2, ini) != 2)
+            ERRLOG("Failed to write <CR> to .ini file");
+    if (fwrite(line, 1, strlen(line), ini) != strlen(line) ||
+        fwrite(&cr, 1, 2, ini) != 2)
+    {
+        ERRLOG("Failed to write line '%s' to .ini file", line);
+    }
+    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/source/gles2glide64/src/Glide64/Ini.h b/source/gles2glide64/src/Glide64/Ini.h
new file mode 100755 (executable)
index 0000000..ac41cd6
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+*   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
+//
+//****************************************************************
+
+//nmn: Fix for MAX_PATH
+#include <limits.h>
+#include <stdio.h>
+#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 );
+
+class Ini
+{
+private:
+       Ini();
+       static Ini *singleton;
+public:
+       static Ini *OpenIni();
+       void SetPath(const char *path);
+       bool Read(const char *key, int *l);
+       bool Read(const char *key, int *l, int defaultVal);
+       int Read(const char *key, int defaultVal);
+};
diff --git a/source/gles2glide64/src/Glide64/Keys.cpp b/source/gles2glide64/src/Glide64/Keys.cpp
new file mode 100644 (file)
index 0000000..0b38539
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+//
+// Keys, used by Glide64. 
+// Since key codes are different for WinAPI and SDL, this difference is managed here
+// Created by Sergey 'Gonetz' Lipski, July 2009
+//
+//****************************************************************
+
+#include "Gfx_1.3.h"
+
+Glide64Keys::Glide64Keys()
+{
+#ifdef __WINDOWS__
+_keys[G64_VK_CONTROL] = 0x11;
+_keys[G64_VK_ALT]     = 0x12;
+_keys[G64_VK_INSERT]  = 0x2D;
+_keys[G64_VK_LBUTTON] = 0x01;
+_keys[G64_VK_UP]      = 0x26;
+_keys[G64_VK_DOWN]    = 0x28;
+_keys[G64_VK_LEFT]    = 0x25;
+_keys[G64_VK_RIGHT]   = 0x27;
+_keys[G64_VK_SPACE]   = 0x20;
+_keys[G64_VK_BACK]    = 0x08;
+_keys[G64_VK_SCROLL]  = 0x91;
+_keys[G64_VK_1]       = 0x31;
+_keys[G64_VK_2]       = 0x32;
+_keys[G64_VK_3]       = 0x33;
+_keys[G64_VK_4]       = 0x34;
+_keys[G64_VK_5]       = 0x35;
+_keys[G64_VK_6]       = 0x36;
+_keys[G64_VK_7]       = 0x37;
+_keys[G64_VK_8]       = 0x38;
+_keys[G64_VK_9]       = 0x39;
+_keys[G64_VK_0]       = 0x30;
+_keys[G64_VK_A]       = 0x41;
+_keys[G64_VK_B]       = 0x42;
+_keys[G64_VK_D]       = 0x44;
+_keys[G64_VK_G]       = 0x47;
+_keys[G64_VK_Q]       = 0x51;
+_keys[G64_VK_R]       = 0x52;
+_keys[G64_VK_S]       = 0x53;
+_keys[G64_VK_V]       = 0x56;
+_keys[G64_VK_W]       = 0x57;
+#else
+_keys[G64_VK_CONTROL] = 306;
+_keys[G64_VK_ALT]     = 308;
+_keys[G64_VK_INSERT]  = 277;
+_keys[G64_VK_LBUTTON] =   1;
+_keys[G64_VK_UP]      = 273;
+_keys[G64_VK_DOWN]    = 274;
+_keys[G64_VK_LEFT]    = 276;
+_keys[G64_VK_RIGHT]   = 275;
+_keys[G64_VK_SPACE]   =  32;
+_keys[G64_VK_BACK]    =   8;
+_keys[G64_VK_SCROLL]  = 302;
+_keys[G64_VK_1]       =  49;
+_keys[G64_VK_2]       =  50;
+_keys[G64_VK_3]       =  51;
+_keys[G64_VK_4]       =  52;
+_keys[G64_VK_5]       =  53;
+_keys[G64_VK_6]       =  54;
+_keys[G64_VK_7]       =  55;
+_keys[G64_VK_8]       =  56;
+_keys[G64_VK_9]       =  57;
+_keys[G64_VK_0]       =  48;
+_keys[G64_VK_A]       =  97;
+_keys[G64_VK_B]       =  98;
+_keys[G64_VK_D]       = 100;
+_keys[G64_VK_G]       = 103;
+_keys[G64_VK_Q]       = 113;
+_keys[G64_VK_R]       = 114;
+_keys[G64_VK_S]       = 115;
+_keys[G64_VK_V]       = 118;
+_keys[G64_VK_W]       = 119;
+#endif
+}
diff --git a/source/gles2glide64/src/Glide64/Keys.h b/source/gles2glide64/src/Glide64/Keys.h
new file mode 100644 (file)
index 0000000..1f1bbf4
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+//
+// Keys, used by Glide64. 
+// Since key codes are different for WinAPI and SDL, this difference is managed here
+// Created by Sergey 'Gonetz' Lipski, July 2009
+//
+//****************************************************************
+
+#ifndef Keys_H
+#define Keys_H
+
+#define G64_VK_CONTROL  0
+#define G64_VK_ALT      1
+#define G64_VK_INSERT   2
+#define G64_VK_LBUTTON  3
+#define G64_VK_UP       4
+#define G64_VK_DOWN     5
+#define G64_VK_LEFT     6
+#define G64_VK_RIGHT    7
+#define G64_VK_SPACE    8
+#define G64_VK_BACK     9
+#define G64_VK_SCROLL   10
+#define G64_VK_1        11
+#define G64_VK_2        12
+#define G64_VK_3        13
+#define G64_VK_4        14
+#define G64_VK_5        15
+#define G64_VK_6        16
+#define G64_VK_7        17
+#define G64_VK_8        18
+#define G64_VK_9        19
+#define G64_VK_0        20
+#define G64_VK_A        21
+#define G64_VK_B        22
+#define G64_VK_D        23
+#define G64_VK_G        24
+#define G64_VK_Q        25
+#define G64_VK_R        26
+#define G64_VK_S        27
+#define G64_VK_V        28
+#define G64_VK_W        29
+
+#define G64_NUM_KEYS    30
+
+class Glide64Keys
+{
+  public:
+    Glide64Keys();
+    ~Glide64Keys(){}
+    int operator[](unsigned int index){return _keys[index];}
+
+  private:
+    int _keys[G64_NUM_KEYS];
+};
+
+#endif //Keys_H
diff --git a/source/gles2glide64/src/Glide64/Main.cpp b/source/gles2glide64/src/Glide64/Main.cpp
new file mode 100755 (executable)
index 0000000..c1df3ad
--- /dev/null
@@ -0,0 +1,2787 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+#include "Gfx_1.3.h"
+#include "Ini.h"
+#include "Config.h"
+#include "Util.h"
+#include "3dmath.h"
+#include "Debugger.h"
+#include "Combine.h"
+#include "TexCache.h"
+#include "CRC.h"
+#include "FBtoScreen.h"
+#include "DepthBufferRender.h"
+
+#if defined(__GNUC__)
+#include <sys/time.h>
+#elif defined(__MSC__)
+#include <time.h>
+#define PATH_MAX MAX_PATH
+#endif
+#include "osal_dynamiclib.h"
+#ifdef TEXTURE_FILTER // Hiroshi Morii <koolsmoky@users.sourceforge.net>
+#include <stdarg.h>
+int  ghq_dmptex_toggle_key = 0;
+#endif
+#if defined(__MINGW32__)
+#define swprintf _snwprintf
+#define vswprintf _vsnwprintf
+#endif
+
+#define G64_VERSION "G64 Mk2"
+#define RELTIME "Date: " __DATE__// " Time: " __TIME__
+
+#ifdef EXT_LOGGING
+std::ofstream extlog;
+#endif
+
+#ifdef LOGGING
+std::ofstream loga;
+#endif
+
+#ifdef RDP_LOGGING
+int log_open = FALSE;
+std::ofstream rdp_log;
+#endif
+
+#ifdef RDP_ERROR_LOG
+int elog_open = FALSE;
+std::ofstream rdp_err;
+#endif
+
+GFX_INFO gfx;
+
+/* definitions of pointers to Core config functions */
+ptr_ConfigOpenSection      ConfigOpenSection = NULL;
+ptr_ConfigSetParameter     ConfigSetParameter = NULL;
+ptr_ConfigGetParameter     ConfigGetParameter = NULL;
+ptr_ConfigGetParameterHelp ConfigGetParameterHelp = NULL;
+ptr_ConfigSetDefaultInt    ConfigSetDefaultInt = NULL;
+ptr_ConfigSetDefaultFloat  ConfigSetDefaultFloat = NULL;
+ptr_ConfigSetDefaultBool   ConfigSetDefaultBool = NULL;
+ptr_ConfigSetDefaultString ConfigSetDefaultString = NULL;
+ptr_ConfigGetParamInt      ConfigGetParamInt = NULL;
+ptr_ConfigGetParamFloat    ConfigGetParamFloat = NULL;
+ptr_ConfigGetParamBool     ConfigGetParamBool = NULL;
+ptr_ConfigGetParamString   ConfigGetParamString = NULL;
+
+ptr_ConfigGetSharedDataFilepath ConfigGetSharedDataFilepath = NULL;
+ptr_ConfigGetUserConfigPath     ConfigGetUserConfigPath = NULL;
+ptr_ConfigGetUserDataPath       ConfigGetUserDataPath = NULL;
+ptr_ConfigGetUserCachePath      ConfigGetUserCachePath = NULL;
+
+/* definitions of pointers to Core video extension functions */
+ptr_VidExt_Init                  CoreVideo_Init = NULL;
+ptr_VidExt_Quit                  CoreVideo_Quit = NULL;
+ptr_VidExt_ListFullscreenModes   CoreVideo_ListFullscreenModes = NULL;
+ptr_VidExt_SetVideoMode          CoreVideo_SetVideoMode = NULL;
+ptr_VidExt_SetCaption            CoreVideo_SetCaption = NULL;
+ptr_VidExt_ToggleFullScreen      CoreVideo_ToggleFullScreen = NULL;
+ptr_VidExt_ResizeWindow          CoreVideo_ResizeWindow = NULL;
+ptr_VidExt_GL_GetProcAddress     CoreVideo_GL_GetProcAddress = NULL;
+ptr_VidExt_GL_SetAttribute       CoreVideo_GL_SetAttribute = NULL;
+ptr_VidExt_GL_SwapBuffers        CoreVideo_GL_SwapBuffers = NULL;
+int to_fullscreen = FALSE;
+int fullscreen = FALSE;
+int romopen = FALSE;
+GrContext_t gfx_context = 0;
+int debugging = FALSE;
+int exception = FALSE;
+
+int evoodoo = 0;
+int ev_fullscreen = 0;
+
+#ifdef __WINDOWS__
+#define WINPROC_OVERRIDE
+#endif
+
+#ifdef WINPROC_OVERRIDE
+LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+WNDPROC oldWndProc = NULL;
+WNDPROC myWndProc = NULL;
+#endif
+
+#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;
+wxUint32   fps_count = 0;
+
+wxUint32   vi_count = 0;
+float      vi = 0.0f;
+
+wxUint32   region = 0;
+
+float      ntsc_percent = 0.0f;
+float      pal_percent = 0.0f;
+
+#endif
+
+// ref rate
+// 60=0x0, 70=0x1, 72=0x2, 75=0x3, 80=0x4, 90=0x5, 100=0x6, 85=0x7, 120=0x8, none=0xff
+
+#ifdef PAULSCODE
+//#include "ae_bridge.h"
+#include "FrameSkipper.h"
+FrameSkipper frameSkipper;
+void vbo_resetcount();
+#endif
+
+unsigned long BMASK = 0x7FFFFF;
+// Reality display processor structure
+RDP rdp;
+
+SETTINGS settings = { FALSE, 640, 480, GR_RESOLUTION_640x480, 0 };
+
+HOTKEY_INFO hotkey_info;
+
+VOODOO voodoo = {0, 0, 0, 0,
+                 0, 0, 0, 0,
+                 0, 0, 0, 0
+                };
+
+GrTexInfo fontTex;
+GrTexInfo cursorTex;
+wxUint32   offset_font = 0;
+wxUint32   offset_cursor = 0;
+wxUint32   offset_textures = 0;
+wxUint32   offset_texbuf1 = 0;
+
+int    capture_screen = 0;
+char    capture_path[256];
+
+//SDL_sem *mutexProcessDList = SDL_CreateSemaphore(1);
+
+// SOME FUNCTION DEFINITIONS 
+
+static void DrawFrameBuffer ();
+
+
+void (*renderCallback)(int) = NULL;
+static void (*l_DebugCallback)(void *, int, const char *) = NULL;
+static void *l_DebugCallContext = NULL;
+
+void _ChangeSize ()
+{
+  rdp.scale_1024 = settings.scr_res_x / 1024.0f;
+  rdp.scale_768 = settings.scr_res_y / 768.0f;
+
+//  float res_scl_x = (float)settings.res_x / 320.0f;
+  float res_scl_y = (float)settings.res_y / 240.0f;
+
+  wxUint32 scale_x = *gfx.VI_X_SCALE_REG & 0xFFF;
+  if (!scale_x) return;
+  wxUint32 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 / 2048.0f;
+
+  wxUint32 dwHStartReg = *gfx.VI_H_START_REG;
+  wxUint32 dwVStartReg = *gfx.VI_V_START_REG;
+
+  wxUint32 hstart = dwHStartReg >> 16;
+  wxUint32 hend = dwHStartReg & 0xFFFF;
+
+  // dunno... but sometimes this happens
+  if (hend == hstart) hend = (int)(*gfx.VI_WIDTH_REG / fscale_x);
+
+  wxUint32 vstart = dwVStartReg >> 16;
+  wxUint32 vend = dwVStartReg & 0xFFFF;
+
+  rdp.vi_width = (hend - hstart) * fscale_x;
+  rdp.vi_height = (vend - vstart) * fscale_y * 1.0126582f;
+  float aspect = (settings.adjust_aspect && (fscale_y > fscale_x) && (rdp.vi_width > rdp.vi_height)) ? fscale_x/fscale_y : 1.0f;
+
+#ifdef LOGGING
+  sprintf (out_buf, "hstart: %d, hend: %d, vstart: %d, vend: %d\n", hstart, hend, vstart, vend);
+  LOG (out_buf);
+  sprintf (out_buf, "size: %d x %d\n", (int)rdp.vi_width, (int)rdp.vi_height);
+  LOG (out_buf);
+#endif
+
+  rdp.scale_x = (float)settings.res_x / rdp.vi_width;
+  if (region > 0 && settings.pal230)
+  {
+    // odd... but pal games seem to want 230 as height...
+    rdp.scale_y = res_scl_y * (230.0f / rdp.vi_height)  * aspect;
+  }
+  else
+  {
+    rdp.scale_y = (float)settings.res_y / rdp.vi_height * aspect;
+  }
+  //  rdp.offset_x = settings.offset_x * res_scl_x;
+  //  rdp.offset_y = settings.offset_y * res_scl_y;
+  //rdp.offset_x = 0;
+  //  rdp.offset_y = 0;
+  rdp.offset_y = ((float)settings.res_y - rdp.vi_height * rdp.scale_y) * 0.5f;
+  if (((wxUint32)rdp.vi_width <= (*gfx.VI_WIDTH_REG)/2) && (rdp.vi_width > rdp.vi_height))
+    rdp.scale_y *= 0.5f;
+
+  rdp.scissor_o.ul_x = 0;
+  rdp.scissor_o.ul_y = 0;
+  rdp.scissor_o.lr_x = (wxUint32)rdp.vi_width;
+  rdp.scissor_o.lr_y = (wxUint32)rdp.vi_height;
+
+  rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
+}
+
+void ChangeSize ()
+{
+  if (debugging)
+  {
+    _ChangeSize ();
+    return;
+  }
+  switch (settings.aspectmode)
+  {
+  case 0: //4:3
+    if (settings.scr_res_x >= settings.scr_res_y * 4.0f / 3.0f) {
+      settings.res_y = settings.scr_res_y;
+      settings.res_x = (wxUint32)(settings.res_y * 4.0f / 3.0f);
+    } else {
+      settings.res_x = settings.scr_res_x;
+      settings.res_y = (wxUint32)(settings.res_x / 4.0f * 3.0f);
+    }
+    break;
+  case 1: //16:9
+    if (settings.scr_res_x >= settings.scr_res_y * 16.0f / 9.0f) {
+      settings.res_y = settings.scr_res_y;
+      settings.res_x = (wxUint32)(settings.res_y * 16.0f / 9.0f);
+    } else {
+      settings.res_x = settings.scr_res_x;
+      settings.res_y = (wxUint32)(settings.res_x / 16.0f * 9.0f);
+    }
+    break;
+  default: //stretch or original
+    settings.res_x = settings.scr_res_x;
+    settings.res_y = settings.scr_res_y;
+  }
+  _ChangeSize ();
+  rdp.offset_x = (settings.scr_res_x - settings.res_x) / 2.0f;
+  float offset_y = (settings.scr_res_y - settings.res_y) / 2.0f;
+  settings.res_x += (wxUint32)rdp.offset_x;
+  settings.res_y += (wxUint32)offset_y;
+  rdp.offset_y += offset_y;
+  if (settings.aspectmode == 3) // original
+  {
+         rdp.scale_x = rdp.scale_y = 1.0f;
+         rdp.offset_x = (settings.scr_res_x - rdp.vi_width) / 2.0f;
+         rdp.offset_y = (settings.scr_res_y - rdp.vi_height) / 2.0f;
+  }
+  //   settings.res_x = settings.scr_res_x;
+  //   settings.res_y = settings.scr_res_y;
+}
+
+void ConfigWrapper()
+{
+  char strConfigWrapperExt[] = "grConfigWrapperExt";
+  GRCONFIGWRAPPEREXT grConfigWrapperExt = (GRCONFIGWRAPPEREXT)grGetProcAddress(strConfigWrapperExt);
+  if (grConfigWrapperExt)
+    grConfigWrapperExt(settings.wrpResolution, settings.wrpVRAM * 1024 * 1024, settings.wrpFBO, settings.wrpAnisotropic);
+}
+/*
+static wxConfigBase * OpenIni()
+{
+  wxConfigBase * ini = wxConfigBase::Get(false);
+  if (!ini)
+  {
+    if (iniName.IsEmpty())
+      iniName = pluginPath + wxT("/Glide64mk2.ini");
+    if (wxFileExists(iniName))
+    {
+      wxFileInputStream is(iniName);
+      wxFileConfig * fcfg = new wxFileConfig(is, wxConvISO8859_1);
+      wxConfigBase::Set(fcfg);
+      ini = fcfg;
+    }
+  }
+  if (!ini)
+    wxMessageBox(_T("Can not find ini file! Plugin will not run properly."), _T("File not found"), wxOK|wxICON_EXCLAMATION);
+  return ini;
+}
+*/
+#ifndef OLDAPI
+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);
+  }
+}
+#endif
+
+void ReadSettings ()
+{
+  //  LOG("ReadSettings\n");
+  if (!Config_Open())
+  {
+    ERRLOG("Could not open configuration!");
+    return;
+  }
+
+  settings.card_id = (BYTE)Config_ReadInt ("card_id", "Card ID", 0, TRUE, FALSE);
+  //settings.lang_id not needed
+  // depth_bias = -Config_ReadInt ("depth_bias", "Depth bias level", 0, TRUE, FALSE);
+  settings.res_data = 0;
+  settings.scr_res_x = settings.res_x = Config_ReadScreenInt("ScreenWidth");
+  settings.scr_res_y = settings.res_y = Config_ReadScreenInt("ScreenHeight");
+
+  settings.vsync = (BOOL)Config_ReadInt ("vsync", "Vertical sync", 0);
+  settings.ssformat = (BOOL)Config_ReadInt("ssformat", "TODO:ssformat", 0);
+  //settings.fast_crc = (BOOL)Config_ReadInt ("fast_crc", "Fast CRC", 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.advanced_options only good for GUI config
+  // settings.texenh_options = only good for GUI config
+  //settings.use_hotkeys = ini->Read(_T("hotkeys"), 1l);
+
+  settings.wrpResolution = (BYTE)Config_ReadInt ("wrpResolution", "Wrapper resolution", 0, TRUE, FALSE);
+  settings.wrpVRAM = (BYTE)Config_ReadInt ("wrpVRAM", "Wrapper VRAM", 0, TRUE, FALSE);
+  settings.wrpFBO = (BOOL)Config_ReadInt ("wrpFBO", "Wrapper FBO", 1, TRUE, TRUE);
+  settings.wrpAnisotropic = (BOOL)Config_ReadInt ("wrpAnisotropic", "Wrapper Anisotropic Filtering", 0, TRUE, TRUE);
+
+#ifndef _ENDUSER_RELEASE_
+  settings.autodetect_ucode = (BOOL)Config_ReadInt ("autodetect_ucode", "Auto-detect microcode", 1);
+  settings.ucode = (wxUint32)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.logging = (BOOL)Config_ReadInt ("logging", "Logging", 0);
+  settings.log_clear = (BOOL)Config_ReadInt ("log_clear", "", 0);
+
+  settings.run_in_window = (BOOL)Config_ReadInt ("run_in_window", "", 0);
+
+  settings.elogging = (BOOL)Config_ReadInt ("elogging", "", 0);
+  settings.filter_cache = (BOOL)Config_ReadInt ("filter_cache", "Filter cache", 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);
+#else
+  settings.autodetect_ucode = TRUE;
+  settings.ucode = 2;
+  settings.wireframe = FALSE;
+  settings.wfmode = 0;
+  settings.logging = FALSE;
+  settings.log_clear = FALSE;
+  settings.run_in_window = FALSE;
+  settings.elogging = FALSE;
+  settings.filter_cache = FALSE;
+  settings.unk_as_red = FALSE;
+  settings.log_unk = FALSE;
+  settings.unk_clear = FALSE;
+#endif
+
+#ifdef TEXTURE_FILTER
+  
+  // settings.ghq_fltr range is 0 through 6
+  // Filters:\nApply a filter to either smooth or sharpen textures.\nThere are 4 different smoothing filters and 2 different sharpening filters.\nThe higher the number, the stronger the effect,\ni.e. \"Smoothing filter 4\" will have a much more noticeable effect than \"Smoothing filter 1\".\nBe aware that performance may have an impact depending on the game and/or the PC.\n[Recommended: your preference]
+  // _("None"),
+  // _("Smooth filtering 1"),
+  // _("Smooth filtering 2"),
+  // _("Smooth filtering 3"),
+  // _("Smooth filtering 4"),
+  // _("Sharp filtering 1"),
+  // _("Sharp filtering 2")
+
+// settings.ghq_cmpr 0=S3TC and 1=FXT1
+
+//settings.ghq_ent is ___
+// "Texture enhancement:\n7 different filters are selectable here, each one with a distinctive look.\nBe aware of possible performance impacts.\n\nIMPORTANT: 'Store' mode - saves textures in cache 'as is'. It can improve performance in games, which load many textures.\nDisable 'Ignore backgrounds' option for better result.\n\n[Recommended: your preference]"
+
+
+
+  settings.ghq_fltr = Config_ReadInt ("ghq_fltr", "Texture Enhancement: Smooth/Sharpen Filters", 0, TRUE, FALSE);
+  settings.ghq_cmpr = Config_ReadInt ("ghq_cmpr", "Texture Compression: 0 for S3TC, 1 for FXT1", 0, TRUE, FALSE);
+  settings.ghq_enht = Config_ReadInt ("ghq_enht", "Texture Enhancement: More filters", 0, TRUE, FALSE);
+  settings.ghq_hirs = Config_ReadInt ("ghq_hirs", "Hi-res texture pack format (0 for none, 1 for Rice)", 0, TRUE, FALSE);
+  settings.ghq_enht_cmpr  = Config_ReadInt ("ghq_enht_cmpr", "Compress texture cache with S3TC or FXT1", 0, TRUE, TRUE);
+  settings.ghq_enht_tile = Config_ReadInt ("ghq_enht_tile", "Tile textures (saves memory but could cause issues)", 0, TRUE, FALSE);
+  settings.ghq_enht_f16bpp = Config_ReadInt ("ghq_enht_f16bpp", "Force 16bpp textures (saves ram but lower quality)", 0, TRUE, TRUE);
+  settings.ghq_enht_gz  = Config_ReadInt ("ghq_enht_gz", "Compress texture cache", 1, TRUE, TRUE);
+  settings.ghq_enht_nobg  = Config_ReadInt ("ghq_enht_nobg", "Don't enhance textures for backgrounds", 0, TRUE, TRUE);
+  settings.ghq_hirs_cmpr  = Config_ReadInt ("ghq_hirs_cmpr", "Enable S3TC and FXT1 compression", 0, TRUE, TRUE);
+  settings.ghq_hirs_tile = Config_ReadInt ("ghq_hirs_tile", "Tile hi-res textures (saves memory but could cause issues)", 0, TRUE, TRUE);
+  settings.ghq_hirs_f16bpp = Config_ReadInt ("ghq_hirs_f16bpp", "Force 16bpp hi-res textures (saves ram but lower quality)", 0, TRUE, TRUE);
+  settings.ghq_hirs_gz  = Config_ReadInt ("ghq_hirs_gz", "Compress hi-res texture cache", 1, TRUE, TRUE);
+  settings.ghq_hirs_altcrc = Config_ReadInt ("ghq_hirs_altcrc", "Alternative CRC calculation -- emulates Rice bug", 1, TRUE, TRUE);
+  settings.ghq_cache_save = Config_ReadInt ("ghq_cache_save", "Save tex cache to disk", 1, TRUE, TRUE);
+  settings.ghq_cache_size = Config_ReadInt ("ghq_cache_size", "Texture Cache Size (MB)", 128, TRUE, FALSE);
+  settings.ghq_hirs_let_texartists_fly = Config_ReadInt ("ghq_hirs_let_texartists_fly", "Use full alpha channel -- could cause issues for some tex packs", 0, TRUE, TRUE);
+  settings.ghq_hirs_dump = Config_ReadInt ("ghq_hirs_dump", "Dump textures", 0, FALSE, TRUE);
+#endif
+  //TODO-PORT: remove?
+  ConfigWrapper();
+}
+
+void ReadSpecialSettings (const char * name)
+{
+  //  char buf [256];
+  //  sprintf(buf, "ReadSpecialSettings. Name: %s\n", name);
+  //  LOG(buf);
+  settings.hacks = 0;
+
+  //detect games which require special hacks
+  if (strstr(name, (const char *)"ZELDA") || strstr(name, (const char *)"MASK"))
+    settings.hacks |= hack_Zelda;
+  else if (strstr(name, (const char *)"ROADSTERS TROPHY"))
+    settings.hacks |= hack_Zelda;
+  else if (strstr(name, (const char *)"Diddy Kong Racing"))
+    settings.hacks |= hack_Diddy;
+  else if (strstr(name, (const char *)"Tonic Trouble"))
+    settings.hacks |= hack_Tonic;
+  else if (strstr(name, (const char *)"All") && strstr(name, (const char *)"Star") && strstr(name, (const char *)"Baseball"))
+    settings.hacks |= hack_ASB;
+  else if (strstr(name, (const char *)"Beetle") || strstr(name, (const char *)"BEETLE") || strstr(name, (const char *)"HSV"))
+    settings.hacks |= hack_BAR;
+  else if (strstr(name, (const char *)"I S S 64") || strstr(name, (const char *)"J WORLD SOCCER3") || strstr(name, (const char *)"PERFECT STRIKER") || strstr(name, (const char *)"RONALDINHO SOCCER"))
+    settings.hacks |= hack_ISS64;
+  else if (strstr(name, (const char *)"MARIOKART64"))
+    settings.hacks |= hack_MK64;
+  else if (strstr(name, (const char *)"NITRO64"))
+    settings.hacks |= hack_WCWnitro;
+  else if (strstr(name, (const char *)"CHOPPER_ATTACK") || strstr(name, (const char *)"WILD CHOPPERS"))
+    settings.hacks |= hack_Chopper;
+  else if (strstr(name, (const char *)"Resident Evil II") || strstr(name, (const char *)"BioHazard II"))
+    settings.hacks |= hack_RE2;
+  else if (strstr(name, (const char *)"YOSHI STORY"))
+    settings.hacks |= hack_Yoshi;
+  else if (strstr(name, (const char *)"F-Zero X") || strstr(name, (const char *)"F-ZERO X"))
+    settings.hacks |= hack_Fzero;
+  else if (strstr(name, (const char *)"PAPER MARIO") || strstr(name, (const char *)"MARIO STORY"))
+    settings.hacks |= hack_PMario;
+  else if (strstr(name, (const char *)"TOP GEAR RALLY 2"))
+    settings.hacks |= hack_TGR2;
+  else if (strstr(name, (const char *)"TOP GEAR RALLY"))
+    settings.hacks |= hack_TGR;
+  else if (strstr(name, (const char *)"Top Gear Hyper Bike"))
+    settings.hacks |= hack_Hyperbike;
+  else if (strstr(name, (const char *)"Killer Instinct Gold") || strstr(name, (const char *)"KILLER INSTINCT GOLD"))
+    settings.hacks |= hack_KI;
+  else if (strstr(name, (const char *)"Knockout Kings 2000"))
+    settings.hacks |= hack_Knockout;
+  else if (strstr(name, (const char *)"LEGORacers"))
+    settings.hacks |= hack_Lego;
+  else if (strstr(name, (const char *)"OgreBattle64"))
+    settings.hacks |= hack_Ogre64;
+  else if (strstr(name, (const char *)"Pilot Wings64"))
+    settings.hacks |= hack_Pilotwings;
+  else if (strstr(name, (const char *)"Supercross"))
+    settings.hacks |= hack_Supercross;
+  else if (strstr(name, (const char *)"STARCRAFT 64"))
+    settings.hacks |= hack_Starcraft;
+  else if (strstr(name, (const char *)"BANJO KAZOOIE 2") || strstr(name, (const char *)"BANJO TOOIE"))
+    settings.hacks |= hack_Banjo2;
+  else if (strstr(name, (const char *)"FIFA: RTWC 98") || strstr(name, (const char *)"RoadToWorldCup98"))
+    settings.hacks |= hack_Fifa98;
+  else if (strstr(name, (const char *)"Mega Man 64") || strstr(name, (const char *)"RockMan Dash"))
+    settings.hacks |= hack_Megaman;
+  else if (strstr(name, (const char *)"MISCHIEF MAKERS") || strstr(name, (const char *)"TROUBLE MAKERS"))
+    settings.hacks |= hack_Makers;
+  else if (strstr(name, (const char *)"GOLDENEYE"))
+    settings.hacks |= hack_GoldenEye;
+  else if (strstr(name, (const char *)"PUZZLE LEAGUE"))
+    settings.hacks |= hack_PPL;
+
+  Ini * ini = Ini::OpenIni();
+  if (!ini)
+    return;
+  ini->SetPath(name);
+
+  ini->Read(_T("alt_tex_size"), &(settings.alt_tex_size));
+  ini->Read(_T("use_sts1_only"), &(settings.use_sts1_only));
+  ini->Read(_T("force_calc_sphere"), &(settings.force_calc_sphere));
+  ini->Read(_T("correct_viewport"), &(settings.correct_viewport));
+  ini->Read(_T("increase_texrect_edge"), &(settings.increase_texrect_edge));
+  ini->Read(_T("decrease_fillrect_edge"), &(settings.decrease_fillrect_edge));
+  if (ini->Read(_T("texture_correction"), -1) == 0) settings.texture_correction = 0;
+  else settings.texture_correction = 1;
+  if (ini->Read(_T("pal230"), -1) == 1) settings.pal230 = 1;
+  else settings.pal230 = 0;
+  ini->Read(_T("stipple_mode"), &(settings.stipple_mode));
+  int stipple_pattern = ini->Read(_T("stipple_pattern"), -1);
+  if (stipple_pattern > 0) settings.stipple_pattern = (wxUint32)stipple_pattern;
+  ini->Read(_T("force_microcheck"), &(settings.force_microcheck));
+  ini->Read(_T("force_quad3d"), &(settings.force_quad3d));
+  ini->Read(_T("clip_zmin"), &(settings.clip_zmin));
+  ini->Read(_T("clip_zmax"), &(settings.clip_zmax));
+  ini->Read(_T("fast_crc"), &(settings.fast_crc));
+  ini->Read(_T("adjust_aspect"), &(settings.adjust_aspect), 1);
+  ini->Read(_T("zmode_compare_less"), &(settings.zmode_compare_less));
+  ini->Read(_T("old_style_adither"), &(settings.old_style_adither));
+  ini->Read(_T("n64_z_scale"), &(settings.n64_z_scale));
+  if (settings.n64_z_scale)
+    ZLUT_init();
+
+  //frame buffer
+  int optimize_texrect = ini->Read(_T("optimize_texrect"), -1);
+  int ignore_aux_copy = ini->Read(_T("ignore_aux_copy"), -1);
+  int hires_buf_clear = ini->Read(_T("hires_buf_clear"), -1);
+  int read_alpha = ini->Read(_T("fb_read_alpha"), -1);
+  int useless_is_useless = ini->Read(_T("useless_is_useless"), -1);
+  int fb_crc_mode = ini->Read(_T("fb_crc_mode"), -1);
+
+  if (optimize_texrect > 0) settings.frame_buffer |= fb_optimize_texrect;
+  else if (optimize_texrect == 0) settings.frame_buffer &= ~fb_optimize_texrect;
+  if (ignore_aux_copy > 0) settings.frame_buffer |= fb_ignore_aux_copy;
+  else if (ignore_aux_copy == 0) settings.frame_buffer &= ~fb_ignore_aux_copy;
+  if (hires_buf_clear > 0) settings.frame_buffer |= fb_hwfbe_buf_clear;
+  else if (hires_buf_clear == 0) settings.frame_buffer &= ~fb_hwfbe_buf_clear;
+  if (read_alpha > 0) settings.frame_buffer |= fb_read_alpha;
+  else if (read_alpha == 0) settings.frame_buffer &= ~fb_read_alpha;
+  if (useless_is_useless > 0) settings.frame_buffer |= fb_useless_is_useless;
+  else settings.frame_buffer &= ~fb_useless_is_useless;
+  if (fb_crc_mode >= 0) settings.fb_crc_mode = (SETTINGS::FBCRCMODE)fb_crc_mode;
+
+  //  if (settings.custom_ini)
+  {
+    ini->Read(_T("filtering"), &(settings.filtering));
+    ini->Read(_T("fog"), &(settings.fog));
+    ini->Read(_T("buff_clear"), &(settings.buff_clear));
+    ini->Read(_T("swapmode"), &(settings.swapmode));
+    ini->Read(_T("aspect"), &(settings.aspectmode));
+    ini->Read(_T("lodmode"), &(settings.lodmode));
+#ifdef PAULSCODE
+    ini->Read(_T("autoframeskip"), &(settings.autoframeskip));
+    ini->Read(_T("maxframeskip"), &(settings.maxframeskip));
+    if( settings.autoframeskip == 1 )
+      frameSkipper.setSkips( FrameSkipper::AUTO, settings.maxframeskip );
+    else
+      frameSkipper.setSkips( FrameSkipper::MANUAL, settings.maxframeskip );
+#endif
+
+    /*
+    TODO-port: fix resolutions
+    int resolution;
+    if (ini->Read(_T("resolution"), &resolution))
+    {
+      settings.res_data = (wxUint32)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];
+    }
+    */
+       
+       PackedScreenResolution tmpRes = Config_ReadScreenSettings();
+       settings.res_data = tmpRes.resolution;
+       settings.scr_res_x = settings.res_x = tmpRes.width;
+       settings.scr_res_y = settings.res_y = tmpRes.height;
+
+    //frame buffer
+    int smart_read = ini->Read(_T("fb_smart"), -1);
+    int hires = ini->Read(_T("fb_hires"), -1);
+    int read_always = ini->Read(_T("fb_read_always"), -1);
+    int read_back_to_screen = ini->Read(_T("read_back_to_screen"), -1);
+    int cpu_write_hack = ini->Read(_T("detect_cpu_write"), -1);
+    int get_fbinfo = ini->Read(_T("fb_get_info"), -1);
+    int depth_render = ini->Read(_T("fb_render"), -1);
+
+    if (smart_read > 0) settings.frame_buffer |= fb_emulation;
+    else if (smart_read == 0) settings.frame_buffer &= ~fb_emulation;
+    if (hires > 0) settings.frame_buffer |= fb_hwfbe;
+    else if (hires == 0) settings.frame_buffer &= ~fb_hwfbe;
+    if (read_always > 0) settings.frame_buffer |= fb_ref;
+    else if (read_always == 0) settings.frame_buffer &= ~fb_ref;
+    if (read_back_to_screen == 1) settings.frame_buffer |= fb_read_back_to_screen;
+    else if (read_back_to_screen == 2) settings.frame_buffer |= fb_read_back_to_screen2;
+    else if (read_back_to_screen == 0) settings.frame_buffer &= ~(fb_read_back_to_screen|fb_read_back_to_screen2);
+    if (cpu_write_hack > 0) settings.frame_buffer |= fb_cpu_write_hack;
+    else if (cpu_write_hack == 0) settings.frame_buffer &= ~fb_cpu_write_hack;
+    if (get_fbinfo > 0) settings.frame_buffer |= fb_get_info;
+    else if (get_fbinfo == 0) settings.frame_buffer &= ~fb_get_info;
+    if (depth_render > 0) settings.frame_buffer |= fb_depth_render;
+    else if (depth_render == 0) settings.frame_buffer &= ~fb_depth_render;
+    settings.frame_buffer |= fb_motionblur;
+  }
+  settings.flame_corona = (settings.hacks & hack_Zelda) && !fb_depth_render_enabled;
+}
+
+//TODO-PORT: more ini stuff
+void WriteSettings (bool saveEmulationSettings)
+{
+/*
+  wxConfigBase * ini = OpenIni();
+  if (!ini || !ini->HasGroup(_T("/SETTINGS")))
+    return;
+  ini->SetPath(_T("/SETTINGS"));
+
+  ini->Write(_T("card_id"), settings.card_id);
+  ini->Write(_T("lang_id"), settings.lang_id);
+  ini->Write(_T("resolution"), (int)settings.res_data);
+  ini->Write(_T("ssformat"), settings.ssformat);
+  ini->Write(_T("vsync"), settings.vsync);
+  ini->Write(_T("show_fps"), settings.show_fps);
+  ini->Write(_T("clock"), settings.clock);
+  ini->Write(_T("clock_24_hr"), settings.clock_24_hr);
+  ini->Write(_T("advanced_options"), settings.advanced_options);
+  ini->Write(_T("texenh_options"), settings.texenh_options);
+
+  ini->Write(_T("wrpResolution"), settings.wrpResolution);
+  ini->Write(_T("wrpVRAM"), settings.wrpVRAM);
+  ini->Write(_T("wrpFBO"), settings.wrpFBO);
+  ini->Write(_T("wrpAnisotropic"), settings.wrpAnisotropic);
+
+#ifndef _ENDUSER_RELEASE_
+  ini->Write(_T("autodetect_ucode"), settings.autodetect_ucode);
+  ini->Write(_T("ucode"), (int)settings.ucode);
+  ini->Write(_T("wireframe"), settings.wireframe);
+  ini->Write(_T("wfmode"), settings.wfmode);
+  ini->Write(_T("logging"), settings.logging);
+  ini->Write(_T("log_clear"), settings.log_clear);
+  ini->Write(_T("run_in_window"), settings.run_in_window);
+  ini->Write(_T("elogging"), settings.elogging);
+  ini->Write(_T("filter_cache"), settings.filter_cache);
+  ini->Write(_T("unk_as_red"), settings.unk_as_red);
+  ini->Write(_T("log_unk"), settings.log_unk);
+  ini->Write(_T("unk_clear"), settings.unk_clear);
+#endif //_ENDUSER_RELEASE_
+
+#ifdef TEXTURE_FILTER
+  ini->Write(_T("ghq_fltr"), settings.ghq_fltr);
+  ini->Write(_T("ghq_cmpr"), settings.ghq_cmpr);
+  ini->Write(_T("ghq_enht"), settings.ghq_enht);
+  ini->Write(_T("ghq_hirs"), settings.ghq_hirs);
+  ini->Write(_T("ghq_enht_cmpr"), settings.ghq_enht_cmpr);
+  ini->Write(_T("ghq_enht_tile"), settings.ghq_enht_tile);
+  ini->Write(_T("ghq_enht_f16bpp"), settings.ghq_enht_f16bpp);
+  ini->Write(_T("ghq_enht_gz"), settings.ghq_enht_gz);
+  ini->Write(_T("ghq_enht_nobg"), settings.ghq_enht_nobg);
+  ini->Write(_T("ghq_hirs_cmpr"), settings.ghq_hirs_cmpr);
+  ini->Write(_T("ghq_hirs_tile"), settings.ghq_hirs_tile);
+  ini->Write(_T("ghq_hirs_f16bpp"), settings.ghq_hirs_f16bpp);
+  ini->Write(_T("ghq_hirs_gz"), settings.ghq_hirs_gz);
+  ini->Write(_T("ghq_hirs_altcrc"), settings.ghq_hirs_altcrc);
+  ini->Write(_T("ghq_cache_save"), settings.ghq_cache_save);
+  ini->Write(_T("ghq_cache_size"), settings.ghq_cache_size);
+  ini->Write(_T("ghq_hirs_let_texartists_fly"), settings.ghq_hirs_let_texartists_fly);
+  ini->Write(_T("ghq_hirs_dump"), settings.ghq_hirs_dump);
+#endif
+
+  if (saveEmulationSettings)
+  {
+    if (romopen)
+    {
+      wxString S = _T("/");
+      ini->SetPath(S+rdp.RomName);
+    }
+    else
+      ini->SetPath(_T("/DEFAULT"));
+    ini->Write(_T("filtering"), settings.filtering);
+    ini->Write(_T("fog"), settings.fog);
+    ini->Write(_T("buff_clear"), settings.buff_clear);
+    ini->Write(_T("swapmode"), settings.swapmode);
+    ini->Write(_T("lodmode"), settings.lodmode);
+    ini->Write(_T("aspect"), settings.aspectmode);
+
+    ini->Write(_T("fb_read_always"), settings.frame_buffer&fb_ref ? 1 : 0l);
+    ini->Write(_T("fb_smart"), settings.frame_buffer & fb_emulation ? 1 : 0l);
+    //    ini->Write("motionblur", settings.frame_buffer & fb_motionblur ? 1 : 0);
+    ini->Write(_T("fb_hires"), settings.frame_buffer & fb_hwfbe ? 1 : 0l);
+    ini->Write(_T("fb_get_info"), settings.frame_buffer & fb_get_info ? 1 : 0l);
+    ini->Write(_T("fb_render"), settings.frame_buffer & fb_depth_render ? 1 : 0l);
+    ini->Write(_T("detect_cpu_write"), settings.frame_buffer & fb_cpu_write_hack ? 1 : 0l);
+    if (settings.frame_buffer & fb_read_back_to_screen)
+      ini->Write(_T("read_back_to_screen"), 1);
+    else if (settings.frame_buffer & fb_read_back_to_screen2)
+      ini->Write(_T("read_back_to_screen"), 2);
+    else
+      ini->Write(_T("read_back_to_screen"), 0l);
+  }
+
+  wxFileOutputStream os(iniName);
+  ((wxFileConfig*)ini)->Save(os);
+*/
+}
+
+GRTEXBUFFEREXT   grTextureBufferExt = NULL;
+GRTEXBUFFEREXT   grTextureAuxBufferExt = NULL;
+GRAUXBUFFEREXT   grAuxBufferExt = NULL;
+GRSTIPPLE grStippleModeExt = NULL;
+GRSTIPPLE grStipplePatternExt = NULL;
+FxBool (FX_CALL *grKeyPressed)(FxU32) = NULL;
+
+int GetTexAddrUMA(int tmu, int texsize)
+{
+  int addr = voodoo.tex_min_addr[0] + voodoo.tmem_ptr[0];
+  voodoo.tmem_ptr[0] += texsize;
+  voodoo.tmem_ptr[1] = voodoo.tmem_ptr[0];
+  return addr;
+}
+int GetTexAddrNonUMA(int tmu, int texsize)
+{
+  int addr = voodoo.tex_min_addr[tmu] + voodoo.tmem_ptr[tmu];
+  voodoo.tmem_ptr[tmu] += texsize;
+  return addr;
+}
+GETTEXADDR GetTexAddr = GetTexAddrNonUMA;
+
+// guLoadTextures - used to load the cursor and font textures
+void guLoadTextures ()
+{
+  if (grTextureBufferExt)
+  {
+    int tbuf_size = 0;
+    if (voodoo.max_tex_size <= 256)
+    {
+      grTextureBufferExt(  GR_TMU1, voodoo.tex_min_addr[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_TMU0, voodoo.tex_min_addr[GR_TMU0], 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);
+      grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
+      grBufferClear (0, 0, 0xFFFF);
+      grRenderBuffer( GR_BUFFER_BACKBUFFER );
+    }
+    else
+    {
+      grTextureBufferExt(  GR_TMU0, voodoo.tex_min_addr[GR_TMU0], 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);
+      grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
+      grBufferClear (0, 0, 0xFFFF);
+      grRenderBuffer( GR_BUFFER_BACKBUFFER );
+    }
+
+    rdp.texbufs[0].tmu = GR_TMU0;
+    rdp.texbufs[0].begin = voodoo.tex_min_addr[GR_TMU0];
+    rdp.texbufs[0].end = rdp.texbufs[0].begin+tbuf_size;
+    rdp.texbufs[0].count = 0;
+    rdp.texbufs[0].clear_allowed = TRUE;
+    offset_font = tbuf_size;
+    if (voodoo.num_tmu > 1)
+    {
+      rdp.texbufs[1].tmu = GR_TMU1;
+      rdp.texbufs[1].begin = voodoo.tex_UMA ? rdp.texbufs[0].end : voodoo.tex_min_addr[GR_TMU1];
+      rdp.texbufs[1].end = rdp.texbufs[1].begin+tbuf_size;
+      rdp.texbufs[1].count = 0;
+      rdp.texbufs[1].clear_allowed = TRUE;
+      if (voodoo.tex_UMA)
+        offset_font += tbuf_size;
+      else
+        offset_texbuf1 = tbuf_size;
+    }
+  }
+  else
+    offset_font = 0;
+
+#include "font.h"
+  wxUint32 *data = (wxUint32*)font;
+  wxUint32 cur;
+
+  // ** Font texture **
+  wxUint8 *tex8 = (wxUint8*)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]
+  wxUint32 i,b;
+  for (i=0; i<0x200; i++)
+  {
+    // cur = ~*(data++), byteswapped
+#ifdef __VISUALC__
+    cur = _byteswap_ulong(~*(data++));
+#else
+    cur = ~*(data++);
+    cur = ((cur&0xFF)<<24)|(((cur>>8)&0xFF)<<16)|(((cur>>16)&0xFF)<<8)|((cur>>24)&0xFF);
+#endif
+
+    for (b=0x80000000; b!=0; b>>=1)
+    {
+      if (cur&b) *tex8 = 0xFF;
+      else *tex8 = 0x00;
+      tex8 ++;
+    }
+  }
+
+  grTexDownloadMipMap (GR_TMU0,
+    voodoo.tex_min_addr[GR_TMU0] + offset_font,
+    GR_MIPMAPLEVELMASK_BOTH,
+    &fontTex);
+
+  offset_cursor = offset_font + grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, &fontTex);
+
+  free (fontTex.data);
+
+  // ** Cursor texture **
+#include "cursor.h"
+  data = (wxUint32*)cursor;
+
+  wxUint16 *tex16 = (wxUint16*)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++) = (wxUint16)(((cur&0x000000FF)<<8)|((cur&0x0000FF00)>>8));
+    *(tex16++) = (wxUint16)(((cur&0x00FF0000)>>8)|((cur&0xFF000000)>>24));
+  }
+
+  grTexDownloadMipMap (GR_TMU0,
+    voodoo.tex_min_addr[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);
+}
+
+#ifdef TEXTURE_FILTER
+void DisplayLoadProgress(const wchar_t *format, ...)
+{
+  va_list args;
+  wchar_t wbuf[INFO_BUF];
+  char buf[INFO_BUF];
+
+  // process input
+  va_start(args, format);
+  vswprintf(wbuf, INFO_BUF, format, args);
+  va_end(args);
+
+  // XXX: convert to multibyte
+  wcstombs(buf, wbuf, INFO_BUF);
+
+  if (fullscreen)
+  {
+    float x;
+    set_message_combiner ();
+    output (382, 380, 1, "LOADING TEXTURES. PLEASE WAIT...");
+    int len = min (strlen(buf)*8, 1024);
+    x = (1024-len)/2.0f;
+    output (x, 360, 1, buf);
+    grBufferSwap (0);
+    grColorMask (FXTRUE, FXTRUE);
+    grBufferClear (0, 0, 0xFFFF);
+  }
+}
+#endif
+
+int InitGfx ()
+{
+#ifdef TEXTURE_FILTER
+  wchar_t romname[256];
+  wchar_t foldername[PATH_MAX + 64];
+  wchar_t cachename[PATH_MAX + 64];
+#endif
+  if (fullscreen)
+    ReleaseGfx ();
+
+  OPEN_RDP_LOG ();  // doesn't matter if opens again; it will check for it
+  OPEN_RDP_E_LOG ();
+  VLOG ("InitGfx ()\n");
+
+  debugging = FALSE;
+  rdp_reset ();
+
+  // Initialize Glide
+  grGlideInit ();
+
+  // Select the Glide device
+  grSstSelect (settings.card_id);
+
+  // Is mirroring allowed?
+  const char *extensions = grGetString (GR_EXTENSION);
+
+  // Check which SST we are using and initialize stuff
+  // Hiroshi Morii <koolsmoky@users.sourceforge.net>
+  enum {
+    GR_SSTTYPE_VOODOO  = 0,
+    GR_SSTTYPE_SST96   = 1,
+    GR_SSTTYPE_AT3D    = 2,
+    GR_SSTTYPE_Voodoo2 = 3,
+    GR_SSTTYPE_Banshee = 4,
+    GR_SSTTYPE_Voodoo3 = 5,
+    GR_SSTTYPE_Voodoo4 = 6,
+    GR_SSTTYPE_Voodoo5 = 7
+  };
+  const char *hardware = grGetString(GR_HARDWARE);
+  unsigned int SST_type = GR_SSTTYPE_VOODOO;
+  if (strstr(hardware, "Rush")) {
+    SST_type = GR_SSTTYPE_SST96;
+  } else if (strstr(hardware, "Voodoo2")) {
+    SST_type = GR_SSTTYPE_Voodoo2;
+  } else if (strstr(hardware, "Voodoo Banshee")) {
+    SST_type = GR_SSTTYPE_Banshee;
+  } else if (strstr(hardware, "Voodoo3")) {
+    SST_type = GR_SSTTYPE_Voodoo3;
+  } else if (strstr(hardware, "Voodoo4")) {
+    SST_type = GR_SSTTYPE_Voodoo4;
+  } else if (strstr(hardware, "Voodoo5")) {
+    SST_type = GR_SSTTYPE_Voodoo5;
+  }
+  // 2Mb Texture boundary
+  voodoo.has_2mb_tex_boundary = (SST_type < GR_SSTTYPE_Banshee) && !evoodoo;
+  // use UMA if available
+  voodoo.tex_UMA = FALSE;
+  //*
+  if (strstr(extensions, " TEXUMA ")) {
+    // we get better texture cache hits with UMA on
+    grEnable(GR_TEXTURE_UMA_EXT);
+    voodoo.tex_UMA = TRUE;
+    LOG ("Using TEXUMA extension.\n");
+  }
+  //*/
+//TODO-PORT: fullscreen stuff
+  wxUint32 res_data = settings.res_data;
+  char strWrapperFullScreenResolutionExt[] = "grWrapperFullScreenResolutionExt";
+  if (ev_fullscreen)
+  {
+      GRWRAPPERFULLSCREENRESOLUTIONEXT grWrapperFullScreenResolutionExt =
+        (GRWRAPPERFULLSCREENRESOLUTIONEXT)grGetProcAddress(strWrapperFullScreenResolutionExt);
+      if (grWrapperFullScreenResolutionExt) {
+        wxUint32 _width, _height = 0;
+        settings.res_data = grWrapperFullScreenResolutionExt(&_width, &_height);
+        settings.scr_res_x = settings.res_x = _width;
+        settings.scr_res_y = settings.res_y = _height;
+      }
+      res_data = settings.res_data;
+  }
+  else if (evoodoo)
+  {
+      GRWRAPPERFULLSCREENRESOLUTIONEXT grWrapperFullScreenResolutionExt =
+        (GRWRAPPERFULLSCREENRESOLUTIONEXT)grGetProcAddress(strWrapperFullScreenResolutionExt);
+      if (grWrapperFullScreenResolutionExt != NULL)
+      {
+/*
+        TODO-port: fix resolutions
+        settings.res_data = settings.res_data_org;
+        settings.scr_res_x = settings.res_x = resolutions[settings.res_data][0];
+        settings.scr_res_y = settings.res_y = resolutions[settings.res_data][1];
+*/
+      }
+      res_data = settings.res_data | 0x80000000;
+  }
+
+  gfx_context = 0;
+
+  // Select the window
+
+  if (fb_hwfbe_enabled)
+  {
+    char strSstWinOpenExt[] ="grSstWinOpenExt";
+    GRWINOPENEXT grSstWinOpenExt = (GRWINOPENEXT)grGetProcAddress(strSstWinOpenExt);
+    if (grSstWinOpenExt)
+      gfx_context = grSstWinOpenExt ((FxU32)NULL,
+      res_data,
+      GR_REFRESH_60Hz,
+      GR_COLORFORMAT_RGBA,
+      GR_ORIGIN_UPPER_LEFT,
+      fb_emulation_enabled?GR_PIXFMT_RGB_565:GR_PIXFMT_ARGB_8888, //32b color is not compatible with fb emulation
+      2,    // Double-buffering
+      1);   // 1 auxillary buffer
+  }
+  if (!gfx_context)
+    gfx_context = grSstWinOpen ((FxU32)NULL,
+    res_data,
+    GR_REFRESH_60Hz,
+    GR_COLORFORMAT_RGBA,
+    GR_ORIGIN_UPPER_LEFT,
+    2,    // Double-buffering
+    1);   // 1 auxillary buffer
+
+  if (!gfx_context)
+  {
+    ERRLOG("Error setting display mode");
+    //    grSstWinClose (gfx_context);
+    grGlideShutdown ();
+    return FALSE;
+  }
+
+  fullscreen = TRUE;
+  to_fullscreen = FALSE;
+
+
+  // get the # of TMUs available
+  grGet (GR_NUM_TMU, 4, (FxI32*)&voodoo.num_tmu);
+  // get maximal texture size
+  grGet (GR_MAX_TEXTURE_SIZE, 4, (FxI32*)&voodoo.max_tex_size);
+  voodoo.sup_large_tex = (voodoo.max_tex_size > 256 && !(settings.hacks & hack_PPL));
+
+  //num_tmu = 1;
+  if (voodoo.tex_UMA)
+  {
+    GetTexAddr = GetTexAddrUMA;
+    voodoo.tex_min_addr[0] = voodoo.tex_min_addr[1] = grTexMinAddress(GR_TMU0);
+    voodoo.tex_max_addr[0] = voodoo.tex_max_addr[1] = grTexMaxAddress(GR_TMU0);
+  }
+  else
+  {
+    GetTexAddr = GetTexAddrNonUMA;
+    voodoo.tex_min_addr[0] = grTexMinAddress(GR_TMU0);
+    voodoo.tex_min_addr[1] = grTexMinAddress(GR_TMU1);
+    voodoo.tex_max_addr[0] = grTexMaxAddress(GR_TMU0);
+    voodoo.tex_max_addr[1] = grTexMaxAddress(GR_TMU1);
+  }
+
+  if (strstr (extensions, "TEXMIRROR") && !(settings.hacks&hack_Zelda)) //zelda's trees suffer from hardware mirroring
+    voodoo.sup_mirroring = 1;
+  else
+    voodoo.sup_mirroring = 0;
+
+  if (strstr (extensions, "TEXFMT"))  //VSA100 texture format extension
+    voodoo.sup_32bit_tex = TRUE;
+  else
+    voodoo.sup_32bit_tex = FALSE;
+
+  voodoo.gamma_correction = 0;
+  if (strstr(extensions, "GETGAMMA"))
+    grGet(GR_GAMMA_TABLE_ENTRIES, sizeof(voodoo.gamma_table_size), &voodoo.gamma_table_size);
+
+  if (fb_hwfbe_enabled)
+  {
+    if (char * extstr = (char*)strstr(extensions, "TEXTUREBUFFER"))
+    {
+      if (!strncmp(extstr, "TEXTUREBUFFER", 13))
+      {
+        char strTextureBufferExt[] = "grTextureBufferExt";
+        grTextureBufferExt = (GRTEXBUFFEREXT) grGetProcAddress(strTextureBufferExt);
+        char strTextureAuxBufferExt[] = "grTextureAuxBufferExt";
+        grTextureAuxBufferExt = (GRTEXBUFFEREXT) grGetProcAddress(strTextureAuxBufferExt);
+        char strAuxBufferExt[] = "grAuxBufferExt";
+        grAuxBufferExt = (GRAUXBUFFEREXT) grGetProcAddress(strAuxBufferExt);
+      }
+    }
+    else
+      settings.frame_buffer &= ~fb_hwfbe;
+  }
+  else
+    grTextureBufferExt = 0;
+
+  grStippleModeExt = (GRSTIPPLE)grStippleMode;
+  grStipplePatternExt = (GRSTIPPLE)grStipplePattern;
+
+  if (grStipplePatternExt)
+    grStipplePatternExt(settings.stipple_pattern);
+
+//  char strKeyPressedExt[] = "grKeyPressedExt";
+//  grKeyPressed = (FxBool (FX_CALL *)(FxU32))grGetProcAddress (strKeyPressedExt);
+
+  InitCombine();
+
+#ifdef SIMULATE_VOODOO1
+  voodoo.num_tmu = 1;
+  voodoo.sup_mirroring = 0;
+#endif
+
+#ifdef SIMULATE_BANSHEE
+  voodoo.num_tmu = 1;
+  voodoo.sup_mirroring = 1;
+#endif
+
+  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_ZBUFFER);
+  grDepthBufferFunction(GR_CMP_LESS);
+  grDepthMask(FXTRUE);
+
+  settings.res_x = settings.scr_res_x;
+  settings.res_y = settings.scr_res_y;
+  ChangeSize ();
+
+  guLoadTextures ();
+  ClearCache ();
+
+  grCullMode (GR_CULL_DISABLE);
+  grDepthBufferMode (GR_DEPTHBUFFER_ZBUFFER);
+  grDepthBufferFunction (GR_CMP_ALWAYS);
+  grRenderBuffer(GR_BUFFER_BACKBUFFER);
+  grColorMask (FXTRUE, FXTRUE);
+  grDepthMask (FXTRUE);
+  grBufferClear (0, 0, 0xFFFF);
+  grBufferSwap (0);
+  grBufferClear (0, 0, 0xFFFF);
+  grDepthMask (FXFALSE);
+  grTexFilterMode (0, GR_TEXTUREFILTER_BILINEAR, GR_TEXTUREFILTER_BILINEAR);
+  grTexFilterMode (1, GR_TEXTUREFILTER_BILINEAR, GR_TEXTUREFILTER_BILINEAR);
+  grTexClampMode (0, GR_TEXTURECLAMP_CLAMP, GR_TEXTURECLAMP_CLAMP);
+  grTexClampMode (1, GR_TEXTURECLAMP_CLAMP, GR_TEXTURECLAMP_CLAMP);
+  grClipWindow (0, 0, settings.scr_res_x, settings.scr_res_y);
+  rdp.update |= UPDATE_SCISSOR | UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE;
+
+#ifdef TEXTURE_FILTER // Hiroshi Morii <koolsmoky@users.sourceforge.net>
+  if (!settings.ghq_use)
+  {
+    settings.ghq_use = settings.ghq_fltr || settings.ghq_enht /*|| settings.ghq_cmpr*/ || settings.ghq_hirs;
+    if (settings.ghq_use)
+    {
+      /* Plugin path */
+      int options = texfltr[settings.ghq_fltr]|texenht[settings.ghq_enht]|texcmpr[settings.ghq_cmpr]|texhirs[settings.ghq_hirs];
+      if (settings.ghq_enht_cmpr)
+        options |= COMPRESS_TEX;
+      if (settings.ghq_hirs_cmpr)
+        options |= COMPRESS_HIRESTEX;
+      //      if (settings.ghq_enht_tile)
+      //        options |= TILE_TEX;
+      if (settings.ghq_hirs_tile)
+        options |= TILE_HIRESTEX;
+      if (settings.ghq_enht_f16bpp)
+        options |= FORCE16BPP_TEX;
+      if (settings.ghq_hirs_f16bpp)
+        options |= FORCE16BPP_HIRESTEX;
+      if (settings.ghq_enht_gz)
+        options |= GZ_TEXCACHE;
+      if (settings.ghq_hirs_gz)
+        options |= GZ_HIRESTEXCACHE;
+      if (settings.ghq_cache_save)
+        options |= (DUMP_TEXCACHE|DUMP_HIRESTEXCACHE);
+      if (settings.ghq_hirs_let_texartists_fly)
+        options |= LET_TEXARTISTS_FLY;
+      if (settings.ghq_hirs_dump)
+        options |= DUMP_TEX;
+
+      ghq_dmptex_toggle_key = 0;
+
+      swprintf(romname, sizeof(romname) / sizeof(*romname), L"%hs", rdp.RomName);
+      swprintf(foldername, sizeof(foldername) / sizeof(*foldername), L"%hs", ConfigGetUserDataPath());
+      swprintf(cachename, sizeof(cachename) / sizeof(*cachename), L"%hs", ConfigGetUserCachePath());
+
+      settings.ghq_use = (int)ext_ghq_init(voodoo.max_tex_size, // max texture width supported by hardware
+        voodoo.max_tex_size, // max texture height supported by hardware
+        voodoo.sup_32bit_tex?32:16, // max texture bpp supported by hardware
+        options,
+        settings.ghq_cache_size * 1024*1024, // cache texture to system memory
+        foldername,
+        cachename,
+        romname, // name of ROM. must be no longer than 256 characters
+        DisplayLoadProgress);
+    }
+  }
+  if (settings.ghq_use && strstr (extensions, "TEXMIRROR"))
+    voodoo.sup_mirroring = 1;
+#endif
+
+  return TRUE;
+}
+
+void ReleaseGfx ()
+{
+  VLOG("ReleaseGfx ()\n");
+
+  // Restore gamma settings
+  if (voodoo.gamma_correction)
+  {
+    if (voodoo.gamma_table_r)
+      grLoadGammaTable(voodoo.gamma_table_size, voodoo.gamma_table_r, voodoo.gamma_table_g, voodoo.gamma_table_b);
+    else
+      guGammaCorrectionRGB(1.3f, 1.3f, 1.3f); //1.3f is default 3dfx gamma for everything but desktop
+    voodoo.gamma_correction = 0;
+  }
+
+  // Release graphics
+  grSstWinClose (gfx_context);
+
+  // Shutdown glide
+  grGlideShutdown();
+
+  fullscreen = FALSE;
+  rdp.window_changed = TRUE;
+}
+
+// new API code begins here!
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EXPORT void CALL ReadScreen2(void *dest, int *width, int *height, int front)
+{
+  VLOG("CALL ReadScreen2 ()\n");
+  *width = settings.res_x;
+  *height = settings.res_y;
+  if (dest)
+  {
+    BYTE * line = (BYTE*)dest;
+    if (!fullscreen)
+    {
+      for (wxUint32 y=0; y<settings.res_y; y++)
+      {
+        for (wxUint32 x=0; x<settings.res_x; x++)
+        {
+          line[x*3] = 0x20;
+          line[x*3+1] = 0x7f;
+          line[x*3+2] = 0x40;
+        }
+      }
+      // LOG ("ReadScreen. not in the fullscreen!\n");
+      WARNLOG("[Glide64] Cannot save screenshot in windowed mode?\n");
+
+      return;
+    }
+
+  GrLfbInfo_t info;
+  info.size = sizeof(GrLfbInfo_t);
+  if (grLfbLock (GR_LFB_READ_ONLY,
+    GR_BUFFER_FRONTBUFFER,
+    GR_LFBWRITEMODE_888,
+    GR_ORIGIN_UPPER_LEFT,
+    FXFALSE,
+    &info))
+  {
+    // Copy the screen, let's hope this works.
+      for (wxUint32 y=0; y<settings.res_y; y++)
+      {
+        BYTE *ptr = (BYTE*) info.lfbPtr + (info.strideInBytes * y);
+        for (wxUint32 x=0; x<settings.res_x; x++)
+        {
+          line[x*3]   = ptr[2];  // red
+          line[x*3+1] = ptr[1];  // green
+          line[x*3+2] = ptr[0];  // blue
+          ptr += 4;
+        }
+        line += settings.res_x * 3;
+      }
+
+      // Unlock the frontbuffer
+      grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_FRONTBUFFER);
+    }
+    VLOG ("ReadScreen. Success.\n");
+  }
+}
+
+EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context,
+                                   void (*DebugCallback)(void *, int, const char *))
+{
+  VLOG("CALL PluginStartup ()\n");
+    l_DebugCallback = DebugCallback;
+    l_DebugCallContext = Context;
+
+    /* attach and call the CoreGetAPIVersions function, check Config and Video Extension API versions for compatibility */
+    ptr_CoreGetAPIVersions CoreAPIVersionFunc;
+    CoreAPIVersionFunc = (ptr_CoreGetAPIVersions) osal_dynlib_getproc(CoreLibHandle, "CoreGetAPIVersions");
+    if (CoreAPIVersionFunc == NULL)
+    {
+        ERRLOG("Core emulator broken; no CoreAPIVersionFunc() function found.");
+        return M64ERR_INCOMPATIBLE;
+    }
+    int ConfigAPIVersion, DebugAPIVersion, VidextAPIVersion;
+    (*CoreAPIVersionFunc)(&ConfigAPIVersion, &DebugAPIVersion, &VidextAPIVersion, NULL);
+    if ((ConfigAPIVersion & 0xffff0000) != (CONFIG_API_VERSION & 0xffff0000))
+    {
+        ERRLOG("Emulator core Config API incompatible with this plugin");
+        return M64ERR_INCOMPATIBLE;
+    }
+    if ((VidextAPIVersion & 0xffff0000) != (VIDEXT_API_VERSION & 0xffff0000))
+    {
+        ERRLOG("Emulator core Video Extension API incompatible with this plugin");
+        return M64ERR_INCOMPATIBLE;
+    }
+
+    ConfigOpenSection = (ptr_ConfigOpenSection) osal_dynlib_getproc(CoreLibHandle, "ConfigOpenSection");
+    ConfigSetParameter = (ptr_ConfigSetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigSetParameter");
+    ConfigGetParameter = (ptr_ConfigGetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParameter");
+    ConfigSetDefaultInt = (ptr_ConfigSetDefaultInt) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultInt");
+    ConfigSetDefaultFloat = (ptr_ConfigSetDefaultFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultFloat");
+    ConfigSetDefaultBool = (ptr_ConfigSetDefaultBool) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultBool");
+    ConfigSetDefaultString = (ptr_ConfigSetDefaultString) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultString");
+    ConfigGetParamInt = (ptr_ConfigGetParamInt) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamInt");
+    ConfigGetParamFloat = (ptr_ConfigGetParamFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamFloat");
+    ConfigGetParamBool = (ptr_ConfigGetParamBool) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamBool");
+    ConfigGetParamString = (ptr_ConfigGetParamString) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamString");
+
+    ConfigGetSharedDataFilepath = (ptr_ConfigGetSharedDataFilepath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetSharedDataFilepath");
+    ConfigGetUserConfigPath = (ptr_ConfigGetUserConfigPath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserConfigPath");
+    ConfigGetUserDataPath = (ptr_ConfigGetUserDataPath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserDataPath");
+    ConfigGetUserCachePath = (ptr_ConfigGetUserCachePath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserCachePath");
+
+    if (!ConfigOpenSection   || !ConfigSetParameter    || !ConfigGetParameter ||
+        !ConfigSetDefaultInt || !ConfigSetDefaultFloat || !ConfigSetDefaultBool || !ConfigSetDefaultString ||
+        !ConfigGetParamInt   || !ConfigGetParamFloat   || !ConfigGetParamBool   || !ConfigGetParamString ||
+        !ConfigGetSharedDataFilepath || !ConfigGetUserConfigPath || !ConfigGetUserDataPath || !ConfigGetUserCachePath)
+    {
+        ERRLOG("Couldn't connect to Core configuration functions");
+        return M64ERR_INCOMPATIBLE;
+    }
+
+    /* Get the core Video Extension function pointers from the library handle */
+    CoreVideo_Init = (ptr_VidExt_Init) osal_dynlib_getproc(CoreLibHandle, "VidExt_Init");
+    CoreVideo_Quit = (ptr_VidExt_Quit) osal_dynlib_getproc(CoreLibHandle, "VidExt_Quit");
+    CoreVideo_ListFullscreenModes = (ptr_VidExt_ListFullscreenModes) osal_dynlib_getproc(CoreLibHandle, "VidExt_ListFullscreenModes");
+    CoreVideo_SetVideoMode = (ptr_VidExt_SetVideoMode) osal_dynlib_getproc(CoreLibHandle, "VidExt_SetVideoMode");
+    CoreVideo_SetCaption = (ptr_VidExt_SetCaption) osal_dynlib_getproc(CoreLibHandle, "VidExt_SetCaption");
+    CoreVideo_ToggleFullScreen = (ptr_VidExt_ToggleFullScreen) osal_dynlib_getproc(CoreLibHandle, "VidExt_ToggleFullScreen");
+    CoreVideo_ResizeWindow = (ptr_VidExt_ResizeWindow) osal_dynlib_getproc(CoreLibHandle, "VidExt_ResizeWindow");
+    CoreVideo_GL_GetProcAddress = (ptr_VidExt_GL_GetProcAddress) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_GetProcAddress");
+    CoreVideo_GL_SetAttribute = (ptr_VidExt_GL_SetAttribute) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_SetAttribute");
+    CoreVideo_GL_SwapBuffers = (ptr_VidExt_GL_SwapBuffers) osal_dynlib_getproc(CoreLibHandle, "VidExt_GL_SwapBuffers");
+
+    if (!CoreVideo_Init || !CoreVideo_Quit || !CoreVideo_ListFullscreenModes || !CoreVideo_SetVideoMode ||
+        !CoreVideo_SetCaption || !CoreVideo_ToggleFullScreen || !CoreVideo_ResizeWindow || !CoreVideo_GL_GetProcAddress ||
+        !CoreVideo_GL_SetAttribute || !CoreVideo_GL_SwapBuffers)
+    {
+        ERRLOG("Couldn't connect to Core video functions");
+        return M64ERR_INCOMPATIBLE;
+    }
+
+    const char *configDir = ConfigGetSharedDataFilepath("Glide64mk2.ini");
+    if (configDir)
+    {
+        SetConfigDir(configDir);
+        CoreVideo_Init();
+        ReadSettings();
+               return M64ERR_SUCCESS;
+    }
+    else
+    {
+        ERRLOG("Couldn't find Glide64mk2.ini");
+        return M64ERR_FILES;
+    }
+}
+
+EXPORT m64p_error CALL PluginShutdown(void)
+{
+  VLOG("CALL PluginShutdown ()\n");
+    return M64ERR_SUCCESS;
+}
+
+EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, int *APIVersion, const char **PluginNamePtr, int *Capabilities)
+{
+  VLOG("CALL PluginGetVersion ()\n");
+    /* set version info */
+    if (PluginType != NULL)
+        *PluginType = M64PLUGIN_GFX;
+
+    if (PluginVersion != NULL)
+        *PluginVersion = PLUGIN_VERSION;
+
+    if (APIVersion != NULL)
+        *APIVersion = VIDEO_PLUGIN_API_VERSION;
+
+    if (PluginNamePtr != NULL)
+        *PluginNamePtr = PLUGIN_NAME;
+
+    if (Capabilities != NULL)
+    {
+        *Capabilities = 0;
+    }
+
+    return M64ERR_SUCCESS;
+}
+
+/******************************************************************
+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 )
+{
+  capture_screen = 1;
+  strcpy (capture_path, 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
+*******************************************************************/
+//#warning ChangeWindow unimplemented
+EXPORT void CALL ChangeWindow (void)
+{
+  VLOG ("ChangeWindow()\n");
+  #ifdef OLDAPI
+  if (evoodoo)
+  {
+    if (!ev_fullscreen)
+    {
+      to_fullscreen = TRUE;
+      ev_fullscreen = TRUE;
+#ifdef __WINDOWS__
+      if (gfx.hStatusBar)
+        ShowWindow( gfx.hStatusBar, SW_HIDE );
+      ShowCursor( FALSE );
+#endif
+    }
+    else
+    {
+      ev_fullscreen = FALSE;
+      InitGfx ();
+#ifdef __WINDOWS__
+      ShowCursor( TRUE );
+      if (gfx.hStatusBar)
+        ShowWindow( gfx.hStatusBar, SW_SHOW );
+      SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc);
+#endif
+    }
+  }
+  else
+  {
+    // Go to fullscreen at next dlist
+    // This is for compatibility with 1964, which reloads the plugin
+    //  when switching to fullscreen
+    if (!fullscreen)
+    {
+      to_fullscreen = TRUE;
+#ifdef __WINDOWS__
+      if (gfx.hStatusBar)
+        ShowWindow( gfx.hStatusBar, SW_HIDE );
+      ShowCursor( FALSE );
+#endif
+    }
+    else
+    {
+      ReleaseGfx ();
+#ifdef __WINDOWS__
+      ShowCursor( TRUE );
+      if (gfx.hStatusBar)
+        ShowWindow( gfx.hStatusBar, SW_SHOW );
+      // SetWindowLong fixes the following Windows XP Banshee issues:
+      // 1964 crash error when loading another rom.
+      // All N64 emu's minimize, restore crashes.
+      SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc);
+#endif
+    }
+  }
+#endif
+}
+
+/******************************************************************
+Function: CloseDLL
+Purpose:  This function is called when the emulator is closing
+down allowing the dll to de-initialise.
+input:    none
+output:   none
+*******************************************************************/
+void CALL CloseDLL (void)
+{
+  VLOG ("CloseDLL ()\n");
+
+  // re-set the old window proc
+#ifdef WINPROC_OVERRIDE
+  SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc);
+#endif
+
+#ifdef ALTTAB_FIX
+  if (hhkLowLevelKybd)
+  {
+    UnhookWindowsHookEx(hhkLowLevelKybd);
+    hhkLowLevelKybd = 0;
+  }
+#endif
+
+  //CLOSELOG ();
+
+#ifdef TEXTURE_FILTER // Hiroshi Morii <koolsmoky@users.sourceforge.net>
+  if (settings.ghq_use)
+  {
+    ext_ghq_shutdown();
+    settings.ghq_use = 0;
+  }
+#endif
+  if (fullscreen)
+    ReleaseGfx ();
+  ZLUT_release();
+  ClearCache ();
+  delete[] voodoo.gamma_table_r;
+  voodoo.gamma_table_r = 0;
+  delete[] voodoo.gamma_table_g;
+  voodoo.gamma_table_g = 0;
+  delete[] voodoo.gamma_table_b;
+  voodoo.gamma_table_b = 0;
+}
+
+/******************************************************************
+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
+*******************************************************************/
+void CALL DllTest ( HWND hParent )
+{
+}
+
+/******************************************************************
+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
+*******************************************************************/
+void CALL DrawScreen (void)
+{
+  VLOG ("DrawScreen ()\n");
+}
+
+/******************************************************************
+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
+*******************************************************************/
+void CALL GetDllInfo ( PLUGIN_INFO * PluginInfo )
+{
+  VLOG ("GetDllInfo ()\n");
+  PluginInfo->Version = 0x0103;     // Set to 0x0103
+  PluginInfo->Type  = PLUGIN_TYPE_GFX;  // Set to PLUGIN_TYPE_GFX
+  sprintf (PluginInfo->Name, "Glide64mk2 " G64_VERSION RELTIME);  // 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 wxUint8 array
+  PluginInfo->MemoryBswaped = TRUE; // a normal wxUint8 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 int CALL InitiateGFX (GFX_INFO Gfx_Info)
+{
+  VLOG ("InitiateGFX (*)\n");
+  voodoo.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 ();
+  char name[21] = "DEFAULT";
+  ReadSpecialSettings (name);
+  settings.res_data_org = settings.res_data;
+#ifdef FPS
+  QueryPerformanceFrequency (&perf_freq);
+  QueryPerformanceCounter (&fps_last);
+#endif
+
+  debug_init ();    // Initialize debugger
+
+  gfx = Gfx_Info;
+
+#ifdef WINPROC_OVERRIDE
+  // [H.Morii] inject our own winproc so that "alt-enter to fullscreen"
+  // message is shown when the emulator window is activated.
+  WNDPROC curWndProc = (WNDPROC)GetWindowLong(gfx.hWnd, GWL_WNDPROC);
+  if (curWndProc && curWndProc != (WNDPROC)WndProc) {
+    oldWndProc = (WNDPROC)SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)WndProc);
+  }
+#endif
+
+  util_init ();
+  math_init ();
+  TexCacheInit ();
+  CRC_BuildTable();
+  CountCombine();
+  if (fb_depth_render_enabled)
+    ZLUT_init();
+
+  char strConfigWrapperExt[] = "grConfigWrapperExt";
+  GRCONFIGWRAPPEREXT grConfigWrapperExt = (GRCONFIGWRAPPEREXT)grGetProcAddress(strConfigWrapperExt);
+  if (grConfigWrapperExt)
+    grConfigWrapperExt(settings.wrpResolution, settings.wrpVRAM * 1024 * 1024, settings.wrpFBO, settings.wrpAnisotropic);
+
+  grGlideInit ();
+  grSstSelect (0);
+  const char *extensions = grGetString (GR_EXTENSION);
+  grGlideShutdown ();
+  if (strstr (extensions, "EVOODOO"))
+  {
+    evoodoo = 1;
+    voodoo.has_2mb_tex_boundary = 0;
+  }
+  else {
+    evoodoo = 0;
+    voodoo.has_2mb_tex_boundary = 1;
+  }
+
+  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)
+{
+  rdp.window_changed = TRUE;
+}
+
+/******************************************************************
+Function: ResizeVideoOutput
+Purpose:  This function is called to force us to resize our output OpenGL window.
+          This is currently unsupported, and should never be called because we do
+          not pass the RESIZABLE flag to VidExt_SetVideoMode when initializing.
+input:    new width and height
+output:   none
+*******************************************************************/
+EXPORT void CALL ResizeVideoOutput(int Width, int Height)
+{
+}
+
+/******************************************************************
+Function: RomClosed
+Purpose:  This function is called when a rom is closed.
+input:    none
+output:   none
+*******************************************************************/
+EXPORT void CALL RomClosed (void)
+{
+  VLOG ("RomClosed ()\n");
+printf("RomClosed ()\n");
+
+  CLOSE_RDP_LOG ();
+  CLOSE_RDP_E_LOG ();
+  rdp.window_changed = TRUE;
+  romopen = FALSE;
+//  if (fullscreen && evoodoo)//*SEB*
+    ReleaseGfx ();
+}
+
+static void CheckDRAMSize()
+{
+  wxUint32 test;
+  GLIDE64_TRY
+  {
+    test = gfx.RDRAM[0x007FFFFF] + 1;
+  }
+  GLIDE64_CATCH
+  {
+    test = 0;
+  }
+  if (test)
+    BMASK = 0x7FFFFF;
+  else
+    BMASK = WMASK;
+#ifdef LOGGING
+  sprintf (out_buf, "Detected RDRAM size: %08lx\n", BMASK);
+  LOG (out_buf);
+#endif
+}
+
+/******************************************************************
+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)
+{
+  VLOG ("RomOpen ()\n");
+  no_dlist = true;
+  romopen = TRUE;
+  ucode_error_report = TRUE;   // allowed to report ucode errors
+  rdp_reset ();
+
+  // Get the country code & translate to NTSC(0) or PAL(1)
+  wxUint16 code = ((wxUint16*)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)
+
+#ifdef PAULSCODE
+  frameSkipper.setTargetFPS(region == 1 ? 50 : 60);
+#endif
+
+  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;
+
+  strncpy(rdp.RomName, name, sizeof(name));
+  ReadSpecialSettings (name);
+  ClearCache ();
+
+  CheckDRAMSize();
+
+  OPEN_RDP_LOG ();
+  OPEN_RDP_E_LOG ();
+
+
+  // ** EVOODOO EXTENSIONS **
+  if (!fullscreen)
+  {
+    grGlideInit ();
+    grSstSelect (0);
+  }
+  const char *extensions = grGetString (GR_EXTENSION);
+  if (!fullscreen)
+  {
+    grGlideShutdown ();
+
+    if (strstr (extensions, "EVOODOO"))
+      evoodoo = 1;
+    else
+      evoodoo = 0;
+
+    if (evoodoo)
+      InitGfx ();
+  }
+
+  if (strstr (extensions, "ROMNAME"))
+  {
+    char strSetRomName[] = "grSetRomName";
+    void (FX_CALL *grSetRomName)(char*);
+    grSetRomName = (void (FX_CALL *)(char*))grGetProcAddress (strSetRomName);
+    grSetRomName (name);
+  }
+  // **
+  return true;
+}
+
+EXPORT void CALL RomResumed(void)
+{
+#ifdef PAULSCODE
+  frameSkipper.start();
+#endif
+}
+
+/******************************************************************
+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
+*******************************************************************/
+bool no_dlist = true;
+EXPORT void CALL ShowCFB (void)
+{
+  no_dlist = true;
+  VLOG ("ShowCFB ()\n");
+}
+
+EXPORT void CALL SetRenderingCallback(void (*callback)(int))
+{
+  VLOG("CALL SetRenderingCallback (*)\n");
+    renderCallback = callback;
+}
+
+void drawViRegBG()
+{
+  LRDP("drawViRegBG\n");
+  const wxUint32 VIwidth = *gfx.VI_WIDTH_REG;
+  FB_TO_SCREEN_INFO fb_info;
+  fb_info.width  = VIwidth;
+  fb_info.height = (wxUint32)rdp.vi_height;
+  if (fb_info.height == 0)
+  {
+    LRDP("Image height = 0 - skipping\n");
+    return;
+  }
+  fb_info.ul_x = 0;
+
+  fb_info.lr_x = VIwidth - 1;
+  //  fb_info.lr_x = (wxUint32)rdp.vi_width - 1;
+  fb_info.ul_y = 0;
+  fb_info.lr_y = fb_info.height - 1;
+  fb_info.opaque = 1;
+  fb_info.addr = *gfx.VI_ORIGIN_REG;
+  fb_info.size = *gfx.VI_STATUS_REG & 3;
+  rdp.last_bg = fb_info.addr;
+
+  bool drawn = DrawFrameBufferToScreen(fb_info);
+  if (settings.hacks&hack_Lego && drawn)
+  {
+    rdp.updatescreen = 1;
+    newSwapBuffers ();
+    DrawFrameBufferToScreen(fb_info);
+  }
+}
+
+}
+
+void drawNoFullscreenMessage();
+
+void DrawFrameBuffer ()
+{
+  if (!fullscreen)
+  {
+    drawNoFullscreenMessage();
+  }
+  if (to_fullscreen)
+    GoToFullScreen();
+
+  if (fullscreen)
+  {
+    grDepthMask (FXTRUE);
+    grColorMask (FXTRUE, FXTRUE);
+    grBufferClear (0, 0, 0xFFFF);
+    drawViRegBG();
+  }
+}
+
+extern "C" {
+/******************************************************************
+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
+*******************************************************************/
+wxUint32 update_screen_count = 0;
+EXPORT void CALL UpdateScreen (void)
+{
+#ifdef PAULSCODE
+//printf("UpdateScreen()\n");
+  frameSkipper.update();
+#endif
+#ifdef LOG_KEY
+  if (CheckKeyPressed(G64_VK_SPACE, 0x0001))
+  {
+    LOG ("KEY!!!\n");
+  }
+#endif
+  char out_buf[128];
+  sprintf (out_buf, "UpdateScreen (). Origin: %08x, Old origin: %08x, width: %d\n", *gfx.VI_ORIGIN_REG, rdp.vi_org_reg, *gfx.VI_WIDTH_REG);
+  VLOG (out_buf);
+  LRDP(out_buf);
+
+  wxUint32 width = (*gfx.VI_WIDTH_REG) << 1;
+  if (fullscreen && (*gfx.VI_ORIGIN_REG  > width))
+    update_screen_count++;
+//TODO-PORT: wx times
+#ifdef FPS
+  // vertical interrupt has occurred, increment counter
+  vi_count ++;
+
+  // 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
+  //*
+  wxUint32 limit = (settings.hacks&hack_Lego) ? 15 : 30;
+#ifdef PAULSCODE0
+  if (frameSkipper.willSkipNext())
+       return;
+#endif
+#ifdef PAULSCODE
+//  if (!frameSkipper.hasSkipped())
+  if (!frameSkipper.willSkipNext())
+#endif
+  if ((settings.frame_buffer&fb_cpu_write_hack) && (update_screen_count > limit) && (rdp.last_bg == 0))
+  {
+    LRDP("DirectCPUWrite hack!\n");
+    update_screen_count = 0;
+    no_dlist = true;
+    ClearCache ();
+    UpdateScreen();
+    return;
+  }
+  //*/
+  //*
+  if( no_dlist )
+  {
+    if( *gfx.VI_ORIGIN_REG  > width )
+    {
+      ChangeSize ();
+      LRDP("ChangeSize done\n");
+#ifdef PAULSCODE
+         if (!frameSkipper.willSkipNext())
+#endif
+      DrawFrameBuffer();
+      LRDP("DrawFrameBuffer done\n");
+      rdp.updatescreen = 1;
+      newSwapBuffers ();
+    }
+    return;
+  }
+  //*/
+#ifdef PAULSCODE0
+  if (!frameSkipper.willSkipNext())
+#endif
+  if (settings.swapmode == 0)
+    newSwapBuffers ();
+}
+
+static void DrawWholeFrameBufferToScreen()
+{
+  static wxUint32 toScreenCI = 0;
+  if (rdp.ci_width < 200)
+    return;
+  if (rdp.cimg == toScreenCI)
+    return;
+  toScreenCI = rdp.cimg;
+  FB_TO_SCREEN_INFO fb_info;
+  fb_info.addr   = rdp.cimg;
+  fb_info.size   = rdp.ci_size;
+  fb_info.width  = rdp.ci_width;
+  fb_info.height = rdp.ci_height;
+  if (fb_info.height == 0)
+    return;
+  fb_info.ul_x = 0;
+  fb_info.lr_x = rdp.ci_width-1;
+  fb_info.ul_y = 0;
+  fb_info.lr_y = rdp.ci_height-1;
+  fb_info.opaque = 0;
+  DrawFrameBufferToScreen(fb_info);
+  if (!(settings.frame_buffer & fb_ref))
+    memset(gfx.RDRAM+rdp.cimg, 0, (rdp.ci_width*rdp.ci_height)<<rdp.ci_size>>1);
+}
+
+static void GetGammaTable()
+{
+  char strGetGammaTableExt[] = "grGetGammaTableExt";
+  void (FX_CALL *grGetGammaTableExt)(FxU32, FxU32*, FxU32*, FxU32*) =
+    (void (FX_CALL *)(FxU32, FxU32*, FxU32*, FxU32*))grGetProcAddress(strGetGammaTableExt);
+  if (grGetGammaTableExt)
+  {
+    voodoo.gamma_table_r = new FxU32[voodoo.gamma_table_size];
+    voodoo.gamma_table_g = new FxU32[voodoo.gamma_table_size];
+    voodoo.gamma_table_b = new FxU32[voodoo.gamma_table_size];
+    grGetGammaTableExt(voodoo.gamma_table_size, voodoo.gamma_table_r, voodoo.gamma_table_g, voodoo.gamma_table_b);
+  }
+}
+
+}
+wxUint32 curframe = 0;
+void newSwapBuffers()
+{
+#ifdef PAULSCODE
+//frameSkipper.newFrame();
+//bool skipped = false;
+//printf("newSwapBuffers()\n");
+bool skipped = frameSkipper.willSkipNext();
+//bool skipped = frameSkipper.hasSkipped();
+#endif
+  if (!rdp.updatescreen) {
+#ifdef PAULSCODE0
+    if (skipped) {
+      if (settings.frame_buffer & fb_read_back_to_screen2)
+        DrawWholeFrameBufferToScreen();
+      frameSkipper.newFrame();
+    }
+#endif
+    return;
+  }
+
+  rdp.updatescreen = 0;
+
+  LRDP("swapped\n");
+
+  // Allow access to the whole screen
+  if (fullscreen)
+  {
+    rdp.update |= UPDATE_SCISSOR | UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE;
+    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 (&ltime);
+          tm *cur_time = localtime (&ltime);
+
+          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 (&ltime);
+          tm *cur_time = localtime (&ltime);
+
+          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);
+      }
+    //hotkeys
+    if (CheckKeyPressed(G64_VK_BACK, 0x0001))
+    {
+      hotkey_info.hk_filtering = 100;
+      if (settings.filtering < 2)
+        settings.filtering++;
+      else
+        settings.filtering = 0;
+    }
+    if ((abs((int)(frame_count - curframe)) > 3 ) && CheckKeyPressed(G64_VK_ALT, 0x8000))  //alt +
+    {
+      if (CheckKeyPressed(G64_VK_B, 0x8000))  //b
+      {
+        hotkey_info.hk_motionblur = 100;
+        hotkey_info.hk_ref = 0;
+        curframe = frame_count;
+        settings.frame_buffer ^= fb_motionblur;
+      }
+      else if (CheckKeyPressed(G64_VK_V, 0x8000))  //v
+      {
+        hotkey_info.hk_ref = 100;
+        hotkey_info.hk_motionblur = 0;
+        curframe = frame_count;
+        settings.frame_buffer ^= fb_ref;
+      }
+    }
+    if (settings.buff_clear && (hotkey_info.hk_ref || hotkey_info.hk_motionblur || hotkey_info.hk_filtering))
+    {
+      set_message_combiner ();
+      char buf[256];
+      buf[0] = 0;
+      char * message = 0;
+      if (hotkey_info.hk_ref)
+      {
+        if (settings.frame_buffer & fb_ref)
+          message = strcat(buf, "FB READ ALWAYS: ON");
+        else
+          message = strcat(buf, "FB READ ALWAYS: OFF");
+        hotkey_info.hk_ref--;
+      }
+      if (hotkey_info.hk_motionblur)
+      {
+        if (settings.frame_buffer & fb_motionblur)
+          message = strcat(buf, "  MOTION BLUR: ON");
+        else
+          message = strcat(buf, "  MOTION BLUR: OFF");
+        hotkey_info.hk_motionblur--;
+      }
+      if (hotkey_info.hk_filtering)
+      {
+        switch (settings.filtering)
+        {
+        case 0:
+          message = strcat(buf, "  FILTERING MODE: AUTOMATIC");
+          break;
+        case 1:
+          message = strcat(buf, "  FILTERING MODE: FORCE BILINEAR");
+          break;
+        case 2:
+          message = strcat(buf, "  FILTERING MODE: FORCE POINT-SAMPLED");
+          break;
+        }
+        hotkey_info.hk_filtering--;
+      }
+      output (120.0f, (float)settings.res_y, 0, message, 0);
+    }
+  }
+    #ifdef OLDAPI
+  if (capture_screen)
+  {
+    //char path[256];
+    // Make the directory if it doesn't exist
+    if (!wxDirExists(capture_path))
+      wxMkdir(capture_path);
+    wxString path;
+    wxString romName = rdp.RomName;
+    romName.Replace(wxT(" "), wxT("_"), true);
+    romName.Replace(wxT(":"), wxT(";"), true);
+
+    for (int i=1; ; i++)
+    {
+      path = capture_path;
+      path += wxT("Glide64mk2_");
+      path += romName;
+      path += wxT("_");
+      if (i < 10)
+        path += wxT("0");
+      path << i << wxT(".") << ScreenShotFormats[settings.ssformat].extension;
+      if (!wxFileName::FileExists(path))
+        break;
+    }
+
+    const wxUint32 offset_x = (wxUint32)rdp.offset_x;
+    const wxUint32 offset_y = (wxUint32)rdp.offset_y;
+    const wxUint32 image_width = settings.scr_res_x - offset_x*2;
+    const wxUint32 image_height = settings.scr_res_y - offset_y*2;
+
+    GrLfbInfo_t info;
+    info.size = sizeof(GrLfbInfo_t);
+    if (grLfbLock (GR_LFB_READ_ONLY,
+      GR_BUFFER_BACKBUFFER,
+      GR_LFBWRITEMODE_565,
+      GR_ORIGIN_UPPER_LEFT,
+      FXFALSE,
+      &info))
+    {
+      wxUint8 *ssimg = (wxUint8*)malloc(image_width * image_height * 3); // will be free in wxImage destructor
+      int sspos = 0;
+      wxUint32 offset_src = info.strideInBytes * offset_y;
+
+      // Copy the screen
+      if (info.writeMode == GR_LFBWRITEMODE_8888)
+      {
+        wxUint32 col;
+        for (wxUint32 y = 0; y < image_height; y++)
+        {
+          wxUint32 *ptr = (wxUint32*)((wxUint8*)info.lfbPtr + offset_src);
+          ptr += offset_x;
+          for (wxUint32 x = 0; x < image_width; x++)
+          {
+            col = *(ptr++);
+            ssimg[sspos++] = (wxUint8)((col >> 16) & 0xFF);
+            ssimg[sspos++] = (wxUint8)((col >> 8) & 0xFF);
+            ssimg[sspos++] = (wxUint8)(col & 0xFF);
+          }
+          offset_src += info.strideInBytes;
+        }
+      }
+      else
+      {
+        wxUint16 col;
+        for (wxUint32 y = 0; y < image_height; y++)
+        {
+          wxUint16 *ptr = (wxUint16*)((wxUint8*)info.lfbPtr + offset_src);
+          ptr += offset_x;
+          for (wxUint32 x = 0; x < image_width; x++)
+          {
+            col = *(ptr++);
+            ssimg[sspos++] = (wxUint8)((float)(col >> 11) / 31.0f * 255.0f);
+            ssimg[sspos++] = (wxUint8)((float)((col >> 5) & 0x3F) / 63.0f * 255.0f);
+            ssimg[sspos++] = (wxUint8)((float)(col & 0x1F) / 31.0f * 255.0f);
+          }
+          offset_src += info.strideInBytes;
+        }
+      }
+      // Unlock the backbuffer
+      grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_BACKBUFFER);
+      wxImage screenshot(image_width, image_height, ssimg);
+      screenshot.SaveFile(path, ScreenShotFormats[settings.ssformat].type);
+      capture_screen = 0;
+    }
+  }
+    #endif
+
+  // Capture the screen if debug capture is set
+  if (_debugger.capture)
+  {
+    // Allocate the screen
+    _debugger.screen = new wxUint8 [(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));
+
+    wxUint32 offset_src=0, offset_dst=0;
+
+    // Copy the screen
+    for (wxUint32 y=0; y<settings.res_y; y++)
+    {
+      if (info.writeMode == GR_LFBWRITEMODE_8888)
+      {
+        wxUint32 *src = (wxUint32*)((wxUint8*)info.lfbPtr + offset_src);
+        wxUint16 *dst = (wxUint16*)(_debugger.screen + offset_dst);
+        wxUint8 r, g, b;
+        wxUint32 col;
+        for (unsigned int x = 0; x < settings.res_x; x++)
+        {
+          col = src[x];
+          r = (wxUint8)((col >> 19) & 0x1F);
+          g = (wxUint8)((col >> 10) & 0x3F);
+          b = (wxUint8)((col >> 3)  & 0x1F);
+          dst[x] = (r<<11)|(g<<5)|b;
+        }
+      }
+      else
+      {
+        memcpy (_debugger.screen + offset_dst, (wxUint8*)info.lfbPtr + offset_src, settings.res_x << 1);
+      }
+      offset_dst += settings.res_x << 1;
+      offset_src += info.strideInBytes;
+    }
+
+    // Unlock the backbuffer
+    grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_BACKBUFFER);
+  }
+
+  if (fullscreen && debugging)
+  {
+    debug_keys ();
+    debug_cacheviewer ();
+    debug_mouse ();
+  }
+
+#ifdef PAULSCODE
+  if (!skipped)
+#endif
+  if (settings.frame_buffer & fb_read_back_to_screen)
+    DrawWholeFrameBufferToScreen();
+
+  if (fullscreen)
+  {
+    if (fb_hwfbe_enabled && !(settings.hacks&hack_RE2) && !evoodoo)
+      grAuxBufferExt( GR_BUFFER_AUXBUFFER );
+#ifdef PAULSCODE
+       if (skipped)
+       {
+               vbo_resetcount();
+       } 
+       else
+#endif
+       {
+               grBufferSwap (settings.vsync);
+               fps_count ++;
+       }
+#ifdef PAULSCODE
+    if (!skipped)
+#endif
+    if (*gfx.VI_STATUS_REG&0x08) //gamma correction is used
+    {
+      if (!voodoo.gamma_correction)
+      {
+        if (voodoo.gamma_table_size && !voodoo.gamma_table_r)
+          GetGammaTable(); //save initial gamma tables
+        guGammaCorrectionRGB(2.0f, 2.0f, 2.0f); //with gamma=2.0 gamma table is the same, as in N64
+        voodoo.gamma_correction = 1;
+      }
+    }
+    else
+    {
+      if (voodoo.gamma_correction)
+      {
+        if (voodoo.gamma_table_r)
+          grLoadGammaTable(voodoo.gamma_table_size, voodoo.gamma_table_r, voodoo.gamma_table_g, voodoo.gamma_table_b);
+        else
+          guGammaCorrectionRGB(1.3f, 1.3f, 1.3f); //1.3f is default 3dfx gamma for everything but desktop
+        voodoo.gamma_correction = 0;
+      }
+    }
+  }
+
+  if (_debugger.capture)
+    debug_capture ();
+
+  if (fullscreen)
+  {
+#ifdef PAULSCODE0
+    if (!skipped)
+#endif
+    if  (debugging || settings.wireframe || settings.buff_clear || (settings.hacks&hack_PPL && settings.ucode == 6))
+    {
+      if (settings.hacks&hack_RE2 && fb_depth_render_enabled)
+        grDepthMask (FXFALSE);
+      else
+        grDepthMask (FXTRUE);
+      grBufferClear (0, 0, 0xFFFF);
+    }
+    /* //let the game to clear the buffers
+    else
+    {
+    grDepthMask (FXTRUE);
+    grColorMask (FXFALSE, FXFALSE);
+    grBufferClear (0, 0, 0xFFFF);
+    grColorMask (FXTRUE, FXTRUE);
+    }
+    */
+  }
+
+#ifdef PAULSCODE
+  if (!skipped)
+#endif
+  if (settings.frame_buffer & fb_read_back_to_screen2)
+    DrawWholeFrameBufferToScreen();
+
+  frame_count ++;
+#ifdef PAULSCODE
+       frameSkipper.newFrame();
+#endif
+
+  // Open/close debugger?
+  if (CheckKeyPressed(G64_VK_SCROLL, 0x0001))
+  {
+    if (!debugging)
+    {
+      //if (settings.scr_res_x == 1024 && settings.scr_res_y == 768)
+      {
+        debugging = 1;
+
+        // Recalculate screen size, don't resize screen
+        settings.res_x = (wxUint32)(settings.scr_res_x * 0.625f);
+        settings.res_y = (wxUint32)(settings.scr_res_y * 0.625f);
+
+        ChangeSize ();
+      }
+    } 
+    else
+    {
+      debugging = 0;
+
+      settings.res_x = settings.scr_res_x;
+      settings.res_y = settings.scr_res_y;
+
+      ChangeSize ();
+    }
+  }
+
+  // Debug capture?
+  if (/*fullscreen && */debugging && CheckKeyPressed(G64_VK_INSERT, 0x0001))
+  {
+    _debugger.capture = 1;
+  }
+}
+
+extern "C"
+{
+
+/******************************************************************
+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 WINPROC_OVERRIDE
+LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+  switch (msg)
+  {
+  case WM_ACTIVATEAPP:
+    if (wParam == TRUE && !fullscreen) rdp.window_changed = TRUE;
+    break;
+  case WM_PAINT:
+    if (!fullscreen) rdp.window_changed = TRUE;
+    break;
+
+    /*    case WM_DESTROY:
+    SetWindowLong (gfx.hWnd, GWL_WNDPROC, (long)oldWndProc);
+    break;*/
+  }
+
+  return CallWindowProc(oldWndProc, hwnd, msg, wParam, lParam);
+}
+#endif
+
+}
+
+int CheckKeyPressed(int key, int mask)
+{
+static Glide64Keys g64Keys;
+  if (settings.use_hotkeys == 0)
+    return 0;
+#ifdef __WINDOWS__
+  return (GetAsyncKeyState(g64Keys[key]) & mask);
+#else
+  if (grKeyPressed)
+    return grKeyPressed(g64Keys[key]);
+#endif
+  return 0;
+}
+
+
+#ifdef ALTTAB_FIX
+int k_ctl=0, k_alt=0, k_del=0;
+
+LRESULT CALLBACK LowLevelKeyboardProc(int nCode,
+                                      WPARAM wParam, LPARAM lParam)
+{
+  if (!fullscreen) return CallNextHookEx(NULL, nCode, wParam, lParam);
+
+  int TabKey = FALSE;
+
+  PKBDLLHOOKSTRUCT p;
+
+  if (nCode == HC_ACTION)
+  {
+    switch (wParam) {
+case WM_KEYUP:    case WM_SYSKEYUP:
+  p = (PKBDLLHOOKSTRUCT) lParam;
+  if (p->vkCode == 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
+
+//
+// DllMain - called when the DLL is loaded, use this to get the DLL's instance
+//
+#ifdef OLDAPI
+class wxDLLApp : public wxApp
+{
+public:
+  virtual bool OnInit();
+};
+
+IMPLEMENT_APP_NO_MAIN(wxDLLApp)
+
+bool wxDLLApp::OnInit()
+{
+/*  if (mutexProcessDList == NULL)
+    mutexProcessDList = new wxMutex(wxMUTEX_DEFAULT);*/
+  wxImage::AddHandler(new wxPNGHandler);
+  wxImage::AddHandler(new wxJPEGHandler);
+  return true;
+}
+
+#ifndef __WINDOWS__
+int __attribute__ ((constructor)) DllLoad(void);
+int __attribute__ ((destructor)) DllUnload(void);
+#endif
+
+// Called when the library is loaded and before dlopen() returns
+int DllLoad(void)
+{
+    int argc = 0;
+    char **argv = NULL;
+    wxEntryStart(argc, argv);
+    if (wxTheApp)
+      return wxTheApp->CallOnInit() ? TRUE : FALSE;
+    return 0;
+}
+
+// Called when the library is unloaded and before dlclose() returns
+int DllUnload(void)
+{
+    if ( wxTheApp )
+      wxTheApp->OnExit();
+    wxEntryCleanup();
+    return TRUE;
+}
+
+#ifdef __WINDOWS__
+extern "C" int WINAPI DllMain (HINSTANCE hinstDLL,
+                     wxUint32 fdwReason,
+                     LPVOID lpReserved)
+{
+  sprintf (out_buf, "DllMain (%08lx - %d)\n", hinstDLL, fdwReason);
+  LOG (out_buf);
+
+  if (fdwReason == DLL_PROCESS_ATTACH)
+  {
+    wxSetInstance(hinstDLL);
+    return DllLoad();
+  }
+  else if (fdwReason == DLL_PROCESS_DETACH)
+  {
+    if (GFXWindow != NULL)
+      GFXWindow->SetHWND(NULL);
+    return DllUnload();
+  }
+  return TRUE;
+}
+
+void CALL ReadScreen(void **dest, int *width, int *height)
+{
+  *width = settings.res_x;
+  *height = settings.res_y;
+  wxUint8 * buff = (wxUint8*)malloc(settings.res_x * settings.res_y * 3);
+  wxUint8 * line = buff;
+  *dest = (void*)buff;
+
+  if (!fullscreen)
+  {
+    for (wxUint32 y=0; y<settings.res_y; y++)
+    {
+      for (wxUint32 x=0; x<settings.res_x; x++)
+      {
+        line[x*3] = 0x20;
+        line[x*3+1] = 0x7f;
+        line[x*3+2] = 0x40;
+      }
+    }
+    LOG ("ReadScreen. not in the fullscreen!\n");
+    return;
+  }
+
+  GrLfbInfo_t info;
+  info.size = sizeof(GrLfbInfo_t);
+  if (grLfbLock (GR_LFB_READ_ONLY,
+    GR_BUFFER_FRONTBUFFER,
+    GR_LFBWRITEMODE_565,
+    GR_ORIGIN_UPPER_LEFT,
+    FXFALSE,
+    &info))
+  {
+    wxUint32 offset_src=info.strideInBytes*(settings.scr_res_y-1);
+
+    // Copy the screen
+    wxUint8 r, g, b;
+    if (info.writeMode == GR_LFBWRITEMODE_8888)
+    {
+      wxUint32 col;
+      for (wxUint32 y=0; y<settings.res_y; y++)
+      {
+        wxUint32 *ptr = (wxUint32*)((wxUint8*)info.lfbPtr + offset_src);
+        for (wxUint32 x=0; x<settings.res_x; x++)
+        {
+          col = *(ptr++);
+          r = (wxUint8)((col >> 16) & 0xFF);
+          g = (wxUint8)((col >> 8) & 0xFF);
+          b = (wxUint8)(col & 0xFF);
+          line[x*3] = b;
+          line[x*3+1] = g;
+          line[x*3+2] = r;
+        }
+        line += settings.res_x * 3;
+        offset_src -= info.strideInBytes;
+      }
+    }
+    else
+    {
+      wxUint16 col;
+      for (wxUint32 y=0; y<settings.res_y; y++)
+      {
+        wxUint16 *ptr = (wxUint16*)((wxUint8*)info.lfbPtr + offset_src);
+        for (wxUint32 x=0; x<settings.res_x; x++)
+        {
+          col = *(ptr++);
+          r = (wxUint8)((float)(col >> 11) / 31.0f * 255.0f);
+          g = (wxUint8)((float)((col >> 5) & 0x3F) / 63.0f * 255.0f);
+          b = (wxUint8)((float)(col & 0x1F) / 31.0f * 255.0f);
+          line[x*3] = b;
+          line[x*3+1] = g;
+          line[x*3+2] = r;
+        }
+        line += settings.res_x * 3;
+        offset_src -= info.strideInBytes;
+      }
+    }
+    // Unlock the frontbuffer
+    grLfbUnlock (GR_LFB_READ_ONLY, GR_BUFFER_FRONTBUFFER);
+  }
+  LOG ("ReadScreen. Success.\n");
+}
+#endif
+#endif
diff --git a/source/gles2glide64/src/Glide64/MiClWr16b.h b/source/gles2glide64/src/Glide64/MiClWr16b.h
new file mode 100644 (file)
index 0000000..8c96ca6
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+static inline void mirror16bS(uint8_t *tex, uint8_t *start, int width, int height, int mask, int line, int full, int count)
+{
+  uint16_t *v8;
+  int v9;
+  int v10;
+
+  v8 = (uint16_t *)start;
+  v9 = height;
+  do
+  {
+    v10 = 0;
+    do
+    {
+      if ( width & (v10 + width) )
+      {
+        *v8 = *(uint16_t *)(&tex[mask] - (mask & 2 * v10));
+        ++v8;
+      }
+      else
+      {
+        *v8 = *(uint16_t *)&tex[mask & 2 * v10];
+        ++v8;
+      }
+      ++v10;
+    }
+    while ( v10 != count );
+    v8 = (uint16_t *)((char *)v8 + line);
+    tex += full;
+    --v9;
+  }
+  while ( v9 );
+}
+
+static inline void wrap16bS(uint8_t *tex, uint8_t *start, int height, int mask, int line, int full, int count)
+{
+  uint32_t *v7;
+  int v8;
+  int v9;
+
+  v7 = (uint32_t *)start;
+  v8 = height;
+  do
+  {
+    v9 = 0;
+    do
+    {
+      *v7 = *(uint32_t *)&tex[4 * (mask & v9)];
+      ++v7;
+      ++v9;
+    }
+    while ( v9 != count );
+    v7 = (uint32_t *)((char *)v7 + line);
+    tex += full;
+    --v8;
+  }
+  while ( v8 );
+}
+
+static inline void clamp16bS(uint8_t *tex, uint8_t *constant, int height, int line, int full, int count)
+{
+  uint16_t *v6;
+  uint16_t *v7;
+  int v8;
+  uint16_t v9;
+  int v10;
+
+  v6 = (uint16_t *)constant;
+  v7 = (uint16_t *)tex;
+  v8 = height;
+  do
+  {
+    v9 = *v6;
+    v10 = count;
+    do
+    {
+      *v7 = v9;
+      ++v7;
+      --v10;
+    }
+    while ( v10 );
+    v6 = (uint16_t *)((char *)v6 + full);
+    v7 = (uint16_t *)((char *)v7 + line);
+    --v8;
+  }
+  while ( v8 );
+}
+
+//****************************************************************
+// 16-bit Horizontal Mirror
+#include <stdint.h>
+#include <string.h>
+typedef uint32_t wxUint32;
+
+void Mirror16bS (unsigned char * tex, wxUint32 mask, wxUint32 max_width, wxUint32 real_width, wxUint32 height)
+{
+  if (mask == 0) return;
+
+  wxUint32 mask_width = (1 << mask);
+  wxUint32 mask_mask = (mask_width-1) << 1;
+  if (mask_width >= max_width) return;
+  int count = max_width - mask_width;
+  if (count <= 0) return;
+  int line_full = real_width << 1;
+  int line = line_full - (count << 1);
+  if (line < 0) return;
+  unsigned char *start = tex + (mask_width << 1);
+  mirror16bS (tex, start, mask_width, height, mask_mask, line, line_full, count);
+}
+
+//****************************************************************
+// 16-bit Horizontal Wrap (like mirror)
+
+void Wrap16bS (unsigned char * tex, wxUint32 mask, wxUint32 max_width, wxUint32 real_width, wxUint32 height)
+{
+  if (mask == 0) return;
+
+  wxUint32 mask_width = (1 << mask);
+  wxUint32 mask_mask = (mask_width-1) >> 1;
+  if (mask_width >= max_width) return;
+  int count = (max_width - mask_width) >> 1;
+  if (count <= 0) return;
+  int line_full = real_width << 1;
+  int line = line_full - (count << 2);
+  if (line < 0) return;
+  unsigned char * start = tex + (mask_width << 1);
+  wrap16bS (tex, start, height, mask_mask, line, line_full, count);
+}
+
+//****************************************************************
+// 16-bit Horizontal Clamp
+
+void Clamp16bS (unsigned char * tex, wxUint32 width, wxUint32 clamp_to, wxUint32 real_width, wxUint32 real_height)
+{
+  if (real_width <= width) return;
+
+  unsigned char * dest = tex + (width << 1);
+  unsigned char * constant = dest-2;
+  int count = clamp_to - width;
+
+  int line_full = real_width << 1;
+  int line = width << 1;
+
+  clamp16bS (dest, constant, real_height, line, line_full, count);
+}
+
+//****************************************************************
+// 16-bit Vertical Mirror
+
+void Mirror16bT (unsigned char * tex, wxUint32 mask, wxUint32 max_height, wxUint32 real_width)
+{
+  if (mask == 0) return;
+
+  wxUint32 mask_height = (1 << mask);
+  wxUint32 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 (wxUint32 y=mask_height; y<max_height; y++)
+  {
+    if (y & mask_height)
+    {
+      // mirrored
+      memcpy ((void*)dst, (void*)(tex + (mask_mask - (y & mask_mask)) * line_full), line_full);
+    }
+    else
+    {
+      // not mirrored
+      memcpy ((void*)dst, (void*)(tex + (y & mask_mask) * line_full), line_full);
+    }
+
+    dst += line_full;
+  }
+}
+
+//****************************************************************
+// 16-bit Vertical Wrap
+
+void Wrap16bT (unsigned char * tex, wxUint32 mask, wxUint32 max_height, wxUint32 real_width)
+{
+  if (mask == 0) return;
+
+  wxUint32 mask_height = (1 << mask);
+  wxUint32 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 (wxUint32 y=mask_height; y<max_height; y++)
+  {
+    // not mirrored
+    memcpy ((void*)dst, (void*)(tex + (y & mask_mask) * line_full), line_full);
+
+    dst += line_full;
+  }
+}
+
+//****************************************************************
+// 16-bit Vertical Clamp
+
+void Clamp16bT (unsigned char * tex, wxUint32 height, wxUint32 real_width, wxUint32 clamp_to)
+{
+  int line_full = real_width << 1;
+  unsigned char * dst = tex + height * line_full;
+  unsigned char * const_line = dst - line_full;
+
+  for (wxUint32 y=height; y<clamp_to; y++)
+  {
+    memcpy ((void*)dst, (void*)const_line, line_full);
+    dst += line_full;
+  }
+}
diff --git a/source/gles2glide64/src/Glide64/MiClWr32b.h b/source/gles2glide64/src/Glide64/MiClWr32b.h
new file mode 100644 (file)
index 0000000..dedf018
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+//
+// Created by Gonetz, 2007
+//
+//****************************************************************
+
+static inline void mirror32bS(uint8_t *tex, uint8_t *start, int width, int height, int mask, int line, int full, int count)
+{
+  uint32_t *v8;
+  int v9;
+  int v10;
+
+  v8 = (uint32_t *)start;
+  v9 = height;
+  do
+  {
+    v10 = 0;
+    do
+    {
+      if ( width & (v10 + width) )
+      {
+        *v8 = *(uint32_t *)(&tex[mask] - (mask & 4 * v10));
+        ++v8;
+      }
+      else
+      {
+        *v8 = *(uint32_t *)&tex[mask & 4 * v10];
+        ++v8;
+      }
+      ++v10;
+    }
+    while ( v10 != count );
+    v8 = (uint32_t *)((char *)v8 + line);
+    tex += full;
+    --v9;
+  }
+  while ( v9 );
+}
+
+static inline void wrap32bS(uint8_t *tex, uint8_t *start, int height, int mask, int line, int full, int count)
+{
+  uint32_t *v7;
+  int v8;
+  int v9;
+
+  v7 = (uint32_t *)start;
+  v8 = height;
+  do
+  {
+    v9 = 0;
+    do
+    {
+      *v7 = *(uint32_t *)&tex[4 * (mask & v9)];
+      ++v7;
+      ++v9;
+    }
+    while ( v9 != count );
+    v7 = (uint32_t *)((char *)v7 + line);
+    tex += full;
+    --v8;
+  }
+  while ( v8 );
+}
+
+static inline void clamp32bS(uint8_t *tex, uint8_t *constant, int height, int line, int full, int count)
+{
+  uint32_t *v6;
+  uint32_t *v7;
+  int v8;
+  uint32_t v9;
+  int v10;
+
+  v6 = (uint32_t *)constant;
+  v7 = (uint32_t *)tex;
+  v8 = height;
+  do
+  {
+    v9 = *v6;
+    v10 = count;
+    do
+    {
+      *v7 = v9;
+      ++v7;
+      --v10;
+    }
+    while ( v10 );
+    v6 = (uint32_t *)((char *)v6 + full);
+    v7 = (uint32_t *)((char *)v7 + line);
+    --v8;
+  }
+  while ( v8 );
+}
+
+//****************************************************************
+// 32-bit Horizontal Mirror
+
+void Mirror32bS (unsigned char * tex, wxUint32 mask, wxUint32 max_width, wxUint32 real_width, wxUint32 height)
+{
+       if (mask == 0) return;
+
+       wxUint32 mask_width = (1 << mask);
+       wxUint32 mask_mask = (mask_width-1) << 2;
+       if (mask_width >= max_width) return;
+       int count = max_width - mask_width;
+       if (count <= 0) return;
+       int line_full = real_width << 2;
+       int line = line_full - (count << 2);
+       if (line < 0) return;
+       unsigned char * start = tex + (mask_width << 2);
+       mirror32bS (tex, start, mask_width, height, mask_mask, line, line_full, count);
+}
+
+//****************************************************************
+// 32-bit Horizontal Wrap 
+
+void Wrap32bS (unsigned char * tex, wxUint32 mask, wxUint32 max_width, wxUint32 real_width, wxUint32 height)
+{
+       if (mask == 0) return;
+
+       wxUint32 mask_width = (1 << mask);
+       wxUint32 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 << 2;
+       int line = line_full - (count << 2);
+       if (line < 0) return;
+       unsigned char * start = tex + (mask_width << 2);
+       wrap32bS (tex, start, height, mask_mask, line, line_full, count);
+}
+
+//****************************************************************
+// 32-bit Horizontal Clamp
+
+void Clamp32bS (unsigned char * tex, wxUint32 width, wxUint32 clamp_to, wxUint32 real_width, wxUint32 real_height)
+{
+       if (real_width <= width) return;
+
+       unsigned char *dest = tex + (width << 2);
+       unsigned char *constant = dest-4;
+       
+       int count = clamp_to - width;
+       
+       int line_full = real_width << 2;
+       int line = width << 2;
+       clamp32bS (dest, constant, real_height, line, line_full, count);
+}
+
+//****************************************************************
+// 32-bit Vertical Mirror
+
+void Mirror32bT (unsigned char * tex, wxUint32 mask, wxUint32 max_height, wxUint32 real_width)
+{
+       if (mask == 0) return;
+
+       wxUint32 mask_height = (1 << mask);
+       wxUint32 mask_mask = mask_height-1;
+       if (max_height <= mask_height) return;
+       int line_full = real_width << 2;
+
+       unsigned char *dst = tex + mask_height * line_full;
+
+       for (wxUint32 y=mask_height; y<max_height; y++)
+       {
+               if (y & mask_height)
+               {
+                       // mirrored
+                       memcpy ((void*)dst, (void*)(tex + (mask_mask - (y & mask_mask)) * line_full), line_full);
+               }
+               else
+               {
+                       // not mirrored
+                       memcpy ((void*)dst, (void*)(tex + (y & mask_mask) * line_full), line_full);
+               }
+
+               dst += line_full;
+       }
+}
+
+//****************************************************************
+// 32-bit Vertical Wrap
+
+void Wrap32bT (unsigned char * tex, wxUint32 mask, wxUint32 max_height, wxUint32 real_width)
+{
+       if (mask == 0) return;
+
+       wxUint32 mask_height = (1 << mask);
+       wxUint32 mask_mask = mask_height-1;
+       if (max_height <= mask_height) return;
+  int line_full = real_width << 2;
+
+       unsigned char *dst = tex + mask_height * line_full;
+
+       for (wxUint32 y=mask_height; y<max_height; y++)
+       {
+               // not mirrored
+               memcpy ((void*)dst, (void*)(tex + (y & mask_mask) * (line_full>>2)), (line_full>>2));
+
+               dst += line_full;
+       }
+}
+
+//****************************************************************
+// 32-bit Vertical Clamp
+
+void Clamp32bT (unsigned char * tex, wxUint32 height, wxUint32 real_width, wxUint32 clamp_to)
+{
+       int line_full = real_width << 2;
+       unsigned char *dst = tex + height * line_full;
+       unsigned char *const_line = dst - line_full;
+
+       for (wxUint32 y=height; y<clamp_to; y++)
+       {
+               memcpy ((void*)dst, (void*)const_line, line_full);
+               dst += line_full;
+       }
+}
diff --git a/source/gles2glide64/src/Glide64/MiClWr8b.h b/source/gles2glide64/src/Glide64/MiClWr8b.h
new file mode 100644 (file)
index 0000000..3513074
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+//****************************************************************
+// 8-bit Horizontal Mirror
+
+static inline void mirror8bS(uint8_t *tex, uint8_t *start, int width, int height, int mask, int line, int full, int count)
+{
+  uint8_t *v8;
+  int v9;
+  int v10;
+
+  v8 = start;
+  v9 = height;
+  do
+  {
+    v10 = 0;
+    do
+    {
+      if ( width & (v10 + width) )
+        *v8++ = *(&tex[mask] - (mask & v10));
+      else
+        *v8++ = tex[mask & v10];
+      ++v10;
+    }
+    while ( v10 != count );
+    v8 += line;
+    tex += full;
+    --v9;
+  }
+  while ( v9 );
+}
+
+static inline void wrap8bS(uint8_t *tex, uint8_t *start, int height, int mask, int line, int full, int count)
+{
+  uint32_t *v7;
+  int v8;
+  int v9;
+
+  v7 = (uint32_t *)start;
+  v8 = height;
+  do
+  {
+    v9 = 0;
+    do
+    {
+      *v7 = *(uint32_t *)&tex[4 * (mask & v9)];
+      ++v7;
+      ++v9;
+    }
+    while ( v9 != count );
+    v7 = (uint32_t *)((char *)v7 + line);
+    tex += full;
+    --v8;
+  }
+  while ( v8 );
+}
+
+static inline void clamp8bS(uint8_t *tex, uint8_t *constant, int height, int line, int full, int count)
+{
+  uint8_t *v6;
+  uint8_t *v7;
+  int v8;
+  uint8_t v9;
+  int v10;
+
+  v6 = constant;
+  v7 = tex;
+  v8 = height;
+  do
+  {
+    v9 = *v6;
+    v10 = count;
+    do
+    {
+      *v7++ = v9;
+      --v10;
+    }
+    while ( v10 );
+    v6 += full;
+    v7 += line;
+    --v8;
+  }
+  while ( v8 );
+}
+
+void Mirror8bS (unsigned char * tex, wxUint32 mask, wxUint32 max_width, wxUint32 real_width, wxUint32 height)
+{
+  if (mask == 0) return;
+
+  wxUint32 mask_width = (1 << mask);
+  wxUint32 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);
+  mirror8bS (tex, start, mask_width, height, mask_mask, line, line_full, count);
+}
+
+//****************************************************************
+// 8-bit Horizontal Wrap (like mirror) ** UNTESTED **
+
+
+void Wrap8bS (unsigned char * tex, wxUint32 mask, wxUint32 max_width, wxUint32 real_width, wxUint32 height)
+{
+  if (mask == 0) return;
+
+  wxUint32 mask_width = (1 << mask);
+  wxUint32 mask_mask = (mask_width-1) >> 2;
+  if (mask_width >= max_width) return;
+  int count = (max_width - mask_width) >> 2;
+  if (count <= 0) return;
+  int line_full = real_width;
+  int line = line_full - (count << 2);
+  if (line < 0) return;
+  unsigned char * start = tex + (mask_width);
+  wrap8bS (tex, start, height, mask_mask, line, line_full, count);
+}
+
+//****************************************************************
+// 8-bit Horizontal Clamp
+
+
+void Clamp8bS (unsigned char * tex, wxUint32 width, wxUint32 clamp_to, wxUint32 real_width, wxUint32 real_height)
+{
+  if (real_width <= width) return;
+
+  unsigned char * dest = tex + (width);
+  unsigned char * constant = dest-1;
+  int count = clamp_to - width;
+
+  int line_full = real_width;
+  int line = width;
+  clamp8bS (dest, constant, real_height, line, line_full, count);
+}
+
+//****************************************************************
+// 8-bit Vertical Mirror
+
+void Mirror8bT (unsigned char * tex, wxUint32 mask, wxUint32 max_height, wxUint32 real_width)
+{
+  if (mask == 0) return;
+
+  wxUint32 mask_height = (1 << mask);
+  wxUint32 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 (wxUint32 y=mask_height; y<max_height; y++)
+  {
+    if (y & mask_height)
+    {
+      // mirrored
+      memcpy ((void*)dst, (void*)(tex + (mask_mask - (y & mask_mask)) * line_full), line_full);
+    }
+    else
+    {
+      // not mirrored
+      memcpy ((void*)dst, (void*)(tex + (y & mask_mask) * line_full), line_full);
+    }
+
+    dst += line_full;
+  }
+}
+
+//****************************************************************
+// 8-bit Vertical Wrap
+
+void Wrap8bT (unsigned char * tex, wxUint32 mask, wxUint32 max_height, wxUint32 real_width)
+{
+  if (mask == 0) return;
+
+  wxUint32 mask_height = (1 << mask);
+  wxUint32 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 (wxUint32 y=mask_height; y<max_height; y++)
+  {
+    // not mirrored
+    memcpy ((void*)dst, (void*)(tex + (y & mask_mask) * line_full), line_full);
+
+    dst += line_full;
+  }
+}
+
+//****************************************************************
+// 8-bit Vertical Clamp
+
+void Clamp8bT (unsigned char * tex, wxUint32 height, wxUint32 real_width, wxUint32 clamp_to)
+{
+  int line_full = real_width;
+  unsigned char * dst = tex + height * line_full;
+  unsigned char * const_line = dst - line_full;
+
+  for (wxUint32 y=height; y<clamp_to; y++)
+  {
+    memcpy ((void*)dst, (void*)const_line, line_full);
+    dst += line_full;
+  }
+}
+
diff --git a/source/gles2glide64/src/Glide64/TexBuffer.cpp b/source/gles2glide64/src/Glide64/TexBuffer.cpp
new file mode 100755 (executable)
index 0000000..62a1fbb
--- /dev/null
@@ -0,0 +1,765 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+//
+// Hardware frame buffer emulation
+// Dec 2003 created by Gonetz
+//
+//****************************************************************
+
+#include "Gfx_1.3.h"
+#include "TexBuffer.h"
+#include "CRC.h"
+
+//#include "ticks.h"
+
+static TBUFF_COLOR_IMAGE * AllocateTextureBuffer(COLOR_IMAGE & cimage)
+{
+  TBUFF_COLOR_IMAGE texbuf;
+  texbuf.addr = cimage.addr;
+  texbuf.end_addr = cimage.addr + ((cimage.width*cimage.height)<<cimage.size>>1);
+  texbuf.width = cimage.width;
+  texbuf.height = cimage.height;
+  texbuf.format = cimage.format;
+  texbuf.size = cimage.size;
+  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;
+//  texbuf.scr_height = texbuf.height * rdp.scale_y;
+
+  wxUint16 max_size = max((wxUint16)texbuf.scr_width, (wxUint16)texbuf.scr_height);
+  if (max_size > voodoo.max_tex_size) //texture size is too large
+    return 0;
+  wxUint32 tex_size;
+  //calculate LOD
+  switch ((max_size-1) >> 6)
+  {
+  case 0:
+    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;
+
+  texbuf.lr_u = 256.0f * texbuf.scr_width / (float)tex_size;// + 1.0f;
+  texbuf.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.u_scale = texbuf.lr_u / (float)(texbuf.width);
+  texbuf.v_scale = texbuf.lr_v / (float)(texbuf.height);
+  texbuf.cache = 0;
+  texbuf.crc = 0;
+  texbuf.t_mem = 0;
+
+  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, texbuf.lr_u, texbuf.lr_v, texbuf.u_scale, texbuf.v_scale);
+
+  wxUint32 required = grTexCalcMemRequired(texbuf.info.smallLodLog2, texbuf.info.largeLodLog2,
+    texbuf.info.aspectRatioLog2, texbuf.info.format);
+  //find free space
+  for (int i = 0; i < voodoo.num_tmu; i++)
+  {
+    wxUint32 available = 0;
+    wxUint32 top = 0;
+    if (rdp.texbufs[i].count)
+    {
+      TBUFF_COLOR_IMAGE & t = rdp.texbufs[i].images[rdp.texbufs[i].count - 1];
+      if (rdp.read_whole_frame || rdp.motionblur)
+      {
+        if ((cimage.status == ci_aux) && (rdp.cur_tex_buf == i))
+        {
+          top = 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 = 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;
+    }
+    if (available >= required)
+    {
+      rdp.texbufs[i].count++;
+      rdp.texbufs[i].clear_allowed = FALSE;
+      texbuf.tex_addr = top;
+      rdp.cur_tex_buf = i;
+      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
+    return 0;
+  rdp.cur_tex_buf ^= 1;
+  rdp.texbufs[rdp.cur_tex_buf].count = 1;
+  rdp.texbufs[rdp.cur_tex_buf].clear_allowed = FALSE;
+  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]);
+}
+
+int OpenTextureBuffer(COLOR_IMAGE & cimage)
+{
+//printf("OpenTextureBuffer. cur_tex_buf: %d, addr: %08lx, width: %d, height: %d\n", rdp.cur_tex_buf, cimage.addr, cimage.width, cimage.height);
+//unsigned int ticks = ticksGetTicks();
+  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;
+
+  int found = FALSE, search = TRUE;
+  TBUFF_COLOR_IMAGE *texbuf = 0;
+  wxUint32 addr = cimage.addr;
+  if ((settings.hacks&hack_Banjo2) && cimage.status == ci_copy_self)
+    addr = rdp.frame_buffers[rdp.copy_ci_index].addr;
+  wxUint32 end_addr = addr + ((cimage.width*cimage.height)<<cimage.size>>1);
+  if (rdp.motionblur)
+  {
+//    if (cimage.format != 0)
+//      return FALSE;
+    search = FALSE;
+  }
+  if (rdp.read_whole_frame)
+  {
+    if (settings.hacks&hack_PMario) //motion blur effects in Paper Mario
+    {
+      rdp.cur_tex_buf = rdp.acc_tex_buf;
+      FRDP("\nread_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)
+  {
+//printf("search ! (%i) : ", voodoo.num_tmu);
+    for (int i = 0; (i < voodoo.num_tmu) && !found; i++)
+    {
+//printf("[%i] ", rdp.texbufs[i].count);
+      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 = (wxUint16)cimage.format;
+          if ((cimage.format != 0))
+            texbuf->info.format = GR_TEXFMT_ALPHA_INTENSITY_88;
+          else
+            texbuf->info.format = GR_TEXFMT_RGB_565;
+          texbuf->crc = 0;
+          texbuf->t_mem = 0;
+          texbuf->tile = 0;
+          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
+          {
+                       grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
+            grTextureBufferExt( texbuf->tmu, texbuf->tex_addr, texbuf->info.smallLodLog2, texbuf->info.largeLodLog2,
+              texbuf->info.aspectRatioLog2, texbuf->info.format, GR_MIPMAPLEVELMASK_BOTH );
+            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(TBUFF_COLOR_IMAGE)*(rdp.texbufs[i].count-j));
+          }
+        }
+      }
+    }
+  }
+  else
+  {
+    LRDP("  not searched");
+  }
+
+  if (!found)
+  {
+    LRDP("  not found");
+    texbuf = AllocateTextureBuffer(cimage);
+//printf("  not found\n");
+  }
+  else
+  {
+    LRDP("  found");
+//printf("  found\n");
+  }
+
+  if (!texbuf)
+  {
+    LRDP("  KO\n");
+    return FALSE;
+  }
+
+//unsigned int tticks=ticksGetTicks();
+  rdp.acc_tex_buf = rdp.cur_tex_buf;
+  rdp.cur_image = texbuf;
+  grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
+  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 );
+  ///*
+//printf("mesured %u ms\n", ticksGetTicks()-tticks);
+  if (rdp.cur_image->clear && (settings.frame_buffer&fb_hwfbe_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);
+//printf("  time = %u ms, texaddr: %08x, tex_width: %d, tex_height: %d, cur_tex_buf: %d, texformat: %d, motionblur: %d\n", ticksGetTicks()-ticks,  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);
+  if (!rdp.offset_x_bak)
+  {
+    rdp.offset_x_bak = rdp.offset_x;
+    rdp.offset_x = 0;
+  }
+  if (!rdp.offset_y_bak)
+  {
+    rdp.offset_y_bak = rdp.offset_y;
+    rdp.offset_y = 0;
+  }
+  rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
+  return TRUE;
+}
+
+static GrTextureFormat_t TexBufSetupCombiner(int force_rgb = FALSE)
+{
+  grColorCombine( GR_COMBINE_FUNCTION_SCALE_OTHER,
+    GR_COMBINE_FACTOR_ONE,
+    GR_COMBINE_LOCAL_NONE,
+    GR_COMBINE_OTHER_TEXTURE,
+//    GR_COMBINE_OTHER_CONSTANT,
+    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_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.tbuff_tex) ? rdp.tbuff_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.tbuff_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;
+}
+
+int CloseTextureBuffer(int draw)
+{
+  if (!fullscreen || !rdp.cur_image)
+  {
+    LRDP("CloseTextureBuffer KO\n");
+    return FALSE;
+  }
+  grRenderBuffer( GR_BUFFER_BACKBUFFER );
+  rdp.offset_x = rdp.offset_x_bak;
+  rdp.offset_y = rdp.offset_y_bak;
+  rdp.offset_x_bak = rdp.offset_y_bak = 0;
+  rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
+  if (!draw)
+  {
+    LRDP("CloseTextureBuffer no draw, OK\n");
+    rdp.cur_image = 0;
+    return TRUE;
+  }
+  rdp.tbuff_tex = rdp.cur_image;
+  rdp.cur_image = 0;
+  rdp.tbuff_tex->info.format = TexBufSetupCombiner();
+  float zero = 0.0f;
+  float ul_x = rdp.offset_x;
+  float ul_y = rdp.offset_y;
+  float lr_x = rdp.tbuff_tex->scr_width + rdp.offset_x;
+  float lr_y = rdp.tbuff_tex->scr_height + rdp.offset_y;
+  float lr_u = rdp.tbuff_tex->lr_u;
+  float lr_v = rdp.tbuff_tex->lr_v;
+  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, zero, zero, zero, zero, {zero, zero, zero, zero} },
+    { lr_x, ul_y, 1, 1, lr_u, zero, lr_u, zero, {lr_u, zero, lr_u, zero} },
+    { ul_x, lr_y, 1, 1, zero, lr_v, zero, lr_v, {zero, lr_v, zero, lr_v} },
+    { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
+  };
+
+  grTexSource( rdp.tbuff_tex->tmu, rdp.tbuff_tex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(rdp.tbuff_tex->info) );
+  grClipWindow (0, 0, settings.res_x, settings.res_y);
+  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;
+  if (settings.fog && (rdp.flags & FOG_ENABLED))
+  {
+    grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
+  }
+  LRDP("CloseTextureBuffer draw, OK\n");
+  rdp.tbuff_tex = 0;
+  return TRUE;
+}
+
+int CopyTextureBuffer(COLOR_IMAGE & fb_from, COLOR_IMAGE & fb_to)
+{
+  if (!fullscreen)
+    return FALSE;
+  FRDP("CopyTextureBuffer from %08x to %08x\n", fb_from.addr, fb_to.addr);
+  if (rdp.cur_image)
+  {
+    rdp.cur_image->crc = 0;
+    if (rdp.cur_image->addr == fb_to.addr)
+      return CloseTextureBuffer(TRUE);
+    rdp.tbuff_tex = rdp.cur_image;
+  }
+  else if (!FindTextureBuffer(fb_from.addr, (wxUint16)fb_from.width))
+  {
+    LRDP("Can't find 'from' buffer.\n");
+    return FALSE;
+  }
+  if (!OpenTextureBuffer(fb_to))
+  {
+    LRDP("Can't open new buffer.\n");
+    return CloseTextureBuffer(TRUE);
+  }
+  rdp.tbuff_tex->crc = 0;
+  GrTextureFormat_t buf_format = rdp.tbuff_tex->info.format;
+  rdp.tbuff_tex->info.format = GR_TEXFMT_RGB_565;
+  TexBufSetupCombiner(TRUE);
+  float ul_x = 0.0f;
+  float ul_y = 0.0f;
+  float lr_x = rdp.tbuff_tex->scr_width;
+  float lr_y = rdp.tbuff_tex->scr_height;
+  float zero = 0.0f;
+  float lr_u = rdp.tbuff_tex->lr_u;
+  float lr_v = rdp.tbuff_tex->lr_v;
+  FRDP("lr_x: %f, lr_y: %f\n", lr_x, lr_y);
+
+
+  // Make the vertices
+  VERTEX v[4] = {
+    { ul_x, ul_y, 1, 1, zero, zero, zero, zero, {zero, zero, zero, zero} },
+    { lr_x, ul_y, 1, 1, lr_u, zero, lr_u, zero, {lr_u, zero, lr_u, zero} },
+    { ul_x, lr_y, 1, 1, zero, lr_v, zero, lr_v, {zero, lr_v, zero, lr_v} },
+    { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
+  };
+
+  grTexSource( rdp.tbuff_tex->tmu, rdp.tbuff_tex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(rdp.tbuff_tex->info) );
+  grDrawTriangle (&v[0], &v[2], &v[1]);
+  grDrawTriangle (&v[2], &v[3], &v[1]);
+  grRenderBuffer( GR_BUFFER_BACKBUFFER );
+  rdp.offset_x = rdp.offset_x_bak;
+  rdp.offset_y = rdp.offset_y_bak;
+  rdp.offset_x_bak = rdp.offset_y_bak = 0;
+  AddOffset(v, 4);
+  grClipWindow (0, 0, settings.res_x, settings.res_y);
+  grDrawTriangle (&v[0], &v[2], &v[1]);
+  grDrawTriangle (&v[2], &v[3], &v[1]);
+  rdp.tbuff_tex->info.format = buf_format;
+
+  rdp.update |= UPDATE_ZBUF_ENABLED | UPDATE_COMBINE | UPDATE_TEXTURE | UPDATE_ALPHA_COMPARE;
+  rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
+  if (settings.fog && (rdp.flags & FOG_ENABLED))
+    grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
+  LRDP("CopyTextureBuffer draw, OK\n");
+  rdp.tbuff_tex = 0;
+  rdp.cur_image = 0;
+  return TRUE;
+}
+
+int CopyDepthBuffer()
+{
+  if (!fullscreen)
+    return FALSE;
+  LRDP("CopyDepthBuffer. ");
+  float bound = 1024.0f;
+  GrLOD_t LOD = GR_LOD_LOG2_1024;
+  if (settings.scr_res_x > 1024)
+  {
+    bound = 2048.0f;
+    LOD = GR_LOD_LOG2_2048;
+  }
+  rdp.tbuff_tex = &(rdp.texbufs[0].images[0]);
+  rdp.tbuff_tex->tmu = rdp.texbufs[0].tmu;
+  rdp.tbuff_tex->info.format = GR_TEXFMT_RGB_565;
+  rdp.tbuff_tex->info.smallLodLog2 = rdp.tbuff_tex->info.largeLodLog2 = LOD;
+  rdp.tbuff_tex->info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1;
+  TexBufSetupCombiner(TRUE);
+  float ul_x = 0.0f;
+  float ul_y = 0.0f;
+  float lr_x = bound;
+  float lr_y = bound;
+  float zero = 0.0f;
+  float lr_u = 255.5f;
+  float lr_v = 255.5f;
+  FRDP("lr_x: %f, lr_y: %f\n", lr_x, lr_y);
+
+
+  // Make the vertices
+  VERTEX v[4] = {
+    { ul_x, ul_y, 1, 1, zero, zero, zero, zero, {zero, zero, zero, zero} },
+    { lr_x, ul_y, 1, 1, lr_u, zero, lr_u, zero, {lr_u, zero, lr_u, zero} },
+    { ul_x, lr_y, 1, 1, zero, lr_v, zero, lr_v, {zero, lr_v, zero, lr_v} },
+    { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
+  };
+
+  grAuxBufferExt( GR_BUFFER_AUXBUFFER );
+  grTexSource( rdp.texbufs[0].tmu, rdp.texbufs[0].begin, GR_MIPMAPLEVELMASK_BOTH, &(rdp.tbuff_tex->info) );
+  grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
+  grTextureBufferExt( rdp.texbufs[1].tmu, rdp.texbufs[1].begin, LOD, LOD,
+    GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );
+  grDrawTriangle (&v[0], &v[2], &v[1]);
+  grDrawTriangle (&v[2], &v[3], &v[1]);
+  grRenderBuffer( GR_BUFFER_BACKBUFFER );
+  grTextureAuxBufferExt( rdp.texbufs[1].tmu, rdp.texbufs[1].begin, LOD, LOD,
+    GR_ASPECT_LOG2_1x1, GR_TEXFMT_RGB_565, GR_MIPMAPLEVELMASK_BOTH );
+  grAuxBufferExt( GR_BUFFER_TEXTUREAUXBUFFER_EXT );
+
+  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);
+  LRDP("CopyDepthBuffer draw, OK\n");
+  rdp.tbuff_tex = 0;
+  return TRUE;
+}
+
+int SwapTextureBuffer()
+{
+  if (!fullscreen || !rdp.tbuff_tex)
+    return FALSE;
+  LRDP("SwapTextureBuffer.");
+  COLOR_IMAGE ci;
+  ci.addr = rdp.tbuff_tex->addr;
+  ci.format = rdp.tbuff_tex->format;
+  ci.width = rdp.tbuff_tex->width;
+  ci.height = rdp.tbuff_tex->height;
+  ci.size = 2;
+  ci.status = ci_main;
+  ci.changed = FALSE;
+  TBUFF_COLOR_IMAGE * texbuf = AllocateTextureBuffer(ci);
+  if (!texbuf)
+  {
+    LRDP("Failed!\n");
+    return FALSE;
+  }
+  TexBufSetupCombiner();
+
+  float ul_x = 0.0f;
+  float ul_y = 0.0f;
+  float lr_x = rdp.tbuff_tex->scr_width;
+  float lr_y = rdp.tbuff_tex->scr_height;
+  float zero = 0.0f;
+  float lr_u = rdp.tbuff_tex->lr_u;
+  float lr_v = rdp.tbuff_tex->lr_v;
+
+  // Make the vertices
+  VERTEX v[4] = {
+    { ul_x, ul_y, 1, 1, zero, zero, zero, zero, {zero, zero, zero, zero} },
+    { lr_x, ul_y, 1, 1, lr_u, zero, lr_u, zero, {lr_u, zero, lr_u, zero} },
+    { ul_x, lr_y, 1, 1, zero, lr_v, zero, lr_v, {zero, lr_v, zero, lr_v} },
+    { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, {lr_u, lr_v, lr_u, lr_v} }
+  };
+
+  grTexSource( rdp.tbuff_tex->tmu, rdp.tbuff_tex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(rdp.tbuff_tex->info) );
+  texbuf->tile_uls = rdp.tbuff_tex->tile_uls;
+  texbuf->tile_ult = rdp.tbuff_tex->tile_ult;
+  texbuf->v_shift = rdp.tbuff_tex->v_shift;
+  grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
+  grTextureBufferExt( texbuf->tmu, texbuf->tex_addr, texbuf->info.smallLodLog2, texbuf->info.largeLodLog2,
+    texbuf->info.aspectRatioLog2, texbuf->info.format, GR_MIPMAPLEVELMASK_BOTH );
+  grDrawTriangle (&v[0], &v[2], &v[1]);
+  grDrawTriangle (&v[2], &v[3], &v[1]);
+  rdp.texbufs[rdp.tbuff_tex->tmu].clear_allowed = TRUE;
+  rdp.texbufs[rdp.tbuff_tex->tmu].count = 0;
+  texbuf->tile_uls = rdp.tbuff_tex->tile_uls;
+  texbuf->tile_ult = rdp.tbuff_tex->tile_ult;
+  texbuf->u_shift = rdp.tbuff_tex->u_shift;
+  texbuf->v_shift = rdp.tbuff_tex->v_shift;
+  rdp.tbuff_tex = texbuf;
+  if (rdp.cur_image)
+  {
+    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 );
+  }
+  else
+  {
+    grRenderBuffer( GR_BUFFER_BACKBUFFER );
+    rdp.offset_x = rdp.offset_x_bak;
+    rdp.offset_y = rdp.offset_y_bak;
+    rdp.offset_x_bak = rdp.offset_y_bak = 0;
+    rdp.update |= UPDATE_VIEWPORT | UPDATE_SCISSOR;
+  }
+  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);
+  }
+  LRDP("SwapTextureBuffer draw, OK\n");
+  return TRUE;
+}
+
+static wxUint32 CalcCRC(TBUFF_COLOR_IMAGE * pTCI)
+{
+  wxUint32 result = 0;
+  if ((settings.frame_buffer&fb_ref) > 0)
+    pTCI->crc = 0; //Since fb content changes each frame, crc check is meaningless.
+  else if (settings.fb_crc_mode == SETTINGS::fbcrcFast)
+    result = *((wxUint32*)(gfx.RDRAM + pTCI->addr + (pTCI->end_addr-pTCI->addr)/2));
+  else if (settings.fb_crc_mode == SETTINGS::fbcrcSafe)
+  {
+    wxUint8 * pSrc = gfx.RDRAM + pTCI->addr;
+    const wxUint32 nSize = pTCI->end_addr-pTCI->addr;
+    result = CRC32(0xFFFFFFFF, pSrc, 32);
+    result = CRC32(result, pSrc + (nSize>>1), 32);
+    result = CRC32(result, pSrc + nSize - 32, 32);
+  }
+  return result;
+}
+
+int FindTextureBuffer(wxUint32 addr, wxUint16 width)
+{
+  if (rdp.skip_drawing)
+    return FALSE;
+  FRDP("FindTextureBuffer. addr: %08lx, width: %d, scale_x: %f\n", addr, width, rdp.scale_x);
+  int found = FALSE;
+  wxUint32 shift = 0;
+  for (int i = 0; i < voodoo.num_tmu && !found; i++)
+  {
+    wxUint8 index = rdp.cur_tex_buf^i;
+    for (int j = 0; j < rdp.texbufs[index].count && !found; j++)
+    {
+      rdp.tbuff_tex = &(rdp.texbufs[index].images[j]);
+      if(addr >= rdp.tbuff_tex->addr && addr < rdp.tbuff_tex->end_addr)// && rdp.timg.format == 0)
+      {
+        bool bCorrect;
+        if (rdp.tbuff_tex->crc == 0)
+        {
+          rdp.tbuff_tex->crc = CalcCRC(rdp.tbuff_tex);
+          bCorrect = width == 1 || rdp.tbuff_tex->width == width || (rdp.tbuff_tex->width > 320 && rdp.tbuff_tex->width == width*2);
+        }
+        else
+          bCorrect = rdp.tbuff_tex->crc == CalcCRC(rdp.tbuff_tex);
+        if (bCorrect)
+        {
+          shift = addr - rdp.tbuff_tex->addr;
+          // if (!rdp.motionblur)
+          if (!rdp.cur_image)
+            rdp.cur_tex_buf = index;
+          found = TRUE;
+          //    FRDP("FindTextureBuffer, found in TMU%d buffer: %d\n", rdp.tbuff_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(TBUFF_COLOR_IMAGE)*(rdp.texbufs[index].count-j));
+        }
+      }
+    }
+  }
+  if (found)
+  {
+    rdp.tbuff_tex->tile_uls = 0;
+    rdp.tbuff_tex->tile_ult = 0;
+    if (shift > 0)
+    {
+      shift >>= 1;
+      rdp.tbuff_tex->v_shift = shift / rdp.tbuff_tex->width;
+      rdp.tbuff_tex->u_shift = shift % rdp.tbuff_tex->width;
+    }
+    else
+    {
+      rdp.tbuff_tex->v_shift = 0;
+      rdp.tbuff_tex->u_shift = 0;
+    }
+    FRDP("FindTextureBuffer, found, u_shift: %d,  v_shift: %d, format: %s\n", rdp.tbuff_tex->u_shift, rdp.tbuff_tex->v_shift, str_format[rdp.tbuff_tex->format]);
+    //FRDP("Buffer, addr=%08lx, end_addr=%08lx, width: %d, height: %d\n", rdp.tbuff_tex->addr, rdp.tbuff_tex->end_addr, rdp.tbuff_tex->width, rdp.tbuff_tex->height);
+    return TRUE;
+  }
+  rdp.tbuff_tex = 0;
+  LRDP("FindTextureBuffer, not found\n");
+  return FALSE;
+}
diff --git a/source/gles2glide64/src/Glide64/TexBuffer.h b/source/gles2glide64/src/Glide64/TexBuffer.h
new file mode 100644 (file)
index 0000000..9b0dc07
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+//
+// Hardware frame buffer emulation
+// Dec 2003 created by Gonetz
+//
+//****************************************************************
+
+#ifndef TEXBUFFER_H
+#define TEXBUFFER_H
+
+int OpenTextureBuffer(COLOR_IMAGE & cimage);
+
+int CloseTextureBuffer(int draw = FALSE);
+
+int CopyTextureBuffer(COLOR_IMAGE & fb_from, COLOR_IMAGE & fb_to);
+
+int CopyDepthBuffer();
+
+int SwapTextureBuffer();
+
+int FindTextureBuffer(wxUint32 addr, wxUint16 width);
+
+#endif  // ifndef TEXBUFFER
diff --git a/source/gles2glide64/src/Glide64/TexCache.cpp b/source/gles2glide64/src/Glide64/TexCache.cpp
new file mode 100644 (file)
index 0000000..60f801d
--- /dev/null
@@ -0,0 +1,1828 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+#include <SDL.h>
+#include "Gfx_1.3.h"
+#include "TexCache.h"
+#include "Combine.h"
+#include "Util.h"
+
+void LoadTex (int id, int tmu);
+
+wxUint8 tex1[1024*1024*4];             // temporary texture
+wxUint8 tex2[1024*1024*4];
+wxUint8 *texture;
+wxUint8 *texture_buffer = tex1;
+
+#include "TexLoad.h"   // texture loading functions, ONLY INCLUDE IN THIS FILE!!!
+#include "MiClWr32b.h"
+#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"
+#ifdef TEXTURE_FILTER // Hiroshi Morii <koolsmoky@users.sourceforge.net>
+extern int ghq_dmptex_toggle_key;
+#endif
+
+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;
+  wxUint32 crc;
+  wxUint32 flags;
+  int splits, splitheight;
+#ifdef TEXTURE_FILTER
+  uint64 ricecrc;
+#endif
+} TEXINFO;
+
+TEXINFO texinfo[2];
+int tex_found[2][MAX_TMU];
+
+#ifdef TEXTURE_FILTER
+typedef struct HIRESTEX_t {
+  int width, height;
+  wxUint16 format;
+  wxUint8 *data;
+} HIRESTEX;
+#endif
+
+//****************************************************************
+// List functions
+
+typedef struct NODE_t {
+  wxUint32     crc;
+  wxUIntPtr    data;
+  int          tmu;
+  int          number;
+  NODE_t       *pNext;
+} NODE;
+
+NODE *cachelut[65536];
+
+void AddToList (NODE **list, wxUint32 crc, wxUIntPtr 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;
+  rdp.n_cached[tmu] ++;
+  if (voodoo.tex_UMA)
+    rdp.n_cached[tmu^1] = rdp.n_cached[tmu];
+}
+
+void DeleteList (NODE **list)
+{
+  while (*list)
+  {
+    NODE *next = (*list)->pNext;
+    delete (*list);
+    *list = next;
+  }
+}
+
+void TexCacheInit ()
+{
+  for (int i=0; i<65536; i++)
+  {
+    cachelut[i] = NULL;
+  }
+}
+
+//****************************************************************
+// ClearCache - clear the texture cache for BOTH tmus
+
+void ClearCache ()
+{
+  voodoo.tmem_ptr[0] = offset_textures;
+  rdp.n_cached[0] = 0;
+  voodoo.tmem_ptr[1] = voodoo.tex_UMA ? offset_textures : offset_texbuf1;
+  rdp.n_cached[1] = 0;
+
+  for (int i=0; i<65536; i++)
+  {
+    DeleteList (&cachelut[i]);
+  }
+}
+
+//****************************************************************
+uint32_t textureCRC(uint8_t *addr, int width, int height, int line)
+{
+  uint32_t crc = 0;
+  uint32_t *pixelpos;
+  unsigned int i;
+  uint64_t twopixel_crc;
+
+  pixelpos = (uint32_t*)addr;
+  for (; height; height--) {
+    for (i = width; i; --i) {
+      twopixel_crc = i * (uint64_t)(pixelpos[1] + pixelpos[0] + crc);
+      crc = (uint32_t) ((twopixel_crc >> 32) + twopixel_crc);
+      pixelpos += 2;
+    }
+    crc = ((unsigned int)height * (uint64_t)crc >> 32) + height * crc;
+    pixelpos = (uint32_t *)((char *)pixelpos + line);
+  }
+
+  return crc;
+}
+// GetTexInfo - gets information for either t0 or t1, checks if in cache & fills tex_found
+
+void GetTexInfo (int id, int tile)
+{
+  FRDP (" | |-+ GetTexInfo (id: %d, tile: %d)\n", id, tile);
+
+  // this is the NEW cache searching, searches only textures with similar crc's
+  int t;
+  for (t=0; t<MAX_TMU; t++)
+    tex_found[id][t] = -1;
+
+  TBUFF_COLOR_IMAGE * pFBTex = 0;
+  if (rdp.aTBuffTex[0] && rdp.aTBuffTex[0]->tile == id)
+    pFBTex = rdp.aTBuffTex[0];
+  else if (rdp.aTBuffTex[1] && rdp.aTBuffTex[1]->tile == id)
+    pFBTex = rdp.aTBuffTex[1];
+  if (pFBTex && pFBTex->cache)
+    return;
+
+  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.
+
+    if (mask_width > 256 && mask_height > 256)
+    {
+      mask_width = tile_width;
+      mask_height = tile_height;
+    }
+
+    // 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;
+  int crc_height = height;
+  if (rdp.timg.set_by == 1)
+    crc_height = tile_height;
+
+  bpl = width << rdp.tiles[tile].size >> 1;
+
+  // ** COMMENT THIS TO DISABLE LARGE TEXTURES
+#ifdef LARGE_TEXTURE_HANDLING
+  if (!voodoo.sup_large_tex && 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;
+  }
+
+  LRDP(" | | |-+ 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);
+  LRDP(" | | |- 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 (rdp.tiles[tile].t_mem + min(height, tile_height) * (rdp.tiles[tile].line<<3) > 4096)
+  {
+    LRDP("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<<shift)<y; shift++);
+    rdp.tiles[tile].mask_t = shift;
+
+    // restart the function
+    LRDP("restarting...\n");
+    GetTexInfo (id, tile);
+    return;
+  }
+
+  line = rdp.tiles[tile].line;
+  if (rdp.tiles[tile].size == 3)
+    line <<= 1;
+  wxUint32 crc = 0;
+  if (settings.fast_crc)
+  {
+    line = (line - wid_64) << 3;
+    if (wid_64 < 1) wid_64 = 1;
+    uint8_t * addr = (((uint8_t*)rdp.tmem) + (rdp.tiles[tile].t_mem<<3));
+    if (crc_height > 0) // Check the CRC
+    {
+      if (rdp.tiles[tile].size < 3)
+        crc = textureCRC(addr, wid_64, crc_height, line);
+      else //32b texture
+      {
+        int line_2 = line >> 1;
+        int wid_64_2 = max(1, wid_64 >> 1);
+        crc = textureCRC(addr, wid_64_2, crc_height, line_2);
+        crc += textureCRC(addr+0x800, wid_64_2, crc_height, line_2);
+      }
+    }
+  }
+  else
+  {
+    crc = 0xFFFFFFFF;
+    wxUIntPtr addr = wxPtrToUInt(rdp.tmem) + (rdp.tiles[tile].t_mem<<3);
+    wxUint32 line2 = max(line,1);
+    if (rdp.tiles[tile].size < 3)
+    {
+      line2 <<= 3;
+      for (int y = 0; y < crc_height; y++)
+      {
+        crc = CRC32( crc, reinterpret_cast<void*>(addr), bpl );
+        addr += line2;
+      }
+    }
+    else //32b texture
+    {
+      line2 <<= 2;
+      //32b texel is split in two 16b parts, so bpl/2 and line/2.
+      //Min value for bpl is 4, because when width==1 first 2 bytes of tmem will not be used.
+      bpl = max(bpl >> 1, 4);
+      for (int y = 0; y < crc_height; y++)
+      {
+        crc = CRC32( crc, reinterpret_cast<void*>(addr), bpl);
+        crc = CRC32( crc, reinterpret_cast<void*>(addr + 0x800), bpl);
+        addr += line2;
+      }
+    }
+    line = (line - wid_64) << 3;
+    if (wid_64 < 1) wid_64 = 1;
+  }
+  if ((rdp.tiles[tile].size < 2) && (rdp.tlut_mode || rdp.tiles[tile].format == 2))
+  {
+    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);
+
+  wxUint32 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
+  LRDP(" | | |-+ Checking cache...\n");
+
+  CACHE_LUT *cache;
+
+  if (rdp.noise == RDP::noise_texture)
+    return;
+
+  wxUint32 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;
+  }
+
+  NODE *node = cachelut[crc>>16];
+  wxUint32 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].palette == cache->palette &&
+          rdp.tiles[tile].format == cache->format &&
+          rdp.tiles[tile].size == cache->size &&*/
+          rdp.tiles[tile].width == cache->width &&
+          rdp.tiles[tile].height == cache->height &&
+          flags == cache->flags)
+      {
+        if (!(mod+cache->mod) || (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((int)(cache->mod_factor - modfactor)) < 8))
+        {
+          FRDP (" | | | |- Texture found in cache (tmu=%d).\n", node->tmu);
+          tex_found[id][node->tmu] = node->number;
+          if (voodoo.tex_UMA)
+          {
+            tex_found[id][node->tmu^1] = node->number;
+            return;
+          }
+        }
+      }
+    }
+    node = node->pNext;
+  }
+
+  LRDP(" | | | +- 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 (voodoo.tex_UMA) return 0;
+
+  if (tmu1 >= voodoo.num_tmu) return tmu2;
+  if (tmu2 >= voodoo.num_tmu) return tmu1;
+
+  if (voodoo.tex_max_addr[tmu1]-voodoo.tmem_ptr[tmu1] >
+    voodoo.tex_max_addr[tmu2]-voodoo.tmem_ptr[tmu2])
+    return tmu1;
+  else
+    return tmu2;
+}
+
+//****************************************************************
+// SelectTBuffTex - select texture from texture buffer
+static void SelectTBuffTex(TBUFF_COLOR_IMAGE * pTBuffTex)
+{
+  FRDP ("SelectTBuffTex: tex: %d, tmu: %d, tile: %d\n", rdp.tex, pTBuffTex->tmu, pTBuffTex->tile);
+  grTexSource(pTBuffTex->tile, pTBuffTex->tex_addr, GR_MIPMAPLEVELMASK_BOTH, &(pTBuffTex->info) );
+}
+
+//****************************************************************
+// TexCache - does texture loading after combiner is set
+int SwapTextureBuffer();
+void TexCache ()
+{
+  LRDP(" |-+ TexCache called\n");
+
+#ifdef TEXTURE_FILTER /* Hiroshi Morii <koolsmoky@users.sourceforge.net> */ // POSTNAPALM
+  if (settings.ghq_use && settings.ghq_hirs_dump) {
+    /* Force reload hi-res textures. Useful for texture artists */
+    if (CheckKeyPressed(G64_VK_R, 0x0001)) {
+      if (ext_ghq_reloadhirestex()) ClearCache();
+    }
+    /* Turn on texture dump */
+    else if (CheckKeyPressed(G64_VK_D, 0x0001)) {
+      extern void DisplayLoadProgress(const wchar_t *format, ...);
+      ghq_dmptex_toggle_key = !ghq_dmptex_toggle_key;
+      if (ghq_dmptex_toggle_key) {
+        DisplayLoadProgress(L"Texture dump - ON\n");
+        ClearCache();
+        SDL_Delay(1000);
+      } else {
+        DisplayLoadProgress(L"Texture dump - OFF\n");
+        SDL_Delay(1000);
+      }
+    }
+  }
+#endif
+
+  if (rdp.tex & 1)
+    GetTexInfo (0, rdp.cur_tile);
+  if (rdp.tex & 2)
+    GetTexInfo (1, rdp.cur_tile+1);
+
+  TBUFF_COLOR_IMAGE * aTBuff[2] = {0, 0};
+  if (rdp.aTBuffTex[0])
+    aTBuff[rdp.aTBuffTex[0]->tile] = rdp.aTBuffTex[0];
+  if (rdp.aTBuffTex[1])
+    aTBuff[rdp.aTBuffTex[1]->tile] = rdp.aTBuffTex[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 (voodoo.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)
+      {
+        LRDP(" | | | |- 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 (!rdp.tex) //nothing more to do
+        return;
+    }
+
+    if (tmu_1 < voodoo.num_tmu)
+    {
+      if (cmb.tex_cmb_ext_use)
+      {
+        LRDP(" | | | |- 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 < voodoo.num_tmu)
+    {
+      if (cmb.tex_cmb_ext_use)
+      {
+        LRDP(" | | | |- 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 < voodoo.num_tmu)
+  {
+    if (aTBuff[0] && aTBuff[0]->cache)
+    {
+      LRDP(" | |- Hires tex T0 found in cache.\n");
+      if (fullscreen)
+      {
+        rdp.cur_cache[0] = aTBuff[0]->cache;
+        rdp.cur_cache[0]->last_used = frame_count;
+        rdp.cur_cache[0]->uses = rdp.debug_n;
+      }
+    }
+    else if (tex_found[0][tmu_0] != -1)
+    {
+      LRDP(" | |- T0 found in cache.\n");
+      if (fullscreen)
+      {
+        CACHE_LUT *cache = voodoo.tex_UMA?&rdp.cache[0][tex_found[0][0]]:&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,
+          (voodoo.tex_min_addr[tmu_0] + cache->tmem_addr),
+          GR_MIPMAPLEVELMASK_BOTH,
+          &cache->t_info);
+      }
+    }
+    else
+      LoadTex (0, tmu_0);
+  }
+  if ((rdp.tex & 2) && tmu_1 < voodoo.num_tmu)
+  {
+    if (aTBuff[1] && aTBuff[1]->cache)
+    {
+      LRDP(" | |- Hires tex T1 found in cache.\n");
+      if (fullscreen)
+      {
+        rdp.cur_cache[1] = aTBuff[1]->cache;
+        rdp.cur_cache[1]->last_used = frame_count;
+        rdp.cur_cache[1]->uses = rdp.debug_n;
+      }
+    }
+    else if (tex_found[1][tmu_1] != -1)
+    {
+      LRDP(" | |- T1 found in cache.\n");
+      if (fullscreen)
+      {
+        CACHE_LUT *cache = voodoo.tex_UMA?&rdp.cache[0][tex_found[1][0]]:&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,
+          (voodoo.tex_min_addr[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 if (i==1) tmu=tmu_1;
+
+      if (tmu >= voodoo.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);
+      }
+
+      if (rdp.cur_cache[i])
+      {
+        wxUint32 mode_s, mode_t;
+        int clamp_s, clamp_t;
+        if (rdp.force_wrap && !rdp.texrecting)
+        {
+          clamp_s = rdp.tiles[tile].clamp_s && rdp.tiles[tile].lr_s-rdp.tiles[tile].ul_s < 256;
+          clamp_t = rdp.tiles[tile].clamp_t && rdp.tiles[tile].lr_t-rdp.tiles[tile].ul_t < 256;
+        }
+        else
+        {
+          clamp_s = (rdp.tiles[tile].clamp_s || rdp.tiles[tile].mask_s == 0) &&
+            rdp.tiles[tile].lr_s-rdp.tiles[tile].ul_s < 256;
+          clamp_t = (rdp.tiles[tile].clamp_t || rdp.tiles[tile].mask_t == 0) &&
+            rdp.tiles[tile].lr_t-rdp.tiles[tile].ul_t < 256;
+        }
+
+        if (rdp.cur_cache[i]->f_mirror_s)
+          mode_s = GR_TEXTURECLAMP_MIRROR_EXT;
+        else if (rdp.cur_cache[i]->f_wrap_s)
+          mode_s = GR_TEXTURECLAMP_WRAP;
+        else if (clamp_s)
+          mode_s = GR_TEXTURECLAMP_CLAMP;
+        else
+        {
+          if (rdp.tiles[tile].mirror_s && voodoo.sup_mirroring)
+            mode_s = GR_TEXTURECLAMP_MIRROR_EXT;
+          else
+            mode_s = GR_TEXTURECLAMP_WRAP;
+        }
+
+        if (rdp.cur_cache[i]->f_mirror_t)
+          mode_t = GR_TEXTURECLAMP_MIRROR_EXT;
+        else if (rdp.cur_cache[i]->f_wrap_t)
+          mode_t = GR_TEXTURECLAMP_WRAP;
+        else if (clamp_t)
+          mode_t = GR_TEXTURECLAMP_CLAMP;
+        else
+        {
+          if (rdp.tiles[tile].mirror_t && voodoo.sup_mirroring)
+            mode_t = GR_TEXTURECLAMP_MIRROR_EXT;
+          else
+            mode_t = GR_TEXTURECLAMP_WRAP;
+        }
+
+        grTexClampMode (tmu,
+          mode_s,
+          mode_t);
+      }
+      if (aTBuff[i] && (rdp.tex&(i+1)))
+        SelectTBuffTex(aTBuff[i]);
+    }
+  }
+
+  LRDP(" | +- TexCache End\n");
+}
+
+
+#ifdef TEXTURE_FILTER
+/** cite from RiceVideo */
+inline wxUint32 CalculateDXT(wxUint32 txl2words)
+{
+  if( txl2words == 0 ) return 1;
+  else return (2048+txl2words-1)/txl2words;
+}
+
+wxUint32 sizeBytes[4] = {0,1,2,4};
+
+inline wxUint32 Txl2Words(wxUint32 width, wxUint32 size)
+{
+  if( size == 0 )
+    return max(1, width/16);
+  else
+    return max(1, width*sizeBytes[size]/8);
+}
+
+inline wxUint32 ReverseDXT(wxUint32 val, wxUint32 lrs, wxUint32 width, wxUint32 size)
+{
+  if( val == 0x800 ) return 1;
+
+  int low = 2047/val;
+  if( CalculateDXT(low) > val )        low++;
+  int high = 2047/(val-1);
+
+  if( low == high )    return low;
+
+  for( int i=low; i<=high; i++ )
+  {
+    if( Txl2Words(width, size) == (wxUint32)i )
+      return i;
+  }
+
+  return       (low+high)/2;
+}
+/** end RiceVideo cite */
+#endif
+
+//****************************************************************
+// 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)
+  {
+    LRDP("Cache count reached, clearing...\n");
+    ClearCache ();
+    if (id == 1 && rdp.tex == 3)
+      LoadTex (0, rdp.t0);
+  }
+
+  // Get this cache object
+  cache = voodoo.tex_UMA?&rdp.cache[0][rdp.n_cached[0]]:&rdp.cache[tmu][rdp.n_cached[tmu]];
+  rdp.cur_cache[id] = cache;
+  rdp.cur_cache_n[id] = rdp.n_cached[tmu];
+
+  //!Hackalert
+  //GoldenEye water texture. It has CI format in fact, but the game set it to RGBA
+  if ((settings.hacks&hack_GoldenEye) && rdp.tiles[td].format == 0 && rdp.tlut_mode == 2 && rdp.tiles[td].size == 2)
+  {
+    rdp.tiles[td].format = 2;
+    rdp.tiles[td].size = 1;
+  }
+
+  // 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 = voodoo.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;
+  cache->f_mirror_s = FALSE;
+  cache->f_mirror_t = FALSE;
+  cache->f_wrap_s = FALSE;
+  cache->f_wrap_t = FALSE;
+#ifdef TEXTURE_FILTER
+  cache->is_hires_tex = FALSE;
+  cache->ricecrc    = texinfo[id].ricecrc;
+#endif
+
+  // Add this cache to the list
+  AddToList (&cachelut[cache->crc>>16], cache->crc, wxPtrToUInt(cache), tmu, rdp.n_cached[tmu]);
+
+  // temporary
+  cache->t_info.format = GR_TEXFMT_ARGB_1555;
+
+  // Calculate lod and aspect
+  wxUint32 size_x = rdp.tiles[td].width;
+  wxUint32 size_y = rdp.tiles[td].height;
+
+  // make size_x and size_y both powers of two
+  if (!voodoo.sup_large_tex)
+  {
+    if (size_x > 256) size_x = 256;
+    if (size_y > 256) size_y = 256;
+  }
+
+  int shift;
+  for (shift=0; (1<<shift) < (int)size_x; shift++);
+  size_x = 1 << shift;
+  for (shift=0; (1<<shift) < (int)size_y; shift++);
+  size_y = 1 << shift;
+
+  // Voodoo 1 support is all here, it will automatically mirror to the full extent.
+  if (!voodoo.sup_mirroring)
+  {
+    if (rdp.tiles[td].mirror_s && !rdp.tiles[td].clamp_s && (voodoo.sup_large_tex || size_x <= 128))
+      size_x <<= 1;
+    if (rdp.tiles[td].mirror_t && !rdp.tiles[td].clamp_t && (voodoo.sup_large_tex || size_y <= 128))
+      size_y <<= 1;
+  }
+
+  // Calculate the maximum size
+  int size_max = max (size_x, size_y);
+  wxUint32 real_x=size_max, real_y=size_max;
+  switch (size_max)
+  {
+  case 1:
+    lod = GR_LOD_LOG2_1;
+    cache->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:
+    lod = GR_LOD_LOG2_256;
+    cache->scale = 1.0f;
+    break;
+  case 512:
+    lod = GR_LOD_LOG2_512;
+    cache->scale = 0.5f;
+    break;
+  default:
+    lod = GR_LOD_LOG2_1024;
+    cache->scale = 0.25f;
+    break;
+  }
+
+  // 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;
+    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;
+    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;
+  }
+
+  cache->c_off = cache->scale * 0.5f;
+  if (wid != 1) cache->c_scl_x = cache->scale;
+  else cache->c_scl_x = 0.0f;
+  if (hei != 1) cache->c_scl_y = cache->scale;
+  else cache->c_scl_y = 0.0f;
+  // **
+
+  wxUint32 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;
+  }
+
+  wxUint16 tmp_pal[256];
+  int 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;
+
+  for (int t = 0; t < 2; t++) {
+    if (rdp.aTBuffTex[t] && rdp.aTBuffTex[t]->tile == id) //texture buffer will be used instead of frame buffer texture
+    {
+      rdp.aTBuffTex[t]->cache = cache;
+      FRDP("tbuff_tex selected: %d, tile=%d\n", t, id);
+      return;
+    }
+  }
+
+  wxUint32 result = 0; // keep =0 so it doesn't mess up on the first split
+
+  texture = tex1;
+
+  // Hiroshi Morii <koolsmoky@users.sourceforge.net>
+  // NOTE: Loading Hi-res texture packs and filtering should be done
+  // before the texture is modified with color palettes, etc.
+  //
+  // Since the internal texture identification needs Glide64CRC, (RiceCRC
+  // doesn't always return unique values) it seems reasonable that the
+  // extra CRC calculation for hires textures should be executed only
+  // when we get passed the texture ram cache and texture buffers for
+  // minimal calculation overhead.
+  //
+#ifdef TEXTURE_FILTER // Hiroshi Morii <koolsmoky@users.sourceforge.net>
+  GHQTexInfo ghqTexInfo;
+  memset(&ghqTexInfo, 0, sizeof(GHQTexInfo));
+  wxUint32 g64_crc = cache->crc;
+  if (settings.ghq_use)
+  {
+    int bpl;
+    wxUint8* addr = (wxUint8*)(gfx.RDRAM+rdp.addr[rdp.tiles[td].t_mem]);
+    int tile_width  = texinfo[id].width;
+    int tile_height = texinfo[id].height;
+    LOAD_TILE_INFO &info = rdp.load_info[rdp.tiles[td].t_mem];
+    if (rdp.timg.set_by == 1)
+    {
+      bpl = info.tex_width << info.tex_size >> 1;
+      addr += (info.tile_ul_t * bpl) + (((info.tile_ul_s<<info.tex_size)+1)>>1);
+
+      tile_width = min(info.tile_width, info.tex_width);
+      if (info.tex_size > rdp.tiles[td].size)
+        tile_width <<= info.tex_size - rdp.tiles[td].size;
+
+      if (rdp.tiles[td].lr_t > rdp.bg_image_height)
+        tile_height = rdp.bg_image_height - rdp.tiles[td].ul_t;
+      else
+        tile_height = info.tile_height;
+    }
+    else
+    {
+      if (rdp.tiles[td].size == 3)
+        bpl = rdp.tiles[td].line << 4;
+      else if (info.dxt == 0)
+        bpl = rdp.tiles[td].line << 3;
+      else {
+        wxUint32 dxt = info.dxt;
+        if (dxt > 1)
+          dxt = ReverseDXT(dxt, info.tile_width, texinfo[id].width, rdp.tiles[td].size);
+        bpl = dxt << 3;
+      }
+    }
+
+    //    wxUint8* addr = (wxUint8*)(gfx.RDRAM+rdp.addr[rdp.tiles[td].t_mem] + (rdp.tiles[td].ul_t * bpl) + (((rdp.tiles[td].ul_s<<rdp.tiles[td].size)+1)>>1));
+    wxUint8 * paladdr = 0;
+    wxUint16 * palette = 0;
+    if ((rdp.tiles[td].size < 2) && (rdp.tlut_mode || rdp.tiles[td].format == 2))
+    {
+      if (rdp.tiles[td].size == 1)
+        paladdr = (wxUint8*)(rdp.pal_8_rice);
+      else if (settings.ghq_hirs_altcrc)
+        paladdr = (wxUint8*)(rdp.pal_8_rice + (rdp.tiles[td].palette << 5));
+      else
+        paladdr = (wxUint8*)(rdp.pal_8_rice + (rdp.tiles[td].palette << 4));
+      palette = (rdp.pal_8 + (rdp.tiles[td].palette << 4));
+    }
+
+    // XXX: Special combiner modes are ignored for hires textures
+    // for now. Come back to this later!! The following is needed
+    // for (2xSai, hq4x, etc) enhanced/filtered textures.
+    g64_crc = CRC32( g64_crc, &cache->mod, 4 );
+    g64_crc = CRC32( g64_crc, &cache->mod_color, 4 );
+    g64_crc = CRC32( g64_crc, &cache->mod_color1, 4 );
+    //g64_crc = CRC32( g64_crc, &cache->mod_color2, 4 ); // not used?
+    g64_crc = CRC32( g64_crc, &cache->mod_factor, 4 );
+
+    cache->ricecrc = ext_ghq_checksum(addr, tile_width, tile_height, (unsigned short)(rdp.tiles[td].format << 8 | rdp.tiles[td].size), bpl, paladdr);
+    FRDP("CI RICE CRC. format: %d, size: %d, CRC: %08lx, PalCRC: %08lx\n", rdp.tiles[td].format, rdp.tiles[td].size, (wxUint32)(cache->ricecrc&0xFFFFFFFF), (wxUint32)(cache->ricecrc>>32));
+    if (ext_ghq_hirestex((uint64)g64_crc, cache->ricecrc, palette, &ghqTexInfo))
+    {
+      cache->is_hires_tex = ghqTexInfo.is_hires_tex;
+      if (!ghqTexInfo.is_hires_tex && aspect != ghqTexInfo.aspectRatioLog2)
+        ghqTexInfo.data = 0; //if aspects of current texture and found filtered texture are different, texture must be filtered again.
+    }
+  }
+
+
+  // ** handle texture splitting **
+  if (ghqTexInfo.data)
+    ;//do nothing
+  else
+#endif
+    if (splits > 1)
+    {
+      cache->scale_y = 0.125f;
+
+      int i;
+      for (i=0; i<splits; i++)
+      {
+        int start_dst = i * cache->splitheight * 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;
+        if (rdp.tiles[td].size == 3)
+          start_src >>= 1;
+
+        result = load_table[rdp.tiles[td].size][rdp.tiles[td].format]
+        (wxPtrToUInt(texture)+start_dst, wxPtrToUInt(rdp.tmem)+(rdp.tiles[td].t_mem<<3)+start_src,
+          texinfo[id].wid_64, texinfo[id].height, texinfo[id].line, real_x, td);
+
+        wxUint32 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 if (size != 2)
+          Clamp8bT ((texture)+start_dst, texinfo[id].height, real_x, cache->splitheight);
+        else
+          Clamp32bT ((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]
+      (wxPtrToUInt(texture), wxPtrToUInt(rdp.tmem)+(rdp.tiles[td].t_mem<<3),
+        texinfo[id].wid_64, texinfo[id].height, texinfo[id].line, real_x, td);
+
+      wxUint32 size = HIWORD(result);
+
+      int min_x, min_y;
+      if (rdp.tiles[td].mask_s != 0)
+        min_x = min((int)real_x, 1<<rdp.tiles[td].mask_s);
+      else
+        min_x = real_x;
+      if (rdp.tiles[td].mask_t != 0)
+        min_y  = min((int)real_y, 1<<rdp.tiles[td].mask_t);
+      else
+        min_y = real_y;
+
+      // Load using mirroring/clamping
+      if (min_x > texinfo[id].width)
+      {
+        if (size == 1)
+          Clamp16bS ((texture), texinfo[id].width, min_x, real_x, texinfo[id].height);
+        else if (size != 2)
+          Clamp8bS ((texture), texinfo[id].width, min_x, real_x, texinfo[id].height);
+        else
+          Clamp32bS ((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 if (size != 2)
+            Mirror8bS ((texture), rdp.tiles[td].mask_s,
+            real_x, real_x, texinfo[id].height);
+          else
+            Mirror32bS ((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 if (size != 2)
+            Wrap8bS ((texture), rdp.tiles[td].mask_s,
+            real_x, real_x, texinfo[id].height);
+          else
+            Wrap32bS ((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 if (size != 2)
+          Clamp8bT ((texture), texinfo[id].height, real_x, min_y);
+        else
+          Clamp32bT ((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 if (size != 2)
+            Mirror8bT ((texture), rdp.tiles[td].mask_t,
+            real_y, real_x);
+          else
+            Mirror32bT ((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 if (size != 2)
+            Wrap8bT ((texture), rdp.tiles[td].mask_t,
+            real_y, real_x);
+          else
+            Wrap32bT ((texture), rdp.tiles[td].mask_t,
+            real_y, real_x);
+        }
+      }
+    }
+
+    if (modifyPalette)
+    {
+      memcpy(rdp.pal_8, tmp_pal, 512);
+    }
+
+#ifdef TEXTURE_FILTER
+    if (mod && !modifyPalette && !ghqTexInfo.data)
+#else
+    if (mod && !modifyPalette)
+#endif
+    {
+      // Convert the texture to ARGB 4444
+      if (LOWORD(result) == GR_TEXFMT_ARGB_1555)
+      {
+        TexConv_ARGB1555_ARGB4444 ((texture), (tex2), real_x, real_y);
+        texture = tex2;
+      }
+      else if (LOWORD(result) == GR_TEXFMT_ALPHA_INTENSITY_88)
+      {
+        TexConv_AI88_ARGB4444 ((texture), (tex2), real_x, real_y);
+        texture = tex2;
+      }
+      else if (LOWORD(result) == GR_TEXFMT_ALPHA_INTENSITY_44)
+      {
+        TexConv_AI44_ARGB4444 ((texture), (tex2), real_x, real_y);
+        texture = tex2;
+      }
+      else if (LOWORD(result) == GR_TEXFMT_ALPHA_8)
+      {
+        TexConv_A8_ARGB4444 ((texture), (tex2), real_x, real_y);
+        texture = tex2;
+      }
+      /*else if (LOWORD(result) == GR_TEXFMT_ARGB_4444)
+      {
+      memcpy (tex2, texture, (real_x*real_y) << 1);
+      texture = tex2;
+      }*/ // we can skip memcpy since "texture" won't be swapped between "tex1" and "tex2" after this.
+      // Hiroshi Morii <koolsmoky@users.sourceoforge.net>
+
+      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 ((wxUint16*)texture, size, modcolor, modfactor);
+        break;
+      case TMOD_TEX_INTER_COL_USING_COL1:
+        mod_tex_inter_col_using_col1 ((wxUint16*)texture, size, modcolor, modcolor1);
+        break;
+      case TMOD_FULL_COLOR_SUB_TEX:
+        mod_full_color_sub_tex ((wxUint16*)texture, size, modcolor);
+        break;
+      case TMOD_COL_INTER_COL1_USING_TEX:
+        mod_col_inter_col1_using_tex ((wxUint16*)texture, size, modcolor, modcolor1);
+        break;
+      case TMOD_COL_INTER_COL1_USING_TEXA:
+        mod_col_inter_col1_using_texa ((wxUint16*)texture, size, modcolor, modcolor1);
+        break;
+      case TMOD_COL_INTER_COL1_USING_TEXA__MUL_TEX:
+        mod_col_inter_col1_using_texa__mul_tex ((wxUint16*)texture, size, modcolor, modcolor1);
+        break;
+      case TMOD_COL_INTER_TEX_USING_TEXA:
+        mod_col_inter_tex_using_texa ((wxUint16*)texture, size, modcolor);
+        break;
+      case TMOD_COL2_INTER__COL_INTER_COL1_USING_TEX__USING_TEXA:
+        mod_col2_inter__col_inter_col1_using_tex__using_texa ((wxUint16*)texture, size, modcolor, modcolor1, modcolor2);
+        break;
+      case TMOD_TEX_SCALE_FAC_ADD_FAC:
+        mod_tex_scale_fac_add_fac ((wxUint16*)texture, size, modfactor);
+        break;
+      case TMOD_TEX_SUB_COL_MUL_FAC_ADD_TEX:
+        mod_tex_sub_col_mul_fac_add_tex ((wxUint16*)texture, size, modcolor, modfactor);
+        break;
+      case TMOD_TEX_SCALE_COL_ADD_COL:
+        mod_tex_scale_col_add_col ((wxUint16*)texture, size, modcolor, modcolor1);
+        break;
+      case TMOD_TEX_ADD_COL:
+        mod_tex_add_col ((wxUint16*)texture, size, modcolor);
+        break;
+      case TMOD_TEX_SUB_COL:
+        mod_tex_sub_col ((wxUint16*)texture, size, modcolor);
+        break;
+      case TMOD_TEX_SUB_COL_MUL_FAC:
+        mod_tex_sub_col_mul_fac ((wxUint16*)texture, size, modcolor, modfactor);
+        break;
+      case TMOD_COL_INTER_TEX_USING_COL1:
+        mod_col_inter_tex_using_col1 ((wxUint16*)texture, size, modcolor, modcolor1);
+        break;
+      case TMOD_COL_MUL_TEXA_ADD_TEX:
+        mod_col_mul_texa_add_tex((wxUint16*)texture, size, modcolor);
+        break;
+      case TMOD_COL_INTER_TEX_USING_TEX:
+        mod_col_inter_tex_using_tex ((wxUint16*)texture, size, modcolor);
+        break;
+      case TMOD_TEX_INTER_NOISE_USING_COL:
+        mod_tex_inter_noise_using_col ((wxUint16*)texture, size, modcolor);
+        break;
+      case TMOD_TEX_INTER_COL_USING_TEXA:
+        mod_tex_inter_col_using_texa ((wxUint16*)texture, size, modcolor);
+        break;
+      case TMOD_TEX_MUL_COL:
+        mod_tex_mul_col ((wxUint16*)texture, size, modcolor);
+        break;
+      case TMOD_TEX_SCALE_FAC_ADD_COL:
+        mod_tex_scale_fac_add_col ((wxUint16*)texture, 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)
+    {
+#ifdef TEXTURE_FILTER // Hiroshi Morii <koolsmoky@users.sourceforge.net>
+      if (settings.ghq_use)
+      {
+        if (!ghqTexInfo.data && ghq_dmptex_toggle_key) {
+          unsigned char *tmpbuf = (unsigned char*)texture;
+          int tmpwidth = real_x;
+          if (texinfo[id].splits > 1) {
+            int dstpixoffset, srcpixoffset;
+            int shift;
+            switch (LOWORD(result) & 0x7fff) { // XXX is there a better way of determining the pixel color depth?
+             case GR_TEXFMT_ARGB_8888:
+               shift = 3;
+               break;
+             case GR_TEXFMT_ALPHA_INTENSITY_44:
+             case GR_TEXFMT_ALPHA_8:
+               shift = 0;
+               break;
+             default:
+               shift = 1;
+            }
+            tmpwidth = texinfo[id].real_image_width;
+            tmpbuf = (unsigned char*)malloc((256*256)<<3); // XXX performance overhead
+            for (int i = 0; i < cache->splitheight; i++) {
+              dstpixoffset = texinfo[id].real_image_width * i;
+              srcpixoffset = 256 * i;
+              for (int k = 0; k < texinfo[id].splits; k++) {
+                memcpy(tmpbuf + (dstpixoffset << shift), texture + (srcpixoffset << shift), (256 << shift));
+                dstpixoffset += 256;
+                srcpixoffset += (256 * cache->splitheight);
+              }
+            }
+          }
+          ext_ghq_dmptx(tmpbuf, (int)texinfo[id].real_image_width, (int)texinfo[id].real_image_height, (int)tmpwidth, (unsigned short)LOWORD(result), (unsigned short)((cache->format << 8) | (cache->size)), cache->ricecrc);
+          if (tmpbuf != texture && tmpbuf) {
+            free(tmpbuf);
+          }
+        }
+
+        if (!ghqTexInfo.data)
+          if (!settings.ghq_enht_nobg || !rdp.texrecting || (texinfo[id].splits == 1 && texinfo[id].width <= 256))
+            ext_ghq_txfilter((unsigned char*)texture, (int)real_x, (int)real_y, LOWORD(result), (uint64)g64_crc, &ghqTexInfo);
+
+        if (ghqTexInfo.data)
+        {
+          if (ghqTexInfo.aspectRatioLog2 < GR_ASPECT_LOG2_1x8 ||
+            ghqTexInfo.aspectRatioLog2 > GR_ASPECT_LOG2_8x1 ||
+            ghqTexInfo.largeLodLog2 > GR_LOD_LOG2_2048 ||
+            ghqTexInfo.largeLodLog2 < GR_LOD_LOG2_1)
+          {
+            /* invalid dimensions */
+          }
+          else
+          {
+            texture = (wxUint8 *)ghqTexInfo.data;
+            lod = ghqTexInfo.largeLodLog2;
+            int splits = cache->splits;
+            if (ghqTexInfo.is_hires_tex)
+            {
+              if (ghqTexInfo.tiles/*ghqTexInfo.untiled_width > max_tex_size*/)
+              {
+                cache->scale = 1.0f;
+                cache->c_off = 0.5f;
+                cache->splits = ghqTexInfo.tiles;//((hirestex.width-1)>>8)+1;
+                cache->splitheight = ghqTexInfo.untiled_height;
+                cache->scale_x = 1.0f;
+                cache->scale_y = float(ghqTexInfo.untiled_height*ghqTexInfo.tiles)/float(ghqTexInfo.width);//*sy;
+                if (splits == 1)
+                {
+                  int shift;
+                  for (shift=9; (1<<shift) < ghqTexInfo.untiled_width; shift++);
+                  float mult = float(1 << shift >> 8);
+                  cache->c_scl_x *= mult;
+                  cache->c_scl_y *= mult;
+                }
+                else
+                {
+                  int tile_width = rdp.tiles[td].width;
+                  if (rdp.timg.set_by == 1)
+                    tile_width = rdp.load_info[rdp.tiles[td].t_mem].tex_width;
+                  float mult = float(ghqTexInfo.untiled_width/tile_width);
+                  cache->c_scl_x *= mult;
+                  cache->c_scl_y *= mult;
+                }
+              }
+              else
+              {
+                cache->scale = 256.0f / float(1<<lod);
+                cache->c_off = cache->scale * 0.5f;
+                cache->splits = 1;
+                if (aspect != ghqTexInfo.aspectRatioLog2)
+                {
+                  float mscale = float(1<<abs(aspect - ghqTexInfo.aspectRatioLog2));
+                  if (abs(aspect) > abs(ghqTexInfo.aspectRatioLog2))
+                  {
+                    cache->c_scl_y *= mscale;
+                    cache->c_scl_x *= mscale;
+                  }
+                  /*
+                  else
+                  {
+                  if (rdp.tiles[td].mirror_s && sup_mirroring)
+                  cache->f_mirror_s = TRUE;
+                  if (rdp.tiles[td].mirror_t && sup_mirroring)
+                  cache->f_mirror_t = TRUE;
+                  //cache->c_scl_y /= mscale;
+                  //cache->c_scl_x /= mscale;
+                  }
+                  */
+                  if (ghqTexInfo.aspectRatioLog2 >= 0)
+                  {
+                    cache->scale_x = 1.0f;
+                    cache->scale_y = 1.0f/float(1<<ghqTexInfo.aspectRatioLog2);
+                  }
+                  else
+                  {
+                    cache->scale_y = 1.0f;
+                    cache->scale_x = 1.0f/float(1<<(-ghqTexInfo.aspectRatioLog2));
+                  }
+                }
+                else if (splits > 1)
+                {
+                  cache->c_scl_x /= splits;
+                  cache->c_scl_y /= splits;
+                }
+              }
+              if (voodoo.sup_mirroring)
+              {
+                if (rdp.tiles[td].mirror_s && texinfo[id].tile_width == 2*texinfo[id].width)
+                  cache->f_mirror_s = TRUE;
+                else if (texinfo[id].tile_width >= 2*texinfo[id].width)
+                  cache->f_wrap_s = TRUE;
+                if (rdp.tiles[td].mirror_t && texinfo[id].tile_height == 2*texinfo[id].height)
+                  cache->f_mirror_t = TRUE;
+                else if (texinfo[id].tile_height >= 2*texinfo[id].height)
+                  cache->f_wrap_t = TRUE;
+                if (cache->f_mirror_s && cache->f_mirror_t)
+                {
+                  cache->c_scl_x *= 2.0f;
+                  cache->c_scl_y *= 2.0f;
+                }
+              }
+              aspect = ghqTexInfo.aspectRatioLog2;
+              cache->lod = lod;
+              cache->aspect = aspect;
+            }
+            else
+            {
+              //cache->scale = 256.0f / float(1<<lod);
+              cache->c_off = 128.0f / float(1<<lod);
+            }
+            real_x = ghqTexInfo.width;
+            real_y = ghqTexInfo.height;
+            result = (1 << 16) | ghqTexInfo.format;
+            cache->t_info.format = ghqTexInfo.format;
+            cache->realwidth = real_x;
+            cache->realheight = real_y;
+          }
+        }
+      }
+#endif
+
+      // 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;
+
+      wxUint32 texture_size = grTexTextureMemRequired (GR_MIPMAPLEVELMASK_BOTH, t_info);
+
+      // Check for 2mb boundary
+      // Hiroshi Morii <koolsmoky@users.sourceforge.net> required only for V1,Rush, and V2
+      if (voodoo.has_2mb_tex_boundary &&
+        (voodoo.tmem_ptr[tmu] < TEXMEM_2MB_EDGE) && (voodoo.tmem_ptr[tmu]+texture_size > TEXMEM_2MB_EDGE))
+      {
+        voodoo.tmem_ptr[tmu] = TEXMEM_2MB_EDGE;
+        cache->tmem_addr = voodoo.tmem_ptr[tmu];
+      }
+
+      // Check for end of memory (too many textures to fit, clear cache)
+      if (voodoo.tmem_ptr[tmu]+texture_size >= voodoo.tex_max_addr[tmu])
+      {
+        LRDP("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)
+      }
+
+      wxUint32 tex_addr = GetTexAddr(tmu, texture_size);
+      grTexDownloadMipMap (tmu,
+        tex_addr,
+        GR_MIPMAPLEVELMASK_BOTH,
+        t_info);
+
+      grTexSource (tmu,
+        tex_addr,
+        GR_MIPMAPLEVELMASK_BOTH,
+        t_info);
+    }
+
+    LRDP(" | | +- LoadTex end\n");
+}
diff --git a/source/gles2glide64/src/Glide64/TexCache.h b/source/gles2glide64/src/Glide64/TexCache.h
new file mode 100644 (file)
index 0000000..d9e4e74
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+#ifndef TEXCACHE_H
+#define TEXCACHE_H
+
+void TexCacheInit ();
+void TexCache ();
+void ClearCache ();
+
+extern wxUint8 * texture_buffer;
+
+#endif //TEXCACHE_H
diff --git a/source/gles2glide64/src/Glide64/TexConv.h b/source/gles2glide64/src/Glide64/TexConv.h
new file mode 100644 (file)
index 0000000..9bb1729
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+static inline void texConv_ARGB1555_ARGB4444(uint8_t *src, uint8_t *dst, int size)
+{
+  uint32_t *v3;
+  uint32_t *v4;
+  int v5;
+  uint32_t v6;
+  uint32_t v7;
+
+  v3 = (uint32_t *)src;
+  v4 = (uint32_t *)dst;
+  v5 = size;
+  do
+  {
+    v6 = *v3;
+    ++v3;
+    v7 = v6;
+    *v4 = ((v7 & 0x1E001E) >> 1) | ((v6 & 0x3C003C0) >> 2) | ((v6 & 0x78007800) >> 3) | ((v6 & 0x80008000) >> 3) | ((v6 & 0x80008000) >> 2) | ((v6 & 0x80008000) >> 1) | (v6 & 0x80008000);
+    ++v4;
+    --v5;
+  }
+  while ( v5 );
+}
+
+static inline void texConv_AI88_ARGB4444(uint8_t *src, uint8_t *dst, int size)
+{
+  uint32_t *v3;
+  uint32_t *v4;
+  int v5;
+  uint32_t v6;
+  uint32_t v7;
+
+  v3 = (uint32_t *)src;
+  v4 = (uint32_t *)dst;
+  v5 = size;
+  do
+  {
+    v6 = *v3;
+    ++v3;
+    v7 = v6;
+    *v4 = (16 * (v7 & 0xF000F0) >> 8) | (v7 & 0xF000F0) | (16 * (v7 & 0xF000F0)) | (v6 & 0xF000F000);
+    ++v4;
+    --v5;
+  }
+  while ( v5 );
+}
+
+static inline void texConv_AI44_ARGB4444(uint8_t *src, uint8_t *dst, int size)
+{
+  uint32_t *v3;
+  uint32_t *v4;
+  int v5;
+  uint32_t v6;
+  uint32_t *v7;
+
+  v3 = (uint32_t *)src;
+  v4 = (uint32_t *)dst;
+  v5 = size;
+  do
+  {
+    v6 = *v3;
+    ++v3;
+    *v4 = ((((uint16_t)v6 << 8) & 0xFF00 & 0xF00u) >> 8) | ((((uint16_t)v6 << 8) & 0xFF00 & 0xF00u) >> 4) | (uint16_t)(((uint16_t)v6 << 8) & 0xFF00) | (((v6 << 16) & 0xF000000) >> 8) | (((v6 << 16) & 0xF000000) >> 4) | ((v6 << 16) & 0xFF000000);
+    v7 = v4 + 1;
+    *v7 = (((v6 >> 8) & 0xF00) >> 8) | (((v6 >> 8) & 0xF00) >> 4) | ((v6 >> 8) & 0xFF00) | ((v6 & 0xF000000) >> 8) | ((v6 & 0xF000000) >> 4) | (v6 & 0xFF000000);
+    v4 = v7 + 1;
+    --v5;
+  }
+  while ( v5 );
+}
+
+static inline void texConv_A8_ARGB4444(uint8_t *src, uint8_t *dst, int size)
+{
+  uint32_t *v3;
+  uint32_t *v4;
+  int v5;
+  uint32_t v6;
+  uint32_t v7;
+  uint32_t *v8;
+
+  v3 = (uint32_t *)src;
+  v4 = (uint32_t *)dst;
+  v5 = size;
+  do
+  {
+    v6 = *v3;
+    ++v3;
+    v7 = v6;
+    *v4 = ((v6 & 0xF0) << 8 >> 12) | (uint8_t)(v6 & 0xF0) | (16 * (uint8_t)(v6 & 0xF0) & 0xFFFFFFF) | ((uint8_t)(v6 & 0xF0) << 8) | (16 * (uint16_t)(v6 & 0xF000) & 0xFFFFF) | (((uint16_t)(v6 & 0xF000) << 8) & 0xFFFFFF) | (((uint16_t)(v6 & 0xF000) << 12) & 0xFFFFFFF) | ((uint16_t)(v6 & 0xF000) << 16);
+    v8 = v4 + 1;
+    *v8 = ((v7 & 0xF00000) >> 20) | ((v7 & 0xF00000) >> 16) | ((v7 & 0xF00000) >> 12) | ((v7 & 0xF00000) >> 8) | ((v6 & 0xF0000000) >> 12) | ((v6 & 0xF0000000) >> 8) | ((v6 & 0xF0000000) >> 4) | (v6 & 0xF0000000);
+    v4 = v8 + 1;
+    --v5;
+  }
+  while ( v5 );
+}
+
+void TexConv_ARGB1555_ARGB4444 (unsigned char * src, unsigned char * dst, int width, int height)
+{
+  int size = (width * height) >> 1;    // Hiroshi Morii <koolsmoky@users.sourceforge.net>
+  // 2 pixels are converted in one loop
+  // NOTE: width * height must be a multiple of 2
+  texConv_ARGB1555_ARGB4444(src, dst, size);
+}
+
+void TexConv_AI88_ARGB4444 (unsigned char * src, unsigned char * dst, int width, int height)
+{
+  int size = (width * height) >> 1;    // Hiroshi Morii <koolsmoky@users.sourceforge.net>
+  // 2 pixels are converted in one loop
+  // NOTE: width * height must be a multiple of 2
+  texConv_AI88_ARGB4444(src, dst, size);
+}
+
+void TexConv_AI44_ARGB4444 (unsigned char * src, unsigned char * dst, int width, int height)
+{
+  int size = (width * height) >> 2;    // Hiroshi Morii <koolsmoky@users.sourceforge.net>
+  // 4 pixels are converted in one loop
+  // NOTE: width * height must be a multiple of 4
+  texConv_AI44_ARGB4444(src, dst, size);
+}
+
+void TexConv_A8_ARGB4444 (unsigned char * src, unsigned char * dst, int width, int height)
+{
+  int size = (width * height) >> 2;    // Hiroshi Morii <koolsmoky@users.sourceforge.net>
+  // 4 pixels are converted in one loop
+  // NOTE: width * height must be a multiple of 4
+  texConv_A8_ARGB4444(src, dst, size);
+}
+
diff --git a/source/gles2glide64/src/Glide64/TexLoad.h b/source/gles2glide64/src/Glide64/TexLoad.h
new file mode 100644 (file)
index 0000000..eb00df6
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+#include "TexLoad4b.h"
+#include "TexLoad8b.h"
+#include "TexLoad16b.h"
+#include "TexLoad32b.h"
+
+wxUint32 LoadNone (wxUIntPtr dst, wxUIntPtr src, int wid_64, int height, int line, int real_width, int tile)
+{
+       memset (texture, 0, 4096*4);
+       return (1 << 16) | GR_TEXFMT_ARGB_1555;
+}
+
+typedef wxUint32 (*texfunc)(wxUIntPtr, wxUIntPtr, int, int, int, int, int);
+texfunc load_table [4][5] = {  // [size][format]
+{      Load4bSelect,
+       LoadNone,
+       Load4bCI,
+       Load4bIA,
+       Load4bI  },
+
+{      Load8bCI,
+       LoadNone,
+       Load8bCI,
+       Load8bIA,
+       Load8bI  },
+
+{      Load16bRGBA,
+       Load16bYUV,
+       Load16bRGBA,
+       Load16bIA,
+       LoadNone },
+
+{      Load32bRGBA,
+       LoadNone,
+       LoadNone,
+       LoadNone,
+       LoadNone }
+};
diff --git a/source/gles2glide64/src/Glide64/TexLoad16b.h b/source/gles2glide64/src/Glide64/TexLoad16b.h
new file mode 100644 (file)
index 0000000..d5aeada
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+static inline void load16bRGBA(uint8_t *src, uint8_t *dst, int wid_64, int height, int line, int ext)
+{
+  uint32_t *v6;
+  uint32_t *v7;
+  int v8;
+  int v9;
+  uint32_t v10;
+  uint32_t v11;
+  uint32_t *v12;
+  uint32_t *v13;
+  int v14;
+  uint32_t v15;
+  uint32_t v16;
+  int v17;
+  int v18;
+
+  v6 = (uint32_t *)src;
+  v7 = (uint32_t *)dst;
+  v8 = height;
+  do
+  {
+    v17 = v8;
+    v9 = wid_64;
+    do
+    {
+      v10 = bswap32(*v6);
+      v11 = bswap32(v6[1]);
+      ALOWORD(v10) = __ROR__((uint16_t)v10, 1);
+      ALOWORD(v11) = __ROR__((uint16_t)v11, 1);
+      v10 = __ROR__(v10, 16);
+      v11 = __ROR__(v11, 16);
+      ALOWORD(v10) = __ROR__((uint16_t)v10, 1);
+      ALOWORD(v11) = __ROR__((uint16_t)v11, 1);
+      *v7 = v10;
+      v7[1] = v11;
+      v6 += 2;
+      v7 += 2;
+      --v9;
+    }
+    while ( v9 );
+    if ( v17 == 1 )
+      break;
+    v18 = v17 - 1;
+    v12 = (uint32_t *)&src[(line + (uintptr_t)v6 - (uintptr_t)src) & 0xFFF];
+    v13 = (uint32_t *)((char *)v7 + ext);
+    v14 = wid_64;
+    do
+    {
+      v15 = bswap32(v12[1]);
+      v16 = bswap32(*v12);
+      ALOWORD(v15) = __ROR__((uint16_t)v15, 1);
+      ALOWORD(v16) = __ROR__((uint16_t)v16, 1);
+      v15 = __ROR__(v15, 16);
+      v16 = __ROR__(v16, 16);
+      ALOWORD(v15) = __ROR__((uint16_t)v15, 1);
+      ALOWORD(v16) = __ROR__((uint16_t)v16, 1);
+      *v13 = v15;
+      v13[1] = v16;
+      v12 += 2;
+      v13 += 2;
+      --v14;
+    }
+    while ( v14 );
+    v6 = (uint32_t *)&src[(line + (uintptr_t)v12 - (uintptr_t)src) & 0xFFF];
+    v7 = (uint32_t *)((char *)v13 + ext);
+    v8 = v18 - 1;
+  }
+  while ( v18 != 1 );
+}
+
+static inline void load16bIA(uint8_t *src, uint8_t *dst, int wid_64, int height, int line, int ext)
+{
+  uint32_t *v6;
+  uint32_t *v7;
+  int v8;
+  int v9;
+  uint32_t v10;
+  uint32_t *v11;
+  uint32_t *v12;
+  int v13;
+  uint32_t v14;
+  int v15;
+  int v16;
+
+  v6 = (uint32_t *)src;
+  v7 = (uint32_t *)dst;
+  v8 = height;
+  do
+  {
+    v15 = v8;
+    v9 = wid_64;
+    do
+    {
+      v10 = v6[1];
+      *v7 = *v6;
+      v7[1] = v10;
+      v6 += 2;
+      v7 += 2;
+      --v9;
+    }
+    while ( v9 );
+    if ( v15 == 1 )
+      break;
+    v16 = v15 - 1;
+    v11 = (uint32_t *)((char *)v6 + line);
+    v12 = (uint32_t *)((char *)v7 + ext);
+    v13 = wid_64;
+    do
+    {
+      v14 = *v11;
+      *v12 = v11[1];
+      v12[1] = v14;
+      v11 += 2;
+      v12 += 2;
+      --v13;
+    }
+    while ( v13 );
+    v6 = (uint32_t *)((char *)v11 + line);
+    v7 = (uint32_t *)((char *)v12 + ext);
+    v8 = v16 - 1;
+  }
+  while ( v16 != 1 );
+}
+
+
+//****************************************************************
+// Size: 2, Format: 0
+//
+
+wxUint32 Load16bRGBA (wxUIntPtr dst, wxUIntPtr 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;
+
+  load16bRGBA((uint8_t *)src, (uint8_t *)dst, wid_64, height, line, ext);
+
+  return (1 << 16) | GR_TEXFMT_ARGB_1555;
+}
+
+//****************************************************************
+// Size: 2, Format: 3
+//
+// ** by Gugaman/Dave2001 **
+
+wxUint32 Load16bIA (wxUIntPtr dst, wxUIntPtr 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;
+
+  load16bIA((uint8_t *)src, (uint8_t *)dst, wid_64, height, line, ext);
+
+  return (1 << 16) | GR_TEXFMT_ALPHA_INTENSITY_88;
+}
+
+//****************************************************************
+// Size: 2, Format: 1
+//
+
+wxUint16 yuv_to_rgb565(wxUint8 y, wxUint8 u, wxUint8 v)
+{
+  //*
+  float r = y + (1.370705f * (v-128));
+  float g = y - (0.698001f * (v-128)) - (0.337633f * (u-128));
+  float b = y + (1.732446f * (u-128));
+  r *= 0.125f;
+  g *= 0.25f;
+  b *= 0.125f;
+  //clipping the result
+  if (r > 31) r = 31;
+  if (g > 63) g = 63;
+  if (b > 31) b = 31;
+  if (r < 0) r = 0;
+  if (g < 0) g = 0;
+  if (b < 0) b = 0;
+  wxUint16 c = (wxUint16)(((wxUint16)(r) << 11) |
+    ((wxUint16)(g) << 5) |
+    (wxUint16)(b) );
+  return c;
+  //*/
+  /*
+  const wxUint32 c = y - 16;
+  const wxUint32 d = u - 128;
+  const wxUint32 e = v - 128;
+
+  wxUint32 r =  (298 * c           + 409 * e + 128) & 0xf800;
+  wxUint32 g = ((298 * c - 100 * d - 208 * e + 128) >> 5) & 0x7e0;
+  wxUint32 b = ((298 * c + 516 * d           + 128) >> 11) & 0x1f;
+
+  WORD texel = (WORD)(r | g | b);
+
+  return texel;
+  */
+}
+
+//****************************************************************
+// Size: 2, Format: 1
+//
+
+wxUint32 Load16bYUV (wxUIntPtr dst, wxUIntPtr src, int wid_64, int height, int line, int real_width, int tile)
+{
+  wxUint32 * mb = (wxUint32*)(gfx.RDRAM+rdp.addr[rdp.tiles[tile].t_mem]); //pointer to the macro block
+  wxUint16 * tex = (wxUint16*)dst;
+  wxUint16 i;
+  for (i = 0; i < 128; i++)
+  {
+    wxUint32 t = mb[i]; //each wxUint32 contains 2 pixels
+    wxUint8 y1 = (wxUint8)t&0xFF;
+    wxUint8 v  = (wxUint8)(t>>8)&0xFF;
+    wxUint8 y0 = (wxUint8)(t>>16)&0xFF;
+    wxUint8 u  = (wxUint8)(t>>24)&0xFF;
+    wxUint16 c = yuv_to_rgb565(y0, u, v);
+    *(tex++) = c;
+    c = yuv_to_rgb565(y1, u, v);
+    *(tex++) = c;
+  }
+  return (1 << 16) | GR_TEXFMT_RGB_565;
+}
diff --git a/source/gles2glide64/src/Glide64/TexLoad32b.h b/source/gles2glide64/src/Glide64/TexLoad32b.h
new file mode 100644 (file)
index 0000000..11c6bcb
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+#include "Gfx_1.3.h"
+
+//****************************************************************
+// Size: 2, Format: 0
+//
+// Load 32bit RGBA texture
+// Based on sources of angrylion's software plugin.
+//
+wxUint32 Load32bRGBA (wxUIntPtr dst, wxUIntPtr src, int wid_64, int height, int line, int real_width, int tile)
+{
+  if (height < 1) height = 1;
+  const wxUint16 *tmem16 = (wxUint16*)rdp.tmem;
+  const wxUint32 tbase = (src - (wxUIntPtr)rdp.tmem) >> 1;
+  const wxUint32 width = max(1, wid_64 << 1);
+  const int ext = real_width - width;
+  line = width + (line>>2);
+  wxUint32 s, t, c;
+  wxUint32 * tex = (wxUint32*)dst;
+  wxUint16 rg, ba;
+  for (t = 0; t < (wxUint32)height; t++)
+  {
+    wxUint32 tline = tbase + line * t;
+    wxUint32 xorval = (t & 1) ? 3 : 1;
+    for (s = 0; s < width; s++)
+    {
+      wxUint32 taddr = ((tline + s) ^ xorval) & 0x3ff;
+      rg = tmem16[taddr];
+      ba = tmem16[taddr|0x400];
+      c = ((ba&0xFF)<<24) | (rg << 8) | (ba>>8);
+      *tex++ = c;
+    }
+    tex += ext;
+  }
+  int id = tile - rdp.cur_tile;
+  wxUint32 mod = (id == 0) ? cmb.mod_0 : cmb.mod_1;
+  if (mod || !voodoo.sup_32bit_tex)
+  {
+    //convert to ARGB_4444
+    const wxUint32 tex_size = real_width * height;
+    tex = (wxUint32 *)dst;
+    wxUint16 *tex16 = (wxUint16*)dst;
+    wxUint16 a, r, g, b;
+    for (wxUint32 i = 0; i < tex_size; i++) {
+      c = tex[i];
+      a = (c >> 28) & 0xF;
+      r = (c >> 20) & 0xF;
+      g = (c >> 12) & 0xF;
+      b = (c >> 4)  & 0xF;
+      tex16[i] = (a <<12) | (r << 8) | (g << 4) | b;
+    }
+    return (1 << 16) | GR_TEXFMT_ARGB_4444;
+  }
+  return (2 << 16) | GR_TEXFMT_ARGB_8888;
+}
+
+//****************************************************************
+// LoadTile for 32bit RGBA texture
+// Based on sources of angrylion's software plugin.
+//
+void LoadTile32b (wxUint32 tile, wxUint32 ul_s, wxUint32 ul_t, wxUint32 width, wxUint32 height)
+{
+  const wxUint32 line = rdp.tiles[tile].line << 2;
+  const wxUint32 tbase = rdp.tiles[tile].t_mem << 2;
+  const wxUint32 addr = rdp.timg.addr >> 2;
+  const wxUint32* src = (const wxUint32*)gfx.RDRAM;
+  wxUint16 *tmem16 = (wxUint16*)rdp.tmem;
+  wxUint32 c, ptr, tline, s, xorval;
+
+  for (wxUint32 j = 0; j < height; j++)
+  {
+    tline = tbase + line * j;
+    s = ((j + ul_t) * rdp.timg.width) + ul_s;
+    xorval = (j & 1) ? 3 : 1;                          
+    for (wxUint32 i = 0; i < width; i++)
+    {
+      c = src[addr + s + i];
+      ptr = ((tline + i) ^ xorval) & 0x3ff;
+      tmem16[ptr] = c >> 16;
+      tmem16[ptr|0x400] = c & 0xffff;
+    }
+  }
+}
+
+//****************************************************************
+// LoadBlock for 32bit RGBA texture
+// Based on sources of angrylion's software plugin.
+//
+void LoadBlock32b(wxUint32 tile, wxUint32 ul_s, wxUint32 ul_t, wxUint32 lr_s, wxUint32 dxt)
+{
+  const wxUint32 * src = (const wxUint32*)gfx.RDRAM;
+  const wxUint32 tb = rdp.tiles[tile].t_mem << 2;
+  const wxUint32 tiwindwords = rdp.timg.width;
+  const wxUint32 slindwords = ul_s;
+  const wxUint32 line = rdp.tiles[tile].line << 2;
+
+  wxUint16 *tmem16 = (wxUint16*)rdp.tmem;
+  wxUint32 addr = rdp.timg.addr >> 2;
+  wxUint32 width = (lr_s - ul_s + 1) << 2;
+  if (width & 7)
+    width = (width & (~7)) + 8;
+
+  if (dxt != 0)
+  {
+    wxUint32 j= 0;
+    wxUint32 t = 0;
+    wxUint32 oldt = 0;
+    wxUint32 ptr;
+
+    addr += (ul_t * tiwindwords) + slindwords;
+    wxUint32 c = 0;
+    for (wxUint32 i = 0; i < width; i += 2)
+    {
+      oldt = t;
+      t = ((j >> 11) & 1) ? 3 : 1;
+      if (t != oldt)
+        i += line;
+      ptr = ((tb + i) ^ t) & 0x3ff;
+      c = src[addr + i];
+      tmem16[ptr] = c >> 16;
+      tmem16[ptr|0x400] = c & 0xffff;
+      ptr = ((tb+ i + 1) ^ t) & 0x3ff;
+      c = src[addr + i + 1];
+      tmem16[ptr] = c >> 16;
+      tmem16[ptr|0x400] = c & 0xffff;
+      j += dxt;
+    }
+  }
+  else
+  {
+    addr += (ul_t * tiwindwords) + slindwords;
+    wxUint32 c, ptr;
+    for (wxUint32 i = 0; i < width; i ++)
+    {
+      ptr = ((tb + i) ^ 1) & 0x3ff;
+      c = src[addr + i];
+      tmem16[ptr] = c >> 16;
+      tmem16[ptr|0x400] = c & 0xffff;
+    }
+  }
+}
diff --git a/source/gles2glide64/src/Glide64/TexLoad4b.h b/source/gles2glide64/src/Glide64/TexLoad4b.h
new file mode 100644 (file)
index 0000000..814edad
--- /dev/null
@@ -0,0 +1,663 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+#include <stdint.h>
+
+static inline void load4bCI(uint8_t *src, uint8_t *dst, int wid_64, int height, uint16_t line, int ext, uint16_t *pal)
+{
+  uint8_t *v7;
+  uint8_t *v8;
+  int v9;
+  int v10;
+  int v11;
+  uint32_t v12;
+  uint8_t *v13;
+  uint32_t v14;
+  uint32_t *v15;
+  uint32_t v16;
+  uint8_t *v17;
+  uint32_t *v18;
+  int v19;
+  int v20;
+  uint32_t v21;
+  uint32_t v22;
+  uint32_t *v23;
+  uint32_t v24;
+  int v25;
+  int v26;
+
+  v7 = src;
+  v8 = dst;
+  v9 = height;
+  do
+  {
+    v25 = v9;
+    v10 = wid_64;
+    do
+    {
+      v11 = v10;
+      v12 = bswap32(*(uint32_t *)v7);
+      v13 = v7 + 4;
+      ALOWORD(v10) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 23) & 0x1E)), 1);
+      v14 = v10 << 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 27) & 0x1E)), 1);
+      *(uint32_t *)v8 = v14;
+      v15 = (uint32_t *)(v8 + 4);
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 15) & 0x1E)), 1);
+      v14 <<= 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 19) & 0x1E)), 1);
+      *v15 = v14;
+      ++v15;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 7) & 0x1E)), 1);
+      v14 <<= 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 11) & 0x1E)), 1);
+      *v15 = v14;
+      ++v15;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint8_t)v12 & 0x1E)), 1);
+      v14 <<= 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 3) & 0x1E)), 1);
+      *v15 = v14;
+      ++v15;
+      v16 = bswap32(*(uint32_t *)v13);
+      v7 = v13 + 4;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 23) & 0x1E)), 1);
+      v14 <<= 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 27) & 0x1E)), 1);
+      *v15 = v14;
+      ++v15;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 15) & 0x1E)), 1);
+      v14 <<= 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 19) & 0x1E)), 1);
+      *v15 = v14;
+      ++v15;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 7) & 0x1E)), 1);
+      v14 <<= 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 11) & 0x1E)), 1);
+      *v15 = v14;
+      ++v15;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint8_t)v16 & 0x1E)), 1);
+      v14 <<= 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 3) & 0x1E)), 1);
+      *v15 = v14;
+      v8 = (uint8_t *)(v15 + 1);
+      v10 = v11 - 1;
+    }
+    while ( v11 != 1 );
+    if ( v25 == 1 )
+      break;
+    v26 = v25 - 1;
+    v17 = &src[(line + (uintptr_t)v7 - (uintptr_t)src) & 0x7FF];
+    v18 = (uint32_t *)&v8[ext];
+    v19 = wid_64;
+    do
+    {
+      v20 = v19;
+      v21 = bswap32(*((uint32_t *)v17 + 1));
+      ALOWORD(v19) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 23) & 0x1E)), 1);
+      v22 = v19 << 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 27) & 0x1E)), 1);
+      *v18 = v22;
+      v23 = v18 + 1;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 15) & 0x1E)), 1);
+      v22 <<= 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 19) & 0x1E)), 1);
+      *v23 = v22;
+      ++v23;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 7) & 0x1E)), 1);
+      v22 <<= 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 11) & 0x1E)), 1);
+      *v23 = v22;
+      ++v23;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint8_t)v21 & 0x1E)), 1);
+      v22 <<= 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 3) & 0x1E)), 1);
+      *v23 = v22;
+      ++v23;
+      v24 = bswap32(*(uint32_t *)v17);
+      v17 = &src[((uintptr_t)v17 + 8 - (uintptr_t)src) & 0x7FF];
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 23) & 0x1E)), 1);
+      v22 <<= 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 27) & 0x1E)), 1);
+      *v23 = v22;
+      ++v23;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 15) & 0x1E)), 1);
+      v22 <<= 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 19) & 0x1E)), 1);
+      *v23 = v22;
+      ++v23;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 7) & 0x1E)), 1);
+      v22 <<= 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 11) & 0x1E)), 1);
+      *v23 = v22;
+      ++v23;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint8_t)v24 & 0x1E)), 1);
+      v22 <<= 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 3) & 0x1E)), 1);
+      *v23 = v22;
+      v18 = v23 + 1;
+      v19 = v20 - 1;
+    }
+    while ( v20 != 1 );
+    v7 = &src[(line + (uintptr_t)v17 - (uintptr_t)src) & 0x7FF];
+    v8 = (uint8_t *)((char *)v18 + ext);
+    v9 = v26 - 1;
+  }
+  while ( v26 != 1 );
+}
+
+static inline void load4bIAPal(uint8_t *src, uint8_t *dst, int wid_64, int height, int line, int ext, uint16_t *pal)
+{
+  uint8_t *v7;
+  uint32_t *v8;
+  int v9;
+  int v10;
+  int v11;
+  uint32_t v12;
+  uint32_t *v13;
+  uint32_t v14;
+  uint32_t *v15;
+  uint32_t v16;
+  uint8_t *v17;
+  uint32_t *v18;
+  int v19;
+  int v20;
+  uint32_t v21;
+  uint32_t v22;
+  uint32_t *v23;
+  uint32_t v24;
+  int v25;
+  int v26;
+
+  v7 = src;
+  v8 = (uint32_t *)dst;
+  v9 = height;
+  do
+  {
+    v25 = v9;
+    v10 = wid_64;
+    do
+    {
+      v11 = v10;
+      v12 = bswap32(*(uint32_t *)v7);
+      v13 = (uint32_t *)(v7 + 4);
+      ALOWORD(v10) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 23) & 0x1E)), 8);
+      v14 = v10 << 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 27) & 0x1E)), 8);
+      *v8 = v14;
+      v15 = v8 + 1;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 15) & 0x1E)), 8);
+      v14 <<= 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 19) & 0x1E)), 8);
+      *v15 = v14;
+      ++v15;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 7) & 0x1E)), 8);
+      v14 <<= 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 11) & 0x1E)), 8);
+      *v15 = v14;
+      ++v15;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint8_t)v12 & 0x1E)), 8);
+      v14 <<= 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 3) & 0x1E)), 8);
+      *v15 = v14;
+      ++v15;
+      v16 = bswap32(*v13);
+      v7 = (uint8_t *)(v13 + 1);
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 23) & 0x1E)), 8);
+      v14 <<= 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 27) & 0x1E)), 8);
+      *v15 = v14;
+      ++v15;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 15) & 0x1E)), 8);
+      v14 <<= 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 19) & 0x1E)), 8);
+      *v15 = v14;
+      ++v15;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 7) & 0x1E)), 8);
+      v14 <<= 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 11) & 0x1E)), 8);
+      *v15 = v14;
+      ++v15;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint8_t)v16 & 0x1E)), 8);
+      v14 <<= 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 3) & 0x1E)), 8);
+      *v15 = v14;
+      v8 = v15 + 1;
+      v10 = v11 - 1;
+    }
+    while ( v11 != 1 );
+    if ( v25 == 1 )
+      break;
+    v26 = v25 - 1;
+    v17 = &src[(line + (uintptr_t)v7 - (uintptr_t)src) & 0x7FF];
+    v18 = (uint32_t *)((char *)v8 + ext);
+    v19 = wid_64;
+    do
+    {
+      v20 = v19;
+      v21 = bswap32(*((uint32_t *)v17 + 1));
+      ALOWORD(v19) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 23) & 0x1E)), 8);
+      v22 = v19 << 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 27) & 0x1E)), 8);
+      *v18 = v22;
+      v23 = v18 + 1;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 15) & 0x1E)), 8);
+      v22 <<= 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 19) & 0x1E)), 8);
+      *v23 = v22;
+      ++v23;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 7) & 0x1E)), 8);
+      v22 <<= 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 11) & 0x1E)), 8);
+      *v23 = v22;
+      ++v23;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint8_t)v21 & 0x1E)), 8);
+      v22 <<= 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 3) & 0x1E)), 8);
+      *v23 = v22;
+      ++v23;
+      v24 = bswap32(*(uint32_t *)v17);
+      v17 = &src[((uintptr_t)v17 + 8 - (uintptr_t)src) & 0x7FF];
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 23) & 0x1E)), 8);
+      v22 <<= 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 27) & 0x1E)), 8);
+      *v23 = v22;
+      ++v23;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 15) & 0x1E)), 8);
+      v22 <<= 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 19) & 0x1E)), 8);
+      *v23 = v22;
+      ++v23;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 7) & 0x1E)), 8);
+      v22 <<= 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 11) & 0x1E)), 8);
+      *v23 = v22;
+      ++v23;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint8_t)v24 & 0x1E)), 8);
+      v22 <<= 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 3) & 0x1E)), 8);
+      *v23 = v22;
+      v18 = v23 + 1;
+      v19 = v20 - 1;
+    }
+    while ( v20 != 1 );
+    v7 = &src[(line + (uintptr_t)v17 - (uintptr_t)src) & 0x7FF];
+    v8 = (uint32_t *)((char *)v18 + ext);
+    v9 = v26 - 1;
+  }
+  while ( v26 != 1 );
+}
+
+static inline void load4bIA(uint8_t *src, uint8_t *dst, int wid_64, int height, int line, int ext)
+{
+  uint32_t *v6;
+  uint32_t *v7;
+  int v8;
+  int v9;
+  int v10;
+  uint32_t v11;
+  uint32_t *v12;
+  uint32_t v13;
+  uint32_t v14;
+  uint32_t v15;
+  uint32_t *v16;
+  uint32_t v17;
+  uint32_t v18;
+  uint32_t v19;
+  uint32_t v20;
+  uint32_t v21;
+  uint32_t v22;
+  uint32_t v23;
+  uint32_t v24;
+  uint32_t v25;
+  uint32_t v26;
+  uint32_t v27;
+  uint32_t v28;
+  uint32_t v29;
+  uint32_t v30;
+  uint32_t v31;
+  uint32_t v32;
+  uint32_t *v33;
+  uint32_t *v34;
+  int v35;
+  int v36;
+  uint32_t v37;
+  uint32_t v38;
+  uint32_t v39;
+  uint32_t *v40;
+  uint32_t v41;
+  uint32_t v42;
+  uint32_t v43;
+  uint32_t v44;
+  uint32_t v45;
+  uint32_t v46;
+  uint32_t v47;
+  uint32_t v48;
+  uint32_t v49;
+  uint32_t v50;
+  uint32_t v51;
+  uint32_t v52;
+  uint32_t v53;
+  uint32_t v54;
+  uint32_t v55;
+  uint32_t v56;
+  int v57;
+  int v58;
+
+  v6 = (uint32_t *)src;
+  v7 = (uint32_t *)dst;
+  v8 = height;
+  do
+  {
+    v57 = v8;
+    v9 = wid_64;
+    do
+    {
+      v10 = v9;
+      v11 = bswap32(*v6);
+      v12 = v6 + 1;
+      v13 = v11;
+      v14 = (8 * (v11 & 0x100000)) | (4 * (v11 & 0x100000)) | (2 * (v11 & 0x100000)) | (v11 & 0x100000) | ((((v11 >> 16) & 0xE00) >> 3) & 0x100) | ((v11 >> 16) & 0xE00) | (8 * ((v11 >> 12) & 0x1000)) | (4 * ((v11 >> 12) & 0x1000)) | (2 * ((v11 >> 12) & 0x1000)) | ((v11 >> 12) & 0x1000) | ((((v11 >> 28) & 0xE) >> 3)) | ((v11 >> 28) & 0xE) | (8 * ((v11 >> 24) & 0x10)) | (4 * ((v11 >> 24) & 0x10)) | (2 * ((v11 >> 24) & 0x10)) | ((v11 >> 24) & 0x10);
+      v11 >>= 4;
+      v11 &= 0xE0000u;
+      v15 = v11 | v14;
+      v11 >>= 3;
+      *v7 = ((((v13 << 8) & 0xE000000) >> 3) & 0x1000000) | ((v13 << 8) & 0xE000000) | (8 * ((v13 << 12) & 0x10000000)) | (4 * ((v13 << 12) & 0x10000000)) | (2 * ((v13 << 12) & 0x10000000)) | ((v13 << 12) & 0x10000000) | (v11 & 0x10000) | v15;
+      v16 = v7 + 1;
+      v17 = 16 * (uint16_t)v13 & 0x1000;
+      v18 = (((v13 & 0xE00) >> 3) & 0x100) | (v13 & 0xE00) | (8 * v17) | (4 * v17) | (2 * v17) | (v17) | ((((v13 >> 12) & 0xE) >> 3)) | ((v13 >> 12) & 0xE) | (8 * ((v13 >> 8) & 0x10)) | (4 * ((v13 >> 8) & 0x10)) | (2 * ((v13 >> 8) & 0x10)) | ((v13 >> 8) & 0x10);
+      v19 = v13 << 16;
+      v20 = (8 * (v19 & 0x100000)) | (4 * (v19 & 0x100000)) | (2 * (v19 & 0x100000)) | (v19 & 0x100000) | v18;
+      v21 = v13 << 12;
+      v21 &= 0xE0000u;
+      v22 = v21 | v20;
+      v21 >>= 3;
+      *v16 = ((((v13 << 24) & 0xE000000) >> 3) & 0x1000000) | ((v13 << 24) & 0xE000000) | (8 * ((v13 << 28) & 0x10000000)) | (4 * ((v13 << 28) & 0x10000000)) | (2 * ((v13 << 28) & 0x10000000)) | ((v13 << 28) & 0x10000000) | (v21 & 0x10000) | v22;
+      ++v16;
+      v23 = bswap32(*v12);
+      v6 = v12 + 1;
+      v24 = v23;
+      v25 = (8 * (v23 & 0x100000)) | (4 * (v23 & 0x100000)) | (2 * (v23 & 0x100000)) | (v23 & 0x100000) | ((((v23 >> 16) & 0xE00) >> 3) & 0x100) | ((v23 >> 16) & 0xE00) | (8 * ((v23 >> 12) & 0x1000)) | (4 * ((v23 >> 12) & 0x1000)) | (2 * ((v23 >> 12) & 0x1000)) | ((v23 >> 12) & 0x1000) | (((v23 >> 28) & 0xE) >> 3) | ((v23 >> 28) & 0xE) | (8 * ((v23 >> 24) & 0x10)) | (4 * ((v23 >> 24) & 0x10)) | (2 * ((v23 >> 24) & 0x10)) | ((v23 >> 24) & 0x10);
+      v23 >>= 4;
+      v23 &= 0xE0000u;
+      v26 = v23 | v25;
+      v23 >>= 3;
+      *v16 = ((((v24 << 8) & 0xE000000) >> 3) & 0x1000000) | ((v24 << 8) & 0xE000000) | (8 * ((v24 << 12) & 0x10000000)) | (4 * ((v24 << 12) & 0x10000000)) | (2 * ((v24 << 12) & 0x10000000)) | ((v24 << 12) & 0x10000000) | (v23 & 0x10000) | (v26);
+      ++v16;
+      v27 = 16 * (uint16_t)v24 & 0x1000;
+      v28 = (((v24 & 0xE00) >> 3) & 0x100) | (v24 & 0xE00) | (8 * v27) | (4 * v27) | (2 * v27) | (v27) | ((((v24 >> 12) & 0xE) >> 3)) | ((v24 >> 12) & 0xE) | (8 * ((v24 >> 8) & 0x10)) | (4 * ((v24 >> 8) & 0x10)) | (2 * ((v24 >> 8) & 0x10)) | ((v24 >> 8) & 0x10);
+      v29 = v24 << 16;
+      v30 = (8 * (v29 & 0x100000)) | (4 * (v29 & 0x100000)) | (2 * (v29 & 0x100000)) | (v29 & 0x100000) | v28;
+      v31 = v24 << 12;
+      v31 &= 0xE0000u;
+      v32 = v31 | v30;
+      v31 >>= 3;
+      *v16 = ((((v24 << 24) & 0xE000000) >> 3) & 0x1000000) | ((v24 << 24) & 0xE000000) | (8 * ((v24 << 28) & 0x10000000)) | (4 * ((v24 << 28) & 0x10000000)) | (2 * ((v24 << 28) & 0x10000000)) | ((v24 << 28) & 0x10000000) | (v31 & 0x10000) | v32;
+      v7 = v16 + 1;
+      v9 = v10 - 1;
+    }
+    while ( v10 != 1 );
+    if ( v57 == 1 )
+      break;
+    v58 = v57 - 1;
+    v33 = (uint32_t *)((char *)v6 + line);
+    v34 = (uint32_t *)((char *)v7 + ext);
+    v35 = wid_64;
+    do
+    {
+      v36 = v35;
+      v37 = bswap32(v33[1]);
+      v38 = v37 >> 4;
+      v38 &= 0xE0000u;
+      v39 = v38 | (8 * (v37 & 0x100000)) | (4 * (v37 & 0x100000)) | (2 * (v37 & 0x100000)) | (v37 & 0x100000) | ((((v37 >> 16) & 0xE00) >> 3) & 0x100) | ((v37 >> 16) & 0xE00) | (8 * ((v37 >> 12) & 0x1000)) | (4 * ((v37 >> 12) & 0x1000)) | (2 * ((v37 >> 12) & 0x1000)) | ((v37 >> 12) & 0x1000) | (((v37 >> 28) & 0xE) >> 3) | ((v37 >> 28) & 0xE) | (8 * ((v37 >> 24) & 0x10)) | (4 * ((v37 >> 24) & 0x10)) | (2 * ((v37 >> 24) & 0x10)) | ((v37 >> 24) & 0x10);
+      v38 >>= 3;
+      *v34 = ((((v37 << 8) & 0xE000000) >> 3) & 0x1000000) | ((v37 << 8) & 0xE000000) | (8 * ((v37 << 12) & 0x10000000)) | (4 * ((v37 << 12) & 0x10000000)) | (2 * ((v37 << 12) & 0x10000000)) | ((v37 << 12) & 0x10000000) | (v38 & 0x10000) | v39;
+      v40 = v34 + 1;
+      v41 = 16 * (uint16_t)v37 & 0x1000;
+      v42 = (((v37 & 0xE00) >> 3) & 0x100) | (v37 & 0xE00) | (8 * v41) | (4 * v41) | (2 * v41) | v41 | (((v37 >> 12) & 0xE) >> 3) | ((v37 >> 12) & 0xE) | (8 * ((v37 >> 8) & 0x10)) | (4 * ((v37 >> 8) & 0x10)) | (2 * ((v37 >> 8) & 0x10)) | ((v37 >> 8) & 0x10);
+      v43 = v37 << 16;
+      v44 = (8 * (v43 & 0x100000)) | (4 * (v43 & 0x100000)) | (2 * (v43 & 0x100000)) | (v43 & 0x100000) | v42;
+      v45 = v37 << 12;
+      v45 &= 0xE0000u;
+      v46 = v45 | v44;
+      v45 >>= 3;
+      *v40 = ((((v37 << 24) & 0xE000000) >> 3) & 0x1000000) | ((v37 << 24) & 0xE000000) | (8 * ((v37 << 28) & 0x10000000)) | (4 * ((v37 << 28) & 0x10000000)) | (2 * ((v37 << 28) & 0x10000000)) | ((v37 << 28) & 0x10000000) | (v45 & 0x10000) | v46;
+      ++v40;
+      v47 = bswap32(*v33);
+      v33 += 2;
+      v48 = v47;
+      v49 = (8 * (v47 & 0x100000)) | (4 * (v47 & 0x100000)) | (2 * (v47 & 0x100000)) | (v47 & 0x100000) | ((((v47 >> 16) & 0xE00) >> 3) & 0x100) | ((v47 >> 16) & 0xE00) | (8 * ((v47 >> 12) & 0x1000)) | (4 * ((v47 >> 12) & 0x1000)) | (2 * ((v47 >> 12) & 0x1000)) | ((v47 >> 12) & 0x1000) | (((v47 >> 28) & 0xE) >> 3) | ((v47 >> 28) & 0xE) | (8 * ((v47 >> 24) & 0x10)) | (4 * ((v47 >> 24) & 0x10)) | (2 * ((v47 >> 24) & 0x10)) | ((v47 >> 24) & 0x10);
+      v47 >>= 4;
+      v47 &= 0xE0000u;
+      v50 = v47 | v49;
+      v47 >>= 3;
+      *v40 = ((((v48 << 8) & 0xE000000) >> 3) & 0x1000000) | ((v48 << 8) & 0xE000000) | (8 * ((v48 << 12) & 0x10000000)) | (4 * ((v48 << 12) & 0x10000000)) | (2 * ((v48 << 12) & 0x10000000)) | ((v48 << 12) & 0x10000000) | (v47 & 0x10000) | v50;
+      ++v40;
+      v51 = 16 * (uint16_t)v48 & 0x1000;
+      v52 = (((v48 & 0xE00) >> 3) & 0x100) | (v48 & 0xE00) | (8 * v51) | (4 * v51) | (2 * v51) | v51 | (((v48 >> 12) & 0xE) >> 3) | ((v48 >> 12) & 0xE) | (8 * ((v48 >> 8) & 0x10)) | (4 * ((v48 >> 8) & 0x10)) | (2 * ((v48 >> 8) & 0x10)) | ((v48 >> 8) & 0x10);
+      v53 = v48 << 16;
+      v54 = (8 * (v53 & 0x100000)) | (4 * (v53 & 0x100000)) | (2 * (v53 & 0x100000)) | (v53 & 0x100000) | v52;
+      v55 = v48 << 12;
+      v55 &= 0xE0000u;
+      v56 = v55 | v54;
+      v55 >>= 3;
+      *v40 = ((((v48 << 24) & 0xE000000) >> 3) & 0x1000000) | ((v48 << 24) & 0xE000000) | (8 * ((v48 << 28) & 0x10000000)) | (4 * ((v48 << 28) & 0x10000000)) | (2 * ((v48 << 28) & 0x10000000)) | ((v48 << 28) & 0x10000000) | (v55 & 0x10000) | v56;
+      v34 = v40 + 1;
+      v35 = v36 - 1;
+    }
+    while ( v36 != 1 );
+    v6 = (uint32_t *)((char *)v33 + line);
+    v7 = (uint32_t *)((char *)v34 + ext);
+    v8 = v58 - 1;
+  }
+  while ( v58 != 1 );
+}
+
+static inline void load4bI(uint8_t *src, uint8_t *dst, int wid_64, int height, int line, int ext)
+{
+  uint32_t *v6;
+  uint32_t *v7;
+  int v8;
+  int v9;
+  int v10;
+  uint32_t v11;
+  uint32_t *v12;
+  uint32_t v13;
+  uint32_t v14;
+  uint32_t *v15;
+  uint32_t v16;
+  unsigned int v17;
+  unsigned int v18;
+  uint32_t v19;
+  uint32_t v20;
+  uint32_t *v21;
+  uint32_t *v22;
+  int v23;
+  int v24;
+  uint32_t v25;
+  uint32_t v26;
+  uint32_t *v27;
+  uint32_t v28;
+  uint32_t v29;
+  uint32_t v30;
+  uint32_t v31;
+  uint32_t v32;
+  int v33;
+  int v34;
+
+  v6 = (uint32_t *)src;
+  v7 = (uint32_t *)dst;
+  v8 = height;
+  do
+  {
+    v33 = v8;
+    v9 = wid_64;
+    do
+    {
+      v10 = v9;
+      v11 = bswap32(*v6);
+      v12 = v6 + 1;
+      v13 = v11;
+      v14 = (16 * ((v11 >> 16) & 0xF00)) | ((v11 >> 16) & 0xF00) | (16 * (v11 >> 28)) | (v11 >> 28);
+      v11 >>= 4;
+      *v7 = (16 * ((v13 << 8) & 0xF000000)) | ((v13 << 8) & 0xF000000) | (16 * (v11 & 0xF0000)) | (v11 & 0xF0000) | v14;
+      v15 = v7 + 1;
+      v16 = v13 << 12;
+      *v15 = (16 * ((v13 << 24) & 0xF000000)) | ((v13 << 24) & 0xF000000) | (16 * (v16 & 0xF0000)) | (v16 & 0xF0000) | (16 * (v13 & 0xF00)) | (v13 & 0xF00) | (16 * ((uint16_t)v13 >> 12)) | ((uint16_t)v13 >> 12);
+      ++v15;
+      v17 = bswap32(*v12);
+      v6 = v12 + 1;
+      v18 = v17;
+      v19 = (16 * ((v17 >> 16) & 0xF00)) | ((v17 >> 16) & 0xF00) | (16 * (v17 >> 28)) | (v17 >> 28);
+      v17 >>= 4;
+      *v15 = (16 * ((v18 << 8) & 0xF000000)) | ((v18 << 8) & 0xF000000) | (16 * (v17 & 0xF0000)) | (v17 & 0xF0000) | v19;
+      ++v15;
+      v20 = v18 << 12;
+      *v15 = (16 * ((v18 << 24) & 0xF000000)) | ((v18 << 24) & 0xF000000) | (16 * (v20 & 0xF0000)) | (v20 & 0xF0000) | (16 * (v18 & 0xF00)) | (v18 & 0xF00) | (16 * ((uint16_t)v18 >> 12)) | ((uint16_t)v18 >> 12);
+      v7 = v15 + 1;
+      v9 = v10 - 1;
+    }
+    while ( v10 != 1 );
+    if ( v33 == 1 )
+      break;
+    v34 = v33 - 1;
+    v21 = (uint32_t *)((char *)v6 + line);
+    v22 = (uint32_t *)((char *)v7 + ext);
+    v23 = wid_64;
+    do
+    {
+      v24 = v23;
+      v25 = bswap32(v21[1]);
+      v26 = v25 >> 4;
+      *v22 = (16 * ((v25 << 8) & 0xF000000)) | ((v25 << 8) & 0xF000000) | (16 * (v26 & 0xF0000)) | (v26 & 0xF0000) | (16 * ((v25 >> 16) & 0xF00)) | ((v25 >> 16) & 0xF00) | (16 * (v25 >> 28)) | (v25 >> 28);
+      v27 = v22 + 1;
+      v28 = v25 << 12;
+      *v27 = (16 * ((v25 << 24) & 0xF000000)) | ((v25 << 24) & 0xF000000) | (16 * (v28 & 0xF0000)) | (v28 & 0xF0000) | (16 * (v25 & 0xF00)) | (v25 & 0xF00) | (16 * ((uint16_t)v25 >> 12)) | ((uint16_t)v25 >> 12);
+      ++v27;
+      v29 = bswap32(*v21);
+      v21 += 2;
+      v30 = v29;
+      v31 = (16 * ((v29 >> 16) & 0xF00)) | ((v29 >> 16) & 0xF00) | (16 * (v29 >> 28)) | (v29 >> 28);
+      v29 >>= 4;
+      *v27 = (16 * ((v30 << 8) & 0xF000000)) | ((v30 << 8) & 0xF000000) | (16 * (v29 & 0xF0000)) | (v29 & 0xF0000) | v31;
+      ++v27;
+      v32 = v30 << 12;
+      *v27 = (16 * ((v30 << 24) & 0xF000000)) | ((v30 << 24) & 0xF000000) | (16 * (v32 & 0xF0000)) | (v32 & 0xF0000) | (16 * (v30 & 0xF00)) | (v30 & 0xF00) | (16 * ((uint16_t)v30 >> 12)) | ((uint16_t)v30 >> 12);
+      v22 = v27 + 1;
+      v23 = v24 - 1;
+    }
+    while ( v24 != 1 );
+    v6 = (uint32_t *)((char *)v21 + line);
+    v7 = (uint32_t *)((char *)v22 + ext);
+    v8 = v34 - 1;
+  }
+  while ( v34 != 1 );
+}
+
+//****************************************************************
+// Size: 0, Format: 2
+
+wxUint32 Load4bCI (wxUIntPtr dst, wxUIntPtr src, int wid_64, int height, int line, int real_width, int tile)
+{
+  if (wid_64 < 1) wid_64 = 1;
+  if (height < 1) height = 1;
+  int ext = (real_width - (wid_64 << 4)) << 1;
+
+  if (rdp.tlut_mode == 0)
+  {
+    //in tlut DISABLE mode load CI texture as plain intensity texture instead of palette dereference.
+    //Thanks to angrylion for the advice
+    load4bI ((uint8_t *)src, (uint8_t *)dst, wid_64, height, line, ext);
+    return /*(0 << 16) | */GR_TEXFMT_ALPHA_INTENSITY_44;
+  }
+
+  wxUIntPtr pal = wxPtrToUInt(rdp.pal_8 + (rdp.tiles[tile].palette << 4));
+  if (rdp.tlut_mode == 2)
+  {
+    load4bCI ((uint8_t *)src, (uint8_t *)dst, wid_64, height, line, ext, (uint16_t *)pal);
+    
+    return (1 << 16) | GR_TEXFMT_ARGB_1555;
+  }
+
+    load4bIAPal ((uint8_t *)src, (uint8_t *)dst, wid_64, height, line, ext, (uint16_t *)pal);
+  return (1 << 16) | GR_TEXFMT_ALPHA_INTENSITY_88;
+}
+
+//****************************************************************
+// Size: 0, Format: 3
+//
+// ** BY GUGAMAN **
+
+wxUint32 Load4bIA (wxUIntPtr dst, wxUIntPtr 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));
+  load4bIA ((uint8_t *)src, (uint8_t *)dst, wid_64, height, line, ext);
+  return /*(0 << 16) | */GR_TEXFMT_ALPHA_INTENSITY_44;
+}
+
+//****************************************************************
+// Size: 0, Format: 4
+
+wxUint32 Load4bI (wxUIntPtr dst, wxUIntPtr 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));
+  load4bI ((uint8_t *)src, (uint8_t *)dst, wid_64, height, line, ext);
+  
+  return /*(0 << 16) | */GR_TEXFMT_ALPHA_INTENSITY_44;
+}
+
+//****************************************************************
+// Size: 0, Format: 0
+
+wxUint32 Load4bSelect (wxUIntPtr dst, wxUIntPtr 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/source/gles2glide64/src/Glide64/TexLoad8b.h b/source/gles2glide64/src/Glide64/TexLoad8b.h
new file mode 100644 (file)
index 0000000..85d7358
--- /dev/null
@@ -0,0 +1,434 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+#include <stdint.h>
+
+static inline void load8bCI(uint8_t *src, uint8_t *dst, int wid_64, int height, int line, int ext, uint16_t *pal)
+{
+  uint8_t *v7;
+  uint32_t *v8;
+  int v9;
+  int v10;
+  int v11;
+  uint32_t v12;
+  uint32_t *v13;
+  uint32_t v14;
+  uint32_t *v15;
+  uint32_t v16;
+  uint32_t *v17;
+  uint32_t *v18;
+  int v19;
+  int v20;
+  uint32_t v21;
+  uint32_t v22;
+  uint32_t *v23;
+  uint32_t v24;
+  int v25;
+  int v26;
+
+  v7 = src;
+  v8 = (uint32_t *)dst;
+  v9 = height;
+  do
+  {
+    v25 = v9;
+    v10 = wid_64;
+    do
+    {
+      v11 = v10;
+      v12 = bswap32(*(uint32_t *)v7);
+      v13 = (uint32_t *)(v7 + 4);
+      ALOWORD(v10) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 15) & 0x1FE)), 1);
+      v14 = v10 << 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 23) & 0x1FE)), 1);
+      *v8 = v14;
+      v15 = v8 + 1;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint16_t)v12 & 0x1FE)), 1);
+      v14 <<= 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 7) & 0x1FE)), 1);
+      *v15 = v14;
+      ++v15;
+      v16 = bswap32(*v13);
+      v7 = (uint8_t *)(v13 + 1);
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 15) & 0x1FE)), 1);
+      v14 <<= 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 23) & 0x1FE)), 1);
+      *v15 = v14;
+      ++v15;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint16_t)v16 & 0x1FE)), 1);
+      v14 <<= 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 7) & 0x1FE)), 1);
+      *v15 = v14;
+      v8 = v15 + 1;
+      v10 = v11 - 1;
+    }
+    while ( v11 != 1 );
+    if ( v25 == 1 )
+      break;
+    v26 = v25 - 1;
+    v17 = (uint32_t *)&src[(line + (uintptr_t)v7 - (uintptr_t)src) & 0x7FF];
+    v18 = (uint32_t *)((char *)v8 + ext);
+    v19 = wid_64;
+    do
+    {
+      v20 = v19;
+      v21 = bswap32(v17[1]);
+      ALOWORD(v19) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 15) & 0x1FE)), 1);
+      v22 = v19 << 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 23) & 0x1FE)), 1);
+      *v18 = v22;
+      v23 = v18 + 1;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint16_t)v21 & 0x1FE)), 1);
+      v22 <<= 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 7) & 0x1FE)), 1);
+      *v23 = v22;
+      ++v23;
+      v24 = bswap32(*v17);
+      v17 = (uint32_t *)&src[((uintptr_t)v17 + 8 - (uintptr_t)src) & 0x7FF];
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 15) & 0x1FE)), 1);
+      v22 <<= 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 23) & 0x1FE)), 1);
+      *v23 = v22;
+      ++v23;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint16_t)v24 & 0x1FE)), 1);
+      v22 <<= 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 7) & 0x1FE)), 1);
+      *v23 = v22;
+      v18 = v23 + 1;
+      v19 = v20 - 1;
+    }
+    while ( v20 != 1 );
+    v7 = &src[(line + (uintptr_t)v17 - (uintptr_t)src) & 0x7FF];
+    v8 = (uint32_t *)((char *)v18 + ext);
+    v9 = v26 - 1;
+  }
+  while ( v26 != 1 );
+}
+
+static inline void load8bIA8(uint8_t *src, uint8_t *dst, int wid_64, int height, int line, int ext, uint16_t *pal)
+{
+  uint32_t *v7;
+  uint32_t *v8;
+  int v9;
+  int v10;
+  int v11;
+  uint32_t v12;
+  uint32_t *v13;
+  uint32_t v14;
+  uint32_t *v15;
+  uint32_t v16;
+  uint32_t *v17;
+  uint32_t *v18;
+  int v19;
+  int v20;
+  uint32_t v21;
+  uint32_t v22;
+  uint32_t *v23;
+  uint32_t v24;
+  int v25;
+  int v26;
+
+  v7 = (uint32_t *)src;
+  v8 = (uint32_t *)dst;
+  v9 = height;
+  do
+  {
+    v25 = v9;
+    v10 = wid_64;
+    do
+    {
+      v11 = v10;
+      v12 = bswap32(*v7);
+      v13 = v7 + 1;
+      ALOWORD(v10) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 15) & 0x1FE)), 8);
+      v14 = v10 << 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 23) & 0x1FE)), 8);
+      *v8 = v14;
+      v15 = v8 + 1;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint16_t)v12 & 0x1FE)), 8);
+      v14 <<= 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v12 >> 7) & 0x1FE)), 8);
+      *v15 = v14;
+      ++v15;
+      v16 = bswap32(*v13);
+      v7 = v13 + 1;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 15) & 0x1FE)), 8);
+      v14 <<= 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 23) & 0x1FE)), 8);
+      *v15 = v14;
+      ++v15;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint16_t)v16 & 0x1FE)), 8);
+      v14 <<= 16;
+      ALOWORD(v14) = __ROR__(*(uint16_t *)((char *)pal + ((v16 >> 7) & 0x1FE)), 8);
+      *v15 = v14;
+      v8 = v15 + 1;
+      v10 = v11 - 1;
+    }
+    while ( v11 != 1 );
+    if ( v25 == 1 )
+      break;
+    v26 = v25 - 1;
+    v17 = (uint32_t *)((char *)v7 + line);
+    v18 = (uint32_t *)((char *)v8 + ext);
+    v19 = wid_64;
+    do
+    {
+      v20 = v19;
+      v21 = bswap32(v17[1]);
+      ALOWORD(v19) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 15) & 0x1FE)), 8);
+      v22 = v19 << 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 23) & 0x1FE)), 8);
+      *v18 = v22;
+      v23 = v18 + 1;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint16_t)v21 & 0x1FE)), 8);
+      v22 <<= 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v21 >> 7) & 0x1FE)), 8);
+      *v23 = v22;
+      ++v23;
+      v24 = bswap32(*v17);
+      v17 += 2;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 15) & 0x1FE)), 8);
+      v22 <<= 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 23) & 0x1FE)), 8);
+      *v23 = v22;
+      ++v23;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + (2 * (uint16_t)v24 & 0x1FE)), 8);
+      v22 <<= 16;
+      ALOWORD(v22) = __ROR__(*(uint16_t *)((char *)pal + ((v24 >> 7) & 0x1FE)), 8);
+      *v23 = v22;
+      v18 = v23 + 1;
+      v19 = v20 - 1;
+    }
+    while ( v20 != 1 );
+    v7 = (uint32_t *)((char *)v17 + line);
+    v8 = (uint32_t *)((char *)v18 + ext);
+    v9 = v26 - 1;
+  }
+  while ( v26 != 1 );
+}
+
+static inline void load8bIA4(uint8_t *src, uint8_t *dst, int wid_64, int height, int line, int ext)
+{
+  uint32_t *v6;
+  uint32_t *v7;
+  int v8;
+  int v9;
+  uint32_t v10;
+  uint32_t v11;
+  uint32_t *v12;
+  uint32_t *v13;
+  uint32_t v14;
+  uint32_t v15;
+  uint32_t *v16;
+  uint32_t *v17;
+  int v18;
+  uint32_t *v19;
+  uint32_t v20;
+  int v21;
+  int v22;
+
+  v6 = (uint32_t *)src;
+  v7 = (uint32_t *)dst;
+  v8 = height;
+  do
+  {
+    v21 = v8;
+    v9 = wid_64;
+    do
+    {
+      v10 = *v6;
+      v11 = (*v6 >> 4) & 0xF0F0F0F;
+      v12 = v6 + 1;
+      *v7 = (16 * v10 & 0xF0F0F0F0) | v11;
+      v13 = v7 + 1;
+      v14 = (*v12 >> 4) & 0xF0F0F0F;
+      v15 = 16 * *v12 & 0xF0F0F0F0;
+      v6 = v12 + 1;
+      *v13 = v15 | v14;
+      v7 = v13 + 1;
+      --v9;
+    }
+    while ( v9 );
+    if ( v21 == 1 )
+      break;
+    v22 = v21 - 1;
+    v16 = (uint32_t *)((char *)v6 + line);
+    v17 = (uint32_t *)((char *)v7 + ext);
+    v18 = wid_64;
+    do
+    {
+      *v17 = (16 * v16[1] & 0xF0F0F0F0) | ((v16[1] >> 4) & 0xF0F0F0F);
+      v19 = v17 + 1;
+      v20 = *v16;
+      v16 += 2;
+      *v19 = (16 * v20 & 0xF0F0F0F0) | ((v20 >> 4) & 0xF0F0F0F);
+      v17 = v19 + 1;
+      --v18;
+    }
+    while ( v18 );
+    v6 = (uint32_t *)((char *)v16 + line);
+    v7 = (uint32_t *)((char *)v17 + ext);
+    v8 = v22 - 1;
+  }
+  while ( v22 != 1 );
+}
+
+static inline void load8bI(uint8_t *src, uint8_t *dst, int wid_64, int height, int line, int ext)
+{
+  uint32_t *v6;
+  uint32_t *v7;
+  int v8;
+  int v9;
+  uint32_t v10;
+  uint32_t *v11;
+  uint32_t *v12;
+  uint32_t v13;
+  uint32_t *v14;
+  uint32_t *v15;
+  int v16;
+  uint32_t *v17;
+  uint32_t v18;
+  int v19;
+  int v20;
+
+  v6 = (uint32_t *)src;
+  v7 = (uint32_t *)dst;
+  v8 = height;
+  do
+  {
+    v19 = v8;
+    v9 = wid_64;
+    do
+    {
+      v10 = *v6;
+      v11 = v6 + 1;
+      *v7 = v10;
+      v12 = v7 + 1;
+      v13 = *v11;
+      v6 = v11 + 1;
+      *v12 = v13;
+      v7 = v12 + 1;
+      --v9;
+    }
+    while ( v9 );
+    if ( v19 == 1 )
+      break;
+    v20 = v19 - 1;
+    v14 = (uint32_t *)((char *)v6 + line);
+    v15 = (uint32_t *)((char *)v7 + ext);
+    v16 = wid_64;
+    do
+    {
+      *v15 = v14[1];
+      v17 = v15 + 1;
+      v18 = *v14;
+      v14 += 2;
+      *v17 = v18;
+      v15 = v17 + 1;
+      --v16;
+    }
+    while ( v16 );
+    v6 = (uint32_t *)((char *)v14 + line);
+    v7 = (uint32_t *)((char *)v15 + ext);
+    v8 = v20 - 1;
+  }
+  while ( v20 != 1 );
+}
+
+//****************************************************************
+// Size: 1, Format: 2
+//
+
+wxUint32 Load8bCI (wxUIntPtr dst, wxUIntPtr 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));
+  unsigned short * pal = rdp.pal_8;
+
+  switch (rdp.tlut_mode) {
+    case 0: //palette is not used
+      //in tlut DISABLE mode load CI texture as plain intensity texture instead of palette dereference.
+      //Thanks to angrylion for the advice
+      load8bI ((uint8_t *)src, (uint8_t *)dst, wid_64, height, line, ext);
+      return /*(0 << 16) | */GR_TEXFMT_ALPHA_8;
+    case 2: //color palette
+      ext <<= 1;
+      load8bCI ((uint8_t *)src, (uint8_t *)dst, wid_64, height, line, ext, pal);
+      return (1 << 16) | GR_TEXFMT_ARGB_1555;
+    default: //IA palette
+      ext <<= 1;
+      load8bIA8 ((uint8_t *)src, (uint8_t *)dst, wid_64, height, line, ext, pal);
+      return (1 << 16) | GR_TEXFMT_ALPHA_INTENSITY_88;
+  }
+}
+
+//****************************************************************
+// Size: 1, Format: 3
+//
+// ** by Gugaman **
+
+wxUint32 Load8bIA (wxUIntPtr dst, wxUIntPtr 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));
+  load8bIA4 ((uint8_t *)src, (uint8_t *)dst, wid_64, height, line, ext);
+  return /*(0 << 16) | */GR_TEXFMT_ALPHA_INTENSITY_44;
+} 
+
+//****************************************************************
+// Size: 1, Format: 4
+//
+// ** by Gugaman **
+
+wxUint32 Load8bI (wxUIntPtr dst, wxUIntPtr 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));
+  load8bI ((uint8_t *)src, (uint8_t *)dst, wid_64, height, line, ext);
+  return /*(0 << 16) | */GR_TEXFMT_ALPHA_8;
+}
+
diff --git a/source/gles2glide64/src/Glide64/TexMod.h b/source/gles2glide64/src/Glide64/TexMod.h
new file mode 100644 (file)
index 0000000..a60f57f
--- /dev/null
@@ -0,0 +1,577 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+static void mod_tex_inter_color_using_factor (wxUint16 *dst, int size, wxUint32 color, wxUint32 factor)
+{
+       float percent = factor / 255.0f;
+       float percent_i = 1 - percent;
+       wxUint32 cr, cg, cb;
+       wxUint16 col, a;
+       wxUint8 r, g, b;
+
+       cr = (color >> 12) & 0xF;
+       cg = (color >> 8) & 0xF;
+       cb = (color >> 4) & 0xF;
+
+       for (int i=0; i<size; i++)
+       {
+               col = *dst;
+               a = col & 0xF000;
+               r = (wxUint8)(percent_i * ((col >> 8) & 0xF) + percent * cr);
+               g = (wxUint8)(percent_i * ((col >> 4) & 0xF) + percent * cg);
+               b = (wxUint8)(percent_i * (col & 0xF) + percent * cb);
+               *(dst++) = a | (r << 8) | (g << 4) | b;
+       }
+}
+
+static void mod_tex_inter_col_using_col1 (wxUint16 *dst, int size, wxUint32 color0, wxUint32 color1)
+{
+       wxUint32 cr, cg, cb;
+       wxUint16 col, a;
+       wxUint8 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<size; i++)
+       {
+               col = *dst;
+               a = col & 0xF000;
+               r = (wxUint8)(percent_r_i * ((col >> 8) & 0xF) + percent_r * cr);
+               g = (wxUint8)(percent_g_i * ((col >> 4) & 0xF) + percent_g * cg);
+               b = (wxUint8)(percent_b_i * (col & 0xF) + percent_b * cb);
+               *(dst++) = a | (r << 8) | (g << 4) | b;
+       }
+}
+
+static void mod_full_color_sub_tex (wxUint16 *dst, int size, wxUint32 color)
+{
+       wxUint32 cr, cg, cb, ca;
+       wxUint16 col;
+       wxUint8 a, r, g, b;
+
+       cr = (color >> 12) & 0xF;
+       cg = (color >> 8) & 0xF;
+       cb = (color >> 4) & 0xF;
+       ca = color & 0xF;
+
+       for (int i=0; i<size; i++)
+       {
+               col = *dst;
+               a = (wxUint8)(ca - ((col >> 12) & 0xF));
+               r = (wxUint8)(cr - ((col >> 8) & 0xF));
+               g = (wxUint8)(cg - ((col >> 4) & 0xF));
+               b = (wxUint8)(cb - (col & 0xF));
+               *(dst++) = (a << 12) | (r << 8) | (g << 4) | b;
+       }
+}
+
+static void mod_col_inter_col1_using_tex (wxUint16 *dst, int size, wxUint32 color0, wxUint32 color1)
+{
+       wxUint32 cr0, cg0, cb0, cr1, cg1, cb1;
+       wxUint16 col;
+       wxUint8 r, g, b;
+       wxUint16 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<size; i++)
+       {
+               col = *dst;
+               a = col & 0xF000;
+               percent_r = ((col >> 8) & 0xF) / 15.0f;
+               percent_g = ((col >> 4) & 0xF) / 15.0f;
+               percent_b = (col & 0xF) / 15.0f;
+               r = min(15, (wxUint8)((1.0f-percent_r) * cr0 + percent_r * cr1 + 0.0001f));
+               g = min(15, (wxUint8)((1.0f-percent_g) * cg0 + percent_g * cg1 + 0.0001f));
+               b = min(15, (wxUint8)((1.0f-percent_b) * cb0 + percent_b * cb1 + 0.0001f));
+               *(dst++) = a | (r << 8) | (g << 4) | b;
+       }
+}
+
+static void mod_col_inter_col1_using_texa (wxUint16 *dst, int size, wxUint32 color0, wxUint32 color1)
+{
+       wxUint32 cr0, cg0, cb0, cr1, cg1, cb1;
+       wxUint16 col;
+       wxUint8 r, g, b;
+       wxUint16 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<size; i++)
+       {
+               col = *dst;
+               a = col & 0xF000;
+               percent = (a >> 12) / 15.0f;
+               percent_i = 1.0f - percent;
+               r = (wxUint8)(percent_i * cr0 + percent * cr1);
+               g = (wxUint8)(percent_i * cg0 + percent * cg1);
+               b = (wxUint8)(percent_i * cb0 + percent * cb1);
+               *(dst++) = a | (r << 8) | (g << 4) | b;
+       }
+}
+
+static void mod_col_inter_col1_using_texa__mul_tex (wxUint16 *dst, int size, wxUint32 color0, wxUint32 color1)
+{
+       wxUint32 cr0, cg0, cb0, cr1, cg1, cb1;
+       wxUint16 col;
+       wxUint8 r, g, b;
+       wxUint16 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<size; i++)
+       {
+               col = *dst;
+               a = col & 0xF000;
+               percent = (a >> 12) / 15.0f;
+               percent_i = 1.0f - percent;
+               r = (wxUint8)(((percent_i * cr0 + percent * cr1) / 15.0f) * (((col & 0x0F00) >> 8) / 15.0f) * 15.0f);
+               g = (wxUint8)(((percent_i * cg0 + percent * cg1) / 15.0f) * (((col & 0x00F0) >> 4) / 15.0f) * 15.0f);
+               b = (wxUint8)(((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 (wxUint16 *dst, int size, wxUint32 color)
+{
+       wxUint32 cr, cg, cb;
+       wxUint16 col;
+       wxUint8 r, g, b;
+       wxUint16 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<size; i++)
+       {
+               col = *dst;
+               a = col & 0xF000;
+               percent_r = ((col >> 8) & 0xF) / 15.0f;
+               percent_g = ((col >> 4) & 0xF) / 15.0f;
+               percent_b = (col & 0xF) / 15.0f;
+               r = (wxUint8)((1.0f-percent_r) * cr + percent_r * ((col & 0x0F00) >> 8));
+               g = (wxUint8)((1.0f-percent_g) * cg + percent_g * ((col & 0x00F0) >> 4));
+               b = (wxUint8)((1.0f-percent_b) * cb + percent_b * (col & 0x000F));       
+               *(dst++) = a | (r << 8) | (g << 4) | b;
+       }
+}
+
+static void mod_col_inter_tex_using_texa (wxUint16 *dst, int size, wxUint32 color)
+{
+       wxUint32 cr, cg, cb;
+       wxUint16 col;
+       wxUint8 r, g, b;
+       wxUint16 a;
+       float percent, percent_i;
+
+       cr = (color >> 12) & 0xF;
+       cg = (color >> 8) & 0xF;
+       cb = (color >> 4) & 0xF;
+
+       for (int i=0; i<size; i++)
+       {
+               col = *dst;
+               a = col & 0xF000;
+               percent = (a >> 12) / 15.0f;
+               percent_i = 1.0f - percent;
+               r = (wxUint8)(percent_i * cr + percent * ((col & 0x0F00) >> 8));
+               g = (wxUint8)(percent_i * cg + percent * ((col & 0x00F0) >> 4));
+               b = (wxUint8)(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 (wxUint16 *dst, int size,
+                                                                                                                                 wxUint32 color0, wxUint32 color1,
+                                                                                                                                 wxUint32 color2)
+{
+       wxUint32 cr0, cg0, cb0, cr1, cg1, cb1, cr2, cg2, cb2;
+       wxUint16 col;
+       wxUint8 r, g, b;
+       wxUint16 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<size; i++)
+       {
+               col = *dst;
+               a = col & 0xF000;
+               percent_a = (a >> 12) / 15.0f;
+               percent_r = ((col >> 8) & 0xF) / 15.0f;
+               percent_g = ((col >> 4) & 0xF) / 15.0f;
+               percent_b = (col & 0xF) / 15.0f;
+               r = (wxUint8)(((1.0f-percent_r) * cr0 + percent_r * cr1) * percent_a + cr2 * (1.0f-percent_a));
+               g = (wxUint8)(((1.0f-percent_g) * cg0 + percent_g * cg1) * percent_a + cg2 * (1.0f-percent_a));
+               b = (wxUint8)(((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 (wxUint16 *dst, int size, wxUint32 factor)
+{
+       float percent = factor / 255.0f;
+       wxUint16 col;
+       wxUint8 a;
+       float base_a = (1.0f - percent) * 15.0f;
+
+       for (int i=0; i<size; i++)
+       {
+               col = *dst;
+               a = (wxUint8)(base_a + percent * (col>>12));
+               *(dst++) = (a<<12) | (col & 0x0FFF);
+       }
+}
+
+static void mod_tex_sub_col_mul_fac_add_tex (wxUint16 *dst, int size, wxUint32 color, wxUint32 factor)
+{
+       float percent = factor / 255.0f;
+       wxUint32 cr, cg, cb;
+       wxUint16 col, a;
+       float r, g, b;
+
+       cr = (color >> 12) & 0xF;
+       cg = (color >> 8) & 0xF;
+       cb = (color >> 4) & 0xF;
+
+       for (int i=0; i<size; i++)
+       {
+               col = *dst;
+               a = col & 0xF000;
+               r = (float)((col >> 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 | ((wxUint16)r << 8) | ((wxUint16)g << 4) | (wxUint16)b;
+       }
+}
+
+static void mod_tex_scale_col_add_col (wxUint16 *dst, int size, wxUint32 color0, wxUint32 color1)
+{
+       wxUint32 cr0, cg0, cb0, cr1, cg1, cb1;
+       wxUint16 col;
+       wxUint8 r, g, b;
+       wxUint16 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<size; i++)
+       {
+               col = *dst;
+               a = col & 0xF000;
+               percent_r = ((col >> 8) & 0xF) / 15.0f;
+               percent_g = ((col >> 4) & 0xF) / 15.0f;
+               percent_b = (col & 0xF) / 15.0f;
+               r = min(15, (wxUint8)(percent_r * cr0 + cr1 + 0.0001f));
+               g = min(15, (wxUint8)(percent_g * cg0 + cg1 + 0.0001f));
+               b = min(15, (wxUint8)(percent_b * cb0 + cb1 + 0.0001f));
+               *(dst++) = a | (r << 8) | (g << 4) | b;
+       }
+}
+
+static void mod_tex_add_col (wxUint16 *dst, int size, wxUint32 color)
+{
+       wxUint32 cr, cg, cb;
+       wxUint16 col;
+       wxUint8 a, r, g, b;
+
+       cr = (color >> 12) & 0xF;
+       cg = (color >> 8) & 0xF;
+       cb = (color >> 4) & 0xF;
+
+       for (int i=0; i<size; i++)
+       {
+               col = *dst;
+               a = (wxUint8)((col >> 12) & 0xF);
+//             a = col & 0xF000;
+               r = (wxUint8)(cr + ((col >> 8) & 0xF))&0xF;
+               g = (wxUint8)(cg + ((col >> 4) & 0xF))&0xF;
+               b = (wxUint8)(cb + (col & 0xF))&0xF;
+               *(dst++) = (a << 12) | (r << 8) | (g << 4) | b;
+       }
+}
+
+static void mod_col_mul_texa_add_tex (wxUint16 *dst, int size, wxUint32 color)
+{
+       wxUint32 cr, cg, cb;
+       wxUint16 col;
+       wxUint8 r, g, b;
+       wxUint16 a;
+       float factor;
+
+       cr = (color >> 12) & 0xF;
+       cg = (color >> 8) & 0xF;
+       cb = (color >> 4) & 0xF;
+
+       for (int i=0; i<size; i++)
+       {
+               col = *dst;
+               a = col & 0xF000;
+               factor = (a >> 12) / 15.0f;
+               r = (wxUint8)(cr*factor + ((col >> 8) & 0xF))&0xF;
+               g = (wxUint8)(cg*factor + ((col >> 4) & 0xF))&0xF;
+               b = (wxUint8)(cb*factor + (col & 0xF))&0xF;
+               *(dst++) = a | (r << 8) | (g << 4) | b;
+       }
+}
+
+static void mod_tex_sub_col (wxUint16 *dst, int size, wxUint32 color)
+{
+       int cr, cg, cb;
+       wxUint16 col;
+       wxUint8 a, r, g, b;
+
+       cr = (color >> 12) & 0xF;
+       cg = (color >> 8) & 0xF;
+       cb = (color >> 4) & 0xF;
+
+       for (int i=0; i<size; i++)
+       {
+               col = *dst;
+               a = (wxUint8)(col & 0xF000);
+               r = (wxUint8)max((((col >> 8) & 0xF) - cr), 0);
+               g = (wxUint8)max((((col >> 4) & 0xF) - cg), 0);
+               b = (wxUint8)max(((col & 0xF) - cb), 0);
+               *(dst++) = (a << 12) | (r << 8) | (g << 4) | b;
+       }
+}
+
+static void mod_tex_sub_col_mul_fac (wxUint16 *dst, int size, wxUint32 color, wxUint32 factor)
+{
+       float percent = factor / 255.0f;
+       wxUint32 cr, cg, cb;
+       wxUint16 col, a;
+       float r, g, b;
+
+       cr = (color >> 12) & 0xF;
+       cg = (color >> 8) & 0xF;
+       cb = (color >> 4) & 0xF;
+
+       for (int i=0; i<size; i++)
+       {
+               col = *dst;
+               a = (wxUint8)((col >> 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) | ((wxUint16)r << 8) | ((wxUint16)g << 4) | (wxUint16)b;
+       }
+}
+
+static void mod_col_inter_tex_using_col1 (wxUint16 *dst, int size, wxUint32 color0, wxUint32 color1)
+{
+       wxUint32 cr, cg, cb;
+       wxUint16 col, a;
+       wxUint8 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<size; i++)
+       {
+               col = *dst;
+               a = (wxUint8)((col >> 12) & 0xF);
+               r = (wxUint8)(percent_r * ((col >> 8) & 0xF) + percent_r_i * cr);
+               g = (wxUint8)(percent_g * ((col >> 4) & 0xF) + percent_g_i * cg);
+               b = (wxUint8)(percent_b * (col & 0xF) + percent_b_i * cb);
+               *(dst++) = (a << 12) | (r << 8) | (g << 4) | b;
+       }
+}
+
+static void mod_tex_inter_noise_using_col (wxUint16 *dst, int size, wxUint32 color)
+{
+       wxUint16 col, a;
+       wxUint8 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<size; i++)
+       {
+               col = *dst;
+               a = col & 0xF000;
+        noise = rand()%16;
+               r = (wxUint8)(percent_r_i * ((col >> 8) & 0xF) + percent_r * noise);
+               g = (wxUint8)(percent_g_i * ((col >> 4) & 0xF) + percent_g * noise);
+               b = (wxUint8)(percent_b_i * (col & 0xF) + percent_b * noise);
+               *(dst++) = a | (r << 8) | (g << 4) | b;
+       }
+}
+
+static void mod_tex_inter_col_using_texa (wxUint16 *dst, int size, wxUint32 color)
+{
+       wxUint32 cr, cg, cb;
+       wxUint16 col;
+       wxUint8 r, g, b;
+       wxUint16 a;
+       float percent, percent_i;
+
+       cr = (color >> 12) & 0xF;
+       cg = (color >> 8) & 0xF;
+       cb = (color >> 4) & 0xF;
+
+       for (int i=0; i<size; i++)
+       {
+               col = *dst;
+               a = col & 0xF000;
+               percent = (a >> 12) / 15.0f;
+               percent_i = 1.0f - percent;
+               r = (wxUint8)(percent * cr + percent_i * ((col & 0x0F00) >> 8));
+               g = (wxUint8)(percent * cg + percent_i * ((col & 0x00F0) >> 4));
+               b = (wxUint8)(percent * cb + percent_i * (col & 0x000F));
+               *(dst++) = a | (r << 8) | (g << 4) | b;
+       }
+}
+
+static void mod_tex_mul_col (wxUint16 *dst, int size, wxUint32 color)
+{
+       float cr, cg, cb;
+       wxUint16 col;
+       wxUint8 r, g, b;
+       wxUint16 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<size; i++)
+       {
+               col = *dst;
+               a = col & 0xF000;
+               r = (wxUint8)(cr * ((col & 0x0F00) >> 8));
+               g = (wxUint8)(cg * ((col & 0x00F0) >> 4));
+               b = (wxUint8)(cb * (col & 0x000F));
+               *(dst++) = a | (r << 8) | (g << 4) | b;
+       }
+}
+
+static void mod_tex_scale_fac_add_col (wxUint16 *dst, int size, wxUint32 color, wxUint32 factor)
+{
+       float percent = factor / 255.0f;
+       wxUint32 cr, cg, cb;
+       wxUint16 col;
+       float r, g, b;
+
+       cr = (color >> 12) & 0xF;
+       cg = (color >> 8) & 0xF;
+       cb = (color >> 4) & 0xF;
+
+       for (int i=0; i<size; i++)
+       {
+               col = *dst;
+               r = cr + percent * (float)((col>>8)&0xF);
+               g = cg + percent * (float)((col>>4)&0xF);
+               b = cb + percent * (float)(col&0xF);
+               *(dst++) = (col&0xF000) | ((wxUint8)r << 8) | ((wxUint8)g << 4) | (wxUint8)b;
+       }
+}
diff --git a/source/gles2glide64/src/Glide64/TexModCI.h b/source/gles2glide64/src/Glide64/TexModCI.h
new file mode 100644 (file)
index 0000000..279cf09
--- /dev/null
@@ -0,0 +1,437 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+static void mod_tex_inter_color_using_factor_CI (wxUint32 color, wxUint32 factor)
+{
+       float percent = factor / 255.0f;
+       float percent_i = 1 - percent;
+       wxUint8 cr, cg, cb;
+       wxUint16 col;
+       wxUint8 a, r, g, b;
+
+       cr = (wxUint8)((color >> 24) & 0xFF);
+       cg = (wxUint8)((color >> 16) & 0xFF);
+       cb = (wxUint8)((color >> 8) & 0xFF);
+
+       for (int i=0; i<256; i++)
+       {
+               col = rdp.pal_8[i];
+               a = (wxUint8)(col&0x0001);;
+               r = (wxUint8)((float)((col&0xF800) >> 11) / 31.0f * 255.0f);
+        g = (wxUint8)((float)((col&0x07C0) >> 6) / 31.0f * 255.0f);
+        b = (wxUint8)((float)((col&0x003E) >> 1) / 31.0f * 255.0f);
+               r = (wxUint8)(min(255, percent_i * r + percent * cr));
+               g = (wxUint8)(min(255, percent_i * g + percent * cg));
+               b = (wxUint8)(min(255, percent_i * b + percent * cb));
+        rdp.pal_8[i] = (wxUint16)(((wxUint16)(r >> 3) << 11) |
+                         ((wxUint16)(g >> 3) << 6) |
+                         ((wxUint16)(b >> 3) << 1) |
+                                 ((wxUint16)(a ) << 0));
+       }
+}
+
+static void mod_tex_inter_col_using_col1_CI (wxUint32 color0, wxUint32 color1)
+{
+       wxUint8 cr, cg, cb;
+       wxUint16 col;
+       wxUint8 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 = (wxUint8)((color0 >> 24) & 0xFF);
+       cg = (wxUint8)((color0 >> 16) & 0xFF);
+       cb = (wxUint8)((color0 >> 8)  & 0xFF);
+
+       for (int i=0; i<256; i++)
+       {
+               col = rdp.pal_8[i];
+               a = (wxUint8)(col&0x0001);;
+               r = (wxUint8)((float)((col&0xF800) >> 11) / 31.0f * 255.0f);
+        g = (wxUint8)((float)((col&0x07C0) >> 6) / 31.0f * 255.0f);
+        b = (wxUint8)((float)((col&0x003E) >> 1) / 31.0f * 255.0f);
+               r = (wxUint8)(min(255, percent_r_i * r + percent_r * cr));
+               g = (wxUint8)(min(255, percent_g_i * g + percent_g * cg));
+               b = (wxUint8)(min(255, percent_b_i * b + percent_b * cb));
+        rdp.pal_8[i] = (wxUint16)(((wxUint16)(r >> 3) << 11) |
+                         ((wxUint16)(g >> 3) << 6) |
+                         ((wxUint16)(b >> 3) << 1) |
+                                 ((wxUint16)(a ) << 0));
+       }
+}
+
+static void mod_full_color_sub_tex_CI (wxUint32 color)
+{
+       wxUint8 cr, cg, cb, ca;
+       wxUint16 col;
+       wxUint8 a, r, g, b;
+
+       cr = (wxUint8)((color >> 24) & 0xFF);
+       cg = (wxUint8)((color >> 16) & 0xFF);
+       cb = (wxUint8)((color >> 8) & 0xFF);
+       ca = (wxUint8)(color & 0xFF);
+
+       for (int i=0; i<256; i++)
+       {
+               col = rdp.pal_8[i];
+               a = (wxUint8)(col&0x0001);;
+               r = (wxUint8)((float)((col&0xF800) >> 11) / 31.0f * 255.0f);
+        g = (wxUint8)((float)((col&0x07C0) >> 6) / 31.0f * 255.0f);
+        b = (wxUint8)((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] = (wxUint16)(((wxUint16)(r >> 3) << 11) |
+                         ((wxUint16)(g >> 3) << 6) |
+                         ((wxUint16)(b >> 3) << 1) |
+                                 ((wxUint16)(a ) << 0));
+       }
+}
+
+static void mod_col_inter_col1_using_tex_CI (wxUint32 color0, wxUint32 color1)
+{
+       wxUint32 cr0, cg0, cb0, cr1, cg1, cb1;
+       wxUint16 col;
+       wxUint8 a, r, g, b;
+       float percent_r, percent_g, percent_b;
+
+       cr0 = (wxUint8)((color0 >> 24) & 0xFF);
+       cg0 = (wxUint8)((color0 >> 16) & 0xFF);
+       cb0 = (wxUint8)((color0 >> 8)  & 0xFF);
+       cr1 = (wxUint8)((color1 >> 24) & 0xFF);
+       cg1 = (wxUint8)((color1 >> 16) & 0xFF);
+       cb1 = (wxUint8)((color1 >> 8)  & 0xFF);
+
+       for (int i=0; i<256; i++)
+       {
+               col = rdp.pal_8[i];
+               a = (wxUint8)(col&0x0001);;
+               percent_r = ((col&0xF800) >> 11) / 31.0f;
+               percent_g = ((col&0x07C0) >> 6) / 31.0f;
+               percent_b = ((col&0x003E) >> 1) / 31.0f;
+               r = (wxUint8)(min((1.0f-percent_r) * cr0 + percent_r * cr1, 255));
+               g = (wxUint8)(min((1.0f-percent_g) * cg0 + percent_g * cg1, 255));
+               b = (wxUint8)(min((1.0f-percent_b) * cb0 + percent_b * cb1, 255));
+        rdp.pal_8[i] = (wxUint16)(((wxUint16)(r >> 3) << 11) |
+                         ((wxUint16)(g >> 3) << 6) |
+                         ((wxUint16)(b >> 3) << 1) |
+                                 ((wxUint16)(a ) << 0));
+       }
+}
+
+
+
+static void mod_tex_sub_col_mul_fac_add_tex_CI (wxUint32 color, wxUint32 factor)
+{
+       float percent = factor / 255.0f;
+       wxUint8 cr, cg, cb, a;
+       wxUint16 col;
+       float r, g, b;
+
+       cr = (wxUint8)((color >> 24) & 0xFF);
+       cg = (wxUint8)((color >> 16) & 0xFF);
+       cb = (wxUint8)((color >> 8) & 0xFF);
+
+       for (int i=0; i<256; i++)
+       {
+               col = rdp.pal_8[i];
+               a = (wxUint8)(col&0x0001);;
+               r = (wxUint8)((float)((col&0xF800) >> 11) / 31.0f * 255.0f);
+        g = (wxUint8)((float)((col&0x07C0) >> 6) / 31.0f * 255.0f);
+        b = (wxUint8)((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] = (wxUint16)(((wxUint16)((wxUint8)(r) >> 3) << 11) |
+                         ((wxUint16)((wxUint8)(g) >> 3) << 6) |
+                         ((wxUint16)((wxUint8)(b) >> 3) << 1) |
+                                 (wxUint16)(a) );
+       }
+}
+
+static void mod_tex_scale_col_add_col_CI (wxUint32 color0, wxUint32 color1)
+{
+       wxUint8 cr, cg, cb;
+       wxUint16 col;
+       wxUint8 a, r, g, b;
+
+       float percent_r = ((color0 >> 24) & 0xFF) / 255.0f;
+       float percent_g = ((color0 >> 16) & 0xFF) / 255.0f;
+       float percent_b = ((color0 >> 8)  & 0xFF) / 255.0f;
+       cr = (wxUint8)((color1 >> 24) & 0xFF);
+       cg = (wxUint8)((color1 >> 16) & 0xFF);
+       cb = (wxUint8)((color1 >> 8)  & 0xFF);
+
+       for (int i=0; i<256; i++)
+       {
+               col = rdp.pal_8[i];
+               a = (wxUint8)(col&0x0001);;
+               r = (wxUint8)((float)((col&0xF800) >> 11) / 31.0f * 255.0f);
+        g = (wxUint8)((float)((col&0x07C0) >> 6) / 31.0f * 255.0f);
+        b = (wxUint8)((float)((col&0x003E) >> 1) / 31.0f * 255.0f);
+               r = (wxUint8)(min(255, percent_r * r + cr));
+               g = (wxUint8)(min(255, percent_g * g + cg));
+               b = (wxUint8)(min(255, percent_b * b + cb));
+        rdp.pal_8[i] = (wxUint16)(((wxUint16)(r >> 3) << 11) |
+                         ((wxUint16)(g >> 3) << 6) |
+                         ((wxUint16)(b >> 3) << 1) |
+                                 ((wxUint16)(a ) << 0));
+       }
+}
+
+static void mod_tex_add_col_CI (wxUint32 color)
+{
+       wxUint8 cr, cg, cb;
+       wxUint16 col;
+       wxUint8 a, r, g, b;
+
+       cr = (wxUint8)((color >> 24) & 0xFF);
+       cg = (wxUint8)((color >> 16) & 0xFF);
+       cb = (wxUint8)((color >> 8) & 0xFF);
+
+       for (int i=0; i<256; i++)
+       {
+               col = rdp.pal_8[i];
+               a = (wxUint8)(col&0x0001);;
+               r = (wxUint8)((float)((col&0xF800) >> 11) / 31.0f * 255.0f);
+        g = (wxUint8)((float)((col&0x07C0) >> 6) / 31.0f * 255.0f);
+        b = (wxUint8)((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] = (wxUint16)(((wxUint16)(r >> 3) << 11) |
+                         ((wxUint16)(g >> 3) << 6) |
+                         ((wxUint16)(b >> 3) << 1) |
+                                 ((wxUint16)(a ) << 0));
+       }
+}
+
+static void mod_tex_sub_col_CI (wxUint32 color)
+{
+       wxUint8 cr, cg, cb;
+       wxUint16 col;
+       wxUint8 a, r, g, b;
+
+       cr = (wxUint8)((color >> 24) & 0xFF);
+       cg = (wxUint8)((color >> 16) & 0xFF);
+       cb = (wxUint8)((color >> 8) & 0xFF);
+
+       for (int i=0; i<256; i++)
+       {
+               col = rdp.pal_8[i];
+               a = (wxUint8)(col&0x0001);;
+               r = (wxUint8)((float)((col&0xF800) >> 11) / 31.0f * 255.0f);
+        g = (wxUint8)((float)((col&0x07C0) >> 6) / 31.0f * 255.0f);
+        b = (wxUint8)((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] = (wxUint16)(((wxUint16)(r >> 3) << 11) |
+                         ((wxUint16)(g >> 3) << 6) |
+                         ((wxUint16)(b >> 3) << 1) |
+                                 ((wxUint16)(a ) << 0));
+       }
+}
+
+static void mod_tex_sub_col_mul_fac_CI (wxUint32 color, wxUint32 factor)
+{
+       float percent = factor / 255.0f;
+       wxUint8 cr, cg, cb;
+       wxUint16 col;
+       wxUint8 a;
+       float r, g, b;
+
+       cr = (wxUint8)((color >> 24) & 0xFF);
+       cg = (wxUint8)((color >> 16) & 0xFF);
+       cb = (wxUint8)((color >> 8) & 0xFF);
+
+       for (int i=0; i<256; i++)
+       {
+               col = rdp.pal_8[i];
+               a = (wxUint8)(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] = (wxUint16)(((wxUint16)((wxUint8)(r) >> 3) << 11) |
+                         ((wxUint16)((wxUint8)(g) >> 3) << 6) |
+                         ((wxUint16)((wxUint8)(b) >> 3) << 1) |
+                                 (wxUint16)(a) );
+       }
+}
+
+static void mod_col_inter_tex_using_col1_CI (wxUint32 color0, wxUint32 color1)
+{
+       wxUint8 cr, cg, cb;
+       wxUint16 col;
+       wxUint8 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 = (wxUint8)((color0 >> 24) & 0xFF);
+       cg = (wxUint8)((color0 >> 16) & 0xFF);
+       cb = (wxUint8)((color0 >> 8)  & 0xFF);
+
+       for (int i=0; i<256; i++)
+       {
+               col = rdp.pal_8[i];
+               a = (wxUint8)(col&0x0001);;
+               r = (wxUint8)((float)((col&0xF800) >> 11) / 31.0f * 255.0f);
+        g = (wxUint8)((float)((col&0x07C0) >> 6) / 31.0f * 255.0f);
+        b = (wxUint8)((float)((col&0x003E) >> 1) / 31.0f * 255.0f);
+               r = (wxUint8)(min(255, percent_r * r + percent_r_i * cr));
+               g = (wxUint8)(min(255, percent_g * g + percent_g_i * cg));
+               b = (wxUint8)(min(255, percent_b * b + percent_b_i * cb));
+        rdp.pal_8[i] = (wxUint16)(((wxUint16)(r >> 3) << 11) |
+                         ((wxUint16)(g >> 3) << 6) |
+                         ((wxUint16)(b >> 3) << 1) |
+                                 ((wxUint16)(a ) << 0));
+       }
+}
+
+static void mod_tex_inter_col_using_texa_CI (wxUint32 color)
+{
+       wxUint8 a, r, g, b;
+
+       r = (wxUint8)((float)((color >> 24) & 0xFF) / 255.0f * 31.0f);
+    g = (wxUint8)((float)((color >> 16) & 0xFF) / 255.0f * 31.0f);
+    b = (wxUint8)((float)((color >> 8)  & 0xFF) / 255.0f * 31.0f);
+    a = (color&0xFF) ? 1 : 0;
+    wxUint16 col16 = (wxUint16)((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 (wxUint32 color)
+{
+       wxUint8 a, r, g, b;
+       wxUint16 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 = (wxUint8)(col&0x0001);;
+               r = (wxUint8)((float)((col&0xF800) >> 11) * cr);
+        g = (wxUint8)((float)((col&0x07C0) >> 6) * cg);
+        b = (wxUint8)((float)((col&0x003E) >> 1) * cb);
+        rdp.pal_8[i] = (wxUint16)(((wxUint16)(r >> 3) << 11) |
+                         ((wxUint16)(g >> 3) << 6) |
+                         ((wxUint16)(b >> 3) << 1) |
+                                 ((wxUint16)(a ) << 0));
+       }
+}
+
+static void ModifyPalette(wxUint32 mod, wxUint32 modcolor, wxUint32 modcolor1, wxUint32 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, modcolor1);
+                       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/source/gles2glide64/src/Glide64/Util.cpp b/source/gles2glide64/src/Glide64/Util.cpp
new file mode 100755 (executable)
index 0000000..7e59469
--- /dev/null
@@ -0,0 +1,2183 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+#include <math.h>
+#include "Gfx_1.3.h"
+#include "Util.h"
+#include "Combine.h"
+#include "3dmath.h"
+#include "Debugger.h"
+#include "TexCache.h"
+#include "DepthBufferRender.h"
+
+#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];
+  }
+}
+
+static wxUint32 u_cull_mode = 0;
+
+//software backface culling. Gonetz
+// mega modifications by Dave2001
+int cull_tri(VERTEX **v) // type changed to VERTEX** [Dave2001]
+{
+  int i;
+
+  if (v[0]->scr_off & v[1]->scr_off & v[2]->scr_off)
+  {
+    LRDP (" clipped\n");
+    return TRUE;
+  }
+
+  // Triangle can't be culled, if it need clipping
+  int draw = FALSE;
+
+  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] + rdp.offset_x;
+      v[i]->sy = rdp.view_trans[1] + v[i]->y_w * rdp.view_scale[1] + rdp.offset_y;
+      v[i]->sz = rdp.view_trans[2] + v[i]->z_w * rdp.view_scale[2];
+      v[i]->screen_translated = 1;
+    }
+    if (v[i]->w < 0.01f) //need clip_z. can't be culled now
+      draw = 1;
+  }
+
+  u_cull_mode = (rdp.flags & CULLMASK);
+  if (draw || u_cull_mode == 0 || u_cull_mode == CULLMASK) //no culling set
+  {
+    u_cull_mode >>= CULLSHIFT;
+    return FALSE;
+  }
+
+#define SW_CULLING
+#ifdef SW_CULLING
+#if 1 // H.Morii - faster float comparisons with zero area check added
+
+  const float x1 = v[0]->sx - v[1]->sx;
+  const float y1 = v[0]->sy - v[1]->sy;
+  const float x2 = v[2]->sx - v[1]->sx;
+  const float y2 = v[2]->sy - v[1]->sy;
+  const float area = y1*x2 - x1*y2;
+
+  const int iarea = *(int*)&area;
+  const unsigned int mode = (u_cull_mode << 19UL);
+  u_cull_mode >>= CULLSHIFT;
+
+  if ((iarea & 0x7FFFFFFF) == 0)
+  {
+         LRDP (" zero area triangles\n");
+      return TRUE;
+  }
+
+  if ((rdp.flags & CULLMASK) && ((int)(iarea ^ mode)) >= 0)
+  {
+         LRDP (" culled\n");
+      return TRUE;
+  }
+#else
+
+  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;
+
+  u_cull_mode >>= CULLSHIFT;
+  switch (u_cull_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
+    {
+      LRDP (" 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
+    {
+      LRDP (" culled!\n");
+      return TRUE;
+    }
+    return FALSE;
+  }
+#endif
+#endif
+
+  return FALSE;
+}
+
+
+void apply_shade_mods (VERTEX *v)
+{
+  float col[4];
+  wxUint32 mod;
+  memcpy (col, rdp.col, 16);
+
+  if (rdp.cmb_flags)
+  {
+    if (v->shade_mod == 0)
+      v->color_backup = *(wxUint32*)(&(v->b));
+    else
+      *(wxUint32*)(&(v->b)) = v->color_backup;
+    mod = rdp.cmb_flags;
+    if (mod & 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 = (wxUint8)(255.0f * col[0]);
+      v->g = (wxUint8)(255.0f * col[1]);
+      v->b = (wxUint8)(255.0f * col[2]);
+    }
+    if (mod & CMB_A_SET)
+    {
+      if (col[3] > 1.0f) col[3] = 1.0f;
+      if (col[3] < 0.0f) col[3] = 0.0f;
+      v->a = (wxUint8)(255.0f * col[3]);
+    }
+    if (mod & CMB_SETSHADE_SHADEALPHA)
+    {
+      v->r = v->g = v->b = v->a;
+    }
+    if (mod & CMB_MULT_OWN_ALPHA)
+    {
+      float percent = v->a / 255.0f;
+      v->r = (wxUint8)(v->r * percent);
+      v->g = (wxUint8)(v->g * percent);
+      v->b = (wxUint8)(v->b * percent);
+    }
+    if (mod & 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 = (wxUint8)(v->r * col[0]);
+      v->g = (wxUint8)(v->g * col[1]);
+      v->b = (wxUint8)(v->b * col[2]);
+    }
+    if (mod & CMB_A_MULT)
+    {
+      if (col[3] > 1.0f) col[3] = 1.0f;
+      if (col[3] < 0.0f) col[3] = 0.0f;
+      v->a = (wxUint8)(v->a * col[3]);
+    }
+    if (mod & 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 = (wxUint8)r;
+      v->g = (wxUint8)g;
+      v->b = (wxUint8)b;
+    }
+    if (mod & CMB_A_SUB)
+    {
+                   int a = v->a - (int)(255.0f * rdp.coladd[3]);
+        if (a < 0) a = 0;
+        v->a = (wxUint8)a;
+    }
+    if (mod & 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 = (wxUint8)r;
+      v->g = (wxUint8)g;
+      v->b = (wxUint8)b;
+    }
+    if (mod & CMB_A_ADD)
+    {
+                   int a = v->a + (int)(255.0f * rdp.coladd[3]);
+        if (a > 255) a = 255;
+        v->a = (wxUint8)a;
+    }
+    if (mod & CMB_COL_SUB_OWN)
+    {
+      int r = (wxUint8)(255.0f * rdp.coladd[0]) - v->r;
+      int g = (wxUint8)(255.0f * rdp.coladd[1]) - v->g;
+      int b = (wxUint8)(255.0f * rdp.coladd[2]) - v->b;
+      if (r < 0) r = 0;
+      if (g < 0) g = 0;
+      if (b < 0) b = 0;
+      v->r = (wxUint8)r;
+      v->g = (wxUint8)g;
+      v->b = (wxUint8)b;
+    }
+    v->shade_mod = cmb.shade_mod_hash;
+  }
+  if (rdp.cmb_flags_2 & CMB_INTER)
+  {
+    v->r = (wxUint8)(rdp.col_2[0] * rdp.shade_factor * 255.0f + v->r * (1.0f - rdp.shade_factor));
+    v->g = (wxUint8)(rdp.col_2[1] * rdp.shade_factor * 255.0f + v->g * (1.0f - rdp.shade_factor));
+    v->b = (wxUint8)(rdp.col_2[2] * rdp.shade_factor * 255.0f + v->b * (1.0f - rdp.shade_factor));
+    v->shade_mod = cmb.shade_mod_hash;
+  }
+}
+
+static int dzdx = 0;
+static int deltaZ = 0;
+VERTEX **org_vtx;
+
+void draw_tri (VERTEX **vtx, wxUint16 linew)
+{
+  deltaZ = dzdx = 0;
+  if (linew == 0 && (fb_depth_render_enabled || (rdp.rm & 0xC00) == 0xC00))
+  {
+    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 diffy_02 = Y0 - Y2;
+    float diffy_12 = Y1 - Y2;
+    float diffx_02 = X0 - X2;
+    float diffx_12 = X1 - X2;
+
+    float denom = (diffx_02 * diffy_12 - diffx_12 * diffy_02);
+    if(denom*denom > 0.0f)
+    {
+      float diffz_02 = vtx[0]->sz - vtx[2]->sz;
+      float diffz_12 = vtx[1]->sz - vtx[2]->sz;
+      float fdzdx = (diffz_02 * diffy_12 - diffz_12 * diffy_02) / denom;
+      if ((rdp.rm & 0xC00) == 0xC00) {
+        // Calculate deltaZ per polygon for Decal z-mode
+        float fdzdy = (diffz_02 * diffx_12 - diffz_12 * diffx_02) / denom;
+        float fdz = fabs(fdzdx) + fabs(fdzdy);
+        if ((settings.hacks & hack_Zelda) && (rdp.rm & 0x800))
+          fdz *= 4.0f;  // Decal mode in Zelda sometimes needs mutiplied deltaZ to work correct, e.g. roads
+        deltaZ = max(8, (int)fdz);
+      }
+      dzdx = (int)(fdzdx * 65536.0);
+    }
+  }
+
+  org_vtx = vtx;
+
+  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
+          {
+            int flag = min(2, (rdp.cmd1 >> 24) & 3);
+            v->a = vtx[flag]->a;
+            v->b = vtx[flag]->b;
+            v->g = vtx[flag]->g;
+            v->r = vtx[flag]->r;
+#ifdef EXTREME_LOGGING
+            FRDP(" * Flat shaded, flag%d - r: %d, g: %d, b: %d, a: %d\n", flag, v->r, v->g, v->b, v->a);
+#endif
+          }
+          else  // prim color
+          {
+#ifdef EXTREME_LOGGING
+            FRDP(" * Prim shaded %08lx\n", rdp.prim_color);
+#endif
+            v->a = (wxUint8)(rdp.prim_color & 0xFF);
+            v->b = (wxUint8)((rdp.prim_color >> 8) & 0xFF);
+            v->g = (wxUint8)((rdp.prim_color >> 16) & 0xFF);
+            v->r = (wxUint8)((rdp.prim_color >> 24) & 0xFF);
+          }
+        }
+      }
+
+      // Fix texture coordinates
+      if (!v->uv_scaled)
+      {
+        v->ou *= rdp.tiles[rdp.cur_tile].s_scale;
+        v->ov *= rdp.tiles[rdp.cur_tile].t_scale;
+        v->uv_scaled = 1;
+        if (!rdp.Persp_en)
+        {
+//          v->oow = v->w = 1.0f;
+          v->ou *= 0.5f;
+          v->ov *= 0.5f;
+        }
+      }
+      v->u1 = v->u0 = v->ou;
+      v->v1 = v->v0 = v->ov;
+
+      if (rdp.tex >= 1 && rdp.cur_cache[0])
+      {
+        if (rdp.aTBuffTex[0])
+        {
+          v->u0 += rdp.aTBuffTex[0]->u_shift + rdp.aTBuffTex[0]->tile_uls;
+          v->v0 += rdp.aTBuffTex[0]->v_shift + rdp.aTBuffTex[0]->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.aTBuffTex[0])
+        {
+          if (rdp.aTBuffTex[0]->tile_uls != (int)rdp.tiles[rdp.cur_tile].f_ul_s)
+            v->u0 -= rdp.tiles[rdp.cur_tile].f_ul_s;
+          if (rdp.aTBuffTex[0]->tile_ult != (int)rdp.tiles[rdp.cur_tile].f_ul_t || (settings.hacks&hack_Megaman))
+            v->v0 -= rdp.tiles[rdp.cur_tile].f_ul_t; //required for megaman (boss special attack)
+          v->u0 *= rdp.aTBuffTex[0]->u_scale;
+          v->v0 *= rdp.aTBuffTex[0]->v_scale;
+#ifdef EXTREME_LOGGING
+          FRDP("tbuff_tex t0: (%f, %f)->(%f, %f)\n", v->ou, v->ov, v->u0, v->v0);
+#endif
+        }
+        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.aTBuffTex[1])
+        {
+          v->u1 += rdp.aTBuffTex[1]->u_shift + rdp.aTBuffTex[1]->tile_uls;
+          v->v1 += rdp.aTBuffTex[1]->v_shift + rdp.aTBuffTex[1]->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.aTBuffTex[1])
+        {
+          if (rdp.aTBuffTex[1]->tile_uls != (int)rdp.tiles[rdp.cur_tile].f_ul_s)
+            v->u1 -= rdp.tiles[rdp.cur_tile].f_ul_s;
+          v->u1 *= rdp.aTBuffTex[1]->u_scale;
+          v->v1 *= rdp.aTBuffTex[1]->v_scale;
+#ifdef EXTREME_LOGGING
+          FRDP("tbuff_tex t1: (%f, %f)->(%f, %f)\n", v->ou, v->ov, v->u1, v->v1);
+#endif
+        }
+        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);
+    }
+#ifdef EXTREME_LOGGING
+            FRDP("draw_tri. v[%d] ou=%f, ov = %f\n", i, v->ou, v->ov);
+#endif
+    if (v->shade_mod != cmb.shade_mod_hash)
+      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_WMIN;
+
+  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.aTBuffTex[0] && !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 += 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 +
+              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 = (wxUint8)(v1->b + (v2->b - v1->b) * percent);
+            rdp.vtxbuf[index].g = (wxUint8)(v1->g + (v2->g - v1->g) * percent);
+            rdp.vtxbuf[index].r = (wxUint8)(v1->r + (v2->r - v1->r) * percent);
+            rdp.vtxbuf[index++].a = (wxUint8)(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 +
+              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 = (wxUint8)(v2->b + (v1->b - v2->b) * percent);
+            rdp.vtxbuf[index].g = (wxUint8)(v2->g + (v1->g - v2->g) * percent);
+            rdp.vtxbuf[index].r = (wxUint8)(v2->r + (v1->r - v2->r) * percent);
+            rdp.vtxbuf[index++].a = (wxUint8)(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 += 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; i<rdp.n_global; i++)
+      {
+        j = i+1;
+        if (j == rdp.n_global) j = 0;
+
+        VERTEX *v1 = &rdp.vtxbuf2[i];
+        VERTEX *v2 = &rdp.vtxbuf2[j];
+
+        // ** Right plane **
+        if (v1->u0 <= right_256)
+        {
+          if (v2->u0 <= right_256)   // 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 = (wxUint8)(v1->b + (v2->b - v1->b) * percent);
+            rdp.vtxbuf[index].g = (wxUint8)(v1->g + (v2->g - v1->g) * percent);
+            rdp.vtxbuf[index].r = (wxUint8)(v1->r + (v2->r - v1->r) * percent);
+            rdp.vtxbuf[index].a = (wxUint8)(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 <= right_256) // 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 = (wxUint8)(v2->b + (v1->b - v2->b) * percent);
+            rdp.vtxbuf[index].g = (wxUint8)(v2->g + (v1->g - v2->g) * percent);
+            rdp.vtxbuf[index].r = (wxUint8)(v2->r + (v1->r - v2->r) * percent);
+            rdp.vtxbuf[index].a = (wxUint8)(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, TRUE);
+    }
+  }
+  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[0].number = 1;
+    rdp.vtxbuf[1] = *vtx[1];
+    rdp.vtxbuf[1].number = 2;
+    rdp.vtxbuf[2] = *vtx[2];
+    rdp.vtxbuf[2].number = 4;
+
+    do_triangle_stuff (linew, FALSE);
+  }
+}
+
+#define interp2p(a, b, r)  (a + (b - a) * r)
+
+//*
+static void InterpolateColors(VERTEX & va, VERTEX & vb, VERTEX & res, float percent)
+{
+  res.b = (wxUint8)interp2p(va.b, vb.b, percent);
+  res.g = (wxUint8)interp2p(va.g, vb.g, percent);;
+  res.r = (wxUint8)interp2p(va.r, vb.r, percent);;
+  res.a = (wxUint8)interp2p(va.a, vb.a, percent);;
+  res.f = interp2p(va.f, vb.f, percent);;
+}
+//*/
+//
+// clip_w - clips aint the z-axis
+//
+static void clip_w (int interpolate_colors)
+{
+  int i,j,index,n=rdp.n_global;
+  float percent;
+  // 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<n; i++)
+  {
+    j = i+1;
+    if (j == 3) j = 0;
+
+    if (Vi.w >= 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].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;
+        if (interpolate_colors)
+          InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent);
+        else
+          rdp.vtxbuf[index++].number = Vi.number | Vj.number;
+      }
+    }
+    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].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;
+        if (interpolate_colors)
+          InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent);
+        else
+          rdp.vtxbuf[index++].number = Vi.number | Vj.number;
+
+        // Save the in point
+        rdp.vtxbuf[index] = Vj;
+        rdp.vtxbuf[index++].not_zclipped = 1;
+      }
+    }
+  }
+  rdp.n_global = index;
+}
+
+static void render_tri (wxUint16 linew, int old_interpolate);
+
+void do_triangle_stuff (wxUint16 linew, int old_interpolate) // what else?? do the triangle stuff :P (to keep from writing code twice)
+{
+  int i;
+
+  if (rdp.clip & CLIP_WMIN)
+    clip_w (old_interpolate);
+
+  float maxZ = (rdp.zsrc != 1) ? rdp.view_trans[2] + rdp.view_scale[2] : rdp.prim_depth;
+
+  wxUint8 no_clip = 2;
+  for (i=0; i<rdp.n_global; i++)
+  {
+    if (rdp.vtxbuf[i].not_zclipped)// && rdp.zsrc != 1)
+    {
+#ifdef EXTREME_LOGGING
+      FRDP (" * NOT ZCLIPPPED: %d\n", rdp.vtxbuf[i].number);
+#endif
+      rdp.vtxbuf[i].x = rdp.vtxbuf[i].sx;
+      rdp.vtxbuf[i].y = rdp.vtxbuf[i].sy;
+      rdp.vtxbuf[i].z = rdp.vtxbuf[i].sz;
+      rdp.vtxbuf[i].q = rdp.vtxbuf[i].oow;
+      rdp.vtxbuf[i].u0 = rdp.vtxbuf[i].u0_w;
+      rdp.vtxbuf[i].v0 = rdp.vtxbuf[i].v0_w;
+      rdp.vtxbuf[i].u1 = rdp.vtxbuf[i].u1_w;
+      rdp.vtxbuf[i].v1 = rdp.vtxbuf[i].v1_w;
+    }
+    else
+    {
+#ifdef EXTREME_LOGGING
+      FRDP (" * ZCLIPPED: %d\n", rdp.vtxbuf[i].number);
+#endif
+      rdp.vtxbuf[i].q = 1.0f / rdp.vtxbuf[i].w;
+      rdp.vtxbuf[i].x = rdp.view_trans[0] + rdp.vtxbuf[i].x * rdp.vtxbuf[i].q * rdp.view_scale[0] + rdp.offset_x;
+      rdp.vtxbuf[i].y = rdp.view_trans[1] + rdp.vtxbuf[i].y * rdp.vtxbuf[i].q * rdp.view_scale[1] + rdp.offset_y;
+      rdp.vtxbuf[i].z = rdp.view_trans[2] + rdp.vtxbuf[i].z * rdp.vtxbuf[i].q * rdp.view_scale[2];
+      if (rdp.tex >= 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.clip_max_x) rdp.clip |= CLIP_XMAX;
+    if (rdp.vtxbuf[i].x < rdp.clip_min_x) rdp.clip |= CLIP_XMIN;
+    if (rdp.vtxbuf[i].y > rdp.clip_max_y) rdp.clip |= CLIP_YMAX;
+    if (rdp.vtxbuf[i].y < rdp.clip_min_y) rdp.clip |= CLIP_YMIN;
+    if (rdp.vtxbuf[i].z > maxZ)           rdp.clip |= CLIP_ZMAX;
+    if (rdp.vtxbuf[i].z < 0.0f)           rdp.clip |= CLIP_ZMIN;
+    no_clip &= rdp.vtxbuf[i].screen_translated;
+  }
+  if (no_clip)
+    rdp.clip = 0;
+  else
+  {
+    if (!settings.clip_zmin)
+      rdp.clip &= ~CLIP_ZMIN;
+    if (!settings.clip_zmax)
+      rdp.clip &= ~CLIP_ZMAX;
+  }
+  render_tri (linew, old_interpolate);
+}
+
+void do_triangle_stuff_2 (wxUint16 linew)
+{
+  rdp.clip = 0;
+
+  for (int i=0; i<rdp.n_global; i++)
+  {
+    // Don't remove clipping, or it will freeze
+    if (rdp.vtxbuf[i].x > rdp.clip_max_x) rdp.clip |= CLIP_XMAX;
+    if (rdp.vtxbuf[i].x < rdp.clip_min_x) rdp.clip |= CLIP_XMIN;
+    if (rdp.vtxbuf[i].y > rdp.clip_max_y) rdp.clip |= CLIP_YMAX;
+    if (rdp.vtxbuf[i].y < rdp.clip_min_y) rdp.clip |= CLIP_YMIN;
+  }
+
+  render_tri (linew, TRUE);
+}
+
+__inline wxUint8 real_to_char(double x)
+{
+  return (wxUint8)(((int)floor(x+0.5))&0xFF);
+}
+
+//*
+static void InterpolateColors2(VERTEX & va, VERTEX & vb, VERTEX & res, float percent)
+{
+  float w = 1.0f/(va.oow + (vb.oow-va.oow) * percent);
+  //   res.oow = va.oow + (vb.oow-va.oow) * percent;
+  //   res.q = res.oow;
+  float ba = va.b * va.oow;
+  float bb = vb.b * vb.oow;
+  res.b = real_to_char(interp2p(ba, bb, percent) * w);
+  float ga = va.g * va.oow;
+  float gb = vb.g * vb.oow;
+  res.g = real_to_char(interp2p(ga, gb, percent) * w);
+  float ra = va.r * va.oow;
+  float rb = vb.r * vb.oow;
+  res.r = real_to_char(interp2p(ra, rb, percent) * w);
+  float aa = va.a * va.oow;
+  float ab = vb.a * vb.oow;
+  res.a = real_to_char(interp2p(aa, ab, percent) * w);
+  float fa = va.f * va.oow;
+  float fb = vb.f * vb.oow;
+  res.f = interp2p(fa, fb, percent) * w;
+  /*
+  float u0a = va.u0_w * va.oow;
+  float u0b = vb.u0_w * vb.oow;
+  res.u0 = (u0a + (u0b - u0a) * percent) * w;
+  float v0a = va.v0_w * va.oow;
+  float v0b = vb.v0_w * vb.oow;
+  res.v0 = (v0a + (v0b - v0a) * percent) * w;
+  float u1a = va.u1_w * va.oow;
+  float u1b = vb.u1_w * vb.oow;
+  res.u1 = (u1a + (u1b - u1a) * percent) * w;
+  float v1a = va.v1_w * va.oow;
+  float v1b = vb.v1_w * vb.oow;
+  res.v1 = (v1a + (v1b - v1a) * percent) * w;
+  */
+}
+//*/
+
+typedef struct {
+  float d;             //*SEB* was doubles
+  float x;
+  float y;
+} LineEuqationType;
+
+static float EvaLine(LineEuqationType &li, float x, float y)   //*SEB* all double before
+{
+  return li.x*x+li.y*y+li.d;
+}
+
+static void Create1LineEq(LineEuqationType &l, VERTEX &v1, VERTEX &v2, VERTEX &v3)
+{
+  // Line between (x1,y1) to (x2,y2)
+  l.x = v2.sy-v1.sy;
+  l.y = v1.sx-v2.sx;
+  l.d = -(l.x*v2.sx+(l.y)*v2.sy);
+  if (EvaLine(l,v3.sx,v3.sy)*v3.oow < 0)
+  {
+    l.x = -l.x;
+    l.y = -l.y;
+    l.d = -l.d;
+  }
+}
+
+
+__inline float interp3p(float a, float b, float c, float r1, float r2) //*SEB* r1 and r2 and function was double
+{
+  return (a)+(((b)+((c)-(b))*(r2))-(a))*(r1);
+}
+/*
+#define interp3p(a, b, c, r1, r2) \
+  (a+(((b)+((c)-(b))*(r2))-(a))*(r1))
+*/
+
+static void InterpolateColors3(VERTEX &v1, VERTEX &v2, VERTEX &v3, VERTEX &out)        //*SEB* all double before
+{
+
+  LineEuqationType line;
+  Create1LineEq(line, v2, v3, v1);
+
+  float aDot = (out.x*line.x + out.y*line.y);
+  float bDot = (v1.sx*line.x + v1.sy*line.y);
+
+  float scale1 = ( - line.d - aDot) / ( bDot - aDot );
+
+  float tx = out.x + scale1 * (v1.sx - out.x);
+  float ty = out.y + scale1 * (v1.sy - out.y);
+
+  float s1 = 101.0, s2 = 101.0;
+  float den = tx - v1.sx;
+  if (fabsf(den) > 1.0)
+    s1 = (out.x-v1.sx)/den;
+  if (s1 > 100.0f)
+    s1 = (out.y-v1.sy)/(ty-v1.sy);
+
+  den = v3.sx - v2.sx;
+  if (fabsf(den) > 1.0)
+    s2 = (tx-v2.sx)/den;
+  if (s2 > 100.0f)
+    s2 =(ty-v2.sy)/(v3.sy-v2.sy);
+
+  float w = 1.0/interp3p(v1.oow,v2.oow,v3.oow,s1,s2);
+
+  out.r = real_to_char(interp3p(v1.r*v1.oow,v2.r*v2.oow,v3.r*v3.oow,s1,s2)*w);
+  out.g = real_to_char(interp3p(v1.g*v1.oow,v2.g*v2.oow,v3.g*v3.oow,s1,s2)*w);
+  out.b = real_to_char(interp3p(v1.b*v1.oow,v2.b*v2.oow,v3.b*v3.oow,s1,s2)*w);
+  out.a = real_to_char(interp3p(v1.a*v1.oow,v2.a*v2.oow,v3.a*v3.oow,s1,s2)*w);
+  out.f = (float)(interp3p(v1.f*v1.oow,v2.f*v2.oow,v3.f*v3.oow,s1,s2)*w);
+  /*
+  out.u0 = interp3p(v1.u0_w*v1.oow,v2.u0_w*v2.oow,v3.u0_w*v3.oow,s1,s2)/oow;
+  out.v0 = interp3p(v1.v0_w*v1.oow,v2.v0_w*v2.oow,v3.v0_w*v3.oow,s1,s2)/oow;
+  out.u1 = interp3p(v1.u1_w*v1.oow,v2.u1_w*v2.oow,v3.u1_w*v3.oow,s1,s2)/oow;
+  out.v1 = interp3p(v1.v1_w*v1.oow,v2.v1_w*v2.oow,v3.v1_w*v3.oow,s1,s2)/oow;
+  */
+}
+
+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;
+  float deltaTexels, deltaPixels, lodFactor = 0;       //*SEB* double before
+  float intptr;                                                                                //*SEB* double before
+  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;
+  }
+  int ilod = (int)lodFactor;
+  int lod_tile = min((int)(log10f((float)ilod)/log10f(2.0f)), rdp.cur_tile + rdp.mipmap_level);
+  float lod_fraction = 1.0f;
+  if (lod_tile < rdp.cur_tile + rdp.mipmap_level)
+  {
+       lod_fraction = max((float)modff(lodFactor / powf(2.,lod_tile),&intptr), (float)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 (voodoo.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);
+}
+
+float ScaleZ(float z)
+{
+  if (settings.n64_z_scale)
+  {
+    int iz = (int)(z*8.0f+0.5f);
+    if (iz < 0) iz = 0;
+    else if (iz >= 0x40000) iz = 0x40000 - 1;
+    return (float)zLUT[iz];
+  }
+  if (z  < 0.0f) return 0.0f;
+  z *= 1.9f;
+  if (z > 65534.0f) return 65534.0f;
+  return z;
+}
+
+static void DepthBuffer(VERTEX * vtx, int n)
+{
+  if (fb_depth_render_enabled && !(settings.hacks&hack_RE2) && dzdx && (rdp.flags & ZBUF_UPDATE))
+  {
+    vertexi v[12];
+    if (u_cull_mode == 1) //cull front
+    {
+      for(int i=0; i<n; i++)
+      {
+        v[i].x = (int)((vtx[n-i-1].x-rdp.offset_x) / rdp.scale_x * 65536.0);
+        v[i].y = (int)((vtx[n-i-1].y-rdp.offset_y) / rdp.scale_y * 65536.0);
+        v[i].z = (int)(vtx[n-i-1].z * 65536.0);
+      }
+    }
+    else
+    {
+      for(int i=0; i<n; i++)
+      {
+        v[i].x = (int)((vtx[i].x-rdp.offset_x) / rdp.scale_x * 65536.0);
+        v[i].y = (int)((vtx[i].y-rdp.offset_y) / rdp.scale_y * 65536.0);
+        v[i].z = (int)(vtx[i].z * 65536.0);
+      }
+    }
+    Rasterize(v, n, dzdx);
+  }
+  for(int i=0; i<n; i++)
+    vtx[i].z = ScaleZ(vtx[i].z);
+}
+
+/*
+std::ofstream loga;
+#define LOGG(x) loga.open("glide_log.txt",std::ios::app); loga << x; loga.flush(); loga.close();
+__inline void FRDP2(char *fmt, ...)
+{
+va_list ap;
+va_start(ap, fmt);
+vsprintf(out_buf, fmt, ap);
+LOGG(out_buf);
+va_end(ap);
+}
+//*/
+//#define LOGG(x)
+//#define FRDP2(x)
+
+
+void clip_tri(int interpolate_colors)
+{
+  int i,j,index,n=rdp.n_global;
+  float percent;
+
+  // 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<n; i++)
+    {
+      j = i+1;
+      if (j == n) j = 0;
+
+      if (Vi.x <= rdp.clip_max_x)
+      {
+        if (Vj.x <= rdp.clip_max_x)   // Both are in, save the last one
+        {
+          rdp.vtxbuf[index++] = Vj;
+        }
+        else      // First is in, second is out, save intersection
+        {
+          percent = (rdp.clip_max_x - Vi.x) / (Vj.x - Vi.x);
+          rdp.vtxbuf[index].x = rdp.clip_max_x;
+          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].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;
+          if (interpolate_colors)
+            InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent);
+          else
+            rdp.vtxbuf[index++].number = Vi.number | Vj.number | 8;
+        }
+      }
+      else
+      {
+        //if (Vj.x > rdp.clip_max_x)  // Both are out, save nothing
+        if (Vj.x <= rdp.clip_max_x) // First is out, second is in, save intersection & in point
+        {
+          percent = (rdp.clip_max_x - Vj.x) / (Vi.x - Vj.x);
+          rdp.vtxbuf[index].x = rdp.clip_max_x;
+          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].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;
+          if (interpolate_colors)
+            InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent);
+          else
+            rdp.vtxbuf[index++].number = Vi.number | Vj.number | 8;
+
+          // 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<n; i++)
+    {
+      j = i+1;
+      if (j == n) j = 0;
+
+      if (Vi.x >= rdp.clip_min_x)
+      {
+        if (Vj.x >= rdp.clip_min_x)   // Both are in, save the last one
+        {
+          rdp.vtxbuf[index++] = Vj;
+        }
+        else      // First is in, second is out, save intersection
+        {
+          percent = (rdp.clip_min_x - Vi.x) / (Vj.x - Vi.x);
+          rdp.vtxbuf[index].x = rdp.clip_min_x;
+          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].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;
+          if (interpolate_colors)
+            InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent);
+          else
+            rdp.vtxbuf[index++].number = Vi.number | Vj.number | 8;
+        }
+      }
+      else
+      {
+        //if (Vj.x < rdp.clip_min_x)  // Both are out, save nothing
+        if (Vj.x >= rdp.clip_min_x) // First is out, second is in, save intersection & in point
+        {
+          percent = (rdp.clip_min_x - Vj.x) / (Vi.x - Vj.x);
+          rdp.vtxbuf[index].x = rdp.clip_min_x;
+          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].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;
+          if (interpolate_colors)
+            InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent);
+          else
+            rdp.vtxbuf[index++].number = Vi.number | Vj.number | 8;
+
+          // 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<n; i++)
+    {
+      j = i+1;
+      if (j == n) j = 0;
+
+      if (Vi.y <= rdp.clip_max_y)
+      {
+        if (Vj.y <= rdp.clip_max_y)   // Both are in, save the last one
+        {
+          rdp.vtxbuf[index++] = Vj;
+        }
+        else      // First is in, second is out, save intersection
+        {
+          percent = (rdp.clip_max_y - Vi.y) / (Vj.y - Vi.y);
+          rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent;
+          rdp.vtxbuf[index].y = rdp.clip_max_y;
+          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].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;
+          if (interpolate_colors)
+            InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent);
+          else
+            rdp.vtxbuf[index++].number = Vi.number | Vj.number | 16;
+        }
+      }
+      else
+      {
+        //if (Vj.y > rdp.clip_max_y)  // Both are out, save nothing
+        if (Vj.y <= rdp.clip_max_y) // First is out, second is in, save intersection & in point
+        {
+          percent = (rdp.clip_max_y - Vj.y) / (Vi.y - Vj.y);
+          rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent;
+          rdp.vtxbuf[index].y = rdp.clip_max_y;
+          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].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;
+          if (interpolate_colors)
+            InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent);
+          else
+            rdp.vtxbuf[index++].number = Vi.number | Vj.number | 16;
+
+          // 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<n; i++)
+    {
+      j = i+1;
+      if (j == n) j = 0;
+
+      if (Vi.y >= rdp.clip_min_y)
+      {
+        if (Vj.y >= rdp.clip_min_y)   // Both are in, save the last one
+        {
+          rdp.vtxbuf[index++] = Vj;
+        }
+        else      // First is in, second is out, save intersection
+        {
+          percent = (rdp.clip_min_y - Vi.y) / (Vj.y - Vi.y);
+          rdp.vtxbuf[index].x = Vi.x + (Vj.x - Vi.x) * percent;
+          rdp.vtxbuf[index].y = rdp.clip_min_y;
+          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].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;
+          if (interpolate_colors)
+            InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent);
+          else
+            rdp.vtxbuf[index++].number = Vi.number | Vj.number | 16;
+        }
+      }
+      else
+      {
+        //if (Vj.y < rdp.clip_min_y)  // Both are out, save nothing
+        if (Vj.y >= rdp.clip_min_y) // First is out, second is in, save intersection & in point
+        {
+          percent = (rdp.clip_min_y - Vj.y) / (Vi.y - Vj.y);
+          rdp.vtxbuf[index].x = Vj.x + (Vi.x - Vj.x) * percent;
+          rdp.vtxbuf[index].y = rdp.clip_min_y;
+          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].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;
+          if (interpolate_colors)
+            InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent);
+          else
+            rdp.vtxbuf[index++].number = Vi.number | Vj.number | 16;
+
+          // Save the in point
+          rdp.vtxbuf[index++] = Vj;
+        }
+      }
+    }
+    n = index;
+  }
+  if (rdp.clip & CLIP_ZMAX) // far plane
+  {
+    // Swap vertex buffers
+    VERTEX *tmp = rdp.vtxbuf2;
+    rdp.vtxbuf2 = rdp.vtxbuf;
+    rdp.vtxbuf = tmp;
+    rdp.vtx_buffer ^= 1;
+    index = 0;
+    float maxZ = rdp.view_trans[2] + rdp.view_scale[2];
+
+    // Check the vertices for clipping
+    for (i=0; i<n; i++)
+    {
+      j = i+1;
+      if (j == n) j = 0;
+
+      if (Vi.z < maxZ)
+      {
+        if (Vj.z < maxZ)   // Both are in, save the last one
+        {
+          rdp.vtxbuf[index++] = Vj;
+        }
+        else      // First is in, second is out, save intersection
+        {
+          percent = (maxZ - Vi.z) / (Vj.z - Vi.z);
+          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 = maxZ - 0.001f;
+          rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * 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;
+          if (interpolate_colors)
+            InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent);
+          else
+            rdp.vtxbuf[index++].number = Vi.number | Vj.number;
+        }
+      }
+      else
+      {
+        //if (Vj.z > maxZ)  // Both are out, save nothing
+        if (Vj.z < maxZ) // First is out, second is in, save intersection & in point
+        {
+          percent = (maxZ - Vj.z) / (Vi.z - Vj.z);
+          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 = maxZ - 0.001f;;
+          rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * 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;
+          if (interpolate_colors)
+            InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent);
+          else
+            rdp.vtxbuf[index++].number = Vi.number | Vj.number;
+
+          // Save the in point
+          rdp.vtxbuf[index++] = Vj;
+        }
+      }
+    }
+    n = index;
+  }
+/*
+  if (rdp.clip & CLIP_ZMIN) // near Z
+  {
+    // 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<n; i++)
+    {
+      j = i+1;
+      if (j == n) j = 0;
+
+      if (Vi.z >= 0.0f)
+      {
+        if (Vj.z >= 0.0f)   // Both are in, save the last one
+        {
+          rdp.vtxbuf[index++] = Vj;
+        }
+        else      // First is in, second is out, save intersection
+        {
+          percent = (-Vi.z) / (Vj.z - Vi.z);
+          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 = 0.0f;
+          rdp.vtxbuf[index].q = Vi.q + (Vj.q - Vi.q) * 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;
+          if (interpolate_colors)
+            InterpolateColors(Vi, Vj, rdp.vtxbuf[index++], percent);
+          else
+            rdp.vtxbuf[index++].number = Vi.number | Vj.number;
+        }
+      }
+      else
+      {
+        //if (Vj.z < 0.0f)  // Both are out, save nothing
+        if (Vj.z >= 0.0f) // First is out, second is in, save intersection & in point
+        {
+          percent = (-Vj.z) / (Vi.z - Vj.z);
+          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 = 0.0f;;
+          rdp.vtxbuf[index].q = Vj.q + (Vi.q - Vj.q) * 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;
+          if (interpolate_colors)
+            InterpolateColors(Vj, Vi, rdp.vtxbuf[index++], percent);
+          else
+            rdp.vtxbuf[index++].number = Vi.number | Vj.number;
+
+          // Save the in point
+          rdp.vtxbuf[index++] = Vj;
+        }
+      }
+    }
+    n = index;
+  }
+*/
+  rdp.n_global = n;
+}
+
+static void render_tri (wxUint16 linew, int old_interpolate)
+{
+  if (rdp.clip)
+    clip_tri(old_interpolate);
+  int n = rdp.n_global;
+  if (n < 3)
+  {
+    FRDP (" * render_tri: n < 3\n");
+    return;
+  }
+  int i,j;
+  //*
+  if ((rdp.clip & CLIP_ZMIN) && (rdp.othermode_l & 0x00000030))
+  {
+
+    int to_render = FALSE;
+    for (i = 0; i < n; i++)
+    {
+      if (rdp.vtxbuf[i].z >= 0.0f)
+      {
+        to_render = TRUE;
+        break;
+      }
+    }
+    if (!to_render) //all z < 0
+    {
+      FRDP (" * render_tri: all z < 0\n");
+      return;
+    }
+  }
+  //*/
+  if (rdp.clip && !old_interpolate)
+  {
+    for (i = 0; i < n; i++)
+    {
+      float percent = 101.0f;
+      VERTEX * v1 = 0,  * v2 = 0;
+      switch (rdp.vtxbuf[i].number&7)
+      {
+      case 1:
+      case 2:
+      case 4:
+        continue;
+        break;
+      case 3:
+        v1 = org_vtx[0];
+        v2 = org_vtx[1];
+        break;
+      case 5:
+        v1 = org_vtx[0];
+        v2 = org_vtx[2];
+        break;
+      case 6:
+        v1 = org_vtx[1];
+        v2 = org_vtx[2];
+        break;
+      case 7:
+        InterpolateColors3(*org_vtx[0], *org_vtx[1], *org_vtx[2], rdp.vtxbuf[i]);
+        continue;
+        break;
+      }
+      switch (rdp.vtxbuf[i].number&24)
+      {
+      case 8:
+        percent = (rdp.vtxbuf[i].x-v1->sx)/(v2->sx-v1->sx);
+        break;
+      case 16:
+        percent = (rdp.vtxbuf[i].y-v1->sy)/(v2->sy-v1->sy);
+        break;
+      default:
+        {
+          float d = (v2->sx-v1->sx);
+          if (fabs(d) > 1.0)
+            percent = (rdp.vtxbuf[i].x-v1->sx)/d;
+          if (percent > 100.0f)
+            percent = (rdp.vtxbuf[i].y-v1->sy)/(v2->sy-v1->sy);
+        }
+      }
+      InterpolateColors2(*v1, *v2, rdp.vtxbuf[i], percent);
+    }
+  }
+  /*
+  if (rdp.clip)
+  {
+  LOGG("Colors before clipping:\n");
+  unsigned int k;
+               for(k=0; k<3; k++)
+    {
+                 FRDP2("V%d: r=%d, g=%d, b=%d, a=%d, f=%d\n", k, org_vtx[k]->r, org_vtx[k]->g, org_vtx[k]->b, org_vtx[k]->a, (short)org_vtx[k]->f);
+      }
+      FRDP("Got %d vertex after clipping\n", n);
+      for(k=0; k<n; k++)
+      {
+      FRDP("V%d: r=%d, g=%d, b=%d, a=%d, f=%d\n", k, rdp.vtxbuf[k].r, rdp.vtxbuf[k].g, rdp.vtxbuf[k].b, rdp.vtxbuf[k].a, (short)rdp.vtxbuf[k].f);
+      }
+      }
+  */
+
+  ConvertCoordsConvert (rdp.vtxbuf, n);
+  if (rdp.fog_mode == RDP::fog_enabled)
+  {
+    for (i = 0; i < n; i++)
+    {
+      rdp.vtxbuf[i].f = 1.0f/max(4.0f, rdp.vtxbuf[i].f);
+    }
+  }
+  else if (rdp.fog_mode == RDP::fog_blend)
+  {
+    float fog = 1.0f/max(1, rdp.fog_color&0xFF);
+    for (i = 0; i < n; i++)
+    {
+      rdp.vtxbuf[i].f = fog;
+    }
+  }
+  else if (rdp.fog_mode == RDP::fog_blend_inverse)
+  {
+    float fog = 1.0f/max(1, (~rdp.fog_color)&0xFF);
+    for (i = 0; i < n; i++)
+    {
+      rdp.vtxbuf[i].f = fog;
+    }
+  }
+
+  if (settings.lodmode > 0 && rdp.cur_tile < rdp.mipmap_level)
+    CalculateLOD(rdp.vtxbuf, n);
+
+  cmb.cmb_ext_use = cmb.tex_cmb_ext_use = 0;
+
+  /*
+  if (rdp.tbuff_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.tbuff_tex->width, rdp.tbuff_tex->height, rdp.tbuff_tex->tex_width, rdp.tbuff_tex->tex_height, rdp.tbuff_tex->lr_u, rdp.tbuff_tex->lr_v);
+  }
+  }
+  */
+  if (fullscreen)
+  {
+    if (settings.wireframe)
+    {
+      SetWireframeCol ();
+      for (i=0; i<n; i++)
+      {
+        j = i+1;
+        if (j == n) j = 0;
+        grDrawLine (&rdp.vtxbuf[i], &rdp.vtxbuf[j]);
+      }
+    }
+    else
+    {
+
+      //      VERTEX ** pv = rdp.vtx_buffer?(vtx_list2):(vtx_list1);
+      //      for (int k = 0; k < n; k ++)
+      //                       FRDP ("DRAW[%d]: v.x = %f, v.y = %f, v.z = %f, v.u = %f, v.v = %f\n", k, pv[k]->x, 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)
+      {
+        VERTEX *V0 = &rdp.vtxbuf[0];
+        VERTEX *V1 = &rdp.vtxbuf[1];
+        if (fabs(V0->x - V1->x) < 0.01 && fabs(V0->y - V1->y) < 0.01)
+          V1 = &rdp.vtxbuf[2];
+        V0->z = ScaleZ(V0->z);
+        V1->z = ScaleZ(V1->z);
+        VERTEX v[4];
+        v[0] = *V0;
+        v[1] = *V0;
+        v[2] = *V1;
+        v[3] = *V1;
+        float width = linew * 0.25f;
+        if (fabs(V0->y - V1->y) < 0.0001)
+        {
+          v[0].x = v[1].x = V0->x;
+          v[2].x = v[3].x = V1->x;
+
+          width *= rdp.scale_y;
+          v[0].y = v[2].y = V0->y - width;
+          v[1].y = v[3].y = V0->y + width;
+        }
+        else if (fabs(V0->x - V1->x) < 0.0001)
+        {
+          v[0].y = v[1].y = V0->y;
+          v[2].y = v[3].y = V1->y;
+
+          width *= rdp.scale_x;
+          v[0].x = v[2].x = V0->x - width;
+          v[1].x = v[3].x = V0->x + width;
+        }
+        else
+        {
+          float dx = V1->x - V0->x;
+          float dy = V1->y - V0->y;
+          float len = sqrtf(dx*dx + dy*dy);
+          float wx = dy * width * rdp.scale_x / len;
+          float wy = dx * width * rdp.scale_y / len;
+          v[0].x = V0->x + wx;
+          v[0].y = V0->y - wy;
+          v[1].x = V0->x - wx;
+          v[1].y = V0->y + wy;
+          v[2].x = V1->x + wx;
+          v[2].y = V1->y - wy;
+          v[3].x = V1->x - wx;
+          v[3].y = V1->y + wy;
+        }
+        grDrawTriangle(&v[0], &v[1], &v[2]);
+        grDrawTriangle(&v[1], &v[2], &v[3]);
+      }
+      else
+      {
+        DepthBuffer(rdp.vtxbuf, n);
+        if ((rdp.rm & 0xC10) == 0xC10)
+          grDepthBiasLevel (-deltaZ);
+        grDrawVertexArray (GR_TRIANGLE_FAN, n, rdp.vtx_buffer?(&vtx_list2):(&vtx_list1));
+      }
+    }
+  }
+
+  if (_debugger.capture) add_tri (rdp.vtxbuf, n, TRI_TRIANGLE);
+}
+
+void add_tri (VERTEX *v, int n, int type)
+{
+  //FRDP ("ENTER (%f, %f, %f), (%f, %f, %f), (%f, %f, %f)\n", v[0].x, v[0].y, v[0].w,
+  //  v[1].x, v[1].y, v[1].w, v[2].x, v[2].y, v[2].w);
+
+  // Debug capture
+  if (_debugger.capture)
+  {
+    rdp.debug_n ++;
+
+    TRI_INFO *info = new TRI_INFO;
+    info->nv = 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 = _debugger.tri_list;
+    _debugger.tri_list = info;
+
+    if (_debugger.tri_last == NULL)
+      _debugger.tri_last = _debugger.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 = (wxUint32)max(min((rdp.scissor_o.ul_x * rdp.scale_x + rdp.offset_x + 0.01f),settings.res_x),0);
+    rdp.scissor.lr_x = (wxUint32)max(min((rdp.scissor_o.lr_x * rdp.scale_x + rdp.offset_x + 0.01f),settings.res_x),0);
+    rdp.scissor.ul_y = (wxUint32)max(min((rdp.scissor_o.ul_y * rdp.scale_y + rdp.offset_y + 0.01f),settings.res_y),0);
+    rdp.scissor.lr_y = (wxUint32)max(min((rdp.scissor_o.lr_y * rdp.scale_y + rdp.offset_y + 0.01f),settings.res_y),0);
+    //grClipWindow specifies the hardware clipping window. Any pixels outside the clipping window are rejected.
+    //Values are inclusive for minimum x and y values and exclusive for maximum x and y values.
+//    grClipWindow (rdp.scissor.ul_x?rdp.scissor.ul_x+1:0, rdp.scissor.ul_y?rdp.scissor.ul_y+1:0, rdp.scissor.lr_x, rdp.scissor.lr_y);
+    if (fullscreen)
+      grClipWindow (rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y);
+    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 ()
+{
+  LRDP ("-+ 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 & 0x00000400)?1:0],
+      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;
+
+    // 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;
+    rdp.update |= UPDATE_ALPHA_COMPARE;
+  }
+
+  // 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 = (wxUint8)((rdp.othermode_l>>30)&0x3);
+    rdp.fbl_b0 = (wxUint8)((rdp.othermode_l>>26)&0x3);
+    rdp.fbl_c0 = (wxUint8)((rdp.othermode_l>>22)&0x3);
+    rdp.fbl_d0 = (wxUint8)((rdp.othermode_l>>18)&0x3);
+    rdp.fbl_a1 = (wxUint8)((rdp.othermode_l>>28)&0x3);
+    rdp.fbl_b1 = (wxUint8)((rdp.othermode_l>>24)&0x3);
+    rdp.fbl_c1 = (wxUint8)((rdp.othermode_l>>20)&0x3);
+    rdp.fbl_d1 = (wxUint8)((rdp.othermode_l>>16)&0x3);
+
+    rdp.update |= UPDATE_COMBINE;
+  }
+
+  // Combine MUST go before texture
+  if ((rdp.update & UPDATE_COMBINE) && rdp.allow_combine)
+  {
+    TBUFF_COLOR_IMAGE * aTBuff[2] = {0, 0};
+    if (rdp.aTBuffTex[0])
+      aTBuff[rdp.aTBuffTex[0]->tile] = rdp.aTBuffTex[0];
+    if (rdp.aTBuffTex[1])
+      aTBuff[rdp.aTBuffTex[1]->tile] = rdp.aTBuffTex[1];
+    rdp.aTBuffTex[0] = aTBuff[0];
+    rdp.aTBuffTex[1] = aTBuff[1];
+
+    LRDP (" |-+ 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 == RDP::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_ENABLED) || rdp.zsrc == 1) && rdp.cycle_mode < 2)
+      {
+        if (rdp.flags & ZBUF_COMPARE)
+        {
+          switch ((rdp.rm & 0xC00)>>10) {
+            case 0:
+              grDepthBiasLevel(0);
+              grDepthBufferFunction (settings.zmode_compare_less ? GR_CMP_LESS : GR_CMP_LEQUAL);
+              break;
+            case 1:
+              grDepthBiasLevel(-4);
+              grDepthBufferFunction (settings.zmode_compare_less ? GR_CMP_LESS : GR_CMP_LEQUAL);
+              break;
+            case 2:
+              grDepthBiasLevel(settings.ucode == 7 ? -4 : 0);
+              grDepthBufferFunction (GR_CMP_LESS);
+              break;
+            case 3:
+              // will be set dynamically per polygon
+              //grDepthBiasLevel(-deltaZ);
+              grDepthBufferFunction (GR_CMP_LEQUAL);
+              break;
+          }
+        }
+        else
+        {
+          grDepthBiasLevel(0);
+          grDepthBufferFunction (GR_CMP_ALWAYS);
+        }
+
+        if (rdp.flags & ZBUF_UPDATE)
+          grDepthMask (FXTRUE);
+        else
+          grDepthMask (FXFALSE);
+      }
+      else
+      {
+        grDepthBiasLevel(0);
+        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)))
+      {
+        wxUint8 reference = (wxUint8)(rdp.blend_color&0xFF);
+        grAlphaTestFunction (reference ? GR_CMP_GEQUAL : 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);
+            LRDP (" |- alpha compare: 0x20\n");
+          }
+          else
+          {
+            grAlphaTestFunction (GR_CMP_GREATER);
+            if (rdp.acmp == 3)
+            {
+              grAlphaTestReferenceValue ((wxUint8)(rdp.blend_color&0xFF));
+              FRDP (" |- alpha compare: blend: %02lx\n", rdp.blend_color&0xFF);
+            }
+            else
+            {
+              grAlphaTestReferenceValue (0x00);
+              LRDP (" |- alpha compare: 0x00\n");
+            }
+          }
+        }
+        else
+        {
+          grAlphaTestFunction (GR_CMP_ALWAYS);
+          LRDP (" |- alpha compare: none\n");
+        }
+      }
+      if (rdp.acmp == 3 && rdp.cycle_mode < 2)
+      {
+        if (grStippleModeExt != 0)
+        {
+          if (settings.old_style_adither || rdp.alpha_dither_mode != 3) {
+            LRDP (" |- alpha compare: dither\n");
+            grStippleModeExt(settings.stipple_mode);
+          }
+          else
+            grStippleModeExt(GR_STIPPLE_DISABLE);
+        }
+      }
+      else
+      {
+        if (grStippleModeExt)
+        {
+          //LRDP (" |- 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;
+      wxUint32 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;
+
+      wxUint16 blender = (wxUint16)(rdp.othermode_l >> 16);
+      if (rdp.flags & FOG_ENABLED)
+      {
+        rdp_blender_setting &bl = *(rdp_blender_setting*)(&(blender));
+        if((rdp.fog_multiplier > 0) && (bl.c1_m1a==3 || bl.c1_m2a == 3 || bl.c2_m1a == 3 || bl.c2_m2a == 3))
+        {
+          grFogColorValue(rdp.fog_color);
+          grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
+          rdp.fog_mode = RDP::fog_enabled;
+          LRDP("fog enabled \n");
+        }
+        else
+        {
+          LRDP("fog disabled in blender\n");
+          rdp.fog_mode = RDP::fog_disabled;
+          grFogMode (GR_FOG_DISABLE);
+        }
+      }
+      else if (blender == 0xc410 || blender == 0xc411 || blender == 0xf500)
+      {
+        grFogColorValue(rdp.fog_color);
+        grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
+        rdp.fog_mode = RDP::fog_blend;
+        LRDP("fog blend \n");
+      }
+      else if (blender == 0x04d1)
+      {
+        grFogColorValue(rdp.fog_color);
+        grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
+        rdp.fog_mode = RDP::fog_blend_inverse;
+        LRDP("fog blend \n");
+      }
+      else
+      {
+        LRDP("fog disabled\n");
+        rdp.fog_mode = RDP::fog_disabled;
+        grFogMode (GR_FOG_DISABLE);
+      }
+    }
+  }
+
+  if (rdp.update & UPDATE_VIEWPORT)
+  {
+    rdp.update ^= UPDATE_VIEWPORT;
+    if (fullscreen)
+    {
+      float scale_x = (float)fabs(rdp.view_scale[0]);
+      float scale_y = (float)fabs(rdp.view_scale[1]);
+
+      rdp.clip_min_x = max((rdp.view_trans[0] - scale_x + rdp.offset_x) / rdp.clip_ratio, 0.0f);
+      rdp.clip_min_y = max((rdp.view_trans[1] - scale_y + rdp.offset_y) / rdp.clip_ratio, 0.0f);
+      rdp.clip_max_x = min((rdp.view_trans[0] + scale_x + rdp.offset_x) * rdp.clip_ratio, settings.res_x);
+      rdp.clip_max_y = min((rdp.view_trans[1] + scale_y + rdp.offset_y) * rdp.clip_ratio, settings.res_y);
+
+      FRDP (" |- viewport - (%d, %d, %d, %d)\n", (wxUint32)rdp.clip_min_x, (wxUint32)rdp.clip_min_y, (wxUint32)rdp.clip_max_x, (wxUint32)rdp.clip_max_y);
+      if (!rdp.scissor_set)
+      {
+        rdp.scissor.ul_x = (wxUint32)rdp.clip_min_x;
+        rdp.scissor.lr_x = (wxUint32)rdp.clip_max_x;
+        rdp.scissor.ul_y = (wxUint32)rdp.clip_min_y;
+        rdp.scissor.lr_y = (wxUint32)rdp.clip_max_y;
+        grClipWindow (rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y);
+      }
+    }
+  }
+
+  if (rdp.update & UPDATE_SCISSOR)
+    update_scissor ();
+
+  LRDP (" + 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);
+  }
+  grTexFilterMode (0, GR_TEXTUREFILTER_BILINEAR, GR_TEXTUREFILTER_BILINEAR);
+  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,
+    voodoo.tex_min_addr[GR_TMU0] + offset_font,
+    GR_MIPMAPLEVELMASK_BOTH,
+    &fontTex);
+  grFogMode (GR_FOG_DISABLE);
+}
+
diff --git a/source/gles2glide64/src/Glide64/Util.h b/source/gles2glide64/src/Glide64/Util.h
new file mode 100644 (file)
index 0000000..f577a9c
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+#ifndef Util_H
+#define Util_H
+
+#define NOT_TMU0       0x00
+#define NOT_TMU1       0x01
+#define NOT_TMU2       0x02
+
+void util_init ();
+void render_tri (wxUint16 linew = 0);
+
+int cull_tri (VERTEX **v);
+void draw_tri (VERTEX **v, wxUint16 linew = 0);
+void do_triangle_stuff (wxUint16 linew = 0, int old_interpolate = TRUE);
+void do_triangle_stuff_2 (wxUint16 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 ();
+
+float ScaleZ(float z);
+
+// positional and texel coordinate clipping
+#define CCLIP(ux,lx,ut,lt,uc,lc) \
+               if (ux > lx || lx < uc || ux > lc) { rdp.tri_n += 2; return; } \
+               if (ux < uc) { \
+                       float p = (uc-ux)/(lx-ux); \
+                       ut = p*(lt-ut)+ut; \
+                       ux = uc; \
+               } \
+               if (lx > lc) { \
+                       float p = (lc-ux)/(lx-ux); \
+                       lt = p*(lt-ut)+ut; \
+                       lx = lc; \
+               }
+
+#define CCLIP2(ux,lx,ut,lt,un,ln,uc,lc) \
+               if (ux > lx || lx < uc || ux > lc) { rdp.tri_n += 2; return; } \
+               if (ux < uc) { \
+                       float p = (uc-ux)/(lx-ux); \
+                       ut = p*(lt-ut)+ut; \
+                       un = p*(ln-un)+un; \
+                       ux = uc; \
+               } \
+               if (lx > lc) { \
+                       float p = (lc-ux)/(lx-ux); \
+                       lt = p*(lt-ut)+ut; \
+                       ln = p*(ln-un)+un; \
+                       lx = lc; \
+               }
+
+#if defined(__GNUC__)
+  #define bswap32(x) __builtin_bswap32(x)
+#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+  #include <stdlib.h>
+  #define bswap32(x) _byteswap_ulong(x)
+#else
+static inline uint32_t bswap32(uint32_t val)
+{
+       return (((val & 0xff000000) >> 24) |
+               ((val & 0x00ff0000) >>  8) |
+               ((val & 0x0000ff00) <<  8) |
+               ((val & 0x000000ff) << 24));
+}
+#endif
+
+#define ALOWORD(x)   (*((uint16_t*)&(x)))   // low word
+
+template<class T> static inline T __ROR__(T value, unsigned int count)
+{
+  const unsigned int nbits = sizeof(T) * 8;
+  count %= nbits;
+
+  T low = value << (nbits - count);
+  value >>= count;
+  value |= low;
+  return value;
+}
+
+// rotate left
+template<class T> static T __ROL__(T value, unsigned int count)
+{
+  const unsigned int nbits = sizeof(T) * 8;
+  count %= nbits;
+
+  T high = value >> (nbits - count);
+  value <<= count;
+  value |= high;
+  return value;
+}
+
+#endif  // ifndef Util_H
diff --git a/source/gles2glide64/src/Glide64/cursor.h b/source/gles2glide64/src/Glide64/cursor.h
new file mode 100644 (file)
index 0000000..6031409
--- /dev/null
@@ -0,0 +1,2069 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+wxUint8 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/source/gles2glide64/src/Glide64/font.h b/source/gles2glide64/src/Glide64/font.h
new file mode 100644 (file)
index 0000000..c44edc2
--- /dev/null
@@ -0,0 +1,2069 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+wxUint8 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/source/gles2glide64/src/Glide64/m64p.h b/source/gles2glide64/src/Glide64/m64p.h
new file mode 100755 (executable)
index 0000000..3f47cf6
--- /dev/null
@@ -0,0 +1,98 @@
+/******************************************************************************
+ * Glide64 - Glide video plugin for Nintendo 64 emulators.
+ * http://bitbucket.org/richard42/mupen64plus-video-glide64mk2/
+ *
+ * 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
+
+#ifndef OLDAPI
+
+#include "m64p_types.h"
+#include "m64p_plugin.h"
+#include "m64p_common.h"
+#include "m64p_config.h"
+#include "m64p_vidext.h"
+#include "winlnxdefs.h"
+#include <stdio.h>
+
+#define PLUGIN_NAME                 "Glide64mk2 Video Plugin"
+#define PLUGIN_VERSION              0x020000
+#define VIDEO_PLUGIN_API_VERSION       0x020200
+#define CONFIG_API_VERSION          0x020000
+#define VIDEXT_API_VERSION          0x030000
+
+void WriteLog(m64p_msg_level level, const char *msg, ...);
+
+//The Glide API originally used an integer to pick an enumerated resolution.
+//To accomodate arbitrary resolutions, pack it into a 32-bit struct
+//so we don't have to change function signatures
+union PackedScreenResolution
+{
+    struct 
+    {
+        int width : 16;
+        int height : 15;
+        int fullscreen : 1;
+    };
+    int resolution;
+};
+
+
+/* definitions of pointers to Core config functions */
+extern ptr_ConfigOpenSection      ConfigOpenSection;
+extern ptr_ConfigSetParameter     ConfigSetParameter;
+extern ptr_ConfigGetParameter     ConfigGetParameter;
+extern ptr_ConfigGetParameterHelp ConfigGetParameterHelp;
+extern ptr_ConfigSetDefaultInt    ConfigSetDefaultInt;
+extern ptr_ConfigSetDefaultFloat  ConfigSetDefaultFloat;
+extern ptr_ConfigSetDefaultBool   ConfigSetDefaultBool;
+extern ptr_ConfigSetDefaultString ConfigSetDefaultString;
+extern ptr_ConfigGetParamInt      ConfigGetParamInt;
+extern ptr_ConfigGetParamFloat    ConfigGetParamFloat;
+extern ptr_ConfigGetParamBool     ConfigGetParamBool;
+extern ptr_ConfigGetParamString   ConfigGetParamString;
+
+extern ptr_ConfigGetSharedDataFilepath ConfigGetSharedDataFilepath;
+extern ptr_ConfigGetUserConfigPath     ConfigGetUserConfigPath;
+extern ptr_ConfigGetUserDataPath       ConfigGetUserDataPath;
+extern ptr_ConfigGetUserCachePath      ConfigGetUserCachePath;
+
+
+extern ptr_VidExt_Init                  CoreVideo_Init;
+extern ptr_VidExt_Quit                  CoreVideo_Quit;
+extern ptr_VidExt_ListFullscreenModes   CoreVideo_ListFullscreenModes;
+extern ptr_VidExt_SetVideoMode          CoreVideo_SetVideoMode;
+extern ptr_VidExt_SetCaption            CoreVideo_SetCaption;
+extern ptr_VidExt_ToggleFullScreen      CoreVideo_ToggleFullScreen;
+extern ptr_VidExt_ResizeWindow          CoreVideo_ResizeWindow;
+extern ptr_VidExt_GL_GetProcAddress     CoreVideo_GL_GetProcAddress;
+extern ptr_VidExt_GL_SetAttribute       CoreVideo_GL_SetAttribute;
+extern ptr_VidExt_GL_SwapBuffers        CoreVideo_GL_SwapBuffers;
+
+#else
+
+#include <wx/wx.h>
+#include <wx/fileconf.h>
+#include <wx/wfstream.h>
+
+
+#endif
+
+#endif
diff --git a/source/gles2glide64/src/Glide64/osal_dynamiclib.h b/source/gles2glide64/src/Glide64/osal_dynamiclib.h
new file mode 100755 (executable)
index 0000000..c24377b
--- /dev/null
@@ -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/source/gles2glide64/src/Glide64/osal_dynamiclib_unix.c b/source/gles2glide64/src/Glide64/osal_dynamiclib_unix.c
new file mode 100755 (executable)
index 0000000..b3b7ba5
--- /dev/null
@@ -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 <stdlib.h>
+#include <stdio.h>
+#include <dlfcn.h>
+
+#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/source/gles2glide64/src/Glide64/osal_dynamiclib_win32.c b/source/gles2glide64/src/Glide64/osal_dynamiclib_win32.c
new file mode 100755 (executable)
index 0000000..685d717
--- /dev/null
@@ -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 <windows.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#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/source/gles2glide64/src/Glide64/rdp.cpp b/source/gles2glide64/src/Glide64/rdp.cpp
new file mode 100755 (executable)
index 0000000..9373bf6
--- /dev/null
@@ -0,0 +1,4355 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+#include <math.h>
+#include "Gfx_1.3.h"
+#include "m64p.h"
+#include "Ini.h"
+#include "Config.h"
+#include "3dmath.h"
+#include "Util.h"
+#include "Debugger.h"
+#include "Combine.h"
+#include "TexCache.h"
+#include "TexBuffer.h"
+#include "FBtoScreen.h"
+#include "CRC.h"
+
+#ifdef PAULSCODE
+#include "FrameSkipper.h"
+extern FrameSkipper frameSkipper;
+#endif
+
+#ifdef PERFORMANCE
+#include "ticks.h"
+#endif
+
+#ifdef __ARM_NEON__
+#include "arm_neon.h"
+//#include "ticks.h"
+#endif
+
+/*
+const int NumOfFormats = 3;
+SCREEN_SHOT_FORMAT ScreenShotFormats[NumOfFormats] = { {wxT("BMP"), wxT("bmp"), wxBITMAP_TYPE_BMP}, {wxT("PNG"), wxT("png"), wxBITMAP_TYPE_PNG}, {wxT("JPEG"), wxT("jpeg"), wxBITMAP_TYPE_JPEG} };
+*/
+const char *ACmp[] = { "NONE", "THRESHOLD", "UNKNOWN", "DITHER" };
+
+const char *Mode0[] = { "COMBINED",    "TEXEL0",
+            "TEXEL1",     "PRIMITIVE",
+            "SHADE",      "ENVIORNMENT",
+            "1",        "NOISE",
+            "0",        "0",
+            "0",        "0",
+            "0",        "0",
+            "0",        "0" };
+
+const char *Mode1[] = { "COMBINED",    "TEXEL0",
+            "TEXEL1",     "PRIMITIVE",
+            "SHADE",      "ENVIORNMENT",
+            "CENTER",     "K4",
+            "0",        "0",
+            "0",        "0",
+            "0",        "0",
+            "0",        "0" };
+
+const char *Mode2[] = { "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[] = { "COMBINED",    "TEXEL0",
+            "TEXEL1",     "PRIMITIVE",
+            "SHADE",      "ENVIORNMENT",
+            "1",        "0" };
+
+const char *Alpha0[] = { "COMBINED",   "TEXEL0",
+            "TEXEL1",     "PRIMITIVE",
+            "SHADE",      "ENVIORNMENT",
+            "1",        "0" };
+
+#define Alpha1 Alpha0
+const char *Alpha2[] = { "LOD_FRACTION", "TEXEL0",
+            "TEXEL1",     "PRIMITIVE",
+            "SHADE",      "ENVIORNMENT",
+            "PRIM_LODFRAC",   "0" };
+#define Alpha3 Alpha0
+
+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[] = { "G_ZS_PIXEL", "G_ZS_PRIM" };
+
+const char *str_yn[] = { "NO", "YES" };
+const char *str_offon[] = { "OFF", "ON" };
+
+const char *str_cull[] = { "DISABLE", "FRONT", "BACK", "BOTH" };
+
+// I=intensity probably
+const char *str_format[] = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" };
+const char *str_size[]   = { "4bit", "8bit", "16bit", "32bit" };
+const char *str_cm[]     = { "WRAP/NO CLAMP", "MIRROR/NO CLAMP", "WRAP/CLAMP", "MIRROR/CLAMP" };
+const char *str_lod[]    = { "1", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024", "2048" };
+const char *str_aspect[] = { "1x8", "1x4", "1x2", "1x1", "2x1", "4x1", "8x1" };
+
+const char *str_filter[] = { "Point Sampled", "Average (box)", "Bilinear" };
+
+const char *str_tlut[]   = { "TT_NONE", "TT_UNKNOWN", "TT_RGBA_16", "TT_IA_16" };
+
+const char *str_dither[] = { "Pattern", "~Pattern", "Noise", "None" };
+
+const char *CIStatus[]   = { "ci_main", "ci_zimg", "ci_unknown",  "ci_useless",
+                            "ci_old_copy", "ci_copy", "ci_copy_self",
+                            "ci_zcopy", "ci_aux", "ci_aux_copy" };
+
+//static variables
+
+char out_buf[2048];
+
+wxUint32 frame_count;  // frame counter
+
+int ucode_error_report = TRUE;
+int wrong_tile = -1;
+
+// ** 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 rdphalf_1();
+static void rdphalf_2();
+static void rdphalf_cont();
+
+static void rsp_reserved0();
+static void rsp_reserved1();
+static void rsp_reserved2();
+static void rsp_reserved3();
+
+static void ys_memrect();
+
+wxUint8 microcode[4096];
+wxUint32 uc_crc;
+void microcheck ();
+
+#ifdef PAULSCODE
+#define Check_FrameSkip  if (frameSkipper.willSkipNext()) return
+#else
+#define Check_FrameSkip         {}
+#endif
+
+// ** 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 "ucode09.h"
+#include "ucode.h"
+#include "ucode09rdp.h"
+#include "turbo3D.h"
+
+static int reset = 0;
+static int old_ucode = -1;
+
+void RDP::Reset()
+{
+  memset(this, 0, sizeof(RDP_Base));
+  // set all vertex numbers
+  for (int i=0; i<MAX_VTX; i++)
+    vtx[i].number = i;
+
+  scissor_o.ul_x = 0;
+  scissor_o.ul_y = 0;
+  scissor_o.lr_x = 320;
+  scissor_o.lr_y = 240;
+
+  vi_org_reg = *gfx.VI_ORIGIN_REG;
+  view_scale[2] = 32.0f * 511.0f;
+  view_trans[2] = 32.0f * 511.0f;
+  clip_ratio = 1.0f;
+
+  lookat[0][0] = lookat[1][1] = 1.0f;
+
+  cycle_mode = 2;
+  allow_combine = 1;
+  rdp.update = UPDATE_SCISSOR | UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE;
+  fog_mode = RDP::fog_enabled;
+  maincimg[0].addr = maincimg[1].addr = last_drawn_ci_addr = 0x7FFFFFFF;
+
+  hotkey_info.hk_ref = 90;
+  hotkey_info.hk_motionblur = (settings.buff_clear == 0)?0:90;
+  hotkey_info.hk_filtering = hotkey_info.hk_motionblur;
+
+  CheckKeyPressed(G64_VK_BACK, 1); //BACK
+  CheckKeyPressed(G64_VK_B, 1);
+  CheckKeyPressed(G64_VK_V, 1);
+}
+
+RDP::RDP()
+{
+  vtx1 = new VERTEX[256];
+  memset(vtx1, 0, sizeof(VERTEX)*256);
+  vtx2 = new VERTEX[256];
+  memset(vtx2, 0, sizeof(VERTEX)*256);
+  vtxbuf = vtxbuf2 = 0;
+  vtx_buffer = n_global = 0;
+
+  for (int i = 0; i < MAX_TMU; i++)
+  {
+    cache[i] = new CACHE_LUT[MAX_CACHE];
+    cur_cache[i] = 0;
+    cur_cache_n[i] = 0;
+  };
+
+  vtx = new VERTEX[MAX_VTX];
+  memset(vtx, 0, sizeof(VERTEX)*MAX_VTX);
+  v0 = vn = 0;
+
+  frame_buffers = new COLOR_IMAGE[NUMTEXBUF+2];
+}
+
+RDP::~RDP()
+{
+  delete[] vtx1;
+  delete[] vtx2;
+  for (int i = 0; i < MAX_TMU; i++)
+    delete[] cache[i];
+
+  delete[] vtx;
+  delete[] frame_buffers;
+}
+
+void rdp_reset ()
+{
+  reset = 1;
+  rdp.Reset();
+}
+
+void microcheck ()
+{
+  wxUint32 i;
+  uc_crc = 0;
+
+  // Check first 3k of ucode, because the last 1k sometimes contains trash
+  for (i=0; i<3072>>2; i++)
+  {
+    uc_crc += ((wxUint32*)microcode)[i];
+  }
+
+  FRDP_E ("crc: %08lx\n", uc_crc);
+
+#ifdef LOG_UCODE
+  std::ofstream ucf;
+  ucf.open ("ucode.txt", std::ios::out | std::ios::binary);
+  char d;
+  for (i=0; i<0x400000; i++)
+  {
+    d = ((char*)gfx.RDRAM)[i^3];
+    ucf.write (&d, 1);
+  }
+  ucf.close ();
+#endif
+
+  FRDP("ucode = %08lx\n", uc_crc);
+
+  Ini * ini = Ini::OpenIni();
+  ini->SetPath("UCODE");
+  char str[9];
+  sprintf (str, "%08lx", (unsigned long)uc_crc);
+  int uc = ini->Read(str, -2);
+
+  if (uc == -2 && ucode_error_report)
+  {
+    settings.ucode = Config_ReadInt("ucode", "Force microcode", 0, TRUE, FALSE);
+
+    ReleaseGfx ();
+    ERRLOG("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)
+  {
+    settings.ucode = ini->Read(_T("/SETTINGS/ucode"), 0);
+
+    ReleaseGfx ();
+    ERRLOG("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);
+    if (uc_crc == 0x8d5735b2 || uc_crc == 0xb1821ed3 || uc_crc == 0x1118b3e0) //F3DLP.Rej ucode. perspective texture correction is not implemented
+    {
+      rdp.Persp_en = 1;
+      rdp.persp_supported = FALSE;
+    }
+    else if (settings.texture_correction)
+      rdp.persp_supported = TRUE;
+  }
+}
+
+#ifdef __WINDOWS__
+static void GetClientSize(int * width, int * height)
+{
+#ifdef __WINDOWS__
+  RECT win_rect;
+  GetClientRect (gfx.hWnd, &win_rect);
+  *width = win_rect.right;
+  *height = win_rect.bottom;
+#else
+  GFXWindow->GetClientSize(width, height);
+#endif
+}
+#endif
+
+void drawNoFullscreenMessage()
+{
+//need to find, how to do it on non-windows OS
+//the code below will compile on any OS
+//but it works only on windows, because
+//I don't know, how to initialize GFXWindow on other OS
+#ifdef __WINDOWS__
+  LOG ("drawNoFullscreenMessage ()\n");
+  if (rdp.window_changed)
+  {
+    rdp.window_changed = FALSE;
+    int width, height;
+    GetClientSize(&width, &height);
+
+    wxClientDC dc(GFXWindow);
+    dc.SetBrush(*wxMEDIUM_GREY_BRUSH);
+    dc.SetTextForeground(*wxWHITE);
+    dc.SetBackgroundMode(wxTRANSPARENT);
+    dc.DrawRectangle(0, 0, width, height);
+
+    wxCoord w, h;
+    wxString text = wxT("Glide64mk2");
+    dc.GetTextExtent(text, &w, &h);
+    wxCoord x = (width - w)/2;
+    wxCoord y = height/2 - h*4;
+    dc.DrawText(text, x, y);
+
+    text = wxT("Gfx cannot be drawn in windowed mode");
+    dc.GetTextExtent(text, &w, &h);
+    x = (width - w)/2;
+    y = height/2 - h;
+    dc.DrawText(text, x, y);
+
+    text = wxT("Press Alt+Enter to switch to fullscreen");
+    dc.GetTextExtent(text, &w, &h);
+    x = (width - w)/2;
+    y = (height - h)/2 + h*2;
+    dc.DrawText(text, x, y);
+  }
+#endif
+}
+
+static wxUint32 d_ul_x, d_ul_y, d_lr_x, d_lr_y;
+
+static void DrawPartFrameBufferToScreen()
+{
+  FB_TO_SCREEN_INFO fb_info;
+  fb_info.addr   = rdp.cimg;
+  fb_info.size   = rdp.ci_size;
+  fb_info.width  = rdp.ci_width;
+  fb_info.height = rdp.ci_height;
+  fb_info.ul_x = d_ul_x;
+  fb_info.lr_x = d_lr_x;
+  fb_info.ul_y = d_ul_y;
+  fb_info.lr_y = d_lr_y;
+  fb_info.opaque = 0;
+  DrawFrameBufferToScreen(fb_info);
+  memset(gfx.RDRAM+rdp.cimg, 0, (rdp.ci_width*rdp.ci_height)<<rdp.ci_size>>1);
+}
+
+#define RGBA16TO32(color) \
+  ((color&1)?0xFF:0) | \
+  ((wxUint32)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) | \
+  ((wxUint32)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) | \
+  ((wxUint32)((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.
+
+  wxUint32 width = rdp.ci_width;//*gfx.VI_WIDTH_REG;
+  wxUint32 height;
+  if (fb_emulation_enabled && !(settings.hacks&hack_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.hacks&hack_PPL)
+      height -= rdp.ci_upper_bound;
+  }
+  FRDP ("width: %d, height: %d...  ", width, height);
+//printf("CopyFrameBuffer width: %d, height: %d...  ", width, height);
+
+  if (rdp.scale_x < 1.1f)
+  {
+    wxUint16 * ptr_src = new wxUint16[width*height];
+    if (grLfbReadRegion(buffer,
+      (wxUint32)rdp.offset_x,
+      (wxUint32)rdp.offset_y,//rdp.ci_upper_bound,
+      width,
+      height,
+      width<<1,
+      ptr_src))
+    {
+      wxUint16 *ptr_dst = (wxUint16*)(gfx.RDRAM+rdp.cimg);
+      wxUint32 *ptr_dst32 = (wxUint32*)(gfx.RDRAM+rdp.cimg);
+      wxUint16 c;
+
+      for (wxUint32 y=0; y<height; y++)
+      {
+        for (wxUint32 x=0; x<width; x++)
+        {
+          c = ptr_src[x + y * width];
+          if (settings.frame_buffer&fb_read_alpha)
+          {
+            if (c > 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);
+        }
+      }
+      LRDP("ReadRegion.  Framebuffer copy complete.\n");
+    }
+    else
+    {
+      LRDP("Framebuffer copy failed.\n");
+    }
+    delete[] ptr_src;
+  }
+  else
+  {
+    if (rdp.motionblur && fb_hwfbe_enabled)
+    {
+      return;
+    }
+    else
+    {
+      float scale_x = (settings.scr_res_x - rdp.offset_x*2.0f)  / max(width, rdp.vi_width);
+      float scale_y = (settings.scr_res_y - rdp.offset_y*2.0f) / max(height, rdp.vi_height);
+
+      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);
+//printf("CopyFrameBuffer 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);
+
+      if (grLfbLock (GR_LFB_READ_ONLY,
+        buffer,
+        GR_LFBWRITEMODE_565,
+        GR_ORIGIN_UPPER_LEFT,
+        FXFALSE,
+        &info))
+      {
+        wxUint16 *ptr_src = (wxUint16*)info.lfbPtr;
+        wxUint16 *ptr_dst = (wxUint16*)(gfx.RDRAM+rdp.cimg);
+        wxUint32 *ptr_dst32 = (wxUint32*)(gfx.RDRAM+rdp.cimg);
+        wxUint16 c;
+        wxUint32 stride = info.strideInBytes>>1;
+
+        int read_alpha = settings.frame_buffer & fb_read_alpha;
+        if ((settings.hacks&hack_PMario) && rdp.frame_buffers[rdp.ci_count-1].status != ci_aux)
+          read_alpha = FALSE;
+        int x_start = 0, y_start = 0, x_end = width, y_end = height;
+        if (settings.hacks&hack_BAR)
+        {
+          x_start = 80, y_start = 24, x_end = 240, y_end = 86;
+        }
+        for (int y=y_start; y<y_end; y++)
+        {
+          for (int x=x_start; x<x_end; x++)
+          {
+            c = ptr_src[int(x*scale_x + rdp.offset_x) + int(y * scale_y + rdp.offset_y) * stride];
+            c = (c&0xFFC0) | ((c&0x001F) << 1) | 1;
+            if (read_alpha && c == 1)
+              c = 0;
+            if (rdp.ci_size <= 2)
+              ptr_dst[(x + y * width)^1] = c;
+            else
+              ptr_dst32[x + y * width] = RGBA16TO32(c);
+          }
+        }
+
+        // Unlock the backbuffer
+        grLfbUnlock (GR_LFB_READ_ONLY, buffer);
+        LRDP("LfbLock.  Framebuffer copy complete.\n");
+      }
+      else
+      {
+        LRDP("Framebuffer copy failed.\n");
+      }
+    }
+  }
+}
+
+void GoToFullScreen()
+{
+    //if (!InitGfx ())
+    {
+      LOG ("FAILED!!!\n");
+      return;
+    }
+}
+
+class SoftLocker
+{
+public:
+  // lock the mutex in the ctor
+  SoftLocker(SDL_sem *mutex)
+    : _isOk(false), _mutex(mutex)
+  { _isOk = ( SDL_SemTryWait(_mutex) == 0 ); }
+
+  // returns true if mutex was successfully locked in ctor
+  bool IsOk() const
+  { return _isOk; }
+
+  // unlock the mutex in dtor
+  ~SoftLocker()
+  { if ( IsOk() ) SDL_SemPost(_mutex); }
+
+private:
+  bool     _isOk;
+  SDL_sem *_mutex;
+};
+
+
+/******************************************************************
+Function: ProcessDList
+Purpose:  This function is called when there is a Dlist to be
+processed. (High level GFX list)
+input:    none
+output:   none
+*******************************************************************/
+void DetectFrameBufferUsage ();
+wxUint32 fbreads_front = 0;
+wxUint32 fbreads_back = 0;
+int cpu_fb_read_called = FALSE;
+int cpu_fb_write_called = FALSE;
+int cpu_fb_write = FALSE;
+int cpu_fb_ignore = FALSE;
+int CI_SET = TRUE;
+wxUint32 ucode5_texshiftaddr = 0;
+wxUint32 ucode5_texshiftcount = 0;
+wxUint16 ucode5_texshift = 0;
+int depth_buffer_fog;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+EXPORT void CALL ProcessDList(void)
+{
+//  SoftLocker lock(mutexProcessDList);
+#ifdef PAULSCODE
+//printf("ProcessDList()\n");
+//  frameSkipper.newFrame();
+  if (0)
+//  if (frameSkipper.willSkipNext())
+#else
+  if (/*!lock.IsOk()*/0) //mutex is busy
+#endif
+  {
+// printf("Frameskip, reason=%s\n", (lock.IsOk())?"lock":"frameskip");
+ /*   if (!fullscreen)
+      drawNoFullscreenMessage();*/
+    // Set an interrupt to allow the game to continue
+    *(gfx.MI_INTR_REG) |= 0x20;
+    gfx.CheckInterrupts();
+       *(gfx.MI_INTR_REG) |= 0x01;
+       gfx.CheckInterrupts();
+//     rdp.updatescreen = 1;
+//     no_dlist = true;
+//    rdp_fullsync();
+    return;
+  }
+
+  no_dlist = false;
+  update_screen_count = 0;
+  ChangeSize ();
+
+#ifdef ALTTAB_FIX
+  if (!hhkLowLevelKybd)
+  {
+    hhkLowLevelKybd = SetWindowsHookEx(WH_KEYBOARD_LL,
+      LowLevelKeyboardProc, NULL, 0);
+  }
+#endif
+
+  VLOG ("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;
+    if (settings.autodetect_ucode)
+    {
+      // Thanks to ZeZu for ucode autodetection!!!
+      wxUint32 startUcode = *(wxUint32*)(gfx.DMEM+0xFD0);
+      memcpy (microcode, gfx.RDRAM+startUcode, 4096);
+      microcheck ();
+    }
+    else
+      memset (microcode, 0, 4096);
+  }
+  else if ( ((old_ucode == ucode_S2DEX) && (settings.ucode == ucode_F3DEX)) || settings.force_microcheck)
+  {
+    wxUint32 startUcode = *(wxUint32*)(gfx.DMEM+0xFD0);
+    memcpy (microcode, gfx.RDRAM+startUcode, 4096);
+    microcheck ();
+  }
+
+  if (exception)
+    return;
+
+  // Switch to fullscreen?
+  if (to_fullscreen)
+    GoToFullScreen();
+
+  if (!fullscreen && !settings.run_in_window)
+    return;
+
+  // 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, (*(wxUint32*)(gfx.DMEM+0x0FE4))>>6);
+  if (rdp.model_stack_size == 0)
+    rdp.model_stack_size = 32;
+  rdp.Persp_en = TRUE;
+  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;
+  rdp.bg_image_height = 0xFFFF;
+  fbreads_front = fbreads_back = 0;
+  rdp.fog_multiplier = rdp.fog_offset = 0;
+  rdp.zsrc = 0;
+  if (rdp.vi_org_reg != *gfx.VI_ORIGIN_REG)
+    rdp.tlut_mode = 0; //is it correct?
+  rdp.scissor_set = FALSE;
+  ucode5_texshiftaddr = ucode5_texshiftcount = 0;
+  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;
+  depth_buffer_fog = TRUE;
+//printf("ProcessDList\n");
+  //analize possible frame buffer usage
+  if (fb_emulation_enabled)
+    DetectFrameBufferUsage();
+  if (!(settings.hacks&hack_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
+  wxUint32 dlist_start = *(wxUint32*)(gfx.DMEM+0xFF0);
+  wxUint32 dlist_length = *(wxUint32*)(gfx.DMEM+0xFF4);
+  FRDP("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx, fbuf_width: %d, dlist start: %08lx, dlist_length: %d, x_scale: %f, y_scale: %f\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG, *gfx.VI_WIDTH_REG, dlist_start, dlist_length, (*gfx.VI_X_SCALE_REG & 0xFFF)/1024.0f, (*gfx.VI_Y_SCALE_REG & 0xFFF)/1024.0f);
+  FRDP_E("--- NEW DLIST --- crc: %08lx, ucode: %d, fbuf: %08lx\n", uc_crc, settings.ucode, *gfx.VI_ORIGIN_REG);
+
+  if (cpu_fb_write == TRUE)
+    DrawPartFrameBufferToScreen();
+  if ((settings.hacks&hack_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;
+  wxUint32 a;
+  
+
+  // catches exceptions so that it doesn't freeze
+#ifdef CATCH_EXCEPTIONS
+  try {
+#endif
+    if (settings.ucode == ucode_Turbo3d)
+    {
+      Turbo3D();
+    }
+    else
+    {
+      // 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 = ((wxUint32*)gfx.RDRAM)[a>>2];   // \ Current command, 64 bit
+        rdp.cmd1 = ((wxUint32*)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
+        perf_cur = ticksGetTicks();
+#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;
+
+            LRDP("End of DL\n");
+            rdp.pc_i --;
+          }
+        }
+
+#ifdef PERFORMANCE
+        perf_next = ticksGetTicks();
+        sprintf (out_buf, "perf %08x: %lli\n", a-8, (perf_next-perf_cur));
+#ifdef RDP_LOGGING
+        rdp_log << out_buf;
+#else
+               printf(out_buf);
+#endif
+#endif
+
+      } while (!rdp.halt);
+    }
+#ifdef CATCH_EXCEPTIONS
+  } catch (...) {
+
+    if (fullscreen)
+    {
+      ReleaseGfx ();
+      rdp_reset ();
+#ifdef TEXTURE_FILTER
+      if (settings.ghq_use)
+      {
+        ext_ghq_shutdown();
+        settings.ghq_use = 0;
+      }
+#endif
+    }
+    ERRLOG("The GFX plugin caused an exception and has been disabled.");
+      exception = TRUE;
+    return;
+  }
+#endif
+
+  if (fb_emulation_enabled)
+  {
+    rdp.scale_x = rdp.scale_x_bak;
+    rdp.scale_y = rdp.scale_y_bak;
+  }
+#ifdef PAULSCODE
+  if (!frameSkipper.willSkipNext())
+#endif
+  if (settings.frame_buffer & fb_ref)
+    CopyFrameBuffer ();
+  if (rdp.cur_image)
+    CloseTextureBuffer(rdp.read_whole_frame && ((settings.hacks&hack_PMario) || rdp.swap_ci_index >= 0));
+
+  if ((settings.hacks&hack_TGR2) && rdp.vi_org_reg != *gfx.VI_ORIGIN_REG && CI_SET)
+  {
+    newSwapBuffers ();
+    CI_SET = FALSE;
+  }
+  LRDP("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 _ENDUSER_RELEASE_
+  *gfx.MI_INTR_REG |= 0x20;
+  gfx.CheckInterrupts();
+  rdp.halt = 1;
+#endif
+}
+
+// spnoop - no operation, always ignore
+static void spnoop()
+{
+  LRDP("spnoop\n");
+}
+
+// noop - no operation, always ignore
+static void rdp_noop()
+{
+  LRDP("noop\n");
+}
+
+static void ys_memrect ()
+{
+  wxUint32 tile = (wxUint16)((rdp.cmd1 & 0x07000000) >> 24);
+
+  wxUint32 lr_x = (wxUint16)((rdp.cmd0 & 0x00FFF000) >> 14);
+  wxUint32 lr_y = (wxUint16)((rdp.cmd0 & 0x00000FFF) >> 2);
+  wxUint32 ul_x = (wxUint16)((rdp.cmd1 & 0x00FFF000) >> 14);
+  wxUint32 ul_y = (wxUint16)((rdp.cmd1 & 0x00000FFF) >> 2);
+
+  if (lr_y > rdp.scissor_o.lr_y)
+    lr_y = rdp.scissor_o.lr_y;
+  wxUint32 off_x = ((rdp.cmd2 & 0xFFFF0000) >> 16) >> 5;
+  wxUint32 off_y = (rdp.cmd2 & 0x0000FFFF) >> 5;
+
+  FRDP ("memrect (%d, %d, %d, %d), ci_width: %d", ul_x, ul_y, lr_x, lr_y, rdp.ci_width);
+  if (off_x > 0)
+    FRDP ("  off_x: %d", off_x);
+  if (off_y > 0)
+    FRDP ("  off_y: %d", off_y);
+  LRDP("\n");
+
+  wxUint32 y, width = lr_x - ul_x;
+  wxUint32 tex_width = rdp.tiles[tile].line << 3;
+  wxUint8 * texaddr = gfx.RDRAM + rdp.addr[rdp.tiles[tile].t_mem] + tex_width*off_y + off_x;
+  wxUint8 * fbaddr = gfx.RDRAM + rdp.cimg + ul_x;
+
+  for (y = ul_y; y < lr_y; y++) {
+    wxUint8 *src = texaddr + (y - ul_y) * tex_width;
+    wxUint8 *dst = fbaddr + y * rdp.ci_width;
+    memcpy (dst, src, width);
+  }
+}
+
+static void pm_palette_mod ()
+{
+  wxUint8 envr = (wxUint8)((float)((rdp.env_color >> 24)&0xFF)/255.0f*31.0f);
+  wxUint8 envg = (wxUint8)((float)((rdp.env_color >> 16)&0xFF)/255.0f*31.0f);
+  wxUint8 envb = (wxUint8)((float)((rdp.env_color >> 8)&0xFF)/255.0f*31.0f);
+  wxUint16 env16 = (wxUint16)((envr<<11)|(envg<<6)|(envb<<1)|1);
+  wxUint8 prmr = (wxUint8)((float)((rdp.prim_color >> 24)&0xFF)/255.0f*31.0f);
+  wxUint8 prmg = (wxUint8)((float)((rdp.prim_color >> 16)&0xFF)/255.0f*31.0f);
+  wxUint8 prmb = (wxUint8)((float)((rdp.prim_color >> 8)&0xFF)/255.0f*31.0f);
+  wxUint16 prim16 = (wxUint16)((prmr<<11)|(prmg<<6)|(prmb<<1)|1);
+  wxUint16 * dst = (wxUint16*)(gfx.RDRAM+rdp.cimg);
+  for (int i = 0; i < 16; i++)
+  {
+    dst[i^1] = (rdp.pal_8[i]&1) ? prim16 : env16;
+  }
+  LRDP("Texrect palette modification\n");
+}
+
+static void pd_zcopy ()
+{
+  wxUint16 ul_x = (wxUint16)((rdp.cmd1 & 0x00FFF000) >> 14);
+  wxUint16 lr_x = (wxUint16)((rdp.cmd0 & 0x00FFF000) >> 14) + 1;
+  wxUint16 ul_u = (wxUint16)((rdp.cmd2 & 0xFFFF0000) >> 21) + 1;
+  wxUint16 *ptr_dst = (wxUint16*)(gfx.RDRAM+rdp.cimg);
+  wxUint16 width = lr_x - ul_x;
+  wxUint16 * ptr_src = ((wxUint16*)rdp.tmem)+ul_u;
+  wxUint16 c;
+  for (wxUint16 x=0; x<width; x++)
+  {
+    c = ptr_src[x];
+    c = ((c<<8)&0xFF00) | (c >> 8);
+    ptr_dst[(ul_x+x)^1] = c;
+    //      FRDP("dst[%d]=%04lx \n", (x + ul_x)^1, c);
+  }
+}
+
+static void DrawDepthBufferFog()
+{
+  if (rdp.zi_width < 200)
+    return;
+  FB_TO_SCREEN_INFO fb_info;
+  fb_info.addr   = rdp.zimg;
+  fb_info.size   = 2;
+  fb_info.width  = rdp.zi_width;
+  fb_info.height = rdp.ci_height;
+  fb_info.ul_x = rdp.scissor_o.ul_x;
+  fb_info.lr_x = rdp.scissor_o.lr_x;
+  fb_info.ul_y = rdp.scissor_o.ul_y;
+  fb_info.lr_y = rdp.scissor_o.lr_y;
+  fb_info.opaque = 0;
+  DrawDepthBufferToScreen(fb_info);
+}
+
+static void rdp_texrect()
+{
+  if (!rdp.LLE)
+  {
+    wxUint32 a = rdp.pc[rdp.pc_i];
+    wxUint8 cmdHalf1 = gfx.RDRAM[a+3];
+    wxUint8 cmdHalf2 = gfx.RDRAM[a+11];
+    a >>= 2;
+    if ((cmdHalf1 == 0xE1 && cmdHalf2 == 0xF1) || (cmdHalf1 == 0xB4 && cmdHalf2 == 0xB3) || (cmdHalf1 == 0xB3 && cmdHalf2 == 0xB2))
+    {
+      //gSPTextureRectangle
+      rdp.cmd2 = ((wxUint32*)gfx.RDRAM)[a+1];
+      rdp.cmd3 = ((wxUint32*)gfx.RDRAM)[a+3];
+      rdp.pc[rdp.pc_i] += 16;
+    }
+    else
+    {
+      //gDPTextureRectangle
+      if (settings.hacks&hack_ASB)
+        rdp.cmd2 = 0;
+      else
+        rdp.cmd2 = ((wxUint32*)gfx.RDRAM)[a+0];
+      rdp.cmd3 = ((wxUint32*)gfx.RDRAM)[a+1];
+      rdp.pc[rdp.pc_i] += 8;
+    }
+  }
+  if ((settings.hacks&hack_Yoshi) && settings.ucode == ucode_S2DEX)
+  {
+    ys_memrect();
+    return;
+  }
+
+  if (rdp.skip_drawing || (!fb_emulation_enabled && (rdp.cimg == rdp.zimg)))
+  {
+    if ((settings.hacks&hack_PMario) && rdp.ci_status == ci_useless)
+    {
+      pm_palette_mod ();
+    }
+    else
+    {
+      LRDP("Texrect skipped\n");
+    }
+    return;
+  }
+
+  if ((settings.ucode == ucode_CBFD) && 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);
+    LRDP("Shadow texrect is skipped.\n");
+    rdp.tri_n += 2;
+    return;
+  }
+
+  if ((settings.ucode == ucode_PerfectDark) && (rdp.frame_buffers[rdp.ci_count-1].status == ci_zcopy))
+  {
+    pd_zcopy ();
+    LRDP("Depth buffer copied.\n");
+    rdp.tri_n += 2;
+    return;
+  }
+
+  if ((rdp.othermode_l >> 16) == 0x3c18 && rdp.cycle1 == 0x03ffffff && rdp.cycle2 == 0x01ff1fff) //depth image based fog
+  {
+    if (!depth_buffer_fog)
+      return;
+    if (settings.fog)
+      DrawDepthBufferFog();
+    depth_buffer_fog = FALSE;
+    return;
+  }
+
+  //  FRDP ("rdp.cycle1 %08lx, rdp.cycle2 %08lx\n", rdp.cycle1, rdp.cycle2);
+
+  float ul_x, ul_y, lr_x, lr_y;
+  if (rdp.cycle_mode == 2)
+  {
+    ul_x = max(0.0f, (short)((rdp.cmd1 & 0x00FFF000) >> 14));
+    ul_y = max(0.0f, (short)((rdp.cmd1 & 0x00000FFF) >> 2));
+    lr_x = max(0.0f, (short)((rdp.cmd0 & 0x00FFF000) >> 14));
+    lr_y = max(0.0f, (short)((rdp.cmd0 & 0x00000FFF) >> 2));
+  }
+  else
+  {
+    ul_x = max(0.0f, ((short)((rdp.cmd1 & 0x00FFF000) >> 12)) / 4.0f);
+    ul_y = max(0.0f, ((short)(rdp.cmd1 & 0x00000FFF)) / 4.0f);
+    lr_x = max(0.0f, ((short)((rdp.cmd0 & 0x00FFF000) >> 12)) / 4.0f);
+    lr_y = max(0.0f, ((short)(rdp.cmd0 & 0x00000FFF)) / 4.0f);
+  }
+
+  if (ul_x >= lr_x)
+  {
+    FRDP("Wrong Texrect: ul_x: %f, lr_x: %f\n", ul_x, lr_x);
+    return;
+  }
+
+  if (rdp.cycle_mode > 1)
+  {
+    lr_x += 1.0f;
+    lr_y += 1.0f;
+  } else if (lr_y - ul_y < 1.0f)
+    lr_y = ceil(lr_y);
+
+  if (settings.increase_texrect_edge)
+  {
+    if (floor(lr_x) != lr_x)
+      lr_x = ceil(lr_x);
+    if (floor(lr_y) != lr_y)
+      lr_y = ceil(lr_y);
+  }
+
+  //*
+  if (rdp.tbuff_tex && (settings.frame_buffer & fb_optimize_texrect))
+  {
+    LRDP("Attempt to optimize texrect\n");
+    if (!rdp.tbuff_tex->drawn)
+    {
+      DRAWIMAGE d;
+      d.imageX  = 0;
+      d.imageW  = (wxUint16)rdp.tbuff_tex->width;
+      d.frameX  = (wxUint16)ul_x;
+      d.frameW  = (wxUint16)(rdp.tbuff_tex->width);
+
+      d.imageY  = 0;
+      d.imageH  = (wxUint16)rdp.tbuff_tex->height;
+      d.frameY  = (wxUint16)ul_y;
+      d.frameH  = (wxUint16)(rdp.tbuff_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.tbuff_tex->width, rdp.tbuff_tex->height);
+      d.scaleX  = 1.0f;
+      d.scaleY  = 1.0f;
+      DrawHiresImage(d, rdp.tbuff_tex->width == rdp.ci_width);
+      rdp.tbuff_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.hacks&hack_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 (!fb_hwfbe_enabled && ((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 == ucode_PerfectDark) && (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 (fb_emulation_enabled)
+      if (rdp.frame_buffers[rdp.ci_count-1].status == ci_copy_self)
+      {
+        //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);
+        LRDP("Wrong Texrect.\n");
+        rdp.tri_n += 2;
+        return;
+      }
+  }
+  //*/
+
+  int i;
+
+  wxUint32 tile = (wxUint16)((rdp.cmd1 & 0x07000000) >> 24);
+
+  rdp.texrecting = 1;
+
+  wxUint32 prev_tile = rdp.cur_tile;
+  rdp.cur_tile = tile;
+
+  const float Z = set_sprite_combine_mode ();
+
+  rdp.texrecting = 0;
+
+  if (!rdp.cur_cache[0])
+  {
+    rdp.cur_tile = prev_tile;
+    rdp.tri_n += 2;
+    return;
+  }
+  // ****
+  // ** Texrect offset by Gugaman **
+  //
+  //integer representation of texture coordinate.
+  //needed to detect and avoid overflow after shifting
+  wxInt32 off_x_i = (rdp.cmd2 >> 16) & 0xFFFF;
+  wxInt32 off_y_i = rdp.cmd2 & 0xFFFF;
+  float dsdx = (float)((short)((rdp.cmd3 & 0xFFFF0000) >> 16)) / 1024.0f;
+  float dtdy = (float)((short)(rdp.cmd3 & 0x0000FFFF)) / 1024.0f;
+  if (off_x_i & 0x8000) //check for sign bit
+    off_x_i |= ~0xffff; //make it negative
+  //the same as for off_x_i
+  if (off_y_i & 0x8000)
+    off_y_i |= ~0xffff;
+
+  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 (%.2f, %.2f, %.2f, %.2f), 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_i/32.0f, off_y_i/32.0f, dsdx, dtdy);
+
+  float off_size_x;
+  float off_size_y;
+
+  if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip
+  {
+#ifdef TEXTURE_FILTER
+    if (rdp.cur_cache[0]->is_hires_tex)
+    {
+      off_size_x = (float)((lr_y - ul_y) * dsdx);
+      off_size_y = (float)((lr_x - ul_x) * dtdy);
+    }
+    else
+#endif
+    {
+      off_size_x = (lr_y - ul_y - 1) * dsdx;
+      off_size_y = (lr_x - ul_x - 1) * dtdy;
+    }
+  }
+  else
+  {
+#ifdef TEXTURE_FILTER
+    if (rdp.cur_cache[0]->is_hires_tex)
+    {
+      off_size_x = (float)((lr_x - ul_x) * dsdx);
+      off_size_y = (float)((lr_y - ul_y) * dtdy);
+    }
+    else
+#endif
+    {
+      off_size_x = (lr_x - ul_x - 1) * dsdx;
+      off_size_y = (lr_y - ul_y - 1) * dtdy;
+    }
+  }
+
+  struct {
+    float ul_u, ul_v, lr_u, lr_v;
+  } texUV[2]; //struct for texture coordinates
+  //angrylion's macro, helps to cut overflowed values.
+  #define SIGN16(x) (((x) & 0x8000) ? ((x) | ~0xffff) : ((x) & 0xffff))
+
+  //calculate texture coordinates
+  for (int i = 0; i < 2; i++)
+  {
+    if (rdp.cur_cache[i] && (rdp.tex & (i+1)))
+    {
+      float sx = 1, sy = 1;
+      int x_i = off_x_i, y_i = off_y_i;
+      TILE & tile = rdp.tiles[rdp.cur_tile + i];
+      //shifting
+      if (tile.shift_s)
+      {
+        if (tile.shift_s > 10)
+        {
+          wxUint8 iShift = (16 - tile.shift_s);
+          x_i <<= iShift;
+          sx = (float)(1 << iShift);
+        }
+        else
+        {
+          wxUint8 iShift = tile.shift_s;
+          x_i >>= iShift;
+          sx = 1.0f/(float)(1 << iShift);
+        }
+      }
+      if (tile.shift_t)
+      {
+        if (tile.shift_t > 10)
+        {
+          wxUint8 iShift = (16 - tile.shift_t);
+          y_i <<= iShift;
+          sy = (float)(1 << iShift);
+        }
+        else
+        {
+          wxUint8 iShift = tile.shift_t;
+          y_i >>= iShift;
+          sy = 1.0f/(float)(1 << iShift);
+        }
+      }
+
+      if (rdp.aTBuffTex[i]) //hwfbe texture
+      {
+        float t0_off_x;
+        float t0_off_y;
+        if (off_x_i + off_y_i == 0)
+        {
+          t0_off_x = tile.ul_s;
+          t0_off_y = tile.ul_t;
+        }
+        else
+        {
+          t0_off_x = off_x_i/32.0f;
+          t0_off_y = off_y_i/32.0f;
+        }
+        t0_off_x += rdp.aTBuffTex[i]->u_shift;// + tile.ul_s; //commented for Paper Mario motion blur
+        t0_off_y += rdp.aTBuffTex[i]->v_shift;// + tile.ul_t;
+        texUV[i].ul_u = t0_off_x * sx;
+        texUV[i].ul_v = t0_off_y * sy;
+
+        texUV[i].lr_u = texUV[i].ul_u + off_size_x * sx;
+        texUV[i].lr_v = texUV[i].ul_v + off_size_y * sy;
+
+        texUV[i].ul_u *= rdp.aTBuffTex[i]->u_scale;
+        texUV[i].ul_v *= rdp.aTBuffTex[i]->v_scale;
+        texUV[i].lr_u *= rdp.aTBuffTex[i]->u_scale;
+        texUV[i].lr_v *= rdp.aTBuffTex[i]->v_scale;
+        FRDP("tbuff_tex[%d] ul_u: %f, ul_v: %f, lr_u: %f, lr_v: %f\n",
+          i, texUV[i].ul_u, texUV[i].ul_v, texUV[i].lr_u, texUV[i].lr_v);
+      }
+      else //common case
+      {
+        //kill 10.5 format overflow by SIGN16 macro
+        texUV[i].ul_u = SIGN16(x_i) / 32.0f;
+        texUV[i].ul_v = SIGN16(y_i) / 32.0f;
+
+        texUV[i].ul_u -= tile.f_ul_s;
+        texUV[i].ul_v -= tile.f_ul_t;
+
+        texUV[i].lr_u = texUV[i].ul_u + off_size_x * sx;
+        texUV[i].lr_v = texUV[i].ul_v + off_size_y * sy;
+
+        texUV[i].ul_u = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_x * texUV[i].ul_u;
+        texUV[i].lr_u = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_x * texUV[i].lr_u;
+        texUV[i].ul_v = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_y * texUV[i].ul_v;
+        texUV[i].lr_v = rdp.cur_cache[i]->c_off + rdp.cur_cache[i]->c_scl_y * texUV[i].lr_v;
+      }
+    }
+    else
+    {
+      texUV[i].ul_u = texUV[i].ul_v = texUV[i].lr_u = texUV[i].lr_v = 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, texUV[0].ul_u, texUV[0].lr_u, texUV[1].ul_u, texUV[1].lr_u, (float)rdp.scissor.ul_x, (float)rdp.scissor.lr_x);
+  CCLIP2 (s_ul_y, s_lr_y, texUV[0].ul_v, texUV[0].lr_v, texUV[1].ul_v, texUV[1].lr_v, (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);
+
+  VERTEX vstd[4] = {
+    { s_ul_x, s_ul_y, Z, 1.0f, texUV[0].ul_u, texUV[0].ul_v, texUV[1].ul_u, texUV[1].ul_v, {0, 0, 0, 0}, 255 },
+    { s_lr_x, s_ul_y, Z, 1.0f, texUV[0].lr_u, texUV[0].ul_v, texUV[1].lr_u, texUV[1].ul_v, {0, 0, 0, 0}, 255 },
+    { s_ul_x, s_lr_y, Z, 1.0f, texUV[0].ul_u, texUV[0].lr_v, texUV[1].ul_u, texUV[1].lr_v, {0, 0, 0, 0}, 255 },
+    { s_lr_x, s_lr_y, Z, 1.0f, texUV[0].lr_u, texUV[0].lr_v, texUV[1].lr_u, texUV[1].lr_v, {0, 0, 0, 0}, 255 } };
+
+    if ( ((rdp.cmd0>>24)&0xFF) == 0xE5 ) //texrectflip
+    {
+      vstd[1].u0 = texUV[0].ul_u;
+      vstd[1].v0 = texUV[0].lr_v;
+      vstd[1].u1 = texUV[1].ul_u;
+      vstd[1].v1 = texUV[1].lr_v;
+
+      vstd[2].u0 = texUV[0].lr_u;
+      vstd[2].v0 = texUV[0].ul_v;
+      vstd[2].u1 = texUV[1].lr_u;
+      vstd[2].v1 = texUV[1].ul_v;
+    }
+
+    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.aTBuffTex[0] && 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;
+      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);
+      n_vertices = num_verts_line << 1;
+      vnew = new VERTEX [n_vertices];
+      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; i<end_u_256; i++)
+      {
+        // Find where x = current 256 multiple
+        float x = m * ((i<<8)+256) + b;
+
+        int vn = 2 + ((i-start_u_256)<<2);
+        vnew[vn] = vstd[0];
+        vnew[vn].x = x;
+        vnew[vn].u0 = 255.5f;
+        vnew[vn].v0 += (float)splitheight * i;
+        vnew[vn].u1 = 255.5f;
+        vnew[vn].v1 += (float)splitheight * i;
+
+        vn ++;
+        vnew[vn] = vstd[2];
+        vnew[vn].x = x;
+        vnew[vn].u0 = 255.5f;
+        vnew[vn].v0 += (float)splitheight * i;
+        vnew[vn].u1 = 255.5f;
+        vnew[vn].v1 += (float)splitheight * i;
+
+        vn ++;
+        vnew[vn] = vnew[vn-2];
+        vnew[vn].u0 = 0.5f;
+        vnew[vn].v0 += (float)splitheight;
+        vnew[vn].u1 = 0.5f;
+        vnew[vn].v1 += (float)splitheight;
+
+        vn ++;
+        vnew[vn] = vnew[vn-2];
+        vnew[vn].u0 = 0.5f;
+        vnew[vn].v0 += (float)splitheight;
+        vnew[vn].u1 = 0.5f;
+        vnew[vn].v1 += (float)splitheight;
+      }
+      //*
+      if (n_vertices > 12)
+      {
+        float texbound = (float)(splitheight << 1);
+        for (int k = 0; k < n_vertices; k ++)
+        {
+          if (vnew[k].v0 > texbound)
+            vnew[k].v0 = (float)fmod(vnew[k].v0, texbound);
+        }
+      }
+      //*/
+    }
+
+    AllowShadeMods (vptr, n_vertices);
+    for (i=0; i<n_vertices; i++)
+    {
+      apply_shade_mods (&vptr[i]);
+    }
+
+    if (fullscreen)
+    {
+      if (rdp.fog_mode >= RDP::fog_blend)
+      {
+        float fog;
+        if (rdp.fog_mode == RDP::fog_blend)
+          fog = 1.0f/max(1, rdp.fog_color&0xFF);
+        else
+          fog = 1.0f/max(1, (~rdp.fog_color)&0xFF);
+        for (i = 0; i < n_vertices; i++)
+        {
+          vptr[i].f = fog;
+        }
+        grFogMode (GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
+      }
+
+      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 (_debugger.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;
+    }
+    else
+    {
+      rdp.tri_n += 2;
+    }
+
+    delete[] vnew;
+}
+
+static void rdp_loadsync()
+{
+  LRDP("loadsync - ignored\n");
+}
+
+static void rdp_pipesync()
+{
+  LRDP("pipesync - ignored\n");
+}
+
+static void rdp_tilesync()
+{
+  LRDP("tilesync - ignored\n");
+}
+
+static void rdp_fullsync()
+{
+  // Set an interrupt to allow the game to continue
+  *gfx.MI_INTR_REG |= 0x20;
+  gfx.CheckInterrupts();
+  LRDP("fullsync\n");
+}
+
+static void rdp_setkeygb()
+{
+  wxUint32 sB = rdp.cmd1&0xFF;
+  wxUint32 cB = (rdp.cmd1>>8)&0xFF;
+  wxUint32 sG = (rdp.cmd1>>16)&0xFF;
+  wxUint32 cG = (rdp.cmd1>>24)&0xFF;
+  rdp.SCALE = (rdp.SCALE&0xFF0000FF) | (sG<<16) | (sB<<8);
+  rdp.CENTER = (rdp.CENTER&0xFF0000FF) | (cG<<16) | (cB<<8);
+  FRDP("setkeygb. cG=%02lx, sG=%02lx, cB=%02lx, sB=%02lx\n", cG, sG, cB, sB);
+}
+
+static void rdp_setkeyr()
+{
+  wxUint32 sR = rdp.cmd1&0xFF;
+  wxUint32 cR = (rdp.cmd1>>8)&0xFF;
+  rdp.SCALE = (rdp.SCALE&0x00FFFFFF) | (sR<<24);
+  rdp.CENTER = (rdp.CENTER&0x00FFFFFF) | (cR<<24);
+  FRDP("setkeyr. cR=%02lx, sR=%02lx\n", cR, sR);
+}
+
+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.K4 = (wxUint8)(rdp.cmd1>>9)&0x1FF;
+  rdp.K5 = (wxUint8)(rdp.cmd1&0x1FF);
+  //  RDP_E("setconvert - IGNORED\n");
+  FRDP("setconvert. K4=%02lx K5=%02lx\n", rdp.K4, rdp.K5);
+}
+
+//
+// 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(*/(wxUint32)(((rdp.cmd0 & 0x00FFF000) >> 14))/*, 320)*/;
+  rdp.scissor_o.ul_y = /*min(*/(wxUint32)(((rdp.cmd0 & 0x00000FFF) >> 2))/*, 240)*/;
+  rdp.scissor_o.lr_x = /*min(*/(wxUint32)(((rdp.cmd1 & 0x00FFF000) >> 14))/*, 320)*/;
+  rdp.scissor_o.lr_y = /*min(*/(wxUint32)(((rdp.cmd1 & 0x00000FFF) >> 2))/*, 240)*/;
+
+  rdp.ci_upper_bound = rdp.scissor_o.ul_y;
+  rdp.ci_lower_bound = rdp.scissor_o.lr_y;
+  rdp.scissor_set = TRUE;
+
+  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;
+
+  if (rdp.view_scale[0] == 0) //viewport is not set?
+  {
+    rdp.view_scale[0] = (rdp.scissor_o.lr_x>>1)*rdp.scale_x;
+    rdp.view_scale[1] = (rdp.scissor_o.lr_y>>1)*-rdp.scale_y;
+    rdp.view_trans[0] = rdp.view_scale[0];
+    rdp.view_trans[1] = -rdp.view_scale[1];
+    rdp.update |= UPDATE_VIEWPORT;
+  }
+}
+
+static void rdp_setprimdepth()
+{
+  rdp.prim_depth = (wxUint16)((rdp.cmd1 >> 16) & 0x7FFF);
+  rdp.prim_dz = (wxUint16)(rdp.cmd1 & 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] (); \
+}
+
+  LRDP("rdp_setothermode\n");
+
+  if ((settings.ucode == ucode_F3DEX2) || (settings.ucode == ucode_CBFD))
+  {
+    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 (wxUint32 addr, wxUint16 start, wxUint16 count)
+{
+  LRDP("Loading palette... ");
+  wxUint16 *dpal = rdp.pal_8 + start;
+  wxUint16 end = start+count;
+#ifdef TEXTURE_FILTER
+  wxUint16 *spal = (wxUint16*)(gfx.RDRAM + (addr & BMASK));
+#endif
+
+  for (wxUint16 i=start; i<end; i++)
+  {
+    *(dpal++) = *(wxUint16 *)(gfx.RDRAM + (addr^2));
+    addr += 2;
+
+#ifdef TLUT_LOGGING
+    FRDP ("%d: %08lx\n", i, *(wxUint16 *)(gfx.RDRAM + (addr^2)));
+#endif
+  }
+#ifdef TEXTURE_FILTER
+  if (settings.ghq_hirs)
+    memcpy((wxUint8*)(rdp.pal_8_rice+start), spal, count<<1);
+#endif
+  start >>= 4;
+  end = start + (count >> 4);
+  if (end == start) // it can be if count < 16
+    end = start + 1;
+  for (wxUint16 p = start; p < end; p++)
+  {
+    rdp.pal_8_crc[p] = CRC32( 0xFFFFFFFF, &rdp.pal_8[(p << 4)], 32 );
+  }
+  rdp.pal_256_crc = CRC32( 0xFFFFFFFF, rdp.pal_8_crc, 64 );
+  LRDP("Done.\n");
+}
+
+static void rdp_loadtlut()
+{
+  wxUint32 tile = (rdp.cmd1 >> 24) & 0x07;
+  wxUint16 start = rdp.tiles[tile].t_mem - 256; // starting location in the palettes
+  //  wxUint16 start = ((wxUint16)(rdp.cmd1 >> 2) & 0x3FF) + 1;
+  wxUint16 count = ((wxUint16)(rdp.cmd1 >> 14) & 0x3FF) + 1;    // number to copy
+
+  if (rdp.timg.addr + (count<<1) > BMASK)
+    count = (wxUint16)((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;
+
+  if (rdp.tbuff_tex) //paranoid check.
+  {
+    //the buffer is definitely wrong, as there must be no CI frame buffers
+    //find and remove it
+    for (int i = 0; i < voodoo.num_tmu; i++)
+    {
+      for (int j = 0; j < rdp.texbufs[i].count; j++)
+      {
+        if (&(rdp.texbufs[i].images[j]) == rdp.tbuff_tex)
+        {
+          rdp.texbufs[i].count--;
+          if (j < rdp.texbufs[i].count)
+            memcpy(&(rdp.texbufs[i].images[j]), &(rdp.texbufs[i].images[j+1]), sizeof(TBUFF_COLOR_IMAGE)*(rdp.texbufs[i].count-j));
+          return;
+        }
+      }
+    }
+  }
+}
+
+int tile_set = 0;
+static void rdp_settilesize()
+{
+  wxUint32 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 = (((wxUint16)(rdp.cmd0 >> 14)) & 0x03ff);
+  int ul_t = (((wxUint16)(rdp.cmd0 >> 2 )) & 0x03ff);
+  int lr_s = (((wxUint16)(rdp.cmd1 >> 14)) & 0x03ff);
+  int lr_t = (((wxUint16)(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;
+
+  FRDP ("settilesize: tile: %d, ul_s: %d, ul_t: %d, lr_s: %d, lr_t: %d, f_ul_s: %f, f_ul_t: %f\n",
+    tile, ul_s, ul_t, lr_s, lr_t, rdp.tiles[tile].f_ul_s, rdp.tiles[tile].f_ul_t);
+}
+
+void setTBufTex(wxUint16 t_mem, wxUint32 cnt)
+{
+  FRDP("setTBufTex t_mem=%d, cnt=%d\n", t_mem, cnt);
+  TBUFF_COLOR_IMAGE * pTbufTex = rdp.tbuff_tex;
+  for (int i = 0; i < 2; i++)
+  {
+    LRDP("Before: ");
+    if (rdp.aTBuffTex[i]) {
+      FRDP("rdp.aTBuffTex[%d]: tmu=%d t_mem=%d tile=%d\n", i, rdp.aTBuffTex[i]->tmu, rdp.aTBuffTex[i]->t_mem, rdp.aTBuffTex[i]->tile);
+    } else {
+      FRDP("rdp.aTBuffTex[%d]=0\n", i);
+    }
+    if ((rdp.aTBuffTex[i] == 0 && rdp.aTBuffTex[i^1] != pTbufTex) || (rdp.aTBuffTex[i] && rdp.aTBuffTex[i]->t_mem >= t_mem && rdp.aTBuffTex[i]->t_mem < t_mem + cnt))
+    {
+      if (pTbufTex)
+      {
+        rdp.aTBuffTex[i] = pTbufTex;
+        rdp.aTBuffTex[i]->t_mem = t_mem;
+        pTbufTex = 0;
+        FRDP("rdp.aTBuffTex[%d] tmu=%d t_mem=%d\n", i, rdp.aTBuffTex[i]->tmu, rdp.aTBuffTex[i]->t_mem);
+      }
+      else
+      {
+        rdp.aTBuffTex[i] = 0;
+        FRDP("rdp.aTBuffTex[%d]=0\n", i);
+      }
+    }
+  }
+}
+
+static inline void loadBlock(uint32_t *src, uint32_t *dst, uint32_t off, int dxt, int cnt)
+{
+  uint32_t *v5;
+  int v6;
+  uint32_t *v7;
+  uint32_t v8;
+  int v9;
+  uint32_t v10;
+  uint32_t *v11;
+  uint32_t v12;
+  uint32_t v13;
+  uint32_t v14;
+  int v15;
+  int v16;
+  uint32_t *v17;
+  int v18;
+  uint32_t v19;
+  uint32_t v20;
+  int i;
+
+  v5 = dst;
+  v6 = cnt;
+  if ( cnt )
+  {
+    v7 = (uint32_t *)((char *)src + (off & 0xFFFFFFFC));
+    v8 = off & 3;
+    if ( !(off & 3) )
+      goto LABEL_23;
+    v9 = 4 - v8;
+    v10 = *v7;
+    v11 = v7 + 1;
+    do
+    {
+      v10 = __ROL__(v10, 8);
+      --v8;
+    }
+    while ( v8 );
+    do
+    {
+      v10 = __ROL__(v10, 8);
+      *(uint8_t *)v5 = v10;
+      v5 = (uint32_t *)((char *)v5 + 1);
+      --v9;
+    }
+    while ( v9 );
+    v12 = *v11;
+    v7 = v11 + 1;
+    *v5 = bswap32(v12);
+    ++v5;
+    v6 = cnt - 1;
+    if ( cnt != 1 )
+    {
+LABEL_23:
+      do
+      {
+        *v5 = bswap32(*v7);
+        v5[1] = bswap32(v7[1]);
+        v7 += 2;
+        v5 += 2;
+        --v6;
+      }
+      while ( v6 );
+    }
+    v13 = off & 3;
+    if ( off & 3 )
+    {
+      v14 = *(uint32_t *)((char *)src + ((8 * cnt + off) & 0xFFFFFFFC));
+      do
+      {
+        v14 = __ROL__(v14, 8);
+        *(uint8_t *)v5 = v14;
+        v5 = (uint32_t *)((char *)v5 + 1);
+        --v13;
+      }
+      while ( v13 );
+    }
+  }
+  v15 = cnt;
+  v16 = 0;
+  v17 = dst;
+  v18 = 0;
+dxt_test:
+  while ( 1 )
+  {
+    v17 += 2;
+    --v15;
+    if ( !v15 )
+      break;
+    v16 += dxt;
+    if ( v16 < 0 )
+    {
+      while ( 1 )
+      {
+        ++v18;
+        --v15;
+        if ( !v15 )
+          goto end_dxt_test;
+        v16 += dxt;
+        if ( v16 >= 0 )
+        {
+          for ( i = v15; v18; --v18 )
+          {
+            v19 = *v17;
+            *v17 = v17[1];
+            v17[1] = v19;
+            v17 += 2;
+          }
+          v15 = i;
+          goto dxt_test;
+        }
+      }
+    }
+  }
+end_dxt_test:
+  while ( v18 )
+  {
+    v20 = *v17;
+    *v17 = v17[1];
+    v17[1] = v20;
+    v17 += 2;
+    --v18;
+  }
+}
+
+void LoadBlock32b(wxUint32 tile, wxUint32 ul_s, wxUint32 ul_t, wxUint32 lr_s, wxUint32 dxt);
+static void rdp_loadblock()
+{
+  if (rdp.skip_drawing)
+  {
+    LRDP("loadblock skipped\n");
+    return;
+  }
+  wxUint32 tile = (wxUint32)((rdp.cmd1 >> 24) & 0x07);
+  wxUint32 dxt = (wxUint32)(rdp.cmd1 & 0x0FFF);
+  wxUint16 lr_s = (wxUint16)(rdp.cmd1 >> 14) & 0x3FF;
+  if (ucode5_texshiftaddr)
+  {
+    if (ucode5_texshift % ((lr_s+1)<<3))
+    {
+      rdp.timg.addr -= ucode5_texshift;
+      ucode5_texshiftaddr = 0;
+      ucode5_texshift = 0;
+      ucode5_texshiftcount = 0;
+    }
+    else
+      ucode5_texshiftcount++;
+  }
+
+  rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr;
+
+  // ** DXT is used for swapping every other line
+  /*  double fdxt = (double)0x8000000F/(double)((wxUint32)(2047/(dxt-1))); // F for error
+  wxUint32 _dxt = (wxUint32)fdxt;*/
+
+  // 0x00000800 -> 0x80000000 (so we can check the sign bit instead of the 11th bit)
+  wxUint32 _dxt = dxt << 20;
+
+  wxUint32 addr = segoffset(rdp.timg.addr) & BMASK;
+
+  // lr_s specifies number of 64-bit words to copy
+  // 10.2 format
+  wxUint16 ul_s = (wxUint16)(rdp.cmd0 >> 14) & 0x3FF;
+  wxUint16 ul_t = (wxUint16)(rdp.cmd0 >>  2) & 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
+
+#ifdef TEXTURE_FILTER
+  LOAD_TILE_INFO &info = rdp.load_info[rdp.tiles[tile].t_mem];
+  info.tile_width = lr_s;
+  info.dxt = dxt;
+#endif
+
+  // 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 = (wxUint16)((BMASK-addr)>>3);
+
+  //angrylion's advice to use ul_s in texture image offset and cnt calculations.
+  //Helps to fix Vigilante 8 jpeg backgrounds and logos
+  wxUint32 off = rdp.timg.addr + (ul_s << rdp.tiles[tile].size >> 1);
+  unsigned char *dst = ((unsigned char *)rdp.tmem) + (rdp.tiles[tile].t_mem<<3);
+  wxUint32 cnt = lr_s-ul_s+1;
+  if (rdp.tiles[tile].size == 3)
+    cnt <<= 1;
+
+  if (((rdp.tiles[tile].t_mem + cnt) << 3) > sizeof(rdp.tmem)) {
+    WriteLog(M64MSG_INFO, "rdp_loadblock wanted to write %u bytes after the end of tmem", ((rdp.tiles[tile].t_mem + cnt) << 3) - sizeof(rdp.tmem));
+    cnt = (sizeof(rdp.tmem) >> 3) - (rdp.tiles[tile].t_mem);
+  }
+
+  if (rdp.timg.size == 3)
+    LoadBlock32b(tile, ul_s, ul_t, lr_s, dxt);
+  else
+    loadBlock((uint32_t *)gfx.RDRAM, (uint32_t *)dst, off, _dxt, cnt);
+
+  rdp.timg.addr += cnt << 3;
+  rdp.tiles[tile].lr_t = ul_t + ((dxt*cnt)>>11);
+
+  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);
+
+  if (fb_hwfbe_enabled)
+    setTBufTex(rdp.tiles[tile].t_mem, cnt);
+}
+
+
+static inline void loadTile(uint32_t *src, uint32_t *dst, int width, int height, int line, int off, uint32_t *end)
+{
+  uint32_t *v7;
+  int v8;
+  uint32_t *v9;
+  int v10;
+  int v11;
+  int v12;
+  uint32_t *v13;
+  int v14;
+  int v15;
+  uint32_t v16;
+  uint32_t *v17;
+  uint32_t v18;
+  int v19;
+  uint32_t v20;
+  int v21;
+  uint32_t v22;
+  int v23;
+  uint32_t *v24;
+  int v25;
+  int v26;
+  uint32_t *v27;
+  int v28;
+  int v29;
+  int v30;
+  uint32_t *v31;
+
+  v7 = dst;
+  v8 = width;
+  v9 = src;
+  v10 = off;
+  v11 = 0;
+  v12 = height;
+  do
+  {
+    if ( end < v7 )
+      break;
+    v31 = v7;
+    v30 = v8;
+    v29 = v12;
+    v28 = v11;
+    v27 = v9;
+    v26 = v10;
+    if ( v8 )
+    {
+      v25 = v8;
+      v24 = v9;
+      v23 = v10;
+      v13 = (uint32_t *)((char *)v9 + (v10 & 0xFFFFFFFC));
+      v14 = v10 & 3;
+      if ( !(v10 & 3) )
+        goto LABEL_20;
+      v15 = 4 - v14;
+      v16 = *v13;
+      v17 = v13 + 1;
+      do
+      {
+        v16 = __ROL__(v16, 8);
+        --v14;
+      }
+      while ( v14 );
+      do
+      {
+        v16 = __ROL__(v16, 8);
+        *(uint8_t *)v7 = v16;
+        v7 = (uint32_t *)((char *)v7 + 1);
+        --v15;
+      }
+      while ( v15 );
+      v18 = *v17;
+      v13 = v17 + 1;
+      *v7 = bswap32(v18);
+      ++v7;
+      --v8;
+      if ( v8 )
+      {
+LABEL_20:
+        do
+        {
+          *v7 = bswap32(*v13);
+          v7[1] = bswap32(v13[1]);
+          v13 += 2;
+          v7 += 2;
+          --v8;
+        }
+        while ( v8 );
+      }
+      v19 = v23 & 3;
+      if ( v23 & 3 )
+      {
+        v20 = *(uint32_t *)((char *)v24 + ((8 * v25 + v23) & 0xFFFFFFFC));
+        do
+        {
+          v20 = __ROL__(v20, 8);
+          *(uint8_t *)v7 = v20;
+          v7 = (uint32_t *)((char *)v7 + 1);
+          --v19;
+        }
+        while ( v19 );
+      }
+    }
+    v9 = v27;
+    v21 = v29;
+    v8 = v30;
+    v11 = v28 ^ 1;
+    if ( v28 == 1 )
+    {
+      v7 = v31;
+      if ( v30 )
+      {
+        do
+        {
+          v22 = *v7;
+          *v7 = v7[1];
+          v7[1] = v22;
+          v7 += 2;
+          --v8;
+        }
+        while ( v8 );
+      }
+      v21 = v29;
+      v8 = v30;
+    }
+    v10 = line + v26;
+    v12 = v21 - 1;
+  }
+  while ( v12 );
+}
+
+void LoadTile32b (wxUint32 tile, wxUint32 ul_s, wxUint32 ul_t, wxUint32 width, wxUint32 height);
+static void rdp_loadtile()
+{
+  if (rdp.skip_drawing)
+  {
+    LRDP("loadtile skipped\n");
+    return;
+  }
+  rdp.timg.set_by = 1;  // load tile
+
+  wxUint32 tile = (wxUint32)((rdp.cmd1 >> 24) & 0x07);
+
+  rdp.addr[rdp.tiles[tile].t_mem] = rdp.timg.addr;
+
+  wxUint16 ul_s = (wxUint16)((rdp.cmd0 >> 14) & 0x03FF);
+  wxUint16 ul_t = (wxUint16)((rdp.cmd0 >> 2 ) & 0x03FF);
+  wxUint16 lr_s = (wxUint16)((rdp.cmd1 >> 14) & 0x03FF);
+  wxUint16 lr_t = (wxUint16)((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;
+    rdp.tiles[wrong_tile].mask_s = rdp.tiles[wrong_tile].mask_t = 0;
+    //     wrong_tile = -1;
+  }
+
+  if (rdp.tbuff_tex)// && (rdp.tiles[tile].format == 0))
+  {
+    FRDP("loadtile: tbuff_tex ul_s: %d, ul_t:%d\n", ul_s, ul_t);
+    rdp.tbuff_tex->tile_uls = ul_s;
+    rdp.tbuff_tex->tile_ult = ul_t;
+  }
+
+  if ((settings.hacks&hack_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;
+  }
+
+  wxUint32 height = lr_t - ul_t + 1;   // get height
+  wxUint32 width = lr_s - ul_s + 1;
+
+#ifdef TEXTURE_FILTER
+  LOAD_TILE_INFO &info = rdp.load_info[rdp.tiles[tile].t_mem];
+  info.tile_ul_s = ul_s;
+  info.tile_ul_t = ul_t;
+  info.tile_width = (rdp.tiles[tile].mask_s ? min((wxUint16)width, 1<<rdp.tiles[tile].mask_s) : (wxUint16)width);
+  info.tile_height = (rdp.tiles[tile].mask_t ? min((wxUint16)height, 1<<rdp.tiles[tile].mask_t) : (wxUint16)height);
+  if (settings.hacks&hack_MK64) {
+    if (info.tile_width%2)
+      info.tile_width--;
+    if (info.tile_height%2)
+      info.tile_height--;
+  }
+  info.tex_width = rdp.timg.width;
+  info.tex_size = rdp.timg.size;
+#endif
+
+  int line_n = rdp.timg.width << rdp.tiles[tile].size >> 1;
+  wxUint32 offs = ul_t * line_n;
+  offs += ul_s << rdp.tiles[tile].size >> 1;
+  offs += rdp.timg.addr;
+  if (offs >= BMASK)
+    return;
+
+  if (rdp.timg.size == 3)
+  {
+    LoadTile32b(tile, ul_s, ul_t, width, height);
+  }
+  else
+  {
+    // check if points to bad location
+    if (offs + line_n*height > BMASK)
+      height = (BMASK - offs) / line_n;
+    if (height == 0)
+      return;
+
+    wxUint32 wid_64 = rdp.tiles[tile].line;
+    unsigned char *dst = ((unsigned char *)rdp.tmem) + (rdp.tiles[tile].t_mem<<3);
+    unsigned char *end = ((unsigned char *)rdp.tmem) + 4096 - (wid_64<<3);
+    loadTile((uint32_t *)gfx.RDRAM, (uint32_t *)dst, wid_64, height, line_n, offs, (uint32_t *)end);
+  }
+  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);
+
+  if (fb_hwfbe_enabled)
+    setTBufTex(rdp.tiles[tile].t_mem, rdp.tiles[tile].line*height);
+}
+
+static void rdp_settile()
+{
+  tile_set = 1; // used to check if we only load the first settilesize
+
+  rdp.first = 0;
+
+  rdp.last_tile = (wxUint32)((rdp.cmd1 >> 24) & 0x07);
+  TILE *tile = &rdp.tiles[rdp.last_tile];
+
+  tile->format = (wxUint8)((rdp.cmd0 >> 21) & 0x07);
+  tile->size = (wxUint8)((rdp.cmd0 >> 19) & 0x03);
+  tile->line = (wxUint16)((rdp.cmd0 >> 9) & 0x01FF);
+  tile->t_mem = (wxUint16)(rdp.cmd0 & 0x1FF);
+  tile->palette = (wxUint8)((rdp.cmd1 >> 20) & 0x0F);
+  tile->clamp_t = (wxUint8)((rdp.cmd1 >> 19) & 0x01);
+  tile->mirror_t = (wxUint8)((rdp.cmd1 >> 18) & 0x01);
+  tile->mask_t = (wxUint8)((rdp.cmd1 >> 14) & 0x0F);
+  tile->shift_t = (wxUint8)((rdp.cmd1 >> 10) & 0x0F);
+  tile->clamp_s = (wxUint8)((rdp.cmd1 >> 9) & 0x01);
+  tile->mirror_s = (wxUint8)((rdp.cmd1 >> 8) & 0x01);
+  tile->mask_s = (wxUint8)((rdp.cmd1 >> 4) & 0x0F);
+  tile->shift_s = (wxUint8)(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);
+
+  if (fb_hwfbe_enabled && rdp.last_tile < rdp.cur_tile + 2)
+  {
+    for (int i = 0; i < 2; i++)
+    {
+      if (rdp.aTBuffTex[i])
+      {
+        if (rdp.aTBuffTex[i]->t_mem == tile->t_mem)
+        {
+          if (rdp.aTBuffTex[i]->size == tile->size)
+          {
+            rdp.aTBuffTex[i]->tile = rdp.last_tile;
+            rdp.aTBuffTex[i]->info.format = tile->format == 0 ? GR_TEXFMT_RGB_565 : GR_TEXFMT_ALPHA_INTENSITY_88;
+            FRDP("rdp.aTBuffTex[%d] tile=%d, format=%s\n", i, rdp.last_tile, tile->format == 0 ? "RGB565" : "Alpha88");
+          }
+          else
+            rdp.aTBuffTex[i] = 0;
+          break;
+        }
+        else if (rdp.aTBuffTex[i]->tile == rdp.last_tile) //wrong! t_mem must be the same
+          rdp.aTBuffTex[i] = 0;
+      }
+    }
+  }
+}
+
+//
+// fillrect - fills a rectangle
+//
+
+static void rdp_fillrect()
+{
+  wxUint32 ul_x = ((rdp.cmd1 & 0x00FFF000) >> 14);
+  wxUint32 ul_y = (rdp.cmd1 & 0x00000FFF) >> 2;
+  wxUint32 lr_x = ((rdp.cmd0 & 0x00FFF000) >> 14) + 1;
+  wxUint32 lr_y = ((rdp.cmd0 & 0x00000FFF) >> 2) + 1;
+  if ((ul_x > lr_x) || (ul_y > lr_y))
+  {
+    LRDP("Fillrect. Wrong coordinates. Skipped\n");
+    return;
+  }
+  int pd_multiplayer = (settings.ucode == ucode_PerfectDark) && (rdp.cycle_mode == 3) && (rdp.fill_color == 0xFFFCFFFC);
+  if ((rdp.cimg == rdp.zimg) || (fb_emulation_enabled && rdp.frame_buffers[rdp.ci_count-1].status == ci_zimg) || pd_multiplayer)
+  {
+    LRDP("Fillrect - cleared the depth buffer\n");
+    if (fullscreen)
+    {
+      if (!(settings.hacks&hack_Hyperbike) || rdp.ci_width > 64) //do not clear main depth buffer for aux depth buffers
+      {
+        update_scissor ();
+        grDepthMask (FXTRUE);
+        grColorMask (FXFALSE, FXFALSE);
+        grBufferClear (0, 0, rdp.fill_color ? rdp.fill_color&0xFFFF : 0xFFFF);
+        grColorMask (FXTRUE, FXTRUE);
+        rdp.update |= UPDATE_ZBUF_ENABLED;
+      }
+      //if (settings.frame_buffer&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);
+        wxUint32 zi_width_in_dwords = rdp.ci_width >> 1;
+        ul_x >>= 1;
+        lr_x >>= 1;
+        wxUint32 * dst = (wxUint32*)(gfx.RDRAM+rdp.cimg);
+        dst += ul_y * zi_width_in_dwords;
+        for (wxUint32 y = ul_y; y < lr_y; y++)
+        {
+          for (wxUint32 x = ul_x; x < lr_x; x++)
+          {
+            dst[x] = rdp.fill_color;
+          }
+          dst += zi_width_in_dwords;
+        }
+      }
+    }
+    return;
+  }
+
+  if (rdp.skip_drawing)
+  {
+    LRDP("Fillrect skipped\n");
+    return;
+  }
+
+  if (rdp.cur_image && (rdp.cur_image->format != 0) && (rdp.cycle_mode == 3) && (rdp.cur_image->width == lr_x - ul_x) && (rdp.cur_image->height == lr_y - ul_y))
+  {
+    wxUint32 color = rdp.fill_color;
+    if (rdp.ci_size < 3)
+    {
+         color = ((color&1)?0xFF:0) |
+               ((wxUint32)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) |
+               ((wxUint32)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) |
+               ((wxUint32)((float)((color&0x003E) >> 1) / 31.0f * 255.0f) << 8);
+    }
+    grDepthMask (FXFALSE);
+    grBufferClear (color, 0, 0xFFFF);
+    grDepthMask (FXTRUE);
+    rdp.update |= UPDATE_ZBUF_ENABLED;
+    LRDP("Fillrect - cleared the texture buffer\n");
+    return;
+  }
+
+  // Update scissor
+  if (fullscreen)
+    update_scissor ();
+
+  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
+  wxInt32 s_ul_x = (wxUint32)min(max(ul_x * rdp.scale_x + rdp.offset_x + 0.01f, rdp.scissor.ul_x), rdp.scissor.lr_x);
+  wxInt32 s_lr_x = (wxUint32)min(max(lr_x * rdp.scale_x + rdp.offset_x + 0.01f, rdp.scissor.ul_x), rdp.scissor.lr_x);
+  wxInt32 s_ul_y = (wxUint32)min(max(ul_y * rdp.scale_y + rdp.offset_y + 0.01f, rdp.scissor.ul_y), rdp.scissor.lr_y);
+  wxInt32 s_lr_y = (wxUint32)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) s_lr_x = 0;
+  if (s_lr_y < 0) s_lr_y = 0;
+  if ((wxUint32)s_ul_x > settings.res_x) s_ul_x = settings.res_x;
+  if ((wxUint32)s_ul_y > 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);
+
+    const float Z = (rdp.cycle_mode == 3) ? 0.0f : set_sprite_combine_mode();
+
+    // 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)
+      {
+        wxUint32 color = rdp.fill_color;
+
+        if ((settings.hacks&hack_PMario) && rdp.frame_buffers[rdp.ci_count-1].status == ci_aux)
+        {
+          //background of auxiliary frame buffers must have zero alpha.
+          //make it black, set 0 alpha to plack pixels on frame buffer read
+          color = 0;
+        }
+        else if (rdp.ci_size < 3)
+        {
+          color = ((color&1)?0xFF:0) |
+            ((wxUint32)((float)((color&0xF800) >> 11) / 31.0f * 255.0f) << 24) |
+            ((wxUint32)((float)((color&0x07C0) >> 6) / 31.0f * 255.0f) << 16) |
+            ((wxUint32)((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);
+
+        grAlphaTestFunction (GR_CMP_ALWAYS);
+        if (grStippleModeExt)
+        grStippleModeExt(GR_STIPPLE_DISABLE);
+
+        grCullMode(GR_CULL_DISABLE);
+        grFogMode (GR_FOG_DISABLE);
+        grDepthBufferFunction (GR_CMP_ALWAYS);
+        grDepthMask (FXFALSE);
+
+        rdp.update |= UPDATE_COMBINE | UPDATE_CULL_MODE | UPDATE_FOG_ENABLED | UPDATE_ZBUF_ENABLED;
+      }
+      else
+      {
+        wxUint32 cmb_mode_c = (rdp.cycle1 << 16) | (rdp.cycle2 & 0xFFFF);
+        wxUint32 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]);
+        }
+        if ((rdp.othermode_l & 0x4000) && ((rdp.othermode_l >> 16) == 0x0550)) //special blender mode for Bomberman64
+        {
+          grAlphaCombine (GR_COMBINE_FUNCTION_LOCAL,
+            GR_COMBINE_FACTOR_NONE,
+            GR_COMBINE_LOCAL_CONSTANT,
+            GR_COMBINE_OTHER_NONE,
+            FXFALSE);
+          grConstantColorValue((cmb.ccolor&0xFFFFFF00)|(rdp.fog_color&0xFF));
+          rdp.update |= UPDATE_COMBINE;
+        }
+      }
+
+      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 (_debugger.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;
+  }
+  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  = (wxUint8)((rdp.cmd0 >> 20) & 0xF);
+  rdp.c_b0  = (wxUint8)((rdp.cmd1 >> 28) & 0xF);
+  rdp.c_c0  = (wxUint8)((rdp.cmd0 >> 15) & 0x1F);
+  rdp.c_d0  = (wxUint8)((rdp.cmd1 >> 15) & 0x7);
+  rdp.c_Aa0 = (wxUint8)((rdp.cmd0 >> 12) & 0x7);
+  rdp.c_Ab0 = (wxUint8)((rdp.cmd1 >> 12) & 0x7);
+  rdp.c_Ac0 = (wxUint8)((rdp.cmd0 >> 9)  & 0x7);
+  rdp.c_Ad0 = (wxUint8)((rdp.cmd1 >> 9)  & 0x7);
+
+  rdp.c_a1  = (wxUint8)((rdp.cmd0 >> 5)  & 0xF);
+  rdp.c_b1  = (wxUint8)((rdp.cmd1 >> 24) & 0xF);
+  rdp.c_c1  = (wxUint8)((rdp.cmd0 >> 0)  & 0x1F);
+  rdp.c_d1  = (wxUint8)((rdp.cmd1 >> 6)  & 0x7);
+  rdp.c_Aa1 = (wxUint8)((rdp.cmd1 >> 21) & 0x7);
+  rdp.c_Ab1 = (wxUint8)((rdp.cmd1 >> 3)  & 0x7);
+  rdp.c_Ac1 = (wxUint8)((rdp.cmd1 >> 18) & 0x7);
+  rdp.c_Ad1 = (wxUint8)((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 = (wxUint8)((rdp.cmd0 >> 21) & 0x07);
+  rdp.timg.size = (wxUint8)((rdp.cmd0 >> 19) & 0x03);
+  rdp.timg.width = (wxUint16)(1 + (rdp.cmd0 & 0x00000FFF));
+  rdp.timg.addr = segoffset(rdp.cmd1);
+  if (ucode5_texshiftaddr)
+  {
+    if (rdp.timg.format == 0)
+    {
+      wxUint16 * t = (wxUint16*)(gfx.RDRAM+ucode5_texshiftaddr);
+      ucode5_texshift = t[ucode5_texshiftcount^1];
+      rdp.timg.addr += ucode5_texshift;
+    }
+    else
+    {
+      ucode5_texshiftaddr = 0;
+      ucode5_texshift = 0;
+      ucode5_texshiftcount = 0;
+    }
+  }
+  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
+        CloseTextureBuffer(TRUE);
+      rdp.fb_drawn = TRUE;
+    }
+  }
+
+  if (fb_hwfbe_enabled) //search this texture among drawn texture buffers
+    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);
+}
+
+int 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 wxUint32 swapped_addr = 0;
+
+static void rdp_setcolorimage()
+{
+//unsigned int ticks = ticksGetTicks();
+//bool showdeb = false;
+  if (fb_emulation_enabled && (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?rdp.ci_count-1:0];
+    COLOR_IMAGE & next_fb = rdp.frame_buffers[rdp.ci_count+1];
+//if (cur_fb.status==ci_aux) showdeb = true;
+//if (showdeb) printf("rp_setcolorimage, status=%i\n", cur_fb.status);
+    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 (!fb_hwfbe_enabled)
+          {
+            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.hacks&hack_PMario)) //tidal wave
+            OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);
+        }
+        else if (!rdp.motionblur && fb_hwfbe_enabled && !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 (fb_hwfbe_enabled && prev_fb.status == ci_aux)
+        {
+          if (rdp.motionblur)
+          {
+            rdp.cur_image = &(rdp.texbufs[rdp.cur_tex_buf].images[0]);
+            grRenderBuffer( GR_BUFFER_TEXTUREBUFFER_EXT );
+            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 );
+          }
+          else if (rdp.read_whole_frame)
+          {
+            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.frame_buffer&fb_motionblur))
+        {
+          if (cur_fb.width == rdp.ci_width)
+          {
+            if (CopyTextureBuffer(prev_fb, cur_fb))
+            {
+              //                      if (CloseTextureBuffer(TRUE))
+              //*
+              if ((settings.hacks&hack_Zelda) && (rdp.frame_buffers[rdp.ci_count+2].status == ci_aux) && !rdp.fb_drawn) //hack for photo camera in Zelda MM
+              {
+                CopyFrameBuffer (GR_BUFFER_TEXTUREBUFFER_EXT);
+                rdp.fb_drawn = TRUE;
+                memcpy(gfx.RDRAM+cur_fb.addr,gfx.RDRAM+rdp.cimg, (cur_fb.width*cur_fb.height)<<cur_fb.size>>1);
+              }
+              //*/
+            }
+            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)<<cur_fb.size>>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 (fb_hwfbe_enabled)
+          OpenTextureBuffer(cur_fb);
+      }
+      break;
+    case ci_old_copy:
+      {
+        if (!rdp.motionblur || (settings.frame_buffer&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)<<cur_fb.size>>1);
+          }
+          //rdp.skip_drawing = TRUE;
+        }
+        else
+        {
+          memset(gfx.RDRAM+cur_fb.addr, 0, (cur_fb.width*cur_fb.height)<<rdp.ci_size>>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:
+      {
+//unsigned int tticks = ticksGetTicks();
+        if (!fb_hwfbe_enabled && cur_fb.format != 0)
+          rdp.skip_drawing = TRUE;
+        else
+        {
+          rdp.skip_drawing = FALSE;
+          if (fb_hwfbe_enabled && 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 (!fb_hwfbe_enabled && (prev_fb.status == ci_main) &&
+              (prev_fb.width == cur_fb.width)) // for Pokemon Stadium
+              CopyFrameBuffer ();
+          }
+        }
+        cur_fb.status = ci_aux;
+//tticks = ticksGetTicks() - ticks;
+//printf("intermediary: %u ms\n", tticks);
+      }
+      break;
+    case ci_zimg:
+      if (settings.ucode != ucode_PerfectDark)
+      {
+        if (fb_hwfbe_enabled && !rdp.copy_ci_index && (rdp.copy_zi_index || (settings.hacks&hack_BAR)))
+        {
+          GrLOD_t LOD = GR_LOD_LOG2_1024;
+          if (settings.scr_res_x > 1024)
+            LOD = GR_LOD_LOG2_2048;
+          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 );
+          LRDP("rdp_setcolorimage - set texture depth buffer to TMU0\n");
+        }
+      }
+      rdp.skip_drawing = TRUE;
+      break;
+    case ci_zcopy:
+      if (settings.ucode != ucode_PerfectDark)
+      {
+        if (fb_hwfbe_enabled && !rdp.copy_ci_index && rdp.copy_zi_index == rdp.ci_count)
+        {
+          CopyDepthBuffer();
+        }
+        rdp.skip_drawing = TRUE;
+      }
+      break;
+    case ci_useless:
+      rdp.skip_drawing = TRUE;
+      break;
+    case ci_copy_self:
+      if (fb_hwfbe_enabled && (rdp.ci_count <= rdp.copy_ci_index) && (!SwapOK || settings.swapmode == 2))
+        OpenTextureBuffer(cur_fb);
+      rdp.skip_drawing = FALSE;
+      break;
+    default:
+      rdp.skip_drawing = FALSE;
+    }
+
+    if ((rdp.ci_count > 0) && (prev_fb.status >= ci_aux)) //for Pokemon Stadium
+    {
+      if (!fb_hwfbe_enabled && prev_fb.format == 0)
+        CopyFrameBuffer ();
+      else if ((settings.hacks&hack_Knockout) && prev_fb.width < 100)
+        CopyFrameBuffer (GR_BUFFER_TEXTUREBUFFER_EXT);
+    }
+    if (!fb_hwfbe_enabled && cur_fb.status == ci_copy)
+    {
+      if (!rdp.motionblur && (rdp.num_of_ci > rdp.ci_count+1) && (next_fb.status != ci_aux))
+      {
+        RestoreScale();
+      }
+    }
+    if (!fb_hwfbe_enabled && cur_fb.status == ci_aux)
+    {
+      if (cur_fb.format == 0)
+      {
+        if ((settings.hacks&hack_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;
+          wxUint16 *ptr_dst = new wxUint16[width*height];
+          wxUint16 *ptr_src = (wxUint16*)(gfx.RDRAM+cur_fb.addr);
+          wxUint16 c;
+
+          for (int y=0; y<height; y++)
+          {
+            for (int x=0; x<width; x++)
+            {
+              c = ((ptr_src[(x + y * width)^1]) >> 1) | 0x8000;
+              ptr_dst[x + y * width] = c;
+            }
+          }
+          grLfbWriteRegion(GR_BUFFER_BACKBUFFER,
+            (wxUint32)rdp.offset_x,
+            (wxUint32)rdp.offset_y,
+            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))
+    {
+      int 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)
+      {
+        LRDP("return to original scale\n");
+        rdp.scale_x = rdp.scale_x_bak;
+        rdp.scale_y = rdp.scale_y_bak;
+        if (fb_hwfbe_enabled && !rdp.read_whole_frame)
+          CloseTextureBuffer();
+      }
+      if (fb_hwfbe_enabled && !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 (fb_emulation_enabled)
+    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;
+  }
+  wxUint32 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 (showdeb) printf("setcolorimage - %08x, width: %d,  height: %d, format: %d, size: %d\n", rdp.cmd1, rdp.ci_width, rdp.ci_height, format, rdp.ci_size);
+//if (showdeb) printf("cimg: %08x, ocimg: %08x, SwapOK: %d\n", rdp.cimg, rdp.ocimg, SwapOK);
+
+  if (format != 0) //can't draw into non RGBA buffer
+  {
+    if (!rdp.cur_image)
+    {
+      if (fb_hwfbe_enabled && rdp.ci_width <= 64)
+        OpenTextureBuffer(rdp.frame_buffers[rdp.ci_count - 1]);
+      else if (format > 2)
+        rdp.skip_drawing = TRUE;
+      return;
+    }
+  }
+  else
+  {
+    if (!fb_emulation_enabled)
+      rdp.skip_drawing = FALSE;
+  }
+
+  CI_SET = TRUE;
+  if (settings.swapmode > 0)
+  {
+    if (rdp.zimg == rdp.cimg)
+      rdp.updatescreen = 1;
+
+    int 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 (fb_emulation_enabled)
+        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 (fb_hwfbe_enabled)
+      {
+        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]);
+        }
+      }
+    }
+  }
+//ticks = ticksGetTicks() - ticks;
+//if (showdeb) printf("time = %u\n", ticks);
+}
+
+static void rsp_reserved0()
+{
+  if (settings.ucode == ucode_DiddyKong)
+  {
+    ucode5_texshiftaddr = segoffset(rdp.cmd1);
+    ucode5_texshiftcount = 0;
+    FRDP("uc5_texshift. addr: %08lx\n", ucode5_texshiftaddr);
+  }
+  else
+  {
+    RDP_E("reserved0 - IGNORED\n");
+    LRDP("reserved0 - IGNORED\n");
+  }
+}
+
+static void rsp_reserved1()
+{
+  LRDP("reserved1 - ignored\n");
+}
+
+static void rsp_reserved2()
+{
+  LRDP("reserved2\n");
+}
+
+static void rsp_reserved3()
+{
+  LRDP("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);
+
+  rdp.update |= UPDATE_COMBINE | UPDATE_ALPHA_COMPARE;
+}
+
+/******************************************************************
+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 = wxUint8, 2 = wxUint16, 4 = wxUint32
+output:   none
+*******************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EXPORT void CALL FBRead(wxUint32 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;
+  wxUint32 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))
+    {
+      wxUint32 cimg = rdp.cimg;
+      rdp.cimg = rdp.maincimg[1].addr;
+      if (fb_emulation_enabled)
+      {
+        rdp.ci_width = rdp.maincimg[1].width;
+        rdp.ci_count = 0;
+        wxUint32 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
+/******************************************************************
+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, wxUint32 size)
+{
+  LOG ("FBWList ()\n");
+  FRDP("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 = wxUint8, 2 = wxUint16, 4 = wxUint32
+output:   none
+*******************************************************************/
+EXPORT void CALL FBWrite(wxUint32 addr, wxUint32 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;
+  wxUint32 a = segoffset(addr);
+  FRDP("FBWrite. addr: %08lx\n", a);
+  if (a < rdp.cimg || a > rdp.ci_end)
+    return;
+  cpu_fb_write = TRUE;
+  wxUint32 shift_l = (a-rdp.cimg) >> 1;
+  wxUint32 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
+typedef struct
+{
+  wxUint32 addr;
+  wxUint32 size;
+  wxUint32 width;
+  wxUint32 height;
+} FrameBufferInfo;
+#endif
+EXPORT void CALL FBGetFrameBufferInfo(void *p)
+{
+  VLOG ("FBGetFrameBufferInfo ()\n");
+  FrameBufferInfo * pinfo = (FrameBufferInfo *)p;
+  memset(pinfo,0,sizeof(FrameBufferInfo)*6);
+  if (!(settings.frame_buffer&fb_get_info))
+    return;
+  LRDP("FBGetFrameBufferInfo ()\n");
+  //*
+  if (fb_emulation_enabled)
+  {
+    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 ()
+{
+  LRDP("DetectFrameBufferUsage\n");
+
+  wxUint32 dlist_start = *(wxUint32*)(gfx.DMEM+0xFF0);
+  wxUint32 a;
+
+  int tidal = FALSE;
+  if ((settings.hacks&hack_PMario) && (rdp.copy_ci_index || rdp.frame_buffers[rdp.copy_ci_index].status == ci_copy_self))
+    tidal = TRUE;
+  wxUint32 ci = rdp.cimg, zi = rdp.zimg;
+  wxUint32 ci_height = rdp.frame_buffers[(rdp.ci_count > 0)?rdp.ci_count-1:0].height;
+  rdp.main_ci = rdp.main_ci_end = rdp.main_ci_bg = rdp.ci_count = 0;
+  rdp.main_ci_index = rdp.copy_ci_index = rdp.copy_zi_index = 0;
+  rdp.zimg_end = 0;
+  rdp.tmpzimg = 0;
+  rdp.motionblur = FALSE;
+  rdp.main_ci_last_tex_addr = 0;
+  int 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 = ((wxUint32*)gfx.RDRAM)[a>>2];   // \ Current command, 64 bit
+    rdp.cmd1 = ((wxUint32*)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 (wxPtrToUInt(reinterpret_cast<void*>(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;
+
+        LRDP("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;
+  }
+
+  int 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;
+  }
+
+  LRDP("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 (!fb_hwfbe_enabled || !rdp.copy_ci_index)
+      rdp.motionblur = TRUE;
+  }
+  if (rdp.motionblur || fb_hwfbe_enabled || (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 (fb_hwfbe_enabled)
+    {
+      if (rdp.read_previous_ci && !previous_ci_was_read && (settings.swapmode != 2) && (settings.ucode != ucode_PerfectDark))
+      {
+        int ind = (rdp.ci_count > 0)?rdp.ci_count-1:0;
+        wxUint32 height = rdp.frame_buffers[ind].height;
+        rdp.frame_buffers[ind].height = ci_height;
+        CopyFrameBuffer();
+        rdp.frame_buffers[ind].height = height;
+      }
+      if (rdp.swap_ci_index < 0)
+      {
+        rdp.texbufs[0].clear_allowed = rdp.texbufs[1].clear_allowed = TRUE;
+        OpenTextureBuffer(rdp.frame_buffers[rdp.main_ci_index]);
+      }
+    }
+    else
+    {
+      if (rdp.motionblur)
+      {
+        if (settings.frame_buffer&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;
+          wxUint32 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 (fb_hwfbe_enabled)
+  {
+    for (i = 0; i < voodoo.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)
+    {
+      //LRDP("Tidal wave!\n");
+      rdp.copy_ci_index = rdp.main_ci_index;
+    }
+  }
+  rdp.ci_count = 0;
+  if (settings.hacks&hack_Banjo2)
+    rdp.cur_tex_buf = 0;
+  rdp.maincimg[0] = rdp.frame_buffers[rdp.main_ci_index];
+  //    rdp.scale_x = rdp.scale_x_bak;
+  //    rdp.scale_y = rdp.scale_y_bak;
+  LRDP("DetectFrameBufferUsage End\n");
+}
+
+/*******************************************
+ *          ProcessRDPList                 *
+ *******************************************
+ *    based on sources of ziggy's z64      *
+ *******************************************/
+
+static wxUint32 rdp_cmd_ptr = 0;
+static wxUint32 rdp_cmd_cur = 0;
+static wxUint32 rdp_cmd_data[0x1000];
+
+void lle_triangle(wxUint32 w1, wxUint32 w2, int shade, int texture, int zbuffer,
+                  wxUint32 * rdp_cmd)
+{
+  rdp.cur_tile = (w1 >> 16) & 0x7;
+  int j;
+  int xleft, xright, xleft_inc, xright_inc;
+  int r, g, b, a, z, s, t, w;
+  int drdx = 0, dgdx = 0, dbdx = 0, dadx = 0, dzdx = 0, dsdx = 0, dtdx = 0, dwdx = 0;
+  int drde = 0, dgde = 0, dbde = 0, dade = 0, dzde = 0, dsde = 0, dtde = 0, dwde = 0;
+  int flip = (w1 & 0x800000) ? 1 : 0;
+
+  wxInt32 yl, ym, yh;
+  wxInt32 xl, xm, xh;
+  wxInt32 dxldy, dxhdy, dxmdy;
+  wxUint32 w3, w4, w5, w6, w7, w8;
+
+  wxUint32 * shade_base = rdp_cmd + 8;
+  wxUint32 * texture_base = rdp_cmd + 8;
+  wxUint32 * zbuffer_base = rdp_cmd + 8;
+
+  if (shade)
+  {
+    texture_base += 16;
+    zbuffer_base += 16;
+  }
+  if (texture)
+  {
+    zbuffer_base += 16;
+  }
+
+  w3 = rdp_cmd[2];
+  w4 = rdp_cmd[3];
+  w5 = rdp_cmd[4];
+  w6 = rdp_cmd[5];
+  w7 = rdp_cmd[6];
+  w8 = rdp_cmd[7];
+
+  yl = (w1 & 0x3fff);
+  ym = ((w2 >> 16) & 0x3fff);
+  yh = ((w2 >>  0) & 0x3fff);
+  xl = (wxInt32)(w3);
+  xh = (wxInt32)(w5);
+  xm = (wxInt32)(w7);
+  dxldy = (wxInt32)(w4);
+  dxhdy = (wxInt32)(w6);
+  dxmdy = (wxInt32)(w8);
+
+  if (yl & (0x800<<2)) yl |= 0xfffff000<<2;
+  if (ym & (0x800<<2)) ym |= 0xfffff000<<2;
+  if (yh & (0x800<<2)) yh |= 0xfffff000<<2;
+
+  yh &= ~3;
+
+  r = 0xff; g = 0xff; b = 0xff; a = 0xff; z = 0xffff0000; s = 0;  t = 0;  w = 0x30000;
+
+  if (shade)
+  {
+    r    = (shade_base[0] & 0xffff0000) | ((shade_base[+4 ] >> 16) & 0x0000ffff);
+    g    = ((shade_base[0 ] << 16) & 0xffff0000) | (shade_base[4 ] & 0x0000ffff);
+    b    = (shade_base[1 ] & 0xffff0000) | ((shade_base[5 ] >> 16) & 0x0000ffff);
+    a    = ((shade_base[1 ] << 16) & 0xffff0000) | (shade_base[5 ] & 0x0000ffff);
+    drdx = (shade_base[2 ] & 0xffff0000) | ((shade_base[6 ] >> 16) & 0x0000ffff);
+    dgdx = ((shade_base[2 ] << 16) & 0xffff0000) | (shade_base[6 ] & 0x0000ffff);
+    dbdx = (shade_base[3 ] & 0xffff0000) | ((shade_base[7 ] >> 16) & 0x0000ffff);
+    dadx = ((shade_base[3 ] << 16) & 0xffff0000) | (shade_base[7 ] & 0x0000ffff);
+    drde = (shade_base[8 ] & 0xffff0000) | ((shade_base[12] >> 16) & 0x0000ffff);
+    dgde = ((shade_base[8 ] << 16) & 0xffff0000) | (shade_base[12] & 0x0000ffff);
+    dbde = (shade_base[9 ] & 0xffff0000) | ((shade_base[13] >> 16) & 0x0000ffff);
+    dade = ((shade_base[9 ] << 16) & 0xffff0000) | (shade_base[13] & 0x0000ffff);
+  }
+  if (texture)
+  {
+    s    = (texture_base[0 ] & 0xffff0000) | ((texture_base[4 ] >> 16) & 0x0000ffff);
+    t    = ((texture_base[0 ] << 16) & 0xffff0000)      | (texture_base[4 ] & 0x0000ffff);
+    w    = (texture_base[1 ] & 0xffff0000) | ((texture_base[5 ] >> 16) & 0x0000ffff);
+    //    w = abs(w);
+    dsdx = (texture_base[2 ] & 0xffff0000) | ((texture_base[6 ] >> 16) & 0x0000ffff);
+    dtdx = ((texture_base[2 ] << 16) & 0xffff0000)      | (texture_base[6 ] & 0x0000ffff);
+    dwdx = (texture_base[3 ] & 0xffff0000) | ((texture_base[7 ] >> 16) & 0x0000ffff);
+    dsde = (texture_base[8 ] & 0xffff0000) | ((texture_base[12] >> 16) & 0x0000ffff);
+    dtde = ((texture_base[8 ] << 16) & 0xffff0000)      | (texture_base[12] & 0x0000ffff);
+    dwde = (texture_base[9 ] & 0xffff0000) | ((texture_base[13] >> 16) & 0x0000ffff);
+  }
+  if (zbuffer)
+  {
+    z    = zbuffer_base[0];
+    dzdx = zbuffer_base[1];
+    dzde = zbuffer_base[2];
+  }
+
+  xh <<= 2;  xm <<= 2;  xl <<= 2;
+  r <<= 2;  g <<= 2;  b <<= 2;  a <<= 2;
+  dsde >>= 2;  dtde >>= 2;  dsdx >>= 2;  dtdx >>= 2;
+  dzdx >>= 2;  dzde >>= 2;
+  dwdx >>= 2;  dwde >>= 2;
+
+#define XSCALE(x) (float(x)/(1<<18))
+#define YSCALE(y) (float(y)/(1<<2))
+#define ZSCALE(z) ((rdp.zsrc == 1)? float(rdp.prim_depth) : float(wxUint32(z))/0xffff0000)
+  //#define WSCALE(w) (rdp.Persp_en? (float(wxUint32(w) + 0x10000)/0xffff0000) : 1.0f)
+  //#define WSCALE(w) (rdp.Persp_en? 4294901760.0/(w + 65536) : 1.0f)
+#define WSCALE(w) (rdp.Persp_en? 65536.0f/float((w+ 0xffff)>>16) : 1.0f)
+#define CSCALE(c) (((c)>0x3ff0000? 0x3ff0000:((c)<0? 0 : (c)))>>18)
+#define _PERSP(w) ( w )
+#define PERSP(s, w) ( ((int64_t)(s) << 20) / (_PERSP(w)? _PERSP(w):1) )
+#define SSCALE(s, _w) (rdp.Persp_en? float(PERSP(s, _w))/(1 << 10) : float(s)/(1<<21))
+#define TSCALE(s, w) (rdp.Persp_en? float(PERSP(s, w))/(1 << 10) : float(s)/(1<<21))
+
+  int nbVtxs = 0;
+  VERTEX vtxbuf[12];
+  VERTEX * vtx = &vtxbuf[nbVtxs++];
+
+  xleft = xm;
+  xright = xh;
+  xleft_inc = dxmdy;
+  xright_inc = dxhdy;
+
+  while (yh<ym &&
+    !((!flip && xleft < xright+0x10000) ||
+    (flip && xleft > xright-0x10000))) {
+      xleft += xleft_inc;
+      xright += xright_inc;
+      s += dsde;    t += dtde;    w += dwde;
+      r += drde;    g += dgde;    b += dbde;    a += dade;
+      z += dzde;
+      yh++;
+  }
+
+  j = ym-yh;
+  if (j > 0)
+  {
+    int dx = (xleft-xright)>>16;
+    if ((!flip && xleft < xright) ||
+      (flip/* && xleft > xright*/))
+    {
+      if (shade) {
+        vtx->r = CSCALE(r+drdx*dx);
+        vtx->g = CSCALE(g+dgdx*dx);
+        vtx->b = CSCALE(b+dbdx*dx);
+        vtx->a = CSCALE(a+dadx*dx);
+      }
+      if (texture) {
+        vtx->ou = SSCALE(s+dsdx*dx, w+dwdx*dx);
+        vtx->ov = TSCALE(t+dtdx*dx, w+dwdx*dx);
+      }
+      vtx->x = XSCALE(xleft);
+      vtx->y = YSCALE(yh);
+      vtx->z = ZSCALE(z+dzdx*dx);
+      vtx->w = WSCALE(w+dwdx*dx);
+      vtx = &vtxbuf[nbVtxs++];
+    }
+    if ((!flip/* && xleft < xright*/) ||
+      (flip && xleft > xright))
+    {
+      if (shade) {
+        vtx->r = CSCALE(r);
+        vtx->g = CSCALE(g);
+        vtx->b = CSCALE(b);
+        vtx->a = CSCALE(a);
+      }
+      if (texture) {
+        vtx->ou = SSCALE(s, w);
+        vtx->ov = TSCALE(t, w);
+      }
+      vtx->x = XSCALE(xright);
+      vtx->y = YSCALE(yh);
+      vtx->z = ZSCALE(z);
+      vtx->w = WSCALE(w);
+      vtx = &vtxbuf[nbVtxs++];
+    }
+    xleft += xleft_inc*j;  xright += xright_inc*j;
+    s += dsde*j;  t += dtde*j;
+    if (w + dwde*j) w += dwde*j;
+    else w += dwde*(j-1);
+    r += drde*j;  g += dgde*j;  b += dbde*j;  a += dade*j;
+    z += dzde*j;
+    // render ...
+  }
+
+  if (xl != xh)
+    xleft = xl;
+
+  //if (yl-ym > 0)
+  {
+    int dx = (xleft-xright)>>16;
+    if ((!flip && xleft <= xright) ||
+      (flip/* && xleft >= xright*/))
+    {
+      if (shade) {
+        vtx->r = CSCALE(r+drdx*dx);
+        vtx->g = CSCALE(g+dgdx*dx);
+        vtx->b = CSCALE(b+dbdx*dx);
+        vtx->a = CSCALE(a+dadx*dx);
+      }
+      if (texture) {
+        vtx->ou = SSCALE(s+dsdx*dx, w+dwdx*dx);
+        vtx->ov = TSCALE(t+dtdx*dx, w+dwdx*dx);
+      }
+      vtx->x = XSCALE(xleft);
+      vtx->y = YSCALE(ym);
+      vtx->z = ZSCALE(z+dzdx*dx);
+      vtx->w = WSCALE(w+dwdx*dx);
+      vtx = &vtxbuf[nbVtxs++];
+    }
+    if ((!flip/* && xleft <= xright*/) ||
+      (flip && xleft >= xright))
+    {
+      if (shade) {
+        vtx->r = CSCALE(r);
+        vtx->g = CSCALE(g);
+        vtx->b = CSCALE(b);
+        vtx->a = CSCALE(a);
+      }
+      if (texture) {
+        vtx->ou = SSCALE(s, w);
+        vtx->ov = TSCALE(t, w);
+      }
+      vtx->x = XSCALE(xright);
+      vtx->y = YSCALE(ym);
+      vtx->z = ZSCALE(z);
+      vtx->w = WSCALE(w);
+      vtx = &vtxbuf[nbVtxs++];
+    }
+  }
+  xleft_inc = dxldy;
+  xright_inc = dxhdy;
+
+  j = yl-ym;
+  //j--; // ?
+  xleft += xleft_inc*j;  xright += xright_inc*j;
+  s += dsde*j;  t += dtde*j;  w += dwde*j;
+  r += drde*j;  g += dgde*j;  b += dbde*j;  a += dade*j;
+  z += dzde*j;
+
+  while (yl>ym &&
+    !((!flip && xleft < xright+0x10000) ||
+    (flip && xleft > xright-0x10000))) {
+      xleft -= xleft_inc;    xright -= xright_inc;
+      s -= dsde;    t -= dtde;    w -= dwde;
+      r -= drde;    g -= dgde;    b -= dbde;    a -= dade;
+      z -= dzde;
+      j--;
+      yl--;
+  }
+
+  // render ...
+  if (j >= 0) {
+    int dx = (xleft-xright)>>16;
+    if ((!flip && xleft <= xright) ||
+      (flip/* && xleft >= xright*/))
+    {
+      if (shade) {
+        vtx->r = CSCALE(r+drdx*dx);
+        vtx->g = CSCALE(g+dgdx*dx);
+        vtx->b = CSCALE(b+dbdx*dx);
+        vtx->a = CSCALE(a+dadx*dx);
+      }
+      if (texture) {
+        vtx->ou = SSCALE(s+dsdx*dx, w+dwdx*dx);
+        vtx->ov = TSCALE(t+dtdx*dx, w+dwdx*dx);
+      }
+      vtx->x = XSCALE(xleft);
+      vtx->y = YSCALE(yl);
+      vtx->z = ZSCALE(z+dzdx*dx);
+      vtx->w = WSCALE(w+dwdx*dx);
+      vtx = &vtxbuf[nbVtxs++];
+    }
+    if ((!flip/* && xleft <= xright*/) ||
+      (flip && xleft >= xright))
+    {
+      if (shade) {
+        vtx->r = CSCALE(r);
+        vtx->g = CSCALE(g);
+        vtx->b = CSCALE(b);
+        vtx->a = CSCALE(a);
+      }
+      if (texture) {
+        vtx->ou = SSCALE(s, w);
+        vtx->ov = TSCALE(t, w);
+      }
+      vtx->x = XSCALE(xright);
+      vtx->y = YSCALE(yl);
+      vtx->z = ZSCALE(z);
+      vtx->w = WSCALE(w);
+      vtx = &vtxbuf[nbVtxs++];
+    }
+  }
+
+  if (fullscreen)
+  {
+    update ();
+    for (int k = 0; k < nbVtxs-1; k++)
+    {
+      VERTEX * v = &vtxbuf[k];
+      v->x = v->x * rdp.scale_x + rdp.offset_x;
+      v->y = v->y * rdp.scale_y + rdp.offset_y;
+      //    v->z = 1.0f;///v->w;
+      v->q = 1.0f/v->w;
+      v->u1 = v->u0 = v->ou;
+      v->v1 = v->v0 = v->ov;
+      if (rdp.tex >= 1 && rdp.cur_cache[0])
+      {
+        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);
+        }
+
+        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 /= v->w;
+        v->v0 /= v->w;
+      }
+
+      if (rdp.tex >= 2 && rdp.cur_cache[1])
+      {
+        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);
+        }
+
+        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 /= v->w;
+        v->v1 /= v->w;
+      }
+      apply_shade_mods (v);
+    }
+    ConvertCoordsConvert (vtxbuf, nbVtxs);
+    grCullMode (GR_CULL_DISABLE);
+    grDrawVertexArrayContiguous (GR_TRIANGLE_STRIP, nbVtxs-1, vtxbuf, sizeof(VERTEX));
+    if (_debugger.capture)
+    {
+      VERTEX vl[3];
+      vl[0] = vtxbuf[0];
+      vl[1] = vtxbuf[2];
+      vl[2] = vtxbuf[1];
+      add_tri (vl, 3, TRI_TRIANGLE);
+      rdp.tri_n++;
+      if (nbVtxs > 4)
+      {
+        vl[0] = vtxbuf[2];
+        vl[1] = vtxbuf[3];
+        vl[2] = vtxbuf[1];
+        add_tri (vl, 3, TRI_TRIANGLE);
+        rdp.tri_n++;
+      }
+    }
+  }
+}
+
+static void rdp_triangle(int shade, int texture, int zbuffer)
+{
+  lle_triangle(rdp.cmd0, rdp.cmd1, shade, texture, zbuffer, rdp_cmd_data + rdp_cmd_cur);
+}
+
+static void rdp_trifill()
+{
+  rdp_triangle(0, 0, 0);
+  LRDP("trifill\n");
+}
+
+static void rdp_trishade()
+{
+  rdp_triangle(1, 0, 0);
+  LRDP("trishade\n");
+}
+
+static void rdp_tritxtr()
+{
+  rdp_triangle(0, 1, 0);
+  LRDP("tritxtr\n");
+}
+
+static void rdp_trishadetxtr()
+{
+  rdp_triangle(1, 1, 0);
+  LRDP("trishadetxtr\n");
+}
+
+static void rdp_trifillz()
+{
+  rdp_triangle(0, 0, 1);
+  LRDP("trifillz\n");
+}
+
+static void rdp_trishadez()
+{
+  rdp_triangle(1, 0, 1);
+  LRDP("trishadez\n");
+}
+
+static void rdp_tritxtrz()
+{
+  rdp_triangle(0, 1, 1);
+  LRDP("tritxtrz\n");
+}
+
+static void rdp_trishadetxtrz()
+{
+  rdp_triangle(1, 1, 1);
+  LRDP("trishadetxtrz\n");
+}
+
+
+static rdp_instr rdp_command_table[64] =
+{
+  /* 0x00 */
+  spnoop,             undef,                  undef,                  undef,
+  undef,              undef,                  undef,                  undef,
+  rdp_trifill,        rdp_trifillz,           rdp_tritxtr,            rdp_tritxtrz,
+  rdp_trishade,       rdp_trishadez,          rdp_trishadetxtr,       rdp_trishadetxtrz,
+  /* 0x10 */
+  undef,              undef,                  undef,                  undef,
+  undef,              undef,                  undef,                  undef,
+  undef,              undef,                  undef,                  undef,
+  undef,              undef,                  undef,                  undef,
+  /* 0x20 */
+  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,
+  /* 0x30 */
+  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
+};
+
+static const wxUint32 rdp_command_length[64] =
+{
+  8,                      // 0x00, No Op
+  8,                      // 0x01, ???
+  8,                      // 0x02, ???
+  8,                      // 0x03, ???
+  8,                      // 0x04, ???
+  8,                      // 0x05, ???
+  8,                      // 0x06, ???
+  8,                      // 0x07, ???
+  32,                     // 0x08, Non-Shaded Triangle
+  32+16,          // 0x09, Non-Shaded, Z-Buffered Triangle
+  32+64,          // 0x0a, Textured Triangle
+  32+64+16,       // 0x0b, Textured, Z-Buffered Triangle
+  32+64,          // 0x0c, Shaded Triangle
+  32+64+16,       // 0x0d, Shaded, Z-Buffered Triangle
+  32+64+64,       // 0x0e, Shaded+Textured Triangle
+  32+64+64+16,// 0x0f, Shaded+Textured, Z-Buffered Triangle
+  8,                      // 0x10, ???
+  8,                      // 0x11, ???
+  8,                      // 0x12, ???
+  8,                      // 0x13, ???
+  8,                      // 0x14, ???
+  8,                      // 0x15, ???
+  8,                      // 0x16, ???
+  8,                      // 0x17, ???
+  8,                      // 0x18, ???
+  8,                      // 0x19, ???
+  8,                      // 0x1a, ???
+  8,                      // 0x1b, ???
+  8,                      // 0x1c, ???
+  8,                      // 0x1d, ???
+  8,                      // 0x1e, ???
+  8,                      // 0x1f, ???
+  8,                      // 0x20, ???
+  8,                      // 0x21, ???
+  8,                      // 0x22, ???
+  8,                      // 0x23, ???
+  16,                     // 0x24, Texture_Rectangle
+  16,                     // 0x25, Texture_Rectangle_Flip
+  8,                      // 0x26, Sync_Load
+  8,                      // 0x27, Sync_Pipe
+  8,                      // 0x28, Sync_Tile
+  8,                      // 0x29, Sync_Full
+  8,                      // 0x2a, Set_Key_GB
+  8,                      // 0x2b, Set_Key_R
+  8,                      // 0x2c, Set_Convert
+  8,                      // 0x2d, Set_Scissor
+  8,                      // 0x2e, Set_Prim_Depth
+  8,                      // 0x2f, Set_Other_Modes
+  8,                      // 0x30, Load_TLUT
+  8,                      // 0x31, ???
+  8,                      // 0x32, Set_Tile_Size
+  8,                      // 0x33, Load_Block
+  8,                      // 0x34, Load_Tile
+  8,                      // 0x35, Set_Tile
+  8,                      // 0x36, Fill_Rectangle
+  8,                      // 0x37, Set_Fill_Color
+  8,                      // 0x38, Set_Fog_Color
+  8,                      // 0x39, Set_Blend_Color
+  8,                      // 0x3a, Set_Prim_Color
+  8,                      // 0x3b, Set_Env_Color
+  8,                      // 0x3c, Set_Combine
+  8,                      // 0x3d, Set_Texture_Image
+  8,                      // 0x3e, Set_Mask_Image
+  8                       // 0x3f, Set_Color_Image
+};
+
+#define rdram ((wxUint32*)gfx.RDRAM)
+#define rsp_dmem ((wxUint32*)gfx.DMEM)
+
+#define dp_start (*(wxUint32*)gfx.DPC_START_REG)
+#define dp_end (*(wxUint32*)gfx.DPC_END_REG)
+#define dp_current (*(wxUint32*)gfx.DPC_CURRENT_REG)
+#define dp_status (*(wxUint32*)gfx.DPC_STATUS_REG)
+
+inline wxUint32 READ_RDP_DATA(wxUint32 address)
+{
+  if (dp_status & 0x1)          // XBUS_DMEM_DMA enabled
+    return rsp_dmem[(address & 0xfff)>>2];
+  else
+    return rdram[address>>2];
+}
+
+static void rdphalf_1()
+{
+  wxUint32 cmd = rdp.cmd1 >> 24;
+  if (cmd >= 0xc8 && cmd <=0xcf) //triangle command
+  {
+    LRDP("rdphalf_1 - lle triangle\n");
+    rdp_cmd_ptr = 0;
+    rdp_cmd_cur = 0;
+    wxUint32 a;
+
+    do
+    {
+      rdp_cmd_data[rdp_cmd_ptr++] = rdp.cmd1;
+      // check DL counter
+      if (rdp.dl_count != -1)
+      {
+        rdp.dl_count --;
+        if (rdp.dl_count == 0)
+        {
+          rdp.dl_count = -1;
+
+          LRDP("End of DL\n");
+          rdp.pc_i --;
+        }
+      }
+
+      // Get the address of the next command
+      a = rdp.pc[rdp.pc_i] & BMASK;
+
+      // Load the next command and its input
+      rdp.cmd0 = ((wxUint32*)gfx.RDRAM)[a>>2];   // \ Current command, 64 bit
+      rdp.cmd1 = ((wxUint32*)gfx.RDRAM)[(a>>2)+1]; // /
+
+      // Go to the next instruction
+      rdp.pc[rdp.pc_i] = (a+8) & BMASK;
+
+    }while ((rdp.cmd0 >> 24) != 0xb3);
+    rdp_cmd_data[rdp_cmd_ptr++] = rdp.cmd1;
+    cmd = (rdp_cmd_data[rdp_cmd_cur] >> 24) & 0x3f;
+    rdp.cmd0 = rdp_cmd_data[rdp_cmd_cur+0];
+    rdp.cmd1 = rdp_cmd_data[rdp_cmd_cur+1];
+    /*
+    wxUint32 cmd3 = ((wxUint32*)gfx.RDRAM)[(a>>2)+2];
+    if ((cmd3>>24) == 0xb4)
+    rglSingleTriangle = TRUE;
+    else
+    rglSingleTriangle = FALSE;
+    */
+    rdp_command_table[cmd]();
+  }
+  else
+  {
+    LRDP("rdphalf_1 - IGNORED\n");
+  }
+}
+
+static void rdphalf_2()
+{
+  RDP_E("rdphalf_2 - IGNORED\n");
+  LRDP("rdphalf_2 - IGNORED\n");
+}
+
+static void rdphalf_cont()
+{
+  RDP_E("rdphalf_cont - IGNORED\n");
+  LRDP("rdphalf_cont - IGNORED\n");
+}
+
+/******************************************************************
+Function: ProcessRDPList
+Purpose:  This function is called when there is a Dlist to be
+processed. (Low level GFX list)
+input:    none
+output:   none
+*******************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+EXPORT void CALL ProcessRDPList(void)
+{
+  LOG ("ProcessRDPList ()\n");
+  LRDP("ProcessRDPList ()\n");
+
+ // SoftLocker lock(mutexProcessDList);
+  if (/*!lock.IsOk()*/0) //mutex is busy
+  {
+    if (!fullscreen)
+      drawNoFullscreenMessage();
+    // Set an interrupt to allow the game to continue
+    *gfx.MI_INTR_REG |= 0x20;
+    gfx.CheckInterrupts();
+    return;
+  }
+
+  wxUint32 i;
+  wxUint32 cmd, length, cmd_length;
+  rdp_cmd_ptr = 0;
+  rdp_cmd_cur = 0;
+
+  if (dp_end <= dp_current) return;
+  length = dp_end - dp_current;
+
+  // load command data
+  for (i=0; i < length; i += 4)
+  {
+    rdp_cmd_data[rdp_cmd_ptr++] = READ_RDP_DATA(dp_current + i);
+    if (rdp_cmd_ptr >= 0x1000)
+    {
+      FRDP("rdp_process_list: rdp_cmd_ptr overflow %x %x --> %x\n", length, dp_current, dp_end);
+    }
+  }
+
+  dp_current = dp_end;
+
+  cmd = (rdp_cmd_data[0] >> 24) & 0x3f;
+  cmd_length = (rdp_cmd_ptr + 1) * 4;
+
+  // check if more data is needed
+  if (cmd_length < rdp_command_length[cmd])
+    return;
+  rdp.LLE = TRUE;
+  while (rdp_cmd_cur < rdp_cmd_ptr)
+  {
+    cmd = (rdp_cmd_data[rdp_cmd_cur] >> 24) & 0x3f;
+
+    if (((rdp_cmd_ptr-rdp_cmd_cur) * 4) < rdp_command_length[cmd])
+      return;
+
+    // execute the command
+    rdp.cmd0 = rdp_cmd_data[rdp_cmd_cur+0];
+    rdp.cmd1 = rdp_cmd_data[rdp_cmd_cur+1];
+    rdp.cmd2 = rdp_cmd_data[rdp_cmd_cur+2];
+    rdp.cmd3 = rdp_cmd_data[rdp_cmd_cur+3];
+    rdp_command_table[cmd]();
+
+    rdp_cmd_cur += rdp_command_length[cmd] / 4;
+  };
+  rdp.LLE = FALSE;
+
+  dp_start = dp_end;
+
+  dp_status &= ~0x0002;
+
+  //}
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/source/gles2glide64/src/Glide64/rdp.h b/source/gles2glide64/src/Glide64/rdp.h
new file mode 100755 (executable)
index 0000000..721ba62
--- /dev/null
@@ -0,0 +1,922 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+#ifndef RDP_H
+#define RDP_H
+
+extern char out_buf[2048];
+
+extern wxUint32 frame_count; // frame counter
+
+//GlideHQ support
+#ifdef TEXTURE_FILTER
+#include "../GlideHQ/Ext_TxFilter.h"
+#endif
+
+#define MAX_CACHE   1024*4
+#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_WMIN 0x00000010
+#define CLIP_ZMAX 0x00000020
+#define CLIP_ZMIN 0x00000040
+
+// 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]
+
+#if defined(_MSC_VER)
+#define DECLAREALIGN16VAR(var) __declspec(align(16)) float var
+#elif defined(__GNUG__)
+#define DECLAREALIGN16VAR(var) float (var) __attribute__ ((aligned(16)))
+#endif
+
+#ifdef __ARM_NEON__
+#include "arm_neon.h"
+#endif
+
+// Vertex structure
+typedef struct
+{
+  float x, y, z, q;
+  float u0, v0, u1, v1;
+  float coord[4];
+  float w;
+  wxUint16  flags;
+
+  wxUint8  b;  // These values are arranged like this so that *(wxUint32*)(VERTEX+?) is
+  wxUint8  g;  // ARGB format that glide can use.
+  wxUint8  r;
+  wxUint8  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;
+  wxUint8  not_zclipped;
+  wxUint8  screen_translated;
+  wxUint8  uv_scaled;
+  wxUint32 uv_calculated;  // like crc
+  wxUint32 shade_mod;
+  wxUint32 color_backup;
+
+  float ou, ov;
+
+  int   number;   // way to identify it
+  int   scr_off, z_off; // off the screen?
+} VERTEX;
+
+// Clipping (scissors)
+typedef struct {
+  wxUint32 ul_x;
+  wxUint32 ul_y;
+  wxUint32 lr_x;
+  wxUint32 lr_y;
+} SCISSOR;
+
+#ifdef TEXTURE_FILTER
+extern wxUint32 texfltr[];
+extern wxUint32 texenht[];
+extern wxUint32 texcmpr[];
+extern wxUint32 texhirs[];
+
+typedef struct {
+  wxUint16 tile_ul_s;
+  wxUint16 tile_ul_t;
+  wxUint16 tile_width;
+  wxUint16 tile_height;
+  wxUint16 tex_width;
+  wxUint16 tex_size;
+  wxUint32 dxt;
+} LOAD_TILE_INFO;
+#endif
+
+// #warning no screenshot support
+/*
+typedef struct {
+  const wxChar * format;
+  const wxChar * extension;
+  wxBitmapType type;
+} SCREEN_SHOT_FORMAT;
+
+extern const int NumOfFormats;
+extern SCREEN_SHOT_FORMAT ScreenShotFormats[];
+*/
+typedef struct {
+  int card_id;
+  int lang_id;
+
+  wxUint32 res_x, scr_res_x;
+  wxUint32 res_y, scr_res_y;
+  wxUint32 res_data, res_data_org;
+
+  int advanced_options;
+  int texenh_options;
+  int ssformat;
+  int vsync;
+
+  int show_fps;
+  int clock;
+  int clock_24_hr;
+
+  int filtering;
+  int fog;
+  int buff_clear;
+  int swapmode;
+  int lodmode;
+#ifdef PAULSCODE
+  int autoframeskip;
+  int maxframeskip;
+#endif
+  int aspectmode;
+  int use_hotkeys;
+
+  //Frame buffer emulation options
+  #define  fb_emulation            (1<<0)   //frame buffer emulation
+  #define  fb_hwfbe                (1<<1)   //hardware frame buffer emualtion
+  #define  fb_motionblur           (1<<2)   //emulate motion blur
+  #define  fb_ref                  (1<<3)   //read every frame
+  #define  fb_read_alpha           (1<<4)   //read alpha
+  #define  fb_hwfbe_buf_clear      (1<<5)   //clear auxiliary texture frame buffers
+  #define  fb_depth_render         (1<<6)   //enable software depth render
+  #define  fb_optimize_texrect     (1<<7)   //fast texrect rendering with hwfbe
+  #define  fb_ignore_aux_copy      (1<<8)   //do not copy auxiliary frame buffers
+  #define  fb_useless_is_useless   (1<<10)  //
+  #define  fb_get_info             (1<<11)  //get frame buffer info
+  #define  fb_read_back_to_screen  (1<<12)  //render N64 frame buffer to screen
+  #define  fb_read_back_to_screen2 (1<<13)  //render N64 frame buffer to screen
+  #define  fb_cpu_write_hack       (1<<14)  //show images writed directly by CPU
+
+  #define fb_emulation_enabled ((settings.frame_buffer&fb_emulation)>0)
+  #define fb_hwfbe_enabled ((settings.frame_buffer&(fb_emulation|fb_hwfbe))==(fb_emulation|fb_hwfbe))
+  #define fb_depth_render_enabled ((settings.frame_buffer&fb_depth_render)>0)
+
+  wxUint32 frame_buffer;
+  enum FBCRCMODE {
+    fbcrcNone = 0,
+    fbcrcFast = 1,
+    fbcrcSafe = 2} fb_crc_mode;
+
+#ifdef TEXTURE_FILTER
+  //Texture filtering options
+  int ghq_fltr;
+  int ghq_enht;
+  int ghq_cmpr;
+  int ghq_hirs;
+  int ghq_use;
+  int ghq_enht_cmpr;
+  int ghq_enht_tile;
+  int ghq_enht_f16bpp;
+  int ghq_enht_gz;
+  int ghq_enht_nobg;
+  int ghq_hirs_cmpr;
+  int ghq_hirs_tile;
+  int ghq_hirs_f16bpp;
+  int ghq_hirs_gz;
+  int ghq_hirs_altcrc;
+  int ghq_cache_save;
+  int ghq_cache_size;
+  int ghq_hirs_let_texartists_fly;
+  int ghq_hirs_dump;
+#endif
+
+  //Debug
+  int autodetect_ucode;
+  int ucode;
+  int logging;
+  int elogging;
+  int log_clear;
+  int run_in_window;
+  int filter_cache;
+  int unk_as_red;
+  int log_unk;
+  int unk_clear;
+  int wireframe;
+  int wfmode;
+
+  // Special fixes
+  int offset_x, offset_y;
+  int scale_x, scale_y;
+  int fast_crc;
+  int alt_tex_size;
+  int use_sts1_only;
+  int flame_corona; //hack for zeldas flame's corona
+  int increase_texrect_edge; // add 1 to lower right corner coordinates of texrect
+  int decrease_fillrect_edge; // sub 1 from lower right corner coordinates of fillrect
+  int texture_correction; // enable perspective texture correction emulation. is on by default
+  int stipple_mode;  //used for dithered alpha emulation
+  wxUint32 stipple_pattern; //used for dithered alpha emulation
+  int force_microcheck; //check microcode each frame, for mixed F3DEX-S2DEX games
+  int force_quad3d; //force 0xb5 command to be quad, not line 3d
+  int clip_zmin; //enable near z clipping
+  int clip_zmax; //enable far plane clipping;
+  int adjust_aspect; //adjust screen aspect for wide screen mode
+  int force_calc_sphere; //use spheric mapping only, Ridge Racer 64
+  int pal230;    //set special scale for PAL games
+  int correct_viewport; //correct viewport values
+  int zmode_compare_less; //force GR_CMP_LESS for zmode=0 (opaque)and zmode=1 (interpenetrating)
+  int old_style_adither; //apply alpha dither regardless of alpha_dither_mode
+  int n64_z_scale; //scale vertex z value before writing to depth buffer, as N64 does.
+
+  //Special game hacks
+  #define  hack_ASB         (1<<0)   //All-Star Baseball games
+  #define  hack_Banjo2      (1<<1)   //Banjo Tooie
+  #define  hack_BAR         (1<<2)   //Beetle Adventure Racing
+  #define  hack_Chopper     (1<<3)   //Chopper Attack
+  #define  hack_Diddy       (1<<4)   //diddy kong racing
+  #define  hack_Fifa98      (1<<5)   //FIFA - Road to World Cup 98
+  #define  hack_Fzero       (1<<6)   //F-Zero
+  #define  hack_GoldenEye   (1<<7)   //Golden Eye
+  #define  hack_Hyperbike   (1<<8)   //Top Gear Hyper Bike
+  #define  hack_ISS64       (1<<9)   //International Superstar Soccer 64
+  #define  hack_KI          (1<<10)  //Killer Instinct
+  #define  hack_Knockout    (1<<11)  //Knockout Kings 2000
+  #define  hack_Lego        (1<<12)  //LEGO Racers
+  #define  hack_MK64        (1<<13)  //Mario Kart
+  #define  hack_Megaman     (1<<14)  //Megaman64
+  #define  hack_Makers      (1<<15)  //Mischief-makers
+  #define  hack_WCWnitro    (1<<16)  //WCW Nitro
+  #define  hack_Ogre64      (1<<17)  //Ogre Battle 64
+  #define  hack_Pilotwings  (1<<18)  //Pilotwings
+  #define  hack_PMario      (1<<19)  //Paper Mario
+  #define  hack_PPL         (1<<20)  //pokemon puzzle league requires many special fixes
+  #define  hack_RE2         (1<<21)  //Resident Evil 2
+  #define  hack_Starcraft   (1<<22)  //StarCraft64
+  #define  hack_Supercross  (1<<23)  //Supercross 2000
+  #define  hack_TGR         (1<<24)  //Top Gear Rally
+  #define  hack_TGR2        (1<<25)  //Top Gear Rally 2
+  #define  hack_Tonic       (1<<26)  //tonic trouble
+  #define  hack_Yoshi       (1<<27)  //Yoshi Story
+  #define  hack_Zelda       (1<<28)  //zeldas hacks
+  wxUint32 hacks;
+
+  //wrapper settings
+  int wrpResolution;
+  int wrpVRAM;
+  int wrpFBO;
+  int wrpAnisotropic;
+
+} SETTINGS;
+
+typedef struct
+{
+  wxUint8 hk_ref;
+  wxUint8 hk_motionblur;
+  wxUint8 hk_filtering;
+} HOTKEY_INFO;
+
+typedef struct
+{
+  int num_tmu;
+  int max_tex_size;
+  int sup_large_tex;
+  int sup_mirroring;
+  int sup_32bit_tex;
+  int has_2mb_tex_boundary;
+  int tex_UMA;
+  int gamma_correction;
+  FxI32 gamma_table_size;
+  FxU32 *gamma_table_r;
+  FxU32 *gamma_table_g;
+  FxU32 *gamma_table_b;
+  wxUint32 tmem_ptr[MAX_TMU];
+  wxUint32 tex_min_addr[MAX_TMU];
+  wxUint32 tex_max_addr[MAX_TMU];
+} VOODOO;
+
+// This structure is what is passed in by rdp:settextureimage
+typedef struct {
+  wxUint8 format;  // format: ARGB, IA, ...
+  wxUint8 size;    // size: 4,8,16, or 32 bit
+  wxUint16 width;   // used in settextureimage
+  wxUint32 addr;   // address in RDRAM to load the texture from
+  int 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
+  wxUint8 format;  // format: ARGB, IA, ...
+  wxUint8 size;    // size: 4,8,16, or 32 bit
+  wxUint16 line;    // size of one row (x axis) in 64 bit words
+  wxUint16 t_mem;   // location in texture memory (in 64 bit words, max 512 (4MB))
+  wxUint8 palette; // palette # to use
+  wxUint8 clamp_t; // clamp or wrap (y axis)?
+  wxUint8 mirror_t;  // mirroring on (y axis)?
+  wxUint8 mask_t;  // mask to wrap around (ex: 5 would wrap around 32) (y axis)
+  wxUint8 shift_t; // ??? (scaling)
+  wxUint8 clamp_s; // clamp or wrap (x axis)?
+  wxUint8 mirror_s;  // mirroring on (x axis)?
+  wxUint8 mask_s;  // mask to wrap around (x axis)
+  wxUint8 shift_s; // ??? (scaling)
+
+    // rdp:settilesize
+  wxUint16 ul_s;    // upper left s coordinate
+  wxUint16 ul_t;    // upper left t coordinate
+  wxUint16 lr_s;    // lower right s coordinate
+  wxUint16 lr_t;    // lower right t coordinate
+
+  float f_ul_s;
+  float f_ul_t;
+
+  // these are set by loadtile
+  wxUint16 t_ul_s;    // upper left s coordinate
+  wxUint16 t_ul_t;    // upper left t coordinate
+  wxUint16 t_lr_s;    // lower right s coordinate
+  wxUint16 t_lr_t;    // lower right t coordinate
+
+  wxUint32 width;
+  wxUint32 height;
+
+  // uc0:texture
+  wxUint8 on;
+  float s_scale;
+  float t_scale;
+
+  wxUint16 org_s_scale;
+  wxUint16 org_t_scale;
+} TILE;
+
+// This structure forms the lookup table for cached textures
+typedef struct {
+  wxUint32 addr;     // address in RDRAM
+  wxUint32 crc;      // CRC check
+  wxUint32 palette;    // Palette #
+  wxUint32 width;    // width
+  wxUint32 height;   // height
+  wxUint32 format;   // format
+  wxUint32 size;     // size
+  wxUint32 last_used;  // what frame # was this texture last used (used for replacing)
+
+  wxUint32 line;
+
+  wxUint32 flags;    // clamp/wrap/mirror flags
+
+  wxUint32 realwidth;  // width of actual texture
+  wxUint32 realheight; // height of actual texture
+  wxUint32 lod;
+  wxUint32 aspect;
+
+  wxUint8 set_by;
+  wxUint8 texrecting;
+
+  int f_mirror_s;
+  int f_mirror_t;
+  int f_wrap_s;
+  int f_wrap_t;
+
+  float scale_x;    // texture scaling
+  float scale_y;
+  float scale;    // general scale to 256
+
+  GrTexInfo t_info; // texture info (glide)
+  wxUint32 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
+
+  wxUint32 mod, mod_color, mod_color1, mod_color2, mod_factor;
+#ifdef TEXTURE_FILTER
+  uint64 ricecrc;
+  int is_hires_tex;
+#endif
+} 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;
+  wxUint32 nonblack;
+  wxUint32 nonzero;
+} LIGHT;
+
+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, auxiliary color image, copy of last color image from previous frame
+  ci_copy,      //5, auxiliary 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, auxiliary color image, copy of depth image
+  ci_aux,       //8, auxiliary color image
+  ci_aux_copy   //9, auxiliary color image, partial copy of previous color image
+} CI_STATUS;
+
+// Frame buffers
+typedef struct
+{
+       wxUint32 addr;   //color image address
+       wxUint8 format;
+       wxUint8 size;
+       wxUint16 width;
+       wxUint16 height;
+       CI_STATUS status;
+       int   changed;
+} COLOR_IMAGE;
+
+typedef struct
+{
+  GrChipID_t tmu;
+       wxUint32 addr;  //address of color image
+       wxUint32 end_addr;
+       wxUint32 tex_addr; //address in video memory
+       wxUint32 width;    //width of color image
+       wxUint32 height;   //height of color image
+       wxUint8  format;   //format of color image
+       wxUint8  size;   //format of color image
+       wxUint8  clear;  //flag. texture buffer must be cleared
+       wxUint8  drawn;  //flag. if equal to 1, this image was already drawn in current frame
+       wxUint32 crc; //checksum of the color image
+       float scr_width; //width of rendered image
+       float scr_height; //height of rendered image
+       wxUint32 tex_width;  //width of texture buffer
+       wxUint32 tex_height; //height of texture buffer
+       int   tile;     //
+       wxUint16  tile_uls; //shift from left bound of the texture
+       wxUint16  tile_ult; //shift from top of the texture
+       wxUint32 v_shift; //shift from top of the texture
+       wxUint32 u_shift; //shift from left of the texture
+       float lr_u;
+       float lr_v;
+       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
+       CACHE_LUT * cache; //pointer to texture cache item
+       GrTexInfo info;
+  wxUint16 t_mem;
+} TBUFF_COLOR_IMAGE;
+
+typedef struct
+{
+       GrChipID_t tmu;
+       wxUint32 begin; //start of the block in video memory
+       wxUint32 end;   //end of the block in video memory
+       wxUint8 count;  //number of allocated texture buffers
+       int clear_allowed; //stack of buffers can be cleared
+       TBUFF_COLOR_IMAGE images[256];
+} TEXTURE_BUFFER;
+
+#define NUMTEXBUF 92
+
+struct RDP_Base{
+  float vi_width;
+  float vi_height;
+
+  int window_changed;
+
+  float offset_x, offset_y, offset_x_bak, offset_y_bak;
+
+  float scale_x, scale_1024, scale_x_bak;
+  float scale_y, scale_768, scale_y_bak;
+
+  float view_scale[3];
+  float view_trans[3];
+  float clip_min_x, clip_max_x, clip_min_y, clip_max_y;
+  float clip_ratio;
+
+  int updatescreen;
+
+  wxUint32 tri_n;  // triangle counter
+  wxUint32 debug_n;
+
+  // Program counter
+  wxUint32 pc[10]; // DList PC stack
+  wxUint32 pc_i;   // current PC index in the stack
+  int dl_count; // number of instructions before returning
+  int LLE;
+
+  // Segments
+  wxUint32 segment[16];  // Segment pointer
+
+  // Marks the end of DList execution (done in uc?:enddl)
+  int halt;
+
+  // Next command
+  wxUint32 cmd0;
+  wxUint32 cmd1;
+  wxUint32 cmd2;
+  wxUint32 cmd3;
+
+  // Clipping
+  SCISSOR scissor_o;
+  SCISSOR scissor;
+  int scissor_set;
+
+  // Colors
+  wxUint32 fog_color;
+  wxUint32 fill_color;
+  wxUint32 prim_color;
+  wxUint32 blend_color;
+  wxUint32 env_color;
+  wxUint32 SCALE;
+  wxUint32 CENTER;
+  wxUint32 prim_lodmin, prim_lodfrac;
+  wxUint16 prim_depth;
+  wxUint16 prim_dz;
+  wxUint8 K4;
+  wxUint8 K5;
+  enum {
+  noise_none,
+  noise_combine,
+  noise_texture
+  } noise;
+
+  float col[4];   // color multiplier
+  float coladd[4];  // color add/subtract
+  float shade_factor;
+
+  float col_2[4];
+
+  wxUint32 cmb_flags, cmb_flags_2;
+
+  // othermode_l flags
+  int acmp; // 0 = none, 1 = threshold, 2 = dither
+  int zsrc; // 0 = pixel, 1 = prim
+  wxUint8 alpha_dither_mode;
+
+  // Matrices
+  DECLAREALIGN16VAR(model[4][4]);
+  DECLAREALIGN16VAR(proj[4][4]);
+  DECLAREALIGN16VAR(combined[4][4]);
+  DECLAREALIGN16VAR(dkrproj[3][4][4]);
+
+  DECLAREALIGN16VAR(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
+  wxUint8 tmem[4096];        // 4k tmem
+  wxUint32 addr[512];        // 512 addresses (used to determine address loaded from)
+#ifdef TEXTURE_FILTER
+  LOAD_TILE_INFO load_info[512];    // 512 addresses. inforamation about tile loading.
+#endif
+
+  int     cur_tile;   // current tile
+  int     mipmap_level;
+  int     last_tile;   // last tile set
+  int     last_tile_size;   // last tile size set
+
+  int     t0, t1;
+  int     best_tex; // if no 2-tmus, which texture? (0 or 1)
+  int     tex;
+  int     filter_mode;
+
+  // Texture palette
+  wxUint16 pal_8[256];
+  wxUint32 pal_8_crc[16];
+  wxUint32 pal_256_crc;
+  wxUint8 tlut_mode;
+  int LOD_en;
+  int Persp_en;
+  int persp_supported;
+  int force_wrap;
+#ifdef TEXTURE_FILTER
+  wxUint16 pal_8_rice[512];
+#endif
+
+  // Lighting
+  wxUint32 num_lights;
+  LIGHT light[12];
+  float light_vector[12][3];
+  float lookat[2][3];
+  int  use_lookat;
+
+  // Combine modes
+  wxUint32 cycle1, cycle2, cycle_mode;
+  wxUint8 c_a0, c_b0, c_c0, c_d0, c_Aa0, c_Ab0, c_Ac0, c_Ad0;
+  wxUint8 c_a1, c_b1, c_c1, c_d1, c_Aa1, c_Ab1, c_Ac1, c_Ad1;
+
+  wxUint8 fbl_a0, fbl_b0, fbl_c0, fbl_d0;
+  wxUint8 fbl_a1, fbl_b1, fbl_c1, fbl_d1;
+
+  wxUint8 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
+
+  // What needs updating
+  wxUint32 update;
+  wxUint32 flags;
+
+  int first;
+
+  wxUint32 tex_ctr;    // incremented every time textures are updated
+
+  int allow_combine; // allow combine updating?
+
+  int s2dex_tex_loaded;
+  wxUint16 bg_image_height;
+
+  // Debug stuff
+  wxUint32 rm; // use othermode_l instead, this just as a check for changes
+  wxUint32 render_mode_changed;
+  wxUint32 geom_mode;
+
+  wxUint32 othermode_h;
+  wxUint32 othermode_l;
+
+  // used to check if in texrect while loading texture
+  wxUint8 texrecting;
+
+  //frame buffer related slots. Added by Gonetz
+  wxUint32 cimg, ocimg, zimg, tmpzimg, vi_org_reg;
+  COLOR_IMAGE maincimg[2];
+  wxUint32 last_drawn_ci_addr;
+  wxUint32 main_ci, main_ci_end, main_ci_bg, main_ci_last_tex_addr, zimg_end, last_bg;
+  wxUint32 ci_width, ci_height, ci_size, ci_end;
+  wxUint32 zi_width;
+  int zi_lrx, zi_lry;
+  wxUint8  ci_count, num_of_ci, main_ci_index, copy_ci_index, copy_zi_index;
+  int swap_ci_index, black_ci_index;
+  wxUint32 ci_upper_bound, ci_lower_bound;
+  int  motionblur, fb_drawn, fb_drawn_front, read_previous_ci, read_whole_frame;
+  CI_STATUS ci_status;
+  TBUFF_COLOR_IMAGE * cur_image;  //image currently being drawn
+  TBUFF_COLOR_IMAGE * tbuff_tex;  //image, which corresponds to currently selected texture
+  TBUFF_COLOR_IMAGE * aTBuffTex[2]; 
+  wxUint8  cur_tex_buf;
+  wxUint8  acc_tex_buf;
+  int skip_drawing; //rendering is not required. used for frame buffer emulation
+
+  //fog related slots. Added by Gonetz
+  float fog_multiplier, fog_offset;
+  enum {
+    fog_disabled,
+    fog_enabled,
+    fog_blend,
+    fog_blend_inverse
+    }
+  fog_mode;
+};
+
+struct RDP : public RDP_Base
+{
+  // 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;
+
+  CACHE_LUT *cache[MAX_TMU]; //[MAX_CACHE]
+  CACHE_LUT *cur_cache[MAX_TMU];
+  wxUint32   cur_cache_n[MAX_TMU];
+  int     n_cached[MAX_TMU];
+
+  // Vertices
+  VERTEX *vtx; //[MAX_VTX]
+  int v0, vn;
+
+  COLOR_IMAGE *frame_buffers; //[NUMTEXBUF+2]
+  TEXTURE_BUFFER texbufs[2];
+
+  char RomName[21];
+
+  RDP();
+  ~RDP();
+  void Reset();
+};
+
+
+void SetWireframeCol ();
+void ChangeSize ();
+void GoToFullScreen();
+
+extern RDP rdp;
+extern SETTINGS settings;
+extern HOTKEY_INFO hotkey_info;
+extern VOODOO voodoo;
+
+extern GrTexInfo  fontTex;
+extern GrTexInfo  cursorTex;
+extern wxUint32   offset_font;
+extern wxUint32   offset_cursor;
+extern wxUint32   offset_textures;
+extern wxUint32   offset_texbuf1;
+
+extern int     ucode_error_report;
+
+/*
+extern wxString pluginPath;
+extern wxString iniPath;
+*/
+// RDP functions
+void rdp_reset ();
+
+extern const char *ACmp[];
+extern const char *Mode0[];
+extern const char *Mode1[];
+extern const char *Mode2[];
+extern const char *Mode3[];
+extern const char *Alpha0[];
+#define Alpha1 Alpha0
+extern const char *Alpha2[];
+#define Alpha3 Alpha0
+extern const char *FBLa[];
+extern const char *FBLb[];
+extern const char *FBLc[];
+extern const char *FBLd[];
+extern const char *str_zs[];
+extern const char *str_yn[];
+extern const char *str_offon[];
+extern const char *str_cull[];
+// I=intensity probably
+extern const char *str_format[];
+extern const char *str_size[];
+extern const char *str_cm[];
+extern const char *str_lod[];
+extern const char *str_aspect[];
+extern const char *str_filter[];
+extern const char *str_tlut[];
+extern const char *CIStatus[];
+
+#define FBL_D_1 2
+#define FBL_D_0 3
+
+#ifndef max
+#define max(a,b)            (((a) > (b)) ? (a) : (b))
+#endif
+#ifndef min
+#define min(a,b)            (((a) < (b)) ? (a) : (b))
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef HIWORD
+#define HIWORD(a) ((unsigned int)(a) >> 16)
+#endif
+#ifndef LOWORD
+#define LOWORD(a) ((a) & 0xFFFF)
+#endif
+
+// 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<n; i++)
+  {
+    v[i].uc(0) = v[i].u0;
+    v[i].vc(0) = v[i].v0;
+    v[i].uc(1) = v[i].u1;
+    v[i].vc(1) = v[i].v1;
+  }
+}
+
+// Convert from u0/v0/u1/v1 to the real coordinates based on the tmu they are on
+__inline void ConvertCoordsConvert (VERTEX *v, int n)
+{
+  for (int i=0; i<n; i++)
+  {
+    v[i].uc(rdp.t0) = v[i].u0;
+    v[i].vc(rdp.t0) = v[i].v0;
+    v[i].uc(rdp.t1) = v[i].u1;
+    v[i].vc(rdp.t1) = v[i].v1;
+  }
+}
+
+__inline void AllowShadeMods (VERTEX *v, int n)
+{
+  for (int i=0; i<n; i++)
+  {
+    v[i].shade_mod = 0;
+  }
+}
+
+__inline void AddOffset (VERTEX *v, int n)
+{
+  for (int i=0; i<n; i++)
+  {
+    v[i].x += rdp.offset_x;
+    v[i].y += rdp.offset_y;
+  }
+}
+
+__inline void CalculateFog (VERTEX *v)
+{
+  if (rdp.flags & FOG_ENABLED)
+  {
+    if (v->w < 0.0f)
+      v->f = 0.0f;
+    else
+      v->f = min(255.0f, max(0.0f, v->z_w * rdp.fog_multiplier + rdp.fog_offset));
+    v->a = (wxUint8)v->f;
+  }
+  else
+  {
+    v->f = 1.0f;
+  }
+}
+
+void newSwapBuffers();
+extern int SwapOK;
+
+// ** utility functions
+void load_palette (wxUint32 addr, wxUint16 start, wxUint16 count);
+void setTBufTex(wxUint16 t_mem, wxUint32 cnt);
+
+#endif  // ifndef RDP_H
diff --git a/source/gles2glide64/src/Glide64/ticks.c b/source/gles2glide64/src/Glide64/ticks.c
new file mode 100644 (file)
index 0000000..7819dcb
--- /dev/null
@@ -0,0 +1,35 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *   Copyright (C) 2011 yongzh (freeman.yong@gmail.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 <time.h>
+
+static struct timespec startTicks;
+
+void ticksInitialize()
+{
+       clock_gettime(CLOCK_MONOTONIC, &startTicks);
+}
+
+unsigned int ticksGetTicks()
+{
+       struct timespec now;
+       clock_gettime(CLOCK_MONOTONIC, &now);
+       return (now.tv_sec - startTicks.tv_sec) * 1000 +
+                       (now.tv_nsec - startTicks.tv_nsec) / 1000000;
+}
diff --git a/source/gles2glide64/src/Glide64/ticks.h b/source/gles2glide64/src/Glide64/ticks.h
new file mode 100644 (file)
index 0000000..5960d19
--- /dev/null
@@ -0,0 +1,34 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *   Copyright (C) 2011 yongzh (freeman.yong@gmail.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.          *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#ifndef EMUTICKS_H
+#define EMUTICKS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void ticksInitialize();
+unsigned int ticksGetTicks();
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/source/gles2glide64/src/Glide64/turbo3D.h b/source/gles2glide64/src/Glide64/turbo3D.h
new file mode 100644 (file)
index 0000000..52a7b5f
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+//
+// Created by Gonetz, 2008
+//
+//****************************************************************
+
+/******************Turbo3D microcode*************************/
+
+struct t3dGlobState {
+  wxUint16             pad0;
+  wxUint16             perspNorm;
+  wxUint32             flag;
+  wxUint32             othermode0;
+  wxUint32             othermode1;
+  wxUint32             segBases[16];
+  /* the viewport to use */
+  short     vsacle1;
+  short     vsacle0;
+  short     vsacle3;
+  short     vsacle2;
+  short     vtrans1;
+  short     vtrans0;
+  short     vtrans3;
+  short     vtrans2;
+  wxUint32  rdpCmds;
+};
+
+struct t3dState {
+    wxUint32   renderState;    /* render state */
+    wxUint32   textureState;   /* texture state */
+    wxUint8    flag;
+    wxUint8    triCount;       /* how many tris? */
+    wxUint8    vtxV0;          /* where to load verts? */
+    wxUint8    vtxCount;       /* how many verts? */
+    wxUint32   rdpCmds;        /* ptr (segment address) to RDP DL */
+    wxUint32   othermode0;
+    wxUint32   othermode1;
+};
+
+
+struct t3dTriN{
+   wxUint8     flag, v2, v1, v0;       /* flag is which one for flat shade */
+};
+
+
+static void t3dProcessRDP(wxUint32 a)
+{
+  if (a)
+  {
+    rdp.LLE = 1;
+    rdp.cmd0 = ((wxUint32*)gfx.RDRAM)[a++];
+    rdp.cmd1 = ((wxUint32*)gfx.RDRAM)[a++];
+    while (rdp.cmd0 + rdp.cmd1) {
+      gfx_instruction[0][rdp.cmd0>>24] ();
+      rdp.cmd0 = ((wxUint32*)gfx.RDRAM)[a++];
+      rdp.cmd1 = ((wxUint32*)gfx.RDRAM)[a++];
+      wxUint32 cmd = rdp.cmd0>>24;
+      if (cmd == 0xE4 || cmd == 0xE5)
+      {
+        rdp.cmd2 = ((wxUint32*)gfx.RDRAM)[a++];
+        rdp.cmd3 = ((wxUint32*)gfx.RDRAM)[a++];
+      }
+    }
+    rdp.LLE = 0;
+  }
+}
+
+static void t3dLoadGlobState(wxUint32 pgstate)
+{
+  t3dGlobState *gstate = (t3dGlobState*)&gfx.RDRAM[segoffset(pgstate)];
+  FRDP ("Global state. pad0: %04lx, perspNorm: %04lx, flag: %08lx\n", gstate->pad0, gstate->perspNorm, gstate->flag);
+  rdp.cmd0 = gstate->othermode0;
+  rdp.cmd1 = gstate->othermode1;
+  rdp_setothermode();
+
+  for (int s = 0; s < 16; s++)
+  {
+    rdp.segment[s] = gstate->segBases[s];
+    FRDP ("segment: %08lx -> seg%d\n", rdp.segment[s], s);
+  }
+
+  short scale_x = gstate->vsacle0 / 4;
+  short scale_y = gstate->vsacle1 / 4;;
+  short scale_z = gstate->vsacle2;
+  short trans_x = gstate->vtrans0 / 4;
+  short trans_y = gstate->vtrans1 / 4;
+  short trans_z = gstate->vtrans2;
+  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)\n", scale_x, scale_y, scale_z,
+    trans_x, trans_y, trans_z);
+
+  t3dProcessRDP(segoffset(gstate->rdpCmds) >> 2);
+}
+
+static void t3d_vertex(wxUint32 addr, wxUint32 v0, wxUint32 n)
+{
+    float x, y, z;
+
+    rdp.v0 = v0; // Current vertex
+    rdp.vn = n; // Number of vertices to copy
+    n <<= 4;
+
+    for (wxUint32 i=0; i < n; 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  = ((wxUint16*)gfx.RDRAM)[(((addr+i) >> 1) + 3)^1];
+      v->ou   = 2.0f * (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 4)^1];
+      v->ov   = 2.0f * (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 5)^1];
+      v->uv_scaled = 0;
+      v->r = ((wxUint8*)gfx.RDRAM)[(addr+i + 12)^3];
+      v->g = ((wxUint8*)gfx.RDRAM)[(addr+i + 13)^3];
+      v->b = ((wxUint8*)gfx.RDRAM)[(addr+i + 14)^3];
+      v->a    = ((wxUint8*)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];
+
+      if (fabs(v->w) < 0.001) v->w = 0.001f;
+      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_mod = 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;
+#ifdef EXTREME_LOGGING
+    FRDP ("v%d - x: %f, y: %f, z: %f, w: %f, u: %f, v: %f, f: %f, z_w: %f, r=%d, g=%d, b=%d, a=%d\n", i>>4, v->x, v->y, v->z, v->w, v->ou*rdp.tiles[rdp.cur_tile].s_scale, v->ov*rdp.tiles[rdp.cur_tile].t_scale, v->f, v->z_w, v->r, v->g, v->b, v->a);
+#endif
+    }
+}
+
+static void t3dLoadObject(wxUint32 pstate, wxUint32 pvtx, wxUint32 ptri)
+{
+  LRDP("Loading Turbo3D object\n");
+  t3dState *ostate = (t3dState*)&gfx.RDRAM[segoffset(pstate)];
+  rdp.cur_tile = (ostate->textureState)&7;
+  FRDP("tile: %d\n", rdp.cur_tile);
+  if (rdp.tiles[rdp.cur_tile].s_scale < 0.001f)
+    rdp.tiles[rdp.cur_tile].s_scale = 0.015625;
+  if (rdp.tiles[rdp.cur_tile].t_scale < 0.001f)
+    rdp.tiles[rdp.cur_tile].t_scale = 0.015625;
+
+#ifdef EXTREME_LOGGING
+  FRDP("renderState: %08lx, textureState: %08lx, othermode0: %08lx, othermode1: %08lx, rdpCmds: %08lx, triCount : %d, v0: %d, vn: %d\n", ostate->renderState, ostate->textureState,
+     ostate->othermode0, ostate->othermode1, ostate->rdpCmds, ostate->triCount, ostate->vtxV0, ostate->vtxCount);
+#endif
+
+  rdp.cmd0 = ostate->othermode0;
+  rdp.cmd1 = ostate->othermode1;
+  rdp_setothermode();
+
+  rdp.cmd1 = ostate->renderState;
+  uc0_setgeometrymode();
+
+  if (!(ostate->flag&1)) //load matrix
+  {
+    wxUint32 addr = segoffset(pstate+sizeof(t3dState)) & BMASK;
+    load_matrix(rdp.combined, addr);
+#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
+  }
+
+  rdp.geom_mode &= ~0x00020000;
+  rdp.geom_mode |= 0x00000200;
+  if (pvtx) //load vtx
+    t3d_vertex(segoffset(pvtx) & BMASK, ostate->vtxV0, ostate->vtxCount);
+
+  t3dProcessRDP(segoffset(ostate->rdpCmds) >> 2);
+
+  if (ptri)
+  {
+    update ();
+    wxUint32 a = segoffset(ptri);
+    for (int t=0; t < ostate->triCount; t++)
+    {
+      t3dTriN * tri = (t3dTriN*)&gfx.RDRAM[a];
+      a += 4;
+      FRDP("tri #%d - %d, %d, %d\n", t, tri->v0, tri->v1, tri->v2);
+      VERTEX *v[3] = { &rdp.vtx[tri->v0], &rdp.vtx[tri->v1], &rdp.vtx[tri->v2] };
+      if (cull_tri(v))
+        rdp.tri_n ++;
+      else
+      {
+        draw_tri (v);
+        rdp.tri_n ++;
+      }
+    }
+  }
+}
+
+static void Turbo3D()
+{
+  LRDP("Start Turbo3D microcode\n");
+  settings.ucode = ucode_Fast3D;
+  wxUint32 a = 0, pgstate = 0, pstate = 0, pvtx = 0, ptri = 0;
+  do {
+    a = rdp.pc[rdp.pc_i] & BMASK;
+    pgstate = ((wxUint32*)gfx.RDRAM)[a>>2];
+    pstate = ((wxUint32*)gfx.RDRAM)[(a>>2)+1];
+    pvtx = ((wxUint32*)gfx.RDRAM)[(a>>2)+2];
+    ptri = ((wxUint32*)gfx.RDRAM)[(a>>2)+3];
+    FRDP("GlobalState: %08lx, Object: %08lx, Vertices: %08lx, Triangles: %08lx\n", pgstate, pstate, pvtx, ptri);
+    if (!pstate)
+    {
+      rdp.halt = 1;
+      break;
+    }
+    if (pgstate)
+      t3dLoadGlobState(pgstate);
+    t3dLoadObject(pstate, pvtx, ptri);
+   // Go to the next instruction
+    rdp.pc[rdp.pc_i] += 16;
+ } while (pstate);
+// rdp_fullsync();
+ settings.ucode = ucode_Turbo3d;
+}
diff --git a/source/gles2glide64/src/Glide64/ucode.h b/source/gles2glide64/src/Glide64/ucode.h
new file mode 100644 (file)
index 0000000..c76ce15
--- /dev/null
@@ -0,0 +1,792 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+typedef void (*rdp_instr)();
+
+// RDP graphic instructions pointer table
+
+static rdp_instr gfx_instruction[10][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,           rdphalf_cont,           rdphalf_2,
+        rdphalf_1,              uc0_line3d,             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,             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,               rdphalf_cont,       rdphalf_2,
+                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,                       rdphalf_cont,       rdphalf_2,
+        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,                   rdphalf_cont,               rdphalf_2,
+        rdphalf_1,              uc0_line3d,             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,            rdphalf_2,
+        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,                               rdphalf_cont,           rdphalf_2,
+                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,           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,                                 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 9 - gzsort
+        // games: Telefoot Soccer
+        // 00-3f
+        spnoop,                     undef,                      undef,                      undef,        
+        undef,                      undef,                      undef,                      undef,        
+        undef,                      undef,                      undef,                      undef,        
+        undef,                      undef,                      undef,                      undef,        
+        undef,                      undef,                      undef,                      undef,        
+        undef,                      undef,                      undef,                      undef,        
+        undef,                      undef,                      undef,                      undef,        
+        undef,                      undef,                      undef,                      undef,        
+        undef,                      undef,                      undef,                      undef,        
+        undef,                      undef,                      undef,                      undef,        
+        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
+        uc9_object,                 uc9_rpdcmd,                 undef,                      undef,        
+        undef,                      undef,                      undef,                      undef,        
+        undef,                      undef,                      undef,                      undef,        
+        undef,                      undef,                      undef,                      undef,        
+        undef,                      undef,                      undef,                      undef,        
+        undef,                      undef,                      undef,                      undef,        
+        undef,                      undef,                      undef,                      undef,        
+        undef,                      undef,                      undef,                      undef,        
+        undef,                      undef,                      undef,                      undef,        
+        undef,                      undef,                      undef,                      undef,        
+        undef,                      undef,                      undef,                      undef,        
+        undef,                      undef,                      undef,                      undef,        
+        undef,                      undef,                      undef,                      undef,        
+        rdphalf_1,                  undef,                      uc0_cleargeometrymode,      uc0_setgeometrymode,
+        uc0_enddl,                  uc0_setothermode_l,         uc0_setothermode_h,         uc0_texture,
+        uc0_moveword,               undef,                      uc0_culldl,                 undef,
+          // 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,
+
+        uc9_mix,                uc9_fmlight,            uc9_light,              undef,    
+        uc9_mtxtrnsp,           uc9_mtxcat,             uc9_mult_mpmtx,         uc9_link_subdl,    
+        uc9_set_subdl,          uc9_wait_signal,        uc9_send_signal,        uc0_moveword,    
+        uc9_movemem,            undef,                  uc0_displaylist,        uc0_enddl,    
+
+        undef,                  undef,                  uc0_setothermode_l,     uc0_setothermode_h,    
+        rdp_texrect,            rdp_texrect,            rdp_loadsync,           rdp_pipesync,
+        rdp_tilesync,           rdp_fullsync,           rdp_setkeygb,           rdp_setkeyr,
+        rdp_setconvert,         uc9_setscissor,         rdp_setprimdepth,       rdp_setothermode,
+
+        rdp_loadtlut,           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/source/gles2glide64/src/Glide64/ucode00.h b/source/gles2glide64/src/Glide64/ucode00.h
new file mode 100755 (executable)
index 0000000..388c388
--- /dev/null
@@ -0,0 +1,1168 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+#define ucode_Fast3D 0
+#define ucode_F3DEX 1
+#define ucode_F3DEX2 2
+#define ucode_WaveRace 3
+#define ucode_StarWars 4
+#define ucode_DiddyKong 5
+#define ucode_S2DEX 6
+#define ucode_PerfectDark 7
+#define ucode_CBFD 8
+#define ucode_zSort 9
+#define ucode_Turbo3d 21
+
+static void rsp_vertex(int v0, int n)
+{
+Check_FrameSkip;
+
+  wxUint32 addr = segoffset(rdp.cmd1) & 0x00FFFFFF;
+  int i;
+  float x, y, z;
+
+  rdp.v0 = v0; // Current vertex
+  rdp.vn = n;  // 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 (wxUint32 l=0; l<rdp.num_lights; l++)
+    {
+      InverseTransformVector(&rdp.light[l].dir_x, rdp.light_vector[l], rdp.model);
+      NormalizeVector (rdp.light_vector[l]);
+    }
+  }
+
+  FRDP ("rsp:vertex v0:%d, n:%d, from: %08lx\n", v0, n, addr);
+
+  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  = ((wxUint16*)gfx.RDRAM)[(((addr+i) >> 1) + 3)^1];
+    v->ou = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 4)^1];
+    v->ov = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 5)^1];
+    v->uv_scaled = 0;
+    v->a    = ((wxUint8*)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];
+
+
+    if (fabs(v->w) < 0.001) v->w = 0.001f;
+    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_mod = 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 (v->z_w > 1.0f) v->scr_off |= 32;
+
+    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 & 0x40000)
+      {
+        if (rdp.geom_mode & 0x80000)
+          calc_linear (v);
+        else
+          calc_sphere (v);
+      }
+      NormalizeVector (v->vec);
+
+      calc_light (v);
+    }
+    else
+    {
+      v->r = ((wxUint8*)gfx.RDRAM)[(addr+i + 12)^3];
+      v->g = ((wxUint8*)gfx.RDRAM)[(addr+i + 13)^3];
+      v->b = ((wxUint8*)gfx.RDRAM)[(addr+i + 14)^3];
+    }
+#ifdef EXTREME_LOGGING
+    FRDP ("v%d - x: %f, y: %f, z: %f, w: %f, u: %f, v: %f, f: %f, z_w: %f, r=%d, g=%d, b=%d, a=%d\n", i>>4, v->x, v->y, v->z, v->w, v->ou*rdp.tiles[rdp.cur_tile].s_scale, v->ov*rdp.tiles[rdp.cur_tile].t_scale, v->f, v->z_w, v->r, v->g, v->b, v->a);
+#endif
+
+  }
+}
+
+static void rsp_tri1(VERTEX **v, wxUint16 linew = 0)
+{
+Check_FrameSkip;
+
+  if (cull_tri(v))
+    rdp.tri_n ++;
+  else
+  {
+    update ();
+    draw_tri (v, linew);
+    rdp.tri_n ++;
+  }
+}
+
+static void rsp_tri2 (VERTEX **v)
+{
+Check_FrameSkip;
+
+  int updated = 0;
+
+  if (cull_tri(v))
+    rdp.tri_n ++;
+  else
+  {
+    updated = 1;
+    update ();
+
+    draw_tri (v);
+    rdp.tri_n ++;
+  }
+
+  if (cull_tri(v+3))
+    rdp.tri_n ++;
+  else
+  {
+    if (!updated)
+      update ();
+
+    draw_tri (v+3);
+    rdp.tri_n ++;
+  }
+}
+
+//
+// uc0:vertex - loads vertices
+//
+static void uc0_vertex()
+{
+  int v0 = (rdp.cmd0 >> 16) & 0xF;      // Current vertex
+  int n = ((rdp.cmd0 >> 20) & 0xF) + 1; // Number of vertices to copy
+  rsp_vertex(v0, n);
+}
+
+// ** Definitions **
+
+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])
+{
+  DECLAREALIGN16VAR(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");
+    LRDP("** 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");
+    LRDP("** 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])
+{
+  DECLAREALIGN16VAR(m_src[4][4]);
+  memcpy (m_src, rdp.proj, 64);
+  MulMatrices(m, m_src, rdp.proj);
+  rdp.update |= UPDATE_MULT_MAT;
+}
+
+void load_matrix (float m[4][4], wxUint32 addr)
+{
+  FRDP ("matrix - addr: %08lx\n", addr);
+  int x,y;  // matrix index
+  addr >>= 1;
+  wxUint16 * src = (wxUint16*)gfx.RDRAM;
+  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)(
+        (((wxInt32)src[(addr+x+y)^1]) << 16) |
+        src[(addr+x+y+16)^1]
+        ) / 65536.0f;
+    }
+  }
+}
+
+//
+// uc0:matrix - performs matrix operations
+//
+static void uc0_matrix()
+{
+  LRDP("uc0:matrix ");
+
+  // Use segment offset to get the address
+  wxUint32 addr = segoffset(rdp.cmd1) & 0x00FFFFFF;
+  wxUint8 command = (wxUint8)((rdp.cmd0 >> 16) & 0xFF);
+
+  DECLAREALIGN16VAR(m[4][4]);
+  load_matrix(m, addr);
+
+  switch (command)
+  {
+  case 0: // modelview mul nopush
+    LRDP("modelview mul\n");
+    modelview_mul (m);
+    break;
+
+  case 1: // projection mul nopush
+  case 5: // projection mul push, can't push projection
+    LRDP("projection mul\n");
+    projection_mul (m);
+    break;
+
+  case 2: // modelview load nopush
+    LRDP("modelview load\n");
+    modelview_load (m);
+    break;
+
+  case 3: // projection load nopush
+  case 7: // projection load push, can't push projection
+    LRDP("projection load\n");
+    projection_load (m);
+
+    break;
+
+  case 4: // modelview mul push
+    LRDP("modelview mul push\n");
+    modelview_mul_push (m);
+    break;
+
+  case 6: // modelview load push
+    LRDP("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()
+{
+  LRDP("uc0:movemem ");
+
+  wxUint32 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];
+      if (settings.correct_viewport)
+      {
+        scale_x = abs(scale_x);
+        scale_y = abs(scale_y);
+      }
+      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;
+
+      // 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)(((wxUint8*)gfx.RDRAM)[(a+0)^3]) / 255.0f;
+    rdp.light[i].g = (float)(((wxUint8*)gfx.RDRAM)[(a+1)^3]) / 255.0f;
+    rdp.light[i].b = (float)(((wxUint8*)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;
+
+      wxUint32 addr = segoffset(rdp.cmd1) & 0x00FFFFFF;
+      load_matrix(rdp.combined, addr);
+
+      addr = rdp.pc[rdp.pc_i] & BMASK;
+      rdp.pc[rdp.pc_i] = (addr+24) & BMASK; //skip next 3 command, b/c they all are part of gSPForceMatrix
+
+#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");
+    LRDP("matrix 0 - IGNORED\n");
+    break;
+
+  case 0x9A:
+    RDP_E ("uc0:movemem matrix 1 - ERROR!\n");
+    LRDP("matrix 1 - IGNORED\n");
+    break;
+
+  case 0x9C:
+    RDP_E ("uc0:movemem matrix 2 - ERROR!\n");
+    LRDP("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:displaylist - makes a call to another section of code
+//
+static void uc0_displaylist()
+{
+  wxUint32 addr = segoffset(rdp.cmd1) & 0x00FFFFFF;
+
+  // This fixes partially Gauntlet: Legends
+  if (addr == rdp.pc[rdp.pc_i] - 8) { LRDP("display list not executed!\n"); return; }
+
+  wxUint32 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 **");
+      LRDP("** 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");
+    LRDP("Unknown displaylist operation\n");
+  }
+}
+
+//
+// tri1 - renders a triangle
+//
+static void uc0_tri1()
+{
+Check_FrameSkip;
+
+  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 (settings.hacks & hack_Makers)
+  {
+    rdp.force_wrap = FALSE;
+    for (int i = 0; i < 3; i++)
+    {
+      if (v[i]->ou < 0.0f || v[i]->ov < 0.0f)
+      {
+        rdp.force_wrap = TRUE;
+        break;
+      }
+    }
+  }
+  rsp_tri1(v);
+}
+
+//
+// uc0:enddl - ends a call made by uc0:displaylist
+//
+static void uc0_enddl()
+{
+  LRDP("uc0:enddl\n");
+
+  if (rdp.pc_i == 0)
+  {
+    LRDP("RDP end\n");
+
+    // Halt execution here
+    rdp.halt = 1;
+  }
+
+  rdp.pc_i --;
+}
+
+static void uc0_culldl()
+{
+  wxUint8 vStart = (wxUint8)((rdp.cmd0 & 0x00FFFFFF) / 40) & 0xF;
+  wxUint8 vEnd = (wxUint8)(rdp.cmd1 / 40) & 0x0F;
+  wxUint32 cond = 0;
+  VERTEX *v;
+
+  FRDP("uc0:culldl start: %d, end: %d\n", vStart, vEnd);
+
+  if (vEnd < vStart) return;
+  for (wxUint16 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;
+  }
+
+  LRDP(" - ");  // specify that the enddl is not a real command
+  uc0_enddl ();
+}
+
+static void uc0_popmatrix()
+{
+  LRDP("uc0:popmatrix\n");
+
+  wxUint32 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);
+  }
+}
+
+static void uc6_obj_sprite ();
+
+static void uc0_modifyvtx(wxUint8 where, wxUint16 vtx, wxUint32 val)
+{
+  VERTEX *v = &rdp.vtx[vtx];
+
+  switch (where)
+  {
+  case 0:
+    uc6_obj_sprite ();
+    break;
+
+  case 0x10:    // RGBA
+    v->r = (wxUint8)(val >> 24);
+    v->g = (wxUint8)((val >> 16) & 0xFF);
+    v->b = (wxUint8)((val >> 8) & 0xFF);
+    v->a = (wxUint8)(val & 0xFF);
+    v->shade_mod = 0;
+
+    FRDP ("RGBA: %d, %d, %d, %d\n", v->r, v->g, v->b, v->a);
+    break;
+
+  case 0x14:    // ST
+    {
+      float scale = rdp.Persp_en ? 0.03125f : 0.015625f;
+      v->ou = (float)((short)(val>>16)) * scale;
+      v->ov = (float)((short)(val&0xFFFF)) * scale;
+      v->uv_calculated = 0xFFFFFFFF;
+      v->uv_scaled = 1;
+    }
+    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 = 2;
+      v->sx = scr_x * rdp.scale_x + rdp.offset_x;
+      v->sy = scr_y * rdp.scale_y + rdp.offset_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:
+    LRDP("UNKNOWN\n");
+    break;
+  }
+}
+
+//
+// uc0:moveword - moves a word to someplace, like the segment pointers
+//
+static void uc0_moveword()
+{
+  LRDP("uc0:moveword ");
+
+  // Find which command this is (lowest byte of cmd0)
+  switch (rdp.cmd0 & 0xFF)
+  {
+  case 0x00:
+    RDP_E ("uc0:moveword matrix - IGNORED\n");
+    LRDP("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:
+    if (((rdp.cmd0>>8)&0xFFFF) == 0x04)
+    {
+      rdp.clip_ratio = sqrt((float)rdp.cmd1);
+      rdp.update |= UPDATE_VIEWPORT;
+    }
+    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)<BMASK)
+      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);
+    }
+    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:
+    {
+      wxUint16 val = (wxUint16)((rdp.cmd0 >> 8) & 0xFFFF);
+      wxUint16 vtx = val / 40;
+      wxUint8 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:
+    LRDP("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;
+  if (tile == 7 && (settings.hacks&hack_Supercross)) tile = 0; //fix for supercross 2000
+  rdp.mipmap_level = (rdp.cmd0 >> 11) & 0x07;
+  wxUint32 on = (rdp.cmd0 & 0xFF);
+  rdp.cur_tile = tile;
+
+  if (on)
+  {
+    wxUint16 s = (wxUint16)((rdp.cmd1 >> 16) & 0xFFFF);
+    wxUint16 t = (wxUint16)(rdp.cmd1 & 0xFFFF);
+
+    TILE *tmp_tile = &rdp.tiles[tile];
+    tmp_tile->on = 1;
+    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
+  {
+    LRDP("uc0:texture skipped b/c of off\n");
+    rdp.tiles[tile].on = 0;
+  }
+}
+
+
+static void uc0_setothermode_h()
+{
+  LRDP("uc0:setothermode_h: ");
+
+  int shift, len;
+  if ((settings.ucode == ucode_F3DEX2) || (settings.ucode == ucode_CBFD))
+  {
+    len = (rdp.cmd0 & 0xFF) + 1;
+    shift = 32 - ((rdp.cmd0 >> 8) & 0xFF) - len;
+  }
+  else
+  {
+    shift = (rdp.cmd0 >> 8) & 0xFF;
+    len = rdp.cmd0 & 0xFF;
+  }
+
+  wxUint32 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 & 0x00000030)  // alpha dither mode
+  {
+    rdp.alpha_dither_mode = (rdp.othermode_h >> 4) & 0x3;
+    FRDP ("alpha dither mode: %s\n", str_dither[rdp.alpha_dither_mode]);
+  }
+
+  if (mask & 0x000000C0)  // rgb dither mode
+  {
+    wxUint32 dither_mode = (rdp.othermode_h >> 6) & 0x3;
+    FRDP ("rgb dither mode: %s\n", str_dither[dither_mode]);
+  }
+
+  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 = (wxUint8)((rdp.othermode_h & 0x0000C000) >> 14);
+    FRDP ("tlut mode: %s\n", str_tlut[rdp.tlut_mode]);
+  }
+
+  if (mask & 0x00300000)  // cycle type
+  {
+    rdp.cycle_mode = (wxUint8)((rdp.othermode_h & 0x00300000) >> 20);
+    rdp.update |= UPDATE_ZBUF_ENABLED;
+    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);
+  }
+
+  if (mask & 0x00080000)  // Persp enable
+  {
+    if (rdp.persp_supported)
+      rdp.Persp_en = (rdp.othermode_h & 0x00080000) ? TRUE : FALSE;
+    FRDP ("Persp_en: %d\n", rdp.Persp_en);
+  }
+
+  wxUint32 unk = mask & 0x0FFC60F0F;
+  if (unk)  // unknown portions, LARGE
+  {
+    FRDP ("UNKNOWN PORTIONS: shift: %d, len: %d, unknowns: %08lx\n", shift, len, unk);
+  }
+}
+
+static void uc0_setothermode_l()
+{
+  LRDP("uc0:setothermode_l ");
+
+  int shift, len;
+  if ((settings.ucode == ucode_F3DEX2) || (settings.ucode == ucode_CBFD))
+  {
+    len = (rdp.cmd0 & 0xFF) + 1;
+    shift = 32 - ((rdp.cmd0 >> 8) & 0xFF) - len;
+    if (shift < 0) shift = 0;
+  }
+  else
+  {
+    len = rdp.cmd0 & 0xFF;
+    shift = (rdp.cmd0 >> 8) & 0xFF;
+  }
+
+  wxUint32 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);
+    rdp.update |= UPDATE_ZBUF_ENABLED;
+  }
+
+  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 :)
+}
+
+static void uc0_setgeometrymode()
+{
+  rdp.geom_mode |= rdp.cmd1;
+  FRDP("uc0:setgeometrymode %08lx; result: %08lx\n", rdp.cmd1, rdp.geom_mode);
+
+  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_line3d()
+{
+Check_FrameSkip;
+
+  wxUint32 v0 = ((rdp.cmd1 >> 16) & 0xff) / 10;
+  wxUint32 v1 = ((rdp.cmd1 >>  8) & 0xff) / 10;
+  wxUint16 width = (wxUint16)(rdp.cmd1 & 0xFF) + 3;
+
+  VERTEX *v[3] = {
+    &rdp.vtx[v1],
+    &rdp.vtx[v0],
+    &rdp.vtx[v0]
+  };
+  wxUint32 cull_mode = (rdp.flags & CULLMASK) >> CULLSHIFT;
+  rdp.flags |= CULLMASK;
+  rdp.update |= UPDATE_CULL_MODE;
+  rsp_tri1(v, width);
+  rdp.flags ^= CULLMASK;
+  rdp.flags |= cull_mode << CULLSHIFT;
+  rdp.update |= UPDATE_CULL_MODE;
+
+  FRDP("uc0:line3d v0:%d, v1:%d, width:%d\n", v0, v1, width);
+}
+
+static void uc0_tri4 ()
+{
+Check_FrameSkip;
+
+  // c0: 0000 0123, c1: 456789ab
+  // becomes: 405 617 829 a3b
+
+  LRDP("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],
+  };
+
+  int updated = 0;
+
+  if (cull_tri(v))
+    rdp.tri_n ++;
+  else
+  {
+    updated = 1;
+    update ();
+
+    draw_tri (v);
+    rdp.tri_n ++;
+  }
+
+  if (cull_tri(v+3))
+    rdp.tri_n ++;
+  else
+  {
+    if (!updated)
+    {
+      updated = 1;
+      update ();
+    }
+
+    draw_tri (v+3);
+    rdp.tri_n ++;
+  }
+
+  if (cull_tri(v+6))
+    rdp.tri_n ++;
+  else
+  {
+    if (!updated)
+    {
+      updated = 1;
+      update ();
+    }
+
+    draw_tri (v+6);
+    rdp.tri_n ++;
+  }
+
+  if (cull_tri(v+9))
+    rdp.tri_n ++;
+  else
+  {
+    if (!updated)
+    {
+      updated = 1;
+      update ();
+    }
+
+    draw_tri (v+9);
+    rdp.tri_n ++;
+  }
+}
diff --git a/source/gles2glide64/src/Glide64/ucode01.h b/source/gles2glide64/src/Glide64/ucode01.h
new file mode 100755 (executable)
index 0000000..7bd9a07
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+//
+// vertex - loads vertices
+//
+
+static void uc1_vertex()
+{
+Check_FrameSkip;
+
+  int v0 = (rdp.cmd0 >> 17) & 0x7F;     // Current vertex
+  int n = (rdp.cmd0 >> 10) & 0x3F;    // Number to copy
+  rsp_vertex(v0, n);
+}
+
+//
+// tri1 - renders a triangle
+//
+
+static void uc1_tri1()
+{
+Check_FrameSkip;
+
+  if (rdp.skip_drawing)
+  {
+    LRDP("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]
+  };
+  
+  rsp_tri1(v);
+}
+
+static void uc1_tri2 ()
+{
+Check_FrameSkip;
+
+  if (rdp.skip_drawing)
+  {
+    LRDP("uc1:tri2. skipped\n");
+    return;
+  }
+  LRDP("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]
+  };
+  
+  rsp_tri2(v);
+}
+
+static void uc1_line3d()
+{
+Check_FrameSkip;
+
+  if (!settings.force_quad3d && ((rdp.cmd1&0xFF000000) == 0) && ((rdp.cmd0&0x00FFFFFF) == 0))
+  {
+    wxUint16 width = (wxUint16)(rdp.cmd1&0xFF) + 3;
+    
+    FRDP("uc1:line3d width: %d #%d, #%d - %d, %d\n", width, 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]
+    };
+    wxUint32 cull_mode = (rdp.flags & CULLMASK) >> CULLSHIFT;
+    rdp.flags |= CULLMASK;
+    rdp.update |= UPDATE_CULL_MODE;
+    rsp_tri1(v, width);
+    rdp.flags ^= CULLMASK;
+    rdp.flags |= cull_mode << CULLSHIFT;
+    rdp.update |= UPDATE_CULL_MODE;
+  }
+  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]
+    };
+    
+    rsp_tri2(v);
+  }
+}
+
+wxUint32 branch_dl = 0;
+
+static void uc1_rdphalf_1()
+{
+  LRDP("uc1:rdphalf_1\n");
+  branch_dl = rdp.cmd1;
+  rdphalf_1();
+}
+
+static void uc1_branch_z()
+{
+  wxUint32 addr = segoffset(branch_dl);
+  FRDP ("uc1:branch_less_z, addr: %08lx\n", addr);
+  wxUint32 vtx = (rdp.cmd0 & 0xFFF) >> 1;
+  if( fabs(rdp.vtx[vtx].z) <= (rdp.cmd1/*&0xFFFF*/) )
+  {
+    rdp.pc[rdp.pc_i] = addr;
+  }
+}
diff --git a/source/gles2glide64/src/Glide64/ucode02.h b/source/gles2glide64/src/Glide64/ucode02.h
new file mode 100755 (executable)
index 0000000..bb8eeda
--- /dev/null
@@ -0,0 +1,849 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+static void calc_point_light (VERTEX *v, float * vpos)
+{
+Check_FrameSkip;
+
+  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 (wxUint32 l=0; l<rdp.num_lights; l++)
+  {
+    if (rdp.light[l].nonblack)
+    {
+      float lvec[3] = {rdp.light[l].x, rdp.light[l].y, rdp.light[l].z};
+                       lvec[0] -= vpos[0];
+        lvec[1] -= vpos[1];
+        lvec[2] -= vpos[2];
+        float light_len2 = lvec[0]*lvec[0] + lvec[1]*lvec[1] + lvec[2]*lvec[2];
+        float light_len = sqrtf(light_len2);
+#ifdef EXTREME_LOGGING
+        FRDP ("calc_point_light: len: %f, len2: %f\n", light_len, light_len2);
+#endif
+        float at = rdp.light[l].ca + light_len/65535.0f*rdp.light[l].la + light_len2/65535.0f*rdp.light[l].qa;
+        if (at > 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 = (wxUint8)(color[0]*255.0f);
+  v->g = (wxUint8)(color[1]*255.0f);
+  v->b = (wxUint8)(color[2]*255.0f);
+}
+
+static void uc6_obj_rectangle();
+
+static void uc2_vertex ()
+{
+Check_FrameSkip;
+
+  if (!(rdp.cmd0 & 0x00FFFFFF))
+  {
+    uc6_obj_rectangle();
+    return;
+  }
+
+  // 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 (wxUint32 l=0; l<rdp.num_lights; l++)
+    {
+      InverseTransformVector(&rdp.light[l].dir_x, rdp.light_vector[l], rdp.model);
+      NormalizeVector (rdp.light_vector[l]);
+    }
+  }
+
+  wxUint32 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 ("uc2:vertex n: %d, v0: %d, from: %08lx\n", n, v0, addr);
+
+  if (v0 < 0)
+  {
+    RDP_E ("** ERROR: uc2:vertex v0 < 0\n");
+    LRDP("** ERROR: uc2:vertex v0 < 0\n");
+    return;
+  }
+
+  wxUint32 geom_mode = rdp.geom_mode;
+  if ((settings.hacks&hack_Fzero) && (rdp.geom_mode & 0x40000))
+  {
+    if (((short*)gfx.RDRAM)[(((addr) >> 1) + 4)^1] || ((short*)gfx.RDRAM)[(((addr) >> 1) + 5)^1])
+      rdp.geom_mode ^= 0x40000;
+  }
+  #ifdef __ARM_NEON__
+  float32x4_t comb0, comb1, comb2, comb3;
+  float32x4_t v_xyzw;
+  comb0 = vld1q_f32(rdp.combined[0]);
+  comb1 = vld1q_f32(rdp.combined[1]);
+  comb2 = vld1q_f32(rdp.combined[2]);
+  comb3 = vld1q_f32(rdp.combined[3]);
+  #endif
+  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  = ((wxUint16*)gfx.RDRAM)[(((addr+i) >> 1) + 3)^1];
+    v->ou   = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 4)^1];
+    v->ov   = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 5)^1];
+    v->uv_scaled = 0;
+    v->a    = ((wxUint8*)gfx.RDRAM)[(addr+i + 15)^3];
+
+       #ifdef __ARM_NEON__
+       v_xyzw = x*comb0+y*comb1+z*comb2+comb3;
+       //vst1q_f32((float*)v, v_xyzw);
+       v->x=v_xyzw[0];
+       v->y=v_xyzw[1];
+       v->z=v_xyzw[2];
+       v->w=v_xyzw[3];
+       #else
+    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];
+       #endif
+
+    v->uv_calculated = 0xFFFFFFFF;
+    v->screen_translated = 0;
+    v->shade_mod = 0;
+
+    if (fabs(v->w) < 0.001) v->w = 0.001f;
+    v->oow = 1.0f / v->w;
+       #ifdef __ARM_NEON__
+       v_xyzw *= v->oow;
+       v->x_w=v_xyzw[0];
+       v->y_w=v_xyzw[1];
+       v->z_w=v_xyzw[2];
+       #else
+    v->x_w = v->x * v->oow;
+    v->y_w = v->y * v->oow;
+    v->z_w = v->z * v->oow;
+       #endif
+    CalculateFog (v);
+
+
+    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 (v->z_w > 1.0f) v->scr_off |= 32;
+
+    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 & 0x40000)
+        {
+          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
+          {
+            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 = ((wxUint8*)gfx.RDRAM)[(addr+i + 12)^3];
+      v->g = ((wxUint8*)gfx.RDRAM)[(addr+i + 13)^3];
+      v->b = ((wxUint8*)gfx.RDRAM)[(addr+i + 14)^3];
+    }
+#ifdef EXTREME_LOGGING
+    FRDP ("v%d - x: %f, y: %f, z: %f, w: %f, u: %f, v: %f, f: %f, z_w: %f, r=%d, g=%d, b=%d, a=%d\n", i>>4, v->x, v->y, v->z, v->w, v->ou*rdp.tiles[rdp.cur_tile].s_scale, v->ov*rdp.tiles[rdp.cur_tile].t_scale, v->f, v->z_w, v->r, v->g, v->b, v->a);
+#endif
+  }
+  rdp.geom_mode = geom_mode;
+}
+
+static void uc2_modifyvtx ()
+{
+Check_FrameSkip;
+
+  wxUint8 where = (wxUint8)((rdp.cmd0 >> 16) & 0xFF);
+  wxUint16 vtx = (wxUint16)((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 ()
+{
+  wxUint16 vStart = (wxUint16)(rdp.cmd0 & 0xFFFF) >> 1;
+  wxUint16 vEnd = (wxUint16)(rdp.cmd1 & 0xFFFF) >> 1;
+  wxUint32 cond = 0;
+  FRDP ("uc2:culldl start: %d, end: %d\n", vStart, vEnd);
+
+  if (vEnd < vStart) return;
+  for (wxUint16 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;
+  }
+
+  LRDP(" - ");  // specify that the enddl is not a real command
+  uc0_enddl ();
+}
+
+static void uc6_obj_loadtxtr ();
+
+static void uc2_tri1()
+{
+Check_FrameSkip;
+
+  if ((rdp.cmd0 & 0x00FFFFFF) == 0x17)
+  {
+    uc6_obj_loadtxtr ();
+    return;
+  }
+  if (rdp.skip_drawing)
+  {
+    LRDP("uc2:tri1. skipped\n");
+    return;
+  }
+
+  FRDP("uc2: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]
+  };
+
+  rsp_tri1(v);
+}
+
+static void uc6_obj_ldtx_sprite ();
+static void uc6_obj_ldtx_rect ();
+
+static void uc2_quad ()
+{
+Check_FrameSkip;
+
+  if ((rdp.cmd0 & 0x00FFFFFF) == 0x2F)
+  {
+    wxUint32 command = rdp.cmd0>>24;
+    if (command == 0x6)
+    {
+      uc6_obj_ldtx_sprite ();
+      return;
+    }
+    if (command == 0x7)
+    {
+      uc6_obj_ldtx_rect ();
+      return;
+    }
+  }
+
+  if (rdp.skip_drawing)
+  {
+    LRDP("uc2_quad. skipped\n");
+    return;
+  }
+
+  LRDP("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]
+  };
+
+  rsp_tri2(v);
+}
+
+static void uc6_ldtx_rect_r ();
+
+static void uc2_line3d ()
+{
+Check_FrameSkip;
+
+  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]
+    };
+    wxUint16 width = (wxUint16)(rdp.cmd0 + 3)&0xFF;
+    wxUint32 cull_mode = (rdp.flags & CULLMASK) >> CULLSHIFT;
+    rdp.flags |= CULLMASK;
+    rdp.update |= UPDATE_CULL_MODE;
+    rsp_tri1(v, width);
+    rdp.flags ^= CULLMASK;
+    rdp.flags |= cull_mode << CULLSHIFT;
+    rdp.update |= UPDATE_CULL_MODE;
+  }
+}
+
+static void uc2_special3 ()
+{
+  LRDP("uc2:special3\n");
+}
+
+static void uc2_special2 ()
+{
+  LRDP("uc2:special2\n");
+}
+
+static void uc2_dma_io ()
+{
+  LRDP("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
+  wxUint32 clr_mode = (rdp.cmd0 & 0x00DFC9FF) |
+    ((rdp.cmd0 & 0x00000600) << 3) |
+    ((rdp.cmd0 & 0x00200000) >> 12) | 0xFF000000;
+  wxUint32 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;
+    }
+  }
+}
+
+static void uc6_obj_rectangle_r ();
+
+static void uc2_matrix ()
+{
+  if (!(rdp.cmd0 & 0x00FFFFFF))
+  {
+    uc6_obj_rectangle_r();
+    return;
+  }
+  LRDP("uc2:matrix\n");
+
+  DECLAREALIGN16VAR(m[4][4]);
+  load_matrix(m, segoffset(rdp.cmd1));
+
+  wxUint8 command = (wxUint8)((rdp.cmd0 ^ 1) & 0xFF);
+  switch (command)
+  {
+  case 0: // modelview mul nopush
+    LRDP("modelview mul\n");
+    modelview_mul (m);
+    break;
+
+  case 1: // modelview mul push
+    LRDP("modelview mul push\n");
+    modelview_mul_push (m);
+    break;
+
+  case 2: // modelview load nopush
+    LRDP("modelview load\n");
+    modelview_load (m);
+    break;
+
+  case 3: // modelview load push
+    LRDP("modelview load push\n");
+    modelview_load_push (m);
+    break;
+
+  case 4: // projection mul nopush
+  case 5: // projection mul push, can't push projection
+    LRDP("projection mul\n");
+    projection_mul (m);
+    break;
+
+  case 6: // projection load nopush
+  case 7: // projection load push, can't push projection
+    LRDP("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 ()
+{
+  wxUint8 index = (wxUint8)((rdp.cmd0 >> 16) & 0xFF);
+  wxUint16 offset = (wxUint16)(rdp.cmd0 & 0xFFFF);
+  wxUint32 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);
+      }
+
+      LRDP("matrix\n");
+    }
+    break;
+
+  case 0x02:
+    rdp.num_lights = data / 24;
+    rdp.update |= UPDATE_LIGHTS;
+    FRDP ("numlights: %d\n", rdp.num_lights);
+    break;
+
+  case 0x04:
+    if (offset == 0x04)
+    {
+      rdp.clip_ratio = sqrt((float)rdp.cmd1);
+      rdp.update |= UPDATE_VIEWPORT;
+    }
+    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)<BMASK)
+        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);
+
+      //offset must be 0 for move_fog, but it can be non zero in Nushi Zuri 64 - Shiokaze ni Notte
+      //low-level display list has setothermode commands in this place, so this is obviously not move_fog.
+      if (offset == 0x04)
+        rdp.tlut_mode = (data == 0xffffffff) ? 0 : 2; 
+    }
+    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");
+    LRDP("forcemtx - IGNORED\n");
+    break;
+
+  case 0x0e:
+    LRDP("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);
+  }
+}
+
+static void uc6_obj_movemem ();
+
+static void uc2_movemem ()
+{
+  int idx = rdp.cmd0 & 0xFF;
+  wxUint32 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
+    {
+      wxUint32 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
+      wxUint8 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;
+      wxUint32 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;
+      load_matrix(rdp.combined, segoffset(rdp.cmd1));
+
+#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 ()
+{
+  LRDP("uc2:load_ucode\n");
+}
+
+static void uc2_rdphalf_2 ()
+{
+  LRDP("uc2:rdphalf_2\n");
+}
+
+static void uc2_dlist_cnt ()
+{
+  wxUint32 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");
+    LRDP("** 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/source/gles2glide64/src/Glide64/ucode03.h b/source/gles2glide64/src/Glide64/ucode03.h
new file mode 100755 (executable)
index 0000000..b57aaa6
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+//
+// vertex - loads vertices
+//
+
+static void uc3_vertex()
+{
+Check_FrameSkip;
+
+  int v0 = ((rdp.cmd0 >> 16) & 0xFF)/5;      // Current vertex
+  int n = (wxUint16)((rdp.cmd0&0xFFFF) + 1)/0x210;    // Number to copy
+
+  if (v0 >= 32)
+    v0 = 31;
+
+  if ((v0 + n) > 32)
+    n = 32 - v0;
+
+  rsp_vertex(v0, n);
+}
+
+//
+// tri1 - renders a triangle
+//
+
+static void uc3_tri1()
+{
+Check_FrameSkip;
+
+  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]
+  };
+
+  rsp_tri1(v);
+}
+
+static void uc3_tri2 ()
+{
+Check_FrameSkip;
+
+  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]
+  };
+
+  rsp_tri2(v);
+}
+
+static void uc3_quad3d()
+{
+Check_FrameSkip;
+
+  FRDP("uc3: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 & 0xFF)/5],
+    &rdp.vtx[((rdp.cmd1 >> 24) & 0xFF)/5],
+    &rdp.vtx[((rdp.cmd1 >> 8) & 0xFF)/5]
+  };
+
+  rsp_tri2(v);
+}
diff --git a/source/gles2glide64/src/Glide64/ucode04.h b/source/gles2glide64/src/Glide64/ucode04.h
new file mode 100755 (executable)
index 0000000..152ed9a
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+//****************************************************************
+// uCode 4 - RSP SW 2.0D EXT
+//****************************************************************
+
+static void uc4_vertex()
+{
+Check_FrameSkip;
+
+  int v0 = 0;     // Current vertex
+  int n = ((rdp.cmd0 >> 4) & 0xFFF) / 33 + 1; // Number of vertices to copy
+  rsp_vertex(v0, n);
+}
+
+static void uc4_tri1()
+{
+Check_FrameSkip;
+
+  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]
+  };
+
+  rsp_tri1(v);
+}
+
+static void uc4_quad3d()
+{
+Check_FrameSkip;
+
+  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]
+  };
+
+  rsp_tri2(v);
+}
diff --git a/source/gles2glide64/src/Glide64/ucode05.h b/source/gles2glide64/src/Glide64/ucode05.h
new file mode 100755 (executable)
index 0000000..ae87b19
--- /dev/null
@@ -0,0 +1,379 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+int cur_mtx = 0;
+int billboarding = 0;
+int vtx_last = 0;
+wxUint32 dma_offset_mtx = 0;
+wxUint32 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
+  wxUint32 addr = dma_offset_mtx + (segoffset(rdp.cmd1) & BMASK);
+
+  wxUint8 n = (wxUint8)((rdp.cmd0 >> 16) & 0xF);
+  wxUint8 multiply;
+
+  if (n == 0) //DKR
+  {
+    n = (wxUint8)((rdp.cmd0 >> 22) & 0x3);
+    multiply = 0;
+  }
+  else //JF
+  {
+    multiply = (wxUint8)((rdp.cmd0 >> 23) & 0x1);
+  }
+
+  cur_mtx = n;
+
+  FRDP("uc5:matrix - #%d, addr: %08lx\n", n, addr);
+
+  if (multiply)
+  {
+    DECLAREALIGN16VAR(m[4][4]);
+    load_matrix(m, addr);
+    DECLAREALIGN16VAR(m_src[4][4]);
+    memcpy (m_src, rdp.dkrproj[0], 64);
+    MulMatrices(m, m_src, rdp.dkrproj[n]);
+  }
+  else
+  {
+    load_matrix(rdp.dkrproj[n], addr);
+  }
+  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 ()
+{
+Check_FrameSkip;
+
+  wxUint32 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.hacks&hack_Diddy)
+    n++;
+
+  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<first+n; i++)
+  {
+    start = (i-first) * 10;
+    VERTEX *v = &rdp.vtx[i];
+    x   = (float)((short*)gfx.RDRAM)[(((addr+start) >> 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;
+    }
+
+    if (fabs(v->w) < 0.001) v->w = 0.001f;
+    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_mod = 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 (fabs(v->z_w) > 1.0) v->scr_off |= 32;
+
+    v->r = ((wxUint8*)gfx.RDRAM)[(addr+start + 6)^3];
+    v->g = ((wxUint8*)gfx.RDRAM)[(addr+start + 7)^3];
+    v->b = ((wxUint8*)gfx.RDRAM)[(addr+start + 8)^3];
+    v->a = ((wxUint8*)gfx.RDRAM)[(addr+start + 9)^3];
+    CalculateFog (v);
+
+#ifdef EXTREME_LOGGING
+    FRDP ("v%d - x: %f, y: %f, z: %f, w: %f, z_w: %f, r=%d, g=%d, b=%d, a=%d\n", i, v->x, v->y, v->z, v->w, v->z_w, v->r, v->g, v->b, v->a);
+#endif
+  }
+
+  vtx_last += n;
+}
+
+static void uc5_tridma ()
+{
+Check_FrameSkip;
+
+  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
+
+  wxUint32 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; i<num; i++)
+  {
+    start = i << 4;
+    v0 = gfx.RDRAM[addr+start];
+    v1 = gfx.RDRAM[addr+start+1];
+    v2 = gfx.RDRAM[addr+start+2];
+
+    FRDP("tri #%d - %d, %d, %d\n", rdp.tri_n, v0, v1, v2);
+
+    VERTEX *v[3] = {
+      &rdp.vtx[v0],
+        &rdp.vtx[v1],
+        &rdp.vtx[v2]
+    };
+
+    flags = gfx.RDRAM[addr+start+3];
+
+    if (flags & 0x40) { // no cull
+      rdp.flags &= ~CULLMASK;
+      grCullMode (GR_CULL_DISABLE);
+    }
+    else {        // front cull
+      rdp.flags &= ~CULLMASK;
+      if (rdp.view_scale[0] < 0) {
+        rdp.flags |= CULL_BACK;   // agh, backwards culling
+        grCullMode (GR_CULL_POSITIVE);
+      }
+      else {
+        rdp.flags |= CULL_FRONT;
+        grCullMode (GR_CULL_NEGATIVE);
+      }
+    }
+    start += 4;
+
+    v[0]->ou = (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 ();
+
+      draw_tri (v);
+      rdp.tri_n ++;
+    }
+  }
+}
+
+static void uc5_dl_in_mem ()
+{
+  wxUint32 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");
+    LRDP("** 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()
+{
+  LRDP("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)
+    if (((rdp.cmd0>>8)&0xFFFF) == 0x04)
+    {
+      rdp.clip_ratio = sqrt((float)rdp.cmd1);
+      rdp.update |= UPDATE_VIEWPORT;
+    }
+    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/source/gles2glide64/src/Glide64/ucode06.h b/source/gles2glide64/src/Glide64/ucode06.h
new file mode 100755 (executable)
index 0000000..5907ce8
--- /dev/null
@@ -0,0 +1,1742 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+
+// STANDARD DRAWIMAGE - draws a 2d image based on the following structure
+
+static float set_sprite_combine_mode ()
+{
+  if (rdp.cycle_mode == 2)
+  {
+    rdp.tex = 1;
+    rdp.allow_combine = 0;
+    // Now actually combine !
+    GrCombineFunction_t color_source = GR_COMBINE_FUNCTION_LOCAL;
+    if (rdp.tbuff_tex && rdp.tbuff_tex->info.format == GR_TEXFMT_ALPHA_INTENSITY_88)
+               color_source = GR_COMBINE_FUNCTION_LOCAL_ALPHA;
+    cmb.tmu1_func = cmb.tmu0_func = color_source;
+    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;
+  update ();
+
+  rdp.allow_combine = 1;
+
+  // set z buffer mode
+  float Z = 0.0f;
+  if ((rdp.othermode_l & 0x00000030) && rdp.cycle_mode < 2)
+  {
+    if (rdp.zsrc == 1)
+    {
+      Z = rdp.prim_depth;
+    }
+    FRDP ("prim_depth = %d, prim_dz = %d\n", rdp.prim_depth, rdp.prim_dz);
+    Z = ScaleZ(Z);
+
+    if (rdp.othermode_l & 0x00000400)
+      grDepthBiasLevel(rdp.prim_dz);
+  }
+  else
+  {
+    LRDP("z compare not used, using 0\n");
+  }
+
+  grCullMode (GR_CULL_DISABLE);
+  grFogMode (GR_FOG_DISABLE);
+  rdp.update |= UPDATE_CULL_MODE | UPDATE_FOG_ENABLED;
+
+  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;
+  }
+  return Z;
+}
+
+void uc6_sprite2d ();
+
+typedef struct DRAWIMAGE_t {
+  float frameX;
+  float frameY;
+  wxUint16 frameW;
+  wxUint16 frameH;
+  wxUint16 imageX;
+  wxUint16 imageY;
+  wxUint16 imageW;
+  wxUint16 imageH;
+  wxUint32 imagePtr;
+  wxUint8 imageFmt;
+  wxUint8 imageSiz;
+  wxUint16 imagePal;
+  wxUint8 flipX;
+  wxUint8 flipY;
+  float scaleX;
+  float scaleY;
+} DRAWIMAGE;
+
+typedef struct DRAWOBJECT_t {
+  float objX;
+  float objY;
+  float scaleW;
+  float scaleH;
+  short imageW;
+  short imageH;
+
+  wxUint16  imageStride;
+  wxUint16  imageAdrs;
+  wxUint8  imageFmt;
+  wxUint8  imageSiz;
+  wxUint8  imagePal;
+  wxUint8  imageFlags;
+} DRAWOBJECT;
+
+void DrawHiresDepthImage (const DRAWIMAGE & d)
+{
+Check_FrameSkip;
+
+  wxUint16 * src = (wxUint16*)(gfx.RDRAM+d.imagePtr);
+  wxUint16 image[512*512];
+  wxUint16 * 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 }
+  };
+  AddOffset(v, 4);
+  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);
+}
+
+
+void DrawDepthImage (const DRAWIMAGE & d)
+{
+Check_FrameSkip;
+
+  if (!fullscreen || !fb_depth_render_enabled)
+    return;
+  if (d.imageH > d.imageW)
+    return;
+  LRDP("Depth image write\n");
+  if (fb_hwfbe_enabled)
+  {
+    DrawHiresDepthImage(d);
+    return;
+  }
+  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);
+  wxUint16 * src = (wxUint16*)(gfx.RDRAM+d.imagePtr);
+  wxUint16 * dst = new wxUint16[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)
+{
+Check_FrameSkip;
+
+  if (d.imageW == 0 || d.imageH == 0 || d.frameH == 0)   return;
+
+  int x_size, y_size, x_shift, y_shift, line;
+  // choose optimum size for the format/size
+  switch (d.imageSiz)
+  {
+  case 0:
+    if (rdp.tlut_mode < 2)
+    {
+      y_size = 64;
+      y_shift = 6;
+    }
+    else
+    {
+      y_size = 32;
+      y_shift = 5;
+    }
+    x_size = 128;
+    x_shift = 7;
+    line = 8;
+    break;
+  case 1:
+    if (rdp.tlut_mode < 2)
+    {
+      y_size = 64;
+      y_shift = 6;
+    }
+    else
+    {
+      y_size = 32;
+      y_shift = 5;
+    }
+    x_size = 64;
+    x_shift = 6;
+    line = 8;
+    break;
+  case 2:
+    x_size = 64;
+    y_size = 32;
+    x_shift = 6;
+    y_shift = 5;
+    line = 16;
+    break;
+  case 3:
+    x_size = 32;
+    y_size = 16;
+    x_shift = 4;
+    y_shift = 3;
+    line = 16;
+    break;
+  default:
+    FRDP("DrawImage. unknown image size: %d\n", d.imageSiz);
+    return;
+  }
+
+  if (rdp.ci_width == 512 && !no_dlist) //RE2
+  {
+    wxUint16 width = (wxUint16)(*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 ((settings.hacks&hack_PPL) > 0)
+  {
+    if (d.imageY > d.imageH)
+      d.imageY = (d.imageY%d.imageH);
+  }
+  else if ((settings.hacks&hack_Starcraft) > 0)
+  {
+    if (d.imageH%2 == 1)
+      d.imageH -= 1;
+  }
+  else
+  {
+    if ( (d.frameX > 0) && (d.frameW == rdp.ci_width) )
+      d.frameW -= (wxUint16)(2.0f*d.frameX);
+    if ( (d.frameY > 0) && (d.frameH == rdp.ci_height) )
+      d.frameH -= (wxUint16)(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%2)?d.imageW-1: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 = (wxUint8)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;
+
+  const float Z = set_sprite_combine_mode ();
+  if (rdp.cycle_mode == 2)
+    rdp.allow_combine = 0;
+
+  if (fullscreen)
+  {
+    if (rdp.ci_width == 512 && !no_dlist)
+      grClipWindow (0, 0, settings.scr_res_x, settings.scr_res_y);
+    else if (d.scaleX == 1.0f && d.scaleY == 1.0f)
+      grClipWindow (rdp.scissor.ul_x, rdp.scissor.ul_y, rdp.scissor.lr_x, rdp.scissor.lr_y);
+    else
+      grClipWindow (rdp.scissor.ul_x, rdp.scissor.ul_y, min(rdp.scissor.lr_x, (wxUint32)((d.frameX+d.imageW/d.scaleX+0.5f)*rdp.scale_x)), min(rdp.scissor.lr_y, (wxUint32)((d.frameY+d.imageH/d.scaleY+0.5f)*rdp.scale_y)));
+    rdp.update |=  UPDATE_SCISSOR;
+  }
+
+  // Texture ()
+  rdp.cur_tile = 0;
+
+  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)<<y_shift);
+  while (cb_v >= d.imageH) cb_v -= d.imageH;
+  tb_v = cb_v;
+  rdp.bg_image_height = d.imageH;
+
+  while (1)
+  {
+    cur_wrap_u = min_wrap_u + 1;
+    cur_u = min_256_u + 1;
+
+    // calculate intersection with this point
+    nlr_v = min (min (cur_wrap_v*d.imageH, (cur_v<<y_shift)), lr_v);
+    nlr_y = my * nlr_v + by;
+
+    nul_u = ul_u;
+    nul_x = ul_x;
+    cb_u = ((cur_u-1)<<x_shift);
+    while (cb_u >= 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<<x_shift)), lr_u);
+      nlr_x = mx * nlr_u + bx;
+
+      // ** Load the texture, constant portions have been set above
+      // SetTileSize ()
+      rdp.tiles[0].ul_s = tb_u;
+      rdp.tiles[0].ul_t = tb_v;
+      rdp.tiles[0].lr_s = tb_u+x_size-1;
+      rdp.tiles[0].lr_t = tb_v+y_size-1;
+
+      // LoadTile ()
+      rdp.cmd0 = ((int)rdp.tiles[0].ul_s << 14) | ((int)rdp.tiles[0].ul_t << 2);
+      rdp.cmd1 = ((int)rdp.tiles[0].lr_s << 14) | ((int)rdp.tiles[0].lr_t << 2);
+      rdp_loadtile ();
+
+      TexCache ();
+      // **
+
+      ful_u = (float)nul_u - cb_u;
+      flr_u = (float)nlr_u - cb_u;
+      ful_v = (float)nul_v - cb_v;
+      flr_v = (float)nlr_v - cb_v;
+
+      ful_u *= rdp.cur_cache[0]->c_scl_x;
+      ful_v *= rdp.cur_cache[0]->c_scl_y;
+      flr_u *= rdp.cur_cache[0]->c_scl_x;
+      flr_v *= rdp.cur_cache[0]->c_scl_y;
+
+      ful_x = nul_x * rdp.scale_x + rdp.offset_x;
+      flr_x = nlr_x * rdp.scale_x + rdp.offset_x;
+      ful_y = nul_y * rdp.scale_y + rdp.offset_y;
+      flr_y = nlr_y * rdp.scale_y + rdp.offset_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)
+            grDrawVertexArrayContiguous (GR_TRIANGLE_STRIP, 4, v, sizeof(VERTEX));
+
+          if (_debugger.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;
+        LRDP("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<<x_shift)) cur_u ++;
+      if (nlr_u == lr_u) break;
+      nul_u = nlr_u;
+      nul_x = nlr_x;
+    }
+
+    tb_v += y_size - (y_size-(nlr_v-cb_v));
+    cb_v = nlr_v;
+    if (nlr_v == cur_wrap_v*d.imageH) {
+      cur_wrap_v ++;
+      tb_v = 0;
+    }
+    if (nlr_v == (cur_v<<y_shift)) cur_v ++;
+    if (nlr_v == lr_v) break;
+    nul_v = nlr_v;
+    nul_y = nlr_y;
+  }
+
+  rdp.allow_combine = 1;
+  rdp.bg_image_height = 0xFFFF;
+}
+
+void DrawHiresImage(DRAWIMAGE & d, int screensize = FALSE)
+{
+Check_FrameSkip;
+
+  if (!fullscreen)
+    return;
+  TBUFF_COLOR_IMAGE *tbuff_tex = rdp.tbuff_tex;
+  if (rdp.motionblur)
+    rdp.tbuff_tex = &(rdp.texbufs[rdp.cur_tex_buf^1].images[0]);
+  else if (rdp.tbuff_tex == 0)
+    return;
+  FRDP("DrawHiresImage. fb format=%d\n", rdp.tbuff_tex->info.format);
+
+  setTBufTex(rdp.tbuff_tex->t_mem, rdp.tbuff_tex->width << rdp.tbuff_tex->size >> 1);
+
+  const float Z = set_sprite_combine_mode ();
+  grClipWindow (0, 0, settings.res_x, settings.res_y);
+
+  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.hacks&hack_PPL))
+  {
+    if ( (d.frameX > 0) && (d.frameW == rdp.ci_width) )
+      d.frameW -= (wxUint16)(2.0f*d.frameX);
+    if ( (d.frameY > 0) && (d.frameH == rdp.ci_height) )
+      d.frameH -= (wxUint16)(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.15f;
+    ul_v = 0.15f;
+    lr_x = rdp.tbuff_tex->scr_width;
+    lr_y = rdp.tbuff_tex->scr_height;
+    lr_u = rdp.tbuff_tex->lr_u;
+    lr_v = rdp.tbuff_tex->lr_v;
+  }
+  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.tbuff_tex->u_scale;
+    lr_u *= rdp.tbuff_tex->u_scale;
+    ul_v *= rdp.tbuff_tex->v_scale;
+    lr_v *= rdp.tbuff_tex->v_scale;
+    ul_u = max(0.15f, ul_u);
+    ul_v = max(0.15f, ul_v);
+    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);
+    AddOffset(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_SCISSOR;
+    if (_debugger.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;
+  rdp.tbuff_tex = tbuff_tex;
+
+}
+
+//****************************************************************
+
+
+struct MAT2D {
+  float A, B, C, D;
+  float X, Y;
+  float BaseScaleX;
+  float BaseScaleY;
+} mat_2d = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f};
+
+static void uc6_read_background_data (DRAWIMAGE & d, bool bReadScale)
+{
+  wxUint32 addr = segoffset(rdp.cmd1) >> 1;
+
+  d.imageX      = (((wxUint16 *)gfx.RDRAM)[(addr+0)^1] >> 5);   // 0
+  d.imageW      = (((wxUint16 *)gfx.RDRAM)[(addr+1)^1] >> 2);   // 1
+  d.frameX      = ((short*)gfx.RDRAM)[(addr+2)^1] / 4.0f;       // 2
+  d.frameW      = ((wxUint16 *)gfx.RDRAM)[(addr+3)^1] >> 2;             // 3
+
+  d.imageY      = (((wxUint16 *)gfx.RDRAM)[(addr+4)^1] >> 5);   // 4
+  d.imageH      = (((wxUint16 *)gfx.RDRAM)[(addr+5)^1] >> 2);   // 5
+  d.frameY      = ((short*)gfx.RDRAM)[(addr+6)^1] / 4.0f;       // 6
+  d.frameH      = ((wxUint16 *)gfx.RDRAM)[(addr+7)^1] >> 2;             // 7
+
+  d.imagePtr    = segoffset(((wxUint32*)gfx.RDRAM)[(addr+8)>>1]);       // 8,9
+  d.imageFmt    = ((wxUint8 *)gfx.RDRAM)[(((addr+11)<<1)+0)^3]; // 11
+  d.imageSiz    = ((wxUint8 *)gfx.RDRAM)[(((addr+11)<<1)+1)^3]; // |
+  d.imagePal    = ((wxUint16 *)gfx.RDRAM)[(addr+12)^1]; // 12
+  wxUint16 imageFlip = ((wxUint16 *)gfx.RDRAM)[(addr+13)^1];    // 13;
+  d.flipX       = (wxUint8)imageFlip&0x01;
+
+  if (bReadScale)
+  {
+    d.scaleX      = ((short *)gfx.RDRAM)[(addr+14)^1] / 1024.0f;  // 14
+    d.scaleY      = ((short *)gfx.RDRAM)[(addr+15)^1] / 1024.0f;  // 15
+  }
+  else
+    d.scaleX = d.scaleY = 1.0f;
+
+  d.flipY       = 0;
+  int imageYorig= ((int *)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);
+}
+
+static void uc6_bg (bool bg_1cyc)
+{
+  static const char *strFuncNames[] = {"uc6:bg_1cyc", "uc6:bg_copy"};
+  const char *strFuncName =  bg_1cyc ? strFuncNames[0] : strFuncNames[1];
+  if (rdp.skip_drawing)
+  {
+    FRDP("%s skipped\n", strFuncName);
+    return;
+  }
+  FRDP ("%s #%d, #%d\n", strFuncName, rdp.tri_n, rdp.tri_n+1);
+
+  DRAWIMAGE d;
+  uc6_read_background_data(d, bg_1cyc);
+
+  if (fb_hwfbe_enabled && FindTextureBuffer(d.imagePtr, d.imageW))
+  {
+    DrawHiresImage(d);
+    return;
+  }
+
+  if (settings.ucode == ucode_F3DEX2 || (settings.hacks&hack_PPL))
+  {
+    if ( (d.imagePtr != rdp.cimg) && (d.imagePtr != rdp.ocimg) && d.imagePtr) //can't draw from framebuffer
+      DrawImage (d);
+    else
+    {
+      FRDP("%s skipped\n", strFuncName);
+    }
+  }
+  else
+  {
+    DrawImage (d);
+  }
+}
+
+static void uc6_bg_1cyc ()
+{
+  uc6_bg(true);
+}
+
+static void uc6_bg_copy ()
+{
+  uc6_bg(false);
+}
+
+static void draw_split_triangle(VERTEX **vtx)
+{
+Check_FrameSkip;
+
+  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 = (wxUint8)(v1->b + (v2->b - v1->b) * percent);
+          rdp.vtxbuf[index].g = (wxUint8)(v1->g + (v2->g - v1->g) * percent);
+          rdp.vtxbuf[index].r = (wxUint8)(v1->r + (v2->r - v1->r) * percent);
+          rdp.vtxbuf[index++].a = (wxUint8)(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 = (wxUint8)(v2->b + (v1->b - v2->b) * percent);
+          rdp.vtxbuf[index].g = (wxUint8)(v2->g + (v1->g - v2->g) * percent);
+          rdp.vtxbuf[index].r = (wxUint8)(v2->r + (v1->r - v2->r) * percent);
+          rdp.vtxbuf[index++].a = (wxUint8)(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; i<rdp.n_global; i++)
+    {
+      j = i+1;
+      if (j == rdp.n_global) j = 0;
+
+      VERTEX *v1 = &rdp.vtxbuf2[i];
+      VERTEX *v2 = &rdp.vtxbuf2[j];
+
+      // ** Right plane **
+      if (v1->u0 <= 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 = (wxUint8)(v1->b + (v2->b - v1->b) * percent);
+          rdp.vtxbuf[index].g = (wxUint8)(v1->g + (v2->g - v1->g) * percent);
+          rdp.vtxbuf[index].r = (wxUint8)(v1->r + (v2->r - v1->r) * percent);
+          rdp.vtxbuf[index++].a = (wxUint8)(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 = (wxUint8)(v2->b + (v1->b - v2->b) * percent);
+          rdp.vtxbuf[index].g = (wxUint8)(v2->g + (v1->g - v2->g) * percent);
+          rdp.vtxbuf[index].r = (wxUint8)(v2->r + (v1->r - v2->r) * percent);
+          rdp.vtxbuf[index++].a = (wxUint8)(v2->a + (v1->a - v2->a) * percent);
+
+          // Save the in point
+          rdp.vtxbuf[index++] = *v2;
+        }
+      }
+    }
+    rdp.n_global = index;
+
+    do_triangle_stuff_2 ();
+  }
+}
+
+static void uc6_draw_polygons (VERTEX v[4])
+{
+Check_FrameSkip;
+
+  AllowShadeMods (v, 4);
+  for (int s = 0; s < 4; s++)
+    apply_shade_mods (&(v[s]));
+  AddOffset(v, 4);
+
+  // Set vertex buffers
+  if (rdp.cur_cache[0] && rdp.cur_cache[0]->splits > 1)
+  {
+    VERTEX *vptr[3];
+    int i;
+    for (i = 0; i < 3; i++)
+      vptr[i] = &v[i];
+    draw_split_triangle(vptr);
+
+    rdp.tri_n ++;
+    for (i = 0; i < 3; i++)
+      vptr[i] = &v[i+1];
+    draw_split_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_read_object_data (DRAWOBJECT & d)
+{
+  wxUint32 addr = segoffset(rdp.cmd1) >> 1;
+
+  d.objX            = ((short*)gfx.RDRAM)[(addr+0)^1] / 4.0f;               // 0
+  d.scaleW  = ((wxUint16 *)gfx.RDRAM)[(addr+1)^1] / 1024.0f;        // 1
+  d.imageW  = ((short*)gfx.RDRAM)[(addr+2)^1] >> 5;                 // 2, 3 is padding
+  d.objY            = ((short*)gfx.RDRAM)[(addr+4)^1] / 4.0f;               // 4
+  d.scaleH  = ((wxUint16 *)gfx.RDRAM)[(addr+5)^1] / 1024.0f;        // 5
+  d.imageH  = ((short*)gfx.RDRAM)[(addr+6)^1] >> 5;                 // 6, 7 is padding
+
+  d.imageStride = ((wxUint16 *)gfx.RDRAM)[(addr+8)^1];                  // 8
+  d.imageAdrs           = ((wxUint16 *)gfx.RDRAM)[(addr+9)^1];                  // 9
+  d.imageFmt             = ((wxUint8 *)gfx.RDRAM)[(((addr+10)<<1)+0)^3]; // 10
+  d.imageSiz             = ((wxUint8 *)gfx.RDRAM)[(((addr+10)<<1)+1)^3]; // |
+  d.imagePal             = ((wxUint8 *)gfx.RDRAM)[(((addr+10)<<1)+2)^3]; // 11
+  d.imageFlags   = ((wxUint8 *)gfx.RDRAM)[(((addr+10)<<1)+3)^3]; // |
+
+  if (d.imageW < 0)
+    d.imageW = (short)rdp.scissor_o.lr_x - (short)d.objX - d.imageW;
+  if (d.imageH < 0)
+    d.imageH = (short)rdp.scissor_o.lr_y - (short)d.objY - d.imageH;
+
+  FRDP ("#%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,
+    d.objX, d.scaleW, d.imageW, d.objY, d.scaleH, d.imageH, d.imageSiz, d.imageFmt);
+}
+
+static void uc6_init_tile(const DRAWOBJECT & d)
+{
+  // SetTile ()
+  TILE *tile = &rdp.tiles[0];
+  tile->format = d.imageFmt;      // RGBA
+  tile->size = d.imageSiz;                // 16-bit
+  tile->line = d.imageStride;
+  tile->t_mem = d.imageAdrs;
+  tile->palette = 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;
+
+  // SetTileSize ()
+  rdp.tiles[0].ul_s = 0;
+  rdp.tiles[0].ul_t = 0;
+  rdp.tiles[0].lr_s = (d.imageW>0)?d.imageW-1:0;
+  rdp.tiles[0].lr_t = (d.imageH>0)?d.imageH-1:0;
+}
+
+static void uc6_obj_rectangle ()
+{
+Check_FrameSkip;
+
+  LRDP ("uc6:obj_rectangle ");
+  DRAWOBJECT d;
+  uc6_read_object_data(d);
+
+  if (d.imageAdrs > 4096)
+  {
+    FRDP("tmem: %08lx is out of bounds! return\n", d.imageAdrs);
+    return;
+  }
+  if (!rdp.s2dex_tex_loaded)
+  {
+    LRDP("Texture was not loaded! return\n");
+    return;
+  }
+
+  uc6_init_tile(d);
+
+  float Z = set_sprite_combine_mode ();
+
+  float ul_x = d.objX;
+  float lr_x = d.objX + d.imageW/d.scaleW;
+  float ul_y = d.objY;
+  float lr_y = d.objY + d.imageH/d.scaleH;
+  float ul_u, lr_u, ul_v, 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;
+  }
+
+  if (d.imageFlags&0x01) //flipS
+  {
+    ul_u = lr_u;
+    lr_u = 0.5f;
+  }
+  else
+    ul_u = 0.5f;
+  if (d.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 }
+  };
+
+  for (int i=0; i<4; i++)
+  {
+    v[i].x *= rdp.scale_x;
+    v[i].y *= rdp.scale_y;
+  }
+
+  uc6_draw_polygons (v);
+}
+
+static void uc6_obj_sprite ()
+{
+Check_FrameSkip;
+
+  LRDP ("uc6:obj_sprite ");
+  DRAWOBJECT d;
+  uc6_read_object_data(d);
+  uc6_init_tile(d);
+
+  float Z = set_sprite_combine_mode ();
+
+  float ul_x = d.objX;
+  float lr_x = d.objX + d.imageW/d.scaleW;
+  float ul_y = d.objY;
+  float lr_y = d.objY + d.imageH/d.scaleH;
+  float ul_u, lr_u, ul_v, 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;
+  }
+
+  if (d.imageFlags&0x01) //flipS
+  {
+    ul_u = lr_u;
+    lr_u = 0.5f;
+  }
+  else
+    ul_u = 0.5f;
+  if (d.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 }
+  };
+
+  for (int 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);
+}
+
+static void uc6_obj_movemem ()
+{
+  LRDP("uc6:obj_movemem\n");
+
+  int index = rdp.cmd0 & 0xFFFF;
+  wxUint32 addr = segoffset(rdp.cmd1) >> 1;
+
+  if (index == 0) {     // movemem matrix
+    mat_2d.A = ((int*)gfx.RDRAM)[(addr+0)>>1] / 65536.0f;
+    mat_2d.B = ((int*)gfx.RDRAM)[(addr+2)>>1] / 65536.0f;
+    mat_2d.C = ((int*)gfx.RDRAM)[(addr+4)>>1] / 65536.0f;
+    mat_2d.D = ((int*)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 = ((wxUint16*)gfx.RDRAM)[(addr+10)^1] / 1024.0f;
+    mat_2d.BaseScaleY = ((wxUint16*)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 = ((wxUint16*)gfx.RDRAM)[(addr+2)^1] / 1024.0f;
+    mat_2d.BaseScaleY = ((wxUint16*)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 ()
+{
+  LRDP("uc6:select_dl\n");
+  RDP_E ("uc6:select_dl\n");
+}
+
+static void uc6_obj_rendermode ()
+{
+  LRDP("uc6:obj_rendermode\n");
+  RDP_E ("uc6:obj_rendermode\n");
+}
+
+static wxUint16 uc6_yuv_to_rgba(wxUint8 y, wxUint8 u, wxUint8 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;
+
+  wxUint16 c = (wxUint16)(((wxUint16)(r) << 11) |
+    ((wxUint16)(g) << 6) |
+    ((wxUint16)(b) << 1) | 1);
+  return c;
+}
+
+static void uc6_DrawYUVImageToFrameBuffer(wxUint16 ul_x, wxUint16 ul_y, wxUint16 lr_x, wxUint16 lr_y)
+{
+Check_FrameSkip;
+
+  FRDP ("uc6:DrawYUVImageToFrameBuffer ul_x%d, ul_y%d, lr_x%d, lr_y%d\n", ul_x, ul_y, lr_x, lr_y);
+  wxUint32 ci_width = rdp.ci_width;
+  wxUint32 ci_height = rdp.ci_lower_bound;
+  if (ul_x >= ci_width)
+    return;
+  if (ul_y >= ci_height)
+    return;
+  wxUint32 width = 16, height = 16;
+  if (lr_x > ci_width)
+    width = ci_width - ul_x;
+  if (lr_y > ci_height)
+    height = ci_height - ul_y;
+  wxUint32 * mb = (wxUint32*)(gfx.RDRAM+rdp.timg.addr); //pointer to the first macro block
+  wxUint16 * dst = (wxUint16*)(gfx.RDRAM+rdp.cimg);
+  dst += ul_x + ul_y * ci_width;
+  //yuv macro block contains 16x16 texture. we need to put it in the proper place inside cimg
+  for (wxUint16 h = 0; h < 16; h++)
+  {
+    for (wxUint16 w = 0; w < 16; w+=2)
+    {
+      wxUint32 t = *(mb++); //each wxUint32 contains 2 pixels
+      if ((h < height) && (w < width)) //clipping. texture image may be larger than color image
+      {
+        wxUint8 y0 = (wxUint8)t&0xFF;
+        wxUint8 v  = (wxUint8)(t>>8)&0xFF;
+        wxUint8 y1 = (wxUint8)(t>>16)&0xFF;
+        wxUint8 u  = (wxUint8)(t>>24)&0xFF;
+        *(dst++) = uc6_yuv_to_rgba(y0, u, v);
+        *(dst++) = uc6_yuv_to_rgba(y1, u, v);
+      }
+    }
+    dst += rdp.ci_width - 16;
+  }
+}
+
+static void uc6_obj_rectangle_r ()
+{
+Check_FrameSkip;
+
+  LRDP ("uc6:obj_rectangle_r ");
+  DRAWOBJECT d;
+  uc6_read_object_data(d);
+
+  if (d.imageFmt == 1 && (settings.hacks&hack_Ogre64)) //Ogre Battle needs to copy YUV texture to frame buffer
+  {
+    float ul_x = d.objX/mat_2d.BaseScaleX + mat_2d.X;
+    float lr_x = (d.objX + d.imageW/d.scaleW)/mat_2d.BaseScaleX + mat_2d.X;
+    float ul_y = d.objY/mat_2d.BaseScaleY + mat_2d.Y;
+    float lr_y = (d.objY + d.imageH/d.scaleH)/mat_2d.BaseScaleY + mat_2d.Y;
+    uc6_DrawYUVImageToFrameBuffer((wxUint16)ul_x, (wxUint16)ul_y, (wxUint16)lr_x, (wxUint16)lr_y);
+    rdp.tri_n += 2;
+    return;
+  }
+
+  uc6_init_tile(d);
+
+  float Z = set_sprite_combine_mode ();
+
+  float ul_x = d.objX/mat_2d.BaseScaleX;
+  float lr_x = (d.objX + d.imageW/d.scaleW)/mat_2d.BaseScaleX;
+  float ul_y = d.objY/mat_2d.BaseScaleY;
+  float lr_y = (d.objY + d.imageH/d.scaleH)/mat_2d.BaseScaleY;
+  float ul_u, lr_u, ul_v, 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;
+  }
+
+  if (d.imageFlags&0x01) //flipS
+  {
+    ul_u = lr_u;
+    lr_u = 0.5f;
+  }
+  else
+    ul_u = 0.5f;
+  if (d.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 }
+  };
+
+  for (int 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);
+}
+
+static void uc6_obj_loadtxtr ()
+{
+Check_FrameSkip;
+
+  LRDP("uc6:obj_loadtxtr ");
+  rdp.s2dex_tex_loaded = TRUE;
+  rdp.update |= UPDATE_TEXTURE;
+
+  wxUint32 addr = segoffset(rdp.cmd1) >> 1;
+  wxUint32 type = ((wxUint32*)gfx.RDRAM)[(addr + 0) >> 1];                      // 0, 1
+
+  if (type == 0x00000030) {     // TLUT
+    wxUint32 image              = segoffset(((wxUint32*)gfx.RDRAM)[(addr + 2) >> 1]);   // 2, 3
+    wxUint16  phead             = ((wxUint16 *)gfx.RDRAM)[(addr + 4) ^ 1] - 256;        // 4
+    wxUint16  pnum              = ((wxUint16 *)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
+    wxUint32 image              = segoffset(((wxUint32*)gfx.RDRAM)[(addr + 2) >> 1]);   // 2, 3
+    wxUint16  tmem              = ((wxUint16 *)gfx.RDRAM)[(addr + 4) ^ 1];      // 4
+    wxUint16  tsize             = ((wxUint16 *)gfx.RDRAM)[(addr + 5) ^ 1];      // 5
+    wxUint16  tline             = ((wxUint16 *)gfx.RDRAM)[(addr + 6) ^ 1];      // 6
+
+    FRDP ("addr: %08lx, tmem: %08lx, size: %d\n", image, tmem, tsize);
+    rdp.timg.addr = image;
+    rdp.timg.width = 1;
+    rdp.timg.size = 1;
+
+    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)
+  {
+    wxUint32 image              = segoffset(((wxUint32*)gfx.RDRAM)[(addr + 2) >> 1]);   // 2, 3
+    wxUint16  tmem              = ((wxUint16 *)gfx.RDRAM)[(addr + 4) ^ 1];      // 4
+    wxUint16  twidth    = ((wxUint16 *)gfx.RDRAM)[(addr + 5) ^ 1];      // 5
+    wxUint16  theight   = ((wxUint16 *)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.timg.size = 1;
+
+    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);
+  }
+}
+
+static void uc6_obj_ldtx_sprite ()
+{
+  LRDP("uc6:obj_ldtx_sprite\n");
+
+  wxUint32 addr = rdp.cmd1;
+  uc6_obj_loadtxtr ();
+  rdp.cmd1 = addr + 24;
+  uc6_obj_sprite ();
+}
+
+static void uc6_obj_ldtx_rect ()
+{
+  LRDP("uc6:obj_ldtx_rect\n");
+
+  wxUint32 addr = rdp.cmd1;
+  uc6_obj_loadtxtr ();
+  rdp.cmd1 = addr + 24;
+  uc6_obj_rectangle ();
+}
+
+static void uc6_ldtx_rect_r ()
+{
+  LRDP("uc6:ldtx_rect_r\n");
+
+  wxUint32 addr = rdp.cmd1;
+  uc6_obj_loadtxtr ();
+  rdp.cmd1 = addr + 24;
+  uc6_obj_rectangle_r ();
+}
+
+static void uc6_loaducode ()
+{
+  LRDP("uc6:load_ucode\n");
+  RDP_E ("uc6:load_ucode\n");
+
+  // copy the microcode data
+  wxUint32 addr = segoffset(rdp.cmd1);
+  wxUint32 size = (rdp.cmd0 & 0xFFFF) + 1;
+  memcpy (microcode, gfx.RDRAM+addr, size);
+
+  microcheck ();
+}
+
+void uc6_sprite2d ()
+{
+Check_FrameSkip;
+
+  wxUint32 a = rdp.pc[rdp.pc_i] & BMASK;
+  wxUint32 cmd0 = ((wxUint32*)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);
+  wxUint32 addr = segoffset(rdp.cmd1) >> 1;
+  DRAWIMAGE d;
+
+  d.imagePtr    = segoffset(((wxUint32*)gfx.RDRAM)[(addr+0)>>1]);       // 0,1
+  wxUint16 stride = (((wxUint16 *)gfx.RDRAM)[(addr+4)^1]);      // 4
+  d.imageW      = (((wxUint16 *)gfx.RDRAM)[(addr+5)^1]);        // 5
+  d.imageH      = (((wxUint16 *)gfx.RDRAM)[(addr+6)^1]);        // 6
+  d.imageFmt    = ((wxUint8 *)gfx.RDRAM)[(((addr+7)<<1)+0)^3];  // 7
+  d.imageSiz    = ((wxUint8 *)gfx.RDRAM)[(((addr+7)<<1)+1)^3];  // |
+  d.imagePal    = 0;
+  d.imageX      = (((wxUint16 *)gfx.RDRAM)[(addr+8)^1]);        // 8
+  d.imageY      = (((wxUint16 *)gfx.RDRAM)[(addr+9)^1]);        // 9
+  wxUint32 tlut         = ((wxUint32*)gfx.RDRAM)[(addr + 2) >> 1];      // 2, 3
+  //low-level implementation of sprite2d apparently calls setothermode command to set tlut mode
+  //However, description of sprite2d microcode just says that
+  //TlutPointer should be Null when CI images will not be used.
+  //HLE implementation sets rdp.tlut_mode=2 if TlutPointer is not null, and rdp.tlut_mode=0 otherwise
+  //Alas, it is not sufficient, since WCW Nitro uses non-Null TlutPointer for rgba textures.
+  //So, additional check added.
+  if (tlut)
+  {
+    load_palette (segoffset(tlut), 0, 256);
+    if (d.imageFmt > 0)
+      rdp.tlut_mode = 2;
+    else
+      rdp.tlut_mode = 0;
+  }
+  else
+  {
+    rdp.tlut_mode = 0;
+  }
+
+  if (d.imageW == 0)
+    return;//     d.imageW = stride;
+
+  cmd0 = ((wxUint32*)gfx.RDRAM)[a>>2]; //check next command
+  while (1)
+  {
+    if ( (cmd0>>24) == 0xBE )
+    {
+      wxUint32 cmd1 = ((wxUint32*)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;
+      //the code below causes wrong background height in super robot spirit, so it is disabled.
+      //need to find, for which game this hack was made
+      //if( (cmd1&0xFFFF) < 0x100 )
+      //  d.scaleY = d.scaleX;
+      d.flipX = (wxUint8)((cmd0>>8)&0xFF);
+      d.flipY = (wxUint8)(cmd0&0xFF);
+
+      a = rdp.pc[rdp.pc_i] & BMASK;
+      rdp.pc[rdp.pc_i] = (a+8) & BMASK;
+      cmd0 = ((wxUint32*)gfx.RDRAM)[a>>2]; //check next command
+    }
+    if ( (cmd0>>24) == 0xBD )
+    {
+      wxUint32 cmd1 = ((wxUint32*)gfx.RDRAM)[(a>>2)+1];
+
+      d.frameX  = ((short)((cmd1>>16)&0xFFFF)) / 4.0f;
+      d.frameY  = ((short)(cmd1&0xFFFF)) / 4.0f;
+      d.frameW    = (wxUint16) (d.imageW / d.scaleX);
+      d.frameH    = (wxUint16) (d.imageH / d.scaleY);
+      if (settings.hacks&hack_WCWnitro)
+      {
+        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;
+    }
+
+    const wxUint32 texsize = (d.imageW * d.imageH) << d.imageSiz >> 1;
+    const wxUint32 maxTexSize = rdp.tlut_mode < 2 ? 4096 : 2048;
+
+    if (texsize > maxTexSize)
+    {
+      if (d.scaleX != 1)
+        d.scaleX *= (float)stride/(float)d.imageW;
+      d.imageW  = stride;
+      d.imageH  += d.imageY;
+      DrawImage (d);
+    }
+    else
+    {
+      wxUint16 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 } };
+
+        for (int 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]));
+        AddOffset(v, 4);
+
+        // 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_split_triangle(vptr);
+
+          rdp.tri_n ++;
+          for (i = 0; i < 3; i++)
+            vptr[i] = &v[i+1];
+          draw_split_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 = ((wxUint32*)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/source/gles2glide64/src/Glide64/ucode07.h b/source/gles2glide64/src/Glide64/ucode07.h
new file mode 100755 (executable)
index 0000000..51bc921
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+//
+// 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!
+//****************************************************************
+
+wxUint32 pd_col_addr = 0;
+
+static void uc7_colorbase ()
+{
+       LRDP("uc7_colorbase\n");
+       pd_col_addr = segoffset(rdp.cmd1);
+}
+
+
+typedef struct 
+{
+       short y;
+       short x;
+       wxUint16 idx;
+
+       short z;
+
+       short t;
+       short s;
+
+} vtx_uc7;
+
+static void uc7_vertex ()
+{
+Check_FrameSkip;
+
+  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 (wxUint32 l=0; l<rdp.num_lights; l++)
+    {
+         InverseTransformVector(&rdp.light[l].dir_x, rdp.light_vector[l], rdp.model);
+      NormalizeVector (rdp.light_vector[l]);
+    }
+  }
+
+  wxUint32 addr = segoffset(rdp.cmd1);
+  wxUint32 v0, i, n;
+  float x, y, z;
+
+  rdp.v0 = v0 = (rdp.cmd0 & 0x0F0000) >> 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;
+    v->ov   = (float)vertex->t;
+    v->uv_scaled = 0;
+
+#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];
+
+
+    if (fabs(v->w) < 0.001) v->w = 0.001f;
+    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;
+
+       wxUint8 *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/source/gles2glide64/src/Glide64/ucode08.h b/source/gles2glide64/src/Glide64/ucode08.h
new file mode 100755 (executable)
index 0000000..6ab6c54
--- /dev/null
@@ -0,0 +1,626 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+//
+// January 2004 Created by Gonetz (Gonetz@ngs.ru)
+//
+//****************************************************************
+
+wxUint32 uc8_normale_addr = 0;
+float uc8_coord_mod[16];
+
+static void uc8_vertex ()
+{
+Check_FrameSkip;
+
+       if (rdp.update & UPDATE_MULT_MAT)
+       {
+               rdp.update ^= UPDATE_MULT_MAT;
+       MulMatrices(rdp.model, rdp.proj, rdp.combined);
+       }
+
+       wxUint32 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");
+               LRDP("** 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 (wxUint32 l=0; l<rdp.num_lights; l++)
+               {
+                       InverseTransformVector(&rdp.light[l].dir_x, rdp.light_vector[l], rdp.model);
+                       NormalizeVector (rdp.light_vector[l]);
+#ifdef EXTREME_LOGGING
+                       FRDP("light_vector[%d] x: %f, y: %f, z: %f\n", l, rdp.light_vector[l][0], rdp.light_vector[l][1], rdp.light_vector[l][2]);
+#endif
+               }
+       }
+       //*/
+    #ifdef __ARM_NEON__
+    float32x4_t comb0, comb1, comb2, comb3;
+    float32x4_t v_xyzw;
+    comb0 = vld1q_f32(rdp.combined[0]);
+    comb1 = vld1q_f32(rdp.combined[1]);
+    comb2 = vld1q_f32(rdp.combined[2]);
+    comb3 = vld1q_f32(rdp.combined[3]);
+       
+       float32x4_t uc8_8_11, uc8_12_15;
+       uc8_8_11 = vld1q_f32(uc8_coord_mod+8);
+       uc8_12_15 = vld1q_f32(uc8_coord_mod+12);
+       float32x4_t unite={1.0f, 1.0f, 1.0f, 1.0f};
+       
+       float32x4_t rdplight[12], rdpcolor[12];
+       for (i=0; i<rdp.num_lights; i++) {
+               rdplight[i] = vld1q_f32(&rdp.light[i].x);
+               rdpcolor[i] = vld1q_f32(&rdp.light[i].r);
+       }
+       
+    #endif
+       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  = ((wxUint16*)gfx.RDRAM)[(((addr+i) >> 1) + 3)^1];
+               v->ou   = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 4)^1];
+               v->ov   = (float)((short*)gfx.RDRAM)[(((addr+i) >> 1) + 5)^1];
+        v->uv_scaled = 0;
+               v->a    = ((wxUint8*)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
+               #ifdef __ARM_NEON__
+               v_xyzw = x*comb0+y*comb1+z*comb2+comb3;
+               //vst1q_f32((float*)v, v_xyzw);
+               #else
+               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];
+               #endif
+
+#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->uv_calculated = 0xFFFFFFFF;
+               v->screen_translated = 0;
+               v->shade_mod = 0;
+               #ifdef __ARM_NEON__
+               v->x=v_xyzw[0];
+               v->y=v_xyzw[1];
+               v->z=v_xyzw[2];
+               v->w=v_xyzw[3];
+               #endif
+
+               ///*
+               v->r = ((wxUint8*)gfx.RDRAM)[(addr+i + 12)^3];
+               v->g = ((wxUint8*)gfx.RDRAM)[(addr+i + 13)^3];
+               v->b = ((wxUint8*)gfx.RDRAM)[(addr+i + 14)^3];
+
+        if (fabs(v->w) < 0.001) v->w = 0.001f;
+               v->oow = 1.0f / v->w;
+               #ifdef __ARM_NEON__
+               v_xyzw *= v->oow;
+               v->x_w=v_xyzw[0];
+               v->y_w=v_xyzw[1];
+               v->z_w=v_xyzw[2];
+               #else
+               v->x_w = v->x * v->oow;
+               v->y_w = v->y * v->oow;
+               v->z_w = v->z * v->oow;
+               #endif
+
+               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;
+#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))
+               {
+                       wxUint32 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);
+                       #ifdef __ARM_NEON__
+                       float32x4_t color = {rdp.light[rdp.num_lights].r, rdp.light[rdp.num_lights].g, rdp.light[rdp.num_lights].b, 1.0f};
+                       #else
+                       float color[3] = {rdp.light[rdp.num_lights].r, rdp.light[rdp.num_lights].g, rdp.light[rdp.num_lights].b};
+                       #endif
+                       FRDP("ambient light. r: %f, g: %f, b: %f\n", color[0], color[1], color[2]);
+                       float light_intensity = 0.0f;
+                       wxUint32 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)
+          {
+                       #ifdef __ARM_NEON__
+                       float32x4_t vxyzw = (v_xyzw + uc8_8_11)*uc8_12_15 - rdplight[l];
+                       vxyzw = vxyzw*vxyzw;
+                       float invlen = 65536.0f/(vxyzw[0]+vxyzw[1]+vxyzw[2]+vxyzw[3]);
+            float p_i = rdp.light[l].ca * invlen;
+                       #else
+            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;
+                       #endif
+            if (p_i > 1.0f) p_i = 1.0f;
+            light_intensity *= p_i;
+                       #if __ARM_NEON__
+            FRDP("light %d, 1/len: %f, p_intensity : %f\n", l, invlen, p_i);
+                       #else
+            FRDP("light %d, len: %f, p_intensity : %f\n", l, len, p_i);
+                       #endif
+          }
+          //*/
+                 #ifdef __ARM_NEON__
+                 color += rdpcolor[l] * light_intensity;
+                 #else
+          color[0] += rdp.light[l].r * light_intensity;
+          color[1] += rdp.light[l].g * light_intensity;
+          color[2] += rdp.light[l].b * light_intensity;
+                 #endif
+          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)
+        {
+                 #ifdef __ARM_NEON__
+                 color += rdpcolor[l] * light_intensity;
+                 #else
+          color[0] += rdp.light[l].r * light_intensity;
+          color[1] += rdp.light[l].g * light_intensity;
+          color[2] += rdp.light[l].b * light_intensity;
+                 #endif
+        }
+        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)
+                                       {
+                                               #ifdef __ARM_NEON__
+                                               float32x4_t vxyzw = (v_xyzw + uc8_8_11)*uc8_12_15 - rdplight[l];
+                                               vxyzw = vxyzw*vxyzw;
+                                               float invlen = 65536.0f/(vxyzw[0]+vxyzw[1]+vxyzw[2]+vxyzw[3]);
+                                               light_intensity = rdp.light[l].ca * invlen;
+                                               #else
+                                               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;
+                                               #endif
+                                               if (light_intensity > 1.0f) light_intensity = 1.0f;
+                                               FRDP("light %d, p_intensity : %f\n", l, light_intensity);
+                                           #ifdef __ARM_NEON__
+                                               color += rdpcolor[l] * light_intensity;
+                                               #else
+                                               color[0] += rdp.light[l].r * light_intensity;
+                                               color[1] += rdp.light[l].g * light_intensity;
+                                               color[2] += rdp.light[l].b * light_intensity;
+                                               #endif
+                                               //FRDP("light %d r: %f, g: %f, b: %f\n", l, color[0], color[1], color[2]);
+                                       }
+                               }
+                       }
+                       #ifdef __ARM_NEON__
+                       color = vminq_f32(color, unite);
+                       #else
+                       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;
+                       #endif
+                       v->r = (wxUint8)(((float)v->r)*color[0]);
+                       v->g = (wxUint8)(((float)v->g)*color[1]);
+                       v->b = (wxUint8)(((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 ()
+{
+       wxUint8 index = (wxUint8)((rdp.cmd0 >> 16) & 0xFF);
+       wxUint16 offset = (wxUint16)(rdp.cmd0 & 0xFFFF);
+       wxUint32 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:
+    if (offset == 0x04)
+    {
+      rdp.clip_ratio = sqrt((float)rdp.cmd1);
+      rdp.update |= UPDATE_VIEWPORT;
+    }
+               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");
+               LRDP("forcemtx - IGNORED\n");
+               break;
+
+       case 0x0e:
+               LRDP("perspnorm - IGNORED\n");
+               break;
+
+       case 0x10:  // moveword coord mod
+               {
+                       wxUint8 n = offset >> 2;
+
+                       FRDP ("coord mod:%d, %08lx\n", n, data);
+                       if (rdp.cmd0&8)
+                               return;
+                       wxUint32 idx = (rdp.cmd0>>1)&3;
+                       wxUint32 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;
+       wxUint32 addr = segoffset(rdp.cmd1);
+       int ofs = (rdp.cmd0 >> 5) & 0x3FFF;
+
+       FRDP ("uc8:movemem ofs:%d ", ofs);
+
+       switch (idx)
+       {
+       case 8:   // VIEWPORT
+               {
+                       wxUint32 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;
+                       wxUint8 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;
+                       // **
+                       wxUint32 a = addr >> 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, ((wxUint16*)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
+      int i;
+                       for (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);
+                       }
+                       wxUint32 a = uc8_normale_addr >> 1;
+                       for (i = 0; i < 32; i++)
+                       {
+                               FRDP ("n[%d] = 0x%04lx \n", i, ((wxUint16*)gfx.RDRAM)[(a+i)^1]);
+                       }
+#endif
+               }
+               break;
+
+       default:
+               FRDP ("uc8:movemem unknown (%d)\n", idx);
+       }
+}
+
+
+static void uc8_tri4() //by Gugaman Apr 19 2002
+{
+Check_FrameSkip;
+
+    if (rdp.skip_drawing)
+    {
+               LRDP("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]
+       };
+
+       int updated = 0;
+
+       if (cull_tri(v))
+               rdp.tri_n ++;
+       else
+       {
+               updated = 1;
+               update ();
+
+               draw_tri (v);
+               rdp.tri_n ++;
+       }
+
+       if (cull_tri(v+3))
+               rdp.tri_n ++;
+       else
+       {
+               if (!updated)
+               {
+                       updated = 1;
+                       update ();
+               }
+
+               draw_tri (v+3);
+               rdp.tri_n ++;
+       }
+
+       if (cull_tri(v+6))
+               rdp.tri_n ++;
+       else
+       {
+               if (!updated)
+               {
+                       updated = 1;
+                       update ();
+               }
+
+               draw_tri (v+6);
+               rdp.tri_n ++;
+       }
+
+       if (cull_tri(v+9))
+               rdp.tri_n ++;
+       else
+       {
+               if (!updated)
+               {
+                       updated = 1;
+                       update ();
+               }
+
+               draw_tri (v+9);
+               rdp.tri_n ++;
+       }
+}
diff --git a/source/gles2glide64/src/Glide64/ucode09.h b/source/gles2glide64/src/Glide64/ucode09.h
new file mode 100755 (executable)
index 0000000..69a4a82
--- /dev/null
@@ -0,0 +1,690 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+//
+// December 2008 Created by Gonetz (Gonetz@ngs.ru)
+//
+//****************************************************************
+
+void uc9_rpdcmd ();
+
+typedef float M44[4][4];
+
+struct ZSORTRDP {
+  float view_scale[2];
+  float view_trans[2];
+  float scale_x;
+  float scale_y;
+} zSortRdp = {{0, 0}, {0, 0}, 0, 0};
+
+//RSP command VRCPL
+static int Calc_invw (int w) {
+       int count, neg;
+  union {
+       wxInt32           W;
+       wxUint32          UW;
+       wxInt16                 HW[2];
+       wxUint16                UHW[2];
+  } Result;
+       Result.W = w;
+       if (Result.UW == 0) {
+               Result.UW = 0x7FFFFFFF;
+       } else {
+               if (Result.W < 0) {
+                       neg = TRUE;
+                       if (Result.UHW[1] == 0xFFFF && Result.HW[0] < 0) {
+                               Result.W = ~Result.W + 1;
+                       } else {
+                               Result.W = ~Result.W;
+                       }
+               } else {
+                       neg = FALSE;
+               }
+               for (count = 31; count > 0; count--) {
+                       if ((Result.W & (1 << count))) {
+                               Result.W &= (0xFFC00000 >> (31 - count) );
+                               count = 0;
+                       }
+               }
+               Result.W = 0x7FFFFFFF / Result.W;
+               for (count = 31; count > 0; count--) {
+                       if ((Result.W & (1 << count))) {
+                               Result.W &= (0xFFFF8000 >> (31 - count) );
+                               count = 0;
+                       }
+               }
+               if (neg == TRUE) {
+                       Result.W = ~Result.W;
+               }
+       }
+  return Result.W;
+}
+
+static void uc9_draw_object (wxUint8 * addr, wxUint32 type)
+{
+Check_FrameSkip;
+
+  wxUint32 textured, vnum, vsize;
+  switch (type) {
+    case 1: //sh tri
+      textured = 0;
+      vnum = 3;
+      vsize = 8;
+      break;
+    case 2: //tx tri
+      textured = 1;
+      vnum = 3;
+      vsize = 16;
+      break;
+    case 3: //sh quad
+      textured = 0;
+      vnum = 4;
+      vsize = 8;
+      break;
+    case 4: //tx quad
+      textured = 1;
+      vnum = 4;
+      vsize = 16;
+      break;
+    case 0: //null
+    default:
+      textured = vnum = vsize = 0;
+      break;
+  }
+  VERTEX vtx[4];
+  for (wxUint32 i = 0; i < vnum; i++)
+  {
+    VERTEX &v = vtx[i];
+    v.sx = zSortRdp.scale_x * ((short*)addr)[0^1];
+    v.sy = zSortRdp.scale_y * ((short*)addr)[1^1];
+    v.sz = 1.0f;
+    v.r = addr[4^3];
+    v.g = addr[5^3];
+    v.b = addr[6^3];
+    v.a = addr[7^3];
+    v.flags = 0;
+    v.uv_scaled = 0;
+    v.uv_calculated = 0xFFFFFFFF;
+    v.shade_mod = 0;
+    v.scr_off = 0;
+    v.screen_translated = 2;
+    if (textured)
+    {
+      v.ou = ((short*)addr)[4^1];
+      v.ov = ((short*)addr)[5^1];
+      v.w = Calc_invw(((int*)addr)[3]) / 31.0f;
+      v.oow = 1.0f / v.w;
+      FRDP ("v%d - sx: %f, sy: %f ou: %f, ov: %f, w: %f, r=%d, g=%d, b=%d, a=%d\n", i, v.sx/rdp.scale_x, v.sy/rdp.scale_y, v.ou*rdp.tiles[rdp.cur_tile].s_scale, v.ov*rdp.tiles[rdp.cur_tile].t_scale, v.w, v.r, v.g, v.b, v.a);
+    }
+    else
+    {
+      v.oow = v.w = 1.0f;
+      FRDP ("v%d - sx: %f, sy: %f r=%d, g=%d, b=%d, a=%d\n", i, v.sx/rdp.scale_x, v.sy/rdp.scale_y, v.r, v.g, v.b, v.a);
+    }
+    addr += vsize;
+  }
+  //*
+  VERTEX *pV[4] = {
+    &vtx[0],
+    &vtx[1],
+    &vtx[2],
+    &vtx[3]
+  };
+  if (vnum == 3)
+  {
+    FRDP("uc9:Tri #%d, #%d\n", rdp.tri_n, rdp.tri_n+1);
+    draw_tri (pV, 0);
+    rdp.tri_n ++;
+  }
+  else
+  {
+    FRDP("uc9:Quad #%d, #%d\n", rdp.tri_n, rdp.tri_n+1);
+    draw_tri (pV, 0);
+    draw_tri (pV+1, 0);
+    rdp.tri_n += 2;
+  }
+}
+
+static wxUint32 uc9_load_object (wxUint32 zHeader, wxUint32 * rdpcmds)
+{
+  wxUint32 type = zHeader & 7;
+  wxUint8 * addr = gfx.RDRAM + (zHeader&0xFFFFFFF8);
+  switch (type) {
+    case 1: //sh tri
+    case 3: //sh quad
+      {
+        rdp.cmd1 = ((wxUint32*)addr)[1];
+        if (rdp.cmd1 != rdpcmds[0])
+        {
+          rdpcmds[0] = rdp.cmd1;
+          uc9_rpdcmd ();
+        }
+        update ();
+        uc9_draw_object(addr + 8, type);
+      }
+      break;
+    case 0: //null
+    case 2: //tx tri
+    case 4: //tx quad
+      {
+        rdp.cmd1 = ((wxUint32*)addr)[1];
+        if (rdp.cmd1 != rdpcmds[0])
+        {
+          rdpcmds[0] = rdp.cmd1;
+          uc9_rpdcmd ();
+        }
+        rdp.cmd1 = ((wxUint32*)addr)[2];
+        if (rdp.cmd1 != rdpcmds[1])
+        {
+          uc9_rpdcmd ();
+          rdpcmds[1] = rdp.cmd1;
+        }
+        rdp.cmd1 = ((wxUint32*)addr)[3];
+        if (rdp.cmd1 != rdpcmds[2])
+        {
+          uc9_rpdcmd ();
+          rdpcmds[2] = rdp.cmd1;
+        }
+        if (type)
+        {
+          update ();
+          uc9_draw_object(addr + 16, type);
+        }
+      }
+      break;
+  }
+  return segoffset(((wxUint32*)addr)[0]);
+}
+
+static void uc9_object ()
+{
+  LRDP("uc9:object\n");
+  wxUint32 rdpcmds[3] = {0, 0, 0};
+  wxUint32 cmd1 = rdp.cmd1;
+  wxUint32 zHeader = segoffset(rdp.cmd0);
+  while (zHeader)
+    zHeader = uc9_load_object(zHeader, rdpcmds);
+  zHeader = segoffset(cmd1);
+  while (zHeader)
+    zHeader = uc9_load_object(zHeader, rdpcmds);
+}
+
+static void uc9_mix ()
+{
+  LRDP("uc9:mix IGNORED\n");
+}
+
+static void uc9_fmlight ()
+{
+  int mid = rdp.cmd0&0xFF;
+  rdp.num_lights = 1 + ((rdp.cmd1>>12)&0xFF);
+  wxUint32 a = -1024 + (rdp.cmd1&0xFFF);
+  FRDP ("uc9:fmlight matrix: %d, num: %d, dmem: %04lx\n", mid, rdp.num_lights, a);
+
+  M44 *m = NULL;
+  switch (mid) {
+  case 4:
+    m = (M44*)rdp.model;
+    break;
+  case 6:
+    m = (M44*)rdp.proj;
+    break;
+  case 8:
+    m = (M44*)rdp.combined;
+    break;
+  }
+
+  rdp.light[rdp.num_lights].r = (float)(((wxUint8*)gfx.DMEM)[(a+0)^3]) / 255.0f;
+  rdp.light[rdp.num_lights].g = (float)(((wxUint8*)gfx.DMEM)[(a+1)^3]) / 255.0f;
+  rdp.light[rdp.num_lights].b = (float)(((wxUint8*)gfx.DMEM)[(a+2)^3]) / 255.0f;
+  rdp.light[rdp.num_lights].a = 1.0f;
+  FRDP ("ambient light: r: %.3f, g: %.3f, b: %.3f\n", rdp.light[rdp.num_lights].r, rdp.light[rdp.num_lights].g, rdp.light[rdp.num_lights].b);
+  a += 8;
+  wxUint32 i;
+  for (i = 0; i < rdp.num_lights; i++)
+  {
+    rdp.light[i].r = (float)(((wxUint8*)gfx.DMEM)[(a+0)^3]) / 255.0f;
+    rdp.light[i].g = (float)(((wxUint8*)gfx.DMEM)[(a+1)^3]) / 255.0f;
+    rdp.light[i].b = (float)(((wxUint8*)gfx.DMEM)[(a+2)^3]) / 255.0f;
+    rdp.light[i].a = 1.0f;
+    rdp.light[i].dir_x = (float)(((char*)gfx.DMEM)[(a+8)^3]) / 127.0f;
+    rdp.light[i].dir_y = (float)(((char*)gfx.DMEM)[(a+9)^3]) / 127.0f;
+    rdp.light[i].dir_z = (float)(((char*)gfx.DMEM)[(a+10)^3]) / 127.0f;
+    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[i].dir_x, rdp.light[i].dir_y, rdp.light[i].dir_z);
+//    TransformVector(&rdp.light[i].dir_x, rdp.light_vector[i], *m);
+    InverseTransformVector(&rdp.light[i].dir_x, rdp.light_vector[i], *m);
+    NormalizeVector (rdp.light_vector[i]);
+    FRDP ("light vector: n: %d, x: %.3f, y: %.3f, z: %.3f\n",
+      i, rdp.light_vector[i][0], rdp.light_vector[i][1], rdp.light_vector[i][2]);
+    a += 24;
+  }
+  for (i = 0; i < 2; i++)
+  {
+    float dir_x = (float)(((char*)gfx.DMEM)[(a+8)^3]) / 127.0f;
+    float dir_y = (float)(((char*)gfx.DMEM)[(a+9)^3]) / 127.0f;
+    float dir_z = (float)(((char*)gfx.DMEM)[(a+10)^3]) / 127.0f;
+    if (sqrt(dir_x*dir_x + dir_y*dir_y + dir_z*dir_z) < 0.98)
+    {
+      rdp.use_lookat = FALSE;
+      return;
+    }
+    rdp.lookat[i][0] = dir_x;
+    rdp.lookat[i][1] = dir_y;
+    rdp.lookat[i][2] = dir_z;
+    a += 24;
+  }
+  rdp.use_lookat = TRUE;
+}
+
+static void uc9_light ()
+{
+  wxUint32 csrs = -1024 + ((rdp.cmd0>>12)&0xFFF);
+  wxUint32 nsrs = -1024 + (rdp.cmd0&0xFFF);
+  wxUint32 num = 1 + ((rdp.cmd1>>24)&0xFF);
+  wxUint32 cdest = -1024 + ((rdp.cmd1>>12)&0xFFF);
+  wxUint32 tdest = -1024 + (rdp.cmd1&0xFFF);
+  int use_material = (csrs != 0x0ff0);
+  tdest >>= 1;
+  FRDP ("uc9:light n: %d, colsrs: %04lx, normales: %04lx, coldst: %04lx, texdst: %04lx\n", num, csrs, nsrs, cdest, tdest);
+  VERTEX v;
+  for (wxUint32 i = 0; i < num; i++)
+  {
+    v.vec[0] = ((char*)gfx.DMEM)[(nsrs++)^3];
+    v.vec[1] = ((char*)gfx.DMEM)[(nsrs++)^3];
+    v.vec[2] = ((char*)gfx.DMEM)[(nsrs++)^3];
+    calc_sphere (&v);
+//    calc_linear (&v);
+    NormalizeVector (v.vec);
+    calc_light (&v);
+    v.a = 0xFF;
+    if (use_material)
+    {
+      v.r = (wxUint8)(((wxUint32)v.r * gfx.DMEM[(csrs++)^3])>>8);
+      v.g = (wxUint8)(((wxUint32)v.g * gfx.DMEM[(csrs++)^3])>>8);
+      v.b = (wxUint8)(((wxUint32)v.b * gfx.DMEM[(csrs++)^3])>>8);
+      v.a = gfx.DMEM[(csrs++)^3];
+    }
+    gfx.DMEM[(cdest++)^3] = v.r;
+    gfx.DMEM[(cdest++)^3] = v.g;
+    gfx.DMEM[(cdest++)^3] = v.b;
+    gfx.DMEM[(cdest++)^3] = v.a;
+    ((short*)gfx.DMEM)[(tdest++)^1] = (short)v.ou;
+    ((short*)gfx.DMEM)[(tdest++)^1] = (short)v.ov;
+  }
+}
+
+static void uc9_mtxtrnsp ()
+{
+  LRDP("uc9:mtxtrnsp - ignored\n");
+  /*
+  LRDP("uc9:mtxtrnsp ");
+  M44 *s;
+  switch (rdp.cmd1&0xF) {
+  case 4:
+    s = (M44*)rdp.model;
+    LRDP("Model\n");
+    break;
+  case 6:
+    s = (M44*)rdp.proj;
+    LRDP("Proj\n");
+    break;
+  case 8:
+    s = (M44*)rdp.combined;
+    LRDP("Comb\n");
+    break;
+  }
+  float m = *s[1][0];
+  *s[1][0] = *s[0][1];
+  *s[0][1] = m;
+  m = *s[2][0];
+  *s[2][0] = *s[0][2];
+  *s[0][2] = m;
+  m = *s[2][1];
+  *s[2][1] = *s[1][2];
+  *s[1][2] = m;
+  */
+}
+
+static void uc9_mtxcat ()
+{
+  LRDP("uc9:mtxcat ");
+  M44 *s = NULL;
+  M44 *t = NULL;
+  wxUint32 S = rdp.cmd0&0xF;
+  wxUint32 T = (rdp.cmd1>>16)&0xF;
+  wxUint32 D = rdp.cmd1&0xF;
+  switch (S) {
+  case 4:
+    s = (M44*)rdp.model;
+    LRDP("Model * ");
+    break;
+  case 6:
+    s = (M44*)rdp.proj;
+    LRDP("Proj * ");
+    break;
+  case 8:
+    s = (M44*)rdp.combined;
+    LRDP("Comb * ");
+    break;
+  }
+  switch (T) {
+  case 4:
+    t = (M44*)rdp.model;
+    LRDP("Model -> ");
+    break;
+  case 6:
+    t = (M44*)rdp.proj;
+    LRDP("Proj -> ");
+    break;
+  case 8:
+    LRDP("Comb -> ");
+    t = (M44*)rdp.combined;
+    break;
+  }
+  DECLAREALIGN16VAR(m[4][4]);
+  MulMatrices(*s, *t, m);
+
+  switch (D) {
+  case 4:
+    memcpy (rdp.model, m, 64);;
+    LRDP("Model\n");
+    break;
+  case 6:
+    memcpy (rdp.proj, m, 64);;
+    LRDP("Proj\n");
+    break;
+  case 8:
+    memcpy (rdp.combined, m, 64);;
+    LRDP("Comb\n");
+    break;
+  }
+#ifdef EXTREME_LOGGING
+  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]);
+  FRDP ("\ncombined\n{%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
+}
+
+typedef struct  {
+  short sy;
+  short sx;
+  int   invw;
+  short yi;
+  short xi;
+  short wi;
+  wxUint8 fog;
+  wxUint8 cc;
+} zSortVDest;
+
+static void uc9_mult_mpmtx ()
+{
+  //int id = rdp.cmd0&0xFF;
+  int num = 1+ ((rdp.cmd1>>24)&0xFF);
+  int src = -1024 + ((rdp.cmd1>>12)&0xFFF);
+  int dst = -1024 + (rdp.cmd1&0xFFF);
+  FRDP ("uc9:mult_mpmtx from: %04lx  to: %04lx n: %d\n", src, dst, num);
+  short * saddr = (short*)(gfx.DMEM+src);
+  zSortVDest * daddr = (zSortVDest*)(gfx.DMEM+dst);
+  int idx = 0;
+  zSortVDest v;
+  memset(&v, 0, sizeof(zSortVDest));
+  //float scale_x = 4.0f/rdp.scale_x;
+  //float scale_y = 4.0f/rdp.scale_y;
+  for (int i = 0; i < num; i++)
+  {
+    short sx   = saddr[(idx++)^1];
+    short sy   = saddr[(idx++)^1];
+    short sz   = saddr[(idx++)^1];
+    float x = sx*rdp.combined[0][0] + sy*rdp.combined[1][0] + sz*rdp.combined[2][0] + rdp.combined[3][0];
+    float y = sx*rdp.combined[0][1] + sy*rdp.combined[1][1] + sz*rdp.combined[2][1] + rdp.combined[3][1];
+    float z = sx*rdp.combined[0][2] + sy*rdp.combined[1][2] + sz*rdp.combined[2][2] + rdp.combined[3][2];
+    float w = sx*rdp.combined[0][3] + sy*rdp.combined[1][3] + sz*rdp.combined[2][3] + rdp.combined[3][3];
+    v.sx = (short)(zSortRdp.view_trans[0] + x / w * zSortRdp.view_scale[0]);
+    v.sy = (short)(zSortRdp.view_trans[1] + y / w * zSortRdp.view_scale[1]);
+
+    v.xi = (short)x;
+    v.yi = (short)y;
+    v.wi = (short)w;
+    v.invw = Calc_invw((int)(w * 31.0));
+
+    if (w < 0.0f)
+      v.fog = 0;
+    else
+    {
+      int fog = (int)(z / w * rdp.fog_multiplier + rdp.fog_offset);
+      if (fog > 255)
+        fog = 255;
+      v.fog = (fog >= 0) ? (wxUint8)fog : 0;
+    }
+
+    v.cc = 0;
+    if (x < -w) v.cc |= 0x10;
+    if (x > w) v.cc |= 0x01;
+    if (y < -w) v.cc |= 0x20;
+    if (y > w) v.cc |= 0x02;
+    if (w < 0.1f) v.cc |= 0x04;
+
+    daddr[i] = v;
+    //memcpy(gfx.DMEM+dst+sizeof(zSortVDest)*i, &v, sizeof(zSortVDest));
+//    FRDP("v%d x: %d, y: %d, z: %d -> sx: %d, sy: %d, w: %d, xi: %d, yi: %d, wi: %d, fog: %d\n", i, sx, sy, sz, v.sx, v.sy, v.invw, v.xi, v.yi, v.wi, v.fog);
+    FRDP("v%d x: %d, y: %d, z: %d -> sx: %04lx, sy: %04lx, invw: %08lx - %f, xi: %04lx, yi: %04lx, wi: %04lx, fog: %04lx\n", i, sx, sy, sz, v.sx, v.sy, v.invw, w, v.xi, v.yi, v.wi, v.fog);
+  }
+}
+
+static void uc9_link_subdl ()
+{
+  LRDP("uc9:link_subdl IGNORED\n");
+}
+
+static void uc9_set_subdl ()
+{
+  LRDP("uc9:set_subdl IGNORED\n");
+}
+
+static void uc9_wait_signal ()
+{
+  LRDP("uc9:wait_signal IGNORED\n");
+}
+
+static void uc9_send_signal ()
+{
+  LRDP("uc9:send_signal IGNORED\n");
+}
+
+void uc9_movemem ()
+{
+  LRDP("uc9:movemem\n");
+  int idx = rdp.cmd0 & 0x0E;
+  int ofs = ((rdp.cmd0>>6)&0x1ff)<<3;
+  int len = (1 + ((rdp.cmd0>>15)&0x1ff))<<3;
+  FRDP ("uc9:movemem ofs: %d, len: %d. ", ofs, len);
+  int flag = rdp.cmd0 & 0x01;
+  wxUint32 addr = segoffset(rdp.cmd1);
+  switch (idx)
+  {
+
+  case 0: //save/load
+    if (flag == 0)
+    {
+      int dmem_addr = (idx<<3) + ofs;
+      FRDP ("Load to DMEM. %08lx -> %08lx\n", addr, dmem_addr);
+      memcpy(gfx.DMEM + dmem_addr, gfx.RDRAM + addr, len);
+    }
+    else
+    {
+      int dmem_addr = (idx<<3) + ofs;
+      FRDP ("Load from DMEM. %08lx -> %08lx\n", dmem_addr, addr);
+      memcpy(gfx.RDRAM + addr, gfx.DMEM + dmem_addr, len);
+    }
+    break;
+
+  case 4:  // model matrix
+  case 6:  // projection matrix
+  case 8:  // combined matrix
+    {
+      DECLAREALIGN16VAR(m[4][4]);
+      load_matrix(m, addr);
+      switch (idx)
+      {
+      case 4:  // model matrix
+        LRDP("Modelview load\n");
+        modelview_load (m);
+        break;
+      case 6:  // projection matrix
+        LRDP("Projection load\n");
+        projection_load (m);
+        break;
+      case 8:  // projection matrix
+        LRDP("Combined load\n");
+        rdp.update &= ~UPDATE_MULT_MAT;
+        memcpy (rdp.combined, m, 64);;
+        break;
+      }
+#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
+    }
+    break;
+
+  case 10:
+    LRDP("Othermode - IGNORED\n");
+    break;
+
+  case 12:   // VIEWPORT
+    {
+      wxUint32 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];
+      rdp.fog_multiplier = ((short*)gfx.RDRAM)[(a+3)^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.fog_offset = ((short*)gfx.RDRAM)[(a+7)^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;
+      zSortRdp.view_scale[0] = (float)(scale_x*4);
+      zSortRdp.view_scale[1] = (float)(scale_y*4);
+      zSortRdp.view_trans[0] = (float)(trans_x*4);
+      zSortRdp.view_trans[1] = (float)(trans_y*4);
+      zSortRdp.scale_x = rdp.scale_x / 4.0f;
+      zSortRdp.scale_y = rdp.scale_y / 4.0f;
+
+      rdp.update |= UPDATE_VIEWPORT;
+
+      rdp.mipmap_level = 0;
+      rdp.cur_tile = 0;
+      TILE *tmp_tile = &rdp.tiles[0];
+      tmp_tile->on = 1;
+      tmp_tile->org_s_scale = 0xFFFF;
+      tmp_tile->org_t_scale = 0xFFFF;
+      tmp_tile->s_scale = 0.031250f;
+      tmp_tile->t_scale = 0.031250f;
+
+      rdp.geom_mode |= 0x0200;
+
+      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);
+      FRDP ("fog: multiplier: %f, offset: %f\n", rdp.fog_multiplier, rdp.fog_offset);
+    }
+    break;
+
+  default:
+    FRDP ("** UNKNOWN %d\n", idx);
+  }
+
+}
+
+static void uc9_setscissor()
+{
+  rdp_setscissor();
+
+  if ((rdp.scissor_o.lr_x - rdp.scissor_o.ul_x) > (zSortRdp.view_scale[0] - zSortRdp.view_trans[0]))
+  {
+    float w = (rdp.scissor_o.lr_x - rdp.scissor_o.ul_x) / 2.0f;
+    float h = (rdp.scissor_o.lr_y - rdp.scissor_o.ul_y) / 2.0f;
+    rdp.view_scale[0] = w * rdp.scale_x;
+    rdp.view_scale[1] = h * rdp.scale_y;
+    rdp.view_trans[0] = w * rdp.scale_x;
+    rdp.view_trans[1] = h * rdp.scale_y;
+    zSortRdp.view_scale[0] = w * 4.0f;
+    zSortRdp.view_scale[1] = h * 4.0f;
+    zSortRdp.view_trans[0] = w * 4.0f;
+    zSortRdp.view_trans[1] = h * 4.0f;
+    zSortRdp.scale_x = rdp.scale_x / 4.0f;
+    zSortRdp.scale_y = rdp.scale_y / 4.0f;
+    rdp.update |= UPDATE_VIEWPORT;
+
+    rdp.mipmap_level = 0;
+    rdp.cur_tile = 0;
+    TILE *tmp_tile = &rdp.tiles[0];
+    tmp_tile->on = 1;
+    tmp_tile->org_s_scale = 0xFFFF;
+    tmp_tile->org_t_scale = 0xFFFF;
+    tmp_tile->s_scale = 0.031250f;
+    tmp_tile->t_scale = 0.031250f;
+
+    rdp.geom_mode |= 0x0200;
+  }
+}
diff --git a/source/gles2glide64/src/Glide64/ucode09rdp.h b/source/gles2glide64/src/Glide64/ucode09rdp.h
new file mode 100644 (file)
index 0000000..adecbd0
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+//
+// December 2008 Created by Gonetz (Gonetz@ngs.ru)
+//
+//****************************************************************
+
+void uc9_rpdcmd ()
+{
+  wxUint32 a = segoffset(rdp.cmd1) >> 2;
+  FRDP ("uc9:rdpcmd addr: %08lx\n", a);
+  if (a)
+  {
+    rdp.LLE = 1;
+    wxUint32 cmd = 0;
+    while(1) 
+    {
+      rdp.cmd0 = ((wxUint32*)gfx.RDRAM)[a++];   
+      cmd = rdp.cmd0>>24; 
+      if (cmd == 0xDF)
+        break;
+      rdp.cmd1 = ((wxUint32*)gfx.RDRAM)[a++]; 
+      if (cmd == 0xE4 || cmd == 0xE5)
+      {
+        a++;
+        rdp.cmd2 = ((wxUint32*)gfx.RDRAM)[a++]; 
+        a++;
+        rdp.cmd3 = ((wxUint32*)gfx.RDRAM)[a++];
+      }
+      gfx_instruction[ucode_zSort][cmd] ();
+    };
+    rdp.LLE = 0;
+  }
+}
diff --git a/source/gles2glide64/src/Glide64/ucodeFB.h b/source/gles2glide64/src/Glide64/ucodeFB.h
new file mode 100644 (file)
index 0000000..c734fab
--- /dev/null
@@ -0,0 +1,1110 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//****************************************************************
+//
+// Glide64 - Glide Plugin for Nintendo 64 emulators
+// Project started on December 29th, 2001
+//
+// Authors:
+// Dave2001, original author, founded the project in 2001, left it in 2002
+// Gugaman, joined the project in 2002, left it in 2002
+// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
+// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
+//
+//****************************************************************
+//
+// To modify Glide64:
+// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
+// * Do NOT send me the whole project or file that you modified.  Take out your modified code sections, and tell me where to put them.  If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
+//
+//****************************************************************
+//
+// Creation 13 August 2003               Gonetz
+//
+//****************************************************************
+
+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;
+
+  wxUint32 addr = segoffset(rdp.cmd1) >> 1;
+  wxUint8 imageFmt     = ((wxUint8 *)gfx.RDRAM)[(((addr+11)<<1)+0)^3];
+  wxUint8 imageSiz     = ((wxUint8 *)gfx.RDRAM)[(((addr+11)<<1)+1)^3];
+  wxUint32 imagePtr    = segoffset(((wxUint32*)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)
+  {
+    wxUint16 frameW    = ((wxUint16 *)gfx.RDRAM)[(addr+3)^1] >> 2;
+    wxUint16 frameH    = ((wxUint16 *)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
+    {
+      LRDP("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)
+  {
+    if (status == ci_unknown)
+    {
+      rdp.frame_buffers[rdp.ci_count-1].status = ci_zcopy;
+      rdp.tmpzimg = rdp.frame_buffers[rdp.ci_count-1].addr;
+      if (!rdp.copy_zi_index)
+        rdp.copy_zi_index = rdp.ci_count-1;
+      FRDP("rdp.frame_buffers[%d].status = ci_zcopy\n", rdp.copy_ci_index);
+    }
+  }
+}
+
+static void fb_setscissor()
+{
+  rdp.scissor_o.lr_y = (wxUint32)(((rdp.cmd1 & 0x00000FFF) >> 2));
+  if (rdp.ci_count)
+  {
+    rdp.scissor_o.ul_x = (wxUint32)(((rdp.cmd0 & 0x00FFF000) >> 14));
+    rdp.scissor_o.lr_x = (wxUint32)(((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 > (wxUint32)(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_uc2_movemem()
+{
+  if ((rdp.cmd0 & 0xFF) == 8)
+  {
+    wxUint32 a = segoffset(rdp.cmd1) >> 1;
+    short scale_x = ((short*)gfx.RDRAM)[(a+0)^1] >> 2;
+    short trans_x = ((short*)gfx.RDRAM)[(a+4)^1] >> 2;
+    COLOR_IMAGE & cur_fb = rdp.frame_buffers[rdp.ci_count-1];
+    if ( abs((int)(scale_x + trans_x - cur_fb.width)) < 3)
+    {
+      short scale_y = ((short*)gfx.RDRAM)[(a+1)^1] >> 2;
+      short trans_y = ((short*)gfx.RDRAM)[(a+5)^1] >> 2;
+      wxUint32 height = scale_y + trans_y;
+      if (height < rdp.scissor_o.lr_y)
+        cur_fb.height = 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;
+  int diff = abs((int)rdp.frame_buffers[rdp.ci_count-1].width - width);
+  if (diff < 4)
+  {
+    wxUint32 lr_y = min(rdp.scissor_o.lr_y, (rdp.cmd0 & 0xFFF) >> 2);
+    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_rdphalf_1()
+{
+  branch_dl = rdp.cmd1;
+}
+
+
+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);
+    wxUint32 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)))
+            {
+              LRDP("motion blur!\n");
+              rdp.motionblur = TRUE;
+            }
+            else
+            {
+              rdp.scale_x = 1.0f;
+              rdp.scale_y = 1.0f;
+            }
+          }
+          else if (!(settings.frame_buffer & 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;
+        if (!rdp.copy_zi_index)
+          rdp.copy_zi_index = rdp.ci_count-1;
+        FRDP("fb_settextureimage. rdp.frame_buffers[%d].status = ci_zcopy\n", rdp.ci_count-1);
+      }
+      //*/
+      else if ((rdp.maincimg[0].width > 64) && (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;
+        LRDP("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;
+        LRDP("read_previous_ci = TRUE\n");
+      }
+    }
+    else if (fb_hwfbe_enabled && (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);
+      for (int i = rdp.main_ci_index+1; i < rdp.ci_count; i++)
+      {
+        COLOR_IMAGE & fb = rdp.frame_buffers[i];
+        if (fb.addr == rdp.main_ci)
+        {
+          fb.status = ci_main;
+          FRDP("rdp.frame_buffers[%d].status = ci_main\n", i);
+        }
+      }
+    }
+    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)
+  {
+    cur_fb.status = ci_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.cimg == rdp.tmpzimg)
+  {
+    cur_fb.status = ci_zcopy;
+    if (!rdp.copy_zi_index)
+      rdp.copy_zi_index = rdp.ci_count-1;
+    FRDP("rdp.frame_buffers[%d].status = ci_zcopy\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.ci_count > 0 && rdp.frame_buffers[rdp.ci_count-1].status == ci_unknown) //status of previous fb was not changed - it is useless
+  {
+    if (fb_hwfbe_enabled && !(settings.frame_buffer & fb_useless_is_useless))
+    {
+      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;
+      /*
+      wxUint32 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)
+  {
+    int 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,
+        fb_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,
+          fb_uc2_movemem,                      uc2_load_ucode,                 uc0_displaylist,        uc0_enddl,
+          0,                                   fb_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,                  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 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,                       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
+                    }
+};
diff --git a/source/gles2glide64/src/Glide64/winlnxdefs.h b/source/gles2glide64/src/Glide64/winlnxdefs.h
new file mode 100644 (file)
index 0000000..6b2e89d
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+* Copyright (c) 2012-2013 balrog, wahrhaft
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#ifndef WINLNXDEFS_H
+#define WINLNXDEFS_H
+
+#define wxPtrToUInt (uintptr_t)
+#define TRUE 1
+#define FALSE 0
+
+#define _T(x) x
+
+#include <stdint.h>
+
+typedef int BOOL;
+typedef uint32_t wxUint32;
+typedef uint16_t wxUint16;
+typedef uint8_t wxUint8;
+typedef uint8_t BYTE;
+typedef long long LONGLONG;
+
+
+typedef int32_t wxInt32;
+typedef int16_t wxInt16;
+typedef int8_t wxInt8;
+
+typedef uint64_t wxUint64;
+typedef int64_t wxInt64;
+
+typedef unsigned char wxChar;
+typedef uintptr_t wxUIntPtr;
+
+#ifndef WIN32
+
+typedef union _LARGE_INTEGER
+{
+   struct
+     {
+    uint32_t LowPart;
+    uint32_t HighPart;
+     } s;
+   struct
+     {
+    uint32_t LowPart;
+    uint32_t HighPart;
+     } u;
+   long long QuadPart;
+} LARGE_INTEGER, *PLARGE_INTEGER;
+
+#define WINAPI
+
+#endif
+
+#endif
diff --git a/source/gles2glide64/src/GlideHQ/Ext_TxFilter.cpp b/source/gles2glide64/src/GlideHQ/Ext_TxFilter.cpp
new file mode 100644 (file)
index 0000000..62377dc
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <memory.h>
+#include <stdlib.h>
+#include "Ext_TxFilter.h"
+
+extern "C"{
+
+boolean txfilter_init(int maxwidth, int maxheight, int maxbpp,
+                      int options, int cachesize,
+                      wchar_t *datapath, wchar_t *cachepath, wchar_t *ident,
+                      dispInfoFuncExt callback);
+
+void txfilter_shutdown(void);
+
+boolean txfilter(unsigned char *src, int srcwidth, int srcheight, unsigned short srcformat,
+                 uint64 g64crc, GHQTexInfo *info);
+
+boolean txfilter_hirestex(uint64 g64crc, uint64 r_crc64, unsigned short *palette, GHQTexInfo *info);
+
+uint64 txfilter_checksum(unsigned char *src, int width, int height, int size, int rowStride, unsigned char *palette);
+
+boolean txfilter_dmptx(unsigned char *src, int width, int height, int rowStridePixel, unsigned short gfmt, unsigned short n64fmt, uint64 r_crc64);
+
+boolean txfilter_reloadhirestex();
+
+}
+
+void ext_ghq_shutdown(void)
+{
+  txfilter_shutdown();
+}
+
+boolean ext_ghq_init(int maxwidth, int maxheight, int maxbpp, int options, int cachesize,
+                     wchar_t *datapath, wchar_t *cachepath, wchar_t *ident,
+                     dispInfoFuncExt callback)
+{
+  boolean bRet = 0;
+
+  bRet = txfilter_init(maxwidth, maxheight, maxbpp, options, cachesize, datapath, cachepath, ident, callback);
+
+  return bRet;
+}
+
+boolean ext_ghq_txfilter(unsigned char *src, int srcwidth, int srcheight, unsigned short srcformat,
+                                uint64 g64crc, GHQTexInfo *info)
+{
+  boolean ret = 0;
+
+  ret = txfilter(src, srcwidth, srcheight, srcformat,
+                 g64crc, info);
+
+  return ret;
+}
+
+boolean ext_ghq_hirestex(uint64 g64crc, uint64 r_crc64, unsigned short *palette, GHQTexInfo *info)
+{
+  boolean ret = 0;
+
+  ret = txfilter_hirestex(g64crc, r_crc64, palette, info);
+
+  return ret;
+}
+
+uint64 ext_ghq_checksum(unsigned char *src, int width, int height, int size, int rowStride, unsigned char *palette)
+{
+  uint64 ret = 0;
+
+  ret = txfilter_checksum(src, width, height, size, rowStride, palette);
+
+  return ret;
+}
+
+boolean ext_ghq_dmptx(unsigned char *src, int width, int height, int rowStridePixel, unsigned short gfmt, unsigned short n64fmt, uint64 r_crc64)
+{
+  boolean ret = 0;
+
+  ret = txfilter_dmptx(src, width, height, rowStridePixel, gfmt, n64fmt, r_crc64);
+
+  return ret;
+}
+
+boolean ext_ghq_reloadhirestex()
+{
+  boolean ret = 0;
+
+  ret = txfilter_reloadhirestex();
+
+  return ret;
+}
diff --git a/source/gles2glide64/src/GlideHQ/Ext_TxFilter.h b/source/gles2glide64/src/GlideHQ/Ext_TxFilter.h
new file mode 100644 (file)
index 0000000..c6d4803
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __EXT_TXFILTER_H__
+#define __EXT_TXFILTER_H__
+
+#ifdef WIN32
+#include <windows.h>
+#define TXHMODULE HMODULE
+#define DLOPEN(a) LoadLibraryW(a)
+#define DLCLOSE(a) FreeLibrary(a)
+#define DLSYM(a, b) GetProcAddress(a, b)
+#define GETCWD(a, b) GetCurrentDirectoryW(a, b)
+#define CHDIR(a) SetCurrentDirectoryW(a)
+#else
+#include <iostream>
+#include <dlfcn.h> 
+#define MAX_PATH 4095
+#define TXHMODULE void*
+#define DLOPEN(a) dlopen(a, RTLD_LAZY|RTLD_GLOBAL)
+#define DLCLOSE(a) dlclose(a)
+#define DLSYM(a, b) dlsym(a, b)
+#define GETCWD(a, b) getcwd(b, a)
+#define CHDIR(a) chdir(a)
+#endif
+
+#ifdef __MSC__
+typedef __int64 int64;
+typedef unsigned __int64 uint64;
+#else
+#include <stdint.h>
+typedef int64_t int64;
+typedef uint64_t uint64;
+typedef unsigned char boolean;
+#endif
+
+#define NO_OPTIONS          0x00000000
+
+#define FILTER_MASK         0x000000ff
+#define NO_FILTER           0x00000000
+#define SMOOTH_FILTER_MASK  0x0000000f
+#define NO_SMOOTH_FILTER    0x00000000
+#define SMOOTH_FILTER_1     0x00000001
+#define SMOOTH_FILTER_2     0x00000002
+#define SMOOTH_FILTER_3     0x00000003
+#define SMOOTH_FILTER_4     0x00000004
+#define SHARP_FILTER_MASK   0x000000f0
+#define NO_SHARP_FILTER     0x00000000
+#define SHARP_FILTER_1      0x00000010
+#define SHARP_FILTER_2      0x00000020
+
+#define ENHANCEMENT_MASK    0x00000f00
+#define NO_ENHANCEMENT      0x00000000
+#define X2_ENHANCEMENT      0x00000100
+#define X2SAI_ENHANCEMENT   0x00000200
+#define HQ2X_ENHANCEMENT    0x00000300
+#define LQ2X_ENHANCEMENT    0x00000400
+#define HQ4X_ENHANCEMENT    0x00000500
+#define HQ2XS_ENHANCEMENT   0x00000600
+#define LQ2XS_ENHANCEMENT   0x00000700
+
+#define COMPRESSION_MASK    0x0000f000
+#define NO_COMPRESSION      0x00000000
+#define FXT1_COMPRESSION    0x00001000
+#define NCC_COMPRESSION     0x00002000
+#define S3TC_COMPRESSION    0x00003000
+
+#define HIRESTEXTURES_MASK  0x000f0000
+#define NO_HIRESTEXTURES    0x00000000
+#define GHQ_HIRESTEXTURES   0x00010000
+#define RICE_HIRESTEXTURES  0x00020000
+#define JABO_HIRESTEXTURES  0x00030000
+
+#define COMPRESS_TEX        0x00100000
+#define COMPRESS_HIRESTEX   0x00200000
+#define GZ_TEXCACHE         0x00400000
+#define GZ_HIRESTEXCACHE    0x00800000
+#define DUMP_TEXCACHE       0x01000000
+#define DUMP_HIRESTEXCACHE  0x02000000
+#define TILE_HIRESTEX       0x04000000
+#define UNDEFINED_0         0x08000000
+#define FORCE16BPP_HIRESTEX 0x10000000
+#define FORCE16BPP_TEX      0x20000000
+#define LET_TEXARTISTS_FLY  0x40000000 /* a little freedom for texture artists */
+#define DUMP_TEX            0x80000000
+
+#ifndef __GLIDE_H__ /* GLIDE3 */
+/* from 3Dfx Interactive Inc. glide.h */
+#define GR_TEXFMT_ALPHA_8           0x2
+#define GR_TEXFMT_INTENSITY_8       0x3
+
+#define GR_TEXFMT_ALPHA_INTENSITY_44 0x4
+#define GR_TEXFMT_P_8                0x5
+
+#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
+
+/* from 3Dfx Interactive Inc. g3ext.h */
+#define GR_TEXFMT_ARGB_CMP_FXT1      0x11
+
+#define GR_TEXFMT_ARGB_8888          0x12
+
+#define GR_TEXFMT_ARGB_CMP_DXT1      0x16
+#define GR_TEXFMT_ARGB_CMP_DXT3      0x18
+#define GR_TEXFMT_ARGB_CMP_DXT5      0x1A
+#endif /* GLIDE3 */
+
+struct GHQTexInfo {
+
+  unsigned char *data;
+
+  int width;
+  int height;
+
+  int smallLodLog2;
+  int largeLodLog2;
+  int aspectRatioLog2;
+
+  int tiles;
+  int untiled_width;
+  int untiled_height;
+
+  unsigned short format;
+
+  unsigned char is_hires_tex;
+};
+
+/* Callback to display hires texture info.
+ * Gonetz <gonetz(at)ngs.ru>
+ *
+ * void DispInfo(const char *format, ...)
+ * {
+ *   va_list args;
+ *   char buf[INFO_BUF];
+ *
+ *   va_start(args, format);
+ *   vsprintf(buf, format, args);
+ *   va_end(args);
+ *
+ *   printf(buf);
+ * }
+ */
+#define INFO_BUF 4095
+typedef void (*dispInfoFuncExt)(const wchar_t *format, ...);
+
+#ifndef TXFILTER_DLL
+boolean ext_ghq_init(int maxwidth, /* maximum texture width supported by hardware */
+                     int maxheight,/* maximum texture height supported by hardware */
+                     int maxbpp,   /* maximum texture bpp supported by hardware */
+                     int options,  /* options */
+                     int cachesize,/* cache textures to system memory */
+                     wchar_t *datapath,   /* user data directory. must be smaller than MAX_PATH */
+                     wchar_t *cachepath,   /* user cache directory. must be smaller than MAX_PATH */
+                     wchar_t *ident,  /* name of ROM. must be no longer than 64 in character. */
+                     dispInfoFuncExt callback /* callback function to display info */
+                     );
+
+void ext_ghq_shutdown(void);
+
+boolean ext_ghq_txfilter(unsigned char *src,        /* input texture */
+                         int srcwidth,              /* width of input texture */
+                         int srcheight,             /* height of input texture */
+                         unsigned short srcformat,  /* format of input texture */
+                         uint64 g64crc,             /* glide64 crc */
+                         GHQTexInfo *info           /* output */
+                         );
+
+boolean ext_ghq_hirestex(uint64 g64crc,             /* glide64 crc */
+                         uint64 r_crc64,            /* checksum hi:palette low:texture */
+                         unsigned short *palette,   /* palette for CI textures */
+                         GHQTexInfo *info           /* output */
+                         );
+
+uint64 ext_ghq_checksum(unsigned char *src, /* input texture */
+                        int width,          /* width of texture */
+                        int height,         /* height of texture */
+                        int size,           /* type of texture pixel */
+                        int rowStride,      /* row stride in bytes */
+                        unsigned char *palette /* palette */
+                        );
+
+boolean ext_ghq_dmptx(unsigned char *src,   /* input texture (must be in 3Dfx Glide format) */
+                      int width,            /* width of texture */
+                      int height,           /* height of texture */
+                      int rowStridePixel,   /* row stride of input texture in pixels */
+                      unsigned short gfmt,  /* glide format of input texture */
+                      unsigned short n64fmt,/* N64 format hi:format low:size */
+                      uint64 r_crc64        /* checksum hi:palette low:texture */
+                      );
+
+boolean ext_ghq_reloadhirestex();
+#endif /* TXFILTER_DLL */
+
+#endif /* __EXT_TXFILTER_H__ */
diff --git a/source/gles2glide64/src/GlideHQ/README.txt b/source/gles2glide64/src/GlideHQ/README.txt
new file mode 100644 (file)
index 0000000..c903e57
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * GlideHQ (Texture enhancer library for Glide64)
+ * Version:  1.5
+ *
+ * Copyright (C) 2007  Hiroshi Morii aka KoolSmoky   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+About:
+This is a realtime texture enhancer library with hi-resolution texture
+pack support for Glide64 (http://glide64.emuxhaven.net). Traditional and
+non-traditional techniques have been used to achieve speed and high image
+quality even on a 9 year old 3Dfx Voodoo2.
+
+Although the 3Dfx Glide3x texture format naming conventions are used, the
+library can be expanded for generic use.
+
+Supported:
+OS: 32bit Linux and MS Windows
+Enhancers: Hq4x, Hq2x, Hq2xS, Lq2x, Lq2xS, Super2xSai, x2
+Filters: Smooth (1,2,3,4), Sharp (1,2)
+Compressors: FXT1, S3TC
+Input formats:  GR_TEXFMT_ALPHA_8,
+                GR_TEXFMT_RGB_565,
+                GR_TEXFMT_ARGB_1555,
+                GR_TEXFMT_ARGB_4444,
+                GR_TEXFMT_ARGB_8888,
+                GR_TEXFMT_ALPHA_INTENSITY_44,
+                GR_TEXFMT_ALPHA_INTENSITY_88
+Output formats: Same as input unless compression or hires packs are used.
+Hires texture packs: Rice format (Jabo and GlideHQ format coming later)
+
+Acknowledgments:
+I hope you enjoy GlideHQ (texture enhancer library for Glide64). Greatest
+thanks to Gonetz for making this happen in his busy time. We've rushed
+everything to share the eye-candy with all of you N64 emulation fans. I
+would also like to thank a great friend of mine, Daniel Borca for providing
+the texture compression code, Maxim Stepin (hq2x 4x), and Derek Liauw Kie Fa
+(2xSaI) for the filtering engines, Rice for his N64 graphics plugin source
+code, and Mudlord for the hq2xS lq2xS code. GlideHQ also uses the boost C++
+libraries, zlib general purpose compression library, and the Portable Network
+Graphics library. Thanks to all the developers for making them available. And
+special thanks to the Glide64 beta testing crew. Without their feedbacks
+this library would not have seen daylight. Thank you all.
+
+The source code for GlideHQ is released in hopes that it will be improved.
+I know the coding is not on par after so much late night caffeine boosts.
+If you have suggestions or modifications, please feel free to post them on
+the Glide64 forum at emuxhaven.
+
+Porting the library to other platforms should not be so hard. The coding is
+done with cross platform compatibility in mind and will build with GCC and
+GNU make. Currently supported are 32bit Linux and MS Windows.
+
+If you are looking for driver updates for your 3Dfx Interactive Inc. gfx 
+card, grab them from the forums at http://www.3dfxzone.it/enboard/
+Unbelievable as it seems, drivers are still being updated after 6 years
+from 3Dfx's demise.
+
+I know N64 rules, anyone up for PSX? :))
+
+-KoolSmoky
+
+References:
+[1] R.W. Floyd & L. Steinberg, An adaptive algorithm for spatial grey scale,
+    Proceedings of the Society of Information Display 17, pp75-77, 1976
+[2] Ken Turkowski, Filters for Common Resampling Tasks, Apple Computer 1990
+    http://www.worldserver.com/turk/computergraphics/ResamplingFilters.pdf
+[3] Don P. Mitchell and Arun N. Netravali, Reconstruction Filters in Computer
+    Graphics, SIGGRAPH '88, Proceedings of the 15th annual conference on
+    Computer graphics and interactive techniques, pp221-228, 1988
+[4] J. F. Kaiser and W. A. Reed, Data smoothing using low-pass digital
+    filters, Rev. Sci. instrum. 48 (11), pp1447-1457, 1977
+[5] Maxim Stepin, hq4x Magnification Filter, http://www.hiend3d.com/hq4x.html
+[6] Derek Liauw Kie Fa, 2xSaI, http://elektron.its.tudelft.nl/~dalikifa
+[7] Dirk Stevens, Eagle engine http://www.retrofx.com/rfxtech.html
+[8] 3DFX_texture_compression_FXT1 and EXT_texture_compression_s3tc extension
+    specs from the OpenGL Extension Registry. http://oss.sgi.com/projects/
+    ogl-sample/registry/
diff --git a/source/gles2glide64/src/GlideHQ/TextureFilters.cpp b/source/gles2glide64/src/GlideHQ/TextureFilters.cpp
new file mode 100644 (file)
index 0000000..b46dcb5
--- /dev/null
@@ -0,0 +1,702 @@
+/*
+Copyright (C) 2003 Rice1964
+
+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.
+
+*/
+
+/* Copyright (C) 2007 Hiroshi Morii <koolsmoky(at)users.sourceforge.net>
+ * Modified for the Texture Filtering library
+ */
+
+#include <string.h>
+#include "TextureFilters.h"
+
+/************************************************************************/
+/* 2X filters                                                           */
+/************************************************************************/
+
+#define DWORD_MAKE(r, g, b, a)   ((uint32) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)))
+#define WORD_MAKE(r, g, b, a)   ((uint16) (((a) << 12) | ((r) << 8) | ((g) << 4) | (b)))
+
+// Basic 2x R8G8B8A8 filter with interpolation
+
+void Texture2x_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height)
+{
+  uint32 *pDst1, *pDst2;
+  uint32 *pSrc, *pSrc2;
+  uint32 nWidth = width;
+  uint32 nHeight = height;
+
+  uint32 b1;
+  uint32 g1;
+  uint32 r1;
+  uint32 a1;
+  uint32 b2;
+  uint32 g2;
+  uint32 r2;
+  uint32 a2;
+  uint32 b3;
+  uint32 g3;
+  uint32 r3;
+  uint32 a3;
+  uint32 b4;
+  uint32 g4;
+  uint32 r4;
+  uint32 a4;
+
+  uint32 xSrc;
+  uint32 ySrc;
+
+  for (ySrc = 0; ySrc < nHeight; ySrc++)
+  {
+    pSrc = (uint32*)(((uint8*)srcPtr)+ySrc*srcPitch);
+    pSrc2 = (uint32*)(((uint8*)srcPtr)+(ySrc+1)*srcPitch);
+    pDst1 = (uint32*)(((uint8*)dstPtr)+(ySrc*2)*dstPitch);
+    pDst2 = (uint32*)(((uint8*)dstPtr)+(ySrc*2+1)*dstPitch);
+
+    for (xSrc = 0; xSrc < nWidth; xSrc++)
+    {
+      b1 = (pSrc[xSrc]>>0)&0xFF;
+      g1 = (pSrc[xSrc]>>8)&0xFF;
+      r1 = (pSrc[xSrc]>>16)&0xFF;
+      a1 = (pSrc[xSrc]>>24)&0xFF;
+
+      // Pixel 1
+      pDst1[xSrc*2] = pSrc[xSrc];
+
+      // Pixel 2
+      if( xSrc<nWidth-1 )
+      {
+        b2 = (pSrc[xSrc+1]>>0)&0xFF;
+        g2 = (pSrc[xSrc+1]>>8)&0xFF;
+        r2 = (pSrc[xSrc+1]>>16)&0xFF;
+        a2 = (pSrc[xSrc+1]>>24)&0xFF;
+        pDst1[xSrc*2+1] = DWORD_MAKE((r1+r2)/2, (g1+g2)/2, (b1+b2)/2, (a1+a2)/2);
+      }
+      else
+        pDst1[xSrc*2+1] = pSrc[xSrc];
+
+      // Pixel 3
+      if( ySrc<nHeight-1 )
+      {
+        b3 = (pSrc2[xSrc]>>0)&0xFF;
+        g3 = (pSrc2[xSrc]>>8)&0xFF;
+        r3 = (pSrc2[xSrc]>>16)&0xFF;
+        a3 = (pSrc2[xSrc]>>24)&0xFF;
+        pDst2[xSrc*2] = DWORD_MAKE((r1+r3)/2, (g1+g3)/2, (b1+b3)/2, (a1+a3)/2);
+        if( xSrc<nWidth-1 )
+        {
+          b4 = (pSrc2[xSrc+1]>>0)&0xFF;
+          g4 = (pSrc2[xSrc+1]>>8)&0xFF;
+          r4 = (pSrc2[xSrc+1]>>16)&0xFF;
+          a4 = (pSrc2[xSrc+1]>>24)&0xFF;
+          // Pixel 4
+          pDst2[xSrc*2+1] = DWORD_MAKE((r1+r2+r3+r4)/4, (g1+g2+g3+g4)/4, (b1+b2+b3+b4)/4, (a1+a2+a3+a4)/4);
+        }
+        else
+        {
+          // Pixel 4
+          pDst2[xSrc*2+1] = DWORD_MAKE((r1+r3)/2, (g1+g3)/2, (b1+b3)/2, (a1+a3)/2);
+        }
+      }
+      else
+      {
+        // Pixel 3
+        pDst2[xSrc*2] = pSrc[xSrc];
+        // Pixel 4
+        if( xSrc<nWidth-1 )
+        {
+          pDst2[xSrc*2+1] = DWORD_MAKE((r1+r2)/2, (g1+g2)/2, (b1+b2)/2, (a1+a2)/2);
+        }
+        else
+        {
+          pDst2[xSrc*2+1] = pSrc[xSrc];
+        }
+      }
+    }
+  }
+}
+
+#if !_16BPP_HACK
+// Basic 2x R4G4B4A4 filter with interpolation
+void Texture2x_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height)
+{
+  uint16 *pDst1, *pDst2;
+  uint16 *pSrc, *pSrc2;
+  uint32 nWidth = width;
+  uint32 nHeight = height;
+
+  uint16 b1;
+  uint16 g1;
+  uint16 r1;
+  uint16 a1;
+  uint16 b2;
+  uint16 g2;
+  uint16 r2;
+  uint16 a2;
+  uint16 b3;
+  uint16 g3;
+  uint16 r3;
+  uint16 a3;
+  uint16 b4;
+  uint16 g4;
+  uint16 r4;
+  uint16 a4;
+
+  uint16 xSrc;
+  uint16 ySrc;
+
+  for (ySrc = 0; ySrc < nHeight; ySrc++)
+  {
+    pSrc = (uint16*)(((uint8*)srcPtr)+ySrc*srcPitch);
+    pSrc2 = (uint16*)(((uint8*)srcPtr)+(ySrc+1)*srcPitch);
+    pDst1 = (uint16*)(((uint8*)dstPtr)+(ySrc*2)*dstPitch);
+    pDst2 = (uint16*)(((uint8*)dstPtr)+(ySrc*2+1)*dstPitch);
+
+    for (xSrc = 0; xSrc < nWidth; xSrc++)
+    {
+      b1 = (pSrc[xSrc]>> 0)&0xF;
+      g1 = (pSrc[xSrc]>> 4)&0xF;
+      r1 = (pSrc[xSrc]>> 8)&0xF;
+      a1 = (pSrc[xSrc]>>12)&0xF;
+
+      if( xSrc<nWidth-1 )
+      {
+        b2 = (pSrc[xSrc+1]>> 0)&0xF;
+        g2 = (pSrc[xSrc+1]>> 4)&0xF;
+        r2 = (pSrc[xSrc+1]>> 8)&0xF;
+        a2 = (pSrc[xSrc+1]>>12)&0xF;
+      }
+
+      if( ySrc<nHeight-1 )
+      {
+        b3 = (pSrc2[xSrc]>> 0)&0xF;
+        g3 = (pSrc2[xSrc]>> 4)&0xF;
+        r3 = (pSrc2[xSrc]>> 8)&0xF;
+        a3 = (pSrc2[xSrc]>>12)&0xF;
+        if( xSrc<nWidth-1 )
+        {
+          b4 = (pSrc2[xSrc+1]>> 0)&0xF;
+          g4 = (pSrc2[xSrc+1]>> 4)&0xF;
+          r4 = (pSrc2[xSrc+1]>> 8)&0xF;
+          a4 = (pSrc2[xSrc+1]>>12)&0xF;
+        }
+      }
+
+      // Pixel 1
+      pDst1[xSrc*2] = pSrc[xSrc];
+
+      // Pixel 2
+      if( xSrc<nWidth-1 )
+      {
+        pDst1[xSrc*2+1] = WORD_MAKE((r1+r2)/2, (g1+g2)/2, (b1+b2)/2, (a1+a2)/2);
+      }
+      else
+        pDst1[xSrc*2+1] = pSrc[xSrc];
+
+
+      // Pixel 3
+      if( ySrc<nHeight-1 )
+      {
+        pDst2[xSrc*2] = WORD_MAKE((r1+r3)/2, (g1+g3)/2, (b1+b3)/2, (a1+a3)/2);
+      }
+      else
+        pDst2[xSrc*2] = pSrc[xSrc];
+
+      // Pixel 4
+      if( xSrc<nWidth-1 )
+      {
+        if( ySrc<nHeight-1 )
+        {
+          pDst2[xSrc*2+1] = WORD_MAKE((r1+r2+r3+r4)/4, (g1+g2+g3+g4)/4, (b1+b2+b3+b4)/4, (a1+a2+a3+a4)/4);
+        }
+        else
+        {
+          pDst2[xSrc*2+1] = WORD_MAKE((r1+r2)/2, (g1+g2)/2, (b1+b2)/2, (a1+a2)/2);
+        }
+      }
+      else
+      {
+        if( ySrc<nHeight-1 )
+        {
+          pDst2[xSrc*2+1] = WORD_MAKE((r1+r3)/2, (g1+g3)/2, (b1+b3)/2, (a1+a3)/2);
+        }
+        else
+          pDst2[xSrc*2+1] = pSrc[xSrc];
+      }
+    }
+  }
+}
+#endif /* !_16BPP_HACK */
+
+/*
+ * Sharp filters
+ * Hiroshi Morii <koolsmoky@users.sourceforge.net>
+ */
+void SharpFilter_8888(uint32 *src, uint32 srcwidth, uint32 srcheight, uint32 *dest, uint32 filter)
+{
+  // NOTE: for now we get away with copying the boundaries
+  //       filter the boundaries if we face problems
+
+  uint32 mul1, mul2, mul3, shift4;
+
+  uint32 x,y,z;
+  uint32 *_src1, *_src2, *_src3, *_dest;
+  uint32 val[4];
+  uint32 t1,t2,t3,t4,t5,t6,t7,t8,t9;
+
+  switch( filter )
+  {
+  case SHARP_FILTER_2:
+    mul1=1;
+    mul2=8;
+    mul3=12;
+    shift4=2;
+    break;
+  case SHARP_FILTER_1:
+  default:
+    mul1=1;
+    mul2=8;
+    mul3=16;
+    shift4=3;
+    break;
+  }
+
+  // setup rows
+  _src1 = src;
+  _src2 = _src1 + srcwidth;
+  _src3 = _src2 + srcwidth;
+  _dest = dest;
+
+  // copy the first row
+  memcpy(_dest, _src1, (srcwidth << 2));
+  _dest += srcwidth;
+  // filter 2nd row to 1 row before the last
+  for (y = 1; y < srcheight-1; y++) {
+    // copy the first pixel
+    _dest[0] = *_src2;
+    // filter 2nd pixel to 1 pixel before last
+    for (x = 1; x < srcwidth-1; x++) {
+      for (z=0; z<4; z++) {
+        t1 = *((uint8*)(_src1+x-1)+z);
+        t2 = *((uint8*)(_src1+x  )+z);
+        t3 = *((uint8*)(_src1+x+1)+z);
+        t4 = *((uint8*)(_src2+x-1)+z);
+        t5 = *((uint8*)(_src2+x  )+z);
+        t6 = *((uint8*)(_src2+x+1)+z);
+        t7 = *((uint8*)(_src3+x-1)+z);
+        t8 = *((uint8*)(_src3+x  )+z);
+        t9 = *((uint8*)(_src3+x+1)+z);
+        
+        if( (t5*mul2) > (t1+t3+t7+t9+t2+t4+t6+t8)*mul1 ) {
+          val[z]= ((t5*mul3) - (t1+t3+t7+t9+t2+t4+t6+t8)*mul1)>>shift4;
+          if (val[z] > 0xFF) val[z] = 0xFF;
+        } else {
+          val[z] = t5;
+        }
+      }
+      _dest[x] = val[0]|(val[1]<<8)|(val[2]<<16)|(val[3]<<24);
+    }
+    // copy the ending pixel
+    _dest[srcwidth-1] = *(_src3 - 1);
+    // next row
+    _src1 += srcwidth;
+    _src2 += srcwidth;
+    _src3 += srcwidth;
+    _dest += srcwidth;
+  }
+  // copy the last row
+  memcpy(_dest, _src2, (srcwidth << 2));
+}
+
+#if !_16BPP_HACK
+void SharpFilter_4444(uint16 *src, uint32 srcwidth, uint32 srcheight, uint16 *dest, uint32 filter)
+{
+  // NOTE: for now we get away with copying the boundaries
+  //       filter the boundaries if we face problems
+
+  uint16 mul1, mul2, mul3, shift4;
+
+  uint32 x,y,z;
+  uint16 *_src1, *_src2, *_src3, *_dest;
+  uint16 val[4];
+  uint16 t1,t2,t3,t4,t5,t6,t7,t8,t9;
+
+  switch( filter ) {
+  case SHARP_FILTER_2:
+    mul1=1;
+    mul2=8;
+    mul3=12;
+    shift4=2;
+    break;
+  case SHARP_FILTER_1:
+  default:
+    mul1=1;
+    mul2=8;
+    mul3=16;
+    shift4=3;
+    break;
+  }
+
+  // setup rows
+  _src1 = src;
+  _src2 = _src1 + srcwidth;
+  _src3 = _src2 + srcwidth;
+  _dest = dest;
+
+  // copy the first row
+  memcpy(_dest, _src1, (srcwidth << 1));
+  _dest += srcwidth;
+  // filter 2nd row to 1 row before the last
+  for( y = 1; y < srcheight - 1; y++) {
+    // copy the first pixel
+    _dest[0] = *_src2;
+    // filter 2nd pixel to 1 pixel before last
+    for( x = 1; x < srcwidth - 1; x++) {
+      for( z = 0; z < 4; z++ ) {
+        /* Hiroshi Morii <koolsmoky@users.sourceforge.net>
+         * Read the entire 16bit pixel and then extract the A,R,G,B components.
+         */
+        uint32 shift = z << 2;
+        t1 = ((*((uint16*)(_src1+x-1))) >> shift) & 0xF;
+        t2 = ((*((uint16*)(_src1+x  ))) >> shift) & 0xF;
+        t3 = ((*((uint16*)(_src1+x+1))) >> shift) & 0xF;
+        t4 = ((*((uint16*)(_src2+x-1))) >> shift) & 0xF;
+        t5 = ((*((uint16*)(_src2+x  ))) >> shift) & 0xF;
+        t6 = ((*((uint16*)(_src2+x+1))) >> shift) & 0xF;
+        t7 = ((*((uint16*)(_src3+x-1))) >> shift) & 0xF;
+        t8 = ((*((uint16*)(_src3+x  ))) >> shift) & 0xF;
+        t9 = ((*((uint16*)(_src3+x+1))) >> shift) & 0xF;
+        
+        if( (t5*mul2) > (t1+t3+t7+t9+t2+t4+t6+t8)*mul1 ) {
+          val[z] = ((t5*mul3) - (t1+t3+t7+t9+t2+t4+t6+t8)*mul1)>>shift4;
+          if (val[z] > 0xF) val[z] = 0xF;
+        } else {
+          val[z] = t5;
+        }
+      }
+      _dest[x] = val[0]|(val[1]<<4)|(val[2]<<8)|(val[3]<<12);
+    }
+    // copy the ending pixel
+    _dest[srcwidth-1] = *(_src3 - 1);
+    // next row
+    _src1 += srcwidth;
+    _src2 += srcwidth;
+    _src3 += srcwidth;
+    _dest += srcwidth;
+  }
+  // copy the last row
+  memcpy(_dest, _src2, (srcwidth << 1));
+}
+#endif /* !_16BPP_HACK */
+
+/*
+ * Smooth filters
+ * Hiroshi Morii <koolsmoky@users.sourceforge.net>
+ */
+void SmoothFilter_8888(uint32 *src, uint32 srcwidth, uint32 srcheight, uint32 *dest, uint32 filter)
+{
+  // NOTE: for now we get away with copying the boundaries
+  //       filter the boundaries if we face problems
+
+  uint32 mul1, mul2, mul3, shift4;
+
+  uint32 x,y,z;
+  uint32 *_src1, *_src2, *_src3, *_dest;
+  uint32 val[4];
+  uint32 t1,t2,t3,t4,t5,t6,t7,t8,t9;
+
+  switch( filter ) {
+  case SMOOTH_FILTER_4:
+    mul1=1;
+    mul2=2;
+    mul3=4;
+    shift4=4;
+    break;
+  case SMOOTH_FILTER_3:
+    mul1=1;
+    mul2=1;
+    mul3=8;
+    shift4=4;
+    break;
+  case SMOOTH_FILTER_2:
+    mul1=1;
+    mul2=1;
+    mul3=2;
+    shift4=2;
+    break;
+  case SMOOTH_FILTER_1:
+  default:
+    mul1=1;
+    mul2=1;
+    mul3=6;
+    shift4=3;
+    break;
+  }
+
+  switch (filter) {
+  case SMOOTH_FILTER_3:
+  case SMOOTH_FILTER_4:
+    // setup rows
+    _src1 = src;
+    _src2 = _src1 + srcwidth;
+    _src3 = _src2 + srcwidth;
+    _dest = dest;
+    // copy the first row
+    memcpy(_dest, _src1, (srcwidth << 2));
+    _dest += srcwidth;
+    // filter 2nd row to 1 row before the last
+    for (y = 1; y < srcheight - 1; y++){
+      // copy the first pixel
+      _dest[0] = _src2[0];
+      // filter 2nd pixel to 1 pixel before last
+      for (x = 1; x < srcwidth - 1; x++) {
+        for (z = 0; z < 4; z++ ) {
+          t1 = *((uint8*)(_src1+x-1)+z);
+          t2 = *((uint8*)(_src1+x  )+z);
+          t3 = *((uint8*)(_src1+x+1)+z);
+          t4 = *((uint8*)(_src2+x-1)+z);
+          t5 = *((uint8*)(_src2+x  )+z);
+          t6 = *((uint8*)(_src2+x+1)+z);
+          t7 = *((uint8*)(_src3+x-1)+z);
+          t8 = *((uint8*)(_src3+x  )+z);
+          t9 = *((uint8*)(_src3+x+1)+z);
+          /* the component value must not overflow 0xFF */
+          val[z] = ((t1+t3+t7+t9)*mul1+((t2+t4+t6+t8)*mul2)+(t5*mul3))>>shift4;
+          if (val[z] > 0xFF) val[z] = 0xFF;
+        }
+        _dest[x] = val[0]|(val[1]<<8)|(val[2]<<16)|(val[3]<<24);
+      }
+      // copy the ending pixel
+      _dest[srcwidth-1] = *(_src3 - 1);
+      // next row
+      _src1 += srcwidth;
+      _src2 += srcwidth;
+      _src3 += srcwidth;
+      _dest += srcwidth;
+    }
+    // copy the last row
+    memcpy(_dest, _src2, (srcwidth << 2));
+    break;
+  case SMOOTH_FILTER_1:
+  case SMOOTH_FILTER_2:
+  default:
+    // setup rows
+    _src1 = src;
+    _src2 = _src1 + srcwidth;
+    _src3 = _src2 + srcwidth;
+    _dest = dest;
+    // copy the first row
+    memcpy(_dest, _src1, (srcwidth << 2));
+    _dest += srcwidth;
+    // filter 2nd row to 1 row before the last
+    for (y = 1; y < srcheight - 1; y++) {
+      // filter 1st pixel to the last
+      if (y & 1) {
+        for( x = 0; x < srcwidth; x++) {
+          for( z = 0; z < 4; z++ ) {
+            t2 = *((uint8*)(_src1+x  )+z);
+            t5 = *((uint8*)(_src2+x  )+z);
+            t8 = *((uint8*)(_src3+x  )+z);
+            /* the component value must not overflow 0xFF */
+            val[z] = ((t2+t8)*mul2+(t5*mul3))>>shift4;
+            if (val[z] > 0xFF) val[z] = 0xFF;
+          }
+          _dest[x] = val[0]|(val[1]<<8)|(val[2]<<16)|(val[3]<<24);
+        }
+      } else {
+         memcpy(_dest, _src2, (srcwidth << 2));
+      }
+      // next row
+      _src1 += srcwidth;
+      _src2 += srcwidth;
+      _src3 += srcwidth;
+      _dest += srcwidth;
+    }
+    // copy the last row
+    memcpy(_dest, _src2, (srcwidth << 2));
+    break;
+  }
+}
+
+#if !_16BPP_HACK
+void SmoothFilter_4444(uint16 *src, uint32 srcwidth, uint32 srcheight, uint16 *dest, uint32 filter)
+{
+  // NOTE: for now we get away with copying the boundaries
+  //       filter the boundaries if we face problems
+
+  uint16 mul1, mul2, mul3, shift4;
+
+  uint32 x,y,z;
+  uint16 *_src1, *_src2, *_src3, *_dest;
+  uint16 val[4];
+  uint16 t1,t2,t3,t4,t5,t6,t7,t8,t9;
+
+  switch( filter ) {
+  case SMOOTH_FILTER_4:
+    mul1=1;
+    mul2=2;
+    mul3=4;
+    shift4=4;
+    break;
+  case SMOOTH_FILTER_3:
+    mul1=1;
+    mul2=1;
+    mul3=8;
+    shift4=4;
+    break;
+  case SMOOTH_FILTER_2:
+    mul1=1;
+    mul2=1;
+    mul3=2;
+    shift4=2;
+    break;
+  case SMOOTH_FILTER_1:
+  default:
+    mul1=1;
+    mul2=1;
+    mul3=6;
+    shift4=3;
+    break;
+  }
+
+  switch (filter) {
+  case SMOOTH_FILTER_3:
+  case SMOOTH_FILTER_4:
+    // setup rows
+    _src1 = src;
+    _src2 = _src1 + srcwidth;
+    _src3 = _src2 + srcwidth;
+    _dest = dest;
+    // copy the first row
+    memcpy(_dest, _src1, (srcwidth << 1));
+    _dest += srcwidth;
+    // filter 2nd row to 1 row before the last
+    for (y = 1; y < srcheight - 1; y++) {
+      // copy the first pixel
+      _dest[0] = *_src2;
+      // filter 2nd pixel to 1 pixel before last
+      for (x = 1; x < srcwidth - 1; x++) {
+        for (z = 0; z < 4; z++ ) {
+          /* Read the entire 16bit pixel and then extract the A,R,G,B components. */
+          uint32 shift = z << 2;
+          t1 = ((*(uint16*)(_src1+x-1)) >> shift) & 0xF;
+          t2 = ((*(uint16*)(_src1+x  )) >> shift) & 0xF;
+          t3 = ((*(uint16*)(_src1+x+1)) >> shift) & 0xF;
+          t4 = ((*(uint16*)(_src2+x-1)) >> shift) & 0xF;
+          t5 = ((*(uint16*)(_src2+x  )) >> shift) & 0xF;
+          t6 = ((*(uint16*)(_src2+x+1)) >> shift) & 0xF;
+          t7 = ((*(uint16*)(_src3+x-1)) >> shift) & 0xF;
+          t8 = ((*(uint16*)(_src3+x  )) >> shift) & 0xF;
+          t9 = ((*(uint16*)(_src3+x+1)) >> shift) & 0xF;
+          /* the component value must not overflow 0xF */
+          val[z] = ((t1+t3+t7+t9)*mul1+((t2+t4+t6+t8)*mul2)+(t5*mul3))>>shift4;
+          if (val[z] > 0xF) val[z] = 0xF;
+        }
+        _dest[x] = val[0]|(val[1]<<4)|(val[2]<<8)|(val[3]<<12);
+      }
+      // copy the ending pixel
+      _dest[srcwidth-1] = *(_src3 - 1);
+      // next row
+      _src1 += srcwidth;
+      _src2 += srcwidth;
+      _src3 += srcwidth;
+      _dest += srcwidth;
+    }
+    // copy the last row
+    memcpy(_dest, _src2, (srcwidth << 1));
+    break;
+  case SMOOTH_FILTER_1:
+  case SMOOTH_FILTER_2:
+  default:
+    // setup rows
+    _src1 = src;
+    _src2 = _src1 + srcwidth;
+    _src3 = _src2 + srcwidth;
+    _dest = dest;
+    // copy the first row
+    memcpy(_dest, _src1, (srcwidth << 1));
+    _dest += srcwidth;
+    // filter 2nd row to 1 row before the last
+    for( y = 1; y < srcheight - 1; y++) {
+      if (y & 1) {
+        for( x = 0; x < srcwidth; x++) {
+          for( z = 0; z < 4; z++ ) {
+            /* Read the entire 16bit pixel and then extract the A,R,G,B components. */
+            uint32 shift = z << 2;
+            t2 = ((*(uint16*)(_src1+x)) >> shift) & 0xF;
+            t5 = ((*(uint16*)(_src2+x)) >> shift) & 0xF;
+            t8 = ((*(uint16*)(_src3+x)) >> shift) & 0xF;
+            /* the component value must not overflow 0xF */
+            val[z] = ((t2+t8)*mul2+(t5*mul3))>>shift4;
+            if (val[z] > 0xF) val[z] = 0xF;
+          }
+          _dest[x] = val[0]|(val[1]<<4)|(val[2]<<8)|(val[3]<<12);
+        }
+      } else {
+         memcpy(_dest, _src2, (srcwidth << 1));
+      }
+      // next row
+      _src1 += srcwidth;
+      _src2 += srcwidth;
+      _src3 += srcwidth;
+      _dest += srcwidth;
+    }
+    // copy the last row
+    memcpy(_dest, _src2, (srcwidth << 1));
+    break;
+  }
+}
+#endif /* !_16BPP_HACK */
+
+void filter_8888(uint32 *src, uint32 srcwidth, uint32 srcheight, uint32 *dest, uint32 filter) {
+  switch (filter & ENHANCEMENT_MASK) {
+  case HQ4X_ENHANCEMENT:
+    hq4x_8888((uint8*)src, (uint8*)dest, srcwidth, srcheight, srcwidth, (srcwidth << 4));
+    return;
+  case HQ2X_ENHANCEMENT:
+    hq2x_32((uint8*)src, (srcwidth << 2), (uint8*)dest, (srcwidth << 3), srcwidth, srcheight);
+    return;
+  case HQ2XS_ENHANCEMENT:
+    hq2xS_32((uint8*)src, (srcwidth << 2), (uint8*)dest, (srcwidth << 3), srcwidth, srcheight);
+    return;
+  case LQ2X_ENHANCEMENT:
+    lq2x_32((uint8*)src, (srcwidth << 2), (uint8*)dest, (srcwidth << 3), srcwidth, srcheight);
+    return;
+  case LQ2XS_ENHANCEMENT:
+    lq2xS_32((uint8*)src, (srcwidth << 2), (uint8*)dest, (srcwidth << 3), srcwidth, srcheight);
+    return;
+  case X2SAI_ENHANCEMENT:
+    Super2xSaI_8888((uint32*)src, (uint32*)dest, srcwidth, srcheight, srcwidth);
+    return;
+  case X2_ENHANCEMENT:
+    Texture2x_32((uint8*)src, (srcwidth << 2), (uint8*)dest, (srcwidth << 3), srcwidth, srcheight);
+    return;
+  }
+
+  switch (filter & (SMOOTH_FILTER_MASK|SHARP_FILTER_MASK)) {
+  case SMOOTH_FILTER_1:
+  case SMOOTH_FILTER_2:
+  case SMOOTH_FILTER_3:
+  case SMOOTH_FILTER_4:
+    SmoothFilter_8888((uint32*)src, srcwidth, srcheight, (uint32*)dest, (filter & SMOOTH_FILTER_MASK));
+    return;
+  case SHARP_FILTER_1:
+  case SHARP_FILTER_2:
+    SharpFilter_8888((uint32*)src, srcwidth, srcheight, (uint32*)dest, (filter & SHARP_FILTER_MASK));
+    return;
+  }
+}
diff --git a/source/gles2glide64/src/GlideHQ/TextureFilters.h b/source/gles2glide64/src/GlideHQ/TextureFilters.h
new file mode 100644 (file)
index 0000000..7830eac
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifndef __TEXTUREFILTERS_H__
+#define __TEXTUREFILTERS_H__
+
+/* 16bpp filters are somewhat buggy and output image is not clean.
+ * Since there's not much time, we'll just convert them to ARGB8888
+ * and use 32bpp filters until fixed.
+ * (1:enable hack, 0:disable hack) */
+#define _16BPP_HACK 1
+
+#include "TxInternal.h"
+
+/* enhancers */
+void hq4x_8888(unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL);
+
+void hq2x_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);
+void hq2xS_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);
+
+void lq2x_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);
+void lq2xS_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);
+
+void Super2xSaI_8888(uint32 *srcPtr, uint32 *destPtr, uint32 width, uint32 height, uint32 pitch);
+
+void Texture2x_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);
+
+/* filters */
+void SharpFilter_8888(uint32 *src, uint32 srcwidth, uint32 srcheight, uint32 *dest, uint32 filter);
+
+void SmoothFilter_8888(uint32 *src, uint32 srcwidth, uint32 srcheight, uint32 *dest, uint32 filter);
+
+/* helper */
+void filter_8888(uint32 *src, uint32 srcwidth, uint32 srcheight, uint32 *dest, uint32 filter);
+
+#if !_16BPP_HACK
+void hq4x_init(void);
+void hq4x_4444(unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL);
+void hq4x_1555(unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL);
+void hq4x_565 (unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL);
+
+void hq2x_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);
+void hq2xS_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);
+
+void lq2x_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);
+void lq2xS_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);
+
+void Super2xSaI_4444(uint16 *srcPtr, uint16 *destPtr, uint32 width, uint32 height, uint32 pitch);
+void Super2xSaI_1555(uint16 *srcPtr, uint16 *destPtr, uint32 width, uint32 height, uint32 pitch);
+void Super2xSaI_565 (uint16 *srcPtr, uint16 *destPtr, uint32 width, uint32 height, uint32 pitch);
+void Super2xSaI_8   (uint8  *srcPtr, uint8  *destPtr, uint32 width, uint32 height, uint32 pitch);
+
+void Texture2x_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);
+
+void SharpFilter_4444(uint16 *src, uint32 srcwidth, uint32 srcheight, uint16 *dest, uint32 filter);
+
+void SmoothFilter_4444(uint16 *src, uint32 srcwidth, uint32 srcheight, uint16 *dest, uint32 filter);
+#endif
+
+#endif /* __TEXTUREFILTERS_H__ */
diff --git a/source/gles2glide64/src/GlideHQ/TextureFilters_2xsai.cpp b/source/gles2glide64/src/GlideHQ/TextureFilters_2xsai.cpp
new file mode 100644 (file)
index 0000000..d7e8305
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Based on Derek Liauw Kie Fa and Rice1964 Super2xSaI code */
+
+#include "TextureFilters.h"
+
+#define GET_RESULT(A, B, C, D) ((A != C || A != D) - (B != C || B != D))
+
+void Super2xSaI_8888(uint32 *srcPtr, uint32 *destPtr, uint32 width, uint32 height, uint32 pitch)
+{
+#define SAI_INTERPOLATE_8888(A, B) ((A & 0xFEFEFEFE) >> 1) + ((B & 0xFEFEFEFE) >> 1) + (A & B & 0x01010101)
+#define SAI_Q_INTERPOLATE_8888(A, B, C, D) ((A & 0xFCFCFCFC) >> 2) + ((B & 0xFCFCFCFC) >> 2) + ((C & 0xFCFCFCFC) >> 2) + ((D & 0xFCFCFCFC) >> 2) \
+  + ((((A & 0x03030303) + (B & 0x03030303) + (C & 0x03030303) + (D & 0x03030303)) >> 2) & 0x03030303)
+
+#define SAI_INTERPOLATE SAI_INTERPOLATE_8888
+#define SAI_Q_INTERPOLATE SAI_Q_INTERPOLATE_8888
+
+  uint32 destWidth = width << 1;
+  
+  uint32 color4, color5, color6;
+  uint32 color1, color2, color3;
+  uint32 colorA0, colorA1, colorA2, colorA3;
+  uint32 colorB0, colorB1, colorB2, colorB3;
+  uint32 colorS1, colorS2;
+  uint32 product1a, product1b, product2a, product2b;
+
+#include "TextureFilters_2xsai.h"
+
+#undef SAI_INTERPOLATE
+#undef SAI_Q_INTERPOLATE
+}
+
+#if !_16BPP_HACK
+void Super2xSaI_4444(uint16 *srcPtr, uint16 *destPtr, uint32 width, uint32 height, uint32 pitch)
+{
+#define SAI_INTERPOLATE_4444(A, B) ((A & 0xEEEE) >> 1) + ((B & 0xEEEE) >> 1) + (A & B & 0x1111)
+#define SAI_Q_INTERPOLATE_4444(A, B, C, D) ((A & 0xCCCC) >> 2) + ((B & 0xCCCC) >> 2) + ((C & 0xCCCC) >> 2) + ((D & 0xCCCC) >> 2) \
+  + ((((A & 0x3333) + (B & 0x3333) + (C & 0x3333) + (D & 0x3333)) >> 2) & 0x3333)
+
+#define SAI_INTERPOLATE SAI_INTERPOLATE_4444
+#define SAI_Q_INTERPOLATE SAI_Q_INTERPOLATE_4444
+
+  uint32 destWidth = width << 1;
+  uint32 destHeight = height << 1;
+
+  uint16 color4, color5, color6;
+  uint16 color1, color2, color3;
+  uint16 colorA0, colorA1, colorA2, colorA3;
+  uint16 colorB0, colorB1, colorB2, colorB3;
+  uint16 colorS1, colorS2;
+  uint16 product1a, product1b, product2a, product2b;
+
+#include "TextureFilters_2xsai.h"
+
+#undef SAI_INTERPOLATE
+#undef SAI_Q_INTERPOLATE
+}
+
+void Super2xSaI_1555(uint16 *srcPtr, uint16 *destPtr, uint32 width, uint32 height, uint32 pitch)
+{
+#define SAI_INTERPOLATE_1555(A, B) ((A & 0x7BDE) >> 1) + ((B & 0x7BDE) >> 1) + (A & B & 0x8421)
+#define SAI_Q_INTERPOLATE_1555(A, B, C, D) ((A & 0x739C) >> 2) + ((B & 0x739C) >> 2) + ((C & 0x739C) >> 2) + ((D & 0x739C) >> 2) \
+  + ((((A & 0x8C63) + (B & 0x8C63) + (C & 0x8C63) + (D & 0x8C63)) >> 2) & 0x8C63)
+
+#define SAI_INTERPOLATE SAI_INTERPOLATE_1555
+#define SAI_Q_INTERPOLATE SAI_Q_INTERPOLATE_1555
+
+  uint32 destWidth = width << 1;
+  uint32 destHeight = height << 1;
+
+  uint16 color4, color5, color6;
+  uint16 color1, color2, color3;
+  uint16 colorA0, colorA1, colorA2, colorA3;
+  uint16 colorB0, colorB1, colorB2, colorB3;
+  uint16 colorS1, colorS2;
+  uint16 product1a, product1b, product2a, product2b;
+
+#include "TextureFilters_2xsai.h"
+
+#undef SAI_INTERPOLATE
+#undef SAI_Q_INTERPOLATE
+}
+
+void Super2xSaI_565(uint16 *srcPtr, uint16 *destPtr, uint32 width, uint32 height, uint32 pitch)
+{
+#define SAI_INTERPOLATE_565(A, B) ((A & 0xF7DE) >> 1) + ((B & 0xF7DE) >> 1) + (A & B & 0x0821)
+#define SAI_Q_INTERPOLATE_565(A, B, C, D) ((A & 0xE79C) >> 2) + ((B & 0xE79C) >> 2) + ((C & 0xE79C) >> 2) + ((D & 0xE79C) >> 2) \
+  + ((((A & 0x1863) + (B & 0x1863) + (C & 0x1863) + (D & 0x1863)) >> 2) & 0x1863)
+
+#define SAI_INTERPOLATE SAI_INTERPOLATE_565
+#define SAI_Q_INTERPOLATE SAI_Q_INTERPOLATE_565
+
+  uint32 destWidth = width << 1;
+  uint32 destHeight = height << 1;
+
+  uint16 color4, color5, color6;
+  uint16 color1, color2, color3;
+  uint16 colorA0, colorA1, colorA2, colorA3;
+  uint16 colorB0, colorB1, colorB2, colorB3;
+  uint16 colorS1, colorS2;
+  uint16 product1a, product1b, product2a, product2b;
+
+#include "TextureFilters_2xsai.h"
+
+#undef SAI_INTERPOLATE
+#undef SAI_Q_INTERPOLATE
+}
+
+void Super2xSaI_8(uint8 *srcPtr, uint8 *destPtr, uint32 width, uint32 height, uint32 pitch)
+{
+#define SAI_INTERPOLATE_8(A, B) ((A & 0xFE) >> 1) + ((B & 0xFE) >> 1) + (A & B & 0x01)
+#define SAI_Q_INTERPOLATE_8(A, B, C, D) ((A & 0xFC) >> 2) + ((B & 0xFC) >> 2) + ((C & 0xFC) >> 2) + ((D & 0xFC) >> 2) \
+  + ((((A & 0x03) + (B & 0x03) + (C & 0x03) + (D & 0x03)) >> 2) & 0x03)
+
+#define SAI_INTERPOLATE SAI_INTERPOLATE_8
+#define SAI_Q_INTERPOLATE SAI_Q_INTERPOLATE_8
+
+  uint32 destWidth = width << 1;
+  uint32 destHeight = height << 1;
+
+  uint8 color4, color5, color6;
+  uint8 color1, color2, color3;
+  uint8 colorA0, colorA1, colorA2, colorA3;
+  uint8 colorB0, colorB1, colorB2, colorB3;
+  uint8 colorS1, colorS2;
+  uint8 product1a, product1b, product2a, product2b;
+
+#include "TextureFilters_2xsai.h"
+
+#undef SAI_INTERPOLATE
+#undef SAI_Q_INTERPOLATE
+}
+#endif /* !_16BPP_HACK */
diff --git a/source/gles2glide64/src/GlideHQ/TextureFilters_2xsai.h b/source/gles2glide64/src/GlideHQ/TextureFilters_2xsai.h
new file mode 100644 (file)
index 0000000..f6696ae
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Based on Derek Liauw Kie Fa and Rice1964 Super2xSaI code */
+
+  int row0, row1, row2, row3;
+  int col0, col1, col2, col3;
+
+  uint16 x;
+  uint16 y;
+
+  for (y = 0; y < height; y++) {
+    if ((y > 0) && (y < height - 1)) {
+      row0 = width;
+      row0 = -row0;
+      row1 = 0;
+      row2 = width;
+      row3 = (y == height - 2 ? width : width << 1);
+    } else {
+      row0 = 0;
+      row1 = 0;
+      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) && (x < width - 1)) {
+        col0 = -1;
+        col1 = 0;
+        col2 = 1;
+        col3 = (x == width - 2 ? 1 : 2);
+      } else {
+        col0 = 0;
+        col1 = 0;
+        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 += GET_RESULT(color6, color5, color1, colorA1);
+        r += GET_RESULT(color6, color5, color4, colorB1);
+        r += GET_RESULT(color6, color5, colorA2, colorS1);
+        r += GET_RESULT(color6, color5, colorB2, colorS2);
+
+        if (r > 0)
+          product2b = product1b = color6;
+        else if (r < 0)
+          product2b = product1b = color5;
+        else
+          product2b = product1b = SAI_INTERPOLATE(color5, color6);
+
+      } else {
+
+        if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0)
+          product2b = SAI_Q_INTERPOLATE(color3, color3, color3, color2);
+        else if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3)
+          product2b = SAI_Q_INTERPOLATE(color2, color2, color2, color3);
+        else
+          product2b = SAI_INTERPOLATE(color2, color3);
+
+        if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0)
+          product1b = SAI_Q_INTERPOLATE(color6, color6, color6, color5);
+        else if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3)
+          product1b = SAI_Q_INTERPOLATE(color6, color5, color5, color5);
+        else
+          product1b = SAI_INTERPOLATE(color5, color6);
+      }
+
+      if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2)
+        product2a = SAI_INTERPOLATE(color2, color5);
+      else if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0)
+        product2a = SAI_INTERPOLATE(color2, color5);
+      else
+        product2a = color2;
+
+      if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2)
+        product1a = SAI_INTERPOLATE(color2, color5);
+      else if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0)
+        product1a = SAI_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/source/gles2glide64/src/GlideHQ/TextureFilters_hq2x.cpp b/source/gles2glide64/src/GlideHQ/TextureFilters_hq2x.cpp
new file mode 100644 (file)
index 0000000..448fd30
--- /dev/null
@@ -0,0 +1,1412 @@
+/*
+Copyright (C) 2003 Rice1964
+
+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.
+
+*/
+
+/* Copyright (C) 2007 Hiroshi Morii <koolsmoky(at)users.sourceforge.net>
+ * Modified for the Texture Filtering library
+ */
+
+/* 2007 Mudlord - Added hq2xS lq2xS filters */
+
+#include "TextureFilters.h"
+
+/************************************************************************/
+/* hq2x filters                                                         */
+/************************************************************************/
+
+/***************************************************************************/
+/* Basic types */
+
+/***************************************************************************/
+/* interpolation */
+
+//static unsigned interp_bits_per_pixel;
+
+#if !_16BPP_HACK
+#define INTERP_16_MASK_1_3(v) ((v)&0x0F0F)
+#define INTERP_16_MASK_SHIFT_2_4(v) (((v)&0xF0F0)>>4)
+#define INTERP_16_MASK_SHIFTBACK_2_4(v) ((INTERP_16_MASK_1_3(v))<<4)
+
+static uint16 hq2x_interp_16_521(uint16 p1, uint16 p2, uint16 p3)
+{
+  return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*5 + INTERP_16_MASK_1_3(p2)*2 + INTERP_16_MASK_1_3(p3)*1) / 8)
+    | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*5 + INTERP_16_MASK_SHIFT_2_4(p2)*2 + INTERP_16_MASK_SHIFT_2_4(p3)*1) / 8);
+}
+
+static uint16 hq2x_interp_16_332(uint16 p1, uint16 p2, uint16 p3)
+{
+  return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*3 + INTERP_16_MASK_1_3(p2)*3 + INTERP_16_MASK_1_3(p3)*2) / 8)
+    | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*3 + INTERP_16_MASK_SHIFT_2_4(p2)*3 + INTERP_16_MASK_SHIFT_2_4(p3)*2) / 8);
+}
+
+static uint16 hq2x_interp_16_611(uint16 p1, uint16 p2, uint16 p3)
+{
+  return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*6 + INTERP_16_MASK_1_3(p2) + INTERP_16_MASK_1_3(p3)) / 8)
+    | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*6 + INTERP_16_MASK_SHIFT_2_4(p2) + INTERP_16_MASK_SHIFT_2_4(p3)) / 8);
+}
+
+static uint16 hq2x_interp_16_71(uint16 p1, uint16 p2)
+{
+  return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*7 + INTERP_16_MASK_1_3(p2)) / 8)
+    | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*7 + INTERP_16_MASK_SHIFT_2_4(p2)) / 8);
+}
+
+static uint16 hq2x_interp_16_211(uint16 p1, uint16 p2, uint16 p3)
+{
+  return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*2 + INTERP_16_MASK_1_3(p2) + INTERP_16_MASK_1_3(p3)) / 4)
+    | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*2 + INTERP_16_MASK_SHIFT_2_4(p2) + INTERP_16_MASK_SHIFT_2_4(p3)) / 4);
+}
+
+static uint16 hq2x_interp_16_772(uint16 p1, uint16 p2, uint16 p3)
+{
+  return INTERP_16_MASK_1_3(((INTERP_16_MASK_1_3(p1) + INTERP_16_MASK_1_3(p2))*7 + INTERP_16_MASK_1_3(p3)*2) / 16)
+    | INTERP_16_MASK_SHIFTBACK_2_4(((INTERP_16_MASK_SHIFT_2_4(p1) + INTERP_16_MASK_SHIFT_2_4(p2))*7 + INTERP_16_MASK_SHIFT_2_4(p3)*2) / 16);
+}
+
+static uint16 hq2x_interp_16_11(uint16 p1, uint16 p2)
+{
+  return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1) + INTERP_16_MASK_1_3(p2)) / 2)
+    | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1) + INTERP_16_MASK_SHIFT_2_4(p2)) / 2);
+}
+
+static uint16 hq2x_interp_16_31(uint16 p1, uint16 p2)
+{
+  return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*3 + INTERP_16_MASK_1_3(p2)) / 4)
+    | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*3 + INTERP_16_MASK_SHIFT_2_4(p2)) / 4);
+}
+
+static uint16 hq2x_interp_16_1411(uint16 p1, uint16 p2, uint16 p3)
+{
+  return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*14 + INTERP_16_MASK_1_3(p2) + INTERP_16_MASK_1_3(p3)) / 16)
+    | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*14 + INTERP_16_MASK_SHIFT_2_4(p2) + INTERP_16_MASK_SHIFT_2_4(p3)) / 16);
+}
+
+static uint16 hq2x_interp_16_431(uint16 p1, uint16 p2, uint16 p3)
+{
+  return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*4 + INTERP_16_MASK_1_3(p2)*3 + INTERP_16_MASK_1_3(p3)) / 8)
+    | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*4 + INTERP_16_MASK_SHIFT_2_4(p2)*3 + INTERP_16_MASK_SHIFT_2_4(p3)) / 8);
+}
+
+static uint16 hq2x_interp_16_53(uint16 p1, uint16 p2)
+{
+  return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*5 + INTERP_16_MASK_1_3(p2)*3) / 8)
+    | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*5 + INTERP_16_MASK_SHIFT_2_4(p2)*3) / 8);
+}
+
+static uint16 hq2x_interp_16_151(uint16 p1, uint16 p2)
+{
+  return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*15 + INTERP_16_MASK_1_3(p2)) / 16)
+    | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*15 + INTERP_16_MASK_SHIFT_2_4(p2)) / 16);
+}
+
+static uint16 hq2x_interp_16_97(uint16 p1, uint16 p2)
+{
+  return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*9 + INTERP_16_MASK_1_3(p2)*7) / 16)
+    | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*9 + INTERP_16_MASK_SHIFT_2_4(p2)*7) / 16);
+}
+#endif /* !_16BPP_HACK */
+
+#define INTERP_32_MASK_1_3(v) ((v)&0x00FF00FF)
+#define INTERP_32_MASK_SHIFT_2_4(v) (((v)&0xFF00FF00)>>8)
+#define INTERP_32_MASK_SHIFTBACK_2_4(v) (((INTERP_32_MASK_1_3(v))<<8))
+
+static uint32 hq2x_interp_32_521(uint32 p1, uint32 p2, uint32 p3)
+{
+  return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*5 + INTERP_32_MASK_1_3(p2)*2 + INTERP_32_MASK_1_3(p3)*1) / 8)
+    | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*5 + INTERP_32_MASK_SHIFT_2_4(p2)*2 + INTERP_32_MASK_SHIFT_2_4(p3)*1) / 8);
+}
+
+static uint32 hq2x_interp_32_332(uint32 p1, uint32 p2, uint32 p3)
+{
+  return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*3 + INTERP_32_MASK_1_3(p2)*3 + INTERP_32_MASK_1_3(p3)*2) / 8)
+    | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*3 + INTERP_32_MASK_SHIFT_2_4(p2)*3 + INTERP_32_MASK_SHIFT_2_4(p3)*2) / 8);
+}
+
+static uint32 hq2x_interp_32_211(uint32 p1, uint32 p2, uint32 p3)
+{
+  return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*2 + INTERP_32_MASK_1_3(p2) + INTERP_32_MASK_1_3(p3)) / 4)
+    | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*2 + INTERP_32_MASK_SHIFT_2_4(p2) + INTERP_32_MASK_SHIFT_2_4(p3)) / 4);
+}
+
+static uint32 hq2x_interp_32_611(uint32 p1, uint32 p2, uint32 p3)
+{
+  return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*6 + INTERP_32_MASK_1_3(p2) + INTERP_32_MASK_1_3(p3)) / 8)
+    | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*6 + INTERP_32_MASK_SHIFT_2_4(p2) + INTERP_32_MASK_SHIFT_2_4(p3)) / 8);
+}
+
+static uint32 hq2x_interp_32_31(uint32 p1, uint32 p2)
+{
+  return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*3 + INTERP_32_MASK_1_3(p2)) / 4)
+    | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*3 + INTERP_32_MASK_SHIFT_2_4(p2)) / 4);
+}
+
+static uint32 hq2x_interp_32_1411(uint32 p1, uint32 p2, uint32 p3)
+{
+  return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*14 + INTERP_32_MASK_1_3(p2) + INTERP_32_MASK_1_3(p3)) / 16)
+    | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*14 + INTERP_32_MASK_SHIFT_2_4(p2) + INTERP_32_MASK_SHIFT_2_4(p3)) / 16);
+}
+
+/***************************************************************************/
+/* diff */
+
+#define INTERP_Y_LIMIT (0x30*4)
+#define INTERP_U_LIMIT (0x07*4)
+#define INTERP_V_LIMIT (0x06*8)
+
+#if !_16BPP_HACK
+static int hq2x_interp_16_diff(uint16 p1, uint16 p2)
+{
+  int r, g, b;
+  int y, u, v;
+
+  if (p1 == p2)
+    return 0;
+
+  b = (int)((p1 & 0x000F) - (p2 & 0x000F));
+  g = (int)((p1 & 0x00F0) - (p2 & 0x00F0)) >> 4;
+  r = (int)((p1 & 0x0F00) - (p2 & 0x0F00)) >> 8;
+
+  y = r + g + b;
+  u = r - b;
+  v = -r + 2*g - b;
+
+  if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT)
+    return 1;
+
+  if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT)
+    return 1;
+
+  if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT)
+    return 1;
+
+  return 0;
+}
+#endif /* !_16BPP_HACK */
+
+static int hq2x_interp_32_diff(uint32 p1, uint32 p2)
+{
+  int r, g, b;
+  int y, u, v;
+
+  if ((p1 & 0xF8F8F8) == (p2 & 0xF8F8F8))
+    return 0;
+
+  b = (int)((p1 & 0xFF) - (p2 & 0xFF));
+  g = (int)((p1 & 0xFF00) - (p2 & 0xFF00)) >> 8;
+  r = (int)((p1 & 0xFF0000) - (p2 & 0xFF0000)) >> 16;
+
+  y = r + g + b;
+  u = r - b;
+  v = -r + 2*g - b;
+
+  if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT)
+    return 1;
+
+  if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT)
+    return 1;
+
+  if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT)
+    return 1;
+
+  return 0;
+}
+
+/*static void interp_set(unsigned bits_per_pixel)
+{
+   interp_bits_per_pixel = bits_per_pixel;
+}*/
+
+#if !_16BPP_HACK
+static void hq2x_16_def(uint16* dst0, uint16* dst1, const uint16* src0, const uint16* src1, const uint16* src2, unsigned count)
+{
+  unsigned i;
+
+  for(i=0;i<count;++i) {
+    unsigned char mask;
+
+    uint16 c[9];
+
+    c[1] = src0[0];
+    c[4] = src1[0];
+    c[7] = src2[0];
+
+    if (i>0) {
+      c[0] = src0[-1];
+      c[3] = src1[-1];
+      c[6] = src2[-1];
+    } else {
+      c[0] = c[1];
+      c[3] = c[4];
+      c[6] = c[7];
+    }
+
+    if (i<count-1) {
+      c[2] = src0[1];
+      c[5] = src1[1];
+      c[8] = src2[1];
+    } else {
+      c[2] = c[1];
+      c[5] = c[4];
+      c[8] = c[7];
+    }
+
+    mask = 0;
+
+    if (hq2x_interp_16_diff(c[0], c[4]))
+      mask |= 1 << 0;
+    if (hq2x_interp_16_diff(c[1], c[4]))
+      mask |= 1 << 1;
+    if (hq2x_interp_16_diff(c[2], c[4]))
+      mask |= 1 << 2;
+    if (hq2x_interp_16_diff(c[3], c[4]))
+      mask |= 1 << 3;
+    if (hq2x_interp_16_diff(c[5], c[4]))
+      mask |= 1 << 4;
+    if (hq2x_interp_16_diff(c[6], c[4]))
+      mask |= 1 << 5;
+    if (hq2x_interp_16_diff(c[7], c[4]))
+      mask |= 1 << 6;
+    if (hq2x_interp_16_diff(c[8], c[4]))
+      mask |= 1 << 7;
+
+#define P0 dst0[0]
+#define P1 dst0[1]
+#define P2 dst1[0]
+#define P3 dst1[1]
+#define HQ2X_MUR hq2x_interp_16_diff(c[1], c[5])
+#define HQ2X_MDR hq2x_interp_16_diff(c[5], c[7])
+#define HQ2X_MDL hq2x_interp_16_diff(c[7], c[3])
+#define HQ2X_MUL hq2x_interp_16_diff(c[3], c[1])
+#define IC(p0) c[p0]
+#define I11(p0,p1) hq2x_interp_16_11(c[p0], c[p1])
+#define I211(p0,p1,p2) hq2x_interp_16_211(c[p0], c[p1], c[p2])
+#define I31(p0,p1) hq2x_interp_16_31(c[p0], c[p1])
+#define I332(p0,p1,p2) hq2x_interp_16_332(c[p0], c[p1], c[p2])
+#define I431(p0,p1,p2) hq2x_interp_16_431(c[p0], c[p1], c[p2])
+#define I521(p0,p1,p2) hq2x_interp_16_521(c[p0], c[p1], c[p2])
+#define I53(p0,p1) hq2x_interp_16_53(c[p0], c[p1])
+#define I611(p0,p1,p2) hq2x_interp_16_611(c[p0], c[p1], c[p2])
+#define I71(p0,p1) hq2x_interp_16_71(c[p0], c[p1])
+#define I772(p0,p1,p2) hq2x_interp_16_772(c[p0], c[p1], c[p2])
+#define I97(p0,p1) hq2x_interp_16_97(c[p0], c[p1])
+#define I1411(p0,p1,p2) hq2x_interp_16_1411(c[p0], c[p1], c[p2])
+#define I151(p0,p1) hq2x_interp_16_151(c[p0], c[p1])
+
+    switch (mask) {
+#include "TextureFilters_hq2x.h"
+    }
+
+#undef P0
+#undef P1
+#undef P2
+#undef P3
+#undef HQ2X_MUR
+#undef HQ2X_MDR
+#undef HQ2X_MDL
+#undef HQ2X_MUL
+#undef IC
+#undef I11
+#undef I211
+#undef I31
+#undef I332
+#undef I431
+#undef I521
+#undef I53
+#undef I611
+#undef I71
+#undef I772
+#undef I97
+#undef I1411
+#undef I151
+
+    src0 += 1;
+    src1 += 1;
+    src2 += 1;
+    dst0 += 2;
+    dst1 += 2;
+  }
+}
+
+static void hq2xS_16_def(uint16* dst0, uint16* dst1, const uint16* src0, const uint16* src1, const uint16* src2, unsigned count)
+{
+  unsigned i;
+
+  for(i=0;i<count;++i) {
+    unsigned char mask;
+
+    uint16 c[9];
+
+    c[1] = src0[0];
+    c[4] = src1[0];
+    c[7] = src2[0];
+
+    if (i>0) {
+      c[0] = src0[-1];
+      c[3] = src1[-1];
+      c[6] = src2[-1];
+    } else {
+      c[0] = c[1];
+      c[3] = c[4];
+      c[6] = c[7];
+    }
+
+    if (i<count-1) {
+      c[2] = src0[1];
+      c[5] = src1[1];
+      c[8] = src2[1];
+    } else {
+      c[2] = c[1];
+      c[5] = c[4];
+      c[8] = c[7];
+    }
+
+    mask = 0;
+
+    // hq2xS dynamic edge detection:
+    // simply comparing the center color against its surroundings will give bad results in many cases,
+    // so, instead, compare the center color relative to the max difference in brightness of this 3x3 block
+    int brightArray[9];
+    int maxBright = 0, minBright = 999999;
+    for(int j = 0 ; j < 9 ; j++) {
+      int r,g,b;
+      if (interp_bits_per_pixel == 16) {
+        b = (int)((c[j] & 0x1F)) << 3;
+        g = (int)((c[j] & 0x7E0)) >> 3;
+        r = (int)((c[j] & 0xF800)) >> 8;
+      } else {
+        b = (int)((c[j] & 0x1F)) << 3;
+        g = (int)((c[j] & 0x3E0)) >> 2;
+        r = (int)((c[j] & 0x7C00)) >> 7;
+      }
+      const int bright = r+r+r + g+g+g + b+b;
+      if(bright > maxBright) maxBright = bright;
+      if(bright < minBright) minBright = bright;
+
+      brightArray[j] = bright;
+    }
+    int diffBright = ((maxBright - minBright) * 7) >> 4;
+    if(diffBright > 7) {
+#define ABS(x) ((x) < 0 ? -(x) : (x))
+
+      const int centerBright = brightArray[4];
+      if(ABS(brightArray[0] - centerBright) > diffBright)
+        mask |= 1 << 0;
+      if(ABS(brightArray[1] - centerBright) > diffBright)
+        mask |= 1 << 1;
+      if(ABS(brightArray[2] - centerBright) > diffBright)
+        mask |= 1 << 2;
+      if(ABS(brightArray[3] - centerBright) > diffBright)
+        mask |= 1 << 3;
+      if(ABS(brightArray[5] - centerBright) > diffBright)
+        mask |= 1 << 4;
+      if(ABS(brightArray[6] - centerBright) > diffBright)
+        mask |= 1 << 5;
+      if(ABS(brightArray[7] - centerBright) > diffBright)
+        mask |= 1 << 6;
+      if(ABS(brightArray[8] - centerBright) > diffBright)
+        mask |= 1 << 7;
+    }
+
+#define P0 dst0[0]
+#define P1 dst0[1]
+#define P2 dst1[0]
+#define P3 dst1[1]
+#define HQ2X_MUR false
+#define HQ2X_MDR false
+#define HQ2X_MDL false
+#define HQ2X_MUL false
+#define IC(p0) c[p0]
+#define I11(p0,p1) hq2x_interp_16_11(c[p0], c[p1])
+#define I211(p0,p1,p2) hq2x_interp_16_211(c[p0], c[p1], c[p2])
+#define I31(p0,p1) hq2x_interp_16_31(c[p0], c[p1])
+#define I332(p0,p1,p2) hq2x_interp_16_332(c[p0], c[p1], c[p2])
+#define I431(p0,p1,p2) hq2x_interp_16_431(c[p0], c[p1], c[p2])
+#define I521(p0,p1,p2) hq2x_interp_16_521(c[p0], c[p1], c[p2])
+#define I53(p0,p1) hq2x_interp_16_53(c[p0], c[p1])
+#define I611(p0,p1,p2) hq2x_interp_16_611(c[p0], c[p1], c[p2])
+#define I71(p0,p1) hq2x_interp_16_71(c[p0], c[p1])
+#define I772(p0,p1,p2) hq2x_interp_16_772(c[p0], c[p1], c[p2])
+#define I97(p0,p1) hq2x_interp_16_97(c[p0], c[p1])
+#define I1411(p0,p1,p2) hq2x_interp_16_1411(c[p0], c[p1], c[p2])
+#define I151(p0,p1) hq2x_interp_16_151(c[p0], c[p1])
+
+    switch (mask) {
+#include "TextureFilters_hq2x.h"
+    }
+
+#undef P0
+#undef P1
+#undef P2
+#undef P3
+#undef HQ2X_MUR
+#undef HQ2X_MDR
+#undef HQ2X_MDL
+#undef HQ2X_MUL
+#undef IC
+#undef I11
+#undef I211
+#undef I31
+#undef I332
+#undef I431
+#undef I521
+#undef I53
+#undef I611
+#undef I71
+#undef I772
+#undef I97
+#undef I1411
+#undef I151
+
+    src0 += 1;
+    src1 += 1;
+    src2 += 1;
+    dst0 += 2;
+    dst1 += 2;
+  }
+}
+#endif /* !_16BPP_HACK */
+
+static void hq2x_32_def(uint32* dst0, uint32* dst1, const uint32* src0, const uint32* src1, const uint32* src2, unsigned count)
+{
+  unsigned i;
+
+  for(i=0;i<count;++i) {
+    unsigned char mask;
+
+    uint32 c[9];
+
+    c[1] = src0[0];
+    c[4] = src1[0];
+    c[7] = src2[0];
+
+    if (i>0) {
+      c[0] = src0[-1];
+      c[3] = src1[-1];
+      c[6] = src2[-1];
+    } else {
+      c[0] = src0[0];
+      c[3] = src1[0];
+      c[6] = src2[0];
+    }
+
+    if (i<count-1) {
+      c[2] = src0[1];
+      c[5] = src1[1];
+      c[8] = src2[1];
+    } else {
+      c[2] = src0[0];
+      c[5] = src1[0];
+      c[8] = src2[0];
+    }
+
+    mask = 0;
+
+    if (hq2x_interp_32_diff(c[0], c[4]))
+      mask |= 1 << 0;
+    if (hq2x_interp_32_diff(c[1], c[4]))
+      mask |= 1 << 1;
+    if (hq2x_interp_32_diff(c[2], c[4]))
+      mask |= 1 << 2;
+    if (hq2x_interp_32_diff(c[3], c[4]))
+      mask |= 1 << 3;
+    if (hq2x_interp_32_diff(c[5], c[4]))
+      mask |= 1 << 4;
+    if (hq2x_interp_32_diff(c[6], c[4]))
+      mask |= 1 << 5;
+    if (hq2x_interp_32_diff(c[7], c[4]))
+      mask |= 1 << 6;
+    if (hq2x_interp_32_diff(c[8], c[4]))
+      mask |= 1 << 7;
+
+#define P0 dst0[0]
+#define P1 dst0[1]
+#define P2 dst1[0]
+#define P3 dst1[1]
+#define HQ2X_MUR hq2x_interp_32_diff(c[1], c[5])
+#define HQ2X_MDR hq2x_interp_32_diff(c[5], c[7])
+#define HQ2X_MDL hq2x_interp_32_diff(c[7], c[3])
+#define HQ2X_MUL hq2x_interp_32_diff(c[3], c[1])
+#define IC(p0) c[p0]
+#define I211(p0,p1,p2) hq2x_interp_32_211(c[p0], c[p1], c[p2])
+#define I31(p0,p1) hq2x_interp_32_31(c[p0], c[p1])
+#define I332(p0,p1,p2) hq2x_interp_32_332(c[p0], c[p1], c[p2])
+#define I521(p0,p1,p2) hq2x_interp_32_521(c[p0], c[p1], c[p2])
+#define I611(p0,p1,p2) hq2x_interp_32_611(c[p0], c[p1], c[p2])
+#define I1411(p0,p1,p2) hq2x_interp_32_1411(c[p0], c[p1], c[p2])
+
+    switch (mask) {
+#include "TextureFilters_hq2x.h"
+    }
+
+#undef P0
+#undef P1
+#undef P2
+#undef P3
+#undef HQ2X_MUR
+#undef HQ2X_MDR
+#undef HQ2X_MDL
+#undef HQ2X_MUL
+#undef IC
+#undef I211
+#undef I31
+#undef I332
+#undef I521
+#undef I611
+#undef I1411
+
+    src0 += 1;
+    src1 += 1;
+    src2 += 1;
+    dst0 += 2;
+    dst1 += 2;
+  }
+}
+
+static void hq2xS_32_def(uint32* dst0, uint32* dst1, const uint32* src0, const uint32* src1, const uint32* src2, unsigned count)
+{
+  unsigned i;
+
+  for(i=0;i<count;++i) {
+    unsigned char mask;
+
+    uint32 c[9];
+
+    c[1] = src0[0];
+    c[4] = src1[0];
+    c[7] = src2[0];
+
+    if (i>0) {
+      c[0] = src0[-1];
+      c[3] = src1[-1];
+      c[6] = src2[-1];
+    } else {
+      c[0] = src0[0];
+      c[3] = src1[0];
+      c[6] = src2[0];
+    }
+
+    if (i<count-1) {
+      c[2] = src0[1];
+      c[5] = src1[1];
+      c[8] = src2[1];
+    } else {
+      c[2] = src0[0];
+      c[5] = src1[0];
+      c[8] = src2[0];
+    }
+    
+    mask = 0;
+    // hq2xS dynamic edge detection:
+    // simply comparing the center color against its surroundings will give bad results in many cases,
+    // so, instead, compare the center color relative to the max difference in brightness of this 3x3 block
+    int brightArray[9];
+    int maxBright = 0, minBright = 999999;
+    for(int j = 0 ; j < 9 ; j++) {
+      const int b = (int)((c[j] & 0xF8));
+      const int g = (int)((c[j] & 0xF800)) >> 8;
+      const int r = (int)((c[j] & 0xF80000)) >> 16;
+      const int bright = r+r+r + g+g+g + b+b;
+      if(bright > maxBright) maxBright = bright;
+      if(bright < minBright) minBright = bright;
+
+      brightArray[j] = bright;
+    }
+    int diffBright = ((maxBright - minBright) * 7) >> 4;
+    if(diffBright > 7) {
+#define ABS(x) ((x) < 0 ? -(x) : (x))
+
+      const int centerBright = brightArray[4];
+      if(ABS(brightArray[0] - centerBright) > diffBright)
+        mask |= 1 << 0;
+      if(ABS(brightArray[1] - centerBright) > diffBright)
+        mask |= 1 << 1;
+      if(ABS(brightArray[2] - centerBright) > diffBright)
+        mask |= 1 << 2;
+      if(ABS(brightArray[3] - centerBright) > diffBright)
+        mask |= 1 << 3;
+      if(ABS(brightArray[5] - centerBright) > diffBright)
+        mask |= 1 << 4;
+      if(ABS(brightArray[6] - centerBright) > diffBright)
+        mask |= 1 << 5;
+      if(ABS(brightArray[7] - centerBright) > diffBright)
+        mask |= 1 << 6;
+      if(ABS(brightArray[8] - centerBright) > diffBright)
+        mask |= 1 << 7;
+    }
+#define P0 dst0[0]
+#define P1 dst0[1]
+#define P2 dst1[0]
+#define P3 dst1[1]
+#define HQ2X_MUR false
+#define HQ2X_MDR false
+#define HQ2X_MDL false
+#define HQ2X_MUL false
+#define IC(p0) c[p0]
+#define I211(p0,p1,p2) hq2x_interp_32_211(c[p0], c[p1], c[p2])
+#define I31(p0,p1) hq2x_interp_32_31(c[p0], c[p1])
+#define I332(p0,p1,p2) hq2x_interp_32_332(c[p0], c[p1], c[p2])
+#define I521(p0,p1,p2) hq2x_interp_32_521(c[p0], c[p1], c[p2])
+#define I611(p0,p1,p2) hq2x_interp_32_611(c[p0], c[p1], c[p2])
+#define I1411(p0,p1,p2) hq2x_interp_32_1411(c[p0], c[p1], c[p2])
+
+    switch (mask) {
+#include "TextureFilters_hq2x.h"
+    }
+
+#undef P0
+#undef P1
+#undef P2
+#undef P3
+#undef HQ2X_MUR
+#undef HQ2X_MDR
+#undef HQ2X_MDL
+#undef HQ2X_MUL
+#undef IC
+#undef I211
+#undef I31
+#undef I332
+#undef I521
+#undef I611
+#undef I1411
+
+    src0 += 1;
+    src1 += 1;
+    src2 += 1;
+    dst0 += 2;
+    dst1 += 2;
+  }
+}
+
+/***************************************************************************/
+/* LQ2x C implementation */
+
+/*
+* This effect is derived from the hq2x effect made by Maxim Stepin
+*/
+
+#if !_16BPP_HACK
+static void lq2x_16_def(uint16* dst0, uint16* dst1, const uint16* src0, const uint16* src1, const uint16* src2, unsigned count)
+{
+  unsigned i;
+
+  for(i=0;i<count;++i) {
+    unsigned char mask;
+
+    uint16 c[9];
+
+    c[1] = src0[0];
+    c[4] = src1[0];
+    c[7] = src2[0];
+
+    if (i>0) {
+      c[0] = src0[-1];
+      c[3] = src1[-1];
+      c[6] = src2[-1];
+    } else {
+      c[0] = c[1];
+      c[3] = c[4];
+      c[6] = c[7];
+    }
+
+    if (i<count-1) {
+      c[2] = src0[1];
+      c[5] = src1[1];
+      c[8] = src2[1];
+    } else {
+      c[2] = c[1];
+      c[5] = c[4];
+      c[8] = c[7];
+    }
+
+    mask = 0;
+
+    if (c[0] != c[4])
+      mask |= 1 << 0;
+    if (c[1] != c[4])
+      mask |= 1 << 1;
+    if (c[2] != c[4])
+      mask |= 1 << 2;
+    if (c[3] != c[4])
+      mask |= 1 << 3;
+    if (c[5] != c[4])
+      mask |= 1 << 4;
+    if (c[6] != c[4])
+      mask |= 1 << 5;
+    if (c[7] != c[4])
+      mask |= 1 << 6;
+    if (c[8] != c[4])
+      mask |= 1 << 7;
+
+#define P0 dst0[0]
+#define P1 dst0[1]
+#define P2 dst1[0]
+#define P3 dst1[1]
+#define HQ2X_MUR (c[1] != c[5])
+#define HQ2X_MDR (c[5] != c[7])
+#define HQ2X_MDL (c[7] != c[3])
+#define HQ2X_MUL (c[3] != c[1])
+#define IC(p0) c[p0]
+#define I11(p0,p1) hq2x_interp_16_11(c[p0], c[p1])
+#define I211(p0,p1,p2) hq2x_interp_16_211(c[p0], c[p1], c[p2])
+#define I31(p0,p1) hq2x_interp_16_31(c[p0], c[p1])
+#define I332(p0,p1,p2) hq2x_interp_16_332(c[p0], c[p1], c[p2])
+#define I431(p0,p1,p2) hq2x_interp_16_431(c[p0], c[p1], c[p2])
+#define I521(p0,p1,p2) hq2x_interp_16_521(c[p0], c[p1], c[p2])
+#define I53(p0,p1) hq2x_interp_16_53(c[p0], c[p1])
+#define I611(p0,p1,p2) hq2x_interp_16_611(c[p0], c[p1], c[p2])
+#define I71(p0,p1) hq2x_interp_16_71(c[p0], c[p1])
+#define I772(p0,p1,p2) hq2x_interp_16_772(c[p0], c[p1], c[p2])
+#define I97(p0,p1) hq2x_interp_16_97(c[p0], c[p1])
+#define I1411(p0,p1,p2) hq2x_interp_16_1411(c[p0], c[p1], c[p2])
+#define I151(p0,p1) hq2x_interp_16_151(c[p0], c[p1])
+
+    switch (mask) {
+#include "TextureFilters_lq2x.h"
+    }
+
+#undef P0
+#undef P1
+#undef P2
+#undef P3
+#undef HQ2X_MUR
+#undef HQ2X_MDR
+#undef HQ2X_MDL
+#undef HQ2X_MUL
+#undef IC
+#undef I11
+#undef I211
+#undef I31
+#undef I332
+#undef I431
+#undef I521
+#undef I53
+#undef I611
+#undef I71
+#undef I772
+#undef I97
+#undef I1411
+#undef I151
+
+    src0 += 1;
+    src1 += 1;
+    src2 += 1;
+    dst0 += 2;
+    dst1 += 2;
+  }
+}
+
+static void lq2xS_16_def(uint16* dst0, uint16* dst1, const uint16* src0, const uint16* src1, const uint16* src2, unsigned count)
+{
+  unsigned i;
+
+  for(i=0;i<count;++i) {
+    unsigned char mask;
+
+    uint16 c[9];
+
+    c[1] = src0[0];
+    c[4] = src1[0];
+    c[7] = src2[0];
+
+    if (i>0) {
+      c[0] = src0[-1];
+      c[3] = src1[-1];
+      c[6] = src2[-1];
+    } else {
+      c[0] = c[1];
+      c[3] = c[4];
+      c[6] = c[7];
+    }
+
+    if (i<count-1) {
+      c[2] = src0[1];
+      c[5] = src1[1];
+      c[8] = src2[1];
+    } else {
+      c[2] = c[1];
+      c[5] = c[4];
+      c[8] = c[7];
+    }
+
+    // hq2xS dynamic edge detection:
+    // simply comparing the center color against its surroundings will give bad results in many cases,
+    // so, instead, compare the center color relative to the max difference in brightness of this 3x3 block
+    int brightArray[9];
+    int maxBright = 0, minBright = 999999;
+    for(int j = 0 ; j < 9 ; j++) {
+      const int b = (int)((c[j] & 0xF8));
+      const int g = (int)((c[j] & 0xF800)) >> 8;
+      const int r = (int)((c[j] & 0xF80000)) >> 16;
+      const int bright = r+r+r + g+g+g + b+b;
+      if(bright > maxBright) maxBright = bright;
+      if(bright < minBright) minBright = bright;
+
+      brightArray[j] = bright;
+    }
+    int diffBright = ((maxBright - minBright) * 7) >> 4;
+    if(diffBright > 7) {
+#define ABS(x) ((x) < 0 ? -(x) : (x))
+
+      const int centerBright = brightArray[4];
+      if(ABS(brightArray[0] - centerBright) > diffBright)
+        mask |= 1 << 0;
+      if(ABS(brightArray[1] - centerBright) > diffBright)
+        mask |= 1 << 1;
+      if(ABS(brightArray[2] - centerBright) > diffBright)
+        mask |= 1 << 2;
+      if(ABS(brightArray[3] - centerBright) > diffBright)
+        mask |= 1 << 3;
+      if(ABS(brightArray[5] - centerBright) > diffBright)
+        mask |= 1 << 4;
+      if(ABS(brightArray[6] - centerBright) > diffBright)
+        mask |= 1 << 5;
+      if(ABS(brightArray[7] - centerBright) > diffBright)
+        mask |= 1 << 6;
+      if(ABS(brightArray[8] - centerBright) > diffBright)
+        mask |= 1 << 7;
+    }
+
+#define P0 dst0[0]
+#define P1 dst0[1]
+#define P2 dst1[0]
+#define P3 dst1[1]
+#define HQ2X_MUR false
+#define HQ2X_MDR false
+#define HQ2X_MDL false
+#define HQ2X_MUL false
+#define IC(p0) c[p0]
+#define I11(p0,p1) hq2x_interp_16_11(c[p0], c[p1])
+#define I211(p0,p1,p2) hq2x_interp_16_211(c[p0], c[p1], c[p2])
+#define I31(p0,p1) hq2x_interp_16_31(c[p0], c[p1])
+#define I332(p0,p1,p2) hq2x_interp_16_332(c[p0], c[p1], c[p2])
+#define I431(p0,p1,p2) hq2x_interp_16_431(c[p0], c[p1], c[p2])
+#define I521(p0,p1,p2) hq2x_interp_16_521(c[p0], c[p1], c[p2])
+#define I53(p0,p1) hq2x_interp_16_53(c[p0], c[p1])
+#define I611(p0,p1,p2) hq2x_interp_16_611(c[p0], c[p1], c[p2])
+#define I71(p0,p1) hq2x_interp_16_71(c[p0], c[p1])
+#define I772(p0,p1,p2) hq2x_interp_16_772(c[p0], c[p1], c[p2])
+#define I97(p0,p1) hq2x_interp_16_97(c[p0], c[p1])
+#define I1411(p0,p1,p2) hq2x_interp_16_1411(c[p0], c[p1], c[p2])
+#define I151(p0,p1) hq2x_interp_16_151(c[p0], c[p1])
+
+    switch (mask) {
+#include "TextureFilters_lq2x.h"
+    }
+
+#undef P0
+#undef P1
+#undef P2
+#undef P3
+#undef HQ2X_MUR
+#undef HQ2X_MDR
+#undef HQ2X_MDL
+#undef HQ2X_MUL
+#undef IC
+#undef I11
+#undef I211
+#undef I31
+#undef I332
+#undef I431
+#undef I521
+#undef I53
+#undef I611
+#undef I71
+#undef I772
+#undef I97
+#undef I1411
+#undef I151
+
+    src0 += 1;
+    src1 += 1;
+    src2 += 1;
+    dst0 += 2;
+    dst1 += 2;
+  }
+}
+#endif /* !_16BPP_HACK */
+
+static void lq2x_32_def(uint32* dst0, uint32* dst1, const uint32* src0, const uint32* src1, const uint32* src2, unsigned count)
+{
+  unsigned i;
+
+  for(i=0;i<count;++i) {
+    unsigned char mask;
+
+    uint32 c[9];
+
+    c[1] = src0[0];
+    c[4] = src1[0];
+    c[7] = src2[0];
+
+    if (i>0) {
+      c[0] = src0[-1];
+      c[3] = src1[-1];
+      c[6] = src2[-1];
+    } else {
+      c[0] = c[1];
+      c[3] = c[4];
+      c[6] = c[7];
+    }
+
+    if (i<count-1) {
+      c[2] = src0[1];
+      c[5] = src1[1];
+      c[8] = src2[1];
+    } else {
+      c[2] = c[1];
+      c[5] = c[4];
+      c[8] = c[7];
+    }
+
+    mask = 0;
+
+    if (c[0] != c[4])
+      mask |= 1 << 0;
+    if (c[1] != c[4])
+      mask |= 1 << 1;
+    if (c[2] != c[4])
+      mask |= 1 << 2;
+    if (c[3] != c[4])
+      mask |= 1 << 3;
+    if (c[5] != c[4])
+      mask |= 1 << 4;
+    if (c[6] != c[4])
+      mask |= 1 << 5;
+    if (c[7] != c[4])
+      mask |= 1 << 6;
+    if (c[8] != c[4])
+      mask |= 1 << 7;
+
+#define P0 dst0[0]
+#define P1 dst0[1]
+#define P2 dst1[0]
+#define P3 dst1[1]
+#define HQ2X_MUR (c[1] != c[5])
+#define HQ2X_MDR (c[5] != c[7])
+#define HQ2X_MDL (c[7] != c[3])
+#define HQ2X_MUL (c[3] != c[1])
+#define IC(p0) c[p0]
+#define I211(p0,p1,p2) hq2x_interp_32_211(c[p0], c[p1], c[p2])
+#define I31(p0,p1) hq2x_interp_32_31(c[p0], c[p1])
+#define I332(p0,p1,p2) hq2x_interp_32_332(c[p0], c[p1], c[p2])
+#define I521(p0,p1,p2) hq2x_interp_32_521(c[p0], c[p1], c[p2])
+#define I611(p0,p1,p2) hq2x_interp_32_611(c[p0], c[p1], c[p2])
+#define I1411(p0,p1,p2) hq2x_interp_32_1411(c[p0], c[p1], c[p2])
+
+    switch (mask) {
+#include "TextureFilters_lq2x.h"
+    }
+
+#undef P0
+#undef P1
+#undef P2
+#undef P3
+#undef HQ2X_MUR
+#undef HQ2X_MDR
+#undef HQ2X_MDL
+#undef HQ2X_MUL
+#undef IC
+#undef I211
+#undef I31
+#undef I332
+#undef I521
+#undef I611
+#undef I1411
+
+    src0 += 1;
+    src1 += 1;
+    src2 += 1;
+    dst0 += 2;
+    dst1 += 2;
+  }
+}
+
+static void lq2xS_32_def(uint32* dst0, uint32* dst1, const uint32* src0, const uint32* src1, const uint32* src2, unsigned count)
+{
+  unsigned i;
+
+  for(i=0;i<count;++i) {
+    unsigned char mask = 0;
+
+    uint32 c[9];
+
+    c[1] = src0[0];
+    c[4] = src1[0];
+    c[7] = src2[0];
+
+    if (i>0) {
+      c[0] = src0[-1];
+      c[3] = src1[-1];
+      c[6] = src2[-1];
+    } else {
+      c[0] = c[1];
+      c[3] = c[4];
+      c[6] = c[7];
+    }
+
+    if (i<count-1) {
+      c[2] = src0[1];
+      c[5] = src1[1];
+      c[8] = src2[1];
+    } else {
+      c[2] = c[1];
+      c[5] = c[4];
+      c[8] = c[7];
+    }
+
+    // hq2xS dynamic edge detection:
+    // simply comparing the center color against its surroundings will give bad results in many cases,
+    // so, instead, compare the center color relative to the max difference in brightness of this 3x3 block
+    int brightArray[9];
+    int maxBright = 0, minBright = 999999;
+    for(int j = 0 ; j < 9 ; j++) {
+      const int b = (int)((c[j] & 0xF8));
+      const int g = (int)((c[j] & 0xF800)) >> 8;
+      const int r = (int)((c[j] & 0xF80000)) >> 16;
+      const int bright = r+r+r + g+g+g + b+b;
+      if(bright > maxBright) maxBright = bright;
+      if(bright < minBright) minBright = bright;
+
+      brightArray[j] = bright;
+    }
+    int diffBright = ((maxBright - minBright) * 7) >> 4;
+    if(diffBright > 7) {
+#define ABS(x) ((x) < 0 ? -(x) : (x))
+
+      const int centerBright = brightArray[4];
+      if(ABS(brightArray[0] - centerBright) > diffBright)
+        mask |= 1 << 0;
+      if(ABS(brightArray[1] - centerBright) > diffBright)
+        mask |= 1 << 1;
+      if(ABS(brightArray[2] - centerBright) > diffBright)
+        mask |= 1 << 2;
+      if(ABS(brightArray[3] - centerBright) > diffBright)
+        mask |= 1 << 3;
+      if(ABS(brightArray[5] - centerBright) > diffBright)
+        mask |= 1 << 4;
+      if(ABS(brightArray[6] - centerBright) > diffBright)
+        mask |= 1 << 5;
+      if(ABS(brightArray[7] - centerBright) > diffBright)
+        mask |= 1 << 6;
+      if(ABS(brightArray[8] - centerBright) > diffBright)
+        mask |= 1 << 7;
+    }
+
+#define P0 dst0[0]
+#define P1 dst0[1]
+#define P2 dst1[0]
+#define P3 dst1[1]
+#define HQ2X_MUR false
+#define HQ2X_MDR false
+#define HQ2X_MDL false
+#define HQ2X_MUL false
+#define IC(p0) c[p0]
+#define I211(p0,p1,p2) hq2x_interp_32_211(c[p0], c[p1], c[p2])
+#define I31(p0,p1) hq2x_interp_32_31(c[p0], c[p1])
+#define I332(p0,p1,p2) hq2x_interp_32_332(c[p0], c[p1], c[p2])
+#define I521(p0,p1,p2) hq2x_interp_32_521(c[p0], c[p1], c[p2])
+#define I611(p0,p1,p2) hq2x_interp_32_611(c[p0], c[p1], c[p2])
+#define I1411(p0,p1,p2) hq2x_interp_32_1411(c[p0], c[p1], c[p2])
+
+    switch (mask) {
+#include "TextureFilters_lq2x.h"
+    }
+
+#undef P0
+#undef P1
+#undef P2
+#undef P3
+#undef HQ2X_MUR
+#undef HQ2X_MDR
+#undef HQ2X_MDL
+#undef HQ2X_MUL
+#undef IC
+#undef I211
+#undef I31
+#undef I332
+#undef I521
+#undef I611
+#undef I1411
+
+    src0 += 1;
+    src1 += 1;
+    src2 += 1;
+    dst0 += 2;
+    dst1 += 2;
+  }
+}
+
+#if !_16BPP_HACK
+void hq2x_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height)
+{
+  uint16 *dst0 = (uint16 *)dstPtr;
+  uint16 *dst1 = dst0 + (dstPitch >> 1);
+
+  uint16 *src0 = (uint16 *)srcPtr;
+  uint16 *src1 = src0 + (srcPitch >> 1);
+  uint16 *src2 = src1 + (srcPitch >> 1);
+
+  int count;
+
+  hq2x_16_def(dst0, dst1, src0, src0, src1, width);
+  if( height == 1 ) return;
+
+  count = height;
+
+  count -= 2;
+  while(count>0) {
+    dst0 += dstPitch;
+    dst1 += dstPitch;
+    hq2x_16_def(dst0, dst1, src0, src1, src2, width);
+    src0 = src1;
+    src1 = src2;
+    src2 += srcPitch >> 1;
+    --count;
+  }
+  dst0 += dstPitch;
+  dst1 += dstPitch;
+  hq2x_16_def(dst0, dst1, src0, src1, src1, width);
+}
+
+
+void hq2xS_16(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
+              u8 *dstPtr, u32 dstPitch, int width, int height)
+{
+  u16 *dst0 = (u16 *)dstPtr;
+  u16 *dst1 = dst0 + (dstPitch >> 1);
+  
+  u16 *src0 = (u16 *)srcPtr;
+  u16 *src1 = src0 + (srcPitch >> 1);
+  u16 *src2 = src1 + (srcPitch >> 1);
+  
+  hq2xS_16_def(dst0, dst1, src0, src0, src1, width);
+  
+  int count = height;
+  
+  count -= 2;
+  while(count) {
+    dst0 += dstPitch;
+    dst1 += dstPitch;
+    hq2xS_16_def(dst0, dst1, src0, src1, src2, width);
+    src0 = src1;
+    src1 = src2;
+    src2 += srcPitch >> 1;
+    --count;
+  }
+  dst0 += dstPitch;
+  dst1 += dstPitch;
+  hq2xS_16_def(dst0, dst1, src0, src1, src1, width);
+}
+#endif /* !_16BPP_HACK */
+
+void hq2x_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height)
+{
+  uint32 *dst0 = (uint32 *)dstPtr;
+  uint32 *dst1 = dst0 + (dstPitch >> 2);
+
+  uint32 *src0 = (uint32 *)srcPtr;
+  uint32 *src1 = src0 + (srcPitch >> 2);
+  uint32 *src2 = src1 + (srcPitch >> 2);
+
+  int count;
+
+  hq2x_32_def(dst0, dst1, src0, src0, src1, width);
+  if( height == 1 ) return;
+
+  count = height;
+
+  count -= 2;
+  while(count>0) {
+    dst0 += dstPitch >> 1;
+    dst1 += dstPitch >> 1;
+    hq2x_32_def(dst0, dst1, src0, src1, src2, width);
+    src0 = src1;
+    src1 = src2;
+    src2 += srcPitch >> 2;
+    --count;
+  }
+  dst0 += dstPitch >> 1;
+  dst1 += dstPitch >> 1;
+  hq2x_32_def(dst0, dst1, src0, src1, src1, width);
+}
+
+void hq2xS_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height)
+{
+  uint32 *dst0 = (uint32 *)dstPtr;
+  uint32 *dst1 = dst0 + (dstPitch >> 2);
+
+  uint32 *src0 = (uint32 *)srcPtr;
+  uint32 *src1 = src0 + (srcPitch >> 2);
+  uint32 *src2 = src1 + (srcPitch >> 2);
+  hq2xS_32_def(dst0, dst1, src0, src0, src1, width);
+  
+  int count = height;
+  
+  count -= 2;
+  while(count) {
+    dst0 += dstPitch >> 1;
+    dst1 += dstPitch >> 1;
+    hq2xS_32_def(dst0, dst1, src0, src1, src2, width);
+    src0 = src1;
+    src1 = src2;
+    src2 += srcPitch >> 2;
+    --count;
+  }
+  dst0 += dstPitch >> 1;
+  dst1 += dstPitch >> 1;
+  hq2xS_32_def(dst0, dst1, src0, src1, src1, width);
+}
+
+#if !_16BPP_HACK
+void lq2x_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height)
+{
+  uint16 *dst0 = (uint16 *)dstPtr;
+  uint16 *dst1 = dst0 + (dstPitch >> 1);
+
+  uint16 *src0 = (uint16 *)srcPtr;
+  uint16 *src1 = src0 + (srcPitch >> 1);
+  uint16 *src2 = src1 + (srcPitch >> 1);
+
+  int count;
+
+  lq2x_16_def(dst0, dst1, src0, src0, src1, width);
+  if( height == 1 ) return;
+
+  count = height;
+
+  count -= 2;
+  while(count>0) {
+    dst0 += dstPitch;
+    dst1 += dstPitch;
+    hq2x_16_def(dst0, dst1, src0, src1, src2, width);
+    src0 = src1;
+    src1 = src2;
+    src2 += srcPitch >> 1;
+    --count;
+  }
+  dst0 += dstPitch;
+  dst1 += dstPitch;
+  lq2x_16_def(dst0, dst1, src0, src1, src1, width);
+}
+
+void lq2xS_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height)
+{
+  uint16 *dst0 = (uint16 *)dstPtr;
+  uint16 *dst1 = dst0 + (dstPitch >> 1);
+
+  uint16 *src0 = (uint16 *)srcPtr;
+  uint16 *src1 = src0 + (srcPitch >> 1);
+  uint16 *src2 = src1 + (srcPitch >> 1);
+
+  int count;
+
+  lq2xS_16_def(dst0, dst1, src0, src0, src1, width);
+  if( height == 1 ) return;
+
+  count = height;
+
+  count -= 2;
+  while(count>0) {
+    dst0 += dstPitch;
+    dst1 += dstPitch;
+    hq2x_16_def(dst0, dst1, src0, src1, src2, width);
+    src0 = src1;
+    src1 = src2;
+    src2 += srcPitch >> 1;
+    --count;
+  }
+  dst0 += dstPitch;
+  dst1 += dstPitch;
+  lq2xS_16_def(dst0, dst1, src0, src1, src1, width);
+}
+#endif /* !_16BPP_HACK */
+
+void lq2x_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height)
+{
+  uint32 *dst0 = (uint32 *)dstPtr;
+  uint32 *dst1 = dst0 + (dstPitch >> 2);
+
+  uint32 *src0 = (uint32 *)srcPtr;
+  uint32 *src1 = src0 + (srcPitch >> 2);
+  uint32 *src2 = src1 + (srcPitch >> 2);
+
+  int count;
+
+  lq2x_32_def(dst0, dst1, src0, src0, src1, width);
+  if( height == 1 ) return;
+
+  count = height;
+
+  count -= 2;
+  while(count>0) {
+    dst0 += dstPitch >> 1;
+    dst1 += dstPitch >> 1;
+    hq2x_32_def(dst0, dst1, src0, src1, src2, width);
+    src0 = src1;
+    src1 = src2;
+    src2 += srcPitch >> 2;
+    --count;
+  }
+  dst0 += dstPitch >> 1;
+  dst1 += dstPitch >> 1;
+  lq2x_32_def(dst0, dst1, src0, src1, src1, width);
+}
+
+void lq2xS_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height)
+{
+  uint32 *dst0 = (uint32 *)dstPtr;
+  uint32 *dst1 = dst0 + (dstPitch >> 2);
+
+  uint32 *src0 = (uint32 *)srcPtr;
+  uint32 *src1 = src0 + (srcPitch >> 2);
+  uint32 *src2 = src1 + (srcPitch >> 2);
+
+  int count;
+
+  lq2xS_32_def(dst0, dst1, src0, src0, src1, width);
+  if( height == 1 ) return;
+
+  count = height;
+
+  count -= 2;
+  while(count>0) {
+    dst0 += dstPitch >> 1;
+    dst1 += dstPitch >> 1;
+    hq2x_32_def(dst0, dst1, src0, src1, src2, width);
+    src0 = src1;
+    src1 = src2;
+    src2 += srcPitch >> 2;
+    --count;
+  }
+  dst0 += dstPitch >> 1;
+  dst1 += dstPitch >> 1;
+  lq2xS_32_def(dst0, dst1, src0, src1, src1, width);
+}
+
+/************************************************************************/
+/* hq3x filters                                                         */
+/************************************************************************/
+
+/************************************************************************/
+/* scale2x filters                                                      */
+/************************************************************************/
+
+/************************************************************************/
+/* scale3x filters                                                      */
+/************************************************************************/
+
diff --git a/source/gles2glide64/src/GlideHQ/TextureFilters_hq2x.h b/source/gles2glide64/src/GlideHQ/TextureFilters_hq2x.h
new file mode 100644 (file)
index 0000000..7946323
--- /dev/null
@@ -0,0 +1,1847 @@
+/*
+Copyright (C) 2003 Rice1964
+
+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.
+
+*/
+
+/* Copyright (C) 2007 Hiroshi Morii <koolsmoky(at)users.sourceforge.net>
+ * Modified for the Texture Filtering library
+ */
+
+case 0 : 
+case 1 : 
+case 4 : 
+case 5 : 
+case 32 : 
+case 33 : 
+case 36 : 
+case 37 : 
+case 128 : 
+case 129 : 
+case 132 : 
+case 133 : 
+case 160 : 
+case 161 : 
+case 164 : 
+case 165 : 
+{
+  P0 = I211(4, 1, 3);
+  P1 = I211(4, 1, 5);
+  P2 = I211(4, 3, 7);
+  P3 = I211(4, 5, 7);
+} break;
+case 2 : 
+case 34 : 
+case 130 : 
+case 162 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 2);
+  P2 = I211(4, 3, 7);
+  P3 = I211(4, 5, 7);
+} break;
+case 3 : 
+case 35 : 
+case 131 : 
+case 163 : 
+{
+  P0 = I31(4, 3);
+  P1 = I31(4, 2);
+  P2 = I211(4, 3, 7);
+  P3 = I211(4, 5, 7);
+} break;
+case 6 : 
+case 38 : 
+case 134 : 
+case 166 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 5);
+  P2 = I211(4, 3, 7);
+  P3 = I211(4, 5, 7);
+} break;
+case 7 : 
+case 39 : 
+case 135 : 
+case 167 : 
+{
+  P0 = I31(4, 3);
+  P1 = I31(4, 5);
+  P2 = I211(4, 3, 7);
+  P3 = I211(4, 5, 7);
+} break;
+case 8 : 
+case 12 : 
+case 136 : 
+case 140 : 
+{
+  P0 = I31(4, 0);
+  P1 = I211(4, 1, 5);
+  P2 = I31(4, 6);
+  P3 = I211(4, 5, 7);
+} break;
+case 9 : 
+case 13 : 
+case 137 : 
+case 141 : 
+{
+  P0 = I31(4, 1);
+  P1 = I211(4, 1, 5);
+  P2 = I31(4, 6);
+  P3 = I211(4, 5, 7);
+} break;
+case 10 : 
+case 138 : 
+{
+  P1 = I31(4, 2);
+  P2 = I31(4, 6);
+  P3 = I211(4, 5, 7);
+  if (HQ2X_MUL) {
+    P0 = I31(4, 0);
+  } else {
+    P0 = I211(4, 1, 3);
+  }
+} break;
+case 11 : 
+case 139 : 
+{
+  P1 = I31(4, 2);
+  P2 = I31(4, 6);
+  P3 = I211(4, 5, 7);
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I211(4, 1, 3);
+  }
+} break;
+case 14 : 
+case 142 : 
+{
+  P2 = I31(4, 6);
+  P3 = I211(4, 5, 7);
+  if (HQ2X_MUL) {
+    P0 = I31(4, 0);
+    P1 = I31(4, 5);
+  } else {
+    P0 = I332(1, 3, 4);
+    P1 = I521(4, 1, 5);
+  }
+} break;
+case 15 : 
+case 143 : 
+{
+  P2 = I31(4, 6);
+  P3 = I211(4, 5, 7);
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+    P1 = I31(4, 5);
+  } else {
+    P0 = I332(1, 3, 4);
+    P1 = I521(4, 1, 5);
+  }
+} break;
+case 16 : 
+case 17 : 
+case 48 : 
+case 49 : 
+{
+  P0 = I211(4, 1, 3);
+  P1 = I31(4, 2);
+  P2 = I211(4, 3, 7);
+  P3 = I31(4, 8);
+} break;
+case 18 : 
+case 50 : 
+{
+  P0 = I31(4, 0);
+  P2 = I211(4, 3, 7);
+  P3 = I31(4, 8);
+  if (HQ2X_MUR) {
+    P1 = I31(4, 2);
+  } else {
+    P1 = I211(4, 1, 5);
+  }
+} break;
+case 19 : 
+case 51 : 
+{
+  P2 = I211(4, 3, 7);
+  P3 = I31(4, 8);
+  if (HQ2X_MUR) {
+    P0 = I31(4, 3);
+    P1 = I31(4, 2);
+  } else {
+    P0 = I521(4, 1, 3);
+    P1 = I332(1, 5, 4);
+  }
+} break;
+case 20 : 
+case 21 : 
+case 52 : 
+case 53 : 
+{
+  P0 = I211(4, 1, 3);
+  P1 = I31(4, 1);
+  P2 = I211(4, 3, 7);
+  P3 = I31(4, 8);
+} break;
+case 22 : 
+case 54 : 
+{
+  P0 = I31(4, 0);
+  P2 = I211(4, 3, 7);
+  P3 = I31(4, 8);
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I211(4, 1, 5);
+  }
+} break;
+case 23 : 
+case 55 : 
+{
+  P2 = I211(4, 3, 7);
+  P3 = I31(4, 8);
+  if (HQ2X_MUR) {
+    P0 = I31(4, 3);
+    P1 = IC(4);
+  } else {
+    P0 = I521(4, 1, 3);
+    P1 = I332(1, 5, 4);
+  }
+} break;
+case 24 : 
+case 66 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 2);
+  P2 = I31(4, 6);
+  P3 = I31(4, 8);
+} break;
+case 25 : 
+{
+  P0 = I31(4, 1);
+  P1 = I31(4, 2);
+  P2 = I31(4, 6);
+  P3 = I31(4, 8);
+} break;
+case 26 : 
+case 31 : 
+case 95 : 
+{
+  P2 = I31(4, 6);
+  P3 = I31(4, 8);
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I211(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I211(4, 1, 5);
+  }
+} break;
+case 27 : 
+case 75 : 
+{
+  P1 = I31(4, 2);
+  P2 = I31(4, 6);
+  P3 = I31(4, 8);
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I211(4, 1, 3);
+  }
+} break;
+case 28 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 1);
+  P2 = I31(4, 6);
+  P3 = I31(4, 8);
+} break;
+case 29 : 
+{
+  P0 = I31(4, 1);
+  P1 = I31(4, 1);
+  P2 = I31(4, 6);
+  P3 = I31(4, 8);
+} break;
+case 30 : 
+case 86 : 
+{
+  P0 = I31(4, 0);
+  P2 = I31(4, 6);
+  P3 = I31(4, 8);
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I211(4, 1, 5);
+  }
+} break;
+case 40 : 
+case 44 : 
+case 168 : 
+case 172 : 
+{
+  P0 = I31(4, 0);
+  P1 = I211(4, 1, 5);
+  P2 = I31(4, 7);
+  P3 = I211(4, 5, 7);
+} break;
+case 41 : 
+case 45 : 
+case 169 : 
+case 173 : 
+{
+  P0 = I31(4, 1);
+  P1 = I211(4, 1, 5);
+  P2 = I31(4, 7);
+  P3 = I211(4, 5, 7);
+} break;
+case 42 : 
+case 170 : 
+{
+  P1 = I31(4, 2);
+  P3 = I211(4, 5, 7);
+  if (HQ2X_MUL) {
+    P0 = I31(4, 0);
+    P2 = I31(4, 7);
+  } else {
+    P0 = I332(1, 3, 4);
+    P2 = I521(4, 3, 7);
+  }
+} break;
+case 43 : 
+case 171 : 
+{
+  P1 = I31(4, 2);
+  P3 = I211(4, 5, 7);
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+    P2 = I31(4, 7);
+  } else {
+    P0 = I332(1, 3, 4);
+    P2 = I521(4, 3, 7);
+  }
+} break;
+case 46 : 
+case 174 : 
+{
+  P1 = I31(4, 5);
+  P2 = I31(4, 7);
+  P3 = I211(4, 5, 7);
+  if (HQ2X_MUL) {
+    P0 = I31(4, 0);
+  } else {
+    P0 = I611(4, 1, 3);
+  }
+} break;
+case 47 : 
+case 175 : 
+{
+  P1 = I31(4, 5);
+  P2 = I31(4, 7);
+  P3 = I211(4, 5, 7);
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I1411(4, 1, 3);
+  }
+} break;
+case 56 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 2);
+  P2 = I31(4, 7);
+  P3 = I31(4, 8);
+} break;
+case 57 : 
+{
+  P0 = I31(4, 1);
+  P1 = I31(4, 2);
+  P2 = I31(4, 7);
+  P3 = I31(4, 8);
+} break;
+case 58 : 
+{
+  P2 = I31(4, 7);
+  P3 = I31(4, 8);
+  if (HQ2X_MUL) {
+    P0 = I31(4, 0);
+  } else {
+    P0 = I611(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = I31(4, 2);
+  } else {
+    P1 = I611(4, 1, 5);
+  }
+} break;
+case 59 : 
+{
+  P2 = I31(4, 7);
+  P3 = I31(4, 8);
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I211(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = I31(4, 2);
+  } else {
+    P1 = I611(4, 1, 5);
+  }
+} break;
+case 60 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 1);
+  P2 = I31(4, 7);
+  P3 = I31(4, 8);
+} break;
+case 61 : 
+{
+  P0 = I31(4, 1);
+  P1 = I31(4, 1);
+  P2 = I31(4, 7);
+  P3 = I31(4, 8);
+} break;
+case 62 : 
+{
+  P0 = I31(4, 0);
+  P2 = I31(4, 7);
+  P3 = I31(4, 8);
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I211(4, 1, 5);
+  }
+} break;
+case 63 : 
+{
+  P2 = I31(4, 7);
+  P3 = I31(4, 8);
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I1411(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I211(4, 1, 5);
+  }
+} break;
+case 64 : 
+case 65 : 
+case 68 : 
+case 69 : 
+{
+  P0 = I211(4, 1, 3);
+  P1 = I211(4, 1, 5);
+  P2 = I31(4, 6);
+  P3 = I31(4, 8);
+} break;
+case 67 : 
+{
+  P0 = I31(4, 3);
+  P1 = I31(4, 2);
+  P2 = I31(4, 6);
+  P3 = I31(4, 8);
+} break;
+case 70 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 5);
+  P2 = I31(4, 6);
+  P3 = I31(4, 8);
+} break;
+case 71 : 
+{
+  P0 = I31(4, 3);
+  P1 = I31(4, 5);
+  P2 = I31(4, 6);
+  P3 = I31(4, 8);
+} break;
+case 72 : 
+case 76 : 
+{
+  P0 = I31(4, 0);
+  P1 = I211(4, 1, 5);
+  P3 = I31(4, 8);
+  if (HQ2X_MDL) {
+    P2 = I31(4, 6);
+  } else {
+    P2 = I211(4, 3, 7);
+  }
+} break;
+case 73 : 
+case 77 : 
+{
+  P1 = I211(4, 1, 5);
+  P3 = I31(4, 8);
+  if (HQ2X_MDL) {
+    P0 = I31(4, 1);
+    P2 = I31(4, 6);
+  } else {
+    P0 = I521(4, 3, 1);
+    P2 = I332(3, 7, 4);
+  }
+} break;
+case 74 : 
+case 107 : 
+case 123 : 
+{
+  P1 = I31(4, 2);
+  P3 = I31(4, 8);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I211(4, 3, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I211(4, 1, 3);
+  }
+} break;
+case 78 : 
+{
+  P1 = I31(4, 5);
+  P3 = I31(4, 8);
+  if (HQ2X_MDL) {
+    P2 = I31(4, 6);
+  } else {
+    P2 = I611(4, 3, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = I31(4, 0);
+  } else {
+    P0 = I611(4, 1, 3);
+  }
+} break;
+case 79 : 
+{
+  P1 = I31(4, 5);
+  P3 = I31(4, 8);
+  if (HQ2X_MDL) {
+    P2 = I31(4, 6);
+  } else {
+    P2 = I611(4, 3, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I211(4, 1, 3);
+  }
+} break;
+case 80 : 
+case 81 : 
+{
+  P0 = I211(4, 1, 3);
+  P1 = I31(4, 2);
+  P2 = I31(4, 6);
+  if (HQ2X_MDR) {
+    P3 = I31(4, 8);
+  } else {
+    P3 = I211(4, 5, 7);
+  }
+} break;
+case 82 : 
+case 214 : 
+case 222 : 
+{
+  P0 = I31(4, 0);
+  P2 = I31(4, 6);
+  if (HQ2X_MDR) {
+    P3 = IC(4);
+  } else {
+    P3 = I211(4, 5, 7);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I211(4, 1, 5);
+  }
+} break;
+case 83 : 
+{
+  P0 = I31(4, 3);
+  P2 = I31(4, 6);
+  if (HQ2X_MDR) {
+    P3 = I31(4, 8);
+  } else {
+    P3 = I611(4, 5, 7);
+  }
+  if (HQ2X_MUR) {
+    P1 = I31(4, 2);
+  } else {
+    P1 = I611(4, 1, 5);
+  }
+} break;
+case 84 : 
+case 85 : 
+{
+  P0 = I211(4, 1, 3);
+  P2 = I31(4, 6);
+  if (HQ2X_MDR) {
+    P1 = I31(4, 1);
+    P3 = I31(4, 8);
+  } else {
+    P1 = I521(4, 5, 1);
+    P3 = I332(5, 7, 4);
+  }
+} break;
+case 87 : 
+{
+  P0 = I31(4, 3);
+  P2 = I31(4, 6);
+  if (HQ2X_MDR) {
+    P3 = I31(4, 8);
+  } else {
+    P3 = I611(4, 5, 7);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I211(4, 1, 5);
+  }
+} break;
+case 88 : 
+case 248 : 
+case 250 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 2);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I211(4, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(4);
+  } else {
+    P3 = I211(4, 5, 7);
+  }
+} break;
+case 89 : 
+{
+  P0 = I31(4, 1);
+  P1 = I31(4, 2);
+  if (HQ2X_MDL) {
+    P2 = I31(4, 6);
+  } else {
+    P2 = I611(4, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = I31(4, 8);
+  } else {
+    P3 = I611(4, 5, 7);
+  }
+} break;
+case 90 : 
+{
+  if (HQ2X_MDL) {
+    P2 = I31(4, 6);
+  } else {
+    P2 = I611(4, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = I31(4, 8);
+  } else {
+    P3 = I611(4, 5, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = I31(4, 0);
+  } else {
+    P0 = I611(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = I31(4, 2);
+  } else {
+    P1 = I611(4, 1, 5);
+  }
+} break;
+case 91 : 
+{
+  if (HQ2X_MDL) {
+    P2 = I31(4, 6);
+  } else {
+    P2 = I611(4, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = I31(4, 8);
+  } else {
+    P3 = I611(4, 5, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I211(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = I31(4, 2);
+  } else {
+    P1 = I611(4, 1, 5);
+  }
+} break;
+case 92 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 1);
+  if (HQ2X_MDL) {
+    P2 = I31(4, 6);
+  } else {
+    P2 = I611(4, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = I31(4, 8);
+  } else {
+    P3 = I611(4, 5, 7);
+  }
+} break;
+case 93 : 
+{
+  P0 = I31(4, 1);
+  P1 = I31(4, 1);
+  if (HQ2X_MDL) {
+    P2 = I31(4, 6);
+  } else {
+    P2 = I611(4, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = I31(4, 8);
+  } else {
+    P3 = I611(4, 5, 7);
+  }
+} break;
+case 94 : 
+{
+  if (HQ2X_MDL) {
+    P2 = I31(4, 6);
+  } else {
+    P2 = I611(4, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = I31(4, 8);
+  } else {
+    P3 = I611(4, 5, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = I31(4, 0);
+  } else {
+    P0 = I611(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I211(4, 1, 5);
+  }
+} break;
+case 96 : 
+case 97 : 
+case 100 : 
+case 101 : 
+{
+  P0 = I211(4, 1, 3);
+  P1 = I211(4, 1, 5);
+  P2 = I31(4, 3);
+  P3 = I31(4, 8);
+} break;
+case 98 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 2);
+  P2 = I31(4, 3);
+  P3 = I31(4, 8);
+} break;
+case 99 : 
+{
+  P0 = I31(4, 3);
+  P1 = I31(4, 2);
+  P2 = I31(4, 3);
+  P3 = I31(4, 8);
+} break;
+case 102 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 5);
+  P2 = I31(4, 3);
+  P3 = I31(4, 8);
+} break;
+case 103 : 
+{
+  P0 = I31(4, 3);
+  P1 = I31(4, 5);
+  P2 = I31(4, 3);
+  P3 = I31(4, 8);
+} break;
+case 104 : 
+case 108 : 
+{
+  P0 = I31(4, 0);
+  P1 = I211(4, 1, 5);
+  P3 = I31(4, 8);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I211(4, 3, 7);
+  }
+} break;
+case 105 : 
+case 109 : 
+{
+  P1 = I211(4, 1, 5);
+  P3 = I31(4, 8);
+  if (HQ2X_MDL) {
+    P0 = I31(4, 1);
+    P2 = IC(4);
+  } else {
+    P0 = I521(4, 3, 1);
+    P2 = I332(3, 7, 4);
+  }
+} break;
+case 106 : 
+case 120 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 2);
+  P3 = I31(4, 8);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I211(4, 3, 7);
+  }
+} break;
+case 110 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 5);
+  P3 = I31(4, 8);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I211(4, 3, 7);
+  }
+} break;
+case 111 : 
+{
+  P1 = I31(4, 5);
+  P3 = I31(4, 8);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I211(4, 3, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I1411(4, 1, 3);
+  }
+} break;
+case 112 : 
+case 113 : 
+{
+  P0 = I211(4, 1, 3);
+  P1 = I31(4, 2);
+  if (HQ2X_MDR) {
+    P2 = I31(4, 3);
+    P3 = I31(4, 8);
+  } else {
+    P2 = I521(4, 7, 3);
+    P3 = I332(5, 7, 4);
+  }
+} break;
+case 114 : 
+{
+  P0 = I31(4, 0);
+  P2 = I31(4, 3);
+  if (HQ2X_MDR) {
+    P3 = I31(4, 8);
+  } else {
+    P3 = I611(4, 5, 7);
+  }
+  if (HQ2X_MUR) {
+    P1 = I31(4, 2);
+  } else {
+    P1 = I611(4, 1, 5);
+  }
+} break;
+case 115 : 
+{
+  P0 = I31(4, 3);
+  P2 = I31(4, 3);
+  if (HQ2X_MDR) {
+    P3 = I31(4, 8);
+  } else {
+    P3 = I611(4, 5, 7);
+  }
+  if (HQ2X_MUR) {
+    P1 = I31(4, 2);
+  } else {
+    P1 = I611(4, 1, 5);
+  }
+} break;
+case 116 : 
+case 117 : 
+{
+  P0 = I211(4, 1, 3);
+  P1 = I31(4, 1);
+  P2 = I31(4, 3);
+  if (HQ2X_MDR) {
+    P3 = I31(4, 8);
+  } else {
+    P3 = I611(4, 5, 7);
+  }
+} break;
+case 118 : 
+{
+  P0 = I31(4, 0);
+  P2 = I31(4, 3);
+  P3 = I31(4, 8);
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I211(4, 1, 5);
+  }
+} break;
+case 119 : 
+{
+  P2 = I31(4, 3);
+  P3 = I31(4, 8);
+  if (HQ2X_MUR) {
+    P0 = I31(4, 3);
+    P1 = IC(4);
+  } else {
+    P0 = I521(4, 1, 3);
+    P1 = I332(1, 5, 4);
+  }
+} break;
+case 121 : 
+{
+  P0 = I31(4, 1);
+  P1 = I31(4, 2);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I211(4, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = I31(4, 8);
+  } else {
+    P3 = I611(4, 5, 7);
+  }
+} break;
+case 122 : 
+{
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I211(4, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = I31(4, 8);
+  } else {
+    P3 = I611(4, 5, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = I31(4, 0);
+  } else {
+    P0 = I611(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = I31(4, 2);
+  } else {
+    P1 = I611(4, 1, 5);
+  }
+} break;
+case 124 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 1);
+  P3 = I31(4, 8);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I211(4, 3, 7);
+  }
+} break;
+case 125 : 
+{
+  P1 = I31(4, 1);
+  P3 = I31(4, 8);
+  if (HQ2X_MDL) {
+    P0 = I31(4, 1);
+    P2 = IC(4);
+  } else {
+    P0 = I521(4, 3, 1);
+    P2 = I332(3, 7, 4);
+  }
+} break;
+case 126 : 
+{
+  P0 = I31(4, 0);
+  P3 = I31(4, 8);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I211(4, 3, 7);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I211(4, 1, 5);
+  }
+} break;
+case 127 : 
+{
+  P3 = I31(4, 8);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I211(4, 3, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I1411(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I211(4, 1, 5);
+  }
+} break;
+case 144 : 
+case 145 : 
+case 176 : 
+case 177 : 
+{
+  P0 = I211(4, 1, 3);
+  P1 = I31(4, 2);
+  P2 = I211(4, 3, 7);
+  P3 = I31(4, 7);
+} break;
+case 146 : 
+case 178 : 
+{
+  P0 = I31(4, 0);
+  P2 = I211(4, 3, 7);
+  if (HQ2X_MUR) {
+    P1 = I31(4, 2);
+    P3 = I31(4, 7);
+  } else {
+    P1 = I332(1, 5, 4);
+    P3 = I521(4, 5, 7);
+  }
+} break;
+case 147 : 
+case 179 : 
+{
+  P0 = I31(4, 3);
+  P2 = I211(4, 3, 7);
+  P3 = I31(4, 7);
+  if (HQ2X_MUR) {
+    P1 = I31(4, 2);
+  } else {
+    P1 = I611(4, 1, 5);
+  }
+} break;
+case 148 : 
+case 149 : 
+case 180 : 
+case 181 : 
+{
+  P0 = I211(4, 1, 3);
+  P1 = I31(4, 1);
+  P2 = I211(4, 3, 7);
+  P3 = I31(4, 7);
+} break;
+case 150 : 
+case 182 : 
+{
+  P0 = I31(4, 0);
+  P2 = I211(4, 3, 7);
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+    P3 = I31(4, 7);
+  } else {
+    P1 = I332(1, 5, 4);
+    P3 = I521(4, 5, 7);
+  }
+} break;
+case 151 : 
+case 183 : 
+{
+  P0 = I31(4, 3);
+  P2 = I211(4, 3, 7);
+  P3 = I31(4, 7);
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I1411(4, 1, 5);
+  }
+} break;
+case 152 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 2);
+  P2 = I31(4, 6);
+  P3 = I31(4, 7);
+} break;
+case 153 : 
+{
+  P0 = I31(4, 1);
+  P1 = I31(4, 2);
+  P2 = I31(4, 6);
+  P3 = I31(4, 7);
+} break;
+case 154 : 
+{
+  P2 = I31(4, 6);
+  P3 = I31(4, 7);
+  if (HQ2X_MUL) {
+    P0 = I31(4, 0);
+  } else {
+    P0 = I611(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = I31(4, 2);
+  } else {
+    P1 = I611(4, 1, 5);
+  }
+} break;
+case 155 : 
+{
+  P1 = I31(4, 2);
+  P2 = I31(4, 6);
+  P3 = I31(4, 7);
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I211(4, 1, 3);
+  }
+} break;
+case 156 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 1);
+  P2 = I31(4, 6);
+  P3 = I31(4, 7);
+} break;
+case 157 : 
+{
+  P0 = I31(4, 1);
+  P1 = I31(4, 1);
+  P2 = I31(4, 6);
+  P3 = I31(4, 7);
+} break;
+case 158 : 
+{
+  P2 = I31(4, 6);
+  P3 = I31(4, 7);
+  if (HQ2X_MUL) {
+    P0 = I31(4, 0);
+  } else {
+    P0 = I611(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I211(4, 1, 5);
+  }
+} break;
+case 159 : 
+{
+  P2 = I31(4, 6);
+  P3 = I31(4, 7);
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I211(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I1411(4, 1, 5);
+  }
+} break;
+case 184 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 2);
+  P2 = I31(4, 7);
+  P3 = I31(4, 7);
+} break;
+case 185 : 
+{
+  P0 = I31(4, 1);
+  P1 = I31(4, 2);
+  P2 = I31(4, 7);
+  P3 = I31(4, 7);
+} break;
+case 186 : 
+{
+  P2 = I31(4, 7);
+  P3 = I31(4, 7);
+  if (HQ2X_MUL) {
+    P0 = I31(4, 0);
+  } else {
+    P0 = I611(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = I31(4, 2);
+  } else {
+    P1 = I611(4, 1, 5);
+  }
+} break;
+case 187 : 
+{
+  P1 = I31(4, 2);
+  P3 = I31(4, 7);
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+    P2 = I31(4, 7);
+  } else {
+    P0 = I332(1, 3, 4);
+    P2 = I521(4, 3, 7);
+  }
+} break;
+case 188 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 1);
+  P2 = I31(4, 7);
+  P3 = I31(4, 7);
+} break;
+case 189 : 
+{
+  P0 = I31(4, 1);
+  P1 = I31(4, 1);
+  P2 = I31(4, 7);
+  P3 = I31(4, 7);
+} break;
+case 190 : 
+{
+  P0 = I31(4, 0);
+  P2 = I31(4, 7);
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+    P3 = I31(4, 7);
+  } else {
+    P1 = I332(1, 5, 4);
+    P3 = I521(4, 5, 7);
+  }
+} break;
+case 191 : 
+{
+  P2 = I31(4, 7);
+  P3 = I31(4, 7);
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I1411(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I1411(4, 1, 5);
+  }
+} break;
+case 192 : 
+case 193 : 
+case 196 : 
+case 197 : 
+{
+  P0 = I211(4, 1, 3);
+  P1 = I211(4, 1, 5);
+  P2 = I31(4, 6);
+  P3 = I31(4, 5);
+} break;
+case 194 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 2);
+  P2 = I31(4, 6);
+  P3 = I31(4, 5);
+} break;
+case 195 : 
+{
+  P0 = I31(4, 3);
+  P1 = I31(4, 2);
+  P2 = I31(4, 6);
+  P3 = I31(4, 5);
+} break;
+case 198 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 5);
+  P2 = I31(4, 6);
+  P3 = I31(4, 5);
+} break;
+case 199 : 
+{
+  P0 = I31(4, 3);
+  P1 = I31(4, 5);
+  P2 = I31(4, 6);
+  P3 = I31(4, 5);
+} break;
+case 200 : 
+case 204 : 
+{
+  P0 = I31(4, 0);
+  P1 = I211(4, 1, 5);
+  if (HQ2X_MDL) {
+    P2 = I31(4, 6);
+    P3 = I31(4, 5);
+  } else {
+    P2 = I332(3, 7, 4);
+    P3 = I521(4, 7, 5);
+  }
+} break;
+case 201 : 
+case 205 : 
+{
+  P0 = I31(4, 1);
+  P1 = I211(4, 1, 5);
+  P3 = I31(4, 5);
+  if (HQ2X_MDL) {
+    P2 = I31(4, 6);
+  } else {
+    P2 = I611(4, 3, 7);
+  }
+} break;
+case 202 : 
+{
+  P1 = I31(4, 2);
+  P3 = I31(4, 5);
+  if (HQ2X_MDL) {
+    P2 = I31(4, 6);
+  } else {
+    P2 = I611(4, 3, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = I31(4, 0);
+  } else {
+    P0 = I611(4, 1, 3);
+  }
+} break;
+case 203 : 
+{
+  P1 = I31(4, 2);
+  P2 = I31(4, 6);
+  P3 = I31(4, 5);
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I211(4, 1, 3);
+  }
+} break;
+case 206 : 
+{
+  P1 = I31(4, 5);
+  P3 = I31(4, 5);
+  if (HQ2X_MDL) {
+    P2 = I31(4, 6);
+  } else {
+    P2 = I611(4, 3, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = I31(4, 0);
+  } else {
+    P0 = I611(4, 1, 3);
+  }
+} break;
+case 207 : 
+{
+  P2 = I31(4, 6);
+  P3 = I31(4, 5);
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+    P1 = I31(4, 5);
+  } else {
+    P0 = I332(1, 3, 4);
+    P1 = I521(4, 1, 5);
+  }
+} break;
+case 208 : 
+case 209 : 
+{
+  P0 = I211(4, 1, 3);
+  P1 = I31(4, 2);
+  P2 = I31(4, 6);
+  if (HQ2X_MDR) {
+    P3 = IC(4);
+  } else {
+    P3 = I211(4, 5, 7);
+  }
+} break;
+case 210 : 
+case 216 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 2);
+  P2 = I31(4, 6);
+  if (HQ2X_MDR) {
+    P3 = IC(4);
+  } else {
+    P3 = I211(4, 5, 7);
+  }
+} break;
+case 211 : 
+{
+  P0 = I31(4, 3);
+  P1 = I31(4, 2);
+  P2 = I31(4, 6);
+  if (HQ2X_MDR) {
+    P3 = IC(4);
+  } else {
+    P3 = I211(4, 5, 7);
+  }
+} break;
+case 212 : 
+case 213 : 
+{
+  P0 = I211(4, 1, 3);
+  P2 = I31(4, 6);
+  if (HQ2X_MDR) {
+    P1 = I31(4, 1);
+    P3 = IC(4);
+  } else {
+    P1 = I521(4, 5, 1);
+    P3 = I332(5, 7, 4);
+  }
+} break;
+case 215 : 
+{
+  P0 = I31(4, 3);
+  P2 = I31(4, 6);
+  if (HQ2X_MDR) {
+    P3 = IC(4);
+  } else {
+    P3 = I211(4, 5, 7);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I1411(4, 1, 5);
+  }
+} break;
+case 217 : 
+{
+  P0 = I31(4, 1);
+  P1 = I31(4, 2);
+  P2 = I31(4, 6);
+  if (HQ2X_MDR) {
+    P3 = IC(4);
+  } else {
+    P3 = I211(4, 5, 7);
+  }
+} break;
+case 218 : 
+{
+  if (HQ2X_MDL) {
+    P2 = I31(4, 6);
+  } else {
+    P2 = I611(4, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(4);
+  } else {
+    P3 = I211(4, 5, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = I31(4, 0);
+  } else {
+    P0 = I611(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = I31(4, 2);
+  } else {
+    P1 = I611(4, 1, 5);
+  }
+} break;
+case 219 : 
+{
+  P1 = I31(4, 2);
+  P2 = I31(4, 6);
+  if (HQ2X_MDR) {
+    P3 = IC(4);
+  } else {
+    P3 = I211(4, 5, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I211(4, 1, 3);
+  }
+} break;
+case 220 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 1);
+  if (HQ2X_MDL) {
+    P2 = I31(4, 6);
+  } else {
+    P2 = I611(4, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(4);
+  } else {
+    P3 = I211(4, 5, 7);
+  }
+} break;
+case 221 : 
+{
+  P0 = I31(4, 1);
+  P2 = I31(4, 6);
+  if (HQ2X_MDR) {
+    P1 = I31(4, 1);
+    P3 = IC(4);
+  } else {
+    P1 = I521(4, 5, 1);
+    P3 = I332(5, 7, 4);
+  }
+} break;
+case 223 : 
+{
+  P2 = I31(4, 6);
+  if (HQ2X_MDR) {
+    P3 = IC(4);
+  } else {
+    P3 = I211(4, 5, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I211(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I1411(4, 1, 5);
+  }
+} break;
+case 224 : 
+case 225 : 
+case 228 : 
+case 229 : 
+{
+  P0 = I211(4, 1, 3);
+  P1 = I211(4, 1, 5);
+  P2 = I31(4, 3);
+  P3 = I31(4, 5);
+} break;
+case 226 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 2);
+  P2 = I31(4, 3);
+  P3 = I31(4, 5);
+} break;
+case 227 : 
+{
+  P0 = I31(4, 3);
+  P1 = I31(4, 2);
+  P2 = I31(4, 3);
+  P3 = I31(4, 5);
+} break;
+case 230 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 5);
+  P2 = I31(4, 3);
+  P3 = I31(4, 5);
+} break;
+case 231 : 
+{
+  P0 = I31(4, 3);
+  P1 = I31(4, 5);
+  P2 = I31(4, 3);
+  P3 = I31(4, 5);
+} break;
+case 232 : 
+case 236 : 
+{
+  P0 = I31(4, 0);
+  P1 = I211(4, 1, 5);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+    P3 = I31(4, 5);
+  } else {
+    P2 = I332(3, 7, 4);
+    P3 = I521(4, 7, 5);
+  }
+} break;
+case 233 : 
+case 237 : 
+{
+  P0 = I31(4, 1);
+  P1 = I211(4, 1, 5);
+  P3 = I31(4, 5);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I1411(4, 3, 7);
+  }
+} break;
+case 234 : 
+{
+  P1 = I31(4, 2);
+  P3 = I31(4, 5);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I211(4, 3, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = I31(4, 0);
+  } else {
+    P0 = I611(4, 1, 3);
+  }
+} break;
+case 235 : 
+{
+  P1 = I31(4, 2);
+  P3 = I31(4, 5);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I1411(4, 3, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I211(4, 1, 3);
+  }
+} break;
+case 238 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 5);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+    P3 = I31(4, 5);
+  } else {
+    P2 = I332(3, 7, 4);
+    P3 = I521(4, 7, 5);
+  }
+} break;
+case 239 : 
+{
+  P1 = I31(4, 5);
+  P3 = I31(4, 5);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I1411(4, 3, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I1411(4, 1, 3);
+  }
+} break;
+case 240 : 
+case 241 : 
+{
+  P0 = I211(4, 1, 3);
+  P1 = I31(4, 2);
+  if (HQ2X_MDR) {
+    P2 = I31(4, 3);
+    P3 = IC(4);
+  } else {
+    P2 = I521(4, 7, 3);
+    P3 = I332(5, 7, 4);
+  }
+} break;
+case 242 : 
+{
+  P0 = I31(4, 0);
+  P2 = I31(4, 3);
+  if (HQ2X_MDR) {
+    P3 = IC(4);
+  } else {
+    P3 = I211(4, 5, 7);
+  }
+  if (HQ2X_MUR) {
+    P1 = I31(4, 2);
+  } else {
+    P1 = I611(4, 1, 5);
+  }
+} break;
+case 243 : 
+{
+  P0 = I31(4, 3);
+  P1 = I31(4, 2);
+  if (HQ2X_MDR) {
+    P2 = I31(4, 3);
+    P3 = IC(4);
+  } else {
+    P2 = I521(4, 7, 3);
+    P3 = I332(5, 7, 4);
+  }
+} break;
+case 244 : 
+case 245 : 
+{
+  P0 = I211(4, 1, 3);
+  P1 = I31(4, 1);
+  P2 = I31(4, 3);
+  if (HQ2X_MDR) {
+    P3 = IC(4);
+  } else {
+    P3 = I1411(4, 5, 7);
+  }
+} break;
+case 246 : 
+{
+  P0 = I31(4, 0);
+  P2 = I31(4, 3);
+  if (HQ2X_MDR) {
+    P3 = IC(4);
+  } else {
+    P3 = I1411(4, 5, 7);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I211(4, 1, 5);
+  }
+} break;
+case 247 : 
+{
+  P0 = I31(4, 3);
+  P2 = I31(4, 3);
+  if (HQ2X_MDR) {
+    P3 = IC(4);
+  } else {
+    P3 = I1411(4, 5, 7);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I1411(4, 1, 5);
+  }
+} break;
+case 249 : 
+{
+  P0 = I31(4, 1);
+  P1 = I31(4, 2);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I1411(4, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(4);
+  } else {
+    P3 = I211(4, 5, 7);
+  }
+} break;
+case 251 : 
+{
+  P1 = I31(4, 2);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I1411(4, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(4);
+  } else {
+    P3 = I211(4, 5, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I211(4, 1, 3);
+  }
+} break;
+case 252 : 
+{
+  P0 = I31(4, 0);
+  P1 = I31(4, 1);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I211(4, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(4);
+  } else {
+    P3 = I1411(4, 5, 7);
+  }
+} break;
+case 253 : 
+{
+  P0 = I31(4, 1);
+  P1 = I31(4, 1);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I1411(4, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(4);
+  } else {
+    P3 = I1411(4, 5, 7);
+  }
+} break;
+case 254 : 
+{
+  P0 = I31(4, 0);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I211(4, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(4);
+  } else {
+    P3 = I1411(4, 5, 7);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I211(4, 1, 5);
+  }
+} break;
+case 255 : 
+{
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I1411(4, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(4);
+  } else {
+    P3 = I1411(4, 5, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I1411(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I1411(4, 1, 5);
+  }
+} break;
diff --git a/source/gles2glide64/src/GlideHQ/TextureFilters_hq4x.cpp b/source/gles2glide64/src/GlideHQ/TextureFilters_hq4x.cpp
new file mode 100644 (file)
index 0000000..89c14ea
--- /dev/null
@@ -0,0 +1,892 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*  Based on Maxim Stepin and Rice1964 hq4x code */
+
+#include <math.h>
+#include <stdlib.h>
+#include "TextureFilters.h"
+
+#if !_16BPP_HACK
+static uint32 RGB444toYUV[4096];
+#define RGB444toYUV(val) RGB444toYUV[val & 0x0FFF]   /* val = ARGB4444 */
+
+/*inline static uint32 RGB444toYUV(uint32 val)
+{
+  uint32 r, g, b, Y, u, v;
+
+  r = (val & 0x0F00) >> 4;
+  g = (val & 0x00F0);
+  b = val & 0x000F;
+  r |= r >> 4;
+  g |= g >> 4;
+  b |= b << 4;
+
+  Y = (r + g + b) >> 2;
+  u = 128 + ((r - b) >> 2);
+  v = 128 + ((2*g - r - b)>>3);
+
+  return ((Y << 16) | (u << 8) | v);
+}*/
+
+static uint32 RGB555toYUV(uint32 val)
+{
+  uint32 r, g, b, Y, u, v;
+
+  r = (val & 0x7C00) >> 7;
+  g = (val & 0x03E0) >> 2;
+  b = (val & 0x001F) << 3;
+  r |= r >> 5;
+  g |= g >> 5;
+  b |= b >> 5;
+
+  Y = (r + g + b) >> 2;
+  u = 128 + ((r - b) >> 2);
+  v = 128 + ((2*g - r - b)>>3);
+
+  return ((Y << 16) | (u << 8) | v);
+}
+
+static uint32 RGB565toYUV(uint32 val)
+{
+  uint32 r, g, b, Y, u, v;
+
+  r = (val & 0xF800) >> 8;
+  g = (val & 0x07E0) >> 3;
+  b = (val & 0x001F) << 3;
+  r |= r >> 5;
+  g |= g >> 6;
+  b |= b >> 5;
+
+  Y = (r + g + b) >> 2;
+  u = 128 + ((r - b) >> 2);
+  v = 128 + ((2*g - r - b)>>3);
+
+  return ((Y << 16) | (u << 8) | v);
+}
+#endif /* !_16BPP_HACK */
+
+static uint32 RGB888toYUV(uint32 val)
+{
+#if 0
+  uint32 Yuv;
+
+  __asm {
+    mov eax, dword ptr [val];
+    mov ebx, eax;
+    mov ecx, eax;
+    and ebx, 0x000000ff; // b
+    and eax, 0x00ff0000; // r
+    and ecx, 0x0000ff00; // g
+    shl ebx, 14;
+    shr eax, 2;
+    shl ecx, 6;
+    mov edx, ebx;
+    add edx, eax;
+    add edx, ecx;
+    and edx, 0xffff0000;
+
+    sub eax, ebx;
+    add eax, 0x00800000;
+    shr eax, 8;
+    or  edx, eax;
+    sub eax, 0x00800000;
+    and edx, 0xffffff00;
+
+    add ecx, 0x00800000;
+    shr ecx, 5;
+    shr ebx, 7;
+    add eax, ebx;
+    sub ecx, eax;
+    shr ecx, 11;
+    or  edx, ecx;
+
+    mov dword ptr [Yuv], edx;
+  }
+
+  return Yuv;
+#else
+  uint32 r, g, b, Y, u, v;
+
+  r = (val & 0x00ff0000) >> 16;
+  g = (val & 0x0000ff00) >> 8;
+  b = val & 0x000000ff;
+
+  Y = (r + g + b) >> 2;
+  u = (0x00000200 + r - b) >> 2;
+  v = (0x00000400 + (g << 1) - r - b) >> 3;
+
+  return ((Y << 16) | (u << 8) | v);
+#endif
+}
+
+#define Ymask 0x00FF0000
+#define Umask 0x0000FF00
+#define Vmask 0x000000FF
+#define trY 0x00300000 // ?
+#define trU 0x00000700 // ??
+#define trV 0x00000006 // ???
+
+#define HQ4X_INTERP1(n, b) \
+static void hq4x_Interp1_##n (uint8 * pc, uint##b p1, uint##b p2) \
+{ \
+  /* *((uint##b*)pc) = (p1*3+p2) >> 2; */ \
+  *((uint##b*)pc) = INTERP_##n##_MASK_1_3((INTERP_##n##_MASK_1_3(p1)*3 + INTERP_##n##_MASK_1_3(p2)) / 4) \
+    | INTERP_##n##_MASK_SHIFTBACK_2_4((INTERP_##n##_MASK_SHIFT_2_4(p1)*3 + INTERP_##n##_MASK_SHIFT_2_4(p2)) / 4 ); \
+}
+
+#define HQ4X_INTERP2(n, b) \
+static void hq4x_Interp2_##n (uint8 * pc, uint##b p1, uint##b p2, uint##b p3) \
+{ \
+  /**((uint##b*)pc) = (p1*2+p2+p3) >> 2;*/ \
+  *((uint##b*)pc) =  INTERP_##n##_MASK_1_3((INTERP_##n##_MASK_1_3(p1)*2 + INTERP_##n##_MASK_1_3(p2) + INTERP_##n##_MASK_1_3(p3)) / 4) \
+    | INTERP_##n##_MASK_SHIFTBACK_2_4((INTERP_##n##_MASK_SHIFT_2_4(p1)*2 + INTERP_##n##_MASK_SHIFT_2_4(p2) + INTERP_##n##_MASK_SHIFT_2_4(p3)) / 4); \
+}
+
+#define HQ4X_INTERP3(n, b) \
+static void hq4x_Interp3_##n (uint8 * pc, uint##b p1, uint##b p2) \
+{ \
+  /**((uint##b*)pc) = (p1*7+p2)/8;*/ \
+  *((uint##b*)pc) =  INTERP_##n##_MASK_1_3((INTERP_##n##_MASK_1_3(p1)*7 + INTERP_##n##_MASK_1_3(p2)) / 8) \
+    | INTERP_##n##_MASK_SHIFTBACK_2_4((INTERP_##n##_MASK_SHIFT_2_4(p1)*7 + INTERP_##n##_MASK_SHIFT_2_4(p2)) / 8); \
+}
+
+#define HQ4X_INTERP5(n, b) \
+static void hq4x_Interp5_##n (uint8 * pc, uint##b p1, uint##b p2) \
+{ \
+  /**((uint##b*)pc) = (p1+p2) >> 1;*/ \
+  *((uint##b*)pc) =  INTERP_##n##_MASK_1_3((INTERP_##n##_MASK_1_3(p1) + INTERP_##n##_MASK_1_3(p2)) / 2) \
+    | INTERP_##n##_MASK_SHIFTBACK_2_4((INTERP_##n##_MASK_SHIFT_2_4(p1) + INTERP_##n##_MASK_SHIFT_2_4(p2)) / 2); \
+}
+
+#define HQ4X_INTERP6(n, b) \
+static void hq4x_Interp6_##n (uint8 * pc, uint##b p1, uint##b p2, uint##b p3) \
+{ \
+  /**((uint##b*)pc) = (p1*5+p2*2+p3)/8;*/ \
+  *((uint##b*)pc) =  INTERP_##n##_MASK_1_3((INTERP_##n##_MASK_1_3(p1)*5 + INTERP_##n##_MASK_1_3(p2)*2 + INTERP_##n##_MASK_1_3(p3)) / 8) \
+    | INTERP_##n##_MASK_SHIFTBACK_2_4((INTERP_##n##_MASK_SHIFT_2_4(p1)*5 + INTERP_##n##_MASK_SHIFT_2_4(p2)*2 + INTERP_##n##_MASK_SHIFT_2_4(p3)) / 8); \
+}
+
+#define HQ4X_INTERP7(n, b) \
+static void hq4x_Interp7_##n (uint8 * pc, uint##b p1, uint##b p2, uint##b p3) \
+{ \
+  /**((uint##b*)pc) = (p1*6+p2+p3)/8;*/ \
+  *((uint##b*)pc) =   INTERP_##n##_MASK_1_3((INTERP_##n##_MASK_1_3(p1)*6 + INTERP_##n##_MASK_1_3(p2) + INTERP_##n##_MASK_1_3(p3)) / 8) \
+    | INTERP_##n##_MASK_SHIFTBACK_2_4((INTERP_##n##_MASK_SHIFT_2_4(p1)*6 + INTERP_##n##_MASK_SHIFT_2_4(p2) + INTERP_##n##_MASK_SHIFT_2_4(p3)) / 8); \
+}
+
+#define HQ4X_INTERP8(n, b) \
+static void hq4x_Interp8_##n (uint8 * pc, uint##b p1, uint##b p2) \
+{ \
+  /**((uint##b*)pc) = (p1*5+p2*3)/8;*/ \
+  *((uint##b*)pc) =   INTERP_##n##_MASK_1_3((INTERP_##n##_MASK_1_3(p1)*5 + INTERP_##n##_MASK_1_3(p2)*3) / 8) \
+    | INTERP_##n##_MASK_SHIFTBACK_2_4((INTERP_##n##_MASK_SHIFT_2_4(p1)*5 + INTERP_##n##_MASK_SHIFT_2_4(p2)*3) / 8); \
+}
+
+#if !_16BPP_HACK
+#define INTERP_4444_MASK_1_3(v)           (v & 0x0F0F)
+#define INTERP_4444_MASK_SHIFT_2_4(v)     ((v & 0xF0F0) >> 4)
+#define INTERP_4444_MASK_SHIFTBACK_2_4(v) (INTERP_4444_MASK_1_3(v) << 4)
+HQ4X_INTERP1(4444, 16)
+HQ4X_INTERP2(4444, 16)
+HQ4X_INTERP3(4444, 16)
+HQ4X_INTERP5(4444, 16)
+HQ4X_INTERP6(4444, 16)
+HQ4X_INTERP7(4444, 16)
+HQ4X_INTERP8(4444, 16)
+
+#define INTERP_1555_MASK_1_3(v)           (v & 0x7C1F)
+#define INTERP_1555_MASK_SHIFT_2_4(v)     ((v & 0x83E0) >> 5)
+#define INTERP_1555_MASK_SHIFTBACK_2_4(v) (INTERP_1555_MASK_1_3(v) << 5)
+HQ4X_INTERP1(1555, 16)
+HQ4X_INTERP2(1555, 16)
+HQ4X_INTERP3(1555, 16)
+HQ4X_INTERP5(1555, 16)
+HQ4X_INTERP6(1555, 16)
+HQ4X_INTERP7(1555, 16)
+HQ4X_INTERP8(1555, 16)
+
+#define INTERP_565_MASK_1_3(v)           (v & 0xF81F)
+#define INTERP_565_MASK_SHIFT_2_4(v)     ((v & 0x7E0) >> 5)
+#define INTERP_565_MASK_SHIFTBACK_2_4(v) (INTERP_565_MASK_1_3(v) << 5)
+HQ4X_INTERP1(565, 16)
+HQ4X_INTERP2(565, 16)
+HQ4X_INTERP3(565, 16)
+HQ4X_INTERP5(565, 16)
+HQ4X_INTERP6(565, 16)
+HQ4X_INTERP7(565, 16)
+HQ4X_INTERP8(565, 16)
+#endif /* !_16BPP_HACK */
+
+#define INTERP_8888_MASK_1_3(v)           (v & 0x00FF00FF)
+#define INTERP_8888_MASK_SHIFT_2_4(v)     ((v & 0xFF00FF00) >> 8)
+#define INTERP_8888_MASK_SHIFTBACK_2_4(v) (INTERP_8888_MASK_1_3(v) << 8)
+HQ4X_INTERP1(8888, 32)
+HQ4X_INTERP2(8888, 32)
+HQ4X_INTERP3(8888, 32)
+HQ4X_INTERP5(8888, 32)
+HQ4X_INTERP6(8888, 32)
+HQ4X_INTERP7(8888, 32)
+HQ4X_INTERP8(8888, 32)
+
+#define PIXEL00_0     *((int*)(pOut)) = c[5];
+#define PIXEL00_11    hq4x_Interp1(pOut, c[5], c[4]);
+#define PIXEL00_12    hq4x_Interp1(pOut, c[5], c[2]);
+#define PIXEL00_20    hq4x_Interp2(pOut, c[5], c[2], c[4]);
+#define PIXEL00_50    hq4x_Interp5(pOut, c[2], c[4]);
+#define PIXEL00_80    hq4x_Interp8(pOut, c[5], c[1]);
+#define PIXEL00_81    hq4x_Interp8(pOut, c[5], c[4]);
+#define PIXEL00_82    hq4x_Interp8(pOut, c[5], c[2]);
+#define PIXEL01_0     *((int*)(pOut+BPP)) = c[5];
+#define PIXEL01_10    hq4x_Interp1(pOut+BPP, c[5], c[1]);
+#define PIXEL01_12    hq4x_Interp1(pOut+BPP, c[5], c[2]);
+#define PIXEL01_14    hq4x_Interp1(pOut+BPP, c[2], c[5]);
+#define PIXEL01_21    hq4x_Interp2(pOut+BPP, c[2], c[5], c[4]);
+#define PIXEL01_31    hq4x_Interp3(pOut+BPP, c[5], c[4]);
+#define PIXEL01_50    hq4x_Interp5(pOut+BPP, c[2], c[5]);
+#define PIXEL01_60    hq4x_Interp6(pOut+BPP, c[5], c[2], c[4]);
+#define PIXEL01_61    hq4x_Interp6(pOut+BPP, c[5], c[2], c[1]);
+#define PIXEL01_82    hq4x_Interp8(pOut+BPP, c[5], c[2]);
+#define PIXEL01_83    hq4x_Interp8(pOut+BPP, c[2], c[4]);
+#define PIXEL02_0     *((int*)(pOut+BPP2)) = c[5];
+#define PIXEL02_10    hq4x_Interp1(pOut+BPP2, c[5], c[3]);
+#define PIXEL02_11    hq4x_Interp1(pOut+BPP2, c[5], c[2]);
+#define PIXEL02_13    hq4x_Interp1(pOut+BPP2, c[2], c[5]);
+#define PIXEL02_21    hq4x_Interp2(pOut+BPP2, c[2], c[5], c[6]);
+#define PIXEL02_32    hq4x_Interp3(pOut+BPP2, c[5], c[6]);
+#define PIXEL02_50    hq4x_Interp5(pOut+BPP2, c[2], c[5]);
+#define PIXEL02_60    hq4x_Interp6(pOut+BPP2, c[5], c[2], c[6]);
+#define PIXEL02_61    hq4x_Interp6(pOut+BPP2, c[5], c[2], c[3]);
+#define PIXEL02_81    hq4x_Interp8(pOut+BPP2, c[5], c[2]);
+#define PIXEL02_83    hq4x_Interp8(pOut+BPP2, c[2], c[6]);
+#define PIXEL03_0     *((int*)(pOut+BPP3)) = c[5];
+#define PIXEL03_11    hq4x_Interp1(pOut+BPP3, c[5], c[2]);
+#define PIXEL03_12    hq4x_Interp1(pOut+BPP3, c[5], c[6]);
+#define PIXEL03_20    hq4x_Interp2(pOut+BPP3, c[5], c[2], c[6]);
+#define PIXEL03_50    hq4x_Interp5(pOut+BPP3, c[2], c[6]);
+#define PIXEL03_80    hq4x_Interp8(pOut+BPP3, c[5], c[3]);
+#define PIXEL03_81    hq4x_Interp8(pOut+BPP3, c[5], c[2]);
+#define PIXEL03_82    hq4x_Interp8(pOut+BPP3, c[5], c[6]);
+#define PIXEL10_0     *((int*)(pOut+BpL)) = c[5];
+#define PIXEL10_10    hq4x_Interp1(pOut+BpL, c[5], c[1]);
+#define PIXEL10_11    hq4x_Interp1(pOut+BpL, c[5], c[4]);
+#define PIXEL10_13    hq4x_Interp1(pOut+BpL, c[4], c[5]);
+#define PIXEL10_21    hq4x_Interp2(pOut+BpL, c[4], c[5], c[2]);
+#define PIXEL10_32    hq4x_Interp3(pOut+BpL, c[5], c[2]);
+#define PIXEL10_50    hq4x_Interp5(pOut+BpL, c[4], c[5]);
+#define PIXEL10_60    hq4x_Interp6(pOut+BpL, c[5], c[4], c[2]);
+#define PIXEL10_61    hq4x_Interp6(pOut+BpL, c[5], c[4], c[1]);
+#define PIXEL10_81    hq4x_Interp8(pOut+BpL, c[5], c[4]);
+#define PIXEL10_83    hq4x_Interp8(pOut+BpL, c[4], c[2]);
+#define PIXEL11_0     *((int*)(pOut+BpL+BPP)) = c[5];
+#define PIXEL11_30    hq4x_Interp3(pOut+BpL+BPP, c[5], c[1]);
+#define PIXEL11_31    hq4x_Interp3(pOut+BpL+BPP, c[5], c[4]);
+#define PIXEL11_32    hq4x_Interp3(pOut+BpL+BPP, c[5], c[2]);
+#define PIXEL11_70    hq4x_Interp7(pOut+BpL+BPP, c[5], c[4], c[2]);
+#define PIXEL12_0     *((int*)(pOut+BpL+BPP2)) = c[5];
+#define PIXEL12_30    hq4x_Interp3(pOut+BpL+BPP2, c[5], c[3]);
+#define PIXEL12_31    hq4x_Interp3(pOut+BpL+BPP2, c[5], c[2]);
+#define PIXEL12_32    hq4x_Interp3(pOut+BpL+BPP2, c[5], c[6]);
+#define PIXEL12_70    hq4x_Interp7(pOut+BpL+BPP2, c[5], c[6], c[2]);
+#define PIXEL13_0     *((int*)(pOut+BpL+BPP3)) = c[5];
+#define PIXEL13_10    hq4x_Interp1(pOut+BpL+BPP3, c[5], c[3]);
+#define PIXEL13_12    hq4x_Interp1(pOut+BpL+BPP3, c[5], c[6]);
+#define PIXEL13_14    hq4x_Interp1(pOut+BpL+BPP3, c[6], c[5]);
+#define PIXEL13_21    hq4x_Interp2(pOut+BpL+BPP3, c[6], c[5], c[2]);
+#define PIXEL13_31    hq4x_Interp3(pOut+BpL+BPP3, c[5], c[2]);
+#define PIXEL13_50    hq4x_Interp5(pOut+BpL+BPP3, c[6], c[5]);
+#define PIXEL13_60    hq4x_Interp6(pOut+BpL+BPP3, c[5], c[6], c[2]);
+#define PIXEL13_61    hq4x_Interp6(pOut+BpL+BPP3, c[5], c[6], c[3]);
+#define PIXEL13_82    hq4x_Interp8(pOut+BpL+BPP3, c[5], c[6]);
+#define PIXEL13_83    hq4x_Interp8(pOut+BpL+BPP3, c[6], c[2]);
+#define PIXEL20_0     *((int*)(pOut+BpL+BpL)) = c[5];
+#define PIXEL20_10    hq4x_Interp1(pOut+BpL+BpL, c[5], c[7]);
+#define PIXEL20_12    hq4x_Interp1(pOut+BpL+BpL, c[5], c[4]);
+#define PIXEL20_14    hq4x_Interp1(pOut+BpL+BpL, c[4], c[5]);
+#define PIXEL20_21    hq4x_Interp2(pOut+BpL+BpL, c[4], c[5], c[8]);
+#define PIXEL20_31    hq4x_Interp3(pOut+BpL+BpL, c[5], c[8]);
+#define PIXEL20_50    hq4x_Interp5(pOut+BpL+BpL, c[4], c[5]);
+#define PIXEL20_60    hq4x_Interp6(pOut+BpL+BpL, c[5], c[4], c[8]);
+#define PIXEL20_61    hq4x_Interp6(pOut+BpL+BpL, c[5], c[4], c[7]);
+#define PIXEL20_82    hq4x_Interp8(pOut+BpL+BpL, c[5], c[4]);
+#define PIXEL20_83    hq4x_Interp8(pOut+BpL+BpL, c[4], c[8]);
+#define PIXEL21_0     *((int*)(pOut+BpL+BpL+BPP)) = c[5];
+#define PIXEL21_30    hq4x_Interp3(pOut+BpL+BpL+BPP, c[5], c[7]);
+#define PIXEL21_31    hq4x_Interp3(pOut+BpL+BpL+BPP, c[5], c[8]);
+#define PIXEL21_32    hq4x_Interp3(pOut+BpL+BpL+BPP, c[5], c[4]);
+#define PIXEL21_70    hq4x_Interp7(pOut+BpL+BpL+BPP, c[5], c[4], c[8]);
+#define PIXEL22_0     *((int*)(pOut+BpL+BpL+BPP2)) = c[5];
+#define PIXEL22_30    hq4x_Interp3(pOut+BpL+BpL+BPP2, c[5], c[9]);
+#define PIXEL22_31    hq4x_Interp3(pOut+BpL+BpL+BPP2, c[5], c[6]);
+#define PIXEL22_32    hq4x_Interp3(pOut+BpL+BpL+BPP2, c[5], c[8]);
+#define PIXEL22_70    hq4x_Interp7(pOut+BpL+BpL+BPP2, c[5], c[6], c[8]);
+#define PIXEL23_0     *((int*)(pOut+BpL+BpL+BPP3)) = c[5];
+#define PIXEL23_10    hq4x_Interp1(pOut+BpL+BpL+BPP3, c[5], c[9]);
+#define PIXEL23_11    hq4x_Interp1(pOut+BpL+BpL+BPP3, c[5], c[6]);
+#define PIXEL23_13    hq4x_Interp1(pOut+BpL+BpL+BPP3, c[6], c[5]);
+#define PIXEL23_21    hq4x_Interp2(pOut+BpL+BpL+BPP3, c[6], c[5], c[8]);
+#define PIXEL23_32    hq4x_Interp3(pOut+BpL+BpL+BPP3, c[5], c[8]);
+#define PIXEL23_50    hq4x_Interp5(pOut+BpL+BpL+BPP3, c[6], c[5]);
+#define PIXEL23_60    hq4x_Interp6(pOut+BpL+BpL+BPP3, c[5], c[6], c[8]);
+#define PIXEL23_61    hq4x_Interp6(pOut+BpL+BpL+BPP3, c[5], c[6], c[9]);
+#define PIXEL23_81    hq4x_Interp8(pOut+BpL+BpL+BPP3, c[5], c[6]);
+#define PIXEL23_83    hq4x_Interp8(pOut+BpL+BpL+BPP3, c[6], c[8]);
+#define PIXEL30_0     *((int*)(pOut+BpL+BpL+BpL)) = c[5];
+#define PIXEL30_11    hq4x_Interp1(pOut+BpL+BpL+BpL, c[5], c[8]);
+#define PIXEL30_12    hq4x_Interp1(pOut+BpL+BpL+BpL, c[5], c[4]);
+#define PIXEL30_20    hq4x_Interp2(pOut+BpL+BpL+BpL, c[5], c[8], c[4]);
+#define PIXEL30_50    hq4x_Interp5(pOut+BpL+BpL+BpL, c[8], c[4]);
+#define PIXEL30_80    hq4x_Interp8(pOut+BpL+BpL+BpL, c[5], c[7]);
+#define PIXEL30_81    hq4x_Interp8(pOut+BpL+BpL+BpL, c[5], c[8]);
+#define PIXEL30_82    hq4x_Interp8(pOut+BpL+BpL+BpL, c[5], c[4]);
+#define PIXEL31_0     *((int*)(pOut+BpL+BpL+BpL+BPP)) = c[5];
+#define PIXEL31_10    hq4x_Interp1(pOut+BpL+BpL+BpL+BPP, c[5], c[7]);
+#define PIXEL31_11    hq4x_Interp1(pOut+BpL+BpL+BpL+BPP, c[5], c[8]);
+#define PIXEL31_13    hq4x_Interp1(pOut+BpL+BpL+BpL+BPP, c[8], c[5]);
+#define PIXEL31_21    hq4x_Interp2(pOut+BpL+BpL+BpL+BPP, c[8], c[5], c[4]);
+#define PIXEL31_32    hq4x_Interp3(pOut+BpL+BpL+BpL+BPP, c[5], c[4]);
+#define PIXEL31_50    hq4x_Interp5(pOut+BpL+BpL+BpL+BPP, c[8], c[5]);
+#define PIXEL31_60    hq4x_Interp6(pOut+BpL+BpL+BpL+BPP, c[5], c[8], c[4]);
+#define PIXEL31_61    hq4x_Interp6(pOut+BpL+BpL+BpL+BPP, c[5], c[8], c[7]);
+#define PIXEL31_81    hq4x_Interp8(pOut+BpL+BpL+BpL+BPP, c[5], c[8]);
+#define PIXEL31_83    hq4x_Interp8(pOut+BpL+BpL+BpL+BPP, c[8], c[4]);
+#define PIXEL32_0     *((int*)(pOut+BpL+BpL+BpL+BPP2)) = c[5];
+#define PIXEL32_10    hq4x_Interp1(pOut+BpL+BpL+BpL+BPP2, c[5], c[9]);
+#define PIXEL32_12    hq4x_Interp1(pOut+BpL+BpL+BpL+BPP2, c[5], c[8]);
+#define PIXEL32_14    hq4x_Interp1(pOut+BpL+BpL+BpL+BPP2, c[8], c[5]);
+#define PIXEL32_21    hq4x_Interp2(pOut+BpL+BpL+BpL+BPP2, c[8], c[5], c[6]);
+#define PIXEL32_31    hq4x_Interp3(pOut+BpL+BpL+BpL+BPP2, c[5], c[6]);
+#define PIXEL32_50    hq4x_Interp5(pOut+BpL+BpL+BpL+BPP2, c[8], c[5]);
+#define PIXEL32_60    hq4x_Interp6(pOut+BpL+BpL+BpL+BPP2, c[5], c[8], c[6]);
+#define PIXEL32_61    hq4x_Interp6(pOut+BpL+BpL+BpL+BPP2, c[5], c[8], c[9]);
+#define PIXEL32_82    hq4x_Interp8(pOut+BpL+BpL+BpL+BPP2, c[5], c[8]);
+#define PIXEL32_83    hq4x_Interp8(pOut+BpL+BpL+BpL+BPP2, c[8], c[6]);
+#define PIXEL33_0     *((int*)(pOut+BpL+BpL+BpL+BPP3)) = c[5];
+#define PIXEL33_11    hq4x_Interp1(pOut+BpL+BpL+BpL+BPP3, c[5], c[6]);
+#define PIXEL33_12    hq4x_Interp1(pOut+BpL+BpL+BpL+BPP3, c[5], c[8]);
+#define PIXEL33_20    hq4x_Interp2(pOut+BpL+BpL+BpL+BPP3, c[5], c[8], c[6]);
+#define PIXEL33_50    hq4x_Interp5(pOut+BpL+BpL+BpL+BPP3, c[8], c[6]);
+#define PIXEL33_80    hq4x_Interp8(pOut+BpL+BpL+BpL+BPP3, c[5], c[9]);
+#define PIXEL33_81    hq4x_Interp8(pOut+BpL+BpL+BpL+BPP3, c[5], c[6]);
+#define PIXEL33_82    hq4x_Interp8(pOut+BpL+BpL+BpL+BPP3, c[5], c[8]);
+
+#define HQ4X_DIFF(n, b) \
+static int Diff_##n (uint##b w1, uint##b w2) \
+{ \
+  int YUV1, YUV2; \
+  YUV1 = RGB##n##toYUV(w1); \
+  YUV2 = RGB##n##toYUV(w2); \
+  return ( ( abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY ) || \
+           ( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) || \
+           ( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) ); \
+}
+
+HQ4X_DIFF(888, 32)
+
+#if !_16BPP_HACK
+HQ4X_DIFF(444, 16)
+HQ4X_DIFF(555, 16)
+HQ4X_DIFF(565, 16)
+
+void hq4x_4444(unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL)
+{
+#define hq4x_Interp1 hq4x_Interp1_4444
+#define hq4x_Interp2 hq4x_Interp2_4444
+#define hq4x_Interp3 hq4x_Interp3_4444
+#define hq4x_Interp4 hq4x_Interp4_4444
+#define hq4x_Interp5 hq4x_Interp5_4444
+#define hq4x_Interp6 hq4x_Interp6_4444
+#define hq4x_Interp7 hq4x_Interp7_4444
+#define hq4x_Interp8 hq4x_Interp8_4444
+#define Diff Diff_444
+#define BPP   2
+#define BPP2  4
+#define BPP3  6
+
+  int  i, j, k;
+  int  prevline, nextline;
+  uint16  w[10];
+  uint16  c[10];
+
+  int pattern;
+  int flag;
+
+  int YUV1, YUV2;
+
+  //   +----+----+----+
+  //   |    |    |    |
+  //   | w1 | w2 | w3 |
+  //   +----+----+----+
+  //   |    |    |    |
+  //   | w4 | w5 | w6 |
+  //   +----+----+----+
+  //   |    |    |    |
+  //   | w7 | w8 | w9 |
+  //   +----+----+----+
+
+  for (j = 0; j < Yres; j++) {
+    if (j>0)      prevline = -SrcPPL*2; else prevline = 0;
+    if (j<Yres-1) nextline =  SrcPPL*2; else nextline = 0;
+
+    for (i=0; i<Xres; i++) {
+      w[2] = *((uint16*)(pIn + prevline));
+      w[5] = *((uint16*)pIn);
+      w[8] = *((uint16*)(pIn + nextline));
+
+      if (i>0) {
+        w[1] = *((uint16*)(pIn + prevline - 2));
+        w[4] = *((uint16*)(pIn - 2));
+        w[7] = *((uint16*)(pIn + nextline - 2));
+      } else {
+        w[1] = w[2];
+        w[4] = w[5];
+        w[7] = w[8];
+      }
+
+      if (i<Xres-1) {
+        w[3] = *((uint16*)(pIn + prevline + 2));
+        w[6] = *((uint16*)(pIn + 2));
+        w[9] = *((uint16*)(pIn + nextline + 2));
+      }   else {
+        w[3] = w[2];
+        w[6] = w[5];
+        w[9] = w[8];
+      }
+
+      pattern = 0;
+      flag = 1;
+
+      YUV1 = RGB444toYUV(w[5]);
+
+      for (k=1; k<=9; k++) {
+        if (k==5) continue;
+
+        if ( w[k] != w[5] ) {
+          YUV2 = RGB444toYUV(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] = w[k];
+
+#include "TextureFilters_hq4x.h"
+
+      pIn+=2;
+      pOut+=8;
+    }
+    pIn += 2*(SrcPPL-Xres);
+    pOut+= 8*(SrcPPL-Xres);
+    pOut+=BpL;
+    pOut+=BpL;
+    pOut+=BpL;
+  }
+
+#undef BPP
+#undef BPP2
+#undef BPP3
+#undef Diff
+#undef hq4x_Interp1
+#undef hq4x_Interp2
+#undef hq4x_Interp3
+#undef hq4x_Interp4
+#undef hq4x_Interp5
+#undef hq4x_Interp6
+#undef hq4x_Interp7
+#undef hq4x_Interp8
+}
+
+void hq4x_1555(unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL)
+{
+#define hq4x_Interp1 hq4x_Interp1_1555
+#define hq4x_Interp2 hq4x_Interp2_1555
+#define hq4x_Interp3 hq4x_Interp3_1555
+#define hq4x_Interp4 hq4x_Interp4_1555
+#define hq4x_Interp5 hq4x_Interp5_1555
+#define hq4x_Interp6 hq4x_Interp6_1555
+#define hq4x_Interp7 hq4x_Interp7_1555
+#define hq4x_Interp8 hq4x_Interp8_1555
+#define Diff Diff_555
+#define BPP   2
+#define BPP2  4
+#define BPP3  6
+
+  int  i, j, k;
+  int  prevline, nextline;
+  uint16  w[10];
+  uint16  c[10];
+
+  int pattern;
+  int flag;
+
+  int YUV1, YUV2;
+
+  //   +----+----+----+
+  //   |    |    |    |
+  //   | w1 | w2 | w3 |
+  //   +----+----+----+
+  //   |    |    |    |
+  //   | w4 | w5 | w6 |
+  //   +----+----+----+
+  //   |    |    |    |
+  //   | w7 | w8 | w9 |
+  //   +----+----+----+
+
+  for (j = 0; j < Yres; j++) {
+    if (j>0)      prevline = -SrcPPL*2; else prevline = 0;
+    if (j<Yres-1) nextline =  SrcPPL*2; else nextline = 0;
+
+    for (i=0; i<Xres; i++) {
+      w[2] = *((uint16*)(pIn + prevline));
+      w[5] = *((uint16*)pIn);
+      w[8] = *((uint16*)(pIn + nextline));
+
+      if (i>0) {
+        w[1] = *((uint16*)(pIn + prevline - 2));
+        w[4] = *((uint16*)(pIn - 2));
+        w[7] = *((uint16*)(pIn + nextline - 2));
+      } else {
+        w[1] = w[2];
+        w[4] = w[5];
+        w[7] = w[8];
+      }
+
+      if (i<Xres-1) {
+        w[3] = *((uint16*)(pIn + prevline + 2));
+        w[6] = *((uint16*)(pIn + 2));
+        w[9] = *((uint16*)(pIn + nextline + 2));
+      }   else {
+        w[3] = w[2];
+        w[6] = w[5];
+        w[9] = w[8];
+      }
+
+      pattern = 0;
+      flag = 1;
+
+      YUV1 = RGB555toYUV(w[5]);
+
+      for (k=1; k<=9; k++) {
+        if (k==5) continue;
+
+        if ( w[k] != w[5] ) {
+          YUV2 = RGB555toYUV(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] = w[k];
+
+#include "TextureFilters_hq4x.h"
+
+      pIn+=2;
+      pOut+=8;
+    }
+    pIn += 2*(SrcPPL-Xres);
+    pOut+= 8*(SrcPPL-Xres);
+    pOut+=BpL;
+    pOut+=BpL;
+    pOut+=BpL;
+  }
+
+#undef BPP
+#undef BPP2
+#undef BPP3
+#undef Diff
+#undef hq4x_Interp1
+#undef hq4x_Interp2
+#undef hq4x_Interp3
+#undef hq4x_Interp4
+#undef hq4x_Interp5
+#undef hq4x_Interp6
+#undef hq4x_Interp7
+#undef hq4x_Interp8
+}
+
+void hq4x_565(unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL)
+{
+#define hq4x_Interp1 hq4x_Interp1_565
+#define hq4x_Interp2 hq4x_Interp2_565
+#define hq4x_Interp3 hq4x_Interp3_565
+#define hq4x_Interp4 hq4x_Interp4_565
+#define hq4x_Interp5 hq4x_Interp5_565
+#define hq4x_Interp6 hq4x_Interp6_565
+#define hq4x_Interp7 hq4x_Interp7_565
+#define hq4x_Interp8 hq4x_Interp8_565
+#define Diff Diff_565
+#define BPP   2
+#define BPP2  4
+#define BPP3  6
+
+  int  i, j, k;
+  int  prevline, nextline;
+  uint16  w[10];
+  uint16  c[10];
+
+  int pattern;
+  int flag;
+
+  int YUV1, YUV2;
+
+  //   +----+----+----+
+  //   |    |    |    |
+  //   | w1 | w2 | w3 |
+  //   +----+----+----+
+  //   |    |    |    |
+  //   | w4 | w5 | w6 |
+  //   +----+----+----+
+  //   |    |    |    |
+  //   | w7 | w8 | w9 |
+  //   +----+----+----+
+
+  for (j = 0; j < Yres; j++) {
+    if (j>0)      prevline = -SrcPPL*2; else prevline = 0;
+    if (j<Yres-1) nextline =  SrcPPL*2; else nextline = 0;
+
+    for (i=0; i<Xres; i++) {
+      w[2] = *((uint16*)(pIn + prevline));
+      w[5] = *((uint16*)pIn);
+      w[8] = *((uint16*)(pIn + nextline));
+
+      if (i>0) {
+        w[1] = *((uint16*)(pIn + prevline - 2));
+        w[4] = *((uint16*)(pIn - 2));
+        w[7] = *((uint16*)(pIn + nextline - 2));
+      } else {
+        w[1] = w[2];
+        w[4] = w[5];
+        w[7] = w[8];
+      }
+
+      if (i<Xres-1) {
+        w[3] = *((uint16*)(pIn + prevline + 2));
+        w[6] = *((uint16*)(pIn + 2));
+        w[9] = *((uint16*)(pIn + nextline + 2));
+      } else {
+        w[3] = w[2];
+        w[6] = w[5];
+        w[9] = w[8];
+      }
+
+      pattern = 0;
+      flag = 1;
+
+      YUV1 = RGB565toYUV(w[5]);
+
+      for (k=1; k<=9; k++) {
+        if (k==5) continue;
+
+        if ( w[k] != w[5] ) {
+          YUV2 = RGB565toYUV(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] = w[k];
+
+#include "TextureFilters_hq4x.h"
+
+      pIn+=2;
+      pOut+=8;
+    }
+    pIn += 2*(SrcPPL-Xres);
+    pOut+= 8*(SrcPPL-Xres);
+    pOut+=BpL;
+    pOut+=BpL;
+    pOut+=BpL;
+  }
+
+#undef BPP
+#undef BPP2
+#undef BPP3
+#undef Diff
+#undef hq4x_Interp1
+#undef hq4x_Interp2
+#undef hq4x_Interp3
+#undef hq4x_Interp4
+#undef hq4x_Interp5
+#undef hq4x_Interp6
+#undef hq4x_Interp7
+#undef hq4x_Interp8
+}
+#endif /* !_16BPP_HACK */
+
+void hq4x_8888(unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int SrcPPL, int BpL)
+{
+#define hq4x_Interp1 hq4x_Interp1_8888
+#define hq4x_Interp2 hq4x_Interp2_8888
+#define hq4x_Interp3 hq4x_Interp3_8888
+#define hq4x_Interp4 hq4x_Interp4_8888
+#define hq4x_Interp5 hq4x_Interp5_8888
+#define hq4x_Interp6 hq4x_Interp6_8888
+#define hq4x_Interp7 hq4x_Interp7_8888
+#define hq4x_Interp8 hq4x_Interp8_8888
+#define Diff Diff_888
+#define BPP  4
+#define BPP2 8
+#define BPP3 12
+
+  int  i, j, k;
+  int  prevline, nextline;
+  uint32  w[10];
+  uint32  c[10];
+
+  int pattern;
+  int flag;
+
+  int YUV1, YUV2;
+
+  //   +----+----+----+
+  //   |    |    |    |
+  //   | w1 | w2 | w3 |
+  //   +----+----+----+
+  //   |    |    |    |
+  //   | w4 | w5 | w6 |
+  //   +----+----+----+
+  //   |    |    |    |
+  //   | w7 | w8 | w9 |
+  //   +----+----+----+
+
+  for (j = 0; j < Yres; j++) {
+    if (j>0)      prevline = -SrcPPL*4; else prevline = 0;
+    if (j<Yres-1) nextline =  SrcPPL*4; else nextline = 0;
+
+    for (i=0; i<Xres; i++) {
+      w[2] = *((uint32*)(pIn + prevline));
+      w[5] = *((uint32*)pIn);
+      w[8] = *((uint32*)(pIn + nextline));
+
+      if (i>0) {
+        w[1] = *((uint32*)(pIn + prevline - 4));
+        w[4] = *((uint32*)(pIn - 4));
+        w[7] = *((uint32*)(pIn + nextline - 4));
+      } else {
+        w[1] = w[2];
+        w[4] = w[5];
+        w[7] = w[8];
+      }
+
+      if (i<Xres-1) {
+        w[3] = *((uint32*)(pIn + prevline + 4));
+        w[6] = *((uint32*)(pIn + 4));
+        w[9] = *((uint32*)(pIn + nextline + 4));
+      } else {
+        w[3] = w[2];
+        w[6] = w[5];
+        w[9] = w[8];
+      }
+
+      pattern = 0;
+      flag = 1;
+
+      YUV1 = RGB888toYUV(w[5]);
+
+      for (k=1; k<=9; k++) {
+        if (k==5) continue;
+
+        if ( w[k] != w[5] ) {
+          YUV2 = RGB888toYUV(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] = w[k];
+
+#include "TextureFilters_hq4x.h"
+
+      pIn+=4;
+      pOut+=16;
+    }
+
+    pIn += 4*(SrcPPL-Xres);
+    pOut+= 16*(SrcPPL-Xres);
+    pOut+=BpL;
+    pOut+=BpL;
+    pOut+=BpL;
+  }
+
+#undef BPP
+#undef BPP2
+#undef BPP3
+#undef Diff
+#undef hq4x_Interp1
+#undef hq4x_Interp2
+#undef hq4x_Interp3
+#undef hq4x_Interp4
+#undef hq4x_Interp5
+#undef hq4x_Interp6
+#undef hq4x_Interp7
+#undef hq4x_Interp8
+}
+
+#if !_16BPP_HACK
+void hq4x_init(void)
+{
+  static int done = 0;
+  int r, g, b, Y, u, v, i, j, k;
+
+  if (done ) return;
+
+  for (i = 0; i < 16; i++) {
+    for (j = 0; j < 16; j++) {
+      for (k = 0; k < 16; k++) {
+        r = (i << 4) | i;
+        g = (j << 4) | j;
+        b = (k << 4) | k;
+
+        /* Microsoft's RGB888->YUV conversion */
+        /*Y = (((  66 * r + 129 * g +  25 * b + 128) >> 8) + 16) & 0xFF;
+        u = ((( -38 * r -  74 * g + 112 * b + 128) >> 8) + 128) & 0xFF;
+        v = ((( 112 * r -  94 * g -  18 * b + 128) >> 8) + 128) & 0xFF;*/
+
+        Y = (r + g + b) >> 2;
+        u = 128 + ((r - b) >> 2);
+        v = 128 + ((-r + 2*g -b)>>3);
+
+        RGB444toYUV[(i << 8) | (j << 4) | k] = (Y << 16) | (u << 8) | v;
+      }
+    }
+  }
+
+  done = 1;
+}
+#endif /* !_16BPP_HACK */
diff --git a/source/gles2glide64/src/GlideHQ/TextureFilters_hq4x.h b/source/gles2glide64/src/GlideHQ/TextureFilters_hq4x.h
new file mode 100644 (file)
index 0000000..a3a2740
--- /dev/null
@@ -0,0 +1,4999 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*  Based on Maxim Stepin and Rice1964 hq4x code */
+
+      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;
+        }
+      }
diff --git a/source/gles2glide64/src/GlideHQ/TextureFilters_lq2x.h b/source/gles2glide64/src/GlideHQ/TextureFilters_lq2x.h
new file mode 100644 (file)
index 0000000..b5318ab
--- /dev/null
@@ -0,0 +1,1307 @@
+/*
+Copyright (C) 2003 Rice1964
+
+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.
+
+*/
+
+/* Copyright (C) 2007 Hiroshi Morii <koolsmoky(at)users.sourceforge.net>
+ * Modified for the Texture Filtering library
+ */
+
+case 0 : 
+case 2 : 
+case 4 : 
+case 6 : 
+case 8 : 
+case 12 : 
+case 16 : 
+case 20 : 
+case 24 : 
+case 28 : 
+case 32 : 
+case 34 : 
+case 36 : 
+case 38 : 
+case 40 : 
+case 44 : 
+case 48 : 
+case 52 : 
+case 56 : 
+case 60 : 
+case 64 : 
+case 66 : 
+case 68 : 
+case 70 : 
+case 96 : 
+case 98 : 
+case 100 : 
+case 102 : 
+case 128 : 
+case 130 : 
+case 132 : 
+case 134 : 
+case 136 : 
+case 140 : 
+case 144 : 
+case 148 : 
+case 152 : 
+case 156 : 
+case 160 : 
+case 162 : 
+case 164 : 
+case 166 : 
+case 168 : 
+case 172 : 
+case 176 : 
+case 180 : 
+case 184 : 
+case 188 : 
+case 192 : 
+case 194 : 
+case 196 : 
+case 198 : 
+case 224 : 
+case 226 : 
+case 228 : 
+case 230 : 
+{
+  P0 = IC(0);
+  P1 = IC(0);
+  P2 = IC(0);
+  P3 = IC(0);
+} break;
+case 1 : 
+case 5 : 
+case 9 : 
+case 13 : 
+case 17 : 
+case 21 : 
+case 25 : 
+case 29 : 
+case 33 : 
+case 37 : 
+case 41 : 
+case 45 : 
+case 49 : 
+case 53 : 
+case 57 : 
+case 61 : 
+case 65 : 
+case 69 : 
+case 97 : 
+case 101 : 
+case 129 : 
+case 133 : 
+case 137 : 
+case 141 : 
+case 145 : 
+case 149 : 
+case 153 : 
+case 157 : 
+case 161 : 
+case 165 : 
+case 169 : 
+case 173 : 
+case 177 : 
+case 181 : 
+case 185 : 
+case 189 : 
+case 193 : 
+case 197 : 
+case 225 : 
+case 229 : 
+{
+  P0 = IC(1);
+  P1 = IC(1);
+  P2 = IC(1);
+  P3 = IC(1);
+} break;
+case 3 : 
+case 35 : 
+case 67 : 
+case 99 : 
+case 131 : 
+case 163 : 
+case 195 : 
+case 227 : 
+{
+  P0 = IC(2);
+  P1 = IC(2);
+  P2 = IC(2);
+  P3 = IC(2);
+} break;
+case 7 : 
+case 39 : 
+case 71 : 
+case 103 : 
+case 135 : 
+case 167 : 
+case 199 : 
+case 231 : 
+{
+  P0 = IC(3);
+  P1 = IC(3);
+  P2 = IC(3);
+  P3 = IC(3);
+} break;
+case 10 : 
+case 138 : 
+{
+  P1 = IC(0);
+  P2 = IC(0);
+  P3 = IC(0);
+  if (HQ2X_MUL) {
+    P0 = IC(0);
+  } else {
+    P0 = I211(0, 1, 3);
+  }
+} break;
+case 11 : 
+case 27 : 
+case 75 : 
+case 139 : 
+case 155 : 
+case 203 : 
+{
+  P1 = IC(2);
+  P2 = IC(2);
+  P3 = IC(2);
+  if (HQ2X_MUL) {
+    P0 = IC(2);
+  } else {
+    P0 = I211(2, 1, 3);
+  }
+} break;
+case 14 : 
+case 142 : 
+{
+  P2 = IC(0);
+  P3 = IC(0);
+  if (HQ2X_MUL) {
+    P0 = IC(0);
+    P1 = IC(0);
+  } else {
+    P0 = I332(1, 3, 0);
+    P1 = I31(0, 1);
+  }
+} break;
+case 15 : 
+case 143 : 
+case 207 : 
+{
+  P2 = IC(4);
+  P3 = IC(4);
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+    P1 = IC(4);
+  } else {
+    P0 = I332(1, 3, 4);
+    P1 = I31(4, 1);
+  }
+} break;
+case 18 : 
+case 22 : 
+case 30 : 
+case 50 : 
+case 54 : 
+case 62 : 
+case 86 : 
+case 118 : 
+{
+  P0 = IC(0);
+  P2 = IC(0);
+  P3 = IC(0);
+  if (HQ2X_MUR) {
+    P1 = IC(0);
+  } else {
+    P1 = I211(0, 1, 5);
+  }
+} break;
+case 19 : 
+case 51 : 
+{
+  P2 = IC(2);
+  P3 = IC(2);
+  if (HQ2X_MUR) {
+    P0 = IC(2);
+    P1 = IC(2);
+  } else {
+    P0 = I31(2, 1);
+    P1 = I332(1, 5, 2);
+  }
+} break;
+case 23 : 
+case 55 : 
+case 119 : 
+{
+  P2 = IC(3);
+  P3 = IC(3);
+  if (HQ2X_MUR) {
+    P0 = IC(3);
+    P1 = IC(3);
+  } else {
+    P0 = I31(3, 1);
+    P1 = I332(1, 5, 3);
+  }
+} break;
+case 26 : 
+{
+  P2 = IC(0);
+  P3 = IC(0);
+  if (HQ2X_MUL) {
+    P0 = IC(0);
+  } else {
+    P0 = I211(0, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(0);
+  } else {
+    P1 = I211(0, 1, 5);
+  }
+} break;
+case 31 : 
+case 95 : 
+{
+  P2 = IC(4);
+  P3 = IC(4);
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I211(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I211(4, 1, 5);
+  }
+} break;
+case 42 : 
+case 170 : 
+{
+  P1 = IC(0);
+  P3 = IC(0);
+  if (HQ2X_MUL) {
+    P0 = IC(0);
+    P2 = IC(0);
+  } else {
+    P0 = I332(1, 3, 0);
+    P2 = I31(0, 3);
+  }
+} break;
+case 43 : 
+case 171 : 
+case 187 : 
+{
+  P1 = IC(2);
+  P3 = IC(2);
+  if (HQ2X_MUL) {
+    P0 = IC(2);
+    P2 = IC(2);
+  } else {
+    P0 = I332(1, 3, 2);
+    P2 = I31(2, 3);
+  }
+} break;
+case 46 : 
+case 174 : 
+{
+  P1 = IC(0);
+  P2 = IC(0);
+  P3 = IC(0);
+  if (HQ2X_MUL) {
+    P0 = IC(0);
+  } else {
+    P0 = I611(0, 1, 3);
+  }
+} break;
+case 47 : 
+case 175 : 
+{
+  P1 = IC(4);
+  P2 = IC(4);
+  P3 = IC(4);
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I1411(4, 1, 3);
+  }
+} break;
+case 58 : 
+case 154 : 
+case 186 : 
+{
+  P2 = IC(0);
+  P3 = IC(0);
+  if (HQ2X_MUL) {
+    P0 = IC(0);
+  } else {
+    P0 = I611(0, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(0);
+  } else {
+    P1 = I611(0, 1, 5);
+  }
+} break;
+case 59 : 
+{
+  P2 = IC(2);
+  P3 = IC(2);
+  if (HQ2X_MUL) {
+    P0 = IC(2);
+  } else {
+    P0 = I211(2, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(2);
+  } else {
+    P1 = I611(2, 1, 5);
+  }
+} break;
+case 63 : 
+{
+  P2 = IC(4);
+  P3 = IC(4);
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I1411(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I211(4, 1, 5);
+  }
+} break;
+case 72 : 
+case 76 : 
+case 104 : 
+case 106 : 
+case 108 : 
+case 110 : 
+case 120 : 
+case 124 : 
+{
+  P0 = IC(0);
+  P1 = IC(0);
+  P3 = IC(0);
+  if (HQ2X_MDL) {
+    P2 = IC(0);
+  } else {
+    P2 = I211(0, 3, 7);
+  }
+} break;
+case 73 : 
+case 77 : 
+case 105 : 
+case 109 : 
+case 125 : 
+{
+  P1 = IC(1);
+  P3 = IC(1);
+  if (HQ2X_MDL) {
+    P0 = IC(1);
+    P2 = IC(1);
+  } else {
+    P0 = I31(1, 3);
+    P2 = I332(3, 7, 1);
+  }
+} break;
+case 74 : 
+{
+  P1 = IC(0);
+  P3 = IC(0);
+  if (HQ2X_MDL) {
+    P2 = IC(0);
+  } else {
+    P2 = I211(0, 3, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(0);
+  } else {
+    P0 = I211(0, 1, 3);
+  }
+} break;
+case 78 : 
+case 202 : 
+case 206 : 
+{
+  P1 = IC(0);
+  P3 = IC(0);
+  if (HQ2X_MDL) {
+    P2 = IC(0);
+  } else {
+    P2 = I611(0, 3, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(0);
+  } else {
+    P0 = I611(0, 1, 3);
+  }
+} break;
+case 79 : 
+{
+  P1 = IC(4);
+  P3 = IC(4);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I611(4, 3, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I211(4, 1, 3);
+  }
+} break;
+case 80 : 
+case 208 : 
+case 210 : 
+case 216 : 
+{
+  P0 = IC(0);
+  P1 = IC(0);
+  P2 = IC(0);
+  if (HQ2X_MDR) {
+    P3 = IC(0);
+  } else {
+    P3 = I211(0, 5, 7);
+  }
+} break;
+case 81 : 
+case 209 : 
+case 217 : 
+{
+  P0 = IC(1);
+  P1 = IC(1);
+  P2 = IC(1);
+  if (HQ2X_MDR) {
+    P3 = IC(1);
+  } else {
+    P3 = I211(1, 5, 7);
+  }
+} break;
+case 82 : 
+case 214 : 
+case 222 : 
+{
+  P0 = IC(0);
+  P2 = IC(0);
+  if (HQ2X_MDR) {
+    P3 = IC(0);
+  } else {
+    P3 = I211(0, 5, 7);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(0);
+  } else {
+    P1 = I211(0, 1, 5);
+  }
+} break;
+case 83 : 
+case 115 : 
+{
+  P0 = IC(2);
+  P2 = IC(2);
+  if (HQ2X_MDR) {
+    P3 = IC(2);
+  } else {
+    P3 = I611(2, 5, 7);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(2);
+  } else {
+    P1 = I611(2, 1, 5);
+  }
+} break;
+case 84 : 
+case 212 : 
+{
+  P0 = IC(0);
+  P2 = IC(0);
+  if (HQ2X_MDR) {
+    P1 = IC(0);
+    P3 = IC(0);
+  } else {
+    P1 = I31(0, 5);
+    P3 = I332(5, 7, 0);
+  }
+} break;
+case 85 : 
+case 213 : 
+case 221 : 
+{
+  P0 = IC(1);
+  P2 = IC(1);
+  if (HQ2X_MDR) {
+    P1 = IC(1);
+    P3 = IC(1);
+  } else {
+    P1 = I31(1, 5);
+    P3 = I332(5, 7, 1);
+  }
+} break;
+case 87 : 
+{
+  P0 = IC(3);
+  P2 = IC(3);
+  if (HQ2X_MDR) {
+    P3 = IC(3);
+  } else {
+    P3 = I611(3, 5, 7);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(3);
+  } else {
+    P1 = I211(3, 1, 5);
+  }
+} break;
+case 88 : 
+case 248 : 
+case 250 : 
+{
+  P0 = IC(0);
+  P1 = IC(0);
+  if (HQ2X_MDL) {
+    P2 = IC(0);
+  } else {
+    P2 = I211(0, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(0);
+  } else {
+    P3 = I211(0, 5, 7);
+  }
+} break;
+case 89 : 
+case 93 : 
+{
+  P0 = IC(1);
+  P1 = IC(1);
+  if (HQ2X_MDL) {
+    P2 = IC(1);
+  } else {
+    P2 = I611(1, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(1);
+  } else {
+    P3 = I611(1, 5, 7);
+  }
+} break;
+case 90 : 
+{
+  if (HQ2X_MDL) {
+    P2 = IC(0);
+  } else {
+    P2 = I611(0, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(0);
+  } else {
+    P3 = I611(0, 5, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(0);
+  } else {
+    P0 = I611(0, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(0);
+  } else {
+    P1 = I611(0, 1, 5);
+  }
+} break;
+case 91 : 
+{
+  if (HQ2X_MDL) {
+    P2 = IC(2);
+  } else {
+    P2 = I611(2, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(2);
+  } else {
+    P3 = I611(2, 5, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(2);
+  } else {
+    P0 = I211(2, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(2);
+  } else {
+    P1 = I611(2, 1, 5);
+  }
+} break;
+case 92 : 
+{
+  P0 = IC(0);
+  P1 = IC(0);
+  if (HQ2X_MDL) {
+    P2 = IC(0);
+  } else {
+    P2 = I611(0, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(0);
+  } else {
+    P3 = I611(0, 5, 7);
+  }
+} break;
+case 94 : 
+{
+  if (HQ2X_MDL) {
+    P2 = IC(0);
+  } else {
+    P2 = I611(0, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(0);
+  } else {
+    P3 = I611(0, 5, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(0);
+  } else {
+    P0 = I611(0, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(0);
+  } else {
+    P1 = I211(0, 1, 5);
+  }
+} break;
+case 107 : 
+case 123 : 
+{
+  P1 = IC(2);
+  P3 = IC(2);
+  if (HQ2X_MDL) {
+    P2 = IC(2);
+  } else {
+    P2 = I211(2, 3, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(2);
+  } else {
+    P0 = I211(2, 1, 3);
+  }
+} break;
+case 111 : 
+{
+  P1 = IC(4);
+  P3 = IC(4);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I211(4, 3, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I1411(4, 1, 3);
+  }
+} break;
+case 112 : 
+case 240 : 
+{
+  P0 = IC(0);
+  P1 = IC(0);
+  if (HQ2X_MDR) {
+    P2 = IC(0);
+    P3 = IC(0);
+  } else {
+    P2 = I31(0, 7);
+    P3 = I332(5, 7, 0);
+  }
+} break;
+case 113 : 
+case 241 : 
+{
+  P0 = IC(1);
+  P1 = IC(1);
+  if (HQ2X_MDR) {
+    P2 = IC(1);
+    P3 = IC(1);
+  } else {
+    P2 = I31(1, 7);
+    P3 = I332(5, 7, 1);
+  }
+} break;
+case 114 : 
+{
+  P0 = IC(0);
+  P2 = IC(0);
+  if (HQ2X_MDR) {
+    P3 = IC(0);
+  } else {
+    P3 = I611(0, 5, 7);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(0);
+  } else {
+    P1 = I611(0, 1, 5);
+  }
+} break;
+case 116 : 
+{
+  P0 = IC(0);
+  P1 = IC(0);
+  P2 = IC(0);
+  if (HQ2X_MDR) {
+    P3 = IC(0);
+  } else {
+    P3 = I611(0, 5, 7);
+  }
+} break;
+case 117 : 
+{
+  P0 = IC(1);
+  P1 = IC(1);
+  P2 = IC(1);
+  if (HQ2X_MDR) {
+    P3 = IC(1);
+  } else {
+    P3 = I611(1, 5, 7);
+  }
+} break;
+case 121 : 
+{
+  P0 = IC(1);
+  P1 = IC(1);
+  if (HQ2X_MDL) {
+    P2 = IC(1);
+  } else {
+    P2 = I211(1, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(1);
+  } else {
+    P3 = I611(1, 5, 7);
+  }
+} break;
+case 122 : 
+{
+  if (HQ2X_MDL) {
+    P2 = IC(0);
+  } else {
+    P2 = I211(0, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(0);
+  } else {
+    P3 = I611(0, 5, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(0);
+  } else {
+    P0 = I611(0, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(0);
+  } else {
+    P1 = I611(0, 1, 5);
+  }
+} break;
+case 126 : 
+{
+  P0 = IC(0);
+  P3 = IC(0);
+  if (HQ2X_MDL) {
+    P2 = IC(0);
+  } else {
+    P2 = I211(0, 3, 7);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(0);
+  } else {
+    P1 = I211(0, 1, 5);
+  }
+} break;
+case 127 : 
+{
+  P3 = IC(4);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I211(4, 3, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I1411(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I211(4, 1, 5);
+  }
+} break;
+case 146 : 
+case 150 : 
+case 178 : 
+case 182 : 
+case 190 : 
+{
+  P0 = IC(0);
+  P2 = IC(0);
+  if (HQ2X_MUR) {
+    P1 = IC(0);
+    P3 = IC(0);
+  } else {
+    P1 = I332(1, 5, 0);
+    P3 = I31(0, 5);
+  }
+} break;
+case 147 : 
+case 179 : 
+{
+  P0 = IC(2);
+  P2 = IC(2);
+  P3 = IC(2);
+  if (HQ2X_MUR) {
+    P1 = IC(2);
+  } else {
+    P1 = I611(2, 1, 5);
+  }
+} break;
+case 151 : 
+case 183 : 
+{
+  P0 = IC(3);
+  P2 = IC(3);
+  P3 = IC(3);
+  if (HQ2X_MUR) {
+    P1 = IC(3);
+  } else {
+    P1 = I1411(3, 1, 5);
+  }
+} break;
+case 158 : 
+{
+  P2 = IC(0);
+  P3 = IC(0);
+  if (HQ2X_MUL) {
+    P0 = IC(0);
+  } else {
+    P0 = I611(0, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(0);
+  } else {
+    P1 = I211(0, 1, 5);
+  }
+} break;
+case 159 : 
+{
+  P2 = IC(4);
+  P3 = IC(4);
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I211(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I1411(4, 1, 5);
+  }
+} break;
+case 191 : 
+{
+  P2 = IC(4);
+  P3 = IC(4);
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I1411(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I1411(4, 1, 5);
+  }
+} break;
+case 200 : 
+case 204 : 
+case 232 : 
+case 236 : 
+case 238 : 
+{
+  P0 = IC(0);
+  P1 = IC(0);
+  if (HQ2X_MDL) {
+    P2 = IC(0);
+    P3 = IC(0);
+  } else {
+    P2 = I332(3, 7, 0);
+    P3 = I31(0, 7);
+  }
+} break;
+case 201 : 
+case 205 : 
+{
+  P0 = IC(1);
+  P1 = IC(1);
+  P3 = IC(1);
+  if (HQ2X_MDL) {
+    P2 = IC(1);
+  } else {
+    P2 = I611(1, 3, 7);
+  }
+} break;
+case 211 : 
+{
+  P0 = IC(2);
+  P1 = IC(2);
+  P2 = IC(2);
+  if (HQ2X_MDR) {
+    P3 = IC(2);
+  } else {
+    P3 = I211(2, 5, 7);
+  }
+} break;
+case 215 : 
+{
+  P0 = IC(3);
+  P2 = IC(3);
+  if (HQ2X_MDR) {
+    P3 = IC(3);
+  } else {
+    P3 = I211(3, 5, 7);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(3);
+  } else {
+    P1 = I1411(3, 1, 5);
+  }
+} break;
+case 218 : 
+{
+  if (HQ2X_MDL) {
+    P2 = IC(0);
+  } else {
+    P2 = I611(0, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(0);
+  } else {
+    P3 = I211(0, 5, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(0);
+  } else {
+    P0 = I611(0, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(0);
+  } else {
+    P1 = I611(0, 1, 5);
+  }
+} break;
+case 219 : 
+{
+  P1 = IC(2);
+  P2 = IC(2);
+  if (HQ2X_MDR) {
+    P3 = IC(2);
+  } else {
+    P3 = I211(2, 5, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(2);
+  } else {
+    P0 = I211(2, 1, 3);
+  }
+} break;
+case 220 : 
+{
+  P0 = IC(0);
+  P1 = IC(0);
+  if (HQ2X_MDL) {
+    P2 = IC(0);
+  } else {
+    P2 = I611(0, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(0);
+  } else {
+    P3 = I211(0, 5, 7);
+  }
+} break;
+case 223 : 
+{
+  P2 = IC(4);
+  if (HQ2X_MDR) {
+    P3 = IC(4);
+  } else {
+    P3 = I211(4, 5, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I211(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I1411(4, 1, 5);
+  }
+} break;
+case 233 : 
+case 237 : 
+{
+  P0 = IC(1);
+  P1 = IC(1);
+  P3 = IC(1);
+  if (HQ2X_MDL) {
+    P2 = IC(1);
+  } else {
+    P2 = I1411(1, 3, 7);
+  }
+} break;
+case 234 : 
+{
+  P1 = IC(0);
+  P3 = IC(0);
+  if (HQ2X_MDL) {
+    P2 = IC(0);
+  } else {
+    P2 = I211(0, 3, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(0);
+  } else {
+    P0 = I611(0, 1, 3);
+  }
+} break;
+case 235 : 
+{
+  P1 = IC(2);
+  P3 = IC(2);
+  if (HQ2X_MDL) {
+    P2 = IC(2);
+  } else {
+    P2 = I1411(2, 3, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(2);
+  } else {
+    P0 = I211(2, 1, 3);
+  }
+} break;
+case 239 : 
+{
+  P1 = IC(4);
+  P3 = IC(4);
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I1411(4, 3, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I1411(4, 1, 3);
+  }
+} break;
+case 242 : 
+{
+  P0 = IC(0);
+  P2 = IC(0);
+  if (HQ2X_MDR) {
+    P3 = IC(0);
+  } else {
+    P3 = I211(0, 5, 7);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(0);
+  } else {
+    P1 = I611(0, 1, 5);
+  }
+} break;
+case 243 : 
+{
+  P0 = IC(2);
+  P1 = IC(2);
+  if (HQ2X_MDR) {
+    P2 = IC(2);
+    P3 = IC(2);
+  } else {
+    P2 = I31(2, 7);
+    P3 = I332(5, 7, 2);
+  }
+} break;
+case 244 : 
+{
+  P0 = IC(0);
+  P1 = IC(0);
+  P2 = IC(0);
+  if (HQ2X_MDR) {
+    P3 = IC(0);
+  } else {
+    P3 = I1411(0, 5, 7);
+  }
+} break;
+case 245 : 
+{
+  P0 = IC(1);
+  P1 = IC(1);
+  P2 = IC(1);
+  if (HQ2X_MDR) {
+    P3 = IC(1);
+  } else {
+    P3 = I1411(1, 5, 7);
+  }
+} break;
+case 246 : 
+{
+  P0 = IC(0);
+  P2 = IC(0);
+  if (HQ2X_MDR) {
+    P3 = IC(0);
+  } else {
+    P3 = I1411(0, 5, 7);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(0);
+  } else {
+    P1 = I211(0, 1, 5);
+  }
+} break;
+case 247 : 
+{
+  P0 = IC(3);
+  P2 = IC(3);
+  if (HQ2X_MDR) {
+    P3 = IC(3);
+  } else {
+    P3 = I1411(3, 5, 7);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(3);
+  } else {
+    P1 = I1411(3, 1, 5);
+  }
+} break;
+case 249 : 
+{
+  P0 = IC(1);
+  P1 = IC(1);
+  if (HQ2X_MDL) {
+    P2 = IC(1);
+  } else {
+    P2 = I1411(1, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(1);
+  } else {
+    P3 = I211(1, 5, 7);
+  }
+} break;
+case 251 : 
+{
+  P1 = IC(2);
+  if (HQ2X_MDL) {
+    P2 = IC(2);
+  } else {
+    P2 = I1411(2, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(2);
+  } else {
+    P3 = I211(2, 5, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(2);
+  } else {
+    P0 = I211(2, 1, 3);
+  }
+} break;
+case 252 : 
+{
+  P0 = IC(0);
+  P1 = IC(0);
+  if (HQ2X_MDL) {
+    P2 = IC(0);
+  } else {
+    P2 = I211(0, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(0);
+  } else {
+    P3 = I1411(0, 5, 7);
+  }
+} break;
+case 253 : 
+{
+  P0 = IC(1);
+  P1 = IC(1);
+  if (HQ2X_MDL) {
+    P2 = IC(1);
+  } else {
+    P2 = I1411(1, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(1);
+  } else {
+    P3 = I1411(1, 5, 7);
+  }
+} break;
+case 254 : 
+{
+  P0 = IC(0);
+  if (HQ2X_MDL) {
+    P2 = IC(0);
+  } else {
+    P2 = I211(0, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(0);
+  } else {
+    P3 = I1411(0, 5, 7);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(0);
+  } else {
+    P1 = I211(0, 1, 5);
+  }
+} break;
+case 255 : 
+{
+  if (HQ2X_MDL) {
+    P2 = IC(4);
+  } else {
+    P2 = I1411(4, 3, 7);
+  }
+  if (HQ2X_MDR) {
+    P3 = IC(4);
+  } else {
+    P3 = I1411(4, 5, 7);
+  }
+  if (HQ2X_MUL) {
+    P0 = IC(4);
+  } else {
+    P0 = I1411(4, 1, 3);
+  }
+  if (HQ2X_MUR) {
+    P1 = IC(4);
+  } else {
+    P1 = I1411(4, 1, 5);
+  }
+} break;
diff --git a/source/gles2glide64/src/GlideHQ/TxCache.cpp b/source/gles2glide64/src/GlideHQ/TxCache.cpp
new file mode 100644 (file)
index 0000000..46960f4
--- /dev/null
@@ -0,0 +1,544 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef __MSC__
+#pragma warning(disable: 4786)
+#endif
+
+#include <boost/filesystem.hpp>
+#include <zlib.h>
+#include "TxCache.h"
+#include "TxDbg.h"
+#include "../Glide64/m64p.h"
+#include "../Glide64/Gfx_1.3.h"
+
+TxCache::~TxCache()
+{
+  /* free memory, clean up, etc */
+  clear();
+
+  delete _txUtil;
+}
+
+TxCache::TxCache(int options, int cachesize, const wchar_t *datapath,
+                 const wchar_t *cachepath, const wchar_t *ident,
+                 dispInfoFuncExt callback)
+{
+  _txUtil = new TxUtil();
+
+  _options = options;
+  _cacheSize = cachesize;
+  _callback = callback;
+  _totalSize = 0;
+
+  /* save path name */
+  if (datapath)
+    _datapath.assign(datapath);
+  if (cachepath)
+    _cachepath.assign(cachepath);
+
+  /* save ROM name */
+  if (ident)
+    _ident.assign(ident);
+
+  /* zlib memory buffers to (de)compress hires textures */
+  if (_options & (GZ_TEXCACHE|GZ_HIRESTEXCACHE)) {
+    _gzdest0   = TxMemBuf::getInstance()->get(0);
+    _gzdest1   = TxMemBuf::getInstance()->get(1);
+    _gzdestLen = (TxMemBuf::getInstance()->size_of(0) < TxMemBuf::getInstance()->size_of(1)) ?
+                  TxMemBuf::getInstance()->size_of(0) : TxMemBuf::getInstance()->size_of(1);
+
+    if (!_gzdest0 || !_gzdest1 || !_gzdestLen) {
+      _options &= ~(GZ_TEXCACHE|GZ_HIRESTEXCACHE);
+      _gzdest0 = NULL;
+      _gzdest1 = NULL;
+      _gzdestLen = 0;
+    }
+  }
+}
+
+boolean
+TxCache::add(uint64 checksum, GHQTexInfo *info, int dataSize)
+{
+  /* NOTE: dataSize must be provided if info->data is zlib compressed. */
+
+  if (!checksum || !info->data) return 0;
+
+  uint8 *dest = info->data;
+  uint16 format = info->format;
+
+  if (!dataSize) {
+    dataSize = _txUtil->sizeofTx(info->width, info->height, info->format);
+
+    if (!dataSize) return 0;
+
+    if (_options & (GZ_TEXCACHE|GZ_HIRESTEXCACHE)) {
+      /* zlib compress it. compression level:1 (best speed) */
+      uLongf destLen = _gzdestLen;
+      dest = (dest == _gzdest0) ? _gzdest1 : _gzdest0;
+      if (compress2(dest, &destLen, info->data, dataSize, 1) != Z_OK) {
+        dest = info->data;
+        DBG_INFO(80, L"Error: zlib compression failed!\n");
+      } else {
+        DBG_INFO(80, L"zlib compressed: %.02fkb->%.02fkb\n", (float)dataSize/1000, (float)destLen/1000);
+        dataSize = destLen;
+        format |= GR_TEXFMT_GZ;
+      }
+    }
+  }
+
+  /* if cache size exceeds limit, remove old cache */
+  if (_cacheSize > 0) {
+    _totalSize += dataSize;
+    if ((_totalSize > _cacheSize) && !_cachelist.empty()) {
+      /* _cachelist is arranged so that frequently used textures are in the back */
+      std::list<uint64>::iterator itList = _cachelist.begin();
+      while (itList != _cachelist.end()) {
+        /* find it in _cache */
+        std::map<uint64, TXCACHE*>::iterator itMap = _cache.find(*itList);
+        if (itMap != _cache.end()) {
+          /* yep we have it. remove it. */
+          _totalSize -= (*itMap).second->size;
+          free((*itMap).second->info.data);
+          delete (*itMap).second;
+          _cache.erase(itMap);
+        }
+        itList++;
+
+        /* check if memory cache has enough space */
+        if (_totalSize <= _cacheSize)
+          break;
+      }
+      /* remove from _cachelist */
+      _cachelist.erase(_cachelist.begin(), itList);
+
+      DBG_INFO(80, L"+++++++++\n");
+    }
+    _totalSize -= dataSize;
+  }
+
+  /* cache it */
+  uint8 *tmpdata = (uint8*)malloc(dataSize);
+  if (tmpdata) {
+    TXCACHE *txCache = new TXCACHE;
+    if (txCache) {
+      /* we can directly write as we filter, but for now we get away
+       * with doing memcpy after all the filtering is done.
+       */
+      memcpy(tmpdata, dest, dataSize);
+
+      /* copy it */
+      memcpy(&txCache->info, info, sizeof(GHQTexInfo));
+      txCache->info.data = tmpdata;
+      txCache->info.format = format;
+      txCache->size = dataSize;
+
+      /* add to cache */
+      if (_cacheSize > 0) {
+        _cachelist.push_back(checksum);
+        txCache->it = --(_cachelist.end());
+      }
+      /* _cache[checksum] = txCache; */
+      _cache.insert(std::map<uint64, TXCACHE*>::value_type(checksum, txCache));
+
+#ifdef DEBUG
+      DBG_INFO(80, L"[%5d] added!! crc:%08X %08X %d x %d gfmt:%x total:%.02fmb\n",
+               _cache.size(), (uint32)(checksum >> 32), (uint32)(checksum & 0xffffffff),
+               info->width, info->height, info->format, (float)_totalSize/1000000);
+
+      DBG_INFO(80, L"smalllodlog2:%d largelodlog2:%d aspectratiolog2:%d\n",
+               txCache->info.smallLodLog2, txCache->info.largeLodLog2, txCache->info.aspectRatioLog2);
+
+      if (info->tiles) {
+        DBG_INFO(80, L"tiles:%d un-tiled size:%d x %d\n", info->tiles, info->untiled_width, info->untiled_height);
+      }
+
+      if (_cacheSize > 0) {
+        DBG_INFO(80, L"cache max config:%.02fmb\n", (float)_cacheSize/1000000);
+
+        if (_cache.size() != _cachelist.size()) {
+          DBG_INFO(80, L"Error: cache/cachelist mismatch! (%d/%d)\n", _cache.size(), _cachelist.size());
+        }
+      }
+#endif
+
+      /* total cache size */
+      _totalSize += dataSize;
+
+      return 1;
+    }
+    free(tmpdata);
+  }
+
+  return 0;
+}
+
+boolean
+TxCache::get(uint64 checksum, GHQTexInfo *info)
+{
+  if (!checksum || _cache.empty()) return 0;
+
+  /* find a match in cache */
+  std::map<uint64, TXCACHE*>::iterator itMap = _cache.find(checksum);
+  if (itMap != _cache.end()) {
+    /* yep, we've got it. */
+    memcpy(info, &(((*itMap).second)->info), sizeof(GHQTexInfo));
+
+    /* push it to the back of the list */
+    if (_cacheSize > 0) {
+      _cachelist.erase(((*itMap).second)->it);
+      _cachelist.push_back(checksum);
+      ((*itMap).second)->it = --(_cachelist.end());
+    }
+
+    /* zlib decompress it */
+    if (info->format & GR_TEXFMT_GZ) {
+      uLongf destLen = _gzdestLen;
+      uint8 *dest = (_gzdest0 == info->data) ? _gzdest1 : _gzdest0;
+      if (uncompress(dest, &destLen, info->data, ((*itMap).second)->size) != Z_OK) {
+        DBG_INFO(80, L"Error: zlib decompression failed!\n");
+        return 0;
+      }
+      info->data = dest;
+      info->format &= ~GR_TEXFMT_GZ;
+      DBG_INFO(80, L"zlib decompressed: %.02fkb->%.02fkb\n", (float)(((*itMap).second)->size)/1000, (float)destLen/1000);
+    }
+
+    return 1;
+  }
+
+  return 0;
+}
+
+boolean
+TxCache::save(const wchar_t *path, const wchar_t *filename, int config)
+{
+  if (!_cache.empty()) {
+    /* dump cache to disk */
+    char cbuf[MAX_PATH];
+
+    boost::filesystem::wpath cachepath(path);
+    boost::filesystem::create_directory(cachepath);
+
+    /* Ugly hack to enable fopen/gzopen in Win9x */
+#ifdef BOOST_WINDOWS_API
+    wchar_t curpath[MAX_PATH];
+    GETCWD(MAX_PATH, curpath);
+    CHDIR(cachepath.wstring().c_str());
+#else
+    char curpath[MAX_PATH];
+    wcstombs(cbuf, cachepath.wstring().c_str(), MAX_PATH);
+    if (GETCWD(MAX_PATH, curpath) == NULL)
+        ERRLOG("Error while retrieving working directory!");
+    if (CHDIR(cbuf) != 0)
+        ERRLOG("Error while changing current directory to '%s'!", cbuf);
+#endif
+
+    wcstombs(cbuf, filename, MAX_PATH);
+
+    gzFile gzfp = gzopen(cbuf, "wb1");
+    DBG_INFO(80, L"gzfp:%x file:%ls\n", gzfp, filename);
+    if (gzfp) {
+      /* write header to determine config match */
+      gzwrite(gzfp, &config, 4);
+
+      std::map<uint64, TXCACHE*>::iterator itMap = _cache.begin();
+      while (itMap != _cache.end()) {
+        uint8 *dest    = (*itMap).second->info.data;
+        uint32 destLen = (*itMap).second->size;
+        uint16 format  = (*itMap).second->info.format;
+
+        /* to keep things simple, we save the texture data in a zlib uncompressed state. */
+        /* sigh... for those who cannot wait the extra few seconds. changed to keep
+         * texture data in a zlib compressed state. if the GZ_TEXCACHE or GZ_HIRESTEXCACHE
+         * option is toggled, the cache will need to be rebuilt.
+         */
+        /*if (format & GR_TEXFMT_GZ) {
+          dest = _gzdest0;
+          destLen = _gzdestLen;
+          if (dest && destLen) {
+            if (uncompress(dest, &destLen, (*itMap).second->info.data, (*itMap).second->size) != Z_OK) {
+              dest = NULL;
+              destLen = 0;
+            }
+            format &= ~GR_TEXFMT_GZ;
+          }
+        }*/
+
+        if (dest && destLen) {
+          /* texture checksum */
+          gzwrite(gzfp, &((*itMap).first), 8);
+
+          /* other texture info */
+          gzwrite(gzfp, &((*itMap).second->info.width), 4);
+          gzwrite(gzfp, &((*itMap).second->info.height), 4);
+          gzwrite(gzfp, &format, 2);
+
+          gzwrite(gzfp, &((*itMap).second->info.smallLodLog2), 4);
+          gzwrite(gzfp, &((*itMap).second->info.largeLodLog2), 4);
+          gzwrite(gzfp, &((*itMap).second->info.aspectRatioLog2), 4);
+
+          gzwrite(gzfp, &((*itMap).second->info.tiles), 4);
+          gzwrite(gzfp, &((*itMap).second->info.untiled_width), 4);
+          gzwrite(gzfp, &((*itMap).second->info.untiled_height), 4);
+
+          gzwrite(gzfp, &((*itMap).second->info.is_hires_tex), 1);
+
+          gzwrite(gzfp, &destLen, 4);
+          gzwrite(gzfp, dest, destLen);
+        }
+
+        itMap++;
+
+        /* not ready yet */
+        /*if (_callback)
+          (*_callback)(L"Total textures saved to HDD: %d\n", std::distance(itMap, _cache.begin()));*/
+      }
+      gzclose(gzfp);
+    }
+
+    if (CHDIR(curpath) != 0)
+        ERRLOG("Error while changing current directory back to original path of '%s'!", curpath);
+  }
+
+  return _cache.empty();
+}
+
+boolean
+TxCache::load(const wchar_t *path, const wchar_t *filename, int config)
+{
+  /* find it on disk */
+  char cbuf[MAX_PATH];
+
+  boost::filesystem::wpath cachepath(path);
+
+#ifdef BOOST_WINDOWS_API
+  wchar_t curpath[MAX_PATH];
+  GETCWD(MAX_PATH, curpath);
+  CHDIR(cachepath.wstring().c_str());
+#else
+  char curpath[MAX_PATH];
+  wcstombs(cbuf, cachepath.wstring().c_str(), MAX_PATH);
+  if (GETCWD(MAX_PATH, curpath) == NULL)
+      ERRLOG("Error while retrieving working directory!");
+  if (CHDIR(cbuf) != 0)
+      ERRLOG("Error while changing current directory to '%s'!", cbuf);
+#endif
+
+  wcstombs(cbuf, filename, MAX_PATH);
+
+  gzFile gzfp = gzopen(cbuf, "rb");
+  DBG_INFO(80, L"gzfp:%x file:%ls\n", gzfp, filename);
+  if (gzfp) {
+    /* yep, we have it. load it into memory cache. */
+    int dataSize;
+    uint64 checksum;
+    GHQTexInfo tmpInfo;
+    int tmpconfig;
+    /* read header to determine config match */
+    gzread(gzfp, &tmpconfig, 4);
+
+    if (tmpconfig == config) {
+      do {
+        memset(&tmpInfo, 0, sizeof(GHQTexInfo));
+
+        gzread(gzfp, &checksum, 8);
+
+        gzread(gzfp, &tmpInfo.width, 4);
+        gzread(gzfp, &tmpInfo.height, 4);
+        gzread(gzfp, &tmpInfo.format, 2);
+
+        gzread(gzfp, &tmpInfo.smallLodLog2, 4);
+        gzread(gzfp, &tmpInfo.largeLodLog2, 4);
+        gzread(gzfp, &tmpInfo.aspectRatioLog2, 4);
+
+        gzread(gzfp, &tmpInfo.tiles, 4);
+        gzread(gzfp, &tmpInfo.untiled_width, 4);
+        gzread(gzfp, &tmpInfo.untiled_height, 4);
+
+        gzread(gzfp, &tmpInfo.is_hires_tex, 1);
+
+        gzread(gzfp, &dataSize, 4);
+
+        tmpInfo.data = (uint8*)malloc(dataSize);
+        if (tmpInfo.data) {
+          gzread(gzfp, tmpInfo.data, dataSize);
+
+          /* add to memory cache */
+          add(checksum, &tmpInfo, (tmpInfo.format & GR_TEXFMT_GZ) ? dataSize : 0);
+
+          free(tmpInfo.data);
+        } else {
+          gzseek(gzfp, dataSize, SEEK_CUR);
+        }
+
+        /* skip in between to prevent the loop from being tied down to vsync */
+        if (_callback && (!(_cache.size() % 100) || gzeof(gzfp)))
+          (*_callback)(L"[%d] total mem:%.02fmb - %ls\n", _cache.size(), (float)_totalSize/1000000, filename);
+
+      } while (!gzeof(gzfp));
+      gzclose(gzfp);
+    } else {
+      if ((tmpconfig & HIRESTEXTURES_MASK) != (config & HIRESTEXTURES_MASK)) {
+        const char *conf_str;
+        if ((tmpconfig & HIRESTEXTURES_MASK) == NO_HIRESTEXTURES)
+          conf_str = "0";
+        else if ((tmpconfig & HIRESTEXTURES_MASK) == RICE_HIRESTEXTURES)
+          conf_str = "1";
+        else
+          conf_str = "set to an unsupported format";
+
+        WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_hirs must be %s", conf_str);
+      }
+      if ((tmpconfig & COMPRESS_HIRESTEX) != (config & COMPRESS_HIRESTEX))
+        WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_hirs_cmpr must be %s", (tmpconfig & COMPRESS_HIRESTEX) ? "True" : "False");
+      if ((tmpconfig & COMPRESSION_MASK) != (config & COMPRESSION_MASK) && (tmpconfig & COMPRESS_HIRESTEX)) {
+        const char *conf_str;
+        if ((tmpconfig & COMPRESSION_MASK) == FXT1_COMPRESSION)
+          conf_str = "1";
+        else if ((tmpconfig & COMPRESSION_MASK) == S3TC_COMPRESSION)
+          conf_str = "0";
+        else
+          conf_str = "set to an unsupported format";
+
+        WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_cmpr must be %s", conf_str);
+      }
+      if ((tmpconfig & TILE_HIRESTEX) != (config & TILE_HIRESTEX))
+        WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_hirs_tile must be %s", (tmpconfig & TILE_HIRESTEX) ? "True" : "False");
+      if ((tmpconfig & FORCE16BPP_HIRESTEX) != (config & FORCE16BPP_HIRESTEX))
+        WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_hirs_f16bpp must be %s", (tmpconfig & FORCE16BPP_HIRESTEX) ? "True" : "False");
+      if ((tmpconfig & GZ_HIRESTEXCACHE) != (config & GZ_HIRESTEXCACHE))
+        WriteLog(M64MSG_WARNING, "ghq_hirs_gz must be %s", (tmpconfig & GZ_HIRESTEXCACHE) ? "True" : "False");
+      if ((tmpconfig & LET_TEXARTISTS_FLY) != (config & LET_TEXARTISTS_FLY))
+        WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_hirs_let_texartists_fly must be %s", (tmpconfig & LET_TEXARTISTS_FLY) ? "True" : "False");
+
+      if ((tmpconfig & FILTER_MASK) != (config & FILTER_MASK)) {
+        const char *conf_str;
+        if ((tmpconfig & FILTER_MASK) == NO_FILTER)
+          conf_str = "0";
+        else if ((tmpconfig & FILTER_MASK) == SMOOTH_FILTER_1)
+          conf_str = "1";
+        else if ((tmpconfig & FILTER_MASK) == SMOOTH_FILTER_2)
+          conf_str = "2";
+        else if ((tmpconfig & FILTER_MASK) == SMOOTH_FILTER_3)
+          conf_str = "3";
+        else if ((tmpconfig & FILTER_MASK) == SMOOTH_FILTER_4)
+          conf_str = "4";
+        else if ((tmpconfig & FILTER_MASK) == SHARP_FILTER_1)
+          conf_str = "5";
+        else if ((tmpconfig & FILTER_MASK) == SHARP_FILTER_2)
+          conf_str = "6";
+        else
+          conf_str = "set to an unsupported format";
+        WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_fltr must be %s", conf_str);
+      }
+
+      if ((tmpconfig & ENHANCEMENT_MASK) != (config & ENHANCEMENT_MASK)) {
+        const char *conf_str;
+        if ((tmpconfig & ENHANCEMENT_MASK) == NO_ENHANCEMENT)
+          conf_str = "0";
+        else if ((tmpconfig & ENHANCEMENT_MASK) == X2_ENHANCEMENT)
+          conf_str = "2";
+        else if ((tmpconfig & ENHANCEMENT_MASK) == X2SAI_ENHANCEMENT)
+          conf_str = "3";
+        else if ((tmpconfig & ENHANCEMENT_MASK) == HQ2X_ENHANCEMENT)
+          conf_str = "4";
+        else if ((tmpconfig & ENHANCEMENT_MASK) == HQ2XS_ENHANCEMENT)
+          conf_str = "5";
+        else if ((tmpconfig & ENHANCEMENT_MASK) == LQ2X_ENHANCEMENT)
+          conf_str = "6";
+        else if ((tmpconfig & ENHANCEMENT_MASK) == LQ2XS_ENHANCEMENT)
+          conf_str = "7";
+        else if ((tmpconfig & ENHANCEMENT_MASK) == HQ4X_ENHANCEMENT)
+          conf_str = "8";
+        else
+          conf_str = "set to an unsupported format";
+        WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_enht must be %s", conf_str);
+      }
+
+      if ((tmpconfig & COMPRESS_TEX) != (config & COMPRESS_TEX))
+        WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_enht_cmpr must be %s", (tmpconfig & COMPRESS_TEX) ? "True" : "False");
+      if ((tmpconfig & FORCE16BPP_TEX) != (config & FORCE16BPP_TEX))
+        WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_enht_f16bpp must be %s", (tmpconfig & FORCE16BPP_TEX) ? "True" : "False");
+      if ((tmpconfig & GZ_TEXCACHE) != (config & GZ_TEXCACHE))
+        WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_enht_gz must be %s", (tmpconfig & GZ_TEXCACHE) ? "True" : "False");
+    }
+  }
+
+  if (CHDIR(curpath) != 0)
+      ERRLOG("Error while changing current directory back to original path of '%s'!", curpath);
+
+  return !_cache.empty();
+}
+
+boolean
+TxCache::del(uint64 checksum)
+{
+  if (!checksum || _cache.empty()) return 0;
+
+  std::map<uint64, TXCACHE*>::iterator itMap = _cache.find(checksum);
+  if (itMap != _cache.end()) {
+
+    /* for texture cache (not hi-res cache) */
+    if (!_cachelist.empty()) _cachelist.erase(((*itMap).second)->it);
+
+    /* remove from cache */
+    free((*itMap).second->info.data);
+    _totalSize -= (*itMap).second->size;
+    delete (*itMap).second;
+    _cache.erase(itMap);
+
+    DBG_INFO(80, L"removed from cache: checksum = %08X %08X\n", (uint32)(checksum & 0xffffffff), (uint32)(checksum >> 32));
+
+    return 1;
+  }
+
+  return 0;
+}
+
+boolean
+TxCache::is_cached(uint64 checksum)
+{
+  std::map<uint64, TXCACHE*>::iterator itMap = _cache.find(checksum);
+  if (itMap != _cache.end()) return 1;
+
+  return 0;
+}
+
+void
+TxCache::clear()
+{
+  if (!_cache.empty()) {
+    std::map<uint64, TXCACHE*>::iterator itMap = _cache.begin();
+    while (itMap != _cache.end()) {
+      free((*itMap).second->info.data);
+      delete (*itMap).second;
+      itMap++;
+    }
+    _cache.clear();
+  }
+
+  if (!_cachelist.empty()) _cachelist.clear();
+
+  _totalSize = 0;
+}
diff --git a/source/gles2glide64/src/GlideHQ/TxCache.h b/source/gles2glide64/src/GlideHQ/TxCache.h
new file mode 100644 (file)
index 0000000..cb2de0c
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __TXCACHE_H__
+#define __TXCACHE_H__
+
+#include "TxInternal.h"
+#include "TxUtil.h"
+#include <list>
+#include <map>
+#include <string>
+
+class TxCache
+{
+private:
+  std::list<uint64> _cachelist;
+  uint8 *_gzdest0;
+  uint8 *_gzdest1;
+  uint32 _gzdestLen;
+protected:
+  int _options;
+  std::wstring _ident;
+  std::wstring _datapath;
+  std::wstring _cachepath;
+  dispInfoFuncExt _callback;
+  TxUtil *_txUtil;
+  struct TXCACHE {
+    int size;
+    GHQTexInfo info;
+    std::list<uint64>::iterator it;
+  };
+  int _totalSize;
+  int _cacheSize;
+  std::map<uint64, TXCACHE*> _cache;
+  boolean save(const wchar_t *path, const wchar_t *filename, const int config);
+  boolean load(const wchar_t *path, const wchar_t *filename, const int config);
+  boolean del(uint64 checksum); /* checksum hi:palette low:texture */
+  boolean is_cached(uint64 checksum); /* checksum hi:palette low:texture */
+  void clear();
+public:
+  ~TxCache();
+  TxCache(int options, int cachesize, const wchar_t *datapath,
+              const wchar_t *cachepath, const wchar_t *ident,
+              dispInfoFuncExt callback);
+  boolean add(uint64 checksum, /* checksum hi:palette low:texture */
+              GHQTexInfo *info, int dataSize = 0);
+  boolean get(uint64 checksum, /* checksum hi:palette low:texture */
+              GHQTexInfo *info);
+};
+
+#endif /* __TXCACHE_H__ */
diff --git a/source/gles2glide64/src/GlideHQ/TxDbg.cpp b/source/gles2glide64/src/GlideHQ/TxDbg.cpp
new file mode 100755 (executable)
index 0000000..fbd757d
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define DBG_LEVEL 80
+
+#include "TxDbg.h"
+#include <string.h>
+#include <stdarg.h>
+#include <string>
+
+#define _GLIBCXX_HAVE_BROKEN_VSWPRINTF 1
+
+TxDbg::TxDbg()
+{
+  _level = DBG_LEVEL;
+
+  if (!_dbgfile)
+#ifdef GHQCHK
+    _dbgfile = fopen("ghqchk.txt", "w");
+#else
+    _dbgfile = fopen("glidehq.dbg", "w");
+#endif
+}
+
+TxDbg::~TxDbg()
+{
+  if (_dbgfile) {
+    fclose(_dbgfile);
+    _dbgfile = 0;
+  }
+
+  _level = DBG_LEVEL;
+}
+
+void
+TxDbg::output(const int level, const wchar_t *format, ...)
+{
+#ifdef _GLIBCXX_HAVE_BROKEN_VSWPRINTF
+  wchar_t newformat[4095];
+#else
+  std::wstring newformat;
+#endif
+
+  va_list args;
+
+  if (level > _level)
+    return;
+
+  va_start(args, format);
+#ifdef _GLIBCXX_HAVE_BROKEN_VSWPRINTF
+  swprintf(newformat, L"%d:\t", level);
+  wcscat(newformat, format);
+  vfwprintf(_dbgfile, newformat, args);
+#else
+  newformat = std::to_wstring(level) + L":\t" + format;
+  vfwprintf(_dbgfile, newformat.c_str(), args);
+#endif
+  fflush(_dbgfile);
+#ifdef GHQCHK
+  //vwprintf(newformat, args);
+  vwprintf(newformat.c_str(), args);
+#endif
+  va_end(args);
+}
diff --git a/source/gles2glide64/src/GlideHQ/TxDbg.h b/source/gles2glide64/src/GlideHQ/TxDbg.h
new file mode 100644 (file)
index 0000000..8f366ce
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __TXDBG_H__
+#define __TXDBG_H__
+
+#include <stdio.h>
+#include "TxInternal.h"
+
+class TxDbg
+{
+private:
+  FILE* _dbgfile;
+  int _level;
+  TxDbg();
+public:
+  static TxDbg* getInstance() {
+    static TxDbg txDbg;
+    return &txDbg;
+  }
+  ~TxDbg();
+  void output(const int level, const wchar_t *format, ...);
+};
+
+#ifdef DEBUG
+#define DBG_INFO(...) TxDbg::getInstance()->output(__VA_ARGS__)
+#define INFO(...) DBG_INFO(__VA_ARGS__)
+#else
+#define DBG_INFO(...)
+#ifdef GHQCHK
+#define INFO(...) TxDbg::getInstance()->output(__VA_ARGS__)
+#else
+#if 0 /* XXX enable this to log basic hires texture checks */
+#define INFO(...) TxDbg::getInstance()->output(__VA_ARGS__)
+#else
+#define INFO(...) DBG_INFO(__VA_ARGS__)
+#endif
+#endif
+#endif
+
+#endif /* __TXDBG_H__ */
diff --git a/source/gles2glide64/src/GlideHQ/TxFilter.cpp b/source/gles2glide64/src/GlideHQ/TxFilter.cpp
new file mode 100644 (file)
index 0000000..2d89caf
--- /dev/null
@@ -0,0 +1,692 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef __MSC__
+#pragma warning(disable: 4786)
+#endif
+
+#include "TxFilter.h"
+#include "TextureFilters.h"
+#include "TxDbg.h"
+#include <functional>
+#include <thread>
+
+void TxFilter::clear()
+{
+  /* clear hires texture cache */
+  delete _txHiResCache;
+  _txHiResCache = NULL;
+
+  /* clear texture cache */
+  delete _txTexCache;
+  _txTexCache = NULL;
+
+  /* free memory */
+  TxMemBuf::getInstance()->shutdown();
+
+  /* clear other stuff */
+  delete _txImage;
+  _txImage = NULL;
+  delete _txQuantize;
+  _txQuantize = NULL;
+  delete _txUtil;
+  _txUtil = NULL;
+}
+
+TxFilter::~TxFilter()
+{
+  clear();
+}
+
+TxFilter::TxFilter(int maxwidth, int maxheight, int maxbpp, int options,
+                   int cachesize, wchar_t *datapath, wchar_t *cachepath,
+                   wchar_t *ident, dispInfoFuncExt callback) :
+  _numcore(1), _tex1(NULL), _tex2(NULL), _maxwidth(0), _maxheight(0),
+  _maxbpp(0), _options(0), _cacheSize(0), _ident(), _datapath(), _cachepath(),
+  _txQuantize(NULL), _txTexCache(NULL), _txHiResCache(NULL), _txUtil(NULL),
+  _txImage(NULL), _initialized(false)
+{
+  clear(); /* gcc does not allow the destructor to be called */
+
+  /* shamelessness :P this first call to the debug output message creates
+   * a file in the executable directory. */
+  INFO(0, L"------------------------------------------------------------------\n");
+#ifdef GHQCHK
+  INFO(0, L" GlideHQ Hires Texture Checker 1.02.00.%d\n", 0);
+#else
+  INFO(0, L" GlideHQ version 1.02.00.%d\n", 0);
+#endif
+  INFO(0, L" Copyright (C) 2010  Hiroshi Morii   All Rights Reserved\n");
+  INFO(0, L"    email   : koolsmoky(at)users.sourceforge.net\n");
+  INFO(0, L"    website : http://www.3dfxzone.it/koolsmoky\n");
+  INFO(0, L"\n");
+  INFO(0, L" Glide64 official website : http://glide64.emuxhaven.net\n");
+  INFO(0, L"------------------------------------------------------------------\n");
+
+  _options = options;
+
+  _txImage      = new TxImage();
+  _txQuantize   = new TxQuantize();
+  _txUtil       = new TxUtil();
+
+  /* get number of CPU cores. */
+  _numcore = _txUtil->getNumberofProcessors();
+
+  _initialized = 0;
+
+  _tex1 = NULL;
+  _tex2 = NULL;
+
+  /* XXX: anything larger than 1024 * 1024 is overkill */
+  _maxwidth  = maxwidth  > 1024 ? 1024 : maxwidth;
+  _maxheight = maxheight > 1024 ? 1024 : maxheight;
+  _maxbpp    = maxbpp;
+
+  _cacheSize = cachesize;
+
+  /* TODO: validate options and do overrides here*/
+
+  /* save path name */
+  if (datapath)
+    _datapath.assign(datapath);
+  if (cachepath)
+    _cachepath.assign(cachepath);
+
+  /* save ROM name */
+  if (ident && wcscmp(ident, L"DEFAULT") != 0)
+    _ident.assign(ident);
+
+  /* check for dxtn extensions */
+  if (!TxLoadLib::getInstance()->getdxtCompressTexFuncExt())
+    _options &= ~S3TC_COMPRESSION;
+
+  if (!TxLoadLib::getInstance()->getfxtCompressTexFuncExt())
+    _options &= ~FXT1_COMPRESSION;
+
+  switch (options & COMPRESSION_MASK) {
+  case FXT1_COMPRESSION:
+  case S3TC_COMPRESSION:
+    break;
+  case NCC_COMPRESSION:
+  default:
+    _options &= ~COMPRESSION_MASK;
+  }
+
+  if (TxMemBuf::getInstance()->init(_maxwidth, _maxheight)) {
+    if (!_tex1)
+      _tex1 = TxMemBuf::getInstance()->get(0);
+
+    if (!_tex2)
+      _tex2 = TxMemBuf::getInstance()->get(1);
+  }
+
+#if !_16BPP_HACK
+  /* initialize hq4x filter */
+  hq4x_init();
+#endif
+
+  /* initialize texture cache in bytes. 128Mb will do nicely in most cases */
+  _txTexCache = new TxTexCache(_options, _cacheSize, _datapath.c_str(), _cachepath.c_str(), _ident.c_str(), callback);
+
+  /* hires texture */
+#if HIRES_TEXTURE
+  _txHiResCache = new TxHiResCache(_maxwidth, _maxheight, _maxbpp, _options, _datapath.c_str(), _cachepath.c_str(), _ident.c_str(), callback);
+
+  if (_txHiResCache->empty())
+    _options &= ~HIRESTEXTURES_MASK;
+#endif
+
+  if (!(_options & COMPRESS_TEX))
+    _options &= ~COMPRESSION_MASK;
+
+  if (_tex1 && _tex2)
+      _initialized = 1;
+}
+
+boolean
+TxFilter::filter(uint8 *src, int srcwidth, int srcheight, uint16 srcformat, uint64 g64crc, GHQTexInfo *info)
+{
+  uint8 *texture = src;
+  uint8 *tmptex = _tex1;
+  uint16 destformat = srcformat;
+
+  /* We need to be initialized first! */
+  if (!_initialized) return 0;
+
+  /* find cached textures */
+  if (_cacheSize) {
+
+    /* calculate checksum of source texture */
+    if (!g64crc)
+      g64crc = (uint64)(_txUtil->checksumTx(texture, srcwidth, srcheight, srcformat));
+
+    DBG_INFO(80, L"filter: crc:%08X %08X %d x %d gfmt:%x\n",
+             (uint32)(g64crc >> 32), (uint32)(g64crc & 0xffffffff), srcwidth, srcheight, srcformat);
+
+#if 0 /* use hirestex to retrieve cached textures. */
+    /* check if we have it in cache */
+    if (!(g64crc & 0xffffffff00000000) && /* we reach here only when there is no hires texture for this crc */
+        _txTexCache->get(g64crc, info)) {
+      DBG_INFO(80, L"cache hit: %d x %d gfmt:%x\n", info->width, info->height, info->format);
+      return 1; /* yep, we've got it */
+    }
+#endif
+  }
+
+  /* Leave small textures alone because filtering makes little difference.
+   * Moreover, some filters require at least 4 * 4 to work.
+   * Bypass _options to do ARGB8888->16bpp if _maxbpp=16 or forced color reduction.
+   */
+  if ((srcwidth >= 4 && srcheight >= 4) &&
+      ((_options & (FILTER_MASK|ENHANCEMENT_MASK|COMPRESSION_MASK)) ||
+       (srcformat == GR_TEXFMT_ARGB_8888 && (_maxbpp < 32 || _options & FORCE16BPP_TEX)))) {
+
+#if !_16BPP_HACK
+    /* convert textures to a format that the compressor accepts (ARGB8888) */
+    if (_options & COMPRESSION_MASK) {
+#endif
+      if (srcformat != GR_TEXFMT_ARGB_8888) {
+        if (!_txQuantize->quantize(texture, tmptex, srcwidth, srcheight, srcformat, GR_TEXFMT_ARGB_8888)) {
+          DBG_INFO(80, L"Error: unsupported format! gfmt:%x\n", srcformat);
+          return 0;
+        }
+        texture = tmptex;
+        destformat = GR_TEXFMT_ARGB_8888;
+      }
+#if !_16BPP_HACK
+    }
+#endif
+
+    switch (destformat) {
+    case GR_TEXFMT_ARGB_8888:
+
+      /*
+       * prepare texture enhancements (x2, x4 scalers)
+       */
+      int scale_shift = 0, num_filters = 0;
+      uint32 filter = 0;
+
+      if ((_options & ENHANCEMENT_MASK) == HQ4X_ENHANCEMENT) {
+        if (srcwidth  <= (_maxwidth >> 2) && srcheight <= (_maxheight >> 2)) {
+          filter |= HQ4X_ENHANCEMENT;
+          scale_shift = 2;
+          num_filters++;
+        } else if (srcwidth  <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
+          filter |= HQ2X_ENHANCEMENT;
+          scale_shift = 1;
+          num_filters++;
+        }
+      } else if (_options & ENHANCEMENT_MASK) {
+        if (srcwidth  <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
+          filter |= (_options & ENHANCEMENT_MASK);
+          scale_shift = 1;
+          num_filters++;
+        }
+      }
+
+      /*
+       * prepare texture filters
+       */
+      if (_options & (SMOOTH_FILTER_MASK|SHARP_FILTER_MASK)) {
+        filter |= (_options & (SMOOTH_FILTER_MASK|SHARP_FILTER_MASK));
+        num_filters++;
+      }
+
+      /*
+       * execute texture enhancements and filters
+       */
+      while (num_filters > 0) {
+
+        tmptex = (texture == _tex1) ? _tex2 : _tex1;
+
+        uint8 *_texture = texture;
+        uint8 *_tmptex  = tmptex;
+
+#if !defined(NO_FILTER_THREAD)
+        unsigned int numcore = _numcore;
+        unsigned int blkrow = 0;
+        while (numcore > 1 && blkrow == 0) {
+          blkrow = (srcheight >> 2) / numcore;
+          numcore--;
+        }
+        if (blkrow > 0 && numcore > 1) {
+          std::thread *thrd[MAX_NUMCORE];
+          unsigned int i;
+          int blkheight = blkrow << 2;
+          unsigned int srcStride = (srcwidth * blkheight) << 2;
+          unsigned int destStride = srcStride << scale_shift << scale_shift;
+          for (i = 0; i < numcore - 1; i++) {
+            thrd[i] = new std::thread(std::bind(filter_8888,
+                                                (uint32*)_texture,
+                                                srcwidth,
+                                                blkheight,
+                                                (uint32*)_tmptex,
+                                                filter));
+            _texture += srcStride;
+            _tmptex  += destStride;
+          }
+          thrd[i] = new std::thread(std::bind(filter_8888,
+                                              (uint32*)_texture,
+                                              srcwidth,
+                                              srcheight - blkheight * i,
+                                              (uint32*)_tmptex,
+                                              filter));
+          for (i = 0; i < numcore; i++) {
+            thrd[i]->join();
+            delete thrd[i];
+          }
+        } else {
+          filter_8888((uint32*)_texture, srcwidth, srcheight, (uint32*)_tmptex, filter);
+        }
+#else
+        filter_8888((uint32*)_texture, srcwidth, srcheight, (uint32*)_tmptex, filter);
+#endif
+
+        if (filter & ENHANCEMENT_MASK) {
+          srcwidth  <<= scale_shift;
+          srcheight <<= scale_shift;
+          filter &= ~ENHANCEMENT_MASK;
+          scale_shift = 0;
+        }
+
+        texture = tmptex;
+        num_filters--;
+      }
+
+      /*
+       * texture compression
+       */
+      /* ignored if we only have texture compression option on.
+       * only done when texture enhancer is used. see constructor. */
+      if ((_options & COMPRESSION_MASK) &&
+          (srcwidth >= 64 && srcheight >= 64) /* Texture compression is not suitable for low pixel coarse detail
+                                               * textures. The assumption here is that textures larger than 64x64
+                                               * have enough detail to produce decent quality when compressed. The
+                                               * down side is that narrow stripped textures that the N64 often use
+                                               * for large background textures are also ignored. It would be more
+                                               * reasonable if decisions are made based on fourier-transform
+                                               * spectrum or RMS error.
+                                               */
+          ) {
+        int compressionType = _options & COMPRESSION_MASK;
+        int tmpwidth, tmpheight;
+        uint16 tmpformat;
+        /* XXX: textures that use 8bit alpha channel look bad with the current
+         * fxt1 library, so we substitute it with dxtn for now. afaik all gfx
+         * cards that support fxt1 also support dxtn. (3dfx and Intel) */
+        if ((destformat == GR_TEXFMT_ALPHA_INTENSITY_88) ||
+            (destformat == GR_TEXFMT_ARGB_8888) ||
+            (destformat == GR_TEXFMT_ALPHA_8)) {
+          compressionType = S3TC_COMPRESSION;
+        }
+        tmptex = (texture == _tex1) ? _tex2 : _tex1;
+        if (_txQuantize->compress(texture, tmptex,
+                                  srcwidth, srcheight, srcformat,
+                                  &tmpwidth, &tmpheight, &tmpformat,
+                                  compressionType)) {
+          srcwidth = tmpwidth;
+          srcheight = tmpheight;
+          destformat = tmpformat;
+          texture = tmptex;
+        }
+      }
+
+
+      /*
+       * texture (re)conversions
+       */
+      if (destformat == GR_TEXFMT_ARGB_8888) {
+        if (srcformat == GR_TEXFMT_ARGB_8888 && (_maxbpp < 32 || _options & FORCE16BPP_TEX)) srcformat = GR_TEXFMT_ARGB_4444;
+        if (srcformat != GR_TEXFMT_ARGB_8888) {
+          tmptex = (texture == _tex1) ? _tex2 : _tex1;
+          if (!_txQuantize->quantize(texture, tmptex, srcwidth, srcheight, GR_TEXFMT_ARGB_8888, srcformat)) {
+            DBG_INFO(80, L"Error: unsupported format! gfmt:%x\n", srcformat);
+            return 0;
+          }
+          texture = tmptex;
+          destformat = srcformat;
+        }
+      }
+
+      break;
+#if !_16BPP_HACK
+    case GR_TEXFMT_ARGB_4444:
+
+      int scale_shift = 0;
+      tmptex = (texture == _tex1) ? _tex2 : _tex1;
+
+      switch (_options & ENHANCEMENT_MASK) {
+      case HQ4X_ENHANCEMENT:
+        if (srcwidth <= (_maxwidth >> 2) && srcheight <= (_maxheight >> 2)) {
+          hq4x_4444((uint8*)texture, (uint8*)tmptex, srcwidth, srcheight, srcwidth, srcwidth * 4 * 2);
+          scale_shift = 2;
+        }/* else if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
+          hq2x_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight);
+          scale_shift = 1;
+        }*/
+        break;
+      case HQ2X_ENHANCEMENT:
+        if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
+          hq2x_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight);
+          scale_shift = 1;
+        }
+        break;
+      case HQ2XS_ENHANCEMENT:
+        if (srcwidth <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
+          hq2xS_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight);
+          scale_shift = 1;
+        }
+        break;
+      case LQ2X_ENHANCEMENT:
+        if (srcwidth  <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
+          lq2x_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight);
+          scale_shift = 1;
+        }
+        break;
+      case LQ2XS_ENHANCEMENT:
+        if (srcwidth  <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
+          lq2xS_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight);
+          scale_shift = 1;
+        }
+        break;
+      case X2SAI_ENHANCEMENT:
+        if (srcwidth  <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
+          Super2xSaI_4444((uint16*)texture, (uint16*)tmptex, srcwidth, srcheight, srcwidth);
+          scale_shift = 1;
+        }
+        break;
+      case X2_ENHANCEMENT:
+        if (srcwidth  <= (_maxwidth >> 1) && srcheight <= (_maxheight >> 1)) {
+          Texture2x_16((uint8*)texture, srcwidth * 2, (uint8*)tmptex, srcwidth * 2 * 2, srcwidth, srcheight);
+          scale_shift = 1;
+        }
+      }
+      if (scale_shift) {
+        srcwidth <<= scale_shift;
+        srcheight <<= scale_shift;
+        texture = tmptex;
+      }
+
+      if (_options & SMOOTH_FILTER_MASK) {
+        tmptex = (texture == _tex1) ? _tex2 : _tex1;
+        SmoothFilter_4444((uint16*)texture, srcwidth, srcheight, (uint16*)tmptex, (_options & SMOOTH_FILTER_MASK));
+        texture = tmptex;
+      } else if (_options & SHARP_FILTER_MASK) {
+        tmptex = (texture == _tex1) ? _tex2 : _tex1;
+        SharpFilter_4444((uint16*)texture, srcwidth, srcheight, (uint16*)tmptex, (_options & SHARP_FILTER_MASK));
+        texture = tmptex;
+      }
+
+      break;
+    case GR_TEXFMT_ARGB_1555:
+      break;
+    case GR_TEXFMT_RGB_565:
+      break;
+    case GR_TEXFMT_ALPHA_8:
+      break;
+#endif /* _16BPP_HACK */
+    }
+  }
+
+  /* fill in the texture info. */
+  info->data = texture;
+  info->width  = srcwidth;
+  info->height = srcheight;
+  info->format = destformat;
+  info->smallLodLog2 = _txUtil->grLodLog2(srcwidth, srcheight);
+  info->largeLodLog2 = info->smallLodLog2;
+  info->aspectRatioLog2 = _txUtil->grAspectRatioLog2(srcwidth, srcheight);
+  info->is_hires_tex = 0;
+
+  /* cache the texture. */
+  if (_cacheSize) _txTexCache->add(g64crc, info);
+
+  DBG_INFO(80, L"filtered texture: %d x %d gfmt:%x\n", info->width, info->height, info->format);
+
+  return 1;
+}
+
+boolean
+TxFilter::hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *info)
+{
+  /* NOTE: Rice CRC32 sometimes return the same value for different textures.
+   * As a workaround, Glide64 CRC32 is used for the key for NON-hires
+   * texture cache.
+   *
+   * r_crc64 = hi:palette low:texture
+   *           (separate crc. doesn't necessary have to be rice crc)
+   * g64crc  = texture + palette glide64 crc32
+   *           (can be any other crc if robust)
+   */
+
+  DBG_INFO(80, L"hirestex: r_crc64:%08X %08X, g64crc:%08X %08X\n",
+           (uint32)(r_crc64 >> 32), (uint32)(r_crc64 & 0xffffffff),
+           (uint32)(g64crc >> 32), (uint32)(g64crc & 0xffffffff));
+
+#if HIRES_TEXTURE
+  /* check if we have it in hires memory cache. */
+  if ((_options & HIRESTEXTURES_MASK) && r_crc64) {
+    if (_txHiResCache->get(r_crc64, info)) {
+      DBG_INFO(80, L"hires hit: %d x %d gfmt:%x\n", info->width, info->height, info->format);
+
+      /* TODO: Enable emulation for special N64 combiner modes. There are few ways
+       * to get this done. Also applies for CI textures below.
+       *
+       * Solution 1. Load the hiresolution textures in ARGB8888 (or A8, IA88) format
+       * to cache. When a cache is hit, then we take the modes passed in from Glide64
+       * (also TODO) and apply the modification. Then we do color reduction or format
+       * conversion or compression if desired and stuff it into the non-hires texture
+       * cache.
+       *
+       * Solution 2. When a cache is hit and if the combiner modes are present,
+       * convert the texture to ARGB4444 and pass it back to Glide64 to process.
+       * If a texture is compressed, it needs to be decompressed first. Then add
+       * the processed texture to the non-hires texture cache.
+       *
+       * Solution 3. Hybrid of the above 2. Load the textures in ARGB8888 (A8, IA88)
+       * format. Convert the texture to ARGB4444 and pass it back to Glide64 when
+       * the combiner modes are present. Get the processed texture back from Glide64
+       * and compress if desired and add it to the non-hires texture cache.
+       *
+       * Solution 4. Take the easy way out and forget about this whole thing.
+       */
+
+      return 1; /* yep, got it */
+    }
+    if (_txHiResCache->get((r_crc64 & 0xffffffff), info)) {
+      DBG_INFO(80, L"hires hit: %d x %d gfmt:%x\n", info->width, info->height, info->format);
+
+      /* for true CI textures, we use the passed in palette to convert to
+       * ARGB1555 and add it to memory cache.
+       *
+       * NOTE: we do this AFTER all other texture cache searches because
+       * only a few texture packs actually use true CI textures.
+       *
+       * NOTE: the pre-converted palette from Glide64 is in RGBA5551 format.
+       * A comp comes before RGB comp.
+       */
+      if (palette && info->format == GR_TEXFMT_P_8) {
+        DBG_INFO(80, L"found GR_TEXFMT_P_8 format. Need conversion!!\n");
+
+        int width = info->width;
+        int height = info->height;
+        uint16 format = info->format;
+        /* XXX: avoid collision with zlib compression buffer in TxHiResTexture::get */
+        uint8 *texture = info->data;
+        uint8 *tmptex = (texture == _tex1) ? _tex2 : _tex1;
+
+        /* use palette and convert to 16bit format */
+        _txQuantize->P8_16BPP((uint32*)texture, (uint32*)tmptex, info->width, info->height, (uint32*)palette);
+        texture = tmptex;
+        format = GR_TEXFMT_ARGB_1555;
+
+#if 1
+        /* XXX: compressed if memory cache compression is ON */
+        if (_options & COMPRESSION_MASK) {
+          tmptex = (texture == _tex1) ? _tex2 : _tex1;
+          if (_txQuantize->quantize(texture, tmptex, info->width, info->height, format, GR_TEXFMT_ARGB_8888)) {
+            texture = tmptex;
+            format = GR_TEXFMT_ARGB_8888;
+          }
+          if (format == GR_TEXFMT_ARGB_8888) {
+            tmptex = (texture == _tex1) ? _tex2 : _tex1;
+            if (_txQuantize->compress(texture, tmptex,
+                                      info->width, info->height, GR_TEXFMT_ARGB_1555,
+                                      &width, &height, &format,
+                                      _options & COMPRESSION_MASK)) {
+              texture = tmptex;
+            } else {
+              /*if (!_txQuantize->quantize(texture, tmptex, info->width, info->height, GR_TEXFMT_ARGB_8888, GR_TEXFMT_ARGB_1555)) {
+                DBG_INFO(80, L"Error: unsupported format! gfmt:%x\n", format);
+                return 0;
+              }*/
+              texture = tmptex;
+              format = GR_TEXFMT_ARGB_1555;
+            }
+          }
+        }
+#endif
+
+        /* fill in the required info to return */
+        info->data = texture;
+        info->width = width;
+        info->height = height;
+        info->format = format;
+        info->smallLodLog2 = _txUtil->grLodLog2(width, height);
+        info->largeLodLog2 = info->smallLodLog2;
+        info->aspectRatioLog2 = _txUtil->grAspectRatioLog2(width, height);
+        info->is_hires_tex = 1;
+
+        /* XXX: add to hires texture cache!!! */
+        _txHiResCache->add(r_crc64, info);
+
+        DBG_INFO(80, L"GR_TEXFMT_P_8 loaded as gfmt:%x!\n", format);
+      }
+
+      return 1;
+    }
+  }
+#endif
+
+  /* check if we have it in memory cache */
+  if (_cacheSize && g64crc) {
+    if (_txTexCache->get(g64crc, info)) {
+      DBG_INFO(80, L"cache hit: %d x %d gfmt:%x\n", info->width, info->height, info->format);
+      return 1; /* yep, we've got it */
+    }
+  }
+
+  DBG_INFO(80, L"no cache hits.\n");
+
+  return 0;
+}
+
+uint64
+TxFilter::checksum64(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette)
+{
+  if (_options & (HIRESTEXTURES_MASK|DUMP_TEX))
+    return _txUtil->checksum64(src, width, height, size, rowStride, palette);
+
+  return 0;
+}
+
+boolean
+TxFilter::dmptx(uint8 *src, int width, int height, int rowStridePixel, uint16 gfmt, uint16 n64fmt, uint64 r_crc64)
+{
+  if (!_initialized)
+    return 0;
+
+  if (!(_options & DUMP_TEX))
+    return 0;
+
+#ifdef DUMP_CACHE
+  DBG_INFO(80, L"gfmt = %02x n64fmt = %02x\n", gfmt, n64fmt);
+  DBG_INFO(80, L"hirestex: r_crc64:%08X %08X\n",
+           (uint32)(r_crc64 >> 32), (uint32)(r_crc64 & 0xffffffff));
+
+  if (!_txQuantize->quantize(src, _tex1, rowStridePixel, height, (gfmt & 0x00ff), GR_TEXFMT_ARGB_8888))
+    return 0;
+
+  src = _tex1;
+
+  if (!_datapath.empty() && !_ident.empty()) {
+    /* dump it to disk */
+    FILE *fp = NULL;
+    std::wstring tmpbuf;
+    wchar_t texid[36];
+
+    /* create directories */
+    tmpbuf.assign(_datapath + L"/texture_dump");
+    if (!boost::filesystem::exists(tmpbuf) &&
+        !boost::filesystem::create_directory(tmpbuf))
+      return 0;
+
+    tmpbuf.append(L"/" + _ident);
+    if (!boost::filesystem::exists(tmpbuf) &&
+        !boost::filesystem::create_directory(tmpbuf))
+      return 0;
+
+    tmpbuf.append(L"/GlideHQ");
+    if (!boost::filesystem::exists(tmpbuf) &&
+        !boost::filesystem::create_directory(tmpbuf))
+      return 0;
+
+    if ((n64fmt >> 8) == 0x2) {
+      swprintf(texid, 36, L"%08X#%01X#%01X#%08X", (uint32)(r_crc64 & 0xffffffff), (uint32)(n64fmt >> 8), (uint32)(n64fmt & 0xf), (uint32)(r_crc64 >> 32));
+      tmpbuf.append(L"/" + _ident + L"#" + texid + L"_ciByRGBA.png");
+    } else {
+      swprintf(texid, 36, L"%08X#%01X#%01X",  (uint32)(r_crc64 & 0xffffffff), (uint32)(n64fmt >> 8), (uint32)(n64fmt & 0xf));
+      tmpbuf.append(L"/" + _ident + L"#" + texid + L"_all.png");
+    }
+
+#ifdef WIN32
+    if ((fp = _wfopen(tmpbuf.c_str(), L"wb")) != NULL) {
+#else
+    char cbuf[MAX_PATH];
+    wcstombs(cbuf, tmpbuf.c_str(), MAX_PATH);
+    if ((fp = fopen(cbuf, "wb")) != NULL) {
+#endif
+      _txImage->writePNG(src, fp, width, height, (rowStridePixel << 2), 0x0003, 0);
+      fclose(fp);
+      return 1;
+    }
+  }
+#endif
+
+  return 0;
+}
+
+boolean
+TxFilter::reloadhirestex()
+{
+  DBG_INFO(80, L"Reload hires textures from texture pack.\n");
+
+  if (_txHiResCache->load(0)) {
+    if (_txHiResCache->empty()) _options &= ~HIRESTEXTURES_MASK;
+    else _options |= HIRESTEXTURES_MASK;
+
+    return 1;
+  }
+
+  return 0;
+}
diff --git a/source/gles2glide64/src/GlideHQ/TxFilter.h b/source/gles2glide64/src/GlideHQ/TxFilter.h
new file mode 100644 (file)
index 0000000..bdbfe1b
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __TXFILTER_H__
+#define __TXFILTER_H__
+
+#include "TxInternal.h"
+#include "TxQuantize.h"
+#include "TxHiResCache.h"
+#include "TxTexCache.h"
+#include "TxUtil.h"
+#include "TxImage.h"
+#include <string>
+
+class TxFilter
+{
+private:
+  int _numcore;
+
+  uint8 *_tex1;
+  uint8 *_tex2;
+  int _maxwidth;
+  int _maxheight;
+  int _maxbpp;
+  int _options;
+  int _cacheSize;
+  std::wstring _ident;
+  std::wstring _datapath;
+  std::wstring _cachepath;
+  TxQuantize *_txQuantize;
+  TxTexCache *_txTexCache;
+  TxHiResCache *_txHiResCache;
+  TxUtil *_txUtil;
+  TxImage *_txImage;
+  boolean _initialized;
+  void clear();
+public:
+  ~TxFilter();
+  TxFilter(int maxwidth,
+           int maxheight,
+           int maxbpp,
+           int options,
+           int cachesize,
+           wchar_t *datapath,
+           wchar_t *cachepath,
+           wchar_t *ident,
+           dispInfoFuncExt callback);
+  boolean filter(uint8 *src,
+                  int srcwidth,
+                  int srcheight,
+                  uint16 srcformat,
+                  uint64 g64crc, /* glide64 crc, 64bit for future use */
+                  GHQTexInfo *info);
+  boolean hirestex(uint64 g64crc, /* glide64 crc, 64bit for future use */
+                      uint64 r_crc64,   /* checksum hi:palette low:texture */
+                      uint16 *palette,
+                      GHQTexInfo *info);
+  uint64 checksum64(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette);
+  boolean dmptx(uint8 *src, int width, int height, int rowStridePixel, uint16 gfmt, uint16 n64fmt, uint64 r_crc64);
+  boolean reloadhirestex();
+};
+
+#endif /* __TXFILTER_H__ */
diff --git a/source/gles2glide64/src/GlideHQ/TxFilterExport.cpp b/source/gles2glide64/src/GlideHQ/TxFilterExport.cpp
new file mode 100644 (file)
index 0000000..7639187
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef __MSC__
+#pragma warning(disable: 4786)
+#endif
+
+#include "TxFilter.h"
+
+TxFilter *txFilter = NULL;
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+TAPI boolean TAPIENTRY
+txfilter_init(int maxwidth, int maxheight, int maxbpp, int options, int cachesize,
+              wchar_t *datapath, wchar_t *cachepath, wchar_t*ident,
+              dispInfoFuncExt callback)
+{
+  if (txFilter) return 0;
+
+  txFilter = new TxFilter(maxwidth, maxheight, maxbpp, options, cachesize,
+                           datapath, cachepath, ident, callback);
+
+  return (txFilter ? 1 : 0);
+}
+
+TAPI void TAPIENTRY
+txfilter_shutdown(void)
+{
+  if (txFilter) delete txFilter;
+
+  txFilter = NULL;
+}
+
+TAPI boolean TAPIENTRY
+txfilter(uint8 *src, int srcwidth, int srcheight, uint16 srcformat,
+         uint64 g64crc, GHQTexInfo *info)
+{
+  if (txFilter)
+    return txFilter->filter(src, srcwidth, srcheight, srcformat,
+                               g64crc, info);
+
+  return 0;
+}
+
+TAPI boolean TAPIENTRY
+txfilter_hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *info)
+{
+  if (txFilter)
+    return txFilter->hirestex(g64crc, r_crc64, palette, info);
+
+  return 0;
+}
+
+TAPI uint64 TAPIENTRY
+txfilter_checksum(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette)
+{
+  if (txFilter)
+    return txFilter->checksum64(src, width, height, size, rowStride, palette);
+
+  return 0;
+}
+
+TAPI boolean TAPIENTRY
+txfilter_dmptx(uint8 *src, int width, int height, int rowStridePixel, uint16 gfmt, uint16 n64fmt, uint64 r_crc64)
+{
+  if (txFilter)
+    return txFilter->dmptx(src, width, height, rowStridePixel, gfmt, n64fmt, r_crc64);
+
+  return 0;
+}
+
+TAPI boolean TAPIENTRY
+txfilter_reloadhirestex()
+{
+  if (txFilter)
+    return txFilter->reloadhirestex();
+
+  return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/gles2glide64/src/GlideHQ/TxHiResCache.cpp b/source/gles2glide64/src/GlideHQ/TxHiResCache.cpp
new file mode 100644 (file)
index 0000000..a01dd5a
--- /dev/null
@@ -0,0 +1,1088 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* 2007 Gonetz <gonetz(at)ngs.ru>
+ * Added callback to display hires texture info. */
+
+#ifdef __MSC__
+#pragma warning(disable: 4786)
+#endif
+
+/* handle oversized textures by
+ *   0: minification
+ *   1: Glide64 style tiling
+ */
+#define TEXTURE_TILING 1
+
+/* use power of 2 texture size
+ * (0:disable, 1:enable, 2:3dfx) */
+#define POW2_TEXTURES 2
+
+#if TEXTURE_TILING
+#undef POW2_TEXTURES
+#define POW2_TEXTURES 2
+#endif
+
+/* hack to reduce texture footprint to achieve
+ * better performace on midrange gfx cards.
+ * (0:disable, 1:enable) */
+#define REDUCE_TEXTURE_FOOTPRINT 0
+
+/* use aggressive format assumption for quantization
+ * (0:disable, 1:enable, 2:extreme) */
+#define AGGRESSIVE_QUANTIZATION 1
+
+#include <zlib.h>
+#include <string>
+#include <SDL.h>
+#include "TxHiResCache.h"
+#include "TxDbg.h"
+#include "../Glide64/Gfx_1.3.h"
+
+TxHiResCache::~TxHiResCache()
+{
+#ifdef DUMP_CACHE
+  if ((_options & DUMP_HIRESTEXCACHE) && !_haveCache && !_abortLoad) {
+    /* dump cache to disk */
+    std::wstring filename = _ident + L"_HIRESTEXTURES.dat";
+    boost::filesystem::wpath cachepath(_cachepath);
+    cachepath /= boost::filesystem::wpath(L"glidehq");
+    int config = _options & (HIRESTEXTURES_MASK|COMPRESS_HIRESTEX|COMPRESSION_MASK|TILE_HIRESTEX|FORCE16BPP_HIRESTEX|GZ_HIRESTEXCACHE|LET_TEXARTISTS_FLY);
+
+    TxCache::save(cachepath.wstring().c_str(), filename.c_str(), config);
+  }
+#endif
+
+  delete _txImage;
+  delete _txQuantize;
+  delete _txReSample;
+}
+
+TxHiResCache::TxHiResCache(int maxwidth, int maxheight, int maxbpp, int options,
+                           const wchar_t *datapath, const wchar_t *cachepath,
+                           const wchar_t *ident, dispInfoFuncExt callback
+                           ) : TxCache((options & ~GZ_TEXCACHE), 0, datapath, cachepath, ident, callback)
+{
+  _txImage = new TxImage();
+  _txQuantize  = new TxQuantize();
+  _txReSample = new TxReSample();
+
+  _maxwidth  = maxwidth;
+  _maxheight = maxheight;
+  _maxbpp    = maxbpp;
+  _abortLoad = 0;
+  _haveCache = 0;
+
+  /* assert local options */
+  if (!(_options & COMPRESS_HIRESTEX))
+    _options &= ~COMPRESSION_MASK;
+
+  if (_cachepath.empty() || _ident.empty()) {
+    _options &= ~DUMP_HIRESTEXCACHE;
+    return;
+  }
+
+#ifdef DUMP_CACHE
+  /* read in hires texture cache */
+  if (_options & DUMP_HIRESTEXCACHE) {
+    /* find it on disk */
+    std::wstring filename = _ident + L"_HIRESTEXTURES.dat";
+    boost::filesystem::wpath cachepath(_cachepath);
+    cachepath /= boost::filesystem::wpath(L"glidehq");
+    int config = _options & (HIRESTEXTURES_MASK|COMPRESS_HIRESTEX|COMPRESSION_MASK|TILE_HIRESTEX|FORCE16BPP_HIRESTEX|GZ_HIRESTEXCACHE|LET_TEXARTISTS_FLY);
+
+    _haveCache = TxCache::load(cachepath.wstring().c_str(), filename.c_str(), config);
+  }
+#endif
+
+  /* read in hires textures */
+  if (!_haveCache) TxHiResCache::load(0);
+}
+
+boolean
+TxHiResCache::empty()
+{
+  return _cache.empty();
+}
+
+boolean
+TxHiResCache::load(boolean replace) /* 0 : reload, 1 : replace partial */
+{
+  if (!_datapath.empty() && !_ident.empty()) {
+
+    if (!replace) TxCache::clear();
+
+    boost::filesystem::wpath dir_path(_datapath);
+
+    switch (_options & HIRESTEXTURES_MASK) {
+    case GHQ_HIRESTEXTURES:
+      break;
+    case RICE_HIRESTEXTURES:
+      INFO(80, L"-----\n");
+      INFO(80, L"using Rice hires texture format...\n");
+      INFO(80, L"  must be one of the following;\n");
+      INFO(80, L"    1) *_rgb.png + *_a.png\n");
+      INFO(80, L"    2) *_all.png\n");
+      INFO(80, L"    3) *_ciByRGBA.png\n");
+      INFO(80, L"    4) *_allciByRGBA.png\n");
+      INFO(80, L"    5) *_ci.bmp\n");
+      INFO(80, L"  usage of only 2) and 3) highly recommended!\n");
+      INFO(80, L"  folder names must be in US-ASCII characters!\n");
+
+      dir_path /= boost::filesystem::wpath(L"hires_texture");
+      dir_path /= boost::filesystem::wpath(_ident);
+      loadHiResTextures(dir_path, replace);
+      break;
+    case JABO_HIRESTEXTURES:
+      ;
+    }
+
+    return 1;
+  }
+
+  return 0;
+}
+
+boolean
+TxHiResCache::loadHiResTextures(boost::filesystem::wpath dir_path, boolean replace)
+{
+  uint32_t last, now, diff;
+  DBG_INFO(80, L"-----\n");
+  DBG_INFO(80, L"path: %ls\n", dir_path.string().c_str());
+  last = SDL_GetTicks();
+
+  /* find it on disk */
+  if (!boost::filesystem::exists(dir_path)) {
+    INFO(80, L"Error: path not found!\n");
+    return 0;
+  }
+
+  /* XXX: deal with UNICODE fiasco!
+   * stupidity flows forth beneath this...
+   *
+   * I opted to use chdir in order to use fopen() for windows 9x.
+   */
+#ifdef WIN32
+  wchar_t curpath[MAX_PATH];
+  GETCWD(MAX_PATH, curpath);
+  CHDIR(dir_path.wstring().c_str());
+#else
+  char curpath[MAX_PATH];
+  char cbuf[MAX_PATH];
+  wcstombs(cbuf, dir_path.wstring().c_str(), MAX_PATH);
+  if (GETCWD(MAX_PATH, curpath) == NULL)
+      ERRLOG("Error while retrieving working directory!");
+  if (CHDIR(cbuf) != 0)
+      ERRLOG("Error while changing current directory to '%s'!", cbuf);
+#endif
+
+  /* NOTE: I could use the boost::wdirectory_iterator and boost::wpath
+   * to resolve UNICODE file names and paths. But then, _wfopen() is
+   * required to get the file descriptor for MS Windows to pass into
+   * libpng, which is incompatible with Win9x. Win9x's fopen() cannot
+   * handle UNICODE names. UNICODE capable boost::filesystem is available
+   * with Boost1.34.1 built with VC8.0 (bjam --toolset=msvc-8.0 stage).
+   *
+   * RULE OF THUMB: NEVER save texture packs in NON-ASCII names!!
+   */
+  boost::filesystem::directory_iterator it(dir_path);
+  boost::filesystem::directory_iterator end_it; /* default construction yields past-the-end */
+
+  for (; it != end_it; ++it) {
+
+    if (KBHIT(0x1B)) {
+      _abortLoad = 1;
+      if (_callback) (*_callback)(L"Aborted loading hiresolution texture!\n");
+      INFO(80, L"Error: aborted loading hiresolution texture!\n");
+    }
+    if (_abortLoad) break;
+
+    /* recursive read into sub-directory */
+    if (boost::filesystem::is_directory(it->status())) {
+      loadHiResTextures(it->path(), replace);
+      continue;
+    }
+
+    DBG_INFO(80, L"-----\n");
+    DBG_INFO(80, L"file: %ls\n", it->path().leaf().c_str());
+
+    int width = 0, height = 0;
+    uint16 format = 0;
+    uint8 *tex = NULL;
+    int tmpwidth = 0, tmpheight = 0;
+    uint16 tmpformat = 0;
+    uint8 *tmptex= NULL;
+    int untiled_width = 0, untiled_height = 0;
+    uint16 destformat = 0;
+
+    /* Rice hi-res textures: begin
+     */
+    uint32 chksum = 0, fmt = 0, siz = 0, palchksum = 0;
+    char *pfname = NULL, fname[MAX_PATH];
+    std::string ident;
+    FILE *fp = NULL;
+
+    wcstombs(fname, _ident.c_str(), MAX_PATH);
+    /* XXX case sensitivity fiasco!
+     * files must use _a, _rgb, _all, _allciByRGBA, _ciByRGBA, _ci
+     * and file extensions must be in lower case letters! */
+#ifdef WIN32
+    {
+      unsigned int i;
+      for (i = 0; i < strlen(fname); i++) fname[i] = tolower(fname[i]);
+    }
+#endif
+    ident.assign(fname);
+
+    /* read in Rice's file naming convention */
+#define CRCFMTSIZ_LEN 13
+#define PALCRC_LEN 9
+    //wcstombs(fname, it->path().leaf().c_str(), MAX_PATH);
+    strncpy(fname, it->path().leaf().string().c_str(), sizeof(fname));
+    fname[sizeof(fname) - 1] = '\0';
+    /* XXX case sensitivity fiasco!
+     * files must use _a, _rgb, _all, _allciByRGBA, _ciByRGBA, _ci
+     * and file extensions must be in lower case letters! */
+#ifdef WIN32
+    {
+      unsigned int i;
+      for (i = 0; i < strlen(fname); i++) fname[i] = tolower(fname[i]);
+    }
+#endif
+    pfname = fname + strlen(fname) - 4;
+    if (!(pfname == strstr(fname, ".png") ||
+          pfname == strstr(fname, ".bmp") ||
+          pfname == strstr(fname, ".dds"))) {
+#if !DEBUG
+      INFO(80, L"-----\n");
+      INFO(80, L"path: %ls\n", dir_path.string().c_str());
+      INFO(80, L"file: %ls\n", it->path().leaf().c_str());
+#endif
+      INFO(80, L"Error: not png or bmp or dds!\n");
+      continue;
+    }
+    pfname = strstr(fname, ident.c_str());
+    if (pfname != fname) pfname = 0;
+    if (pfname) {
+      if (sscanf(pfname + ident.size(), "#%08X#%01X#%01X#%08X", &chksum, &fmt, &siz, &palchksum) == 4)
+        pfname += (ident.size() + CRCFMTSIZ_LEN + PALCRC_LEN);
+      else if (sscanf(pfname + ident.size(), "#%08X#%01X#%01X", &chksum, &fmt, &siz) == 3)
+        pfname += (ident.size() + CRCFMTSIZ_LEN);
+      else
+        pfname = 0;
+    }
+    if (!pfname) {
+#if !DEBUG
+      INFO(80, L"-----\n");
+      INFO(80, L"path: %ls\n", dir_path.string().c_str());
+      INFO(80, L"file: %ls\n", it->path().leaf().c_str());
+#endif
+      INFO(80, L"Error: not Rice texture naming convention!\n");
+      continue;
+    }
+    if (!chksum) {
+#if !DEBUG
+      INFO(80, L"-----\n");
+      INFO(80, L"path: %ls\n", dir_path.string().c_str());
+      INFO(80, L"file: %ls\n", it->path().leaf().c_str());
+#endif
+      INFO(80, L"Error: crc32 = 0!\n");
+      continue;
+    }
+
+    /* check if we already have it in hires texture cache */
+    if (!replace) {
+      uint64 chksum64 = (uint64)palchksum;
+      chksum64 <<= 32;
+      chksum64 |= (uint64)chksum;
+      if (TxCache::is_cached(chksum64)) {
+#if !DEBUG
+        INFO(80, L"-----\n");
+        INFO(80, L"path: %ls\n", dir_path.string().c_str());
+        INFO(80, L"file: %ls\n", it->path().leaf().c_str());
+#endif
+        INFO(80, L"Error: already cached! duplicate texture!\n");
+        continue;
+      }
+    }
+
+    DBG_INFO(80, L"rom: %ls chksum:%08X %08X fmt:%x size:%x\n", _ident.c_str(), chksum, palchksum, fmt, siz);
+
+    /* Deal with the wackiness some texture packs utilize Rice format.
+     * Read in the following order: _a.* + _rgb.*, _all.png _ciByRGBA.png,
+     * _allciByRGBA.png, and _ci.bmp. PNG are prefered over BMP.
+     *
+     * For some reason there are texture packs that include them all. Some
+     * even have RGB textures named as _all.* and ARGB textures named as
+     * _rgb.*... Someone pleeeez write a GOOD guideline for the texture
+     * designers!!!
+     *
+     * We allow hires textures to have higher bpp than the N64 originals.
+     */
+    /* N64 formats
+     * Format: 0 - RGBA, 1 - YUV, 2 - CI, 3 - IA, 4 - I
+     * Size:   0 - 4bit, 1 - 8bit, 2 - 16bit, 3 - 32 bit
+     */
+
+    /*
+     * read in _rgb.* and _a.*
+     */
+    if (pfname == strstr(fname, "_rgb.") || pfname == strstr(fname, "_a.")) {
+      strcpy(pfname, "_rgb.png");
+      if (!boost::filesystem::exists(fname)) {
+        strcpy(pfname, "_rgb.bmp");
+        if (!boost::filesystem::exists(fname)) {
+#if !DEBUG
+          INFO(80, L"-----\n");
+          INFO(80, L"path: %ls\n", dir_path.string().c_str());
+          INFO(80, L"file: %ls\n", it->path().leaf().c_str());
+#endif
+          INFO(80, L"Error: missing _rgb.*! _a.* must be paired with _rgb.*!\n");
+          continue;
+        }
+      }
+      /* _a.png */
+      strcpy(pfname, "_a.png");
+      if ((fp = fopen(fname, "rb")) != NULL) {
+        tmptex = _txImage->readPNG(fp, &tmpwidth, &tmpheight, &tmpformat);
+        fclose(fp);
+      }
+      if (!tmptex) {
+        /* _a.bmp */
+        strcpy(pfname, "_a.bmp");
+        if ((fp = fopen(fname, "rb")) != NULL) {
+          tmptex = _txImage->readBMP(fp, &tmpwidth, &tmpheight, &tmpformat);
+          fclose(fp);
+        }
+      }
+      /* _rgb.png */
+      strcpy(pfname, "_rgb.png");
+      if ((fp = fopen(fname, "rb")) != NULL) {
+        tex = _txImage->readPNG(fp, &width, &height, &format);
+        fclose(fp);
+      }
+      if (!tex) {
+        /* _rgb.bmp */
+        strcpy(pfname, "_rgb.bmp");
+        if ((fp = fopen(fname, "rb")) != NULL) {
+          tex = _txImage->readBMP(fp, &width, &height, &format);
+          fclose(fp);
+        }
+      }
+      if (tmptex) {
+        /* check if _rgb.* and _a.* have matching size and format. */
+        if (!tex || width != tmpwidth || height != tmpheight ||
+            format != GR_TEXFMT_ARGB_8888 || tmpformat != GR_TEXFMT_ARGB_8888) {
+#if !DEBUG
+          INFO(80, L"-----\n");
+          INFO(80, L"path: %ls\n", dir_path.string().c_str());
+          INFO(80, L"file: %ls\n", it->path().leaf().c_str());
+#endif
+          if (!tex) {
+            INFO(80, L"Error: missing _rgb.*!\n");
+          } else if (width != tmpwidth || height != tmpheight) {
+            INFO(80, L"Error: _rgb.* and _a.* have mismatched width or height!\n");
+          } else if (format != GR_TEXFMT_ARGB_8888 || tmpformat != GR_TEXFMT_ARGB_8888) {
+            INFO(80, L"Error: _rgb.* or _a.* not in 32bit color!\n");
+          }
+          if (tex) free(tex);
+          if (tmptex) free(tmptex);
+          tex = NULL;
+          tmptex = NULL;
+          continue;
+        }
+      }
+      /* make adjustments */
+      if (tex) {
+        if (tmptex) {
+          /* merge (A)RGB and A comp */
+          DBG_INFO(80, L"merge (A)RGB and A comp\n");
+          int i;
+          for (i = 0; i < height * width; i++) {
+#if 1
+            /* use R comp for alpha. this is what Rice uses. sigh... */
+            ((uint32*)tex)[i] &= 0x00ffffff;
+            ((uint32*)tex)[i] |= ((((uint32*)tmptex)[i] & 0x00ff0000) << 8);
+#endif
+#if 0
+            /* use libpng style grayscale conversion */
+            uint32 texel = ((uint32*)tmptex)[i];
+            uint32 acomp = (((texel >> 16) & 0xff) * 6969 +
+                            ((texel >>  8) & 0xff) * 23434 +
+                            ((texel      ) & 0xff) * 2365) / 32768;
+            ((uint32*)tex)[i] = (acomp << 24) | (((uint32*)tex)[i] & 0x00ffffff);
+#endif
+#if 0
+            /* use the standard NTSC gray scale conversion */
+            uint32 texel = ((uint32*)tmptex)[i];
+            uint32 acomp = (((texel >> 16) & 0xff) * 299 +
+                            ((texel >>  8) & 0xff) * 587 +
+                            ((texel      ) & 0xff) * 114) / 1000;
+            ((uint32*)tex)[i] = (acomp << 24) | (((uint32*)tex)[i] & 0x00ffffff);
+#endif
+          }
+          free(tmptex);
+          tmptex = NULL;
+        } else {
+          /* clobber A comp. never a question of alpha. only RGB used. */
+#if !DEBUG
+          INFO(80, L"-----\n");
+          INFO(80, L"path: %ls\n", dir_path.string().c_str());
+          INFO(80, L"file: %ls\n", it->path().leaf().c_str());
+#endif
+          INFO(80, L"Warning: missing _a.*! only using _rgb.*. treat as opaque texture.\n");
+          int i;
+          for (i = 0; i < height * width; i++) {
+            ((uint32*)tex)[i] |= 0xff000000;
+          }
+        }
+      }
+    } else
+
+    /*
+     * read in _all.png, _all.dds, _allciByRGBA.png, _allciByRGBA.dds
+     * _ciByRGBA.png, _ciByRGBA.dds, _ci.bmp
+     */
+    if (pfname == strstr(fname, "_all.png") ||
+        pfname == strstr(fname, "_all.dds") ||
+#ifdef WIN32
+        pfname == strstr(fname, "_allcibyrgba.png") ||
+        pfname == strstr(fname, "_allcibyrgba.dds") ||
+        pfname == strstr(fname, "_cibyrgba.png") ||
+        pfname == strstr(fname, "_cibyrgba.dds") ||
+#else
+        pfname == strstr(fname, "_allciByRGBA.png") ||
+        pfname == strstr(fname, "_allciByRGBA.dds") ||
+        pfname == strstr(fname, "_ciByRGBA.png") ||
+        pfname == strstr(fname, "_ciByRGBA.dds") ||
+#endif
+        pfname == strstr(fname, "_ci.bmp")) {
+      if ((fp = fopen(fname, "rb")) != NULL) {
+        if      (strstr(fname, ".png")) tex = _txImage->readPNG(fp, &width, &height, &format);
+        else if (strstr(fname, ".dds")) tex = _txImage->readDDS(fp, &width, &height, &format);
+        else                            tex = _txImage->readBMP(fp, &width, &height, &format);
+        fclose(fp);
+      }
+      /* XXX: auto-adjustment of dxt dds textures unsupported for now */
+      if (tex && strstr(fname, ".dds")) {
+        const float aspectratio = (width > height) ? (float)width/(float)height : (float)height/(float)width;
+        if (!(aspectratio == 1.0 ||
+              aspectratio == 2.0 ||
+              aspectratio == 4.0 ||
+              aspectratio == 8.0)) {
+          free(tex);
+          tex = NULL;
+#if !DEBUG
+          INFO(80, L"-----\n");
+          INFO(80, L"path: %ls\n", dir_path.string().c_str());
+          INFO(80, L"file: %ls\n", it->path().leaf().c_str());
+#endif
+          INFO(80, L"Error: W:H aspect ratio range not 8:1 - 1:8!\n");
+          continue;
+        }
+        if (width  != _txReSample->nextPow2(width) ||
+            height != _txReSample->nextPow2(height)) {
+          free(tex);
+          tex = NULL;
+#if !DEBUG
+          INFO(80, L"-----\n");
+          INFO(80, L"path: %ls\n", dir_path.string().c_str());
+          INFO(80, L"file: %ls\n", it->path().leaf().c_str());
+#endif
+          INFO(80, L"Error: not power of 2 size!\n");
+          continue;
+        }
+      }
+    }
+
+    /* if we do not have a texture at this point we are screwed */
+    if (!tex) {
+#if !DEBUG
+      INFO(80, L"-----\n");
+      INFO(80, L"path: %ls\n", dir_path.string().c_str());
+      INFO(80, L"file: %ls\n", it->path().leaf().c_str());
+#endif
+      INFO(80, L"Error: load failed!\n");
+      continue;
+    }
+    DBG_INFO(80, L"read in as %d x %d gfmt:%x\n", tmpwidth, tmpheight, tmpformat);
+
+    /* check if size and format are OK */
+    if (!(format == GR_TEXFMT_ARGB_8888     ||
+          format == GR_TEXFMT_P_8           ||
+          format == GR_TEXFMT_ARGB_CMP_DXT1 ||
+          format == GR_TEXFMT_ARGB_CMP_DXT3 ||
+          format == GR_TEXFMT_ARGB_CMP_DXT5) ||
+        (width * height) < 4) { /* TxQuantize requirement: width * height must be 4 or larger. */
+      free(tex);
+      tex = NULL;
+#if !DEBUG
+      INFO(80, L"-----\n");
+      INFO(80, L"path: %ls\n", dir_path.string().c_str());
+      INFO(80, L"file: %ls\n", it->path().leaf().c_str());
+#endif
+      INFO(80, L"Error: not width * height > 4 or 8bit palette color or 32bpp or dxt1 or dxt3 or dxt5!\n");
+      continue;
+    }
+
+    /* analyze and determine best format to quantize */
+    if (format == GR_TEXFMT_ARGB_8888) {
+      int i;
+      int alphabits = 0;
+      int fullalpha = 0;
+      boolean intensity = 1;
+
+      if (!(_options & LET_TEXARTISTS_FLY)) {
+        /* HACK ALERT! */
+        /* Account for Rice's weirdness with fmt:0 siz:2 textures.
+         * Although the conditions are relaxed with other formats,
+         * the D3D RGBA5551 surface is used for this format in certain
+         * cases. See Nintemod's SuperMario64 life gauge and power
+         * meter. The same goes for fmt:2 textures. See Mollymutt's
+         * PaperMario text. */
+        if ((fmt == 0 && siz == 2) || fmt == 2) {
+          DBG_INFO(80, L"Remove black, white, etc borders along the alpha edges.\n");
+          /* round A comp */
+          for (i = 0; i < height * width; i++) {
+            uint32 texel = ((uint32*)tex)[i];
+            ((uint32*)tex)[i] = ((texel & 0xff000000) == 0xff000000 ? 0xff000000 : 0) |
+                                (texel & 0x00ffffff);
+          }
+          /* Substitute texel color with the average of the surrounding
+           * opaque texels. This removes borders regardless of hardware
+           * texture filtering (bilinear, etc). */
+          int j;
+          for (i = 0; i < height; i++) {
+            for (j = 0; j < width; j++) {
+              uint32 texel = ((uint32*)tex)[i * width + j];
+              if ((texel & 0xff000000) != 0xff000000) {
+                uint32 tmptexel[8];
+                uint32 k, numtexel, r, g, b;
+                numtexel = r = g = b = 0;
+                memset(&tmptexel, 0, sizeof(tmptexel));
+                if (i > 0) {
+                  tmptexel[0] = ((uint32*)tex)[(i - 1) * width + j];                        /* north */
+                  if (j > 0)         tmptexel[1] = ((uint32*)tex)[(i - 1) * width + j - 1]; /* north-west */
+                  if (j < width - 1) tmptexel[2] = ((uint32*)tex)[(i - 1) * width + j + 1]; /* north-east */
+                }
+                if (i < height - 1) {
+                  tmptexel[3] = ((uint32*)tex)[(i + 1) * width + j];                        /* south */
+                  if (j > 0)         tmptexel[4] = ((uint32*)tex)[(i + 1) * width + j - 1]; /* south-west */
+                  if (j < width - 1) tmptexel[5] = ((uint32*)tex)[(i + 1) * width + j + 1]; /* south-east */
+                }
+                if (j > 0)         tmptexel[6] = ((uint32*)tex)[i * width + j - 1]; /* west */
+                if (j < width - 1) tmptexel[7] = ((uint32*)tex)[i * width + j + 1]; /* east */
+                for (k = 0; k < 8; k++) {
+                  if ((tmptexel[k] & 0xff000000) == 0xff000000) {
+                    r += ((tmptexel[k] & 0x00ff0000) >> 16);
+                    g += ((tmptexel[k] & 0x0000ff00) >>  8);
+                    b += ((tmptexel[k] & 0x000000ff)      );
+                    numtexel++;
+                  }
+                }
+                if (numtexel) {
+                  ((uint32*)tex)[i * width + j] = ((r / numtexel) << 16) |
+                                                  ((g / numtexel) <<  8) |
+                                                  ((b / numtexel)      );
+                } else {
+                  ((uint32*)tex)[i * width + j] = texel & 0x00ffffff;
+                }
+              }
+            }
+          }
+        }
+      }
+
+      /* simple analysis of texture */
+      for (i = 0; i < height * width; i++) {
+        uint32 texel = ((uint32*)tex)[i];
+        if (alphabits != 8) {
+#if AGGRESSIVE_QUANTIZATION
+          if ((texel & 0xff000000) < 0x00000003) {
+            alphabits = 1;
+            fullalpha++;
+          } else if ((texel & 0xff000000) < 0xfe000000) {
+            alphabits = 8;
+          }
+#else
+          if ((texel & 0xff000000) == 0x00000000) {
+            alphabits = 1;
+            fullalpha++;
+          } else if ((texel & 0xff000000) != 0xff000000) {
+            alphabits = 8;
+          }
+#endif
+        }
+        if (intensity) {
+          int rcomp = (texel >> 16) & 0xff;
+          int gcomp = (texel >>  8) & 0xff;
+          int bcomp = (texel      ) & 0xff;
+#if AGGRESSIVE_QUANTIZATION
+          if (abs(rcomp - gcomp) > 8 || abs(rcomp - bcomp) > 8 || abs(gcomp - bcomp) > 8) intensity = 0;
+#else
+          if (rcomp != gcomp || rcomp != bcomp || gcomp != bcomp) intensity = 0;
+#endif
+        }
+        if (!intensity && alphabits == 8) break;
+      }
+      DBG_INFO(80, L"required alpha bits:%d zero acomp texels:%d rgb as intensity:%d\n", alphabits, fullalpha, intensity);
+
+      /* preparations based on above analysis */
+#if !REDUCE_TEXTURE_FOOTPRINT
+      if (_maxbpp < 32 || _options & (FORCE16BPP_HIRESTEX|COMPRESSION_MASK)) {
+#endif
+        if      (alphabits == 0) destformat = GR_TEXFMT_RGB_565;
+        else if (alphabits == 1) destformat = GR_TEXFMT_ARGB_1555;
+        else                     destformat = GR_TEXFMT_ARGB_8888;
+#if !REDUCE_TEXTURE_FOOTPRINT
+      } else {
+        destformat = GR_TEXFMT_ARGB_8888;
+      }
+#endif
+      if (fmt == 4 && alphabits == 0) {
+        destformat = GR_TEXFMT_ARGB_8888;
+        /* Rice I format; I = (R + G + B) / 3 */
+        for (i = 0; i < height * width; i++) {
+          uint32 texel = ((uint32*)tex)[i];
+          uint32 icomp = (((texel >> 16) & 0xff) +
+                          ((texel >>  8) & 0xff) +
+                          ((texel      ) & 0xff)) / 3;
+          ((uint32*)tex)[i] = (icomp << 24) | (texel & 0x00ffffff);
+        }
+      }
+      if (intensity) {
+        if (alphabits == 0) {
+          if (fmt == 4) destformat = GR_TEXFMT_ALPHA_8;
+          else          destformat = GR_TEXFMT_INTENSITY_8;
+        } else {
+          destformat = GR_TEXFMT_ALPHA_INTENSITY_88;
+        }
+      }
+
+      DBG_INFO(80, L"best gfmt:%x\n", destformat);
+    }
+    /*
+     * Rice hi-res textures: end */
+
+
+    /* XXX: only ARGB8888 for now. comeback to this later... */
+    if (format == GR_TEXFMT_ARGB_8888) {
+
+#if TEXTURE_TILING
+
+      /* Glide64 style texture tiling */
+      /* NOTE: narrow wide textures can be tiled into 256x256 size textures */
+
+      /* adjust texture size to allow tiling for V1, Rush, V2, Banshee, V3 */
+      /* NOTE: we skip this for palette textures that need minification
+       * becasue it will look ugly. */
+
+      /* minification */
+      {
+        int ratio = 1;
+
+        /* minification to enable glide64 style texture tiling */
+        /* determine the minification ratio to tile the texture into 256x256 size */
+        if ((_options & TILE_HIRESTEX) && _maxwidth >= 256 && _maxheight >= 256) {
+          DBG_INFO(80, L"determine minification ratio to tile\n");
+          tmpwidth = width;
+          tmpheight = height;
+          if (height > 256) {
+            ratio = ((height - 1) >> 8) + 1;
+            tmpwidth = width / ratio;
+            tmpheight = height / ratio;
+            DBG_INFO(80, L"height > 256, minification ratio:%d %d x %d -> %d x %d\n",
+                     ratio, width, height, tmpwidth, tmpheight);
+          }
+          if (tmpwidth > 256 && (((tmpwidth - 1) >> 8) + 1) * tmpheight > 256) {
+            ratio *= ((((((tmpwidth - 1) >> 8) + 1) * tmpheight) - 1) >> 8) + 1;
+            DBG_INFO(80, L"width > 256, minification ratio:%d %d x %d -> %d x %d\n",
+                     ratio, width, height, width / ratio, height / ratio);
+          }
+        } else {
+          /* normal minification to fit max texture size */
+          if (width > _maxwidth || height > _maxheight) {
+            DBG_INFO(80, L"determine minification ratio to fit max texture size\n");
+            tmpwidth = width;
+            tmpheight = height;
+            while (tmpwidth > _maxwidth) {
+              tmpheight >>= 1;
+              tmpwidth >>= 1;
+              ratio <<= 1;
+            }
+            while (tmpheight > _maxheight) {
+              tmpheight >>= 1;
+              tmpwidth >>= 1;
+              ratio <<= 1;
+            }
+            DBG_INFO(80, L"minification ratio:%d %d x %d -> %d x %d\n",
+                     ratio, width, height, tmpwidth, tmpheight);
+          }
+        }
+
+        if (ratio > 1) {
+          if (!_txReSample->minify(&tex, &width, &height, ratio)) {
+            free(tex);
+            tex = NULL;
+            DBG_INFO(80, L"Error: minification failed!\n");
+            continue;
+          }
+        }
+      }
+
+      /* tiling */
+      if ((_options & TILE_HIRESTEX) && _maxwidth >= 256 && _maxheight >= 256) {
+        boolean usetile = 0;
+
+        /* to tile or not to tile, that is the question */
+        if (width > 256 && height <= 128 && (((width - 1) >> 8) + 1) * height <= 256) {
+
+          if (width > _maxwidth) usetile = 1;
+          else {
+            /* tile if the tiled texture memory footprint is smaller */
+            int tilewidth  = 256;
+            int tileheight = _txReSample->nextPow2((((width - 1) >> 8) + 1) * height);
+            tmpwidth  = width;
+            tmpheight = height;
+
+            /* 3dfx Glide3 tmpheight, W:H aspect ratio range (8:1 - 1:8) */
+            if (tilewidth > (tileheight << 3)) tileheight = tilewidth >> 3;
+
+            /* HACKALERT: see TxReSample::pow2(); */
+            if      (tmpwidth  > 64) tmpwidth  -= 4;
+            else if (tmpwidth  > 16) tmpwidth  -= 2;
+            else if (tmpwidth  >  4) tmpwidth  -= 1;
+
+            if      (tmpheight > 64) tmpheight -= 4;
+            else if (tmpheight > 16) tmpheight -= 2;
+            else if (tmpheight >  4) tmpheight -= 1;
+
+            tmpwidth  = _txReSample->nextPow2(tmpwidth);
+            tmpheight = _txReSample->nextPow2(tmpheight);
+
+            /* 3dfx Glide3 tmpheight, W:H aspect ratio range (8:1 - 1:8) */
+            if (tmpwidth > tmpheight) {
+              if (tmpwidth  > (tmpheight << 3)) tmpheight = tmpwidth  >> 3;
+            } else {
+              if (tmpheight > (tmpwidth  << 3)) tmpwidth  = tmpheight >> 3;
+            }
+
+            usetile = (tilewidth * tileheight < tmpwidth * tmpheight);
+          }
+
+        }
+
+        /* tile it! do the actual tiling into 256x256 size */
+        if (usetile) {
+          DBG_INFO(80, L"Glide64 style texture tiling\n");
+
+          int x, y, z, ratio, offset;
+          offset = 0;
+          ratio = ((width - 1) >> 8) + 1;
+          tmptex = (uint8 *)malloc(_txUtil->sizeofTx(256, height * ratio, format));
+          if (tmptex) {
+            for (x = 0; x < ratio; x++) {
+              for (y = 0; y < height; y++) {
+                if (x < ratio - 1) {
+                  memcpy(&tmptex[offset << 2], &tex[(x * 256 + y * width) << 2], 256 << 2);
+                } else {
+                  for (z = 0; z < width - 256 * (ratio - 1); z++) {
+                    ((uint32*)tmptex)[offset + z] = ((uint32*)tex)[x * 256 + y * width + z];
+                  }
+                  for (; z < 256; z++) {
+                    ((uint32*)tmptex)[offset + z] = ((uint32*)tmptex)[offset + z - 1];
+                  }
+                }
+                offset += 256;
+              }
+            }
+            free(tex);
+            tex = tmptex;
+            untiled_width = width;
+            untiled_height = height;
+            width = 256;
+            height *= ratio;
+            DBG_INFO(80, L"Tiled: %d x %d -> %d x %d\n", untiled_width, untiled_height, width, height);
+          }
+        }
+      }
+
+#else  /* TEXTURE_TILING */
+
+      /* minification */
+      if (width > _maxwidth || height > _maxheight) {
+        int ratio = 1;
+        if (width / _maxwidth > height / _maxheight) {
+          ratio = (int)ceil((double)width / _maxwidth);
+        } else {
+          ratio = (int)ceil((double)height / _maxheight);
+        }
+        if (!_txReSample->minify(&tex, &width, &height, ratio)) {
+          free(tex);
+          tex = NULL;
+          DBG_INFO(80, L"Error: minification failed!\n");
+          continue;
+        }
+      }
+
+#endif /* TEXTURE_TILING */
+
+      /* texture compression */
+      if ((_options & COMPRESSION_MASK) &&
+          (width >= 64 && height >= 64) /* Texture compression is not suitable for low pixel coarse detail
+                                         * textures. The assumption here is that textures larger than 64x64
+                                         * have enough detail to produce decent quality when compressed. The
+                                         * down side is that narrow stripped textures that the N64 often use
+                                         * for large background textures are also ignored. It would be more
+                                         * reasonable if decisions are made based on fourier-transform
+                                         * spectrum or RMS error.
+                                         *
+                                         * NOTE: texture size must be checked before expanding to pow2 size.
+                                         */
+          ) {
+        int dataSize = 0;
+        int compressionType = _options & COMPRESSION_MASK;
+
+#if POW2_TEXTURES
+#if (POW2_TEXTURES == 2)
+        /* 3dfx Glide3x aspect ratio (8:1 - 1:8) */
+        if (!_txReSample->nextPow2(&tex, &width , &height, 32, 1)) {
+#else
+        /* normal pow2 expansion */
+        if (!_txReSample->nextPow2(&tex, &width , &height, 32, 0)) {
+#endif
+          free(tex);
+          tex = NULL;
+          DBG_INFO(80, L"Error: aspect ratio adjustment failed!\n");
+          continue;
+        }
+#endif
+
+        switch (_options & COMPRESSION_MASK) {
+        case S3TC_COMPRESSION:
+          switch (destformat) {
+          case GR_TEXFMT_ARGB_8888:
+#if GLIDE64_DXTN
+          case GR_TEXFMT_ARGB_1555: /* for ARGB1555 use DXT5 instead of DXT1 */
+#endif
+          case GR_TEXFMT_ALPHA_INTENSITY_88:
+            dataSize = width * height;
+            break;
+#if !GLIDE64_DXTN
+          case GR_TEXFMT_ARGB_1555:
+#endif
+          case GR_TEXFMT_RGB_565:
+          case GR_TEXFMT_INTENSITY_8:
+            dataSize = (width * height) >> 1;
+            break;
+          case GR_TEXFMT_ALPHA_8: /* no size benefit with dxtn */
+            ;
+          }
+          break;
+        case FXT1_COMPRESSION:
+          switch (destformat) {
+          case GR_TEXFMT_ARGB_1555:
+          case GR_TEXFMT_RGB_565:
+          case GR_TEXFMT_INTENSITY_8:
+            dataSize = (width * height) >> 1;
+            break;
+            /* XXX: textures that use 8bit alpha channel look bad with the current
+             * fxt1 library, so we substitute it with dxtn for now. afaik all gfx
+             * cards that support fxt1 also support dxtn. (3dfx and Intel) */
+          case GR_TEXFMT_ALPHA_INTENSITY_88:
+          case GR_TEXFMT_ARGB_8888:
+            compressionType = S3TC_COMPRESSION;
+            dataSize = width * height;
+            break;
+          case GR_TEXFMT_ALPHA_8: /* no size benefit with dxtn */
+            ;
+          }
+        }
+        /* compress it! */
+        if (dataSize) {
+#if 0 /* TEST: dither before compression for better results with gradients */
+          tmptex = (uint8 *)malloc(_txUtil->sizeofTx(width, height, destformat));
+          if (tmptex) {
+            if (_txQuantize->quantize(tex, tmptex, width, height, GR_TEXFMT_ARGB_8888, destformat, 0))
+              _txQuantize->quantize(tmptex, tex, width, height, destformat, GR_TEXFMT_ARGB_8888, 0);
+            free(tmptex);
+          }
+#endif
+          tmptex = (uint8 *)malloc(dataSize);
+          if (tmptex) {
+            if (_txQuantize->compress(tex, tmptex,
+                                      width, height, destformat,
+                                      &tmpwidth, &tmpheight, &tmpformat,
+                                      compressionType)) {
+              free(tex);
+              tex = tmptex;
+              width = tmpwidth;
+              height = tmpheight;
+              format = destformat = tmpformat;
+            } else {
+              free(tmptex);
+            }
+          }
+        }
+
+      } else {
+
+#if POW2_TEXTURES
+#if (POW2_TEXTURES == 2)
+        /* 3dfx Glide3x aspect ratio (8:1 - 1:8) */
+        if (!_txReSample->nextPow2(&tex, &width , &height, 32, 1)) {
+#else
+        /* normal pow2 expansion */
+        if (!_txReSample->nextPow2(&tex, &width , &height, 32, 0)) {
+#endif
+          free(tex);
+          tex = NULL;
+          DBG_INFO(80, L"Error: aspect ratio adjustment failed!\n");
+          continue;
+        }
+#endif
+      }
+
+      /* quantize */
+      {
+        tmptex = (uint8 *)malloc(_txUtil->sizeofTx(width, height, destformat));
+        if (tmptex) {
+          switch (destformat) {
+          case GR_TEXFMT_ARGB_8888:
+          case GR_TEXFMT_ARGB_4444:
+#if !REDUCE_TEXTURE_FOOTPRINT
+            if (_maxbpp < 32 || _options & FORCE16BPP_HIRESTEX)
+#endif
+              destformat = GR_TEXFMT_ARGB_4444;
+            break;
+          case GR_TEXFMT_ARGB_1555:
+#if !REDUCE_TEXTURE_FOOTPRINT
+            if (_maxbpp < 32 || _options & FORCE16BPP_HIRESTEX)
+#endif
+              destformat = GR_TEXFMT_ARGB_1555;
+            break;
+          case GR_TEXFMT_RGB_565:
+#if !REDUCE_TEXTURE_FOOTPRINT
+            if (_maxbpp < 32 || _options & FORCE16BPP_HIRESTEX)
+#endif
+              destformat = GR_TEXFMT_RGB_565;
+            break;
+          case GR_TEXFMT_ALPHA_INTENSITY_88:
+          case GR_TEXFMT_ALPHA_INTENSITY_44:
+#if !REDUCE_TEXTURE_FOOTPRINT
+            destformat = GR_TEXFMT_ALPHA_INTENSITY_88;
+#else
+            destformat = GR_TEXFMT_ALPHA_INTENSITY_44;
+#endif
+            break;
+          case GR_TEXFMT_ALPHA_8:
+            destformat = GR_TEXFMT_ALPHA_8; /* yes, this is correct. ALPHA_8 instead of INTENSITY_8 */
+            break;
+          case GR_TEXFMT_INTENSITY_8:
+            destformat = GR_TEXFMT_INTENSITY_8;
+          }
+          if (_txQuantize->quantize(tex, tmptex, width, height, GR_TEXFMT_ARGB_8888, destformat, 0)) {
+            format = destformat;
+            free(tex);
+            tex = tmptex;
+          }
+        }
+      }
+
+    }
+
+
+    /* last minute validations */
+    if (!tex || !chksum || !width || !height || !format || width > _maxwidth || height > _maxheight) {
+#if !DEBUG
+      INFO(80, L"-----\n");
+      INFO(80, L"path: %ls\n", dir_path.string().c_str());
+      INFO(80, L"file: %ls\n", it->path().leaf().c_str());
+#endif
+      if (tex) {
+        free(tex);
+        tex = NULL;
+        INFO(80, L"Error: bad format or size! %d x %d gfmt:%x\n", width, height, format);
+      } else {
+        INFO(80, L"Error: load failed!!\n");
+      }
+      continue;
+    }
+
+    /* load it into hires texture cache. */
+    {
+      uint64 chksum64 = (uint64)palchksum;
+      chksum64 <<= 32;
+      chksum64 |= (uint64)chksum;
+
+      GHQTexInfo tmpInfo;
+      memset(&tmpInfo, 0, sizeof(GHQTexInfo));
+
+      tmpInfo.data = tex;
+      tmpInfo.width = width;
+      tmpInfo.height = height;
+      tmpInfo.format = format;
+      tmpInfo.largeLodLog2 = _txUtil->grLodLog2(width, height);
+      tmpInfo.smallLodLog2 = tmpInfo.largeLodLog2;
+      tmpInfo.aspectRatioLog2 = _txUtil->grAspectRatioLog2(width, height);
+      tmpInfo.is_hires_tex = 1;
+
+#if TEXTURE_TILING
+      /* Glide64 style texture tiling. */
+      if (untiled_width && untiled_height) {
+        tmpInfo.tiles = ((untiled_width - 1) >> 8) + 1;
+        tmpInfo.untiled_width = untiled_width;
+        tmpInfo.untiled_height = untiled_height;
+      }
+#endif
+
+      /* remove redundant in cache */
+      if (replace && TxCache::del(chksum64)) {
+        DBG_INFO(80, L"removed duplicate old cache.\n");
+      }
+
+      /* add to cache */
+      if (TxCache::add(chksum64, &tmpInfo)) {
+        now = SDL_GetTicks();
+        diff = now - last;
+
+        /* Callback to display hires texture info.
+         * Gonetz <gonetz(at)ngs.ru> */
+        if (_callback && diff > 250) {
+          wchar_t tmpbuf[MAX_PATH];
+          mbstowcs(tmpbuf, fname, MAX_PATH);
+          (*_callback)(L"[%d] total mem:%.2fmb - %ls\n", _cache.size(), (float)_totalSize/1000000, tmpbuf);
+          last = now;
+        }
+        DBG_INFO(80, L"texture loaded!\n");
+      }
+      free(tex);
+    }
+
+  }
+
+  if (CHDIR(curpath) != 0)
+      ERRLOG("Error while changing current directory back to original path of '%s'!", curpath);
+
+  return 1;
+}
diff --git a/source/gles2glide64/src/GlideHQ/TxHiResCache.h b/source/gles2glide64/src/GlideHQ/TxHiResCache.h
new file mode 100644 (file)
index 0000000..d2094fe
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __TXHIRESCACHE_H__
+#define __TXHIRESCACHE_H__
+
+/* support hires textures
+ *   0: disable
+ *   1: enable
+ */
+#define HIRES_TEXTURE 1
+
+#include "TxCache.h"
+#include "TxQuantize.h"
+#include "TxImage.h"
+#include "TxReSample.h"
+#include <boost/filesystem.hpp>
+
+class TxHiResCache : public TxCache
+{
+private:
+  int _maxwidth;
+  int _maxheight;
+  int _maxbpp;
+  boolean _haveCache;
+  boolean _abortLoad;
+  TxImage *_txImage;
+  TxQuantize *_txQuantize;
+  TxReSample *_txReSample;
+  boolean loadHiResTextures(boost::filesystem::wpath dir_path, boolean replace);
+public:
+  ~TxHiResCache();
+  TxHiResCache(int maxwidth, int maxheight, int maxbpp, int options,
+               const wchar_t *datapath, const wchar_t *cachepath,
+               const wchar_t *ident, dispInfoFuncExt callback);
+  boolean empty();
+  boolean load(boolean replace);
+};
+
+#endif /* __TXHIRESCACHE_H__ */
diff --git a/source/gles2glide64/src/GlideHQ/TxImage.cpp b/source/gles2glide64/src/GlideHQ/TxImage.cpp
new file mode 100644 (file)
index 0000000..c8fbf07
--- /dev/null
@@ -0,0 +1,805 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* use power of 2 texture size
+ * (0:disable, 1:enable, 2:3dfx) */
+#define POW2_TEXTURES 0
+
+/* check 8 bytes. use a larger value if needed. */
+#define PNG_CHK_BYTES 8
+
+#include "TxImage.h"
+#include "TxReSample.h"
+#include "TxDbg.h"
+#include <stdlib.h>
+#include "../Glide64/Gfx_1.3.h"
+
+boolean
+TxImage::getPNGInfo(FILE *fp, png_structp *png_ptr, png_infop *info_ptr)
+{
+  unsigned char sig[PNG_CHK_BYTES];
+
+  /* check for valid file pointer */
+  if (!fp)
+    return 0;
+
+  /* check if file is PNG */
+  if (fread(sig, 1, PNG_CHK_BYTES, fp) != PNG_CHK_BYTES)
+    return 0;
+
+  if (png_sig_cmp(sig, 0, PNG_CHK_BYTES) != 0)
+    return 0;
+
+  /* get PNG file info */
+  *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+  if (!*png_ptr)
+    return 0;
+
+  *info_ptr = png_create_info_struct(*png_ptr);
+  if (!*info_ptr) {
+    png_destroy_read_struct(png_ptr, NULL, NULL);
+    return 0;
+  }
+
+  if (setjmp(png_jmpbuf(*png_ptr))) {
+    DBG_INFO(80, L"error reading png!\n");
+    png_destroy_read_struct(png_ptr, info_ptr, NULL);
+    return 0;
+  }
+
+  png_init_io(*png_ptr, fp);
+  png_set_sig_bytes(*png_ptr, PNG_CHK_BYTES);
+  png_read_info(*png_ptr, *info_ptr);
+
+  return 1;
+}
+
+uint8*
+TxImage::readPNG(FILE* fp, int* width, int* height, uint16* format)
+{
+  /* NOTE: returned image format is GR_TEXFMT_ARGB_8888 */
+
+  png_structp png_ptr;
+  png_infop info_ptr;
+  uint8 *image = NULL;
+  int bit_depth, color_type, interlace_type, compression_type, filter_type,
+      row_bytes, o_width, o_height, num_pas;
+
+  /* initialize */
+  *width  = 0;
+  *height = 0;
+  *format = 0;
+
+  /* check if we have a valid png file */
+  if (!fp)
+    return NULL;
+
+  if (!getPNGInfo(fp, &png_ptr, &info_ptr)) {
+    INFO(80, L"error reading png file! png image is corrupt.\n");
+    return NULL;
+  }
+
+  png_get_IHDR(png_ptr, info_ptr,
+               (png_uint_32*)&o_width, (png_uint_32*)&o_height, &bit_depth, &color_type,
+               &interlace_type, &compression_type, &filter_type);
+
+  DBG_INFO(80, L"png format %d x %d bitdepth:%d color:%x interlace:%x compression:%x filter:%x\n",
+           o_width, o_height, bit_depth, color_type,
+           interlace_type, compression_type, filter_type);
+
+  /* transformations */
+
+  /* Rice hi-res textures
+   * _all.png
+   * _rgb.png, _a.png
+   * _ciByRGBA.png
+   * _allciByRGBA.png
+   */
+
+  /* strip if color channel is larger than 8 bits */
+  if (bit_depth > 8) {
+    png_set_strip_16(png_ptr);
+    bit_depth = 8;
+  }
+
+#if 1
+  /* These are not really required per Rice format spec,
+   * but is done just in case someone uses them.
+   */
+  /* convert palette color to rgb color */
+  if (color_type == PNG_COLOR_TYPE_PALETTE) {
+    png_set_palette_to_rgb(png_ptr);
+    color_type = PNG_COLOR_TYPE_RGB;
+  }
+
+  /* expand 1,2,4 bit gray scale to 8 bit gray scale */
+  if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
+    png_set_expand_gray_1_2_4_to_8(png_ptr);
+
+  /* convert gray scale or gray scale + alpha to rgb color */
+  if (color_type == PNG_COLOR_TYPE_GRAY ||
+      color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
+    png_set_gray_to_rgb(png_ptr);
+    color_type = PNG_COLOR_TYPE_RGB;
+  }
+#endif
+
+  /* add alpha channel if any */
+  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
+    png_set_tRNS_to_alpha(png_ptr);
+    color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+  }
+
+  /* convert rgb to rgba */
+  if (color_type == PNG_COLOR_TYPE_RGB) {
+    png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
+    color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+  }
+
+  /* punt invalid formats */
+  if (color_type != PNG_COLOR_TYPE_RGB_ALPHA) {
+    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+    DBG_INFO(80, L"Error: not PNG_COLOR_TYPE_RGB_ALPHA format!\n");
+    return NULL;
+  }
+
+  /*png_color_8p sig_bit;
+  if (png_get_sBIT(png_ptr, info_ptr, &sig_bit))
+    png_set_shift(png_ptr, sig_bit);*/
+
+  /* convert rgba to bgra */
+  png_set_bgr(png_ptr);
+
+  /* turn on interlace handling to cope with the weirdness
+   * of texture authors using interlaced format */
+  num_pas = png_set_interlace_handling(png_ptr);
+
+  /* update info structure */
+  png_read_update_info(png_ptr, info_ptr);
+
+  /* we only get here if ARGB8888 */
+  row_bytes = png_get_rowbytes(png_ptr, info_ptr);
+
+  /* allocate memory to read in image */
+  image = (uint8*)malloc(row_bytes * o_height);
+
+  /* read in image */
+  if (image) {
+    int pas, i;
+    uint8* tmpimage;
+
+    for (pas = 0; pas < num_pas; pas++) { /* deal with interlacing */
+      tmpimage = image;
+
+      for (i = 0; i < o_height; i++) {
+        /* copy row */
+        png_read_rows(png_ptr, &tmpimage, NULL, 1);
+        tmpimage += row_bytes;
+      }
+    }
+
+    /* read rest of the info structure */
+    png_read_end(png_ptr, info_ptr);
+
+    *width = (row_bytes >> 2);
+    *height = o_height;
+    *format = GR_TEXFMT_ARGB_8888;
+
+#if POW2_TEXTURES
+    /* next power of 2 size conversions */
+    /* NOTE: I can do this in the above loop for faster operations, but some
+     * texture packs require a workaround. see HACKALERT in nextPow2().
+     */
+
+    TxReSample txReSample = new TxReSample; // XXX: temporary. move to a better place.
+
+#if (POW2_TEXTURES == 2)
+    if (!txReSample->nextPow2(&image, width, height, 32, 1)) {
+#else
+    if (!txReSample->nextPow2(&image, width, height, 32, 0)) {
+#endif
+      if (image) {
+        free(image);
+        image = NULL;
+      }
+      *width = 0;
+      *height = 0;
+      *format = 0;
+    }
+
+    delete txReSample;
+
+#endif /* POW2_TEXTURES */
+  }
+
+  /* clean up */
+  png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+
+#ifdef DEBUG
+  if (!image) {
+    DBG_INFO(80, L"Error: failed to load png image!\n");
+  }
+#endif
+
+  return image;
+}
+
+boolean
+TxImage::writePNG(uint8* src, FILE* fp, int width, int height, int rowStride, uint16 format, uint8 *palette)
+{
+  png_structp png_ptr;
+  png_infop info_ptr;
+  png_color_8 sig_bit;
+  png_colorp palette_ptr = NULL;
+  png_bytep trans_ptr = NULL;
+  int bit_depth, color_type, row_bytes, num_palette;
+  int i;
+  //uint16 srcfmt, destfmt;
+
+  if (!src || !fp)
+    return 0;
+
+  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+  if (png_ptr == NULL)
+    return 0;
+
+  info_ptr = png_create_info_struct(png_ptr);
+  if (info_ptr == NULL) {
+    png_destroy_write_struct(&png_ptr, NULL);
+    return 0;
+  }
+
+  if (png_jmpbuf(png_ptr)) {
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+    return 0;
+  }
+
+  png_init_io(png_ptr, fp);
+
+  /* TODO: images must be converted to RGBA8888 or CI8,
+   * palettes need to be separated to A and RGB. */
+
+  /* N64 formats
+   * Format: 0 - RGBA, 1 - YUV, 2 - CI, 3 - IA, 4 - I
+   * Size:   0 - 4bit, 1 - 8bit, 2 - 16bit, 3 - 32 bit
+   * format = (Format << 8 | Size);
+   */
+
+  /* each channel is saved in 8bits for consistency */
+  switch (format) {
+  case 0x0002:/* RGBA5551 */
+    bit_depth = 8;
+    sig_bit.red   = 5;
+    sig_bit.green = 5;
+    sig_bit.blue  = 5;
+    sig_bit.alpha = 1;
+    color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+    break;
+  case 0x0003:/* RGBA8888 */
+  case 0x0302:/* IA88 */
+    bit_depth = 8;
+    sig_bit.red   = 8;
+    sig_bit.green = 8;
+    sig_bit.blue  = 8;
+    sig_bit.alpha = 8;
+    color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+    break;
+  case 0x0300:/* IA31 */
+    bit_depth = 8;
+    sig_bit.red   = 3;
+    sig_bit.green = 3;
+    sig_bit.blue  = 3;
+    sig_bit.alpha = 1;
+    color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+    break;
+  case 0x0301:/* IA44 */
+    bit_depth = 8;
+    sig_bit.red   = 4;
+    sig_bit.green = 4;
+    sig_bit.blue  = 4;
+    sig_bit.alpha = 4;
+    color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+    break;
+  case 0x0400:/* I4 */
+    bit_depth = 8;
+    sig_bit.red   = 4;
+    sig_bit.green = 4;
+    sig_bit.blue  = 4;
+    color_type = PNG_COLOR_TYPE_RGB;
+    break;
+  case 0x0401:/* I8 */
+  case 0x0402:/* I16 */
+    bit_depth = 8;
+    sig_bit.red   = 8;
+    sig_bit.green = 8;
+    sig_bit.blue  = 8;
+    color_type = PNG_COLOR_TYPE_RGB;
+    break;
+  case 0x0200:/* CI4 */
+    bit_depth = 8;
+    num_palette = 16;
+    color_type = PNG_COLOR_TYPE_PALETTE;
+    break;
+  case 0x0201:/* CI8 */
+    bit_depth = 8;
+    num_palette = 256;
+    color_type = PNG_COLOR_TYPE_PALETTE;
+    break;
+  case 0x0102:/* YUV ? */
+  case 0x0103:
+  default:
+    /* unsupported format */
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+    return 0;
+  }
+
+  switch (color_type) {
+  case PNG_COLOR_TYPE_RGB_ALPHA:
+  case PNG_COLOR_TYPE_RGB:
+    //row_bytes = (bit_depth * width) >> 1;
+    row_bytes = rowStride;
+    png_set_bgr(png_ptr);
+    png_set_sBIT(png_ptr, info_ptr, &sig_bit);
+    break;
+  case PNG_COLOR_TYPE_PALETTE:
+    //row_bytes = (bit_depth * width) >> 3;
+    row_bytes = rowStride;
+    png_set_PLTE(png_ptr, info_ptr, palette_ptr, num_palette);
+    png_set_tRNS(png_ptr, info_ptr, trans_ptr, num_palette, 0);
+  }
+
+  //png_set_filter(png_ptr, 0, PNG_ALL_FILTERS);
+
+  //if (bit_depth == 16)
+  //  png_set_swap(png_ptr);
+
+  //if (bit_depth < 8)
+  //  png_set_packswap(png_ptr);
+
+  png_set_IHDR(png_ptr, info_ptr, width, height,
+               bit_depth, color_type, PNG_INTERLACE_NONE,
+               PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+
+  //png_set_gAMA(png_ptr, info_ptr, 1.0);
+
+  png_write_info(png_ptr, info_ptr);
+  for (i = 0; i < height; i++) {
+    png_write_row(png_ptr, (png_bytep)src);
+    src += row_bytes;
+  }
+  png_write_end(png_ptr, info_ptr);
+
+  png_destroy_write_struct(&png_ptr, &info_ptr);
+
+  //if (tex_ptr) delete [] tex_ptr;
+
+  return 1;
+}
+
+boolean
+TxImage::getBMPInfo(FILE* fp, BITMAPFILEHEADER* bmp_fhdr, BITMAPINFOHEADER* bmp_ihdr)
+{
+  /*
+   * read in BITMAPFILEHEADER
+   */
+
+  /* is this a BMP file? */
+  if (fread(&bmp_fhdr->bfType, 2, 1, fp) != 1)
+    return 0;
+
+  if (memcmp(&bmp_fhdr->bfType, "BM", 2) != 0)
+    return 0;
+
+  /* get file size */
+  if (fread(&bmp_fhdr->bfSize, 4, 1, fp) != 1)
+    return 0;
+
+  /* reserved 1 */
+  if (fread(&bmp_fhdr->bfReserved1, 2, 1, fp) != 1)
+    return 0;
+
+  /* reserved 2 */
+  if (fread(&bmp_fhdr->bfReserved2, 2, 1, fp) != 1)
+    return 0;
+
+  /* offset to the image data */
+  if (fread(&bmp_fhdr->bfOffBits, 4, 1, fp) != 1)
+    return 0;
+
+  /*
+   * read in BITMAPINFOHEADER
+   */
+
+  /* size of BITMAPINFOHEADER */
+  if (fread(&bmp_ihdr->biSize, 4, 1, fp) != 1)
+    return 0;
+
+  /* is this a Windows BMP? */
+  if (bmp_ihdr->biSize != 40)
+    return 0;
+
+  /* width of the bitmap in pixels */
+  if (fread(&bmp_ihdr->biWidth, 4, 1, fp) != 1)
+    return 0;
+
+  /* height of the bitmap in pixels */
+  if (fread(&bmp_ihdr->biHeight, 4, 1, fp) != 1)
+    return 0;
+
+  /* number of planes (always 1) */
+  if (fread(&bmp_ihdr->biPlanes, 2, 1, fp) != 1)
+    return 0;
+
+  /* number of bits-per-pixel. (1, 4, 8, 16, 24, 32) */
+  if (fread(&bmp_ihdr->biBitCount, 2, 1, fp) != 1)
+    return 0;
+
+  /* compression for a compressed bottom-up bitmap
+   *   0 : uncompressed format
+   *   1 : run-length encoded 4 bpp format
+   *   2 : run-length encoded 8 bpp format
+   *   3 : bitfield
+   */
+  if (fread(&bmp_ihdr->biCompression, 4, 1, fp) != 1)
+    return 0;
+
+  /* size of the image in bytes */
+  if (fread(&bmp_ihdr->biSizeImage, 4, 1, fp) != 1)
+    return 0;
+
+  /* horizontal resolution in pixels-per-meter */
+  if (fread(&bmp_ihdr->biXPelsPerMeter, 4, 1, fp) != 1)
+    return 0;
+
+  /* vertical resolution in pixels-per-meter */
+  if (fread(&bmp_ihdr->biYPelsPerMeter, 4, 1, fp) != 1)
+    return 0;
+
+  /* number of color indexes in the color table that are actually used */
+  if (fread(&bmp_ihdr->biClrUsed, 4, 1, fp) != 1)
+    return 0;
+
+  /*  the number of color indexes that are required for displaying */
+  if (fread(&bmp_ihdr->biClrImportant, 4, 1, fp) != 1)
+    return 0;
+
+  return 1;
+}
+
+uint8*
+TxImage::readBMP(FILE* fp, int* width, int* height, uint16* format)
+{
+  /* NOTE: returned image format;
+   *       4, 8bit palette bmp -> GR_TEXFMT_P_8
+   *       24, 32bit bmp -> GR_TEXFMT_ARGB_8888
+   */
+
+  uint8 *image = NULL;
+  uint8 *image_row = NULL;
+  uint8 *tmpimage = NULL;
+  unsigned int row_bytes, pos;
+  int i, j;
+  /* Windows Bitmap */
+  BITMAPFILEHEADER bmp_fhdr;
+  BITMAPINFOHEADER bmp_ihdr;
+
+  /* initialize */
+  *width  = 0;
+  *height = 0;
+  *format = 0;
+
+  /* check if we have a valid bmp file */
+  if (!fp)
+    return NULL;
+
+  if (!getBMPInfo(fp, &bmp_fhdr, &bmp_ihdr)) {
+    INFO(80, L"error reading bitmap file! bitmap image is corrupt.\n");
+    return NULL;
+  }
+
+  DBG_INFO(80, L"bmp format %d x %d bitdepth:%d compression:%x offset:%d\n",
+           bmp_ihdr.biWidth, bmp_ihdr.biHeight, bmp_ihdr.biBitCount,
+           bmp_ihdr.biCompression, bmp_fhdr.bfOffBits);
+
+  /* rowStride in bytes */
+  row_bytes = (bmp_ihdr.biWidth * bmp_ihdr.biBitCount) >> 3;
+  /* align to 4bytes boundary */
+  row_bytes = (row_bytes + 3) & ~3;
+
+  /* Rice hi-res textures */
+  if (!(bmp_ihdr.biBitCount == 8 || bmp_ihdr.biBitCount == 4 || bmp_ihdr.biBitCount == 32 || bmp_ihdr.biBitCount == 24) ||
+      bmp_ihdr.biCompression != 0) {
+    DBG_INFO(80, L"Error: incompatible bitmap format!\n");
+    return NULL;
+  }
+
+  switch (bmp_ihdr.biBitCount) {
+  case 8:
+  case 32:
+    /* 8 bit, 32 bit bitmap */
+    image = (uint8*)malloc(row_bytes * bmp_ihdr.biHeight);
+    if (image) {
+      tmpimage = image;
+      pos = bmp_fhdr.bfOffBits + row_bytes * (bmp_ihdr.biHeight - 1);
+      for (i = 0; i < bmp_ihdr.biHeight; i++) {
+        /* read in image */
+        fseek(fp, pos, SEEK_SET);
+        if (fread(tmpimage, 1, row_bytes, fp) != row_bytes)
+            ERRLOG("fread() failed for row of '%i' bytes in 8/32-bit BMP image", row_bytes);
+        tmpimage += row_bytes;
+        pos -= row_bytes;
+      }
+    }
+    break;
+  case 4:
+    /* 4bit bitmap */
+    image = (uint8*)malloc((row_bytes * bmp_ihdr.biHeight) << 1);
+    image_row = (uint8*)malloc(row_bytes);
+    if (image && image_row) {
+      tmpimage = image;
+      pos = bmp_fhdr.bfOffBits + row_bytes * (bmp_ihdr.biHeight - 1);
+      for (i = 0; i < bmp_ihdr.biHeight; i++) {
+        /* read in image */
+        fseek(fp, pos, SEEK_SET);
+        if (fread(image_row, 1, row_bytes, fp) != row_bytes)
+            ERRLOG("fread failed for row of '%i' bytes in 4-bit BMP image", row_bytes);
+        /* expand 4bpp to 8bpp. stuff 4bit values into 8bit comps. */
+        for (j = 0; j < (int) row_bytes; j++) {
+          tmpimage[j << 1] = image_row[j] & 0x0f;
+          tmpimage[(j << 1) + 1] = (image_row[j] & 0xf0) >> 4;
+        }
+        tmpimage += (row_bytes << 1);
+        pos -= row_bytes;
+      }
+      free(image_row);
+    } else {
+      if (image_row) free(image_row);
+      if (image) free(image);
+      image = NULL;
+    }
+    break;
+  case 24:
+    /* 24 bit bitmap */
+    image = (uint8*)malloc((bmp_ihdr.biWidth * bmp_ihdr.biHeight) << 2);
+    image_row = (uint8*)malloc(row_bytes);
+    if (image && image_row) {
+      tmpimage = image;
+      pos = bmp_fhdr.bfOffBits + row_bytes * (bmp_ihdr.biHeight - 1);
+      for (i = 0; i < bmp_ihdr.biHeight; i++) {
+        /* read in image */
+        fseek(fp, pos, SEEK_SET);
+        if (fread(image_row, 1, row_bytes, fp) != row_bytes)
+            ERRLOG("fread failed for row of '%i' bytes in 24-bit BMP image", row_bytes);
+        /* convert 24bpp to 32bpp. */
+        for (j = 0; j < bmp_ihdr.biWidth; j++) {
+          tmpimage[(j << 2)]     = image_row[j * 3];
+          tmpimage[(j << 2) + 1] = image_row[j * 3 + 1];
+          tmpimage[(j << 2) + 2] = image_row[j * 3 + 2];
+          tmpimage[(j << 2) + 3] = 0xFF;
+        }
+        tmpimage += (bmp_ihdr.biWidth << 2);
+        pos -= row_bytes;
+      }
+      free(image_row);
+    } else {
+      if (image_row) free(image_row);
+      if (image) free(image);
+      image = NULL;
+    }
+  }
+
+  if (image) {
+    *width = (row_bytes << 3) / bmp_ihdr.biBitCount;
+    *height = bmp_ihdr.biHeight;
+
+    switch (bmp_ihdr.biBitCount) {
+    case 8:
+    case 4:
+      *format = GR_TEXFMT_P_8;
+      break;
+    case 32:
+    case 24:
+      *format = GR_TEXFMT_ARGB_8888;
+    }
+
+#if POW2_TEXTURES
+    /* next power of 2 size conversions */
+    /* NOTE: I can do this in the above loop for faster operations, but some
+     * texture packs require a workaround. see HACKALERT in nextPow2().
+     */
+
+    TxReSample txReSample = new TxReSample; // XXX: temporary. move to a better place.
+
+#if (POW2_TEXTURES == 2)
+    if (!txReSample->nextPow2(&image, width, height, 8, 1)) {
+#else
+    if (!txReSample->nextPow2(&image, width, height, 8, 0)) {
+#endif
+      if (image) {
+        free(image);
+        image = NULL;
+      }
+      *width = 0;
+      *height = 0;
+      *format = 0;
+    }
+
+    delete txReSample;
+
+#endif /* POW2_TEXTURES */
+  }
+
+#ifdef DEBUG
+  if (!image) {
+    DBG_INFO(80, L"Error: failed to load bmp image!\n");
+  }
+#endif
+
+  return image;
+}
+
+boolean
+TxImage::getDDSInfo(FILE *fp, DDSFILEHEADER *dds_fhdr)
+{
+  /*
+   * read in DDSFILEHEADER
+   */
+
+  /* is this a DDS file? */
+  if (fread(&dds_fhdr->dwMagic, 4, 1, fp) != 1)
+    return 0;
+
+  if (memcmp(&dds_fhdr->dwMagic, "DDS ", 4) != 0)
+    return 0;
+
+  if (fread(&dds_fhdr->dwSize, 4, 1, fp) != 1)
+    return 0;
+
+  /* get file flags */
+  if (fread(&dds_fhdr->dwFlags, 4, 1, fp) != 1)
+    return 0;
+
+  /* height of dds in pixels */
+  if (fread(&dds_fhdr->dwHeight, 4, 1, fp) != 1)
+    return 0;
+
+  /* width of dds in pixels */
+  if (fread(&dds_fhdr->dwWidth, 4, 1, fp) != 1)
+    return 0;
+
+  if (fread(&dds_fhdr->dwLinearSize, 4, 1, fp) != 1)
+    return 0;
+
+  if (fread(&dds_fhdr->dwDepth, 4, 1, fp) != 1)
+    return 0;
+
+  if (fread(&dds_fhdr->dwMipMapCount, 4, 1, fp) != 1)
+    return 0;
+
+  if (fread(&dds_fhdr->dwReserved1, 4 * 11, 1, fp) != 1)
+    return 0;
+
+  if (fread(&dds_fhdr->ddpf.dwSize, 4, 1, fp) != 1)
+    return 0;
+
+  if (fread(&dds_fhdr->ddpf.dwFlags, 4, 1, fp) != 1)
+    return 0;
+
+  if (fread(&dds_fhdr->ddpf.dwFourCC, 4, 1, fp) != 1)
+    return 0;
+
+  if (fread(&dds_fhdr->ddpf.dwRGBBitCount, 4, 1, fp) != 1)
+    return 0;
+
+  if (fread(&dds_fhdr->ddpf.dwRBitMask, 4, 1, fp) != 1)
+    return 0;
+
+  if (fread(&dds_fhdr->ddpf.dwGBitMask, 4, 1, fp) != 1)
+    return 0;
+
+  if (fread(&dds_fhdr->ddpf.dwBBitMask, 4, 1, fp) != 1)
+    return 0;
+
+  if (fread(&dds_fhdr->ddpf.dwRGBAlphaBitMask, 4, 1, fp) != 1)
+    return 0;
+
+  if (fread(&dds_fhdr->dwCaps1, 4, 1, fp) != 1)
+    return 0;
+
+  if (fread(&dds_fhdr->dwCaps2, 4, 1, fp) != 1)
+    return 0;
+
+  return 1;
+}
+
+uint8*
+TxImage::readDDS(FILE* fp, int* width, int* height, uint16* format)
+{
+  uint8 *image = NULL;
+  DDSFILEHEADER dds_fhdr;
+  uint16 tmpformat = 0;
+
+  /* initialize */
+  *width  = 0;
+  *height = 0;
+  *format = 0;
+
+  /* check if we have a valid dds file */
+  if (!fp)
+    return NULL;
+
+  if (!getDDSInfo(fp, &dds_fhdr)) {
+    INFO(80, L"error reading dds file! dds image is corrupt.\n");
+    return NULL;
+  }
+
+  DBG_INFO(80, L"dds format %d x %d HeaderSize %d LinearSize %d\n",
+           dds_fhdr.dwWidth, dds_fhdr.dwHeight, dds_fhdr.dwSize, dds_fhdr.dwLinearSize);
+
+  if (!(dds_fhdr.dwFlags & (DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT|DDSD_LINEARSIZE))) {
+    DBG_INFO(80, L"Error: incompatible dds format!\n");
+    return NULL;
+  }
+
+  if ((dds_fhdr.dwFlags & DDSD_MIPMAPCOUNT) && dds_fhdr.dwMipMapCount != 1) {
+    DBG_INFO(80, L"Error: mipmapped dds not supported!\n");
+    return NULL;
+  }
+
+  if (!((dds_fhdr.ddpf.dwFlags & DDPF_FOURCC) && dds_fhdr.dwCaps2 == 0)) {
+    DBG_INFO(80, L"Error: not fourcc standard texture!\n");
+    return NULL;
+  }
+
+  if (memcmp(&dds_fhdr.ddpf.dwFourCC, "DXT1", 4) == 0) {
+    DBG_INFO(80, L"DXT1 format\n");
+    /* compensate for missing LinearSize */
+    dds_fhdr.dwLinearSize = (dds_fhdr.dwWidth * dds_fhdr.dwHeight) >> 1;
+    tmpformat = GR_TEXFMT_ARGB_CMP_DXT1;
+  } else if (memcmp(&dds_fhdr.ddpf.dwFourCC, "DXT3", 4) == 0) {
+    DBG_INFO(80, L"DXT3 format\n");
+    dds_fhdr.dwLinearSize = dds_fhdr.dwWidth * dds_fhdr.dwHeight;
+    tmpformat = GR_TEXFMT_ARGB_CMP_DXT3;
+  } else if (memcmp(&dds_fhdr.ddpf.dwFourCC, "DXT5", 4) == 0) {
+    DBG_INFO(80, L"DXT5 format\n");
+    dds_fhdr.dwLinearSize = dds_fhdr.dwWidth * dds_fhdr.dwHeight;
+    tmpformat = GR_TEXFMT_ARGB_CMP_DXT5;
+  } else {
+    DBG_INFO(80, L"Error: not DXT1 or DXT3 or DXT5 format!\n");
+    return NULL;
+  }
+
+  /* read in image */
+  image = (uint8*)malloc(dds_fhdr.dwLinearSize);
+  if (image) {
+    *width  = dds_fhdr.dwWidth;
+    *height = dds_fhdr.dwHeight;
+    *format = tmpformat;
+
+    fseek(fp, 128, SEEK_SET); /* size of header is 128 bytes */
+    if (fread(image, 1, dds_fhdr.dwLinearSize, fp) != dds_fhdr.dwLinearSize)
+        ERRLOG("fread failed to read DDS image of '%i' bytes", dds_fhdr.dwLinearSize);
+  }
+
+  return image;
+}
diff --git a/source/gles2glide64/src/GlideHQ/TxImage.h b/source/gles2glide64/src/GlideHQ/TxImage.h
new file mode 100644 (file)
index 0000000..b9eaa6a
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __TXIMAGE_H__
+#define __TXIMAGE_H__
+
+#include <stdio.h>
+#include <png.h>
+#include "TxInternal.h"
+
+#ifndef WIN32
+typedef struct tagBITMAPFILEHEADER {
+  uint16_t bfType;
+  uint32_t bfSize;
+  uint16_t bfReserved1;
+  uint16_t bfReserved2;
+  uint32_t bfOffBits;
+} BITMAPFILEHEADER;
+
+typedef struct tagBITMAPINFOHEADER {
+  uint32_t biSize;
+  int32_t  biWidth;
+  int32_t  biHeight;
+  uint16_t biPlanes;
+  uint16_t biBitCount;
+  uint32_t biCompression;
+  uint32_t biSizeImage;
+  uint32_t biXPelsPerMeter;
+  uint32_t biYPelsPerMeter;
+  uint32_t biClrUsed;
+  uint32_t biClrImportant;
+} BITMAPINFOHEADER;
+#else
+typedef struct tagBITMAPFILEHEADER BITMAPFILEHEADER;
+typedef struct tagBITMAPINFOHEADER BITMAPINFOHEADER;
+#endif
+
+#define DDSD_CAPS      0x00000001
+#define DDSD_HEIGHT    0x00000002
+#define DDSD_WIDTH     0x00000004
+#define DDSD_PITCH     0x00000008
+#define DDSD_PIXELFORMAT       0x00001000
+#define DDSD_MIPMAPCOUNT       0x00020000
+#define DDSD_LINEARSIZE        0x00080000
+#define DDSD_DEPTH     0x00800000
+
+#define DDPF_ALPHAPIXELS       0x00000001
+#define DDPF_FOURCC    0x00000004
+#define DDPF_RGB       0x00000040
+
+#define DDSCAPS_COMPLEX        0x00000008
+#define DDSCAPS_TEXTURE        0x00001000
+#define DDSCAPS_MIPMAP 0x00400000
+
+typedef struct tagDDSPIXELFORMAT {
+  uint32_t dwSize;
+  uint32_t dwFlags;
+  uint32_t dwFourCC;
+  uint32_t dwRGBBitCount;
+  uint32_t dwRBitMask;
+  uint32_t dwGBitMask;
+  uint32_t dwBBitMask;
+  uint32_t dwRGBAlphaBitMask;
+} DDSPIXELFORMAT;
+
+typedef struct tagDDSFILEHEADER {
+  uint32_t dwMagic;
+  uint32_t dwSize;
+  uint32_t dwFlags;
+  uint32_t dwHeight;
+  uint32_t dwWidth;
+  uint32_t dwLinearSize;
+  uint32_t dwDepth;
+  uint32_t dwMipMapCount;
+  uint32_t dwReserved1[11];
+  DDSPIXELFORMAT ddpf;
+  uint32_t dwCaps1;
+  uint32_t dwCaps2;
+} DDSFILEHEADER;
+
+class TxImage
+{
+private:
+  boolean getPNGInfo(FILE *fp, png_structp *png_ptr, png_infop *info_ptr);
+  boolean getBMPInfo(FILE *fp, BITMAPFILEHEADER *bmp_fhdr, BITMAPINFOHEADER *bmp_ihdr);
+  boolean getDDSInfo(FILE *fp, DDSFILEHEADER *dds_fhdr);
+public:
+  TxImage() {}
+  ~TxImage() {}
+  uint8* readPNG(FILE* fp, int* width, int* height, uint16* format);
+  boolean writePNG(uint8* src, FILE* fp, int width, int height, int rowStride, uint16 format, uint8 *palette);
+  uint8* readBMP(FILE* fp, int* width, int* height, uint16* format);
+  uint8* readDDS(FILE* fp, int* width, int* height, uint16* format);
+};
+
+#endif /* __TXIMAGE_H__ */
diff --git a/source/gles2glide64/src/GlideHQ/TxInternal.h b/source/gles2glide64/src/GlideHQ/TxInternal.h
new file mode 100644 (file)
index 0000000..1274a57
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __INTERNAL_H__
+#define __INTERNAL_H__
+
+#include "Ext_TxFilter.h"
+
+/* dll exports */
+#ifdef TXFILTER_DLL
+#define TAPI __declspec(dllexport)
+#define TAPIENTRY
+#else
+#define TAPI
+#define TAPIENTRY
+#endif
+
+#include <stdint.h>
+
+typedef uint8_t  uint8;
+typedef uint16_t uint16;
+typedef uint32_t  uint32;
+
+#ifdef WIN32
+#define KBHIT(key) ((GetAsyncKeyState(key) & 0x8001) == 0x8001)
+#else
+#define KBHIT(key) (0)
+#endif
+
+/* from OpenGL glext.h */
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT   0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT  0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT  0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT  0x83F3
+
+/* for explicit fxt1 compression */
+#define CC_CHROMA 0x0
+#define CC_HI     0x1
+#define CC_ALPHA  0x2
+
+/* in-memory zlib texture compression */
+#define GR_TEXFMT_GZ                 0x8000
+
+#if 0 /* this is here to remind me of other formats */
+/* from 3Dfx Interactive Inc. glide.h */
+#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
+
+/* from 3Dfx Interactive Inc. g3ext.h */
+#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
+#endif
+
+#endif /* __INTERNAL_H__ */
diff --git a/source/gles2glide64/src/GlideHQ/TxQuantize.cpp b/source/gles2glide64/src/GlideHQ/TxQuantize.cpp
new file mode 100644 (file)
index 0000000..b21db71
--- /dev/null
@@ -0,0 +1,2420 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef __MSC__
+#pragma warning(disable: 4786)
+#endif
+
+#include <functional>
+#include <thread>
+
+/* NOTE: The codes are not optimized. They can be made faster. */
+
+#include "TxQuantize.h"
+
+TxQuantize::TxQuantize()
+{
+  _txUtil = new TxUtil();
+
+  /* get number of CPU cores. */
+  _numcore = _txUtil->getNumberofProcessors();
+
+  /* get dxtn extensions */
+  _tx_compress_fxt1 = TxLoadLib::getInstance()->getfxtCompressTexFuncExt();
+  _tx_compress_dxtn = TxLoadLib::getInstance()->getdxtCompressTexFuncExt();
+}
+
+
+TxQuantize::~TxQuantize()
+{
+  delete _txUtil;
+}
+
+void
+TxQuantize::ARGB1555_ARGB8888(uint32* src, uint32* dest, int width, int height)
+{
+#if 1
+  int siz = (width * height) >> 1;
+  int i;
+  for (i = 0; i < siz; i++) {
+    *dest = (((*src & 0x00008000) ? 0xff000000 : 0x00000000) |
+            ((*src & 0x00007c00) << 9) | ((*src & 0x00007000) << 4) |
+            ((*src & 0x000003e0) << 6) | ((*src & 0x00000380) << 1) |
+            ((*src & 0x0000001f) << 3) | ((*src & 0x0000001c) >> 2));
+    dest++;
+    *dest = (((*src & 0x80000000) ? 0xff000000 : 0x00000000) |
+            ((*src & 0x7c000000) >>  7) | ((*src & 0x70000000) >> 12) |
+            ((*src & 0x03e00000) >> 10) | ((*src & 0x03800000) >> 15) |
+            ((*src & 0x001f0000) >> 13) | ((*src & 0x001c0000) >> 18));
+    dest++;
+    src++;
+  }
+#else
+  int siz = (width * height) >> 1;
+
+  __asm {
+    push ebx;
+    push esi;
+    push edi;
+
+    mov esi, dword ptr [src];
+    mov edi, dword ptr [dest];
+    mov ecx, dword ptr [siz];
+
+  tc1_loop:
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    // arrr rrgg gggb bbbb
+    // aaaaaaaa rrrrrrrr gggggggg bbbbbbbb
+    mov edx, eax;         // edx = arrrrrgg gggbbbbb arrrrrgg gggbbbbb
+    mov ebx, 0x00000000;
+    and eax, 0x00008000;  // eax = 00000000 00000000 a0000000 00000000
+    jz  transparent1;
+    mov ebx, 0xff000000;  // ebx = aaaaaaaa 00000000 00000000 00000000
+
+  transparent1:
+    mov eax, edx;         // eax = arrrrrgg gggbbbbb arrrrrgg gggbbbbb
+    and edx, 0x00007c00;  // edx = 00000000 00000000 0rrrrr00 00000000
+    shl edx, 4;           // edx = 00000000 00000rrr rr000000 00000000
+    or  ebx, edx;         // ebx = aaaaaaaa 00000rrr rr000000 00000000
+    shl edx, 5;           // edx = 00000000 rrrrr000 00000000 00000000
+    or  ebx, edx;         // ebx = aaaaaaaa rrrrrrrr rr000000 00000000
+    and ebx, 0xffff0000;  // ebx = aaaaaaaa rrrrrrrr 00000000 00000000
+    mov edx, eax;
+    and edx, 0x000003e0;  // edx = 00000000 00000000 000000gg ggg00000
+    shl edx, 1;           // edx = 00000000 00000000 00000ggg gg000000
+    or  ebx, edx;         // ebx = aaaaaaaa rrrrrrrr 00000ggg gg000000
+    shl edx, 5;           // edx = 00000000 00000000 ggggg000 00000000
+    or  ebx, edx;         // ebx = aaaaaaaa rrrrrrrr gggggggg gg000000
+    and ebx, 0xffffff00;  // ebx = aaaaaaaa rrrrrrrr gggggggg 00000000
+    mov edx, eax;
+    and edx, 0x0000001f;  // edx = 00000000 00000000 00000000 000bbbbb
+    shl edx, 3;           // edx = 00000000 00000000 00000000 bbbbb000
+    or  ebx, edx;         // ebx = aaaaaaaa rrrrrrrr gggggggg bbbbb000
+    shr edx, 5;           // edx = 00000000 00000000 00000000 00000bbb
+    or  ebx, edx;         // ebx = aaaaaaaa rrrrrrrr gggggggg bbbbbbbb
+
+    mov dword ptr [edi], ebx;
+    add edi, 4;
+
+    shr eax, 16;          // eax = 00000000 00000000 arrrrrgg gggbbbbb
+    mov edx, eax;         // edx = 00000000 00000000 arrrrrgg gggbbbbb
+    mov ebx, 0x00000000;
+    and eax, 0x00008000;  // eax = 00000000 00000000 a0000000 00000000
+    jz  transparent2;
+    mov ebx, 0xff000000;  // ebx = aaaaaaaa 00000000 00000000 00000000
+
+  transparent2:
+    mov eax, edx;         // eax = 00000000 00000000 arrrrrgg gggbbbbb
+    and edx, 0x00007c00;  // edx = 00000000 00000000 0rrrrr00 00000000
+    shl edx, 4;           // edx = 00000000 00000rrr rr000000 00000000
+    or  ebx, edx;         // ebx = aaaaaaaa 00000rrr rr000000 00000000
+    shl edx, 5;           // edx = 00000000 rrrrr000 00000000 00000000
+    or  ebx, edx;         // ebx = aaaaaaaa rrrrrrrr rr000000 00000000
+    and ebx, 0xffff0000;  // ebx = aaaaaaaa rrrrrrrr 00000000 00000000
+    mov edx, eax;
+    and edx, 0x000003e0;  // edx = 00000000 00000000 000000gg ggg00000
+    shl edx, 1;           // edx = 00000000 00000000 00000ggg gg000000
+    or  ebx, edx;         // ebx = aaaaaaaa rrrrrrrr 00000ggg gg000000
+    shl edx, 5;           // edx = 00000000 00000000 ggggg000 00000000
+    or  ebx, edx;         // ebx = aaaaaaaa rrrrrrrr gggggggg gg000000
+    and ebx, 0xffffff00;  // ebx = aaaaaaaa rrrrrrrr gggggggg 00000000
+    mov edx, eax;
+    and edx, 0x0000001f;  // edx = 00000000 00000000 00000000 000bbbbb
+    shl edx, 3;           // edx = 00000000 00000000 00000000 bbbbb000
+    or  ebx, edx;         // ebx = aaaaaaaa rrrrrrrr gggggggg bbbbb000
+    shr edx, 5;           // edx = 00000000 00000000 00000000 00000bbb
+    or  ebx, edx;         // ebx = aaaaaaaa rrrrrrrr gggggggg bbbbbbbb
+
+    mov dword ptr [edi], ebx;
+    add edi, 4;
+
+    dec ecx;
+    jnz tc1_loop;
+
+    pop edi;
+    pop esi;
+    pop ebx;
+  }
+#endif
+}
+
+void
+TxQuantize::ARGB4444_ARGB8888(uint32* src, uint32* dest, int width, int height)
+{
+#if 1
+  int siz = (width * height) >> 1;
+  int i;
+  for (i = 0; i < siz; i++) {
+    *dest = ((*src & 0x0000f000) << 12) |
+            ((*src & 0x00000f00) << 8) |
+            ((*src & 0x000000f0) << 4) |
+             (*src & 0x0000000f);
+    *dest |= (*dest << 4);
+    dest++;
+    *dest = ((*src & 0xf0000000) |
+            ((*src & 0x0f000000) >> 4) |
+            ((*src & 0x00f00000) >> 8) |
+            ((*src & 0x000f0000) >> 12));
+    *dest |= (*dest >> 4);
+    dest++;
+    src++;
+  }
+#else
+  int siz = (width * height) >> 1;
+
+  __asm {
+    push ebx;
+    push esi;
+    push edi;
+
+    mov esi, dword ptr [src];
+    mov edi, dword ptr [dest];
+    mov ecx, dword ptr [siz];
+
+  tc1_loop:
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    // aaaa rrrr gggg bbbb
+    // aaaaaaaa rrrrrrrr gggggggg bbbbbbbb
+    mov edx, eax;
+    and eax, 0x0000ffff;
+    mov ebx, eax;        // 00000000 00000000 aaaarrrr ggggbbbb
+    and ebx, 0x0000f000; // 00000000 00000000 aaaa0000 00000000
+    shl ebx, 12;         // 0000aaaa 00000000 00000000 00000000
+    or  eax, ebx;        // 0000aaaa 00000000 aaaarrrr ggggbbbb
+    mov ebx, eax;
+    and ebx, 0x00000f00; // 00000000 00000000 0000rrrr 00000000
+    shl ebx, 8;          // 00000000 0000rrrr 00000000 00000000
+    or  eax, ebx;        // 0000aaaa 0000rrrr aaaarrrr ggggbbbb
+    mov ebx, eax;
+    and ebx, 0x000000f0; // 00000000 00000000 00000000 gggg0000
+    shl ebx, 4;          // 00000000 00000000 0000gggg 00000000
+    and eax, 0x0f0f000f; // 0000aaaa 0000rrrr 00000000 0000bbbb
+    or  eax, ebx;        // 0000aaaa 0000rrrr 0000gggg 0000bbbb
+    mov ebx, eax;
+    shl ebx, 4;          // aaaa0000 rrrr0000 gggg0000 bbbb0000
+    or  eax, ebx;        // aaaaaaaa rrrrrrrr gggggggg bbbbbbbb
+
+    mov dword ptr [edi], eax;
+    add edi, 4;
+
+    shr edx, 16;
+    mov ebx, edx;        // 00000000 00000000 aaaarrrr ggggbbbb
+    and ebx, 0x0000f000; // 00000000 00000000 aaaa0000 00000000
+    shl ebx, 12;         // 0000aaaa 00000000 00000000 00000000
+    or  edx, ebx;        // 0000aaaa 00000000 aaaarrrr ggggbbbb
+    mov ebx, edx;
+    and ebx, 0x00000f00; // 00000000 00000000 0000rrrr 00000000
+    shl ebx, 8;          // 00000000 0000rrrr 00000000 00000000
+    or  edx, ebx;        // 0000aaaa 0000rrrr aaaarrrr ggggbbbb
+    mov ebx, edx;
+    and ebx, 0x000000f0; // 00000000 00000000 00000000 gggg0000
+    shl ebx, 4;          // 00000000 00000000 0000gggg 00000000
+    and edx, 0x0f0f000f; // 0000aaaa 0000rrrr 00000000 0000bbbb
+    or  edx, ebx;        // 0000aaaa 0000rrrr 0000gggg 0000bbbb
+    mov ebx, edx;
+    shl ebx, 4;          // aaaa0000 rrrr0000 gggg0000 bbbb0000
+    or  edx, ebx;        // aaaaaaaa rrrrrrrr gggggggg bbbbbbbb
+
+    mov dword ptr [edi], edx;
+    add edi, 4;
+
+    dec ecx;
+    jnz tc1_loop;
+
+    pop edi;
+    pop esi;
+    pop ebx;
+  }
+#endif
+}
+
+void
+TxQuantize::RGB565_ARGB8888(uint32* src, uint32* dest, int width, int height)
+{
+#if 1
+  int siz = (width * height) >> 1;
+  int i;
+  for (i = 0; i < siz; i++) {
+    *dest = (0xff000000 |
+            ((*src & 0x0000f800) << 8) | ((*src & 0x0000e000) << 3) |
+            ((*src & 0x000007e0) << 5) | ((*src & 0x00000600) >> 1) |
+            ((*src & 0x0000001f) << 3) | ((*src & 0x0000001c) >> 2));
+    dest++;
+    *dest = (0xff000000 |
+            ((*src & 0xf8000000) >>  8) | ((*src & 0xe0000000) >> 13) |
+            ((*src & 0x07e00000) >> 11) | ((*src & 0x06000000) >> 17) |
+            ((*src & 0x001f0000) >> 13) | ((*src & 0x001c0000) >> 18));
+    dest++;
+    src++;
+  }
+#else
+  int siz = (width * height) >> 1;
+
+  __asm {
+    push ebx;
+    push esi;
+    push edi;
+
+    mov esi, dword ptr [src];
+    mov edi, dword ptr [dest];
+    mov ecx, dword ptr [siz];
+
+  tc1_loop:
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    // rrrr rggg gggb bbbb
+    // 11111111 rrrrrrrr gggggggg bbbbbbbb
+    mov edx, eax;
+    and eax, 0x0000ffff;
+    mov ebx, eax;        // 00000000 00000000 rrrrrggg gggbbbbb
+    and ebx, 0x0000f800; // 00000000 00000000 rrrrr000 00000000
+    shl ebx, 5;          // 00000000 000rrrrr 00000000 00000000
+    or  eax, ebx;        // 00000000 000rrrrr rrrrrggg gggbbbbb
+    mov ebx, eax;
+    and ebx, 0x000007e0; // 00000000 00000000 00000ggg ggg00000
+    shl ebx, 5;          // 00000000 00000000 gggggg00 00000000
+    and eax, 0x001F001F; // 00000000 000rrrrr 00000000 000bbbbb
+    shl eax, 3;          // 00000000 rrrrr000 00000000 bbbbb000
+    or  eax, ebx;        // 00000000 rrrrr000 gggggg00 bbbbb000
+    mov ebx, eax;
+    shr ebx, 5;          // 00000000 00000rrr rr000ggg ggg00bbb
+    and ebx, 0x00070007; // 00000000 00000rrr 00000000 00000bbb
+    or  eax, ebx;        // 00000000 rrrrrrrr gggggg00 bbbbbbbb
+    mov ebx, eax;
+    shr ebx, 6;
+    and ebx, 0x00000300; // 00000000 00000000 000000gg 00000000
+    or  eax, ebx         // 00000000 rrrrrrrr gggggggg bbbbbbbb
+    or  eax, 0xff000000; // 11111111 rrrrrrrr gggggggg bbbbbbbb
+
+    mov dword ptr [edi], eax;
+    add edi, 4;
+
+    shr edx, 16;
+    mov eax, edx;        // 00000000 00000000 rrrrrggg gggbbbbb
+    and eax, 0x0000ffff;
+    mov ebx, eax;        // 00000000 00000000 rrrrrggg gggbbbbb
+    and ebx, 0x0000f800; // 00000000 00000000 rrrrr000 00000000
+    shl ebx, 5;          // 00000000 000rrrrr 00000000 00000000
+    or  eax, ebx;        // 00000000 000rrrrr rrrrrggg gggbbbbb
+    mov ebx, eax;
+    and ebx, 0x000007e0; // 00000000 00000000 00000ggg ggg00000
+    shl ebx, 5;          // 00000000 00000000 gggggg00 00000000
+    and eax, 0x001F001F; // 00000000 000rrrrr 00000000 000bbbbb
+    shl eax, 3;          // 00000000 rrrrr000 00000000 bbbbb000
+    or  eax, ebx;        // 00000000 rrrrr000 gggggg00 bbbbb000
+    mov ebx, eax;
+    shr ebx, 5;          // 00000000 00000rrr rr000ggg ggg00bbb
+    and ebx, 0x00070007; // 00000000 00000rrr 00000000 00000bbb
+    or  eax, ebx;        // 00000000 rrrrrrrr gggggg00 bbbbbbbb
+    mov ebx, eax;
+    shr ebx, 6;
+    and ebx, 0x00000300; // 00000000 00000000 000000gg 00000000
+    or  eax, ebx         // 00000000 rrrrrrrr gggggggg bbbbbbbb
+    or  eax, 0xff000000; // 11111111 rrrrrrrr gggggggg bbbbbbbb
+
+    mov dword ptr [edi], eax;
+    add edi, 4;
+
+    dec ecx;
+    jnz tc1_loop;
+
+    pop edi;
+    pop esi;
+    pop ebx;
+  }
+#endif
+}
+
+void
+TxQuantize::A8_ARGB8888(uint32* src, uint32* dest, int width, int height)
+{
+#if 1
+  int siz = (width * height) >> 2;
+  int i;
+  for (i = 0; i < siz; i++) {
+    *dest = (*src & 0x000000ff);
+    *dest |= (*dest << 8);
+    *dest |= (*dest << 16);
+    dest++;
+    *dest = (*src & 0x0000ff00);
+    *dest |= (*dest >> 8);
+    *dest |= (*dest << 16);
+    dest++;
+    *dest = (*src & 0x00ff0000);
+    *dest |= (*dest << 8);
+    *dest |= (*dest >> 16);
+    dest++;
+    *dest = (*src & 0xff000000);
+    *dest |= (*dest >> 8);
+    *dest |= (*dest >> 16);
+    dest++;
+    src++;
+  }
+#else
+  int siz = (width * height) >> 2;
+
+  __asm {
+    push ebx;
+    push esi;
+    push edi;
+
+    mov esi, dword ptr [src];
+    mov edi, dword ptr [dest];
+    mov ecx, dword ptr [siz];
+
+  tc1_loop:
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    // aaaaaaaa
+    // aaaaaaaa rrrrrrrr gggggggg bbbbbbbb
+    mov edx, eax;
+    and eax, 0x000000ff;
+    mov ebx, eax;        // 00000000 00000000 00000000 aaaaaaaa
+    shl ebx, 8;          // 00000000 00000000 aaaaaaaa 00000000
+    or  eax, ebx;        // 00000000 00000000 aaaaaaaa aaaaaaaa
+    mov ebx, eax;
+    shl ebx, 16;         // aaaaaaaa aaaaaaaa 00000000 00000000
+    or  eax, ebx;        // aaaaaaaa rrrrrrrr gggggggg bbbbbbbb
+
+    mov dword ptr [edi], eax;
+    add edi, 4;
+
+    mov eax, edx;
+    and eax, 0x0000ff00;
+    mov ebx, eax;        // 00000000 00000000 aaaaaaaa 00000000
+    shr ebx, 8;          // 00000000 00000000 00000000 aaaaaaaa
+    or  eax, ebx;        // 00000000 00000000 aaaaaaaa aaaaaaaa
+    mov ebx, eax;
+    shl ebx, 16;         // aaaaaaaa aaaaaaaa 00000000 00000000
+    or  eax, ebx;        // aaaaaaaa rrrrrrrr gggggggg bbbbbbbb
+
+    mov dword ptr [edi], eax;
+    add edi, 4;
+
+    mov eax, edx;
+    and eax, 0x00ff0000;
+    mov ebx, eax;        // 00000000 aaaaaaaa 00000000 00000000
+    shl ebx, 8;          // aaaaaaaa 00000000 00000000 00000000
+    or  eax, ebx;        // aaaaaaaa aaaaaaaa 00000000 00000000
+    mov ebx, eax;
+    shr ebx, 16;         // 00000000 00000000 aaaaaaaa aaaaaaaa
+    or  eax, ebx;        // aaaaaaaa rrrrrrrr gggggggg bbbbbbbb
+
+    mov dword ptr [edi], eax;
+    add edi, 4;
+
+    mov eax, edx;
+    and eax, 0xff000000;
+    mov ebx, eax;        // aaaaaaaa 00000000 00000000 00000000
+    shr ebx, 8;          // 00000000 aaaaaaaa 00000000 00000000
+    or  eax, ebx;        // aaaaaaaa aaaaaaaa 00000000 00000000
+    mov ebx, eax;
+    shr ebx, 16;         // 00000000 00000000 aaaaaaaa aaaaaaaa
+    or  eax, ebx;        // aaaaaaaa rrrrrrrr gggggggg bbbbbbbb
+
+    mov dword ptr [edi], eax;
+    add edi, 4;
+
+    dec ecx;
+    jnz tc1_loop;
+
+    pop edi;
+    pop esi;
+    pop ebx;
+  }
+#endif
+}
+
+void
+TxQuantize::AI44_ARGB8888(uint32* src, uint32* dest, int width, int height)
+{
+#if 1
+  int siz = (width * height) >> 2;
+  int i;
+  for (i = 0; i < siz; i++) {
+    *dest = (*src & 0x0000000f);
+    *dest |= ((*dest << 8) | (*dest << 16));
+    *dest |= ((*src & 0x000000f0) << 20);
+    *dest |= (*dest << 4);
+    dest++;
+    *dest = (*src & 0x00000f00);
+    *dest |= ((*dest << 8) | (*dest >> 8));
+    *dest |= ((*src & 0x0000f000) << 12);
+    *dest |= (*dest << 4);
+    dest++;
+    *dest = (*src & 0x000f0000);
+    *dest |= ((*dest >> 8) | (*dest >> 16));
+    *dest |= ((*src & 0x00f00000) << 4);
+    *dest |= (*dest << 4);
+    dest++;
+    *dest = ((*src & 0x0f000000) >> 4);
+    *dest |= ((*dest >> 8) | (*dest >> 16));
+    *dest |= (*src & 0xf0000000);
+    *dest |= (*dest >> 4);
+    dest++;
+    src++;
+  }
+#else
+  int siz = (width * height) >> 2;
+
+  __asm {
+    push ebx;
+    push esi;
+    push edi;
+
+    mov esi, dword ptr [src];
+    mov edi, dword ptr [dest];
+    mov ecx, dword ptr [siz];
+
+  tc1_loop:
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    // aaaaiiii
+    // aaaaaaaa iiiiiiii iiiiiiii iiiiiiii
+    mov edx, eax;
+    and eax, 0x000000f0; // 00000000 00000000 00000000 aaaa0000
+    mov ebx, edx;
+    shl eax, 20;         // 0000aaaa 00000000 00000000 00000000
+    and ebx, 0x0000000f; // 00000000 00000000 00000000 0000iiii
+    or  eax, ebx;        // 0000aaaa 00000000 00000000 0000iiii
+    shl ebx, 8;          // 00000000 00000000 0000iiii 00000000
+    or  eax, ebx;        // 0000aaaa 00000000 0000iiii 0000iiii
+    shl ebx, 8;          // 00000000 0000iiii 00000000 00000000
+    or  eax, ebx;        // 0000aaaa 0000iiii 0000iiii 0000iiii
+    mov ebx, eax;
+    shl ebx, 4;          // aaaa0000 iiii0000 iiii0000 iiii0000
+    or  eax, ebx;        // aaaaaaaa iiiiiiii iiiiiiii iiiiiiii
+
+    mov dword ptr [edi], eax;
+    add edi, 4;
+
+    mov eax, edx;
+    and eax, 0x0000f000; // 00000000 00000000 aaaa0000 00000000
+    mov ebx, edx;
+    shl eax, 12;         // 0000aaaa 00000000 00000000 00000000
+    and ebx, 0x00000f00; // 00000000 00000000 0000iiii 00000000
+    or  eax, ebx;        // 0000aaaa 00000000 0000iiii 00000000
+    shr ebx, 8;          // 00000000 00000000 00000000 0000iiii
+    or  eax, ebx;        // 0000aaaa 00000000 0000iiii 0000iiii
+    shl ebx, 16;         // 00000000 0000iiii 00000000 00000000
+    or  eax, ebx;        // 0000aaaa 0000iiii 0000iiii 0000iiii
+    mov ebx, eax;
+    shl ebx, 4;          // aaaa0000 iiii0000 iiii0000 iiii0000
+    or  eax, ebx;        // aaaaaaaa iiiiiiii iiiiiiii iiiiiiii
+
+    mov dword ptr [edi], eax;
+    add edi, 4;
+
+    mov eax, edx;
+    and eax, 0x00f00000; // 00000000 aaaa0000 00000000 00000000
+    mov ebx, edx;
+    shl eax, 4;          // 0000aaaa 00000000 00000000 00000000
+    and ebx, 0x000f0000; // 00000000 0000iiii 00000000 00000000
+    or  eax, ebx;        // 0000aaaa 0000iiii 00000000 00000000
+    shr ebx, 8;          // 00000000 00000000 0000iiii 00000000
+    or  eax, ebx;        // 0000aaaa 0000iiii 0000iiii 00000000
+    shr ebx, 8;          // 00000000 00000000 00000000 0000iiii
+    or  eax, ebx;        // 0000aaaa 0000iiii 0000iiii 0000iiii
+    mov ebx, eax;
+    shl ebx, 4;          // aaaa0000 iiii0000 iiii0000 iiii0000
+    or  eax, ebx;        // aaaaaaaa iiiiiiii iiiiiiii iiiiiiii
+
+    mov dword ptr [edi], eax;
+    add edi, 4;
+
+    mov eax, edx;
+    and eax, 0xf0000000; // aaaa0000 00000000 00000000 00000000
+    mov ebx, edx;
+    and ebx, 0x0f000000; // 0000iiii 00000000 00000000 00000000
+    shr ebx, 4;          // 00000000 iiii0000 00000000 00000000
+    or  eax, ebx;        // aaaa0000 iiii0000 00000000 00000000
+    shr ebx, 8;          // 00000000 00000000 iiii0000 00000000
+    or  eax, ebx;        // aaaa0000 iiii0000 iiii0000 00000000
+    shr ebx, 8;          // 00000000 00000000 00000000 iiii0000
+    or  eax, ebx;        // aaaa0000 iiii0000 iiii0000 iiii0000
+    mov ebx, eax;
+    shr ebx, 4;          // 0000aaaa 0000iiii 0000iiii 0000iiii
+    or  eax, ebx;        // aaaaaaaa iiiiiiii iiiiiiii iiiiiiii
+
+    mov dword ptr [edi], eax;
+    add edi, 4;
+
+    dec ecx;
+    jnz tc1_loop;
+
+    pop edi;
+    pop esi;
+    pop ebx;
+  }
+#endif
+}
+
+void
+TxQuantize::AI88_ARGB8888(uint32* src, uint32* dest, int width, int height)
+{
+#if 1
+  int siz = (width * height) >> 1;
+  int i;
+  for (i = 0; i < siz; i++) {
+    *dest = (*src & 0x000000ff);
+    *dest |= ((*dest << 8) | (*dest << 16));
+    *dest |= ((*src & 0x0000ff00) << 16);
+    dest++;
+    *dest = (*src & 0x00ff0000);
+    *dest |= ((*dest >> 8) | (*dest >> 16));
+    *dest |= (*src & 0xff000000);
+    dest++;
+    src++;
+  }
+#else
+  int siz = (width * height) >> 1;
+
+  __asm {
+    push ebx;
+    push esi;
+    push edi;
+
+    mov esi, dword ptr [src];
+    mov edi, dword ptr [dest];
+    mov ecx, dword ptr [siz];
+
+  tc1_loop:
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    // aaaaaaaa iiiiiiii
+    // aaaaaaaa iiiiiiii iiiiiiii iiiiiiii
+    mov edx, eax;
+    and eax, 0x0000ffff; // 00000000 00000000 aaaaaaaa iiiiiiii
+    mov ebx, eax;        // 00000000 00000000 aaaaaaaa iiiiiiii
+    shl eax, 16;         // aaaaaaaa iiiiiiii 00000000 00000000
+    and ebx, 0x000000ff; // 00000000 00000000 00000000 iiiiiiii
+    or  eax, ebx;        // aaaaaaaa iiiiiiii 00000000 iiiiiiii
+    shl ebx, 8;          // 00000000 00000000 iiiiiiii 00000000
+    or  eax, ebx;        // aaaaaaaa iiiiiiii iiiiiiii iiiiiiii
+
+    mov dword ptr [edi], eax;
+    add edi, 4;
+
+    mov eax, edx;
+    and eax, 0xffff0000; // aaaaaaaa iiiiiiii 00000000 00000000
+    mov ebx, eax;        // aaaaaaaa iiiiiiii 00000000 00000000
+    and ebx, 0x00ff0000; // 00000000 iiiiiiii 00000000 00000000
+    shr ebx, 8;          // 00000000 00000000 iiiiiiii 00000000
+    or  eax, ebx;        // aaaaaaaa iiiiiiii iiiiiiii 00000000
+    shr ebx, 8;          // 00000000 00000000 00000000 iiiiiiii
+    or  eax, ebx;        // aaaaaaaa iiiiiiii iiiiiiii iiiiiiii
+
+    mov dword ptr [edi], eax;
+    add edi, 4;
+
+    dec ecx;
+    jnz tc1_loop;
+
+    pop edi;
+    pop esi;
+    pop ebx;
+  }
+#endif
+}
+
+void
+TxQuantize::ARGB8888_ARGB1555(uint32* src, uint32* dest, int width, int height)
+{
+#if 1
+  int siz = (width * height) >> 1;
+  int i;
+  for (i = 0; i < siz; i++) {
+    *dest = ((*src & 0xff000000) ? 0x00008000 : 0x00000000);
+    *dest |= (((*src & 0x00f80000) >> 9) |
+              ((*src & 0x0000f800) >> 6) |
+              ((*src & 0x000000f8) >> 3));
+    src++;
+    *dest |= ((*src & 0xff000000) ? 0x80000000 : 0x00000000);
+    *dest |= (((*src & 0x00f80000) << 7) |
+              ((*src & 0x0000f800) << 10) |
+              ((*src & 0x000000f8) << 13));
+    src++;
+    dest++;
+  }
+#else
+  int siz = (width * height) >> 1;
+
+  __asm {
+    push ebx;
+    push esi;
+    push edi;
+
+    mov esi, dword ptr [src];
+    mov edi, dword ptr [dest];
+    mov ecx, dword ptr [siz];
+
+  tc1_loop:
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+#if 1
+    mov edx, eax;
+    and eax, 0xff000000;  // aaaa0000 00000000 00000000 00000000
+    jz transparent1;
+    mov eax, 0x00008000;  // 00000000 00000000 a0000000 00000000
+
+  transparent1:
+    mov ebx, edx;
+    and ebx, 0x00f80000;  // 00000000 rrrrr000 00000000 00000000
+    shr ebx, 9;           // 00000000 00000000 0rrrrr00 00000000
+    or  eax, ebx;         // 00000000 00000000 arrrrr00 00000000
+    mov ebx, edx;
+    and ebx, 0x0000f800;  // 00000000 00000000 ggggg000 00000000
+    shr ebx, 6;           // 00000000 00000000 000000gg ggg00000
+    or  eax, ebx;         // 00000000 00000000 arrrrrgg ggg00000
+    and edx, 0x000000f8;  // 00000000 00000000 00000000 bbbbb000
+    shr edx, 3;           // 00000000 00000000 00000000 000bbbbb
+    or  edx, eax;         // 00000000 00000000 arrrrrgg gggbbbbb
+
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    mov ebx, eax;
+    and eax, 0xff000000;  // aaaa0000 00000000 00000000 00000000
+    jz transparent2;
+    or  edx, 0x80000000;  // a0000000 00000000 arrrrrgg gggbbbbb
+
+  transparent2:
+    mov eax, ebx;
+    and ebx, 0x00f80000;  // 00000000 rrrrr000 00000000 00000000
+    shl ebx, 7;           // 0rrrrr00 00000000 00000000 00000000
+    or  edx, ebx;         // arrrrr00 00000000 arrrrrgg gggbbbbb
+    mov ebx, eax;
+    and ebx, 0x0000f800;  // 00000000 00000000 ggggg000 00000000
+    shl ebx, 10;          // 000000gg ggg00000 00000000 00000000
+    or  edx, ebx;         // arrrrrgg ggg00000 arrrrrgg gggbbbbb
+    and eax, 0x000000f8;  // 00000000 00000000 00000000 bbbbb000
+    shl eax, 13;          // 00000000 000bbbbb 00000000 00000000
+    or  edx, eax;         // arrrrrgg gggbbbbb arrrrrgg gggbbbbb
+
+    mov dword ptr [edi], edx;
+    add edi, 4;
+#else
+    mov edx, eax;
+    and edx, 0x01000000;  // 0000000a 00000000 00000000 00000000
+    shr edx, 9;           // 00000000 00000000 a0000000 00000000
+    mov ebx, eax;
+    and ebx, 0x00f80000;  // 00000000 rrrrr000 00000000 00000000
+    shr ebx, 9;           // 00000000 00000000 0rrrrr00 00000000
+    or  edx, ebx;         // 00000000 00000000 arrrrr00 00000000
+    mov ebx, eax;
+    and ebx, 0x0000f800;  // 00000000 00000000 ggggg000 00000000
+    shr ebx, 6;           // 00000000 00000000 000000gg ggg00000
+    or  edx, ebx;         // 00000000 00000000 arrrrrgg ggg00000
+    and eax, 0x000000f8;  // 00000000 00000000 00000000 bbbbb000
+    shr eax, 3;           // 00000000 00000000 00000000 000bbbbb
+    or  edx, eax;         // 00000000 00000000 arrrrrgg gggbbbbb
+
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    mov ebx, eax;
+    and ebx, 0x80000000;  // a0000000 00000000 00000000 00000000
+    or  edx, ebx;         // a0000000 00000000 arrrrrgg gggbbbbb
+    mov ebx, eax;
+    and ebx, 0x00f80000;  // 00000000 rrrrr000 00000000 00000000
+    shl ebx, 7;           // 0rrrrr00 00000000 00000000 00000000
+    or  edx, ebx;         // arrrrr00 00000000 arrrrrgg gggbbbbb
+    mov ebx, eax;
+    and ebx, 0x0000f800;  // 00000000 00000000 ggggg000 00000000
+    shl ebx, 10;          // 000000gg ggg00000 00000000 00000000
+    or  edx, ebx;         // arrrrrgg ggg00000 arrrrrgg gggbbbbb
+    and eax, 0x000000f8;  // 00000000 00000000 00000000 bbbbb000
+    shl eax, 13;          // 00000000 000bbbbb 00000000 00000000
+    or  edx, eax;         // arrrrrgg gggbbbbb arrrrrgg gggbbbbb
+
+    mov dword ptr [edi], edx;
+    add edi, 4;
+#endif
+    dec ecx;
+    jnz tc1_loop;
+
+    pop edi;
+    pop esi;
+    pop ebx;
+  }
+#endif
+}
+
+void
+TxQuantize::ARGB8888_ARGB4444(uint32* src, uint32* dest, int width, int height)
+{
+#if 1
+  int siz = (width * height) >> 1;
+  int i;
+  for (i = 0; i < siz; i++) {
+    *dest = (((*src & 0xf0000000) >> 16) |
+             ((*src & 0x00f00000) >> 12) |
+             ((*src & 0x0000f000) >> 8) |
+             ((*src & 0x000000f0) >> 4));
+    src++;
+    *dest |= ((*src & 0xf0000000) |
+              ((*src & 0x00f00000) << 4) |
+              ((*src & 0x0000f000) << 8) |
+              ((*src & 0x000000f0) << 12));
+    src++;
+    dest++;
+  }
+#else
+  int siz = (width * height) >> 1;
+
+  __asm {
+    push ebx;
+    push esi;
+    push edi;
+
+    mov esi, dword ptr [src];
+    mov edi, dword ptr [dest];
+    mov ecx, dword ptr [siz];
+
+  tc1_loop:
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    mov edx, eax;
+    and edx, 0xf0000000;  // aaaa0000 00000000 00000000 00000000
+    shr edx, 16;          // 00000000 00000000 aaaa0000 00000000
+    mov ebx, eax;
+    and ebx, 0x00f00000;  // 00000000 rrrr0000 00000000 00000000
+    shr ebx, 12;          // 00000000 00000000 0000rrrr 00000000
+    or  edx, ebx;         // 00000000 00000000 aaaarrrr 00000000
+    mov ebx, eax;
+    and ebx, 0x0000f000;  // 00000000 00000000 gggg0000 00000000
+    shr ebx, 8;           // 00000000 00000000 00000000 gggg0000
+    or  edx, ebx;         // 00000000 00000000 aaaarrrr gggg0000
+    and eax, 0x000000f0;  // 00000000 00000000 00000000 bbbb0000
+    shr eax, 4;           // 00000000 00000000 00000000 0000bbbb
+    or  edx, eax;         // 00000000 00000000 aaaarrrr ggggbbbb
+
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    mov ebx, eax;
+    and ebx, 0xf0000000;  // aaaa0000 00000000 00000000 00000000
+    or  edx, ebx;         // aaaa0000 00000000 aaaarrrr ggggbbbb
+    mov ebx, eax;
+    and ebx, 0x00f00000;  // 00000000 rrrr0000 00000000 00000000
+    shl ebx, 4;           // 0000rrrr 00000000 00000000 00000000
+    or  edx, ebx;         // aaaarrrr 00000000 aaaarrrr ggggbbbb
+    mov ebx, eax;
+    and ebx, 0x0000f000;  // 00000000 00000000 gggg0000 00000000
+    shl ebx, 8;           // 00000000 gggg0000 00000000 00000000
+    or  edx, ebx;         // aaaarrrr gggg0000 aaaarrrr ggggbbbb
+    and eax, 0x000000f0;  // 00000000 00000000 00000000 bbbb0000
+    shl eax, 12;          // 00000000 0000bbbb 00000000 00000000
+    or  edx, eax;         // arrrrrgg ggggbbbb aaaarrrr ggggbbbb
+
+    mov dword ptr [edi], edx;
+    add edi, 4;
+
+    dec ecx;
+    jnz tc1_loop;
+
+    pop edi;
+    pop esi;
+    pop ebx;
+  }
+#endif
+}
+
+void
+TxQuantize::ARGB8888_RGB565(uint32* src, uint32* dest, int width, int height)
+{
+#if 1
+  int siz = (width * height) >> 1;
+  int i;
+  for (i = 0; i < siz; i++) {
+    *dest = (((*src & 0x000000f8) >> 3) |
+             ((*src & 0x0000fc00) >> 5) |
+             ((*src & 0x00f80000) >> 8));
+    src++;
+    *dest |= (((*src & 0x000000f8) << 13) |
+              ((*src & 0x0000fc00) << 11) |
+              ((*src & 0x00f80000) << 8));
+    src++;
+    dest++;
+  }
+#else
+  int siz = (width * height) >> 1;
+
+  __asm {
+    push ebx;
+    push esi;
+    push edi;
+
+    mov esi, dword ptr [src];
+    mov edi, dword ptr [dest];
+    mov ecx, dword ptr [siz];
+
+  tc1_loop:
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    mov edx, eax;
+    and edx, 0x000000F8;  // 00000000 00000000 00000000 bbbbb000
+    shr edx, 3;           // 00000000 00000000 00000000 000bbbbb
+    mov ebx, eax;
+    and ebx, 0x0000FC00;  // 00000000 00000000 gggggg00 00000000
+    shr ebx, 5;           // 00000000 00000000 00000ggg ggg00000
+    or  edx, ebx;         // 00000000 00000000 00000ggg gggbbbbb
+    mov ebx, eax;
+    and ebx, 0x00F80000;  // 00000000 rrrrr000 00000000 00000000
+    shr ebx, 8;           // 00000000 00000000 rrrrr000 00000000
+    or  edx, ebx;         // 00000000 00000000 rrrrrggg gggbbbbb
+
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    mov ebx, eax;
+    and ebx, 0x000000F8;  // 00000000 00000000 00000000 bbbbb000
+    shl ebx, 13;          // 00000000 000bbbbb 00000000 00000000
+    or  edx, ebx;         // 00000000 000bbbbb rrrrrggg gggbbbbb
+    mov ebx, eax;
+    and ebx, 0x0000FC00;  // 00000000 00000000 gggggg00 00000000
+    shl ebx, 11;          // 00000ggg ggg00000 00000000 00000000
+    or  edx, ebx;         // 00000ggg gggbbbbb rrrrrggg gggbbbbb
+    mov ebx, eax;
+    and ebx, 0x00F80000;  // 00000000 rrrrr000 00000000 00000000
+    shl ebx, 8;           // rrrrr000 00000000 00000000 00000000
+    or  edx, ebx;         // rrrrrggg gggbbbbb rrrrrggg gggbbbbb
+
+    mov dword ptr [edi], edx;
+    add edi, 4;
+
+    dec ecx;
+    jnz tc1_loop;
+
+    pop edi;
+    pop esi;
+    pop ebx;
+  }
+#endif
+}
+
+void
+TxQuantize::ARGB8888_A8(uint32* src, uint32* dest, int width, int height)
+{
+#if 1
+  int siz = (width * height) >> 2;
+  int i;
+  for (i = 0; i < siz; i++) {
+    *dest = (*src & 0x0000ff00) >> 8;
+    src++;
+    *dest |= (*src & 0x0000ff00);
+    src++;
+    *dest |= ((*src & 0x0000ff00) << 8);
+    src++;
+    *dest |= ((*src & 0x0000ff00) << 16);
+    src++;
+    dest++;
+  }
+#else
+  int siz = (width * height) >> 2;
+
+  __asm {
+    push ebx;
+    push esi;
+    push edi;
+
+    mov esi, dword ptr [src];
+    mov edi, dword ptr [dest];
+    mov ecx, dword ptr [siz];
+
+  tc1_loop:
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+#if 0
+    mov edx, eax;         // we'll use A comp for every pixel
+    and edx, 0xFF000000;  // aaaaaaaa 00000000 00000000 00000000
+    shr edx, 24;          // 00000000 00000000 00000000 aaaaaaaa
+
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    and eax, 0xFF000000;  // aaaaaaaa 00000000 00000000 00000000
+    shr eax, 16;          // 00000000 00000000 aaaaaaaa 00000000
+    or  edx, eax;         // 00000000 00000000 aaaaaaaa aaaaaaaa
+
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    and eax, 0xFF000000;  // aaaaaaaa 00000000 00000000 00000000
+    shr eax, 8;           // 00000000 aaaaaaaa 00000000 00000000
+    or  edx, eax;         // 00000000 aaaaaaaa aaaaaaaa aaaaaaaa
+
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    and eax, 0xFF000000;  // aaaaaaaa 00000000 00000000 00000000
+    or  edx, eax;         // aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa
+#endif
+
+#if 1
+    mov edx, eax;         // we'll use G comp for every pixel
+    and edx, 0x0000FF00;  // 00000000 00000000 aaaaaaaa 00000000
+    shr edx, 8;           // 00000000 00000000 00000000 aaaaaaaa
+
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    and eax, 0x0000FF00;  // 00000000 00000000 aaaaaaaa 00000000
+    or  edx, eax;         // 00000000 00000000 aaaaaaaa aaaaaaaa
+
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    and eax, 0x0000FF00;  // 00000000 00000000 aaaaaaaa 00000000
+    shl eax, 8;           // 00000000 aaaaaaaa 00000000 00000000
+    or  edx, eax;         // 00000000 aaaaaaaa aaaaaaaa aaaaaaaa
+
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    and eax, 0x0000FF00;  // 00000000 00000000 aaaaaaaa 00000000
+    shl eax, 16;          // aaaaaaaa 00000000 00000000 00000000
+    or  edx, eax;         // aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa
+#endif
+
+#if 0
+    mov edx, eax;
+    and edx, 0x000000FF;  // 00000000 00000000 00000000 aaaaaaaa
+
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    and eax, 0x0000FF00;  // 00000000 00000000 aaaaaaaa 00000000
+    or  edx, eax;         // 00000000 00000000 aaaaaaaa aaaaaaaa
+
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    and eax, 0x00FF0000;  // 00000000 aaaaaaaa 00000000 00000000
+    or  edx, eax;         // 00000000 aaaaaaaa aaaaaaaa aaaaaaaa
+
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    and eax, 0xFF000000;  // aaaaaaaa 00000000 00000000 00000000
+    or  edx, eax;         // aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa
+#endif
+    mov dword ptr [edi], edx;
+    add edi, 4;
+
+    dec ecx;
+    jnz tc1_loop;
+
+    pop edi;
+    pop esi;
+    pop ebx;
+  }
+#endif
+}
+
+void
+TxQuantize::ARGB8888_AI44(uint32* src, uint32* dest, int width, int height)
+{
+#if 1
+  int siz = (width * height) >> 2;
+  int i;
+  for (i = 0; i < siz; i++) {
+    *dest = (((*src & 0xf0000000) >> 24) | ((*src & 0x0000f000) >> 12));
+    src++;
+    *dest |= (((*src & 0xf0000000) >> 16) | ((*src & 0x0000f000) >> 4));
+    src++;
+    *dest |= (((*src & 0xf0000000) >> 8) | ((*src & 0x0000f000) << 4));
+    src++;
+    *dest |= ((*src & 0xf0000000) | ((*src & 0x0000f000) << 12));
+    src++;
+    dest++;
+  }
+#else
+  int siz = (width * height) >> 2;
+
+  __asm {
+    push ebx;
+    push esi;
+    push edi;
+
+    mov esi, dword ptr [src];
+    mov edi, dword ptr [dest];
+    mov ecx, dword ptr [siz];
+
+  tc1_loop:
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    mov edx, eax;         // use A and G comps MSB
+    and edx, 0xF0000000;  // aaaa0000 00000000 00000000 00000000
+    mov ebx, eax;
+    shr edx, 24;          // 00000000 00000000 00000000 aaaa0000
+    and ebx, 0x0000F000;  // 00000000 00000000 iiii0000 00000000
+    shr ebx, 12;          // 00000000 00000000 00000000 0000iiii
+    or  edx, ebx;         // 00000000 00000000 00000000 aaaaiiii
+
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    mov ebx, eax;
+    and eax, 0xF0000000;  // aaaa0000 00000000 00000000 00000000
+    shr eax, 16;          // 00000000 00000000 aaaa0000 00000000
+    and ebx, 0x0000F000;  // 00000000 00000000 iiii0000 00000000
+    shr ebx, 4;           // 00000000 00000000 0000iiii 00000000
+    or  eax, ebx;         // 00000000 00000000 aaaaiiii 00000000
+    or  edx, eax;         // 00000000 00000000 aaaaiiii aaaaiiii
+
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    mov ebx, eax;
+    and eax, 0xF0000000;  // aaaa0000 00000000 00000000 00000000
+    shr eax, 8;           // 00000000 aaaa0000 00000000 00000000
+    and ebx, 0x0000F000;  // 00000000 00000000 iiii0000 00000000
+    shl ebx, 4;           // 00000000 0000iiii 00000000 00000000
+    or  eax, ebx;         // 00000000 aaaaiiii 00000000 00000000
+    or  edx, eax;         // 00000000 aaaaiiii aaaaiiii aaaaiiii
+
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    mov ebx, eax;
+    and eax, 0xF0000000;   // aaaa0000 00000000 00000000 00000000
+    and ebx, 0x0000F000;   // 00000000 00000000 iiii0000 00000000
+    shl ebx, 12;           // 0000iiii 00000000 00000000 00000000
+    or  eax, ebx;          // aaaaiiii 00000000 00000000 00000000
+    or  edx, eax;          // aaaaiiii aaaaiiii aaaaiiii aaaaiiii
+
+    mov dword ptr [edi], edx;
+    add edi, 4;
+
+    dec ecx;
+    jnz tc1_loop;
+
+    pop edi;
+    pop esi;
+    pop ebx;
+  }
+#endif
+}
+
+void
+TxQuantize::ARGB8888_AI88(uint32* src, uint32* dest, int width, int height)
+{
+#if 1
+  int siz = (width * height) >> 1;
+  int i;
+  for (i = 0; i < siz; i++) {
+    *dest = (((*src & 0xff000000) >> 16) | ((*src & 0x0000ff00) >> 8));
+    src++;
+    *dest |= ((*src & 0xff000000) | ((*src & 0x0000ff00) << 8));
+    src++;
+    dest++;
+  }
+#else
+  int siz = (width * height) >> 1;
+
+  __asm {
+    push ebx;
+    push esi;
+    push edi;
+
+    mov esi, dword ptr [src];
+    mov edi, dword ptr [dest];
+    mov ecx, dword ptr [siz];
+
+  tc1_loop:
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    mov edx, eax;
+    and edx, 0xFF000000;   // aaaaaaaa 00000000 00000000 00000000
+    mov ebx, eax;
+    shr edx, 16;           // 00000000 00000000 aaaaaaaa 00000000
+    and ebx, 0x0000FF00;   // 00000000 00000000 iiiiiiii 00000000
+    shr ebx, 8;            // 00000000 00000000 00000000 iiiiiiii
+    or  edx, ebx;          // 00000000 00000000 aaaaaaaa iiiiiiii
+
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    mov ebx, eax;
+    and eax, 0xFF000000;    // aaaaaaaa 00000000 00000000 00000000
+    and ebx, 0x0000FF00;    // 00000000 00000000 iiiiiiii 00000000
+    shl ebx, 8;             // 00000000 iiiiiiii 00000000 00000000
+    or  eax, ebx;           // aaaaaaaa iiiiiiii 00000000 00000000
+    or  edx, eax;           // aaaaaaaa iiiiiiii aaaaaaaa iiiiiiii
+
+    mov dword ptr [edi], edx;
+    add edi, 4;
+
+    dec ecx;
+    jnz tc1_loop;
+
+    pop edi;
+    pop esi;
+    pop ebx;
+  }
+#endif
+}
+
+/* R.W. Floyd and L. Steinberg, An adaptive algorithm
+ * for spatial grey scale, Proceedings of the Society
+ * of Information Display 17, pp75-77, 1976
+ */
+void
+TxQuantize::ARGB8888_RGB565_ErrD(uint32* src, uint32* dst, int width, int height)
+{
+  /* Floyd-Steinberg error-diffusion halftoning */
+
+  int i, x, y;
+  int qr, qg, qb; /* quantized incoming values */
+  int ir, ig, ib; /* incoming values */
+  int t;
+  int *errR = new int[width];
+  int *errG = new int[width];
+  int *errB = new int[width];
+
+  uint16 *dest = (uint16 *)dst;
+
+  for (i = 0; i < width; i++) errR[i] = errG[i] = errB[i] = 0;
+
+  for (y = 0; y < height; y++) {
+    qr = qg = qb = 0;
+    for (x = 0; x < width; x++) {
+      /* incoming pixel values */
+      ir = ((*src >> 16) & 0xFF) * 10000;
+      ig = ((*src >>  8) & 0xFF) * 10000;
+      ib = ((*src      ) & 0xFF) * 10000;
+
+      /* quantize pixel values. 
+       * qr * 0.4375 is the error from the pixel to the left, 
+       * errR is the error from the pixel to the top, top left, and top right */
+      /* qr * 0.4375 is the error distribution to the EAST in 
+       * the previous loop */
+      ir += errR[x] + qr * 4375 / 10000;
+      ig += errG[x] + qg * 4375 / 10000;
+      ib += errB[x] + qb * 4375 / 10000;
+
+      /* error distribution to the SOUTH-EAST in the previous loop 
+       * can't calculate in the previous loop because it steps on 
+       * the above quantization */
+      errR[x] = qr * 625 / 10000;
+      errG[x] = qg * 625 / 10000;
+      errB[x] = qb * 625 / 10000;
+
+      qr = ir;
+      qg = ig;
+      qb = ib;
+
+      /* clamp */
+      if (qr < 0) qr = 0; else if (qr > 2550000) qr = 2550000; 
+      if (qg < 0) qg = 0; else if (qg > 2550000) qg = 2550000;
+      if (qb < 0) qb = 0; else if (qb > 2550000) qb = 2550000;
+
+      /* convert to RGB565 */
+      qr = qr * 0x1F / 2550000;
+      qg = qg * 0x3F / 2550000;
+      qb = qb * 0x1F / 2550000;
+
+      /* this is the dithered pixel */
+      t  = (qr << 11) | (qg << 5) | qb;
+
+      /* compute the errors */
+      qr = ((qr << 3) | (qr >> 2)) * 10000;
+      qg = ((qg << 2) | (qg >> 4)) * 10000;
+      qb = ((qb << 3) | (qb >> 2)) * 10000;
+      qr = ir - qr;
+      qg = ig - qg;
+      qb = ib - qb;
+
+      /* compute the error distributions */
+      /* Floyd-Steinberg filter
+       * 7/16 (=0.4375) to the EAST 
+       * 5/16 (=0.3125) to the SOUTH 
+       * 1/16 (=0.0625) to the SOUTH-EAST 
+       * 3/16 (=0.1875) to the SOUTH-WEST
+       *
+       *         x    7/16
+       *  3/16  5/16  1/16
+       */
+      /* SOUTH-WEST */
+      if (x > 1) {
+        errR[x - 1] += qr * 1875 / 10000;
+        errG[x - 1] += qg * 1875 / 10000;
+        errB[x - 1] += qb * 1875 / 10000;
+      }
+
+      /* SOUTH */
+      errR[x] += qr * 3125 / 10000;
+      errG[x] += qg * 3125 / 10000;
+      errB[x] += qb * 3125 / 10000;
+
+      *dest = (t & 0xFFFF);
+
+      dest++;
+      src++;
+    }
+  }
+
+  delete [] errR;
+  delete [] errG;
+  delete [] errB;
+}
+
+
+void
+TxQuantize::ARGB8888_ARGB1555_ErrD(uint32* src, uint32* dst, int width, int height)
+{
+  /* Floyd-Steinberg error-diffusion halftoning */
+
+  int i, x, y;
+  int qr, qg, qb; /* quantized incoming values */
+  int ir, ig, ib; /* incoming values */
+  int t;
+  int *errR = new int[width];
+  int *errG = new int[width];
+  int *errB = new int[width];
+
+  uint16 *dest = (uint16 *)dst;
+
+  for (i = 0; i < width; i++) errR[i] = errG[i] = errB[i] = 0;
+
+  for (y = 0; y < height; y++) {
+    qr = qg = qb = 0;
+    for (x = 0; x < width; x++) {
+      /* incoming pixel values */
+      ir = ((*src >> 16) & 0xFF) * 10000;
+      ig = ((*src >>  8) & 0xFF) * 10000;
+      ib = ((*src      ) & 0xFF) * 10000;
+
+      /* quantize pixel values. 
+       * qr * 0.4375 is the error from the pixel to the left, 
+       * errR is the error from the pixel to the top, top left, and top right */
+      /* qr * 0.4375 is the error distribution to the EAST in 
+       * the previous loop */
+      ir += errR[x] + qr * 4375 / 10000;
+      ig += errG[x] + qg * 4375 / 10000;
+      ib += errB[x] + qb * 4375 / 10000;
+
+      /* error distribution to the SOUTH-EAST of the previous loop. 
+       * cannot calculate in the previous loop because it steps on 
+       * the above quantization */
+      errR[x] = qr * 625 / 10000;
+      errG[x] = qg * 625 / 10000;
+      errB[x] = qb * 625 / 10000;
+
+      qr = ir;
+      qg = ig;
+      qb = ib;
+
+      /* clamp */
+      if (qr < 0) qr = 0; else if (qr > 2550000) qr = 2550000;
+      if (qg < 0) qg = 0; else if (qg > 2550000) qg = 2550000;
+      if (qb < 0) qb = 0; else if (qb > 2550000) qb = 2550000;
+
+      /* convert to RGB555 */
+      qr = qr * 0x1F / 2550000;
+      qg = qg * 0x1F / 2550000;
+      qb = qb * 0x1F / 2550000;
+
+      /* this is the dithered pixel */
+      t  = (qr << 10) | (qg << 5) | qb;
+      t |= ((*src >> 24) ? 0x8000 : 0);
+
+      /* compute the errors */
+      qr = ((qr << 3) | (qr >> 2)) * 10000;
+      qg = ((qg << 3) | (qg >> 2)) * 10000;
+      qb = ((qb << 3) | (qb >> 2)) * 10000;
+      qr = ir - qr;
+      qg = ig - qg;
+      qb = ib - qb;
+
+      /* compute the error distributions */
+      /* Floyd-Steinberg filter
+       * 7/16 (=0.4375) to the EAST 
+       * 5/16 (=0.3125) to the SOUTH 
+       * 1/16 (=0.0625) to the SOUTH-EAST 
+       * 3/16 (=0.1875) to the SOUTH-WEST
+       *
+       *         x    7/16
+       *  3/16  5/16  1/16
+       */
+      /* SOUTH-WEST */
+      if (x > 1) {
+        errR[x - 1] += qr * 1875 / 10000;
+        errG[x - 1] += qg * 1875 / 10000;
+        errB[x - 1] += qb * 1875 / 10000;
+      }
+
+      /* SOUTH */
+      errR[x] += qr * 3125 / 10000;
+      errG[x] += qg * 3125 / 10000;
+      errB[x] += qb * 3125 / 10000;
+
+      *dest = (t & 0xFFFF);
+
+      dest++;
+      src++;
+    }
+  }
+
+  delete [] errR;
+  delete [] errG;
+  delete [] errB;
+}
+
+void
+TxQuantize::ARGB8888_ARGB4444_ErrD(uint32* src, uint32* dst, int width, int height)
+{
+  /* Floyd-Steinberg error-diffusion halftoning */
+
+  /* NOTE: alpha dithering looks better for alpha gradients, but are prone
+   * to producing noisy speckles for constant or step level alpha. Output
+   * results should always be checked.
+   */
+  boolean ditherAlpha = 0;
+
+  int i, x, y;
+  int qr, qg, qb, qa; /* quantized incoming values */
+  int ir, ig, ib, ia; /* incoming values */
+  int t;
+  int *errR = new int[width];
+  int *errG = new int[width];
+  int *errB = new int[width];
+  int *errA = new int[width];
+
+  uint16 *dest = (uint16 *)dst;
+
+  for (i = 0; i < width; i++) errR[i] = errG[i] = errB[i] = errA[i] = 0;
+
+  for (y = 0; y < height; y++) {
+    qr = qg = qb = qa = 0;
+    for (x = 0; x < width; x++) {
+      /* incoming pixel values */
+      ir = ((*src >> 16) & 0xFF) * 10000;
+      ig = ((*src >>  8) & 0xFF) * 10000;
+      ib = ((*src      ) & 0xFF) * 10000;
+      ia = ((*src >> 24) & 0xFF) * 10000;
+
+      /* quantize pixel values. 
+       * qr * 0.4375 is the error from the pixel to the left, 
+       * errR is the error from the pixel to the top, top left, and top right */
+      /* qr * 0.4375 is the error distribution to the EAST in 
+       * the previous loop */
+      ir += errR[x] + qr * 4375 / 10000;
+      ig += errG[x] + qg * 4375 / 10000;
+      ib += errB[x] + qb * 4375 / 10000;
+      ia += errA[x] + qa * 4375 / 10000;
+
+      /* error distribution to the SOUTH-EAST of the previous loop. 
+       * cannot calculate in the previous loop because it steps on 
+       * the above quantization */
+      errR[x] = qr * 625 / 10000;
+      errG[x] = qg * 625 / 10000;
+      errB[x] = qb * 625 / 10000;
+      errA[x] = qa * 625 / 10000;
+
+      qr = ir;
+      qg = ig;
+      qb = ib;
+      qa = ia;
+
+      /* clamp */
+      if (qr < 0) qr = 0; else if (qr > 2550000) qr = 2550000;
+      if (qg < 0) qg = 0; else if (qg > 2550000) qg = 2550000;
+      if (qb < 0) qb = 0; else if (qb > 2550000) qb = 2550000;
+      if (qa < 0) qa = 0; else if (qa > 2550000) qa = 2550000;
+
+      /* convert to RGB444 */
+      qr = qr * 0xF / 2550000;
+      qg = qg * 0xF / 2550000;
+      qb = qb * 0xF / 2550000;
+      qa = qa * 0xF / 2550000;
+
+      /* this is the value to be returned */
+      if (ditherAlpha) {
+        t = (qa << 12) | (qr <<  8) | (qg << 4) | qb;
+      } else {
+        t = (qr <<  8) | (qg << 4) | qb;
+        t |= (*src >> 16) & 0xF000;
+      }
+
+      /* compute the errors */
+      qr = ((qr << 4) | qr) * 10000;
+      qg = ((qg << 4) | qg) * 10000;
+      qb = ((qb << 4) | qb) * 10000;
+      qa = ((qa << 4) | qa) * 10000;
+      qr = ir - qr;
+      qg = ig - qg;
+      qb = ib - qb;
+      qa = ia - qa;
+
+      /* compute the error distributions */
+      /* Floyd-Steinberg filter
+       * 7/16 (=0.4375) to the EAST 
+       * 5/16 (=0.3125) to the SOUTH 
+       * 1/16 (=0.0625) to the SOUTH-EAST 
+       * 3/16 (=0.1875) to the SOUTH-WEST
+       *
+       *         x    7/16
+       *  3/16  5/16  1/16
+       */
+      /* SOUTH-WEST */
+      if (x > 1) {
+        errR[x - 1] += qr * 1875 / 10000;
+        errG[x - 1] += qg * 1875 / 10000;
+        errB[x - 1] += qb * 1875 / 10000;
+        errA[x - 1] += qa * 1875 / 10000;
+      }
+
+      /* SOUTH */
+      errR[x] += qr * 3125 / 10000;
+      errG[x] += qg * 3125 / 10000;
+      errB[x] += qb * 3125 / 10000;
+      errA[x] += qa * 3125 / 10000;
+
+      *dest = (t & 0xFFFF);
+
+      dest++;
+      src++;
+    }
+  }
+
+  delete [] errR;
+  delete [] errG;
+  delete [] errB;
+  delete [] errA;
+}
+
+void
+TxQuantize::ARGB8888_AI44_ErrD(uint32* src, uint32* dst, int width, int height)
+{
+  /* Floyd-Steinberg error-diffusion halftoning */
+
+  /* NOTE: alpha dithering looks better for alpha gradients, but are prone
+   * to producing noisy speckles for constant or step level alpha. Output
+   * results should always be checked.
+   */
+  boolean ditherAlpha = 0;
+
+  int i, x, y;
+  int qi, qa; /* quantized incoming values */
+  int ii, ia; /* incoming values */
+  int t;
+  int *errI = new int[width];
+  int *errA = new int[width];
+
+  uint8 *dest = (uint8 *)dst;
+
+  for (i = 0; i < width; i++) errI[i] = errA[i] = 0;
+
+  for (y = 0; y < height; y++) {
+    qi = qa = 0;
+    for (x = 0; x < width; x++) {
+      /* 3dfx style Intensity = R * 0.299 + G * 0.587 + B * 0.114 */
+      ii = ((*src >> 16) & 0xFF) * 2990 +
+           ((*src >>  8) & 0xFF) * 5870 +
+           ((*src      ) & 0xFF) * 1140;
+      ia = ((*src >> 24) & 0xFF) * 10000;
+
+      /* quantize pixel values. 
+       * qi * 0.4375 is the error from the pixel to the left, 
+       * errI is the error from the pixel to the top, top left, and top right */
+      /* qi * 0.4375 is the error distrtibution to the EAST in
+       * the previous loop */
+      ii += errI[x] + qi * 4375 / 10000;
+      ia += errA[x] + qa * 4375 / 10000;
+
+      /* error distribution to the SOUTH-EAST in the previous loop. 
+       * cannot calculate in the previous loop because it steps on 
+       * the above quantization */
+      errI[x] = qi * 625 / 10000;
+      errA[x] = qa * 625 / 10000;
+
+      qi = ii;
+      qa = ia;
+
+      /* clamp */
+      if (qi < 0) qi = 0; else if (qi > 2550000) qi = 2550000;
+      if (qa < 0) qa = 0; else if (qa > 2550000) qa = 2550000;
+
+      /* convert to I4 */
+      qi = qi * 0xF / 2550000;
+      qa = qa * 0xF / 2550000;
+
+      /* this is the value to be returned */
+      if (ditherAlpha) {
+        t = (qa << 4) | qi;
+      } else {
+        t = qi;
+        t |= ((*src >> 24) & 0xF0);
+      }
+
+      /* compute the errors */
+      qi = ((qi << 4) | qi) * 10000;
+      qa = ((qa << 4) | qa) * 10000;
+      qi = ii - qi;
+      qa = ia - qa;
+
+      /* compute the error distributions */
+      /* Floyd-Steinberg filter
+       * 7/16 (=0.4375) to the EAST 
+       * 5/16 (=0.3125) to the SOUTH 
+       * 1/16 (=0.0625) to the SOUTH-EAST 
+       * 3/16 (=0.1875) to the SOUTH-WEST
+       *
+       *         x    7/16
+       *  3/16  5/16  1/16
+       */
+      /* SOUTH-WEST */
+      if (x > 1) {
+        errI[x - 1] += qi * 1875 / 10000;
+        errA[x - 1] += qa * 1875 / 10000;
+      }
+
+      /* SOUTH */
+      errI[x] += qi * 3125 / 10000;
+      errA[x] += qa * 3125 / 10000;
+
+      *dest = t & 0xFF;
+
+      dest++;
+      src++;
+    }
+  }
+
+  delete [] errI;
+  delete [] errA;
+}
+
+void
+TxQuantize::ARGB8888_AI88_Slow(uint32* src, uint32* dst, int width, int height)
+{
+  int x, y;
+  uint16 *dest = (uint16 *)dst;
+  for (y = 0; y < height; y++) {
+    for (x = 0; x < width; x++) {
+#if 1
+      /* libpng style grayscale conversion.
+       * Reduce RGB files to grayscale with or without alpha
+       * using the equation given in Poynton's ColorFAQ at
+       * <http://www.inforamp.net/~poynton/>
+       * Copyright (c) 1998-01-04 Charles Poynton poynton at inforamp.net
+       *
+       *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
+       *
+       *  We approximate this with
+       *
+       *     Y = 0.21268 * R    + 0.7151 * G    + 0.07217 * B
+       *
+       *  which can be expressed with integers as
+       *
+       *     Y = (6969 * R + 23434 * G + 2365 * B)/32768
+       *
+       *  The calculation is to be done in a linear colorspace.
+       */
+      *dest = (((int)((((*src >> 16) & 0xFF) * 6969 +
+                       ((*src >>  8) & 0xFF) * 23434 +
+                       ((*src      ) & 0xFF) * 2365) / 32768) & 0xFF) |
+              (uint16)((*src >> 16) & 0xFF00));
+#else
+      /* 3dfx style Intensity = R * 0.299 + G * 0.587 + B * 0.114
+       * this is same as the standard NTSC gray scale conversion. */
+      *dest = (((int)((((*src >> 16) & 0xFF) * 299 +
+                       ((*src >>  8) & 0xFF) * 587 +
+                       ((*src      ) & 0xFF) * 114) / 1000) & 0xFF) |
+              (uint16)((*src >> 16) & 0xFF00));
+#endif
+      dest++;
+      src++;
+    }
+  }
+}
+
+void
+TxQuantize::ARGB8888_I8_Slow(uint32* src, uint32* dst, int width, int height)
+{
+  int x, y;
+  uint8 *dest = (uint8 *)dst;
+  for (y = 0; y < height; y++) {
+    for (x = 0; x < width; x++) {
+#if 1
+      /* libpng style Intensity = (6969 * R + 23434 * G + 2365 * B)/32768 */
+      *dest = (int)((((*src >> 16) & 0xFF) * 6969 +
+                     ((*src >>  8) & 0xFF) * 23434 +
+                     ((*src      ) & 0xFF) * 2365) / 32768) & 0xFF;
+#else
+      /* 3dfx style Intensity = R * 0.299 + G * 0.587 + B * 0.114
+       * this is same as the standard NTSC gray scale conversion. */
+      *dest = (int)((((*src >>16) & 0xFF) * 299 +
+                     ((*src >> 8) & 0xFF) * 587 +
+                     ((*src     ) & 0xFF) * 114) / 1000) & 0xFF;
+#endif
+      dest++;
+      src++;
+    }
+  }
+}
+
+void
+TxQuantize::P8_16BPP(uint32* src, uint32* dest, int width, int height, uint32* palette)
+{
+  /* passed in palette is RGBA5551 format */
+#if 1
+  int i;
+  int size = width * height;
+  for (i = 0; i < size; i++) {
+    ((uint16*)dest)[i] = ((uint16*)palette)[(int)(((uint8*)src)[i])];
+    ((uint16*)dest)[i] = ((((uint16*)dest)[i] << 15) | (((uint16*)dest)[i] >> 1));
+  }
+#else
+
+  /* not finished yet... */
+
+  int siz = (width * height) >> 2;
+
+  __asm {
+    push ebx;
+    push esi;
+    push edi;
+
+    mov esi, dword ptr [src];
+    mov edi, dword ptr [dest];
+    mov ecx, dword ptr [siz];
+    mov edx, dword ptr [palette];
+
+  tc1_loop:
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    dec ecx;
+    jnz tc1_loop;
+
+    pop edi;
+    pop esi;
+    pop ebx;
+  }
+#endif
+}
+
+boolean
+TxQuantize::quantize(uint8* src, uint8* dest, int width, int height, uint16 srcformat, uint16 destformat, boolean fastQuantizer)
+{
+  typedef void (TxQuantize::*quantizerFunc)(uint32* src, uint32* dest, int width, int height);
+  quantizerFunc quantizer;
+  int bpp_shift = 0;
+
+  if (destformat == GR_TEXFMT_ARGB_8888) {
+    switch (srcformat) {
+    case GR_TEXFMT_ARGB_1555:
+      quantizer = &TxQuantize::ARGB1555_ARGB8888;
+      bpp_shift = 1;
+      break;
+    case GR_TEXFMT_ARGB_4444:
+      quantizer = &TxQuantize::ARGB4444_ARGB8888;
+      bpp_shift = 1;
+      break;
+    case GR_TEXFMT_RGB_565:
+      quantizer = &TxQuantize::RGB565_ARGB8888;
+      bpp_shift = 1;
+      break;
+    case GR_TEXFMT_ALPHA_8:
+      quantizer = &TxQuantize::A8_ARGB8888;
+      bpp_shift = 2;
+      break;
+    case GR_TEXFMT_ALPHA_INTENSITY_44:
+      quantizer = &TxQuantize::AI44_ARGB8888;
+      bpp_shift = 2;
+      break;
+    case GR_TEXFMT_ALPHA_INTENSITY_88:
+      quantizer = &TxQuantize::AI88_ARGB8888;
+      bpp_shift = 1;
+      break;
+    default:
+      return 0;
+    }
+
+#if !defined(NO_FILTER_THREAD)
+    unsigned int numcore = _numcore;
+    unsigned int blkrow = 0;
+    while (numcore > 1 && blkrow == 0) {
+      blkrow = (height >> 2) / numcore;
+      numcore--;
+    }
+    if (blkrow > 0 && numcore > 1) {
+      std::thread *thrd[MAX_NUMCORE];
+      unsigned int i;
+      int blkheight = blkrow << 2;
+      unsigned int srcStride = (width * blkheight) << (2 - bpp_shift);
+      unsigned int destStride = srcStride << bpp_shift;
+      for (i = 0; i < numcore - 1; i++) {
+        thrd[i] = new std::thread(std::bind(quantizer,
+                                            this,
+                                            (uint32*)src,
+                                            (uint32*)dest,
+                                            width,
+                                            blkheight));
+        src  += srcStride;
+        dest += destStride;
+      }
+      thrd[i] = new std::thread(std::bind(quantizer,
+                                          this,
+                                          (uint32*)src,
+                                          (uint32*)dest,
+                                          width,
+                                          height - blkheight * i));
+      for (i = 0; i < numcore; i++) {
+        thrd[i]->join();
+        delete thrd[i];
+      }
+    } else {
+      (*this.*quantizer)((uint32*)src, (uint32*)dest, width, height);
+    }
+#else
+    (*this.*quantizer)((uint32*)src, (uint32*)dest, width, height);
+#endif
+
+  } else if (srcformat == GR_TEXFMT_ARGB_8888) {
+    switch (destformat) {
+    case GR_TEXFMT_ARGB_1555:
+      quantizer = fastQuantizer ? &TxQuantize::ARGB8888_ARGB1555 : &TxQuantize::ARGB8888_ARGB1555_ErrD;
+      bpp_shift = 1;
+      break;
+    case GR_TEXFMT_ARGB_4444:
+      quantizer = fastQuantizer ? &TxQuantize::ARGB8888_ARGB4444 : &TxQuantize::ARGB8888_ARGB4444_ErrD;
+      bpp_shift = 1;
+      break;
+    case GR_TEXFMT_RGB_565:
+      quantizer = fastQuantizer ? &TxQuantize::ARGB8888_RGB565 : &TxQuantize::ARGB8888_RGB565_ErrD;
+      bpp_shift = 1;
+      break;
+    case GR_TEXFMT_ALPHA_8:
+    case GR_TEXFMT_INTENSITY_8:
+      quantizer = fastQuantizer ? &TxQuantize::ARGB8888_A8 : &TxQuantize::ARGB8888_I8_Slow;
+      bpp_shift = 2;
+      break;
+    case GR_TEXFMT_ALPHA_INTENSITY_44:
+      quantizer = fastQuantizer ? &TxQuantize::ARGB8888_AI44 : &TxQuantize::ARGB8888_AI44_ErrD;
+      bpp_shift = 2;
+      break;
+    case GR_TEXFMT_ALPHA_INTENSITY_88:
+      quantizer = fastQuantizer ? &TxQuantize::ARGB8888_AI88 : &TxQuantize::ARGB8888_AI88_Slow;
+      bpp_shift = 1;
+      break;
+    default:
+      return 0;
+    }
+
+#if !defined(NO_FILTER_THREAD)
+    unsigned int numcore = _numcore;
+    unsigned int blkrow = 0;
+    while (numcore > 1 && blkrow == 0) {
+      blkrow = (height >> 2) / numcore;
+      numcore--;
+    }
+    if (blkrow > 0 && numcore > 1) {
+      std::thread *thrd[MAX_NUMCORE];
+      unsigned int i;
+      int blkheight = blkrow << 2;
+      unsigned int srcStride = (width * blkheight) << 2;
+      unsigned int destStride = srcStride >> bpp_shift;
+      for (i = 0; i < numcore - 1; i++) {
+        thrd[i] = new std::thread(std::bind(quantizer,
+                                            this,
+                                            (uint32*)src,
+                                            (uint32*)dest,
+                                            width,
+                                            blkheight));
+        src  += srcStride;
+        dest += destStride;
+      }
+      thrd[i] = new std::thread(std::bind(quantizer,
+                                          this,
+                                          (uint32*)src,
+                                          (uint32*)dest,
+                                          width,
+                                          height - blkheight * i));
+      for (i = 0; i < numcore; i++) {
+        thrd[i]->join();
+        delete thrd[i];
+      }
+    } else {
+      (*this.*quantizer)((uint32*)src, (uint32*)dest, width, height);
+    }
+#else
+    (*this.*quantizer)((uint32*)src, (uint32*)dest, width, height);
+#endif
+
+  } else {
+    return 0;
+  }
+
+  return 1;
+}
+
+boolean
+TxQuantize::FXT1(uint8 *src, uint8 *dest,
+             int srcwidth, int srcheight, uint16 srcformat,
+             int *destwidth, int *destheight, uint16 *destformat)
+{
+  /*
+   * NOTE: src must be in ARGB8888 format, srcformat describes
+   * the closest 16bbp representation of src.
+   *
+   * NOTE: I have modified the dxtn library to use ARGB format
+   * which originaly was ABGR format.
+   */
+
+  boolean bRet = 0;
+
+  if (_tx_compress_fxt1 &&
+      srcwidth >= 8 && srcheight >= 4) {
+    /* compress to fxt1
+     * width and height must be larger than 8 and 4 respectively
+     */
+    int dstRowStride = ((srcwidth + 7) & ~7) << 1;
+    int srcRowStride = (srcwidth << 2);
+
+#if !defined(NO_FILTER_THREAD)
+    unsigned int numcore = _numcore;
+    unsigned int blkrow = 0;
+    while (numcore > 1 && blkrow == 0) {
+      blkrow = (srcheight >> 2) / numcore;
+      numcore--;
+    }
+    if (blkrow > 0 && numcore > 1) {
+      std::thread *thrd[MAX_NUMCORE];
+      unsigned int i;
+      int blkheight = blkrow << 2;
+      unsigned int srcStride = (srcwidth * blkheight) << 2;
+      unsigned int destStride = dstRowStride * blkrow;
+      for (i = 0; i < numcore - 1; i++) {
+        thrd[i] = new std::thread(std::bind(_tx_compress_fxt1,
+                                            srcwidth,
+                                            blkheight,
+                                            4,
+                                            src,
+                                            srcRowStride,
+                                            dest,
+                                            dstRowStride));
+        src  += srcStride;
+        dest += destStride;
+      }
+      thrd[i] = new std::thread(std::bind(_tx_compress_fxt1,
+                                          srcwidth,
+                                          srcheight - blkheight * i,
+                                          4,
+                                          src,
+                                          srcRowStride,
+                                          dest,
+                                          dstRowStride));
+      for (i = 0; i < numcore; i++) {
+        thrd[i]->join();
+        delete thrd[i];
+      }
+    } else {
+      (*_tx_compress_fxt1)(srcwidth,      /* width */
+                           srcheight,     /* height */
+                           4,             /* comps: ARGB8888=4, RGB888=3 */
+                           src,           /* source */
+                           srcRowStride,  /* width*comps */
+                           dest,          /* destination */
+                           dstRowStride); /* 16 bytes per 8x4 texel */
+    }
+#else
+    (*_tx_compress_fxt1)(srcwidth,      /* width */
+                         srcheight,     /* height */
+                         4,             /* comps: ARGB8888=4, RGB888=3 */
+                         src,           /* source */
+                         srcRowStride,  /* width*comps */
+                         dest,          /* destination */
+                         dstRowStride); /* 16 bytes per 8x4 texel */
+#endif
+
+    /* dxtn adjusts width and height to M8 and M4 respectively by replication */
+    *destwidth  = (srcwidth  + 7) & ~7;
+    *destheight = (srcheight + 3) & ~3;
+    *destformat = GR_TEXFMT_ARGB_CMP_FXT1;
+
+    bRet = 1;
+  }
+  
+  return bRet;
+}
+
+boolean
+TxQuantize::DXTn(uint8 *src, uint8 *dest,
+             int srcwidth, int srcheight, uint16 srcformat,
+             int *destwidth, int *destheight, uint16 *destformat)
+{
+  /*
+   * NOTE: src must be in ARGB8888 format, srcformat describes
+   * the closest 16bbp representation of src.
+   *
+   * NOTE: I have modified the dxtn library to use ARGB format
+   * which originaly was ABGR format.
+   */
+
+  boolean bRet = 0;
+
+  if (_tx_compress_dxtn &&
+      srcwidth >= 4 && srcheight >= 4) {
+    /* compress to dxtn
+     * width and height must be larger than 4
+     */
+
+    /* skip formats that DXTn won't help in size. */
+    if (srcformat == GR_TEXFMT_ALPHA_8 ||
+        srcformat == GR_TEXFMT_ALPHA_INTENSITY_44) {
+      ; /* shutup compiler */
+    } else {
+      int dstRowStride = ((srcwidth + 3) & ~3) << 2;
+      int compression = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+
+      *destformat = GR_TEXFMT_ARGB_CMP_DXT5;
+
+#if !GLIDE64_DXTN
+      /* okay... we are going to disable DXT1 with 1bit alpha
+       * for Glide64. some textures have all 0 alpha values.
+       * see "N64 Kobe Bryant in NBA Courtside"
+       */
+      if (srcformat == GR_TEXFMT_ARGB_1555) {
+        dstRowStride >>= 1;
+        compression = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+        *destformat = GR_TEXFMT_ARGB_CMP_DXT1;
+      } else
+#endif
+      if (srcformat == GR_TEXFMT_RGB_565 ||
+          srcformat == GR_TEXFMT_INTENSITY_8) {
+        dstRowStride >>= 1;
+        compression = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+        *destformat = GR_TEXFMT_ARGB_CMP_DXT1;
+      }
+
+#if !defined(NO_FILTER_THREAD)
+      unsigned int numcore = _numcore;
+      unsigned int blkrow = 0;
+      while (numcore > 1 && blkrow == 0) {
+        blkrow = (srcheight >> 2) / numcore;
+        numcore--;
+      }
+      if (blkrow > 0 && numcore > 1) {
+        std::thread *thrd[MAX_NUMCORE];
+        unsigned int i;
+        int blkheight = blkrow << 2;
+        unsigned int srcStride = (srcwidth * blkheight) << 2;
+        unsigned int destStride = dstRowStride * blkrow;
+        for (i = 0; i < numcore - 1; i++) {
+          thrd[i] = new std::thread(std::bind(_tx_compress_dxtn,
+                                              4,
+                                              srcwidth,
+                                              blkheight,
+                                              src,
+                                              compression,
+                                              dest,
+                                              dstRowStride));
+          src  += srcStride;
+          dest += destStride;
+        }
+        thrd[i] = new std::thread(std::bind(_tx_compress_dxtn,
+                                            4,
+                                            srcwidth,
+                                            srcheight - blkheight * i,
+                                            src,
+                                            compression,
+                                            dest,
+                                            dstRowStride));
+        for (i = 0; i < numcore; i++) {
+          thrd[i]->join();
+          delete thrd[i];
+        }
+      } else {
+        (*_tx_compress_dxtn)(4,             /* comps: ARGB8888=4, RGB888=3 */
+                             srcwidth,      /* width */
+                             srcheight,     /* height */
+                             src,           /* source */
+                             compression,   /* format */
+                             dest,          /* destination */
+                             dstRowStride); /* DXT1 = 8 bytes per 4x4 texel
+                                             * others = 16 bytes per 4x4 texel */
+      }
+#else
+      (*_tx_compress_dxtn)(4,             /* comps: ARGB8888=4, RGB888=3 */
+                           srcwidth,      /* width */
+                           srcheight,     /* height */
+                           src,           /* source */
+                           compression,   /* format */
+                           dest,          /* destination */
+                           dstRowStride); /* DXT1 = 8 bytes per 4x4 texel
+                                           * others = 16 bytes per 4x4 texel */
+#endif
+
+      /* dxtn adjusts width and height to M4 by replication */
+      *destwidth  = (srcwidth  + 3) & ~3;
+      *destheight = (srcheight + 3) & ~3;
+
+      bRet = 1;
+    }
+  }
+
+  return bRet;
+}
+
+boolean
+TxQuantize::compress(uint8 *src, uint8 *dest,
+                    int srcwidth, int srcheight, uint16 srcformat,
+                    int *destwidth, int *destheight, uint16 *destformat,
+                    int compressionType)
+{
+  boolean bRet = 0;
+
+  switch (compressionType) {
+  case FXT1_COMPRESSION:
+    bRet = FXT1(src, dest,
+                srcwidth, srcheight, srcformat,
+                destwidth, destheight, destformat);
+    break;
+  case S3TC_COMPRESSION:
+    bRet = DXTn(src, dest,
+                srcwidth, srcheight, srcformat,
+                destwidth, destheight, destformat);
+    break;
+  case NCC_COMPRESSION:
+    /* TODO: narrow channel compression */
+    ;
+  }
+
+  return bRet;
+}
+
+#if 0 /* unused */
+void
+TxQuantize::I8_ARGB8888(uint32* src, uint32* dest, int width, int height)
+{
+  int siz = (width * height) >> 2;
+
+  __asm {
+    push ebx;
+    push esi;
+    push edi;
+
+    mov esi, dword ptr [src];
+    mov edi, dword ptr [dest];
+    mov ecx, dword ptr [siz];
+
+  tc1_loop:
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    // aaaaaaaa
+    // 11111111 aaaaaaaa aaaaaaaa aaaaaaaa
+    mov edx, eax;
+    and eax, 0x000000ff;
+    mov ebx, eax;        // 00000000 00000000 00000000 aaaaaaaa
+    shl ebx, 8;          // 00000000 00000000 aaaaaaaa 00000000
+    or  eax, ebx;        // 00000000 00000000 aaaaaaaa aaaaaaaa
+    shl ebx, 8;         // 00000000 aaaaaaaa 00000000 00000000
+    or  eax, ebx;        // 00000000 aaaaaaaa aaaaaaaa aaaaaaaa
+    or  eax, 0xff000000; // 11111111 aaaaaaaa aaaaaaaa aaaaaaaa
+
+    mov dword ptr [edi], eax;
+    add edi, 4;
+
+    mov eax, edx;
+    and eax, 0x0000ff00;
+    mov ebx, eax;        // 00000000 00000000 aaaaaaaa 00000000
+    shr ebx, 8;          // 00000000 00000000 00000000 aaaaaaaa
+    or  eax, ebx;        // 00000000 00000000 aaaaaaaa aaaaaaaa
+    shl ebx, 16;         // 00000000 aaaaaaaa 00000000 00000000
+    or  eax, ebx;        // 00000000 aaaaaaaa aaaaaaaa aaaaaaaa
+    or  eax, 0xff000000; // 11111111 aaaaaaaa aaaaaaaa aaaaaaaa
+
+    mov dword ptr [edi], eax;
+    add edi, 4;
+
+    mov eax, edx;
+    and eax, 0x00ff0000;
+    mov ebx, eax;        // 00000000 aaaaaaaa 00000000 00000000
+    shr ebx, 8;          // 00000000 00000000 aaaaaaaa 00000000
+    or  eax, ebx;        // 00000000 aaaaaaaa aaaaaaaa 00000000
+    shr ebx, 8;         // 00000000 00000000 00000000 aaaaaaaa
+    or  eax, ebx;        // 00000000 aaaaaaaa aaaaaaaa aaaaaaaa
+    or  eax, 0xff000000; // 11111111 aaaaaaaa aaaaaaaa aaaaaaaa
+
+    mov dword ptr [edi], eax;
+    add edi, 4;
+
+    mov eax, edx;
+    and eax, 0xff000000;
+    mov ebx, eax;        // aaaaaaaa 00000000 00000000 00000000
+    shr ebx, 8;          // 00000000 aaaaaaaa 00000000 00000000
+    or  eax, ebx;        // aaaaaaaa aaaaaaaa 00000000 00000000
+    shr ebx, 8;         // 00000000 00000000 aaaaaaaa 00000000
+    or  eax, ebx;        // aaaaaaaa aaaaaaaa aaaaaaaa 00000000
+    shr eax, 8;         // 00000000 aaaaaaaa aaaaaaaa aaaaaaaa
+    or  eax, 0xff000000; // 11111111 aaaaaaaa aaaaaaaa aaaaaaaa
+
+    mov dword ptr [edi], eax;
+    add edi, 4;
+
+    dec ecx;
+    jnz tc1_loop;
+
+    pop edi;
+    pop esi;
+    pop ebx;
+  }
+}
+
+void
+TxQuantize::ARGB8888_I8(uint32* src, uint32* dest, int width, int height)
+{
+  ARGB8888_A8(src, dest, width, height);
+}
+
+void
+TxQuantize::ARGB1555_ABGR8888(uint32* src, uint32* dest, int width, int height)
+{
+  int siz = (width * height) >> 1;
+
+  __asm {
+    push ebx;
+    push esi;
+    push edi;
+
+    mov esi, dword ptr [src];
+    mov edi, dword ptr [dest];
+    mov ecx, dword ptr [siz];
+
+  tc1_loop:
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    // arrr rrgg gggb bbbb
+    // aaaaaaaa bbbbbbbb gggggggg rrrrrrrr
+    mov edx, eax;         // edx = arrrrrgg gggbbbbb arrrrrgg gggbbbbb
+    and ebx, 0x00000000;
+    and eax, 0x00008000;  // eax = 00000000 00000000 a0000000 00000000
+    jz  transparent1;
+    or  ebx, 0xff000000;  // ebx = aaaaaaaa 00000000 00000000 00000000
+
+  transparent1:
+    mov eax, edx;         // eax = arrrrrgg gggbbbbb arrrrrgg gggbbbbb
+    and edx, 0x0000001f;  // edx = 00000000 00000000 00000000 000bbbbb
+    shl edx, 14;          // edx = 00000000 00000bbb bb000000 00000000
+    or  ebx, edx;         // ebx = aaaaaaaa 00000bbb bb000000 00000000
+    shl edx, 5;           // edx = 00000000 bbbbb000 00000000 00000000
+    or  ebx, edx;         // ebx = aaaaaaaa bbbbbbbb bb000000 00000000
+    and ebx, 0xffff0000;  // ebx = aaaaaaaa bbbbbbbb 00000000 00000000
+    mov edx, eax;
+    and edx, 0x000003e0;  // edx = 00000000 00000000 000000gg ggg00000
+    shl edx, 1;           // edx = 00000000 00000000 00000ggg gg000000
+    or  ebx, edx;         // ebx = aaaaaaaa bbbbbbbb 00000ggg gg000000
+    shl edx, 5;           // edx = 00000000 00000000 ggggg000 00000000
+    or  ebx, edx;         // ebx = aaaaaaaa bbbbbbbb gggggggg gg000000
+    and ebx, 0xffffff00;  // ebx = aaaaaaaa bbbbbbbb gggggggg 00000000
+    mov edx, eax;
+    and edx, 0x00007c00;  // edx = 00000000 00000000 0rrrrr00 00000000
+    shr edx, 7;           // edx = 00000000 00000000 00000000 rrrrr000
+    or  ebx, edx;         // ebx = aaaaaaaa bbbbbbbb gggggggg rrrrr000
+    shr edx, 5;           // edx = 00000000 00000000 00000000 00000rrr
+    or  ebx, edx;         // ebx = aaaaaaaa bbbbbbbb gggggggg rrrrrrrr
+
+    mov dword ptr [edi], ebx;
+    add edi, 4;
+
+    shr eax, 16;          // eax = 00000000 00000000 arrrrrgg gggbbbbb
+    mov edx, eax;         // edx = 00000000 00000000 arrrrrgg gggbbbbb
+    and ebx, 0x00000000;
+    and eax, 0x00008000;  // eax = 00000000 00000000 a0000000 00000000
+    jz  transparent2;
+    or  ebx, 0xff000000;  // ebx = aaaaaaaa 00000000 00000000 00000000
+
+  transparent2:
+    mov eax, edx;         // eax = arrrrrgg gggbbbbb arrrrrgg gggbbbbb
+    and edx, 0x0000001f;  // edx = 00000000 00000000 00000000 000bbbbb
+    shl edx, 14;          // edx = 00000000 00000bbb bb000000 00000000
+    or  ebx, edx;         // ebx = aaaaaaaa 00000bbb bb000000 00000000
+    shl edx, 5;           // edx = 00000000 bbbbb000 00000000 00000000
+    or  ebx, edx;         // ebx = aaaaaaaa bbbbbbbb bb000000 00000000
+    and ebx, 0xffff0000;  // ebx = aaaaaaaa bbbbbbbb 00000000 00000000
+    mov edx, eax;
+    and edx, 0x000003e0;  // edx = 00000000 00000000 000000gg ggg00000
+    shl edx, 1;           // edx = 00000000 00000000 00000ggg gg000000
+    or  ebx, edx;         // ebx = aaaaaaaa bbbbbbbb 00000ggg gg000000
+    shl edx, 5;           // edx = 00000000 00000000 ggggg000 00000000
+    or  ebx, edx;         // ebx = aaaaaaaa bbbbbbbb gggggggg gg000000
+    and ebx, 0xffffff00;  // ebx = aaaaaaaa bbbbbbbb gggggggg 00000000
+    mov edx, eax;
+    and edx, 0x00007c00;  // edx = 00000000 00000000 0rrrrr00 00000000
+    shr edx, 7;           // edx = 00000000 00000000 00000000 rrrrr000
+    or  ebx, edx;         // ebx = aaaaaaaa bbbbbbbb gggggggg rrrrr000
+    shr edx, 5;           // edx = 00000000 00000000 00000000 00000rrr
+    or  ebx, edx;         // ebx = aaaaaaaa bbbbbbbb gggggggg rrrrrrrr
+
+    mov dword ptr [edi], ebx;
+    add edi, 4;
+
+    dec ecx;
+    jnz tc1_loop;
+
+    pop edi;
+    pop esi;
+    pop ebx;
+  }
+}
+
+void
+TxQuantize::ARGB4444_ABGR8888(uint32* src, uint32* dest, int width, int height)
+{
+  int siz = (width * height) >> 1;
+
+  __asm {
+    push ebx;
+    push esi;
+    push edi;
+
+    mov esi, dword ptr [src];
+    mov edi, dword ptr [dest];
+    mov ecx, dword ptr [siz];
+
+  tc1_loop:
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    // aaaa rrrr gggg bbbb
+    // aaaaaaaa bbbbbbbb gggggggg rrrrrrrr
+    mov edx, eax;
+    and eax, 0x0000ffff;
+    mov ebx, eax;        // 00000000 00000000 aaaarrrr ggggbbbb
+    and ebx, 0x0000f000; // 00000000 00000000 aaaa0000 00000000
+    shl ebx, 12;         // 0000aaaa 00000000 00000000 00000000
+    or  eax, ebx;        // 0000aaaa 00000000 aaaarrrr ggggbbbb
+    mov ebx, eax;
+    and ebx, 0x0000000f; // 00000000 00000000 00000000 0000bbbb
+    shl ebx, 16;         // 00000000 0000bbbb 00000000 00000000
+    or  eax, ebx;        // 0000aaaa 0000bbbb aaaarrrr ggggbbbb
+    mov ebx, eax;
+    and ebx, 0x00000f00; // 00000000 00000000 0000rrrr 00000000
+    shr ebx, 8;          // 00000000 00000000 00000000 0000rrrr
+    and eax, 0xfffffff0;
+    or  eax, ebx;        // 0000aaaa 0000bbbb aaaarrrr ggggrrrr
+    mov ebx, eax;
+    and ebx, 0x000000f0; // 00000000 00000000 00000000 gggg0000
+    shl ebx, 4;          // 00000000 00000000 0000gggg 00000000
+    and eax, 0x0f0f000f; // 0000aaaa 0000bbbb 00000000 0000rrrr
+    or  eax, ebx;        // 0000aaaa 0000bbbb 0000gggg 0000rrrr
+    mov ebx, eax;
+    shl ebx, 4;          // aaaa0000 bbbb0000 gggg0000 rrrr0000
+    or  eax, ebx;        // aaaaaaaa bbbbbbbb gggggggg rrrrrrrr
+
+    mov dword ptr [edi], eax;
+
+    add edi, 4;
+
+    shr edx, 16;
+    mov ebx, edx;        // 00000000 00000000 aaaarrrr ggggbbbb
+    and ebx, 0x0000f000; // 00000000 00000000 aaaa0000 00000000
+    shl ebx, 12;         // 0000aaaa 00000000 00000000 00000000
+    or  edx, ebx;        // 0000aaaa 00000000 aaaarrrr ggggbbbb
+    mov ebx, edx;
+    and ebx, 0x0000000f; // 00000000 00000000 00000000 0000bbbb
+    shl ebx, 16;         // 00000000 0000bbbb 00000000 00000000
+    or  edx, ebx;        // 0000aaaa 0000bbbb aaaarrrr ggggbbbb
+    mov ebx, edx;
+    and ebx, 0x00000f00; // 00000000 00000000 0000rrrr 00000000
+    shr ebx, 8;          // 00000000 00000000 00000000 0000rrrr
+    and edx, 0xfffffff0;
+    or  edx, ebx;        // 0000aaaa 0000bbbb aaaarrrr ggggrrrr
+    mov ebx, edx;
+    and ebx, 0x000000f0; // 00000000 00000000 00000000 gggg0000
+    shl ebx, 4;          // 00000000 00000000 0000gggg 00000000
+    and edx, 0x0f0f000f; // 0000aaaa 0000bbbb 00000000 0000rrrr
+    or  edx, ebx;        // 0000aaaa 0000bbbb 0000gggg 0000rrrr
+    mov ebx, edx;
+    shl ebx, 4;          // aaaa0000 bbbb0000 gggg0000 rrrr0000
+    or  edx, ebx;        // aaaaaaaa bbbbbbbb gggggggg rrrrrrrr
+
+    mov dword ptr [edi], edx;
+    add edi, 4;
+
+    dec ecx;
+    jnz tc1_loop;
+
+    pop edi;
+    pop esi;
+    pop ebx;
+  }
+}
+
+void
+TxQuantize::ARGB8888_ABGR8888(uint32* src, uint32* dest, int width, int height)
+{
+  int siz = width * height;
+
+  __asm {
+    push ebx;
+    push esi;
+    push edi;
+
+    mov esi, dword ptr [src];
+    mov edi, dword ptr [dest];
+    mov ecx, dword ptr [siz];
+
+  tc1_loop:
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    // aaaaaaaa bbbbbbbb gggggggg rrrrrrrr
+    mov edx, eax;
+    bswap edx;
+    shr edx, 8;
+    and eax, 0xff000000;
+
+    or eax, edx;
+
+    mov dword ptr [edi], eax;
+    add edi, 4;
+
+    dec ecx;
+    jnz tc1_loop;
+
+    pop edi;
+    pop esi;
+    pop ebx;
+  }
+}
+#endif
diff --git a/source/gles2glide64/src/GlideHQ/TxQuantize.h b/source/gles2glide64/src/GlideHQ/TxQuantize.h
new file mode 100644 (file)
index 0000000..d3c6ae6
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __TXQUANTIZE_H__
+#define __TXQUANTIZE_H__
+
+/* Glide64 DXTn workaround
+ * (0:disable, 1:enable) */
+#define GLIDE64_DXTN 1
+
+#include "TxInternal.h"
+#include "TxUtil.h"
+
+class TxQuantize
+{
+private:
+  TxUtil *_txUtil;
+  int _numcore;
+
+  fxtCompressTexFuncExt _tx_compress_fxt1;
+  dxtCompressTexFuncExt _tx_compress_dxtn;
+
+  /* fast optimized... well, sort of. */
+  void ARGB1555_ARGB8888(uint32* src, uint32* dst, int width, int height);
+  void ARGB4444_ARGB8888(uint32* src, uint32* dst, int width, int height);
+  void RGB565_ARGB8888(uint32* src, uint32* dst, int width, int height);
+  void A8_ARGB8888(uint32* src, uint32* dst, int width, int height);
+  void AI44_ARGB8888(uint32* src, uint32* dst, int width, int height);
+  void AI88_ARGB8888(uint32* src, uint32* dst, int width, int height);
+
+  void ARGB8888_ARGB1555(uint32* src, uint32* dst, int width, int height);
+  void ARGB8888_ARGB4444(uint32* src, uint32* dst, int width, int height);
+  void ARGB8888_RGB565(uint32* src, uint32* dst, int width, int height);
+  void ARGB8888_A8(uint32* src, uint32* dst, int width, int height);
+  void ARGB8888_AI44(uint32* src, uint32* dst, int width, int height);
+  void ARGB8888_AI88(uint32* src, uint32* dst, int width, int height);
+
+  /* quality */
+  void ARGB8888_RGB565_ErrD(uint32* src, uint32* dst, int width, int height);
+  void ARGB8888_ARGB1555_ErrD(uint32* src, uint32* dst, int width, int height);
+  void ARGB8888_ARGB4444_ErrD(uint32* src, uint32* dst, int width, int height);
+  void ARGB8888_AI44_ErrD(uint32* src, uint32* dst, int width, int height);
+  void ARGB8888_AI88_Slow(uint32* src, uint32* dst, int width, int height);
+  void ARGB8888_I8_Slow(uint32* src, uint32* dst, int width, int height);
+
+  /* compressors */
+  boolean FXT1(uint8 *src, uint8 *dest,
+               int srcwidth, int srcheight, uint16 srcformat,
+               int *destwidth, int *destheight, uint16 *destformat);
+  boolean DXTn(uint8 *src, uint8 *dest,
+               int srcwidth, int srcheight, uint16 srcformat,
+               int *destwidth, int *destheight, uint16 *destformat);
+
+public:
+  TxQuantize();
+  ~TxQuantize();
+
+  /* others */
+  void P8_16BPP(uint32* src, uint32* dst, int width, int height, uint32* palette);
+
+  boolean quantize(uint8* src, uint8* dest, int width, int height, uint16 srcformat, uint16 destformat, boolean fastQuantizer = 1);
+
+  boolean compress(uint8 *src, uint8 *dest,
+                   int srcwidth, int srcheight, uint16 srcformat,
+                   int *destwidth, int *destheight, uint16 *destformat,
+                   int compressionType);
+
+
+#if 0 /* unused */
+  void ARGB8888_I8(uint32* src, uint32* dst, int width, int height);
+  void I8_ARGB8888(uint32* src, uint32* dst, int width, int height);
+  
+  void ARGB1555_ABGR8888(uint32* src, uint32* dst, int width, int height);
+  void ARGB4444_ABGR8888(uint32* src, uint32* dst, int width, int height);
+  void ARGB8888_ABGR8888(uint32* src, uint32* dst, int width, int height);
+#endif
+};
+
+#endif /* __TXQUANTIZE_H__ */
diff --git a/source/gles2glide64/src/GlideHQ/TxReSample.cpp b/source/gles2glide64/src/GlideHQ/TxReSample.cpp
new file mode 100644 (file)
index 0000000..138428b
--- /dev/null
@@ -0,0 +1,417 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "TxReSample.h"
+#include "TxDbg.h"
+#include <stdlib.h>
+#include <memory.h>
+
+#define _USE_MATH_DEFINES
+#include <math.h>
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+int
+TxReSample::nextPow2(int num)
+{
+  num = num - 1;
+  num = num | (num >> 1);
+  num = num | (num >> 2);
+  num = num | (num >> 4);
+  num = num | (num >> 8);
+  num = num | (num >> 16);
+  /*num = num | (num >> 32);*//* for 64bit architecture */
+  num = num + 1;
+
+  return num;
+}
+
+boolean
+TxReSample::nextPow2(uint8** image, int* width, int* height, int bpp, boolean use_3dfx = 0)
+{
+  /* NOTE: bpp must be one of the follwing: 8, 16, 24, 32 bits per pixel */
+
+  if (!*image || !*width || !*height || !bpp)
+    return 0;
+
+  int row_bytes = ((*width * bpp) >> 3);
+  int o_row_bytes = row_bytes;
+  int o_width = *width;
+  int n_width = *width;
+  int o_height = *height;
+  int n_height = *height;
+
+  /* HACKALERT: I have explicitly subtracted (n) from width/height to
+   * adjust textures that have (n) pixel larger width/height than
+   * power of 2 size. This is a dirty hack for textures that have
+   * munged aspect ratio by (n) pixel to the original.
+   */
+  if      (n_width  > 64) n_width  -= 4;
+  else if (n_width  > 16) n_width  -= 2;
+  else if (n_width  >  4) n_width  -= 1;
+
+  if      (n_height > 64) n_height -= 4;
+  else if (n_height > 16) n_height -= 2;
+  else if (n_height >  4) n_height -= 1;
+
+  n_width = nextPow2(n_width);
+  n_height = nextPow2(n_height);
+  row_bytes = (n_width * bpp) >> 3;
+
+  /* 3dfx Glide3 format, W:H aspect ratio range (8:1 - 1:8) */
+  if (use_3dfx) {
+    if (n_width > n_height) {
+      if (n_width > (n_height << 3))
+        n_height = n_width >> 3;
+    } else {
+      if (n_height > (n_width << 3)) {
+        n_width = n_height >> 3;
+        row_bytes = (n_width * bpp) >> 3;
+      }
+    }
+    DBG_INFO(80, L"using 3dfx W:H aspect ratio range (8:1 - 1:8).\n");
+  }
+
+  /* do we really need to do this ? */
+  if (o_width == n_width && o_height == n_height)
+    return 1; /* nope */
+
+  DBG_INFO(80, L"expand image to next power of 2 dimensions. %d x %d -> %d x %d\n",
+           o_width, o_height, n_width, n_height);
+
+  if (o_width > n_width)
+    o_width = n_width;
+
+  if (o_height > n_height)
+    o_height = n_height;
+
+  /* allocate memory to read in image */
+  uint8 *pow2image = (uint8*)malloc(row_bytes * n_height);
+
+  /* read in image */
+  if (pow2image) {
+    int i, j;
+    uint8 *tmpimage = *image, *tmppow2image = pow2image;
+
+    for (i = 0; i < o_height; i++) {
+      /* copy row */
+      memcpy(tmppow2image, tmpimage, ((o_width * bpp) >> 3));
+
+      /* expand to pow2 size by replication */
+      for(j = ((o_width * bpp) >> 3); j < row_bytes; j++)
+        tmppow2image[j] = tmppow2image[j - (bpp >> 3)];
+
+      tmppow2image += row_bytes;
+      tmpimage += o_row_bytes;
+    }
+    /* expand to pow2 size by replication */
+    for (i = o_height; i < n_height; i++)
+      memcpy(&pow2image[row_bytes * i], &pow2image[row_bytes * (i - 1)], row_bytes);
+
+    free(*image);
+
+    *image = pow2image;
+    *height = n_height;
+    *width = n_width;
+
+    return 1;
+  }
+
+  return 0;
+}
+
+/* Ken Turkowski
+ * Filters for Common Resampling Tasks
+ * Apple Computer 1990
+ */
+double
+TxReSample::tent(double x)
+{
+  if (x < 0.0) x = -x;
+  if (x < 1.0) return (1.0 - x);
+  return 0.0;
+}
+
+double
+TxReSample::gaussian(double x)
+{
+  if (x < 0) x = -x;
+  if (x < 2.0) return pow(2.0, -2.0 * x * x);
+  return 0.0;
+}
+
+double 
+TxReSample::sinc(double x)
+{
+  if (x == 0) return 1.0;
+  x *= M_PI;
+  return (sin(x) / x);
+}
+
+double 
+TxReSample::lanczos3(double x)
+{
+  if (x < 0) x = -x;
+  if (x < 3.0) return (sinc(x) * sinc(x/3.0));
+  return 0.0;
+}
+
+/* Don P. Mitchell and Arun N. Netravali
+ * Reconstruction Filters in Computer Graphics
+ * SIGGRAPH '88
+ * Proceedings of the 15th annual conference on Computer 
+ * graphics and interactive techniques, pp221-228, 1988
+ */
+double
+TxReSample::mitchell(double x)
+{
+  if (x < 0) x = -x;
+  if (x < 2.0) {
+    const double B = 1.0 / 3.0;
+    const double C = 1.0 / 3.0;
+    if (x < 1.0) {
+      x = (((12.0 - 9.0 * B - 6.0 * C) * (x * x * x))
+           + ((-18.0 + 12.0 * B + 6.0 * C) * (x * x))
+           + (6.0 - 2.0 * B));
+    } else {
+      x = (((-1.0 * B - 6.0 * C) * (x * x * x))
+           + ((6.0 * B + 30.0 * C) * (x * x))
+           + ((-12.0 * B - 48.0 * C) * x)
+           + (8.0 * B + 24.0 * C));
+    }
+    return (x / 6.0);
+  }
+  return 0.0;
+}
+
+/* J. F. Kaiser and W. A. Reed
+ * Data smoothing using low-pass digital filters
+ * Rev. Sci. instrum. 48 (11), pp1447-1457, 1977
+ */
+double
+TxReSample::besselI0(double x)
+{
+  /* zero-order modified bessel function of the first kind */
+  const double eps_coeff = 1E-16; /* small enough */
+  double xh, sum, pow, ds;
+  xh = 0.5 * x;
+  sum = 1.0;
+  pow = 1.0;
+  ds = 1.0;
+  int k = 0;
+  while (ds > sum * eps_coeff) {
+    k++;
+    pow *= (xh / k);
+    ds = pow * pow;
+    sum = sum + ds;
+  }
+  return sum;
+}
+
+double
+TxReSample::kaiser(double x)
+{
+  const double alpha = 4.0;
+  const double half_window = 5.0;
+  const double ratio = x / half_window;
+  return sinc(x) * besselI0(alpha * sqrt(1 - ratio * ratio)) / besselI0(alpha);
+}
+
+boolean
+TxReSample::minify(uint8 **src, int *width, int *height, int ratio)
+{
+  /* NOTE: src must be ARGB8888, ratio is the inverse representation */
+
+#if 0
+  if (!*src || ratio < 2) return 0;
+
+  /* Box filtering.
+   * It would be nice to do Kaiser filtering.
+   * N64 uses narrow strip textures which makes it hard to filter effectively.
+   */
+
+  int x, y, x2, y2, offset, numtexel;
+  uint32 A, R, G, B, texel;
+
+  int tmpwidth = *width / ratio;
+  int tmpheight = *height / ratio;
+
+  uint8 *tmptex = (uint8*)malloc((tmpwidth * tmpheight) << 2);
+
+  if (tmptex) {
+    numtexel = ratio * ratio;
+    for (y = 0; y < tmpheight; y++) {
+      offset = ratio * y * *width;
+      for (x = 0; x < tmpwidth; x++) {
+        A = R = G = B = 0;
+        for (y2 = 0; y2 < ratio; y2++) {
+          for (x2 = 0; x2 < ratio; x2++) {
+            texel = ((uint32*)*src)[offset + *width * y2 + x2];
+            A += (texel >> 24);
+            R += ((texel >> 16) & 0x000000ff);
+            G += ((texel >> 8) & 0x000000ff);
+            B += (texel & 0x000000ff);
+          }
+        }
+        A = (A + ratio) / numtexel;
+        R = (R + ratio) / numtexel;
+        G = (G + ratio) / numtexel;
+        B = (B + ratio) / numtexel;
+        ((uint32*)tmptex)[y * tmpwidth + x] = ((A << 24) | (R << 16) | (G << 8) | B);
+        offset += ratio;
+      }
+    }
+    free(*src);
+    *src = tmptex;
+    *width = tmpwidth;
+    *height = tmpheight;
+
+    DBG_INFO(80, L"minification ratio:%d -> %d x %d\n", ratio, *width, *height);
+
+    return 1;
+  }
+
+  DBG_INFO(80, L"Error: failed minification!\n");
+
+  return 0;
+
+#else
+
+  if (!*src || ratio < 2) return 0;
+
+  /* Image Resampling */
+  
+  /* half width of filter window.
+   * NOTE: must be 1.0 or larger. 
+   *
+   * kaiser-bessel 5, lanczos3 3, mitchell 2, gaussian 1.5, tent 1
+   */
+  double half_window = 5.0;
+
+  int x, y, x2, y2, z;
+  double A, R, G, B;
+  uint32 texel;
+
+  int tmpwidth = *width / ratio;
+  int tmpheight = *height / ratio;
+
+  /* resampled destination */
+  uint8 *tmptex = (uint8*)malloc((tmpwidth * tmpheight) << 2);
+  if (!tmptex) return 0;
+
+  /* work buffer. single row */
+  uint8 *workbuf = (uint8*)malloc(*width << 2);
+  if (!workbuf) {
+    free(tmptex);
+    return 0;
+  }
+
+  /* prepare filter lookup table. only half width required for symetric filters. */
+  double *weight = (double*)malloc((int)((half_window * ratio) * sizeof(double)));
+  if (!weight) {
+    free(tmptex);
+    free(workbuf);
+    return 0;
+  }
+  for (x = 0; x < half_window * ratio; x++) {
+    //weight[x] = tent((double)x / ratio) / ratio;
+    //weight[x] = gaussian((double)x / ratio) / ratio;
+    //weight[x] = lanczos3((double)x / ratio) / ratio;
+    //weight[x] = mitchell((double)x / ratio) / ratio;
+    weight[x] = kaiser((double)x / ratio) / ratio;
+  }
+
+  /* linear convolution */
+  for (y = 0; y < tmpheight; y++) {
+    for (x = 0; x < *width; x++) {
+      texel = ((uint32*)*src)[y * ratio * *width + x];
+      A = (double)(texel >> 24) * weight[0];
+      R = (double)((texel >> 16) & 0xff) * weight[0];
+      G = (double)((texel >>  8) & 0xff) * weight[0];
+      B = (double)((texel      ) & 0xff) * weight[0];
+      for (y2 = 1; y2 < half_window * ratio; y2++) {
+        z = y * ratio + y2;
+        if (z >= *height) z = *height - 1;
+        texel = ((uint32*)*src)[z * *width + x];
+        A += (double)(texel >> 24) * weight[y2];
+        R += (double)((texel >> 16) & 0xff) * weight[y2];
+        G += (double)((texel >>  8) & 0xff) * weight[y2];
+        B += (double)((texel      ) & 0xff) * weight[y2];
+        z = y * ratio - y2;
+        if (z < 0) z = 0;
+        texel = ((uint32*)*src)[z * *width + x];
+        A += (double)(texel >> 24) * weight[y2];
+        R += (double)((texel >> 16) & 0xff) * weight[y2];
+        G += (double)((texel >>  8) & 0xff) * weight[y2];
+        B += (double)((texel      ) & 0xff) * weight[y2];
+      }
+      if (A < 0) A = 0; else if (A > 255) A = 255;
+      if (R < 0) R = 0; else if (R > 255) R = 255;
+      if (G < 0) G = 0; else if (G > 255) G = 255;
+      if (B < 0) B = 0; else if (B > 255) B = 255;
+      ((uint32*)workbuf)[x] = (((uint32)A << 24) | ((uint32)R << 16) | ((uint32)G << 8) | (uint32)B);
+    }
+    for (x = 0; x < tmpwidth; x++) {
+      texel = ((uint32*)workbuf)[x * ratio];
+      A = (double)(texel >> 24) * weight[0];
+      R = (double)((texel >> 16) & 0xff) * weight[0];
+      G = (double)((texel >>  8) & 0xff) * weight[0];
+      B = (double)((texel      ) & 0xff) * weight[0];
+      for (x2 = 1; x2 < half_window * ratio; x2++) {
+        z = x * ratio + x2;
+        if (z >= *width) z = *width - 1;
+        texel = ((uint32*)workbuf)[z];
+        A += (double)(texel >> 24) * weight[x2];
+        R += (double)((texel >> 16) & 0xff) * weight[x2];
+        G += (double)((texel >>  8) & 0xff) * weight[x2];
+        B += (double)((texel      ) & 0xff) * weight[x2];
+        z = x * ratio - x2;
+        if (z < 0) z = 0;
+        texel = ((uint32*)workbuf)[z];
+        A += (double)(texel >> 24) * weight[x2];
+        R += (double)((texel >> 16) & 0xff) * weight[x2];
+        G += (double)((texel >>  8) & 0xff) * weight[x2];
+        B += (double)((texel      ) & 0xff) * weight[x2];
+      }
+      if (A < 0) A = 0; else if (A > 255) A = 255;
+      if (R < 0) R = 0; else if (R > 255) R = 255;
+      if (G < 0) G = 0; else if (G > 255) G = 255;
+      if (B < 0) B = 0; else if (B > 255) B = 255;
+      ((uint32*)tmptex)[y * tmpwidth + x] = (((uint32)A << 24) | ((uint32)R << 16) | ((uint32)G << 8) | (uint32)B);
+    }
+  }
+
+  free(*src);
+  *src = tmptex;
+  free(weight);
+  free(workbuf);
+  *width = tmpwidth;
+  *height = tmpheight;
+
+  DBG_INFO(80, L"minification ratio:%d -> %d x %d\n", ratio, *width, *height);
+
+  return 1;
+#endif
+}
diff --git a/source/gles2glide64/src/GlideHQ/TxReSample.h b/source/gles2glide64/src/GlideHQ/TxReSample.h
new file mode 100644 (file)
index 0000000..805647d
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __TXRESAMPLE_H__
+#define __TXRESAMPLE_H__
+
+#include "TxInternal.h"
+
+class TxReSample
+{
+private:
+  double tent(double x);
+  double gaussian(double x);
+  double sinc(double x);
+  double lanczos3(double x);
+  double mitchell(double x);
+  double besselI0(double x);
+  double kaiser(double x);
+public:
+  boolean minify(uint8 **src, int *width, int *height, int ratio);
+  boolean nextPow2(uint8** image, int* width, int* height, int bpp, boolean use_3dfx);
+  int nextPow2(int num);
+};
+
+#endif /* __TXRESAMPLE_H__ */
diff --git a/source/gles2glide64/src/GlideHQ/TxTexCache.cpp b/source/gles2glide64/src/GlideHQ/TxTexCache.cpp
new file mode 100644 (file)
index 0000000..2297a0f
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef __MSC__
+#pragma warning(disable: 4786)
+#endif
+
+#include "TxTexCache.h"
+#include "TxDbg.h"
+#include <zlib.h>
+#include <string>
+#include <boost/filesystem.hpp>
+
+TxTexCache::~TxTexCache()
+{
+#ifdef DUMP_CACHE
+  if (_options & DUMP_TEXCACHE) {
+    /* dump cache to disk */
+    std::wstring filename = _ident + L"_MEMORYCACHE.dat";
+    boost::filesystem::wpath cachepath(_cachepath);
+    cachepath /= boost::filesystem::wpath(L"glidehq");
+    int config = _options & (FILTER_MASK|ENHANCEMENT_MASK|COMPRESS_TEX|COMPRESSION_MASK|FORCE16BPP_TEX|GZ_TEXCACHE);
+
+    TxCache::save(cachepath.wstring().c_str(), filename.c_str(), config);
+  }
+#endif
+}
+
+TxTexCache::TxTexCache(int options, int cachesize, const wchar_t *datapath, const wchar_t *cachepath,
+                       const wchar_t *ident, dispInfoFuncExt callback
+                       ) : TxCache((options & ~GZ_HIRESTEXCACHE), cachesize, datapath, cachepath, ident, callback)
+{
+  /* assert local options */
+  if (_cachepath.empty() || _ident.empty() || !_cacheSize)
+    _options &= ~DUMP_TEXCACHE;
+
+#ifdef DUMP_CACHE
+  if (_options & DUMP_TEXCACHE) {
+    /* find it on disk */
+    std::wstring filename = _ident + L"_MEMORYCACHE.dat";
+    boost::filesystem::wpath cachepath(_cachepath);
+    cachepath /= boost::filesystem::wpath(L"glidehq");
+    int config = _options & (FILTER_MASK|ENHANCEMENT_MASK|COMPRESS_TEX|COMPRESSION_MASK|FORCE16BPP_TEX|GZ_TEXCACHE);
+
+    TxCache::load(cachepath.wstring().c_str(), filename.c_str(), config);
+  }
+#endif
+}
+
+boolean
+TxTexCache::add(uint64 checksum, GHQTexInfo *info)
+{
+  if (_cacheSize <= 0) return 0;
+
+  return TxCache::add(checksum, info);
+}
diff --git a/source/gles2glide64/src/GlideHQ/TxTexCache.h b/source/gles2glide64/src/GlideHQ/TxTexCache.h
new file mode 100644 (file)
index 0000000..61b1214
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __TXTEXCACHE_H__
+#define __TXTEXCACHE_H__
+
+#include "TxCache.h"
+
+class TxTexCache : public TxCache
+{
+public:
+  ~TxTexCache();
+  TxTexCache(int options, int cachesize, const wchar_t *datapath,
+             const wchar_t *cachepath, const wchar_t *ident,
+             dispInfoFuncExt callback);
+  boolean add(uint64 checksum, /* checksum hi:palette low:texture */
+              GHQTexInfo *info);
+};
+
+#endif /* __TXTEXCACHE_H__ */
diff --git a/source/gles2glide64/src/GlideHQ/TxUtil.cpp b/source/gles2glide64/src/GlideHQ/TxUtil.cpp
new file mode 100644 (file)
index 0000000..9ad7e44
--- /dev/null
@@ -0,0 +1,587 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "TxUtil.h"
+#include "TxDbg.h"
+#include <zlib.h>
+#include <stdlib.h>
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+
+/*
+ * External libraries
+ ******************************************************************************/
+TxLoadLib::TxLoadLib()
+{
+#ifdef DXTN_DLL
+  if (!_dxtnlib)
+    _dxtnlib = LoadLibrary("dxtn");
+
+  if (_dxtnlib) {
+    if (!_tx_compress_dxtn)
+      _tx_compress_dxtn = (dxtCompressTexFuncExt)DLSYM(_dxtnlib, "tx_compress_dxtn");
+
+    if (!_tx_compress_fxt1)
+      _tx_compress_fxt1 = (fxtCompressTexFuncExt)DLSYM(_dxtnlib, "fxt1_encode");
+  }
+#else
+  _tx_compress_dxtn = tx_compress_dxtn;
+  _tx_compress_fxt1 = fxt1_encode;
+
+#endif
+}
+
+TxLoadLib::~TxLoadLib()
+{
+#ifdef DXTN_DLL
+  /* free dynamic library */
+  if (_dxtnlib)
+    FreeLibrary(_dxtnlib);
+#endif
+
+}
+
+fxtCompressTexFuncExt
+TxLoadLib::getfxtCompressTexFuncExt()
+{
+  return _tx_compress_fxt1;
+}
+
+dxtCompressTexFuncExt
+TxLoadLib::getdxtCompressTexFuncExt()
+{
+  return _tx_compress_dxtn;
+}
+
+
+/*
+ * Utilities
+ ******************************************************************************/
+uint32
+TxUtil::checksumTx(uint8 *src, int width, int height, uint16 format)
+{
+  int dataSize = sizeofTx(width, height, format);
+
+  /* for now we use adler32 if something else is better
+   * we can simply swtich later
+   */
+  /* return (dataSize ? Adler32(src, dataSize, 1) : 0); */
+
+  /* zlib crc32 */
+  return (dataSize ? crc32(crc32(0L, Z_NULL, 0), src, dataSize) : 0);
+}
+
+int
+TxUtil::sizeofTx(int width, int height, uint16 format)
+{
+  int dataSize = 0;
+
+  /* a lookup table for the shifts would be better */
+  switch (format) {
+  case GR_TEXFMT_ARGB_CMP_FXT1:
+    dataSize = (((width + 0x7) & ~0x7) * ((height + 0x3) & ~0x3)) >> 1;
+    break;
+  case GR_TEXFMT_ARGB_CMP_DXT1:
+    dataSize = (((width + 0x3) & ~0x3) * ((height + 0x3) & ~0x3)) >> 1;
+    break;
+  case GR_TEXFMT_ARGB_CMP_DXT3:
+  case GR_TEXFMT_ARGB_CMP_DXT5:
+    dataSize = ((width + 0x3) & ~0x3) * ((height + 0x3) & ~0x3);
+    break;
+  case GR_TEXFMT_ALPHA_INTENSITY_44:
+  case GR_TEXFMT_ALPHA_8:
+  case GR_TEXFMT_INTENSITY_8:
+  case GR_TEXFMT_P_8:
+    dataSize = width * height;
+    break;
+  case GR_TEXFMT_ARGB_4444:
+  case GR_TEXFMT_ARGB_1555:
+  case GR_TEXFMT_RGB_565:
+  case GR_TEXFMT_ALPHA_INTENSITY_88:
+    dataSize = (width * height) << 1;
+    break;
+  case GR_TEXFMT_ARGB_8888:
+    dataSize = (width * height) << 2;
+    break;
+  default:
+    /* unsupported format */
+    DBG_INFO(80, L"Error: cannot get size. unsupported gfmt:%x\n", format);
+    ;
+  }
+
+  return dataSize;
+}
+
+#if 0 /* unused */
+uint32
+TxUtil::chkAlpha(uint32* src, int width, int height)
+{
+  /* NOTE: _src must be ARGB8888
+   * return values
+   * 0x00000000: 8bit alpha
+   * 0x00000001: 1bit alpha
+   * 0xff000001: no alpha
+   */
+
+  int _size = width * height;
+  uint32 alpha = 0;
+
+  __asm {
+    mov esi, dword ptr [src];
+    mov ecx, dword ptr [_size];
+    mov ebx, 0xff000000;
+
+  tc1_loop:
+    mov eax, dword ptr [esi];
+    add esi, 4;
+
+    and eax, 0xff000000;
+    jz  alpha1bit;
+    cmp eax, 0xff000000;
+    je  alpha1bit;
+    jmp done;
+
+  alpha1bit:
+    and ebx, eax;
+    dec ecx;
+    jnz tc1_loop;
+
+    or  ebx, 0x00000001;
+    mov dword ptr [alpha], ebx;
+
+  done:
+  }
+
+  return alpha;
+}
+#endif
+
+uint32
+TxUtil::checksum(uint8 *src, int width, int height, int size, int rowStride)
+{
+  /* Rice CRC32 for now. We can switch this to Jabo MD5 or
+   * any other custom checksum.
+   * TODO: use *_HIRESTEXTURE option. */
+
+  if (!src) return 0;
+
+  return RiceCRC32(src, width, height, size, rowStride);
+}
+
+uint64
+TxUtil::checksum64(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette)
+{
+  /* Rice CRC32 for now. We can switch this to Jabo MD5 or
+   * any other custom checksum.
+   * TODO: use *_HIRESTEXTURE option. */
+  /* Returned value is 64bits: hi=palette crc32 low=texture crc32 */
+
+  if (!src) return 0;
+
+  uint64 crc64Ret = 0;
+
+  if (palette) {
+    uint32 crc32 = 0, cimax = 0;
+    switch (size & 0xff) {
+    case 1:
+      if (RiceCRC32_CI8(src, width, height, size, rowStride, &crc32, &cimax)) {
+        crc64Ret = (uint64)RiceCRC32(palette, cimax + 1, 1, 2, 512);
+        crc64Ret <<= 32;
+        crc64Ret |= (uint64)crc32;
+      }
+      break;
+    case 0:
+      if (RiceCRC32_CI4(src, width, height, size, rowStride, &crc32, &cimax)) {
+        crc64Ret = (uint64)RiceCRC32(palette, cimax + 1, 1, 2, 32);
+        crc64Ret <<= 32;
+        crc64Ret |= (uint64)crc32;
+      }
+    }
+  }
+  if (!crc64Ret) {
+    crc64Ret = (uint64)RiceCRC32(src, width, height, size, rowStride);
+  }
+
+  return crc64Ret;
+}
+
+/*
+** Computes Adler32 checksum for a stream of data.
+**
+** From the specification found in RFC 1950: (ZLIB Compressed Data Format
+** Specification version 3.3)
+**
+** ADLER32 (Adler-32 checksum) This contains a checksum value of the
+** uncompressed data (excluding any dictionary data) computed according to
+** Adler-32 algorithm. This algorithm is a 32-bit extension and improvement
+** of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073 standard.
+**
+** Adler-32 is composed of two sums accumulated per byte: s1 is the sum of
+** all bytes, s2 is the sum of all s1 values. Both sums are done modulo
+** 65521. s1 is initialized to 1, s2 to zero. The Adler-32 checksum is stored
+** as s2*65536 + s1 in most-significant-byte first (network) order.
+**
+** 8.2. The Adler-32 algorithm 
+**
+** The Adler-32 algorithm is much faster than the CRC32 algorithm yet still
+** provides an extremely low probability of undetected errors.
+**
+** The modulo on unsigned long accumulators can be delayed for 5552 bytes,
+** so the modulo operation time is negligible. If the bytes are a, b, c,
+** the second sum is 3a + 2b + c + 3, and so is position and order sensitive,
+** unlike the first sum, which is just a checksum. That 65521 is prime is
+** important to avoid a possible large class of two-byte errors that leave
+** the check unchanged. (The Fletcher checksum uses 255, which is not prime
+** and which also makes the Fletcher check insensitive to single byte
+** changes 0 <-> 255.)
+**
+** The sum s1 is initialized to 1 instead of zero to make the length of
+** the sequence part of s2, so that the length does not have to be checked
+** separately. (Any sequence of zeroes has a Fletcher checksum of zero.)
+*/
+
+uint32
+TxUtil::Adler32(const uint8* data, int Len, uint32 dwAdler32)
+{
+#if 1
+  /* zlib adler32 */
+  return adler32(dwAdler32, data, Len);
+#else
+  register uint32 s1 = dwAdler32 & 0xFFFF;
+  register uint32 s2 = (dwAdler32 >> 16) & 0xFFFF;
+  int k;
+
+  while (Len > 0) {
+    /* 5552 is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+    k = (Len < 5552 ? Len : 5552);
+    Len -= k;
+    while (k--) {
+      s1 += *data++;
+      s2 += s1;
+    }
+    /* 65521 is the largest prime smaller than 65536 */
+    s1 %= 65521;
+    s2 %= 65521;
+  }
+
+  return (s2 << 16) | s1;
+#endif
+}
+
+uint32
+TxUtil::Adler32(const uint8* src, int width, int height, int size, int rowStride)
+{
+  int i;
+  uint32 ret = 1;
+  uint32 width_in_bytes = width * size;
+
+  for (i = 0; i < height; i++) {
+    ret = Adler32(src, width_in_bytes, ret);
+    src += rowStride;
+  }
+
+  return ret;
+}
+
+// rotate left
+template<class T> static T __ROL__(T value, unsigned int count)
+{
+  const unsigned int nbits = sizeof(T) * 8;
+  count %= nbits;
+
+  T high = value >> (nbits - count);
+  value <<= count;
+  value |= high;
+  return value;
+}
+
+/* Rice CRC32 for hires texture packs */
+/* NOTE: The following is used in Glide64 to calculate the CRC32
+ * for Rice hires texture packs.
+ *
+ * BYTE* addr = (BYTE*)(gfx.RDRAM +
+ *                     rdp.addr[rdp.tiles[tile].t_mem] +
+ *                     (rdp.tiles[tile].ul_t * bpl) +
+ *                     (((rdp.tiles[tile].ul_s<<rdp.tiles[tile].size)+1)>>1));
+ * RiceCRC32(addr,
+ *          rdp.tiles[tile].width,
+ *          rdp.tiles[tile].height,
+ *          (unsigned short)(rdp.tiles[tile].format << 8 | rdp.tiles[tile].size),
+ *          bpl);
+ */
+uint32
+TxUtil::RiceCRC32(const uint8* src, int width, int height, int size, int rowStride)
+{
+  const uint8_t *row;
+  uint32_t crc32Ret;
+  int cur_height;
+  uint32_t pos;
+  uint32_t word;
+  uint32_t word_hash = 0;
+  uint32_t tmp;
+  const uint32_t bytes_per_width = ((width << size) + 1) >> 1;
+
+  row = src;
+  crc32Ret = 0;
+
+  for (cur_height = height - 1; cur_height >= 0; cur_height--) {
+    for (pos = bytes_per_width - 4; pos < 0x80000000u; pos -= 4) {
+      word = *(uint32_t *)&row[pos];
+      word_hash = pos ^ word;
+      tmp = __ROL__(crc32Ret, 4);
+      crc32Ret = word_hash + tmp;
+    }
+    crc32Ret += cur_height ^ word_hash;
+    row += rowStride;
+  }
+  return crc32Ret;
+}
+
+boolean
+TxUtil::RiceCRC32_CI4(const uint8* src, int width, int height, int size, int rowStride,
+                        uint32* crc32, uint32* cimax)
+{
+  const uint8_t *row;
+  uint32_t crc32Ret;
+  uint32_t cimaxRet;
+  int cur_height;
+  uint32_t pos;
+  uint32_t word;
+  uint32_t word_hash = 0;
+  uint32_t tmp;
+  const uint32_t bytes_per_width = ((width << size) + 1) >> 1;
+
+  row = src;
+  crc32Ret = 0;
+  cimaxRet = 0;
+
+  for (cur_height = height - 1; cur_height >= 0; cur_height--) {
+    for (pos = bytes_per_width - 4; pos < 0x80000000u; pos -= 4) {
+      word = *(uint32_t *)&row[pos];
+      if (cimaxRet != 15) {
+        if ((word & 0xF) >= cimaxRet)
+          cimaxRet = word & 0xF;
+        if ((uint32_t)((uint8_t)word >> 4) >= cimaxRet)
+          cimaxRet = (uint8_t)word >> 4;
+        if (((word >> 8) & 0xF) >= cimaxRet)
+          cimaxRet = (word >> 8) & 0xF;
+        if ((uint32_t)((uint16_t)word >> 12) >= cimaxRet)
+          cimaxRet = (uint16_t)word >> 12;
+        if (((word >> 16) & 0xF) >= cimaxRet)
+          cimaxRet = (word >> 16) & 0xF;
+        if (((word >> 20) & 0xF) >= cimaxRet)
+          cimaxRet = (word >> 20) & 0xF;
+        if (((word >> 24) & 0xF) >= cimaxRet)
+          cimaxRet = (word >> 24) & 0xF;
+        if (word >> 28 >= cimaxRet )
+          cimaxRet = word >> 28;
+      }
+      word_hash = pos ^ word;
+      tmp = __ROL__(crc32Ret, 4);
+      crc32Ret = word_hash + tmp;
+    }
+    crc32Ret += cur_height ^ word_hash;
+    row += rowStride;
+  }
+  *crc32 = crc32Ret;
+  *cimax = cimaxRet;
+  return 1;
+}
+
+boolean
+TxUtil::RiceCRC32_CI8(const uint8* src, int width, int height, int size, int rowStride,
+                      uint32* crc32, uint32* cimax)
+{
+  const uint8_t *row;
+  uint32_t crc32Ret;
+  uint32_t cimaxRet;
+  int cur_height;
+  uint32_t pos;
+  uint32_t word;
+  uint32_t word_hash = 0;
+  uint32_t tmp;
+  const uint32_t bytes_per_width = ((width << size) + 1) >> 1;
+
+  row = src;
+  crc32Ret = 0;
+  cimaxRet = 0;
+
+  for (cur_height = height - 1; cur_height >= 0; cur_height--) {
+    for (pos = bytes_per_width - 4; pos < 0x80000000u; pos -= 4) {
+      word = *(uint32_t *)&row[pos];
+      if (cimaxRet != 255) {
+        if ((uint8_t)word >= cimaxRet)
+          cimaxRet = (uint8_t)word;
+        if ((uint32_t)((uint16_t)word >> 8) >= cimaxRet)
+          cimaxRet = (uint16_t)word >> 8;
+        if (((word >> 16) & 0xFF) >= cimaxRet)
+          cimaxRet = (word >> 16) & 0xFF;
+        if (word >> 24 >= cimaxRet)
+          cimaxRet = word >> 24;
+      }
+      word_hash = pos ^ word;
+      tmp = __ROL__(crc32Ret, 4);
+      crc32Ret = word_hash + tmp;
+    }
+    crc32Ret += cur_height ^ word_hash;
+    row += rowStride;
+  }
+  *crc32 = crc32Ret;
+  *cimax = cimaxRet;
+  return 1;
+}
+
+int
+TxUtil::log2(int num)
+{
+#if defined(__GNUC__)
+  return __builtin_ctz(num);
+#elif defined(_MSC_VER) && _MSC_VER >= 1400
+  uint32_t i;
+  _BitScanForward((DWORD *)&i, num);
+  return i;
+#elif defined(__MSC__)
+  __asm {
+    mov eax, dword ptr [num];
+    bsr eax, eax;
+    mov dword ptr [i], eax;
+  }
+#else
+  switch (num) {
+    case 1:    return 0;
+    case 2:    return 1;
+    case 4:    return 2;
+    case 8:    return 3;
+    case 16:   return 4;
+    case 32:   return 5;
+    case 64:   return 6;
+    case 128:  return 7;
+    case 256:  return 8;
+    case 512:  return 9;
+    case 1024:  return 10;
+    case 2048:  return 11;
+  }
+#endif
+}
+
+int
+TxUtil::grLodLog2(int w, int h)
+{
+  return (w >= h ? log2(w) : log2(h));
+}
+
+int
+TxUtil::grAspectRatioLog2(int w, int h)
+{
+  return (w >= h ? log2(w/h) : -log2(h/w));
+}
+
+int
+TxUtil::getNumberofProcessors()
+{
+  int numcore = 1, ret;
+
+#ifdef _WIN32
+#ifndef _SC_NPROCESSORS_ONLN
+  SYSTEM_INFO info;
+  GetSystemInfo(&info);
+#define sysconf(a) info.dwNumberOfProcessors
+#define _SC_NPROCESSORS_ONLN
+#endif
+#endif
+#ifdef _SC_NPROCESSORS_ONLN
+  ret = sysconf(_SC_NPROCESSORS_CONF);
+  if (ret >= 1) {
+    numcore = ret;
+  }
+  ret = sysconf(_SC_NPROCESSORS_ONLN);
+  if (ret < 1) {
+    numcore = ret;
+  }
+#endif
+
+  return numcore;
+}
+
+
+/*
+ * Memory buffers for texture manipulations
+ ******************************************************************************/
+TxMemBuf::TxMemBuf()
+{
+  int i;
+  for (i = 0; i < 2; i++) {
+    _tex[i] = NULL;
+    _size[i] = 0;
+  }
+}
+
+TxMemBuf::~TxMemBuf()
+{
+  shutdown();
+}
+
+boolean
+TxMemBuf::init(int maxwidth, int maxheight)
+{
+  int i;
+  for (i = 0; i < 2; i++) {
+    if (!_tex[i]) {
+      _tex[i] = (uint8 *)malloc(maxwidth * maxheight * 4);
+      _size[i] = maxwidth * maxheight * 4;
+    }
+
+    if (!_tex[i]) {
+      shutdown();
+      return 0;
+    }
+  }
+  return 1;
+}
+
+void
+TxMemBuf::shutdown()
+{
+  int i;
+  for (i = 0; i < 2; i++) {
+    if (_tex[i]) free(_tex[i]);
+    _tex[i] = NULL;
+    _size[i] = 0;
+  }
+}
+
+uint8*
+TxMemBuf::get(unsigned int num)
+{
+  return ((num < 2) ? _tex[num] : NULL);
+}
+
+uint32
+TxMemBuf::size_of(unsigned int num)
+{
+  return ((num < 2) ? _size[num] : 0);
+}
diff --git a/source/gles2glide64/src/GlideHQ/TxUtil.h b/source/gles2glide64/src/GlideHQ/TxUtil.h
new file mode 100644 (file)
index 0000000..b89f660
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Texture Filtering
+ * Version:  1.0
+ *
+ * Copyright (C) 2007  Hiroshi Morii   All Rights Reserved.
+ * Email koolsmoky(at)users.sourceforge.net
+ * Web   http://www.3dfxzone.it/koolsmoky
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __TXUTIL_H__
+#define __TXUTIL_H__
+
+/* maximum number of CPU cores allowed */
+#define MAX_NUMCORE 8
+
+#include "TxInternal.h"
+#include <string>
+
+#ifndef DXTN_DLL
+#ifdef __cplusplus
+extern "C"{
+#endif
+void tx_compress_dxtn(int srccomps, int width, int height,
+                      const void *source, int destformat, void *dest,
+                      int destRowStride);
+
+int fxt1_encode(int width, int height, int comps,
+                const void *source, int srcRowStride,
+                void *dest, int destRowStride);
+#ifdef __cplusplus
+}
+#endif
+#endif /* DXTN_DLL */
+
+typedef void (*dxtCompressTexFuncExt)(int srccomps, int width,
+                                      int height, const void *srcPixData,
+                                      int destformat, void *dest,
+                                      int dstRowStride);
+
+typedef int (*fxtCompressTexFuncExt)(int width, int height, int comps,
+                                     const void *source, int srcRowStride,
+                                     void *dest, int destRowStride);
+
+class TxLoadLib
+{
+private:
+#ifdef DXTN_DLL
+  HMODULE _dxtnlib;
+#endif
+  fxtCompressTexFuncExt _tx_compress_fxt1;
+  dxtCompressTexFuncExt _tx_compress_dxtn;
+  TxLoadLib();
+public:
+  static TxLoadLib* getInstance() {
+    static TxLoadLib txLoadLib;
+    return &txLoadLib;
+  }
+  ~TxLoadLib();
+  fxtCompressTexFuncExt getfxtCompressTexFuncExt();
+  dxtCompressTexFuncExt getdxtCompressTexFuncExt();
+};
+
+class TxUtil
+{
+private:
+  uint32 Adler32(const uint8* data, int Len, uint32 Adler);
+  uint32 Adler32(const uint8* src, int width, int height, int size, int rowStride);
+  uint32 RiceCRC32(const uint8* src, int width, int height, int size, int rowStride);
+  boolean RiceCRC32_CI4(const uint8* src, int width, int height, int size, int rowStride,
+                        uint32* crc32, uint32* cimax);
+  boolean RiceCRC32_CI8(const uint8* src, int width, int height, int size, int rowStride,
+                        uint32* crc32, uint32* cimax);
+  int log2(int num);
+public:
+  TxUtil() { }
+  ~TxUtil() { }
+  int sizeofTx(int width, int height, uint16 format);
+  uint32 checksumTx(uint8 *data, int width, int height, uint16 format);
+#if 0 /* unused */
+  uint32 chkAlpha(uint32* src, int width, int height);
+#endif
+  uint32 checksum(uint8 *src, int width, int height, int size, int rowStride);
+  uint64 checksum64(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette);
+  int grLodLog2(int w, int h);
+  int grAspectRatioLog2(int w, int h);
+  int getNumberofProcessors();
+};
+
+class TxMemBuf
+{
+private:
+  uint8 *_tex[2];
+  uint32 _size[2];
+  TxMemBuf();
+public:
+  static TxMemBuf* getInstance() {
+    static TxMemBuf txMemBuf;
+    return &txMemBuf;
+  }
+  ~TxMemBuf();
+  boolean init(int maxwidth, int maxheight);
+  void shutdown(void);
+  uint8 *get(unsigned int num);
+  uint32 size_of(unsigned int num);
+};
+
+#endif /* __TXUTIL_H__ */
diff --git a/source/gles2glide64/src/GlideHQ/tc-1.1+/dxtn.c b/source/gles2glide64/src/GlideHQ/tc-1.1+/dxtn.c
new file mode 100644 (file)
index 0000000..e2d335a
--- /dev/null
@@ -0,0 +1,884 @@
+/*
+ * DXTn codec
+ * Version:  1.1
+ *
+ * Copyright (C) 2004  Daniel Borca   All Rights Reserved.
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.       
+ */
+
+/* Copyright (C) 2007  Hiroshi Morii <koolsmoky(at)users.sourceforge.net>
+ * Added support for ARGB inputs, DXT3,5 workaround for ATI Radeons, and
+ * YUV conversions to determine representative colors.
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <stdio.h>
+
+#include "types.h"
+#include "internal.h"
+#include "dxtn.h"
+
+
+/***************************************************************************\
+ * DXTn encoder
+ *
+ * The encoder was built by reversing the decoder,
+ * and is vaguely based on FXT1 codec. Note that this code
+ * is merely a proof of concept, since it is highly UNoptimized!
+\***************************************************************************/
+
+
+#define MAX_COMP 4 /* ever needed maximum number of components in texel */
+#define MAX_VECT 4 /* ever needed maximum number of base vectors to find */
+#define N_TEXELS 16 /* number of texels in a block (always 16) */
+#define COLOR565(v) (word)((((v)[RCOMP] & 0xf8) << 8) | (((v)[GCOMP] & 0xfc) << 3) | ((v)[BCOMP] >> 3))
+
+
+static const int dxtn_color_tlat[2][4] = {
+    { 0, 2, 3, 1 },
+    { 0, 2, 1, 3 }
+};
+
+static const int dxtn_alpha_tlat[2][8] = {
+    { 0, 2, 3, 4, 5, 6, 7, 1 },
+    { 0, 2, 3, 4, 5, 1, 6, 7 }
+};
+
+
+static void
+dxt1_rgb_quantize (dword *cc, const byte *lines[], int comps)
+{
+    float b, iv[MAX_COMP];   /* interpolation vector */
+
+    dword hi; /* high doubleword */
+    int color0, color1;
+    int n_vect;
+    const int n_comp = 3;
+    int black = 0;
+
+#ifndef YUV
+    int minSum = 2000; /* big enough */
+#else
+    int minSum = 2000000;
+#endif
+    int maxSum = -1; /* small enough */
+    int minCol = 0; /* phoudoin: silent compiler! */
+    int maxCol = 0; /* phoudoin: silent compiler! */
+
+    byte input[N_TEXELS][MAX_COMP];
+    int i, k, l;
+
+    /* make the whole block opaque */
+    /* we will NEVER reference ACOMP of any pixel */
+
+    /* 4 texels each line */
+#ifndef ARGB
+    for (l = 0; l < 4; l++) {
+       for (k = 0; k < 4; k++) {
+           for (i = 0; i < comps; i++) {
+               input[k + l * 4][i] = *lines[l]++;
+           }
+       }
+    }
+#else
+    /* H.Morii - support for ARGB inputs */
+    for (l = 0; l < 4; l++) {
+       for (k = 0; k < 4; k++) {
+          input[k + l * 4][2] = *lines[l]++;
+          input[k + l * 4][1] = *lines[l]++;
+          input[k + l * 4][0] = *lines[l]++;
+          if (comps == 4) input[k + l * 4][3] = *lines[l]++;
+       }
+    }
+#endif
+
+    /* Our solution here is to find the darkest and brightest colors in
+     * the 4x4 tile and use those as the two representative colors.
+     * There are probably better algorithms to use (histogram-based).
+     */
+    for (k = 0; k < N_TEXELS; k++) {
+       int sum = 0;
+#ifndef YUV
+       for (i = 0; i < n_comp; i++) {
+           sum += input[k][i];
+       }
+#else
+        /* RGB to YUV conversion according to CCIR 601 specs
+         * Y = 0.299R+0.587G+0.114B
+         * U = 0.713(R - Y) = 0.500R-0.419G-0.081B
+         * V = 0.564(B - Y) = -0.169R-0.331G+0.500B
+         */
+        sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] +  114 * input[k][BCOMP];
+#endif
+       if (minSum > sum) {
+           minSum = sum;
+           minCol = k;
+       }
+       if (maxSum < sum) {
+           maxSum = sum;
+           maxCol = k;
+       }
+       if (sum == 0) {
+           black = 1;
+       }
+    }
+
+    color0 = COLOR565(input[minCol]);
+    color1 = COLOR565(input[maxCol]);
+
+    if (color0 == color1) {
+       /* we'll use 3-vector */
+       cc[0] = color0 | (color1 << 16);
+       hi = black ? -1 : 0;
+    } else {
+       if (black && ((color0 == 0) || (color1 == 0))) {
+           /* we still can use 4-vector */
+           black = 0;
+       }
+
+       if (black ^ (color0 <= color1)) {
+           int aux;
+           aux = color0;
+           color0 = color1;
+           color1 = aux;
+           aux = minCol;
+           minCol = maxCol;
+           maxCol = aux;
+       }
+       n_vect = (color0 <= color1) ? 2 : 3;
+
+       MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]);
+
+       /* add in texels */
+       cc[0] = color0 | (color1 << 16);
+       hi = 0;
+       for (k = N_TEXELS - 1; k >= 0; k--) {
+           int texel = 3;
+           int sum = 0;
+           if (black) {
+               for (i = 0; i < n_comp; i++) {
+                   sum += input[k][i];
+               }
+           }
+           if (!black || sum) {
+               /* interpolate color */
+               CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+               texel = dxtn_color_tlat[black][texel];
+           }
+           /* add in texel */
+           hi <<= 2;
+           hi |= texel;
+       }
+    }
+    cc[1] = hi;
+}
+
+
+static void
+dxt1_rgba_quantize (dword *cc, const byte *lines[], int comps)
+{
+    float b, iv[MAX_COMP];     /* interpolation vector */
+
+    dword hi;          /* high doubleword */
+    int color0, color1;
+    int n_vect;
+    const int n_comp = 3;
+    int transparent = 0;
+
+#ifndef YUV
+    int minSum = 2000;          /* big enough */
+#else
+    int minSum = 2000000;
+#endif
+    int maxSum = -1;           /* small enough */
+    int minCol = 0;            /* phoudoin: silent compiler! */
+    int maxCol = 0;            /* phoudoin: silent compiler! */
+
+    byte input[N_TEXELS][MAX_COMP];
+    int i, k, l;
+
+    if (comps == 3) {
+       /* make the whole block opaque */
+       memset(input, -1, sizeof(input));
+    }
+
+    /* 4 texels each line */
+#ifndef ARGB
+    for (l = 0; l < 4; l++) {
+       for (k = 0; k < 4; k++) {
+           for (i = 0; i < comps; i++) {
+               input[k + l * 4][i] = *lines[l]++;
+           }
+       }
+    }
+#else
+    /* H.Morii - support for ARGB inputs */
+    for (l = 0; l < 4; l++) {
+       for (k = 0; k < 4; k++) {
+          input[k + l * 4][2] = *lines[l]++;
+          input[k + l * 4][1] = *lines[l]++;
+          input[k + l * 4][0] = *lines[l]++;
+          if (comps == 4) input[k + l * 4][3] = *lines[l]++;
+       }
+    }
+#endif
+
+    /* Our solution here is to find the darkest and brightest colors in
+     * the 4x4 tile and use those as the two representative colors.
+     * There are probably better algorithms to use (histogram-based).
+     */
+    for (k = 0; k < N_TEXELS; k++) {
+       int sum = 0;
+#ifndef YUV
+       for (i = 0; i < n_comp; i++) {
+           sum += input[k][i];
+       }
+#else
+        sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] +  114 * input[k][BCOMP];
+#endif
+       if (minSum > sum) {
+           minSum = sum;
+           minCol = k;
+       }
+       if (maxSum < sum) {
+           maxSum = sum;
+           maxCol = k;
+       }
+       if (input[k][ACOMP] < 128) {
+           transparent = 1;
+       }
+    }
+
+    color0 = COLOR565(input[minCol]);
+    color1 = COLOR565(input[maxCol]);
+
+    if (color0 == color1) {
+       /* we'll use 3-vector */
+       cc[0] = color0 | (color1 << 16);
+       hi = transparent ? -1 : 0;
+    } else {
+       if (transparent ^ (color0 <= color1)) {
+           int aux;
+           aux = color0;
+           color0 = color1;
+           color1 = aux;
+           aux = minCol;
+           minCol = maxCol;
+           maxCol = aux;
+       }
+       n_vect = (color0 <= color1) ? 2 : 3;
+
+       MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]);
+
+       /* add in texels */
+       cc[0] = color0 | (color1 << 16);
+       hi = 0;
+       for (k = N_TEXELS - 1; k >= 0; k--) {
+           int texel = 3;
+           if (input[k][ACOMP] >= 128) {
+               /* interpolate color */
+               CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+               texel = dxtn_color_tlat[transparent][texel];
+           }
+           /* add in texel */
+           hi <<= 2;
+           hi |= texel;
+       }
+    }
+    cc[1] = hi;
+}
+
+
+static void
+dxt3_rgba_quantize (dword *cc, const byte *lines[], int comps)
+{
+    float b, iv[MAX_COMP];     /* interpolation vector */
+
+    dword lolo, lohi;  /* low quadword: lo dword, hi dword */
+    dword hihi;                /* high quadword: high dword */
+    int color0, color1;
+    const int n_vect = 3;
+    const int n_comp = 3;
+
+#ifndef YUV
+    int minSum = 2000;          /* big enough */
+#else
+    int minSum = 2000000;
+#endif
+    int maxSum = -1;           /* small enough */
+    int minCol = 0;            /* phoudoin: silent compiler! */
+    int maxCol = 0;            /* phoudoin: silent compiler! */
+
+    byte input[N_TEXELS][MAX_COMP];
+    int i, k, l;
+
+    if (comps == 3) {
+       /* make the whole block opaque */
+       memset(input, -1, sizeof(input));
+    }
+
+    /* 4 texels each line */
+#ifndef ARGB
+    for (l = 0; l < 4; l++) {
+       for (k = 0; k < 4; k++) {
+           for (i = 0; i < comps; i++) {
+               input[k + l * 4][i] = *lines[l]++;
+           }
+       }
+    }
+#else
+    /* H.Morii - support for ARGB inputs */
+    for (l = 0; l < 4; l++) {
+       for (k = 0; k < 4; k++) {
+          input[k + l * 4][2] = *lines[l]++;
+          input[k + l * 4][1] = *lines[l]++;
+          input[k + l * 4][0] = *lines[l]++;
+          if (comps == 4) input[k + l * 4][3] = *lines[l]++;
+       }
+    }
+#endif
+
+    /* Our solution here is to find the darkest and brightest colors in
+     * the 4x4 tile and use those as the two representative colors.
+     * There are probably better algorithms to use (histogram-based).
+     */
+    for (k = 0; k < N_TEXELS; k++) {
+       int sum = 0;
+#ifndef YUV
+       for (i = 0; i < n_comp; i++) {
+           sum += input[k][i];
+       }
+#else
+        sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] +  114 * input[k][BCOMP];
+#endif
+       if (minSum > sum) {
+           minSum = sum;
+           minCol = k;
+       }
+       if (maxSum < sum) {
+           maxSum = sum;
+           maxCol = k;
+       }
+    }
+
+    /* add in alphas */
+    lolo = lohi = 0;
+    for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
+       /* add in alpha */
+       lohi <<= 4;
+       lohi |= input[k][ACOMP] >> 4;
+    }
+    cc[1] = lohi;
+    for (; k >= 0; k--) {
+       /* add in alpha */
+       lolo <<= 4;
+       lolo |= input[k][ACOMP] >> 4;
+    }
+    cc[0] = lolo;
+
+    color0 = COLOR565(input[minCol]);
+    color1 = COLOR565(input[maxCol]);
+
+#ifdef RADEON
+    /* H.Morii - Workaround for ATI Radeon
+     * According to the OpenGL EXT_texture_compression_s3tc specs,
+     * the encoding of the RGB components for DXT3 and DXT5 formats
+     * use the non-transparent encodings of DXT1 but treated as
+     * though color0 > color1, regardless of the actual values of
+     * color0 and color1. ATI Radeons however require the values to
+     * be color0 > color1.
+     */
+    if (color0 < color1) {
+       int aux;
+       aux = color0;
+       color0 = color1;
+       color1 = aux;
+       aux = minCol;
+       minCol = maxCol;
+       maxCol = aux;
+    }
+#endif
+
+    cc[2] = color0 | (color1 << 16);
+
+    hihi = 0;
+    if (color0 != color1) {
+       MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]);
+
+       /* add in texels */
+       for (k = N_TEXELS - 1; k >= 0; k--) {
+           int texel;
+           /* interpolate color */
+           CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+           texel = dxtn_color_tlat[0][texel];
+           /* add in texel */
+           hihi <<= 2;
+           hihi |= texel;
+       }
+    }
+    cc[3] = hihi;
+}
+
+
+static void
+dxt5_rgba_quantize (dword *cc, const byte *lines[], int comps)
+{
+    float b, iv[MAX_COMP];     /* interpolation vector */
+
+    qword lo;                  /* low quadword */
+    dword hihi;                /* high quadword: high dword */
+    int color0, color1;
+    const int n_vect = 3;
+    const int n_comp = 3;
+
+#ifndef YUV
+    int minSum = 2000;          /* big enough */
+#else
+    int minSum = 2000000;
+#endif
+    int maxSum = -1;           /* small enough */
+    int minCol = 0;            /* phoudoin: silent compiler! */
+    int maxCol = 0;            /* phoudoin: silent compiler! */
+    int alpha0 = 2000;         /* big enough */
+    int alpha1 = -1;           /* small enough */
+    int anyZero = 0, anyOne = 0;
+    int a_vect;
+
+    byte input[N_TEXELS][MAX_COMP];
+    int i, k, l;
+
+    if (comps == 3) {
+       /* make the whole block opaque */
+       memset(input, -1, sizeof(input));
+    }
+
+    /* 4 texels each line */
+#ifndef ARGB
+    for (l = 0; l < 4; l++) {
+       for (k = 0; k < 4; k++) {
+           for (i = 0; i < comps; i++) {
+               input[k + l * 4][i] = *lines[l]++;
+           }
+       }
+    }
+#else
+    /* H.Morii - support for ARGB inputs */
+    for (l = 0; l < 4; l++) {
+       for (k = 0; k < 4; k++) {
+          input[k + l * 4][2] = *lines[l]++;
+          input[k + l * 4][1] = *lines[l]++;
+          input[k + l * 4][0] = *lines[l]++;
+          if (comps == 4) input[k + l * 4][3] = *lines[l]++;
+       }
+    }
+#endif
+
+    /* Our solution here is to find the darkest and brightest colors in
+     * the 4x4 tile and use those as the two representative colors.
+     * There are probably better algorithms to use (histogram-based).
+     */
+    for (k = 0; k < N_TEXELS; k++) {
+       int sum = 0;
+#ifndef YUV
+       for (i = 0; i < n_comp; i++) {
+           sum += input[k][i];
+       }
+#else
+        sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] +  114 * input[k][BCOMP];
+#endif
+       if (minSum > sum) {
+           minSum = sum;
+           minCol = k;
+       }
+       if (maxSum < sum) {
+           maxSum = sum;
+           maxCol = k;
+       }
+       if (alpha0 > input[k][ACOMP]) {
+           alpha0 = input[k][ACOMP];
+       }
+       if (alpha1 < input[k][ACOMP]) {
+           alpha1 = input[k][ACOMP];
+       }
+       if (input[k][ACOMP] == 0) {
+           anyZero = 1;
+       }
+       if (input[k][ACOMP] == 255) {
+           anyOne = 1;
+       }
+    }
+
+    /* add in alphas */
+    if (alpha0 == alpha1) {
+       /* we'll use 6-vector */
+       cc[0] = alpha0 | (alpha1 << 8);
+       cc[1] = 0;
+    } else {
+       if (anyZero && ((alpha0 == 0) || (alpha1 == 0))) {
+           /* we still might use 8-vector */
+           anyZero = 0;
+       }
+       if (anyOne && ((alpha0 == 255) || (alpha1 == 255))) {
+           /* we still might use 8-vector */
+           anyOne = 0;
+       }
+       if ((anyZero | anyOne) ^ (alpha0 <= alpha1)) {
+           int aux;
+           aux = alpha0;
+           alpha0 = alpha1;
+           alpha1 = aux;
+       }
+       a_vect = (alpha0 <= alpha1) ? 5 : 7;
+
+       /* compute interpolation vector */
+       iv[ACOMP] = (float)a_vect / (alpha1 - alpha0);
+       b = -iv[ACOMP] * alpha0 + 0.5F;
+
+       /* add in alphas */
+       Q_MOV32(lo, 0);
+       for (k = N_TEXELS - 1; k >= 0; k--) {
+           int texel = -1;
+           if (anyZero | anyOne) {
+               if (input[k][ACOMP] == 0) {
+                   texel = 6;
+               } else if (input[k][ACOMP] == 255) {
+                   texel = 7;
+               }
+           }
+           /* interpolate alpha */
+           if (texel == -1) {
+               float dot = input[k][ACOMP] * iv[ACOMP];
+               texel = (int)(dot + b);
+#if SAFECDOT
+               if (texel < 0) {
+                   texel = 0;
+               } else if (texel > a_vect) {
+                   texel = a_vect;
+               }
+#endif
+               texel = dxtn_alpha_tlat[anyZero | anyOne][texel];
+           }
+           /* add in texel */
+           Q_SHL(lo, 3);
+           Q_OR32(lo, texel);
+       }
+       Q_SHL(lo, 16);
+       Q_OR32(lo, alpha0 | (alpha1 << 8));
+       ((qword *)cc)[0] = lo;
+    }
+
+    color0 = COLOR565(input[minCol]);
+    color1 = COLOR565(input[maxCol]);
+
+#ifdef RADEON /* H.Morii - Workaround for ATI Radeon */
+    if (color0 < color1) {
+       int aux;
+       aux = color0;
+       color0 = color1;
+       color1 = aux;
+       aux = minCol;
+       minCol = maxCol;
+       maxCol = aux;
+    }
+#endif
+
+    cc[2] = color0 | (color1 << 16);
+
+    hihi = 0;
+    if (color0 != color1) {
+       MAKEIVEC(n_vect, n_comp, iv, b, input[minCol], input[maxCol]);
+
+       /* add in texels */
+       for (k = N_TEXELS - 1; k >= 0; k--) {
+           int texel;
+           /* interpolate color */
+           CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+           texel = dxtn_color_tlat[0][texel];
+           /* add in texel */
+           hihi <<= 2;
+           hihi |= texel;
+       }
+    }
+    cc[3] = hihi;
+}
+
+
+#define ENCODER(dxtn, n)                                               \
+int TAPIENTRY                                                          \
+dxtn##_encode (int width, int height, int comps,                       \
+              const void *source, int srcRowStride,                    \
+              void *dest, int destRowStride)                           \
+{                                                                      \
+    int x, y;                                                          \
+    const byte *data;                                                  \
+    dword *encoded = (dword *)dest;                                    \
+    void *newSource = NULL;                                            \
+                                                                       \
+    /* Replicate image if width is not M4 or height is not M4 */       \
+    if ((width & 3) | (height & 3)) {                                  \
+       int newWidth = (width + 3) & ~3;                                \
+       int newHeight = (height + 3) & ~3;                              \
+       newSource = malloc(comps * newWidth * newHeight * sizeof(byte *));\
+       _mesa_upscale_teximage2d(width, height, newWidth, newHeight,    \
+                               comps, (const byte *)source,            \
+                              srcRowStride, (byte *)newSource);        \
+       source = newSource;                                             \
+       width = newWidth;                                               \
+       height = newHeight;                                             \
+       srcRowStride = comps * newWidth;                                \
+    }                                                                  \
+                                                                       \
+    data = (const byte *)source;                                       \
+    destRowStride = (destRowStride - width * n) / 4;                   \
+    for (y = 0; y < height; y += 4) {                                  \
+       unsigned int offs = 0 + (y + 0) * srcRowStride;                 \
+       for (x = 0; x < width; x += 4) {                                \
+           const byte *lines[4];                                       \
+           lines[0] = &data[offs];                                     \
+           lines[1] = lines[0] + srcRowStride;                         \
+           lines[2] = lines[1] + srcRowStride;                         \
+           lines[3] = lines[2] + srcRowStride;                         \
+           offs += 4 * comps;                                          \
+           dxtn##_quantize(encoded, lines, comps);                     \
+           /* 4x4 block */                                             \
+           encoded += n;                                               \
+       }                                                               \
+       encoded += destRowStride;                                       \
+    }                                                                  \
+                                                                       \
+    if (newSource != NULL) {                                           \
+       free(newSource);                                                \
+    }                                                                  \
+                                                                       \
+    return 0;                                                          \
+}
+
+ENCODER(dxt1_rgb,  2)
+ENCODER(dxt1_rgba, 2)
+ENCODER(dxt3_rgba, 4)
+ENCODER(dxt5_rgba, 4)
+
+
+/***************************************************************************\
+ * DXTn decoder
+ *
+ * The decoder is based on GL_EXT_texture_compression_s3tc
+ * specification and serves as a concept for the encoder.
+\***************************************************************************/
+
+
+/* lookup table for scaling 4 bit colors up to 8 bits */
+static const byte _rgb_scale_4[] = {
+    0,   17,  34,  51,  68,  85,  102, 119,
+    136, 153, 170, 187, 204, 221, 238, 255
+};
+
+/* lookup table for scaling 5 bit colors up to 8 bits */
+static const byte _rgb_scale_5[] = {
+    0,   8,   16,  25,  33,  41,  49,  58,
+    66,  74,  82,  90,  99,  107, 115, 123,
+    132, 140, 148, 156, 165, 173, 181, 189,
+    197, 206, 214, 222, 230, 239, 247, 255
+};
+
+/* lookup table for scaling 6 bit colors up to 8 bits */
+static const byte _rgb_scale_6[] = {
+    0,   4,   8,   12,  16,  20,  24,  28,
+    32,  36,  40,  45,  49,  53,  57,  61,
+    65,  69,  73,  77,  81,  85,  89,  93,
+    97,  101, 105, 109, 113, 117, 121, 125,
+    130, 134, 138, 142, 146, 150, 154, 158,
+    162, 166, 170, 174, 178, 182, 186, 190,
+    194, 198, 202, 206, 210, 215, 219, 223,
+    227, 231, 235, 239, 243, 247, 251, 255
+};
+
+
+#define CC_SEL(cc, which) (((dword *)(cc))[(which) / 32] >> ((which) & 31))
+#define UP4(c) _rgb_scale_4[(c) & 15]
+#define UP5(c) _rgb_scale_5[(c) & 31]
+#define UP6(c) _rgb_scale_6[(c) & 63]
+#define ZERO_4UBV(v) *((dword *)(v)) = 0
+
+
+void TAPIENTRY
+dxt1_rgb_decode_1 (const void *texture, int stride,
+                  int i, int j, byte *rgba)
+{
+    const byte *src = (const byte *)texture
+                      + ((j / 4) * ((stride + 3) / 4) + i / 4) * 8;
+    const int code = (src[4 + (j & 3)] >> ((i & 3) * 2)) & 0x3;
+    if (code == 0) {
+       rgba[RCOMP] = UP5(CC_SEL(src, 11));
+       rgba[GCOMP] = UP6(CC_SEL(src,  5));
+       rgba[BCOMP] = UP5(CC_SEL(src,  0));
+    } else if (code == 1) {
+       rgba[RCOMP] = UP5(CC_SEL(src, 27));
+       rgba[GCOMP] = UP6(CC_SEL(src, 21));
+       rgba[BCOMP] = UP5(CC_SEL(src, 16));
+    } else {
+       const word col0 = src[0] | (src[1] << 8);
+       const word col1 = src[2] | (src[3] << 8);
+       if (col0 > col1) {
+           if (code == 2) {
+               rgba[RCOMP] = (UP5(col0 >> 11) * 2 + UP5(col1 >> 11)) / 3;
+               rgba[GCOMP] = (UP6(col0 >>  5) * 2 + UP6(col1 >>  5)) / 3;
+               rgba[BCOMP] = (UP5(col0      ) * 2 + UP5(col1      )) / 3;
+           } else {
+               rgba[RCOMP] = (UP5(col0 >> 11) + 2 * UP5(col1 >> 11)) / 3;
+               rgba[GCOMP] = (UP6(col0 >>  5) + 2 * UP6(col1 >>  5)) / 3;
+               rgba[BCOMP] = (UP5(col0      ) + 2 * UP5(col1      )) / 3;
+           }
+       } else {
+           if (code == 2) {
+               rgba[RCOMP] = (UP5(col0 >> 11) + UP5(col1 >> 11)) / 2;
+               rgba[GCOMP] = (UP6(col0 >>  5) + UP6(col1 >>  5)) / 2;
+               rgba[BCOMP] = (UP5(col0      ) + UP5(col1      )) / 2;
+           } else {
+               ZERO_4UBV(rgba);
+           }
+       }
+    }
+    rgba[ACOMP] = 255;
+}
+
+
+void TAPIENTRY
+dxt1_rgba_decode_1 (const void *texture, int stride,
+                   int i, int j, byte *rgba)
+{
+    /* Same as rgb_dxt1 above, except alpha=0 if col0<=col1 and code=3. */
+    const byte *src = (const byte *)texture
+                      + ((j / 4) * ((stride + 3) / 4) + i / 4) * 8;
+    const int code = (src[4 + (j & 3)] >> ((i & 3) * 2)) & 0x3;
+    if (code == 0) {
+       rgba[RCOMP] = UP5(CC_SEL(src, 11));
+       rgba[GCOMP] = UP6(CC_SEL(src,  5));
+       rgba[BCOMP] = UP5(CC_SEL(src,  0));
+       rgba[ACOMP] = 255;
+    } else if (code == 1) {
+       rgba[RCOMP] = UP5(CC_SEL(src, 27));
+       rgba[GCOMP] = UP6(CC_SEL(src, 21));
+       rgba[BCOMP] = UP5(CC_SEL(src, 16));
+       rgba[ACOMP] = 255;
+    } else {
+       const word col0 = src[0] | (src[1] << 8);
+       const word col1 = src[2] | (src[3] << 8);
+       if (col0 > col1) {
+           if (code == 2) {
+               rgba[RCOMP] = (UP5(col0 >> 11) * 2 + UP5(col1 >> 11)) / 3;
+               rgba[GCOMP] = (UP6(col0 >>  5) * 2 + UP6(col1 >>  5)) / 3;
+               rgba[BCOMP] = (UP5(col0      ) * 2 + UP5(col1      )) / 3;
+           } else {
+               rgba[RCOMP] = (UP5(col0 >> 11) + 2 * UP5(col1 >> 11)) / 3;
+               rgba[GCOMP] = (UP6(col0 >>  5) + 2 * UP6(col1 >>  5)) / 3;
+               rgba[BCOMP] = (UP5(col0      ) + 2 * UP5(col1      )) / 3;
+           }
+           rgba[ACOMP] = 255;
+       } else {
+           if (code == 2) {
+               rgba[RCOMP] = (UP5(col0 >> 11) + UP5(col1 >> 11)) / 2;
+               rgba[GCOMP] = (UP6(col0 >>  5) + UP6(col1 >>  5)) / 2;
+               rgba[BCOMP] = (UP5(col0      ) + UP5(col1      )) / 2;
+               rgba[ACOMP] = 255;
+           } else {
+               ZERO_4UBV(rgba);
+           }
+       }
+    }
+}
+
+
+void TAPIENTRY
+dxt3_rgba_decode_1 (const void *texture, int stride,
+                   int i, int j, byte *rgba)
+{
+    const byte *src = (const byte *)texture
+                      + ((j / 4) * ((stride + 3) / 4) + i / 4) * 16;
+    const int code = (src[12 + (j & 3)] >> ((i & 3) * 2)) & 0x3;
+    const dword *cc = (const dword *)(src + 8);
+    if (code == 0) {
+       rgba[RCOMP] = UP5(CC_SEL(cc, 11));
+       rgba[GCOMP] = UP6(CC_SEL(cc,  5));
+       rgba[BCOMP] = UP5(CC_SEL(cc,  0));
+    } else if (code == 1) {
+       rgba[RCOMP] = UP5(CC_SEL(cc, 27));
+       rgba[GCOMP] = UP6(CC_SEL(cc, 21));
+       rgba[BCOMP] = UP5(CC_SEL(cc, 16));
+    } else if (code == 2) {
+       /* (col0 * (4 - code) + col1 * (code - 1)) / 3 */
+       rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) * 2 + UP5(CC_SEL(cc, 27))) / 3;
+       rgba[GCOMP] = (UP6(CC_SEL(cc,  5)) * 2 + UP6(CC_SEL(cc, 21))) / 3;
+       rgba[BCOMP] = (UP5(CC_SEL(cc,  0)) * 2 + UP5(CC_SEL(cc, 16))) / 3;
+    } else {
+       rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) + 2 * UP5(CC_SEL(cc, 27))) / 3;
+       rgba[GCOMP] = (UP6(CC_SEL(cc,  5)) + 2 * UP6(CC_SEL(cc, 21))) / 3;
+       rgba[BCOMP] = (UP5(CC_SEL(cc,  0)) + 2 * UP5(CC_SEL(cc, 16))) / 3;
+    }
+    rgba[ACOMP] = UP4(src[((j & 3) * 4 + (i & 3)) / 2] >> ((i & 1) * 4));
+}
+
+
+void TAPIENTRY
+dxt5_rgba_decode_1 (const void *texture, int stride,
+                   int i, int j, byte *rgba)
+{
+    const byte *src = (const byte *)texture
+                      + ((j / 4) * ((stride + 3) / 4) + i / 4) * 16;
+    const int code = (src[12 + (j & 3)] >> ((i & 3) * 2)) & 0x3;
+    const dword *cc = (const dword *)(src + 8);
+    const byte alpha0 = src[0];
+    const byte alpha1 = src[1];
+    const int alphaShift = (((j & 3) * 4) + (i & 3)) * 3 + 16;
+    const int acode = ((alphaShift == 31)
+                       ? CC_SEL(src + 2, alphaShift - 16)
+                       : CC_SEL(src, alphaShift)) & 0x7;
+    if (code == 0) {
+       rgba[RCOMP] = UP5(CC_SEL(cc, 11));
+       rgba[GCOMP] = UP6(CC_SEL(cc,  5));
+       rgba[BCOMP] = UP5(CC_SEL(cc,  0));
+    } else if (code == 1) {
+       rgba[RCOMP] = UP5(CC_SEL(cc, 27));
+       rgba[GCOMP] = UP6(CC_SEL(cc, 21));
+       rgba[BCOMP] = UP5(CC_SEL(cc, 16));
+    } else if (code == 2) {
+       /* (col0 * (4 - code) + col1 * (code - 1)) / 3 */
+       rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) * 2 + UP5(CC_SEL(cc, 27))) / 3;
+       rgba[GCOMP] = (UP6(CC_SEL(cc,  5)) * 2 + UP6(CC_SEL(cc, 21))) / 3;
+       rgba[BCOMP] = (UP5(CC_SEL(cc,  0)) * 2 + UP5(CC_SEL(cc, 16))) / 3;
+    } else {
+       rgba[RCOMP] = (UP5(CC_SEL(cc, 11)) + 2 * UP5(CC_SEL(cc, 27))) / 3;
+       rgba[GCOMP] = (UP6(CC_SEL(cc,  5)) + 2 * UP6(CC_SEL(cc, 21))) / 3;
+       rgba[BCOMP] = (UP5(CC_SEL(cc,  0)) + 2 * UP5(CC_SEL(cc, 16))) / 3;
+    }
+    if (acode == 0) {
+       rgba[ACOMP] = alpha0;
+    } else if (acode == 1) {
+       rgba[ACOMP] = alpha1;
+    } else if (alpha0 > alpha1) {
+       rgba[ACOMP] = ((8 - acode) * alpha0 + (acode - 1) * alpha1) / 7;
+    } else if (acode == 6) {
+       rgba[ACOMP] = 0;
+    } else if (acode == 7) {
+       rgba[ACOMP] = 255;
+    } else {
+       rgba[ACOMP] = ((6 - acode) * alpha0 + (acode - 1) * alpha1) / 5;
+    }
+}
diff --git a/source/gles2glide64/src/GlideHQ/tc-1.1+/dxtn.h b/source/gles2glide64/src/GlideHQ/tc-1.1+/dxtn.h
new file mode 100644 (file)
index 0000000..4078fd9
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * DXTn codec
+ * Version:  1.1
+ *
+ * Copyright (C) 2004  Daniel Borca   All Rights Reserved.
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.       
+ */
+
+
+#ifndef DXTN_H_included
+#define DXTN_H_included
+
+TAPI int TAPIENTRY
+dxt1_rgb_encode (int width, int height, int comps,
+                const void *source, int srcRowStride,
+                void *dest, int destRowStride);
+
+TAPI int TAPIENTRY
+dxt1_rgba_encode (int width, int height, int comps,
+                 const void *source, int srcRowStride,
+                 void *dest, int destRowStride);
+
+TAPI int TAPIENTRY
+dxt3_rgba_encode (int width, int height, int comps,
+                 const void *source, int srcRowStride,
+                 void *dest, int destRowStride);
+
+TAPI int TAPIENTRY
+dxt5_rgba_encode (int width, int height, int comps,
+                 const void *source, int srcRowStride,
+                 void *dest, int destRowStride);
+
+TAPI void TAPIENTRY
+dxt1_rgb_decode_1 (const void *texture, int stride /* in pixels */,
+                  int i, int j, byte *rgba);
+
+TAPI void TAPIENTRY
+dxt1_rgba_decode_1 (const void *texture, int stride /* in pixels */,
+                   int i, int j, byte *rgba);
+
+TAPI void TAPIENTRY
+dxt3_rgba_decode_1 (const void *texture, int stride /* in pixels */,
+                   int i, int j, byte *rgba);
+
+TAPI void TAPIENTRY
+dxt5_rgba_decode_1 (const void *texture, int stride /* in pixels */,
+                   int i, int j, byte *rgba);
+
+#endif
diff --git a/source/gles2glide64/src/GlideHQ/tc-1.1+/fxt1.c b/source/gles2glide64/src/GlideHQ/tc-1.1+/fxt1.c
new file mode 100644 (file)
index 0000000..623e69c
--- /dev/null
@@ -0,0 +1,1459 @@
+/*
+ * FXT1 codec
+ * Version:  1.1
+ *
+ * Copyright (C) 2004  Daniel Borca   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * DANIEL BORCA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* Copyright (C) 2007  Hiroshi Morii <koolsmoky(at)users.sourceforge.net>
+ * Added support for ARGB inputs.
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "types.h"
+#include "internal.h"
+#include "fxt1.h"
+
+
+/***************************************************************************\
+ * FXT1 encoder
+ *
+ * The encoder was built by reversing the decoder,
+ * and is vaguely based on Texus2 by 3dfx. Note that this code
+ * is merely a proof of concept, since it is highly UNoptimized;
+ * moreover, it is sub-optimal due to initial conditions passed
+ * to Lloyd's algorithm (the interpolation modes are even worse).
+\***************************************************************************/
+
+
+#define MAX_COMP 4 /* ever needed maximum number of components in texel */
+#define MAX_VECT 4 /* ever needed maximum number of base vectors to find */
+#define N_TEXELS 32 /* number of texels in a block (always 32) */
+#define LL_N_REP 50 /* number of iterations in lloyd's vq */
+#define LL_RMS_D 10 /* fault tolerance (maximum delta) */
+#define LL_RMS_E 255 /* fault tolerance (maximum error) */
+#define ALPHA_TS 2 /* alpha threshold: (255 - ALPHA_TS) deemed opaque */
+#define ISTBLACK(v) (*((dword *)(v)) == 0)
+#define COPY_4UBV(DST, SRC) *((dword *)(DST)) = *((dword *)(SRC))
+
+
+static int
+fxt1_bestcol (float vec[][MAX_COMP], int nv,
+             byte input[MAX_COMP], int nc)
+{
+    int i, j, best = -1;
+    float err = 1e9; /* big enough */
+
+    for (j = 0; j < nv; j++) {
+       float e = 0.0F;
+       for (i = 0; i < nc; i++) {
+           e += (vec[j][i] - input[i]) * (vec[j][i] - input[i]);
+       }
+       if (e < err) {
+           err = e;
+           best = j;
+       }
+    }
+
+    return best;
+}
+
+
+static int
+fxt1_worst (float vec[MAX_COMP],
+           byte input[N_TEXELS][MAX_COMP], int nc, int n)
+{
+    int i, k, worst = -1;
+    float err = -1.0F; /* small enough */
+
+    for (k = 0; k < n; k++) {
+       float e = 0.0F;
+       for (i = 0; i < nc; i++) {
+           e += (vec[i] - input[k][i]) * (vec[i] - input[k][i]);
+       }
+       if (e > err) {
+           err = e;
+           worst = k;
+       }
+    }
+
+    return worst;
+}
+
+
+static int
+fxt1_variance (double variance[MAX_COMP],
+              byte input[N_TEXELS][MAX_COMP], int nc, int n)
+{
+    int i, k, best = 0;
+    dword sx, sx2;
+    double var, maxvar = -1; /* small enough */
+    double teenth = 1.0 / n;
+
+    for (i = 0; i < nc; i++) {
+       sx = sx2 = 0;
+       for (k = 0; k < n; k++) {
+           int t = input[k][i];
+           sx += t;
+           sx2 += t * t;
+       }
+       var = sx2 * teenth - sx * sx * teenth * teenth;
+       if (maxvar < var) {
+           maxvar = var;
+           best = i;
+       }
+       if (variance) {
+           variance[i] = var;
+       }
+    }
+
+    return best;
+}
+
+
+static int
+fxt1_choose (float vec[][MAX_COMP], int nv,
+            byte input[N_TEXELS][MAX_COMP], int nc, int n)
+{
+#if 0
+    /* Choose colors from a grid.
+     */
+    int i, j;
+
+    for (j = 0; j < nv; j++) {
+       int m = j * (n - 1) / (nv - 1);
+       for (i = 0; i < nc; i++) {
+           vec[j][i] = input[m][i];
+       }
+    }
+#else
+    /* Our solution here is to find the darkest and brightest colors in
+     * the 8x4 tile and use those as the two representative colors.
+     * There are probably better algorithms to use (histogram-based).
+     */
+    int i, j, k;
+#ifndef YUV
+    int minSum = 2000; /* big enough */
+#else
+    int minSum = 2000000;
+#endif
+    int maxSum = -1; /* small enough */
+    int minCol = 0; /* phoudoin: silent compiler! */
+    int maxCol = 0; /* phoudoin: silent compiler! */
+
+    struct {
+       int flag;
+       dword key;
+       int freq;
+       int idx;
+    } hist[N_TEXELS];
+    int lenh = 0;
+
+    memset(hist, 0, sizeof(hist));
+
+    for (k = 0; k < n; k++) {
+       int l;
+       dword key = 0;
+       int sum = 0;
+       for (i = 0; i < nc; i++) {
+           key <<= 8;
+           key |= input[k][i];
+#ifndef YUV
+           sum += input[k][i];
+#else
+            /* RGB to YUV conversion according to CCIR 601 specs
+             * Y = 0.299R+0.587G+0.114B
+             * U = 0.713(R - Y) = 0.500R-0.419G-0.081B
+             * V = 0.564(B - Y) = -0.169R-0.331G+0.500B
+             */
+            sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] +  114 * input[k][BCOMP];
+#endif
+        }
+       for (l = 0; l < n; l++) {
+           if (!hist[l].flag) {
+               /* alloc new slot */
+               hist[l].flag = !0;
+               hist[l].key = key;
+               hist[l].freq = 1;
+               hist[l].idx = k;
+               lenh = l + 1;
+               break;
+           } else if (hist[l].key == key) {
+               hist[l].freq++;
+               break;
+           }
+       }
+       if (minSum > sum) {
+           minSum = sum;
+           minCol = k;
+       }
+       if (maxSum < sum) {
+           maxSum = sum;
+           maxCol = k;
+       }
+    }
+
+    if (lenh <= nv) {
+       for (j = 0; j < lenh; j++) {
+           for (i = 0; i < nc; i++) {
+               vec[j][i] = (float)input[hist[j].idx][i];
+           }
+       }
+       for (; j < nv; j++) {
+           for (i = 0; i < nc; i++) {
+               vec[j][i] = vec[0][i];
+           }
+       }
+       return 0;
+    }
+
+    for (j = 0; j < nv; j++) {
+       for (i = 0; i < nc; i++) {
+           vec[j][i] = ((nv - 1 - j) * input[minCol][i] + j * input[maxCol][i] + (nv - 1) / 2) / (float)(nv - 1);
+       }
+    }
+#endif
+
+    return !0;
+}
+
+
+static int
+fxt1_lloyd (float vec[][MAX_COMP], int nv,
+           byte input[N_TEXELS][MAX_COMP], int nc, int n)
+{
+    /* Use the generalized lloyd's algorithm for VQ:
+     *     find 4 color vectors.
+     *
+     *     for each sample color
+     *         sort to nearest vector.
+     *
+     *     replace each vector with the centroid of it's matching colors.
+     *
+     *     repeat until RMS doesn't improve.
+     *
+     *     if a color vector has no samples, or becomes the same as another
+     *     vector, replace it with the color which is farthest from a sample.
+     *
+     * vec[][MAX_COMP]           initial vectors and resulting colors
+     * nv                        number of resulting colors required
+     * input[N_TEXELS][MAX_COMP] input texels
+     * nc                        number of components in input / vec
+     * n                         number of input samples
+     */
+
+    int sum[MAX_VECT][MAX_COMP]; /* used to accumulate closest texels */
+    int cnt[MAX_VECT]; /* how many times a certain vector was chosen */
+    float error, lasterror = 1e9;
+
+    int i, j, k, rep;
+
+    /* the quantizer */
+    for (rep = 0; rep < LL_N_REP; rep++) {
+       /* reset sums & counters */
+       for (j = 0; j < nv; j++) {
+           for (i = 0; i < nc; i++) {
+               sum[j][i] = 0;
+           }
+           cnt[j] = 0;
+       }
+       error = 0;
+
+       /* scan whole block */
+       for (k = 0; k < n; k++) {
+#if 1
+           int best = -1;
+           float err = 1e9; /* big enough */
+           /* determine best vector */
+           for (j = 0; j < nv; j++) {
+               float e = (vec[j][0] - input[k][0]) * (vec[j][0] - input[k][0]) +
+                         (vec[j][1] - input[k][1]) * (vec[j][1] - input[k][1]) +
+                         (vec[j][2] - input[k][2]) * (vec[j][2] - input[k][2]);
+               if (nc == 4) {
+                   e += (vec[j][3] - input[k][3]) * (vec[j][3] - input[k][3]);
+               }
+               if (e < err) {
+                   err = e;
+                   best = j;
+               }
+           }
+#else
+           int best = fxt1_bestcol(vec, nv, input[k], nc, &err);
+#endif
+           /* add in closest color */
+           for (i = 0; i < nc; i++) {
+               sum[best][i] += input[k][i];
+           }
+           /* mark this vector as used */
+           cnt[best]++;
+           /* accumulate error */
+           error += err;
+       }
+
+       /* check RMS */
+       if ((error < LL_RMS_E) ||
+           ((error < lasterror) && ((lasterror - error) < LL_RMS_D))) {
+           return !0; /* good match */
+       }
+       lasterror = error;
+
+       /* move each vector to the barycenter of its closest colors */
+       for (j = 0; j < nv; j++) {
+           if (cnt[j]) {
+               float div = 1.0F / cnt[j];
+               for (i = 0; i < nc; i++) {
+                   vec[j][i] = div * sum[j][i];
+               }
+           } else {
+               /* this vec has no samples or is identical with a previous vec */
+               int worst = fxt1_worst(vec[j], input, nc, n);
+               for (i = 0; i < nc; i++) {
+                   vec[j][i] = input[worst][i];
+               }
+           }
+       }
+    }
+
+    return 0; /* could not converge fast enough */
+}
+
+
+static void
+fxt1_quantize_CHROMA (dword *cc,
+                     byte input[N_TEXELS][MAX_COMP])
+{
+    const int n_vect = 4; /* 4 base vectors to find */
+    const int n_comp = 3; /* 3 components: R, G, B */
+    float vec[MAX_VECT][MAX_COMP];
+    int i, j, k;
+    qword hi; /* high quadword */
+    dword lohi, lolo; /* low quadword: hi dword, lo dword */
+
+    if (fxt1_choose(vec, n_vect, input, n_comp, N_TEXELS) != 0) {
+       fxt1_lloyd(vec, n_vect, input, n_comp, N_TEXELS);
+    }
+
+    Q_MOV32(hi, 4); /* cc-chroma = "010" + unused bit */
+    for (j = n_vect - 1; j >= 0; j--) {
+       for (i = 0; i < n_comp; i++) {
+           /* add in colors */
+           Q_SHL(hi, 5);
+           Q_OR32(hi, (dword)(vec[j][i] / 8.0F));
+       }
+    }
+    ((qword *)cc)[1] = hi;
+
+    lohi = lolo = 0;
+    /* right microtile */
+    for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
+       lohi <<= 2;
+       lohi |= fxt1_bestcol(vec, n_vect, input[k], n_comp);
+    }
+    /* left microtile */
+    for (; k >= 0; k--) {
+       lolo <<= 2;
+       lolo |= fxt1_bestcol(vec, n_vect, input[k], n_comp);
+    }
+    cc[1] = lohi;
+    cc[0] = lolo;
+}
+
+
+static void
+fxt1_quantize_ALPHA0 (dword *cc,
+                     byte input[N_TEXELS][MAX_COMP],
+                     byte reord[N_TEXELS][MAX_COMP], int n)
+{
+    const int n_vect = 3; /* 3 base vectors to find */
+    const int n_comp = 4; /* 4 components: R, G, B, A */
+    float vec[MAX_VECT][MAX_COMP];
+    int i, j, k;
+    qword hi; /* high quadword */
+    dword lohi, lolo; /* low quadword: hi dword, lo dword */
+
+    /* the last vector indicates zero */
+    for (i = 0; i < n_comp; i++) {
+       vec[n_vect][i] = 0;
+    }
+
+    /* the first n texels in reord are guaranteed to be non-zero */
+    if (fxt1_choose(vec, n_vect, reord, n_comp, n) != 0) {
+       fxt1_lloyd(vec, n_vect, reord, n_comp, n);
+    }
+
+    Q_MOV32(hi, 6); /* alpha = "011" + lerp = 0 */
+    for (j = n_vect - 1; j >= 0; j--) {
+       /* add in alphas */
+       Q_SHL(hi, 5);
+       Q_OR32(hi, (dword)(vec[j][ACOMP] / 8.0F));
+    }
+    for (j = n_vect - 1; j >= 0; j--) {
+       for (i = 0; i < n_comp - 1; i++) {
+           /* add in colors */
+           Q_SHL(hi, 5);
+           Q_OR32(hi, (dword)(vec[j][i] / 8.0F));
+       }
+    }
+    ((qword *)cc)[1] = hi;
+
+    lohi = lolo = 0;
+    /* right microtile */
+    for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
+       lohi <<= 2;
+       lohi |= fxt1_bestcol(vec, n_vect + 1, input[k], n_comp);
+    }
+    /* left microtile */
+    for (; k >= 0; k--) {
+       lolo <<= 2;
+       lolo |= fxt1_bestcol(vec, n_vect + 1, input[k], n_comp);
+    }
+    cc[1] = lohi;
+    cc[0] = lolo;
+}
+
+
+static void
+fxt1_quantize_ALPHA1 (dword *cc,
+                     byte input[N_TEXELS][MAX_COMP])
+{
+    const int n_vect = 3; /* highest vector number in each microtile */
+    const int n_comp = 4; /* 4 components: R, G, B, A */
+    float vec[1 + 1 + 1][MAX_COMP]; /* 1.5 extrema for each sub-block */
+    float b, iv[MAX_COMP]; /* interpolation vector */
+    int i, j, k;
+    qword hi; /* high quadword */
+    dword lohi, lolo; /* low quadword: hi dword, lo dword */
+
+    int minSum;
+    int maxSum;
+    int minColL = 0, maxColL = 0;
+    int minColR = 0, maxColR = 0;
+    int sumL = 0, sumR = 0;
+
+    /* Our solution here is to find the darkest and brightest colors in
+     * the 4x4 tile and use those as the two representative colors.
+     * There are probably better algorithms to use (histogram-based).
+     */
+#ifndef YUV
+    minSum = 2000; /* big enough */
+#else
+    minSum = 2000000;
+#endif
+    maxSum = -1; /* small enough */
+    for (k = 0; k < N_TEXELS / 2; k++) {
+       int sum = 0;
+#ifndef YUV
+       for (i = 0; i < n_comp; i++) {
+           sum += input[k][i];
+       }
+#else
+        sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] +  114 * input[k][BCOMP];
+#endif
+       if (minSum > sum) {
+           minSum = sum;
+           minColL = k;
+       }
+       if (maxSum < sum) {
+           maxSum = sum;
+           maxColL = k;
+       }
+       sumL += sum;
+    }
+#ifndef YUV
+    minSum = 2000; /* big enough */
+#else
+    minSum = 2000000;
+#endif
+    maxSum = -1; /* small enough */
+    for (; k < N_TEXELS; k++) {
+       int sum = 0;
+#ifndef YUV
+       for (i = 0; i < n_comp; i++) {
+           sum += input[k][i];
+       }
+#else
+        sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] +  114 * input[k][BCOMP];
+#endif
+       if (minSum > sum) {
+           minSum = sum;
+           minColR = k;
+       }
+       if (maxSum < sum) {
+           maxSum = sum;
+           maxColR = k;
+       }
+       sumR += sum;
+    }
+
+    /* choose the common vector (yuck!) */
+    {
+       int j1, j2;
+       int v1 = 0, v2 = 0;
+       float err = 1e9; /* big enough */
+       float tv[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */
+       for (i = 0; i < n_comp; i++) {
+           tv[0][i] = input[minColL][i];
+           tv[1][i] = input[maxColL][i];
+           tv[2][i] = input[minColR][i];
+           tv[3][i] = input[maxColR][i];
+       }
+       for (j1 = 0; j1 < 2; j1++) {
+           for (j2 = 2; j2 < 4; j2++) {
+               float e = 0.0F;
+               for (i = 0; i < n_comp; i++) {
+                   e += (tv[j1][i] - tv[j2][i]) * (tv[j1][i] - tv[j2][i]);
+               }
+               if (e < err) {
+                   err = e;
+                   v1 = j1;
+                   v2 = j2;
+               }
+           }
+       }
+       for (i = 0; i < n_comp; i++) {
+           vec[0][i] = tv[1 - v1][i];
+           vec[1][i] = (tv[v1][i] * sumL + tv[v2][i] * sumR) / (sumL + sumR);
+           vec[2][i] = tv[5 - v2][i];
+       }
+    }
+
+    /* left microtile */
+    cc[0] = 0;
+    if (minColL != maxColL) {
+       /* compute interpolation vector */
+       MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]);
+
+       /* add in texels */
+       lolo = 0;
+       for (k = N_TEXELS / 2 - 1; k >= 0; k--) {
+           int texel;
+           /* interpolate color */
+           CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+           /* add in texel */
+           lolo <<= 2;
+           lolo |= texel;
+       }
+
+       cc[0] = lolo;
+    }
+
+    /* right microtile */
+    cc[1] = 0;
+    if (minColR != maxColR) {
+       /* compute interpolation vector */
+       MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[1]);
+
+       /* add in texels */
+       lohi = 0;
+       for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
+           int texel;
+           /* interpolate color */
+           CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+           /* add in texel */
+           lohi <<= 2;
+           lohi |= texel;
+       }
+
+       cc[1] = lohi;
+    }
+
+    Q_MOV32(hi, 7); /* alpha = "011" + lerp = 1 */
+    for (j = n_vect - 1; j >= 0; j--) {
+       /* add in alphas */
+       Q_SHL(hi, 5);
+       Q_OR32(hi, (dword)(vec[j][ACOMP] / 8.0F));
+    }
+    for (j = n_vect - 1; j >= 0; j--) {
+       for (i = 0; i < n_comp - 1; i++) {
+           /* add in colors */
+           Q_SHL(hi, 5);
+           Q_OR32(hi, (dword)(vec[j][i] / 8.0F));
+       }
+    }
+    ((qword *)cc)[1] = hi;
+}
+
+
+static void
+fxt1_quantize_HI (dword *cc,
+                 byte input[N_TEXELS][MAX_COMP],
+                 byte reord[N_TEXELS][MAX_COMP], int n)
+{
+    const int n_vect = 6; /* highest vector number */
+    const int n_comp = 3; /* 3 components: R, G, B */
+    float b = 0.0F;       /* phoudoin: silent compiler! */
+    float iv[MAX_COMP];   /* interpolation vector */
+    int i, k;
+    dword hihi; /* high quadword: hi dword */
+
+#ifndef YUV
+    int minSum = 2000; /* big enough */
+#else
+    int minSum = 2000000;
+#endif
+    int maxSum = -1; /* small enough */
+    int minCol = 0; /* phoudoin: silent compiler! */
+    int maxCol = 0; /* phoudoin: silent compiler! */
+
+    /* Our solution here is to find the darkest and brightest colors in
+     * the 8x4 tile and use those as the two representative colors.
+     * There are probably better algorithms to use (histogram-based).
+     */
+    for (k = 0; k < n; k++) {
+       int sum = 0;
+#ifndef YUV
+       for (i = 0; i < n_comp; i++) {
+           sum += reord[k][i];
+       }
+#else
+        sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] +  114 * input[k][BCOMP];
+#endif
+       if (minSum > sum) {
+           minSum = sum;
+           minCol = k;
+       }
+       if (maxSum < sum) {
+           maxSum = sum;
+           maxCol = k;
+       }
+    }
+
+    hihi = 0; /* cc-hi = "00" */
+    for (i = 0; i < n_comp; i++) {
+       /* add in colors */
+       hihi <<= 5;
+       hihi |= reord[maxCol][i] >> 3;
+    }
+    for (i = 0; i < n_comp; i++) {
+       /* add in colors */
+       hihi <<= 5;
+       hihi |= reord[minCol][i] >> 3;
+    }
+    cc[3] = hihi;
+    cc[0] = cc[1] = cc[2] = 0;
+
+    /* compute interpolation vector */
+    if (minCol != maxCol) {
+       MAKEIVEC(n_vect, n_comp, iv, b, reord[minCol], reord[maxCol]);
+    }
+
+    /* add in texels */
+    for (k = N_TEXELS - 1; k >= 0; k--) {
+       int t = k * 3;
+       dword *kk = (dword *)((byte *)cc + t / 8);
+       int texel = n_vect + 1; /* transparent black */
+
+       if (!ISTBLACK(input[k])) {
+           if (minCol != maxCol) {
+               /* interpolate color */
+               CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+               /* add in texel */
+               kk[0] |= texel << (t & 7);
+           }
+       } else {
+           /* add in texel */
+           kk[0] |= texel << (t & 7);
+       }
+    }
+}
+
+
+static void
+fxt1_quantize_MIXED1 (dword *cc,
+                     byte input[N_TEXELS][MAX_COMP])
+{
+    const int n_vect = 2; /* highest vector number in each microtile */
+    const int n_comp = 3; /* 3 components: R, G, B */
+    byte vec[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */
+    float b, iv[MAX_COMP]; /* interpolation vector */
+    int i, j, k;
+    qword hi; /* high quadword */
+    dword lohi, lolo; /* low quadword: hi dword, lo dword */
+
+    int minSum;
+    int maxSum;
+    int minColL = 0, maxColL = -1;
+    int minColR = 0, maxColR = -1;
+
+    /* Our solution here is to find the darkest and brightest colors in
+     * the 4x4 tile and use those as the two representative colors.
+     * There are probably better algorithms to use (histogram-based).
+     */
+#ifndef YUV
+    minSum = 2000; /* big enough */
+#else
+    minSum = 2000000;
+#endif
+    maxSum = -1; /* small enough */
+    for (k = 0; k < N_TEXELS / 2; k++) {
+       if (!ISTBLACK(input[k])) {
+           int sum = 0;
+#ifndef YUV
+           for (i = 0; i < n_comp; i++) {
+               sum += input[k][i];
+           }
+#else
+            sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] +  114 * input[k][BCOMP];
+#endif
+           if (minSum > sum) {
+               minSum = sum;
+               minColL = k;
+           }
+           if (maxSum < sum) {
+               maxSum = sum;
+               maxColL = k;
+           }
+       }
+    }
+#ifndef YUV
+    minSum = 2000; /* big enough */
+#else
+    minSum = 2000000;
+#endif
+    maxSum = -1; /* small enough */
+    for (; k < N_TEXELS; k++) {
+       if (!ISTBLACK(input[k])) {
+           int sum = 0;
+#ifndef YUV
+           for (i = 0; i < n_comp; i++) {
+               sum += input[k][i];
+           }
+#else
+            sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] +  114 * input[k][BCOMP];
+#endif
+           if (minSum > sum) {
+               minSum = sum;
+               minColR = k;
+           }
+           if (maxSum < sum) {
+               maxSum = sum;
+               maxColR = k;
+           }
+       }
+    }
+
+    /* left microtile */
+    if (maxColL == -1) {
+       /* all transparent black */
+       cc[0] = 0xFFFFFFFF;
+       for (i = 0; i < n_comp; i++) {
+           vec[0][i] = 0;
+           vec[1][i] = 0;
+       }
+    } else {
+       cc[0] = 0;
+       for (i = 0; i < n_comp; i++) {
+           vec[0][i] = input[minColL][i];
+           vec[1][i] = input[maxColL][i];
+       }
+       if (minColL != maxColL) {
+           /* compute interpolation vector */
+           MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]);
+
+           /* add in texels */
+           lolo = 0;
+           for (k = N_TEXELS / 2 - 1; k >= 0; k--) {
+               int texel = n_vect + 1; /* transparent black */
+               if (!ISTBLACK(input[k])) {
+                   /* interpolate color */
+                   CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+               }
+               /* add in texel */
+               lolo <<= 2;
+               lolo |= texel;
+           }
+           cc[0] = lolo;
+       }
+    }
+
+    /* right microtile */
+    if (maxColR == -1) {
+       /* all transparent black */
+       cc[1] = 0xFFFFFFFF;
+       for (i = 0; i < n_comp; i++) {
+           vec[2][i] = 0;
+           vec[3][i] = 0;
+       }
+    } else {
+       cc[1] = 0;
+       for (i = 0; i < n_comp; i++) {
+           vec[2][i] = input[minColR][i];
+           vec[3][i] = input[maxColR][i];
+       }
+       if (minColR != maxColR) {
+           /* compute interpolation vector */
+           MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[3]);
+
+           /* add in texels */
+           lohi = 0;
+           for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
+               int texel = n_vect + 1; /* transparent black */
+               if (!ISTBLACK(input[k])) {
+                   /* interpolate color */
+                   CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+               }
+               /* add in texel */
+               lohi <<= 2;
+               lohi |= texel;
+           }
+           cc[1] = lohi;
+       }
+    }
+
+    Q_MOV32(hi, 9 | (vec[3][GCOMP] & 4) | ((vec[1][GCOMP] >> 1) & 2)); /* chroma = "1" */
+    for (j = 2 * 2 - 1; j >= 0; j--) {
+       for (i = 0; i < n_comp; i++) {
+           /* add in colors */
+           Q_SHL(hi, 5);
+           Q_OR32(hi, vec[j][i] >> 3);
+       }
+    }
+    ((qword *)cc)[1] = hi;
+}
+
+
+static void
+fxt1_quantize_MIXED0 (dword *cc,
+                     byte input[N_TEXELS][MAX_COMP])
+{
+    const int n_vect = 3; /* highest vector number in each microtile */
+    const int n_comp = 3; /* 3 components: R, G, B */
+    byte vec[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */
+    float b, iv[MAX_COMP]; /* interpolation vector */
+    int i, j, k;
+    qword hi; /* high quadword */
+    dword lohi, lolo; /* low quadword: hi dword, lo dword */
+
+    int minColL = 0, maxColL = 0;
+    int minColR = 0, maxColR = 0;
+#if 0
+    int minSum;
+    int maxSum;
+
+    /* Our solution here is to find the darkest and brightest colors in
+     * the 4x4 tile and use those as the two representative colors.
+     * There are probably better algorithms to use (histogram-based).
+     */
+#ifndef YUV
+    minSum = 2000; /* big enough */
+#else
+    minSum = 2000000;
+#endif
+    maxSum = -1; /* small enough */
+    for (k = 0; k < N_TEXELS / 2; k++) {
+       int sum = 0;
+#ifndef YUV
+       for (i = 0; i < n_comp; i++) {
+           sum += input[k][i];
+       }
+#else
+        sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] +  114 * input[k][BCOMP];
+#endif
+       if (minSum > sum) {
+           minSum = sum;
+           minColL = k;
+       }
+       if (maxSum < sum) {
+           maxSum = sum;
+           maxColL = k;
+       }
+    }
+    minSum = 2000; /* big enough */
+    maxSum = -1; /* small enough */
+    for (; k < N_TEXELS; k++) {
+       int sum = 0;
+#ifndef YUV
+       for (i = 0; i < n_comp; i++) {
+           sum += input[k][i];
+       }
+#else
+        sum = 299 * input[k][RCOMP] + 587 * input[k][GCOMP] +  114 * input[k][BCOMP];
+#endif
+       if (minSum > sum) {
+           minSum = sum;
+           minColR = k;
+       }
+       if (maxSum < sum) {
+           maxSum = sum;
+           maxColR = k;
+       }
+    }
+#else
+    int minVal;
+    int maxVal;
+    int maxVarL = fxt1_variance(NULL, input, n_comp, N_TEXELS / 2);
+    int maxVarR = fxt1_variance(NULL, &input[N_TEXELS / 2], n_comp, N_TEXELS / 2);
+
+    /* Scan the channel with max variance for lo & hi
+     * and use those as the two representative colors.
+     */
+    minVal = 2000; /* big enough */
+    maxVal = -1; /* small enough */
+    for (k = 0; k < N_TEXELS / 2; k++) {
+       int t = input[k][maxVarL];
+       if (minVal > t) {
+           minVal = t;
+           minColL = k;
+       }
+       if (maxVal < t) {
+           maxVal = t;
+           maxColL = k;
+       }
+    }
+    minVal = 2000; /* big enough */
+    maxVal = -1; /* small enough */
+    for (; k < N_TEXELS; k++) {
+       int t = input[k][maxVarR];
+       if (minVal > t) {
+           minVal = t;
+           minColR = k;
+       }
+       if (maxVal < t) {
+           maxVal = t;
+           maxColR = k;
+       }
+    }
+#endif
+
+    /* left microtile */
+    cc[0] = 0;
+    for (i = 0; i < n_comp; i++) {
+       vec[0][i] = input[minColL][i];
+       vec[1][i] = input[maxColL][i];
+    }
+    if (minColL != maxColL) {
+       /* compute interpolation vector */
+       MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]);
+
+       /* add in texels */
+       lolo = 0;
+       for (k = N_TEXELS / 2 - 1; k >= 0; k--) {
+           int texel;
+           /* interpolate color */
+           CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+           /* add in texel */
+           lolo <<= 2;
+           lolo |= texel;
+       }
+
+       /* funky encoding for LSB of green */
+       if ((int)((lolo >> 1) & 1) != (((vec[1][GCOMP] ^ vec[0][GCOMP]) >> 2) & 1)) {
+           for (i = 0; i < n_comp; i++) {
+               vec[1][i] = input[minColL][i];
+               vec[0][i] = input[maxColL][i];
+           }
+           lolo = ~lolo;
+       }
+
+       cc[0] = lolo;
+    }
+
+    /* right microtile */
+    cc[1] = 0;
+    for (i = 0; i < n_comp; i++) {
+       vec[2][i] = input[minColR][i];
+       vec[3][i] = input[maxColR][i];
+    }
+    if (minColR != maxColR) {
+       /* compute interpolation vector */
+       MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[3]);
+
+       /* add in texels */
+       lohi = 0;
+       for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
+           int texel;
+           /* interpolate color */
+           CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
+           /* add in texel */
+           lohi <<= 2;
+           lohi |= texel;
+       }
+
+       /* funky encoding for LSB of green */
+       if ((int)((lohi >> 1) & 1) != (((vec[3][GCOMP] ^ vec[2][GCOMP]) >> 2) & 1)) {
+           for (i = 0; i < n_comp; i++) {
+               vec[3][i] = input[minColR][i];
+               vec[2][i] = input[maxColR][i];
+           }
+           lohi = ~lohi;
+       }
+
+       cc[1] = lohi;
+    }
+
+    Q_MOV32(hi, 8 | (vec[3][GCOMP] & 4) | ((vec[1][GCOMP] >> 1) & 2)); /* chroma = "1" */
+    for (j = 2 * 2 - 1; j >= 0; j--) {
+       for (i = 0; i < n_comp; i++) {
+           /* add in colors */
+           Q_SHL(hi, 5);
+           Q_OR32(hi, vec[j][i] >> 3);
+       }
+    }
+    ((qword *)cc)[1] = hi;
+}
+
+
+static void
+fxt1_quantize (dword *cc, const byte *lines[], int comps)
+{
+    int trualpha;
+    byte reord[N_TEXELS][MAX_COMP];
+
+    byte input[N_TEXELS][MAX_COMP];
+#ifndef ARGB
+    int i;
+#endif
+    int k, l;
+
+    if (comps == 3) {
+       /* make the whole block opaque */
+       memset(input, -1, sizeof(input));
+    }
+
+    /* 8 texels each line */
+#ifndef ARGB
+    for (l = 0; l < 4; l++) {
+       for (k = 0; k < 4; k++) {
+           for (i = 0; i < comps; i++) {
+               input[k + l * 4][i] = *lines[l]++;
+           }
+       }
+       for (; k < 8; k++) {
+           for (i = 0; i < comps; i++) {
+               input[k + l * 4 + 12][i] = *lines[l]++;
+           }
+       }
+    }
+#else
+    /* H.Morii - support for ARGB inputs */
+    for (l = 0; l < 4; l++) {
+       for (k = 0; k < 4; k++) {
+          input[k + l * 4][2] = *lines[l]++;
+          input[k + l * 4][1] = *lines[l]++;
+          input[k + l * 4][0] = *lines[l]++;
+          if (comps == 4) input[k + l * 4][3] = *lines[l]++;
+       }
+       for (; k < 8; k++) {
+          input[k + l * 4 + 12][2] = *lines[l]++;
+          input[k + l * 4 + 12][1] = *lines[l]++;
+          input[k + l * 4 + 12][0] = *lines[l]++;
+          if (comps == 4) input[k + l * 4 + 12][3] = *lines[l]++;
+       }
+    }
+#endif
+
+    /* block layout:
+     * 00, 01, 02, 03, 08, 09, 0a, 0b
+     * 10, 11, 12, 13, 18, 19, 1a, 1b
+     * 04, 05, 06, 07, 0c, 0d, 0e, 0f
+     * 14, 15, 16, 17, 1c, 1d, 1e, 1f
+     */
+
+    /* [dBorca]
+     * stupidity flows forth from this
+     */
+    l = N_TEXELS;
+    trualpha = 0;
+    if (comps == 4) {
+       /* skip all transparent black texels */
+       l = 0;
+       for (k = 0; k < N_TEXELS; k++) {
+           /* test all components against 0 */
+           if (!ISTBLACK(input[k])) {
+               /* texel is not transparent black */
+               COPY_4UBV(reord[l], input[k]);
+               if (reord[l][ACOMP] < (255 - ALPHA_TS)) {
+                   /* non-opaque texel */
+                   trualpha = !0;
+               }
+               l++;
+           }
+       }
+    }
+
+#if 0
+    if (trualpha) {
+       fxt1_quantize_ALPHA0(cc, input, reord, l);
+    } else if (l == 0) {
+       cc[0] = cc[1] = cc[2] = -1;
+       cc[3] = 0;
+    } else if (l < N_TEXELS) {
+       fxt1_quantize_HI(cc, input, reord, l);
+    } else {
+       fxt1_quantize_CHROMA(cc, input);
+    }
+    (void)fxt1_quantize_ALPHA1;
+    (void)fxt1_quantize_MIXED1;
+    (void)fxt1_quantize_MIXED0;
+#else
+    if (trualpha) {
+       fxt1_quantize_ALPHA1(cc, input);
+    } else if (l == 0) {
+       cc[0] = cc[1] = cc[2] = 0xFFFFFFFF;
+       cc[3] = 0;
+    } else if (l < N_TEXELS) {
+       fxt1_quantize_MIXED1(cc, input);
+    } else {
+       fxt1_quantize_MIXED0(cc, input);
+    }
+    (void)fxt1_quantize_ALPHA0;
+    (void)fxt1_quantize_HI;
+    (void)fxt1_quantize_CHROMA;
+#endif
+}
+
+
+TAPI int TAPIENTRY
+fxt1_encode (int width, int height, int comps,
+            const void *source, int srcRowStride,
+            void *dest, int destRowStride)
+{
+    int x, y;
+    const byte *data;
+    dword *encoded = (dword *)dest;
+    void *newSource = NULL;
+
+    /* Replicate image if width is not M8 or height is not M4 */
+    if ((width & 7) | (height & 3)) {
+       int newWidth = (width + 7) & ~7;
+       int newHeight = (height + 3) & ~3;
+       newSource = malloc(comps * newWidth * newHeight * sizeof(byte *));
+       _mesa_upscale_teximage2d(width, height, newWidth, newHeight,
+                                comps, (const byte *)source,
+                                srcRowStride, (byte *)newSource);
+       source = newSource;
+       width = newWidth;
+       height = newHeight;
+       srcRowStride = comps * newWidth;
+    }
+
+    data = (const byte *)source;
+    destRowStride = (destRowStride - width * 2) / 4;
+    for (y = 0; y < height; y += 4) {
+       unsigned int offs = 0 + (y + 0) * srcRowStride;
+       for (x = 0; x < width; x += 8) {
+           const byte *lines[4];
+           lines[0] = &data[offs];
+           lines[1] = lines[0] + srcRowStride;
+           lines[2] = lines[1] + srcRowStride;
+           lines[3] = lines[2] + srcRowStride;
+           offs += 8 * comps;
+           fxt1_quantize(encoded, lines, comps);
+           /* 128 bits per 8x4 block */
+           encoded += 4;
+       }
+       encoded += destRowStride;
+    }
+
+    if (newSource != NULL) {
+       free(newSource);
+    }
+
+    return 0;
+}
+
+
+/***************************************************************************\
+ * FXT1 decoder
+ *
+ * The decoder is based on GL_3DFX_texture_compression_FXT1
+ * specification and serves as a concept for the encoder.
+\***************************************************************************/
+
+
+/* lookup table for scaling 5 bit colors up to 8 bits */
+static const byte _rgb_scale_5[] = {
+    0,   8,   16,  25,  33,  41,  49,  58,
+    66,  74,  82,  90,  99,  107, 115, 123,
+    132, 140, 148, 156, 165, 173, 181, 189,
+    197, 206, 214, 222, 230, 239, 247, 255
+};
+
+/* lookup table for scaling 6 bit colors up to 8 bits */
+static const byte _rgb_scale_6[] = {
+    0,   4,   8,   12,  16,  20,  24,  28,
+    32,  36,  40,  45,  49,  53,  57,  61,
+    65,  69,  73,  77,  81,  85,  89,  93,
+    97,  101, 105, 109, 113, 117, 121, 125,
+    130, 134, 138, 142, 146, 150, 154, 158,
+    162, 166, 170, 174, 178, 182, 186, 190,
+    194, 198, 202, 206, 210, 215, 219, 223,
+    227, 231, 235, 239, 243, 247, 251, 255
+};
+
+
+#define CC_SEL(cc, which) (((dword *)(cc))[(which) / 32] >> ((which) & 31))
+#define UP5(c) _rgb_scale_5[(c) & 31]
+#define UP6(c, b) _rgb_scale_6[(((c) & 31) << 1) | ((b) & 1)]
+#define LERP(n, t, c0, c1) (((n) - (t)) * (c0) + (t) * (c1) + (n) / 2) / (n)
+#define ZERO_4UBV(v) *((dword *)(v)) = 0
+
+
+static void
+fxt1_decode_1HI (const byte *code, int t, byte *rgba)
+{
+    const dword *cc;
+
+    t *= 3;
+    cc = (const dword *)(code + t / 8);
+    t = (cc[0] >> (t & 7)) & 7;
+
+    if (t == 7) {
+       ZERO_4UBV(rgba);
+    } else {
+       cc = (const dword *)(code + 12);
+       if (t == 0) {
+           rgba[BCOMP] = UP5(CC_SEL(cc, 0));
+           rgba[GCOMP] = UP5(CC_SEL(cc, 5));
+           rgba[RCOMP] = UP5(CC_SEL(cc, 10));
+       } else if (t == 6) {
+           rgba[BCOMP] = UP5(CC_SEL(cc, 15));
+           rgba[GCOMP] = UP5(CC_SEL(cc, 20));
+           rgba[RCOMP] = UP5(CC_SEL(cc, 25));
+       } else {
+           rgba[BCOMP] = LERP(6, t, UP5(CC_SEL(cc, 0)), UP5(CC_SEL(cc, 15)));
+           rgba[GCOMP] = LERP(6, t, UP5(CC_SEL(cc, 5)), UP5(CC_SEL(cc, 20)));
+           rgba[RCOMP] = LERP(6, t, UP5(CC_SEL(cc, 10)), UP5(CC_SEL(cc, 25)));
+       }
+       rgba[ACOMP] = 255;
+    }
+}
+
+
+static void
+fxt1_decode_1CHROMA (const byte *code, int t, byte *rgba)
+{
+    const dword *cc;
+    dword kk;
+
+    cc = (const dword *)code;
+    if (t & 16) {
+       cc++;
+       t &= 15;
+    }
+    t = (cc[0] >> (t * 2)) & 3;
+
+    t *= 15;
+    cc = (const dword *)(code + 8 + t / 8);
+    kk = cc[0] >> (t & 7);
+    rgba[BCOMP] = UP5(kk);
+    rgba[GCOMP] = UP5(kk >> 5);
+    rgba[RCOMP] = UP5(kk >> 10);
+    rgba[ACOMP] = 255;
+}
+
+
+static void
+fxt1_decode_1MIXED (const byte *code, int t, byte *rgba)
+{
+    const dword *cc;
+    int col[2][3];
+    int glsb, selb;
+
+    cc = (const dword *)code;
+    if (t & 16) {
+       t &= 15;
+       t = (cc[1] >> (t * 2)) & 3;
+       /* col 2 */
+       col[0][BCOMP] = (*(const dword *)(code + 11)) >> 6;
+       col[0][GCOMP] = CC_SEL(cc, 99);
+       col[0][RCOMP] = CC_SEL(cc, 104);
+       /* col 3 */
+       col[1][BCOMP] = CC_SEL(cc, 109);
+       col[1][GCOMP] = CC_SEL(cc, 114);
+       col[1][RCOMP] = CC_SEL(cc, 119);
+       glsb = CC_SEL(cc, 126);
+       selb = CC_SEL(cc, 33);
+    } else {
+       t = (cc[0] >> (t * 2)) & 3;
+       /* col 0 */
+       col[0][BCOMP] = CC_SEL(cc, 64);
+       col[0][GCOMP] = CC_SEL(cc, 69);
+       col[0][RCOMP] = CC_SEL(cc, 74);
+       /* col 1 */
+       col[1][BCOMP] = CC_SEL(cc, 79);
+       col[1][GCOMP] = CC_SEL(cc, 84);
+       col[1][RCOMP] = CC_SEL(cc, 89);
+       glsb = CC_SEL(cc, 125);
+       selb = CC_SEL(cc, 1);
+    }
+
+    if (CC_SEL(cc, 124) & 1) {
+       /* alpha[0] == 1 */
+
+       if (t == 3) {
+           ZERO_4UBV(rgba);
+       } else {
+           if (t == 0) {
+               rgba[BCOMP] = UP5(col[0][BCOMP]);
+               rgba[GCOMP] = UP5(col[0][GCOMP]);
+               rgba[RCOMP] = UP5(col[0][RCOMP]);
+           } else if (t == 2) {
+               rgba[BCOMP] = UP5(col[1][BCOMP]);
+               rgba[GCOMP] = UP6(col[1][GCOMP], glsb);
+               rgba[RCOMP] = UP5(col[1][RCOMP]);
+           } else {
+               rgba[BCOMP] = (UP5(col[0][BCOMP]) + UP5(col[1][BCOMP])) / 2;
+               rgba[GCOMP] = (UP5(col[0][GCOMP]) + UP6(col[1][GCOMP], glsb)) / 2;
+               rgba[RCOMP] = (UP5(col[0][RCOMP]) + UP5(col[1][RCOMP])) / 2;
+           }
+           rgba[ACOMP] = 255;
+       }
+    } else {
+       /* alpha[0] == 0 */
+
+       if (t == 0) {
+           rgba[BCOMP] = UP5(col[0][BCOMP]);
+           rgba[GCOMP] = UP6(col[0][GCOMP], glsb ^ selb);
+           rgba[RCOMP] = UP5(col[0][RCOMP]);
+       } else if (t == 3) {
+           rgba[BCOMP] = UP5(col[1][BCOMP]);
+           rgba[GCOMP] = UP6(col[1][GCOMP], glsb);
+           rgba[RCOMP] = UP5(col[1][RCOMP]);
+       } else {
+           rgba[BCOMP] = LERP(3, t, UP5(col[0][BCOMP]), UP5(col[1][BCOMP]));
+           rgba[GCOMP] = LERP(3, t, UP6(col[0][GCOMP], glsb ^ selb),
+                                    UP6(col[1][GCOMP], glsb));
+           rgba[RCOMP] = LERP(3, t, UP5(col[0][RCOMP]), UP5(col[1][RCOMP]));
+       }
+       rgba[ACOMP] = 255;
+    }
+}
+
+
+static void
+fxt1_decode_1ALPHA (const byte *code, int t, byte *rgba)
+{
+    const dword *cc;
+
+    cc = (const dword *)code;
+    if (CC_SEL(cc, 124) & 1) {
+       /* lerp == 1 */
+       int col0[4];
+
+       if (t & 16) {
+           t &= 15;
+           t = (cc[1] >> (t * 2)) & 3;
+           /* col 2 */
+           col0[BCOMP] = (*(const dword *)(code + 11)) >> 6;
+           col0[GCOMP] = CC_SEL(cc, 99);
+           col0[RCOMP] = CC_SEL(cc, 104);
+           col0[ACOMP] = CC_SEL(cc, 119);
+       } else {
+           t = (cc[0] >> (t * 2)) & 3;
+           /* col 0 */
+           col0[BCOMP] = CC_SEL(cc, 64);
+           col0[GCOMP] = CC_SEL(cc, 69);
+           col0[RCOMP] = CC_SEL(cc, 74);
+           col0[ACOMP] = CC_SEL(cc, 109);
+       }
+
+       if (t == 0) {
+           rgba[BCOMP] = UP5(col0[BCOMP]);
+           rgba[GCOMP] = UP5(col0[GCOMP]);
+           rgba[RCOMP] = UP5(col0[RCOMP]);
+           rgba[ACOMP] = UP5(col0[ACOMP]);
+       } else if (t == 3) {
+           rgba[BCOMP] = UP5(CC_SEL(cc, 79));
+           rgba[GCOMP] = UP5(CC_SEL(cc, 84));
+           rgba[RCOMP] = UP5(CC_SEL(cc, 89));
+           rgba[ACOMP] = UP5(CC_SEL(cc, 114));
+       } else {
+           rgba[BCOMP] = LERP(3, t, UP5(col0[BCOMP]), UP5(CC_SEL(cc, 79)));
+           rgba[GCOMP] = LERP(3, t, UP5(col0[GCOMP]), UP5(CC_SEL(cc, 84)));
+           rgba[RCOMP] = LERP(3, t, UP5(col0[RCOMP]), UP5(CC_SEL(cc, 89)));
+           rgba[ACOMP] = LERP(3, t, UP5(col0[ACOMP]), UP5(CC_SEL(cc, 114)));
+       }
+    } else {
+       /* lerp == 0 */
+
+       if (t & 16) {
+           cc++;
+           t &= 15;
+       }
+       t = (cc[0] >> (t * 2)) & 3;
+
+       if (t == 3) {
+           ZERO_4UBV(rgba);
+       } else {
+           dword kk;
+           cc = (const dword *)code;
+           rgba[ACOMP] = UP5(cc[3] >> (t * 5 + 13));
+           t *= 15;
+           cc = (const dword *)(code + 8 + t / 8);
+           kk = cc[0] >> (t & 7);
+           rgba[BCOMP] = UP5(kk);
+           rgba[GCOMP] = UP5(kk >> 5);
+           rgba[RCOMP] = UP5(kk >> 10);
+       }
+    }
+}
+
+
+TAPI void TAPIENTRY
+fxt1_decode_1 (const void *texture, int stride,
+              int i, int j, byte *rgba)
+{
+    static void (*decode_1[]) (const byte *, int, byte *) = {
+       fxt1_decode_1HI,        /* cc-high   = "00?" */
+       fxt1_decode_1HI,        /* cc-high   = "00?" */
+       fxt1_decode_1CHROMA,    /* cc-chroma = "010" */
+       fxt1_decode_1ALPHA,     /* alpha     = "011" */
+       fxt1_decode_1MIXED,     /* mixed     = "1??" */
+       fxt1_decode_1MIXED,     /* mixed     = "1??" */
+       fxt1_decode_1MIXED,     /* mixed     = "1??" */
+       fxt1_decode_1MIXED      /* mixed     = "1??" */
+    };
+
+    const byte *code = (const byte *)texture +
+                       ((j / 4) * (stride / 8) + (i / 8)) * 16;
+    int mode = CC_SEL(code, 125);
+    int t = i & 7;
+
+    if (t & 4) {
+       t += 12;
+    }
+    t += (j & 3) * 4;
+
+    decode_1[mode](code, t, rgba);
+
+#if VERBOSE
+    {
+       extern int cc_chroma;
+       extern int cc_alpha;
+       extern int cc_high;
+       extern int cc_mixed;
+       static int *cctype[] = {
+           &cc_high,
+           &cc_high,
+           &cc_chroma,
+           &cc_alpha,
+           &cc_mixed,
+           &cc_mixed,
+           &cc_mixed,
+           &cc_mixed
+       };
+       (*cctype[mode])++;
+    }
+#endif
+}
diff --git a/source/gles2glide64/src/GlideHQ/tc-1.1+/fxt1.h b/source/gles2glide64/src/GlideHQ/tc-1.1+/fxt1.h
new file mode 100644 (file)
index 0000000..c2919bb
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * FXT1 codec
+ * Version:  1.1
+ *
+ * Copyright (C) 2004  Daniel Borca   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * DANIEL BORCA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef FXT1_H_included
+#define FXT1_H_included
+
+TAPI int TAPIENTRY
+fxt1_encode (int width, int height, int comps,
+             const void *source, int srcRowStride,
+             void *dest, int destRowStride);
+
+TAPI void TAPIENTRY
+fxt1_decode_1 (const void *texture, int stride /* in pixels */,
+              int i, int j, byte *rgba);
+
+#endif
diff --git a/source/gles2glide64/src/GlideHQ/tc-1.1+/internal.h b/source/gles2glide64/src/GlideHQ/tc-1.1+/internal.h
new file mode 100644 (file)
index 0000000..f1cd6dc
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Texture compression
+ * Version:  1.0
+ *
+ * Copyright (C) 2004  Daniel Borca   All Rights Reserved.
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.       
+ */
+
+
+#ifndef INTERNAL_H_included
+#define INTERNAL_H_included
+
+/*****************************************************************************\
+ * DLL stuff
+\*****************************************************************************/
+
+#ifdef __WIN32__
+#define TAPI __declspec(dllexport)
+#define TAPIENTRY /*__stdcall*/
+#else
+#define TAPI
+#define TAPIENTRY
+#endif
+
+
+/*****************************************************************************\
+ * 64bit types on 32bit machine
+\*****************************************************************************/
+
+#if (defined(__GNUC__) && !defined(__cplusplus)) || defined(__MSC__)
+
+typedef unsigned long long qword;
+
+#define Q_MOV32(a, b) a = b
+#define Q_OR32(a, b)  a |= b
+#define Q_SHL(a, c)   a <<= c
+
+#else  /* !__GNUC__ */
+
+typedef struct {
+    dword lo, hi;
+} qword;
+
+#define Q_MOV32(a, b) a.lo = b
+#define Q_OR32(a, b)  a.lo |= b
+#define Q_SHL(a, c)                                    \
+    do {                                               \
+       if ((c) >= 32) {                                \
+           a.hi = a.lo << ((c) - 32);                  \
+           a.lo = 0;                                   \
+       } else {                                        \
+           a.hi = (a.hi << (c)) | (a.lo >> (32 - (c)));\
+           a.lo <<= c;                                 \
+       }                                               \
+    } while (0)
+
+#endif /* !__GNUC__ */
+
+
+/*****************************************************************************\
+ * Config
+\*****************************************************************************/
+
+#define RCOMP 0
+#define GCOMP 1
+#define BCOMP 2
+#define ACOMP 3
+
+/*****************************************************************************\
+ * Metric
+\*****************************************************************************/
+
+#define F(i) (float)1 /* can be used to obtain an oblong metric: 0.30 / 0.59 / 0.11 */
+#define SAFECDOT 1 /* for paranoids */
+
+#define MAKEIVEC(NV, NC, IV, B, V0, V1)        \
+    do {                               \
+       /* compute interpolation vector */\
+       float d2 = 0.0F;                \
+       float rd2;                      \
+                                       \
+       for (i = 0; i < NC; i++) {      \
+           IV[i] = (V1[i] - V0[i]) * F(i);\
+           d2 += IV[i] * IV[i];        \
+       }                               \
+       rd2 = (float)NV / d2;           \
+       B = 0;                          \
+       for (i = 0; i < NC; i++) {      \
+           IV[i] *= F(i);              \
+           B -= IV[i] * V0[i];         \
+           IV[i] *= rd2;               \
+       }                               \
+       B = B * rd2 + 0.5F;             \
+    } while (0)
+
+#define CALCCDOT(TEXEL, NV, NC, IV, B, V)\
+    do {                               \
+       float dot = 0.0F;               \
+       for (i = 0; i < NC; i++) {      \
+           dot += V[i] * IV[i];        \
+       }                               \
+       TEXEL = (int)(dot + B);         \
+       if (SAFECDOT) {                 \
+           if (TEXEL < 0) {            \
+               TEXEL = 0;              \
+           } else if (TEXEL > NV) {    \
+               TEXEL = NV;             \
+           }                           \
+       }                               \
+    } while (0)
+
+
+/*****************************************************************************\
+ * Utility functions
+\*****************************************************************************/
+
+void
+_mesa_upscale_teximage2d (unsigned int inWidth, unsigned int inHeight,
+                         unsigned int outWidth, unsigned int outHeight,
+                         unsigned int comps,
+                         const byte *src, int srcRowStride,
+                         unsigned char *dest);
+
+#endif
diff --git a/source/gles2glide64/src/GlideHQ/tc-1.1+/texstore.c b/source/gles2glide64/src/GlideHQ/tc-1.1+/texstore.c
new file mode 100644 (file)
index 0000000..2eb0306
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.3
+ *
+ * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* Copyright (C) 2007  Hiroshi Morii <koolsmoky(at)users.sourceforge.net>
+ * _mesa_upscale_teximage2d speedup
+ */
+
+#include <assert.h>
+
+#include "types.h"
+#include "internal.h"
+
+
+void
+_mesa_upscale_teximage2d (unsigned int inWidth, unsigned int inHeight,
+                         unsigned int outWidth, unsigned int outHeight,
+                         unsigned int comps,
+                         const byte *src, int srcRowStride,
+                         byte *dest)
+{
+    unsigned int i, j, k;
+
+    assert(outWidth >= inWidth);
+    assert(outHeight >= inHeight);
+
+#if 1 /* H.Morii - faster loops */
+  for (i = 0; i < inHeight; i++) {
+    for (j = 0; j < inWidth; j++) {
+      const int aa = (i * outWidth + j) * comps;
+      const int bb = i * srcRowStride + j * comps;
+      for (k = 0; k < comps; k++) {
+        dest[aa + k] = src[bb + k];
+      }
+    }
+    for (; j < outWidth; j++) {
+      const int aa = (i * outWidth + j) * comps;
+      const int bb = i * srcRowStride + (j - inWidth) * comps;
+      for (k = 0; k < comps; k++) {
+        dest[aa + k] = src[bb + k];
+      }
+    }
+  }
+  for (; i < outHeight; i++) {
+    for (j = 0; j < inWidth; j++) {
+      const int aa = (i * outWidth + j) * comps;
+      const int bb = (i - inHeight) * srcRowStride + j * comps;
+      for (k = 0; k < comps; k++) {
+        dest[aa + k] = src[bb + k];
+      }
+    }
+    for (; j < outWidth; j++) {
+      const int aa = (i * outWidth + j) * comps;
+      const int bb = (i - inHeight) * srcRowStride + (j - inWidth) * comps;
+      for (k = 0; k < comps; k++) {
+        dest[aa + k] = src[bb + k];
+      }
+    }
+  }
+#else
+    for (i = 0; i < outHeight; i++) {
+       const int ii = i % inHeight;
+       for (j = 0; j < outWidth; j++) {
+           const int jj = j % inWidth;
+            const int aa = (i * outWidth + j) * comps;
+            const int bb = ii * srcRowStride + jj * comps;
+           for (k = 0; k < comps; k++) {
+               dest[aa + k] = src[bb + k];
+           }
+       }
+    }
+#endif
+}
diff --git a/source/gles2glide64/src/GlideHQ/tc-1.1+/types.h b/source/gles2glide64/src/GlideHQ/tc-1.1+/types.h
new file mode 100644 (file)
index 0000000..ccdbb40
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Texture compression
+ * Version:  1.0
+ *
+ * Copyright (C) 2004  Daniel Borca   All Rights Reserved.
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.        
+ */
+
+#ifndef TYPES_H_included
+#define TYPES_H_included
+
+/*****************************************************************************\
+ * 32bit types
+\*****************************************************************************/
+typedef unsigned char byte;    /*  8-bit */
+typedef unsigned short word;   /* 16-bit */
+typedef unsigned int dword;    /* 32-bit */
+
+#endif
diff --git a/source/gles2glide64/src/GlideHQ/tc-1.1+/wrapper.c b/source/gles2glide64/src/GlideHQ/tc-1.1+/wrapper.c
new file mode 100644 (file)
index 0000000..0a171ee
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Texture compression
+ * Version:  1.0
+ *
+ * Copyright (C) 2004  Daniel Borca   All Rights Reserved.
+ *
+ * this is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * this 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 GNU Make; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.       
+ */
+
+
+#include <assert.h>
+
+#include "types.h"
+#include "internal.h"
+#include "dxtn.h"
+
+
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT   0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT  0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT  0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT  0x83F3
+
+
+TAPI void TAPIENTRY
+fetch_2d_texel_rgb_dxt1 (int texImage_RowStride,
+                        const byte *texImage_Data,
+                        int i, int j,
+                        byte *texel)
+{
+    dxt1_rgb_decode_1(texImage_Data, texImage_RowStride, i, j, texel);
+}
+
+
+TAPI void TAPIENTRY
+fetch_2d_texel_rgba_dxt1 (int texImage_RowStride,
+                         const byte *texImage_Data,
+                         int i, int j,
+                         byte *texel)
+{
+    dxt1_rgba_decode_1(texImage_Data, texImage_RowStride, i, j, texel);
+}
+
+
+TAPI void TAPIENTRY
+fetch_2d_texel_rgba_dxt3 (int texImage_RowStride,
+                         const byte *texImage_Data,
+                         int i, int j,
+                         byte *texel)
+{
+    dxt3_rgba_decode_1(texImage_Data, texImage_RowStride, i, j, texel);
+}
+
+
+TAPI void TAPIENTRY
+fetch_2d_texel_rgba_dxt5 (int texImage_RowStride,
+                         const byte *texImage_Data,
+                         int i, int j,
+                         byte *texel)
+{
+    dxt5_rgba_decode_1(texImage_Data, texImage_RowStride, i, j, texel);
+}
+
+
+TAPI void TAPIENTRY
+tx_compress_dxtn (int srccomps, int width, int height,
+                 const byte *source, int destformat, byte *dest,
+                 int destRowStride)
+{
+    int srcRowStride = width * srccomps;
+
+    switch (destformat) {
+       case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+           dxt1_rgb_encode(width, height, srccomps,
+                           source, srcRowStride,
+                           dest, destRowStride);
+           break;
+       case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+           dxt1_rgba_encode(width, height, srccomps,
+                            source, srcRowStride,
+                            dest, destRowStride);
+           break;
+       case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+           dxt3_rgba_encode(width, height, srccomps,
+                            source, srcRowStride,
+                            dest, destRowStride);
+           break;
+       case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+           dxt5_rgba_encode(width, height, srccomps,
+                            source, srcRowStride,
+                            dest, destRowStride);
+           break;
+       default:
+           assert(0);
+    }
+}
diff --git a/source/gles2glide64/src/Glitch64/combiner.cpp b/source/gles2glide64/src/Glitch64/combiner.cpp
new file mode 100755 (executable)
index 0000000..b82f8fa
--- /dev/null
@@ -0,0 +1,2826 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifdef _WIN32
+#include <windows.h>
+#else // _WIN32
+#include <string.h>
+#include <stdlib.h>
+#endif // _WIN32
+#include <math.h>
+#include <stdio.h>
+#include "glide.h"
+#include "main.h"
+
+#define GLchar char
+
+void vbo_draw();
+
+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;
+bool alpha_test = 0;
+
+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;
+
+float fogStart,fogEnd;
+float fogColor[4];
+
+#ifdef _WIN32
+static float farF;
+static float nearF;
+#endif // _WIN32
+
+int need_lambda[2];
+float lambda_color[2][4];
+
+// shaders variables
+int need_to_compile;
+
+static GLuint fragment_shader_object;
+static GLuint fragment_depth_shader_object;
+static GLuint vertex_shader_object;
+static GLuint program_object_default;
+static GLuint program_object_depth;
+static GLuint 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;
+
+#define GLSL_VERSION "100"
+
+#define SHADER_HEADER \
+"#version " GLSL_VERSION "          \n" \
+"#define gl_Color vFrontColor       \n" \
+"#define gl_FrontColor vFrontColor  \n" \
+"#define gl_TexCoord vTexCoord      \n"
+
+#define SHADER_VARYING \
+"varying highp vec4 gl_FrontColor;  \n" \
+"varying highp vec4 gl_TexCoord[4]; \n"
+
+static const char* fragment_shader_header =
+SHADER_HEADER
+"precision lowp float;             \n"
+"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"
+"uniform vec3 fogColor;            \n"
+"uniform float alphaRef;           \n"
+SHADER_VARYING
+"                                  \n"
+"void test_chroma(vec4 ctexture1); \n"
+"                                  \n"
+"                                  \n"
+"void main()                       \n"
+"{                                 \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 =
+" \n"
+/*"  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_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"
+;
+static const char* fragment_shader_readtex0bw_2 =
+"  vec4 readtex0 = vec4(dot(texture2D(texture0, vec2(gl_TexCoord[0])), vec4(1.0/3, 1.0/3, 1.0/3, 0)));                        \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"
+;
+static const char* fragment_shader_readtex1bw_2 =
+"  vec4 readtex1 = vec4(dot(texture2D(texture1, vec2(gl_TexCoord[1])), vec4(1.0/3, 1.0/3, 1.0/3, 0)));                        \n"
+;
+
+static const char* fragment_shader_fog =
+"  float fog;                                                                         \n"
+"  fog = gl_TexCoord[0].b;                                                            \n"
+"  gl_FragColor.rgb = mix(fogColor, gl_FragColor.rgb, fog); \n"
+;
+
+static const char* fragment_shader_end =
+"if(gl_FragColor.a <= alphaRef) {discard;}   \n"
+"                                \n"
+"}                               \n"
+;
+
+static const char* fragment_shader_alt_end =
+"                                \n"
+"}                               \n"
+;
+
+static const char* vertex_shader =
+SHADER_HEADER
+"#define Z_MAX 65536.0                                          \n"
+"attribute highp vec4 aVertex;                                  \n"
+"attribute mediump vec4 aColor;                                   \n"  //*SEB* highp -> lowp
+"attribute highp vec4 aMultiTexCoord0;                          \n"
+"attribute highp vec4 aMultiTexCoord1;                          \n"
+"attribute float aFog;                                          \n"
+"uniform vec3 vertexOffset;                                     \n" //Moved some calculations from grDrawXXX to shader
+"uniform vec4 textureSizes;                                     \n" 
+"uniform vec3 fogModeEndScale;                                  \n" //0 = Mode, 1 = gl_Fog.end, 2 = gl_Fog.scale
+SHADER_VARYING
+"                                                               \n"
+"void main()                                                    \n"
+"{                                                              \n"
+"  float q = aVertex.w;                                                     \n"
+"  float invertY = vertexOffset.z;                                          \n" //Usually 1.0 but -1.0 when rendering to a texture (see inverted_culling grRenderBuffer)
+"  gl_Position.x = (aVertex.x - vertexOffset.x) / vertexOffset.x;           \n"
+"  gl_Position.y = invertY *-(aVertex.y - vertexOffset.y) / vertexOffset.y; \n"
+"  gl_Position.z = aVertex.z / Z_MAX;                                       \n"
+"  gl_Position.w = 1.0;                                                     \n"
+"  gl_Position /= q;                                                        \n"
+"  gl_FrontColor = aColor.bgra;                                             \n"
+"                                                                           \n"
+"  gl_TexCoord[0] = vec4(aMultiTexCoord0.xy / q / textureSizes.xy,0,1);     \n"
+"  gl_TexCoord[1] = vec4(aMultiTexCoord1.xy / q / textureSizes.zw,0,1);     \n"
+"                                                                           \n"
+"  float fogV = (1.0 / mix(q,aFog,fogModeEndScale[0])) / 255.0;             \n"
+"  //if(fogMode == 2) {                                                     \n"
+"  //  fogV = 1.0 / aFog / 255                                              \n"
+"  //}                                                                      \n"
+"                                                                           \n"
+"  float f = (fogModeEndScale[1] - fogV) * fogModeEndScale[2];              \n"
+"  f = clamp(f, 0.0, 1.0);                                                  \n"
+"  gl_TexCoord[0].b = f;                                                    \n"
+"  gl_TexCoord[2].b = aVertex.x;                                            \n" 
+"  gl_TexCoord[2].a = aVertex.y;                                            \n" 
+"}                                                                          \n" 
+;
+
+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 check_compile(GLuint shader)
+{
+  GLint success;
+  glGetShaderiv(shader,GL_COMPILE_STATUS,&success);
+  if(!success)
+  {
+    char log[1024];
+    glGetShaderInfoLog(shader,1024,NULL,log);
+    LOGINFO(log);
+  }
+}
+
+void check_link(GLuint program)
+{
+  GLint success;
+  glGetProgramiv(program,GL_LINK_STATUS,&success);
+  if(!success)
+  {
+    char log[1024];
+    glGetProgramInfoLog(program,1024,NULL,log);
+    LOGINFO(log);
+  }
+}
+
+void init_combiner()
+{
+  int texture[4] = {0, 0, 0, 0};
+
+  glActiveTexture(GL_TEXTURE0);
+  glEnable(GL_TEXTURE_2D);
+
+  // creating a fake texture
+  glBindTexture(GL_TEXTURE_2D, default_texture);
+  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 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);
+
+  glActiveTexture(GL_TEXTURE1);
+  glBindTexture(GL_TEXTURE_2D, default_texture);
+  glEnable(GL_TEXTURE_2D);
+
+  int texture0_location;
+  int texture1_location;
+  char *fragment_shader;
+  int log_length;
+
+//#ifndef ANDROID
+  // depth shader
+  fragment_depth_shader_object = glCreateShader(GL_FRAGMENT_SHADER);
+
+  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);
+  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);
+  glShaderSource(fragment_depth_shader_object, 1, (const GLchar**)&fragment_shader, NULL);
+  free(fragment_shader);
+
+  glCompileShader(fragment_depth_shader_object);
+  check_compile(fragment_depth_shader_object);
+//#endif
+
+  // default shader
+  fragment_shader_object = glCreateShader(GL_FRAGMENT_SHADER);
+
+  fragment_shader = (char*)malloc(strlen(fragment_shader_header)+
+    strlen(fragment_shader_default)+
+    strlen(fragment_shader_alt_end)+1);
+  strcpy(fragment_shader, fragment_shader_header);
+  strcat(fragment_shader, fragment_shader_default);
+  strcat(fragment_shader, fragment_shader_alt_end);    /*SEB*/
+  glShaderSource(fragment_shader_object, 1, (const GLchar**)&fragment_shader, NULL);
+  free(fragment_shader);
+
+  glCompileShader(fragment_shader_object);
+  check_compile(fragment_shader_object);
+
+  vertex_shader_object = glCreateShader(GL_VERTEX_SHADER);
+  glShaderSource(vertex_shader_object, 1, &vertex_shader, NULL);
+  glCompileShader(vertex_shader_object);
+  check_compile(vertex_shader_object);
+
+  // depth program
+  program_object = glCreateProgram();
+  program_object_depth = program_object;
+  glAttachShader(program_object, fragment_depth_shader_object);
+  glAttachShader(program_object, vertex_shader_object);
+
+  glBindAttribLocation(program_object,POSITION_ATTR,"aPosition");
+  glBindAttribLocation(program_object,COLOUR_ATTR,"aColor");
+  glBindAttribLocation(program_object,TEXCOORD_0_ATTR,"aMultiTexCoord0");
+  glBindAttribLocation(program_object,TEXCOORD_1_ATTR,"aMultiTexCoord1");
+  glBindAttribLocation(program_object,FOG_ATTR,"aFog");
+
+  glLinkProgram(program_object);
+  check_link(program_object);
+  glUseProgram(program_object);
+
+  texture0_location = glGetUniformLocation(program_object, "texture0");
+  texture1_location = glGetUniformLocation(program_object, "texture1");
+  glUniform1i(texture0_location, 0);
+  glUniform1i(texture1_location, 1);
+
+  // default program
+  program_object = glCreateProgram();
+  program_object_default = program_object;
+  glAttachShader(program_object, fragment_shader_object);
+  glAttachShader(program_object, vertex_shader_object);
+
+  glBindAttribLocation(program_object,POSITION_ATTR,"aPosition");
+  glBindAttribLocation(program_object,COLOUR_ATTR,"aColor");
+  glBindAttribLocation(program_object,TEXCOORD_0_ATTR,"aMultiTexCoord0");
+  glBindAttribLocation(program_object,TEXCOORD_1_ATTR,"aMultiTexCoord1");
+  glBindAttribLocation(program_object,FOG_ATTR,"aFog");
+
+  glLinkProgram(program_object);
+  check_link(program_object);
+  glUseProgram(program_object);
+
+  texture0_location = glGetUniformLocation(program_object, "texture0");
+  texture1_location = glGetUniformLocation(program_object, "texture1");
+  glUniform1i(texture0_location, 0);
+  glUniform1i(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;
+  int alpha_test;                      //*SEB*
+  GLuint fragment_shader_object;
+  GLuint program_object;
+  int texture0_location;
+  int texture1_location;
+  int vertexOffset_location;
+  int textureSizes_location;
+  int fogModeEndScale_location;
+  int fogColor_location;
+  int alphaRef_location;
+  int ditherTex_location;
+  int chroma_color_location;
+} 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 update_uniforms(shader_program_key prog)
+{
+  glUniform1i(prog.texture0_location, 0);
+  glUniform1i(prog.texture1_location, 1);
+
+  glUniform3f(prog.vertexOffset_location,widtho,heighto,inverted_culling ? -1.0f : 1.0f);
+  glUniform4f(prog.textureSizes_location,tex0_width,tex0_height,tex1_width,tex1_height);
+
+  glUniform3f(prog.fogModeEndScale_location,
+    fog_enabled != 2 ? 0.0f : 1.0f,
+    fogEnd,
+    1.0f / (fogEnd - fogStart)
+    );
+
+  if(prog.fogColor_location != -1)
+  {
+    glUniform3f(prog.fogColor_location,fogColor[0],fogColor[1],fogColor[2]);
+  }
+
+  glUniform1f(prog.alphaRef_location,alpha_test ? alpha_ref/255.0f : -1.0f);
+
+  constant_color_location = glGetUniformLocation(program_object, "constant_color");
+  glUniform4f(constant_color_location, texture_env_color[0], texture_env_color[1],
+    texture_env_color[2], texture_env_color[3]);
+
+  ccolor0_location = glGetUniformLocation(program_object, "ccolor0");
+  glUniform4f(ccolor0_location, ccolor0[0], ccolor0[1], ccolor0[2], ccolor0[3]);
+
+  ccolor1_location = glGetUniformLocation(program_object, "ccolor1");
+  glUniform4f(ccolor1_location, ccolor1[0], ccolor1[1], ccolor1[2], ccolor1[3]);
+
+  glUniform4f(prog.chroma_color_location, chroma_color[0], chroma_color[1],
+    chroma_color[2], chroma_color[3]);
+
+  if(dither_enabled)
+  {
+    glUniform1i(prog.ditherTex_location, 2);
+  }
+
+  set_lambda();
+}
+
+void disable_textureSizes() 
+{
+  int textureSizes_location = glGetUniformLocation(program_object_default,"textureSizes");
+  glUniform4f(textureSizes_location,1,1,1,1);
+}
+
+void compile_shader()
+{
+  int texture0_location;
+  int texture1_location;
+  int ditherTex_location;
+  int vertexOffset_location;
+  int textureSizes_location;
+  char *fragment_shader;
+  int i;
+  int chroma_color_location;
+  int log_length;
+  
+  int noalpha;
+
+  need_to_compile = 0;
+
+  for(i=0; i<number_of_programs; i++)
+  {
+    shader_program_key prog = shader_programs[i];
+    if(prog.color_combiner == color_combiner_key &&
+      prog.alpha_combiner == alpha_combiner_key &&
+      prog.texture0_combiner == texture0_combiner_key &&
+      prog.texture1_combiner == texture1_combiner_key &&
+      prog.texture0_combinera == texture0_combinera_key &&
+      prog.texture1_combinera == texture1_combinera_key &&
+      prog.fog_enabled == fog_enabled &&
+         prog.alpha_test == alpha_test &&                              //*SEB*
+      prog.chroma_enabled == chroma_enabled &&
+      prog.dither_enabled == dither_enabled &&
+      prog.blackandwhite0 == blackandwhite0 &&
+      prog.blackandwhite1 == blackandwhite1)
+    {
+      program_object = shader_programs[i].program_object;
+      glUseProgram(program_object);
+      update_uniforms(prog);
+      return;
+    }
+  }
+
+  if(shader_programs != NULL) {
+       if ((number_of_programs+1)>1024)
+               shader_programs = (shader_program_key*)realloc(shader_programs, (number_of_programs+1)*sizeof(shader_program_key));
+  }
+  else
+    shader_programs = (shader_program_key*)malloc(sizeof(shader_program_key)*1024);
+       //printf("number of shaders %d\n", number_of_programs);
+
+  shader_programs[number_of_programs].color_combiner = color_combiner_key;
+  shader_programs[number_of_programs].alpha_combiner = alpha_combiner_key;
+  shader_programs[number_of_programs].texture0_combiner = texture0_combiner_key;
+  shader_programs[number_of_programs].texture1_combiner = texture1_combiner_key;
+  shader_programs[number_of_programs].texture0_combinera = texture0_combinera_key;
+  shader_programs[number_of_programs].texture1_combinera = texture1_combinera_key;
+  shader_programs[number_of_programs].fog_enabled = fog_enabled;
+  shader_programs[number_of_programs].chroma_enabled = chroma_enabled;
+  shader_programs[number_of_programs].dither_enabled = dither_enabled;
+  shader_programs[number_of_programs].blackandwhite0 = blackandwhite0;
+  shader_programs[number_of_programs].blackandwhite1 = blackandwhite1;
+  shader_programs[number_of_programs].alpha_test = alpha_test;         //*SEB*
+
+  if(chroma_enabled)
+  {
+    strcat(fragment_shader_texture1, "test_chroma(ctexture1); \n");
+    compile_chroma_shader();
+  }
+
+  fragment_shader = (char*)malloc(4096);
+
+  strcpy(fragment_shader, fragment_shader_header);
+  if(dither_enabled) strcat(fragment_shader, fragment_shader_dither);
+  switch (blackandwhite0) {
+    case 1: strcat(fragment_shader, fragment_shader_readtex0bw); break;
+    case 2: strcat(fragment_shader, fragment_shader_readtex0bw_2); break;
+    default: strcat(fragment_shader, fragment_shader_readtex0color);
+  }
+  switch (blackandwhite1) {
+    case 1: strcat(fragment_shader, fragment_shader_readtex1bw); break;
+    case 2: strcat(fragment_shader, fragment_shader_readtex1bw_2); break;
+    default: strcat(fragment_shader, fragment_shader_readtex1color);
+  }
+  strcat(fragment_shader, fragment_shader_texture0);
+  strcat(fragment_shader, fragment_shader_texture1);
+  strcat(fragment_shader, fragment_shader_color_combiner);
+  strcat(fragment_shader, fragment_shader_alpha_combiner);
+  if(fog_enabled) strcat(fragment_shader, fragment_shader_fog);
+  if (alpha_test)
+               strcat(fragment_shader, fragment_shader_end);
+  else
+               strcat(fragment_shader, fragment_shader_alt_end);               //*SEB*
+  if(chroma_enabled) strcat(fragment_shader, fragment_shader_chroma);
+
+  shader_programs[number_of_programs].fragment_shader_object = glCreateShader(GL_FRAGMENT_SHADER);
+  glShaderSource(shader_programs[number_of_programs].fragment_shader_object, 1, (const GLchar**)&fragment_shader, NULL);
+
+  glCompileShader(shader_programs[number_of_programs].fragment_shader_object);
+  check_compile(shader_programs[number_of_programs].fragment_shader_object);
+
+  program_object = glCreateProgram();
+  shader_programs[number_of_programs].program_object = program_object;
+
+  glBindAttribLocation(program_object,POSITION_ATTR,"aPosition");
+  glBindAttribLocation(program_object,COLOUR_ATTR,"aColor");
+  glBindAttribLocation(program_object,TEXCOORD_0_ATTR,"aMultiTexCoord0");
+  glBindAttribLocation(program_object,TEXCOORD_1_ATTR,"aMultiTexCoord1");
+  glBindAttribLocation(program_object,FOG_ATTR,"aFog");
+
+  glAttachShader(program_object, shader_programs[number_of_programs].fragment_shader_object);
+  glAttachShader(program_object, vertex_shader_object);
+
+  glLinkProgram(program_object);
+  check_link(program_object);
+  glUseProgram(program_object);
+
+
+  shader_programs[number_of_programs].texture0_location = glGetUniformLocation(program_object, "texture0");
+  shader_programs[number_of_programs].texture1_location = glGetUniformLocation(program_object, "texture1");
+  shader_programs[number_of_programs].vertexOffset_location = glGetUniformLocation(program_object, "vertexOffset");
+  shader_programs[number_of_programs].textureSizes_location = glGetUniformLocation(program_object, "textureSizes");
+  shader_programs[number_of_programs].fogModeEndScale_location = glGetUniformLocation(program_object, "fogModeEndScale");
+  shader_programs[number_of_programs].fogColor_location = glGetUniformLocation(program_object, "fogColor");
+  shader_programs[number_of_programs].alphaRef_location = glGetUniformLocation(program_object, "alphaRef");
+
+  update_uniforms(shader_programs[number_of_programs]);
+
+  number_of_programs++;
+}
+
+void free_combiners()
+{
+  free(shader_programs);
+  shader_programs = NULL;
+  number_of_programs = 0;
+}
+
+void set_copy_shader()
+{
+  int texture0_location;
+  int alphaRef_location;
+
+  glUseProgram(program_object_default);
+  texture0_location = glGetUniformLocation(program_object_default, "texture0");
+  glUniform1i(texture0_location, 0);
+
+  alphaRef_location = glGetUniformLocation(program_object_default, "alphaRef");
+  if(alphaRef_location != -1)
+      glUniform1f(alphaRef_location,alpha_test ? alpha_ref/255.0f : -1.0f);
+}
+
+void set_depth_shader()
+{
+  int texture0_location;
+  int alphaRef_location;
+
+  glUseProgram(program_object_depth);
+  texture0_location = glGetUniformLocation(program_object_depth, "texture0");
+  glUniform1i(texture0_location, 0);
+
+  alphaRef_location = glGetUniformLocation(program_object_depth, "alphaRef");
+  if(alphaRef_location != -1)
+      glUniform1f(alphaRef_location,alpha_test ? alpha_ref/255.0f : -1.0f);
+}
+
+void set_lambda()
+{
+  int lambda_location = glGetUniformLocation(program_object, "lambda");
+  glUniform1f(lambda_location, lambda);
+}
+
+FX_ENTRY void FX_CALL 
+grConstantColorValue( GrColor_t value )
+{
+  LOG("grConstantColorValue(%d)\r\n", value);
+  switch(lfb_color_fmt)
+  {
+  case GR_COLORFORMAT_ARGB:
+    texture_env_color[3] = ((value >> 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);
+  }
+
+  vbo_draw();
+
+  constant_color_location = glGetUniformLocation(program_object, "constant_color");
+  glUniform4f(constant_color_location, texture_env_color[0], texture_env_color[1], 
+    texture_env_color[2], texture_env_color[3]);
+}
+
+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 )
+{
+  LOG("grColorCombine(%d,%d,%d,%d,%d)\r\n", function, factor, local, other, invert);
+  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;
+}
+
+/*
+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
+               )
+{
+  LOG("grAlphaCombine(%d,%d,%d,%d,%d)\r\n", function, factor, local, other, invert);
+  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;
+}
+
+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
+             )
+{
+  LOG("grTexCombine(%d,%d,%d,%d,%d,%d,%d)\r\n", tmu, rgb_function, rgb_factor, alpha_function, alpha_factor, rgb_invert, alpha_invert);
+  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");
+  }
+  need_to_compile = 1;
+}
+
+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;
+  LOG("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);
+  glBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
+/*
+  if (blend_func_separate_support)
+    glBlendFuncSeparateEXT(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
+  else
+    glBlendFunc(sfactorRGB, dfactorRGB);
+*/
+}
+
+FX_ENTRY void FX_CALL
+grAlphaTestReferenceValue( GrAlpha_t value )
+{
+  LOG("grAlphaTestReferenceValue(%d)\r\n", value);
+  alpha_ref = value;
+  grAlphaTestFunction(alpha_func);
+}
+
+FX_ENTRY void FX_CALL
+grAlphaTestFunction( GrCmpFnc_t function )
+{
+  LOG("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);
+    alpha_test = false;
+    return;
+    break;
+  default:
+    display_warning("grAlphaTestFunction : unknown function : %x", function);
+  }
+  //glEnable(GL_ALPHA_TEST);
+  alpha_test = true;
+}
+
+// fog
+
+FX_ENTRY void FX_CALL 
+grFogMode( GrFogMode_t mode )
+{
+  LOG("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);
+  }
+  need_to_compile = 1;
+}
+
+FX_ENTRY float FX_CALL
+guFogTableIndexToW( int i )
+{
+  LOG("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 )
+{
+  LOG("guFogGenerateLinear(%f,%f)\r\n", nearZ, farZ);
+/*
+  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);
+*/
+  fogStart = nearZ / 255.0f;
+  fogEnd = farZ / 255.0f;
+}
+
+FX_ENTRY void FX_CALL 
+grFogTable( const GrFog_t ft[] )
+{
+  LOG("grFogTable()\r\n");
+}
+
+FX_ENTRY void FX_CALL 
+grFogColorValue( GrColor_t fogcolor )
+{
+  LOG("grFogColorValue(%x)\r\n", fogcolor);
+
+  switch(lfb_color_fmt)
+  {
+  case GR_COLORFORMAT_ARGB:
+    fogColor[3] = ((fogcolor >> 24) & 0xFF) / 255.0f;
+    fogColor[0] = ((fogcolor >> 16) & 0xFF) / 255.0f;
+    fogColor[1] = ((fogcolor >>  8) & 0xFF) / 255.0f;
+    fogColor[2] = (fogcolor & 0xFF) / 255.0f;
+    break;
+  case GR_COLORFORMAT_RGBA:
+    fogColor[0] = ((fogcolor >> 24) & 0xFF) / 255.0f;
+    fogColor[1] = ((fogcolor >> 16) & 0xFF) / 255.0f;
+    fogColor[2] = ((fogcolor >>  8) & 0xFF) / 255.0f;
+    fogColor[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 )
+{
+  LOG("grChromakeyMode(%d)\r\n", mode);
+  switch(mode)
+  {
+  case GR_CHROMAKEY_DISABLE:
+    chroma_enabled = 0;
+    break;
+  case GR_CHROMAKEY_ENABLE:
+    chroma_enabled = 1;
+    break;
+  default:
+    display_warning("grChromakeyMode : unknown mode : %x", mode);
+  }
+  need_to_compile = 1;
+}
+
+FX_ENTRY void FX_CALL 
+grChromakeyValue( GrColor_t value )
+{
+  LOG("grChromakeyValue(%x)\r\n", value);
+  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);
+  }
+  vbo_draw();
+  chroma_color_location = glGetUniformLocation(program_object, "chroma_color");
+  glUniform4f(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;
+  }
+  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;
+    }
+  }
+  glActiveTexture(GL_TEXTURE2);
+  glEnable(GL_TEXTURE_2D);
+  glBindTexture(GL_TEXTURE_2D, 33*1024*1024);
+  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 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)
+{
+  LOG("grStipplePattern(%x)\r\n", stipple);
+  srand(stipple);
+  setPattern();
+}
+
+FX_ENTRY void FX_CALL
+grStippleMode( GrStippleMode_t mode )
+{
+  LOG("grStippleMode(%d)\r\n", mode);
+  switch(mode)
+  {
+  case GR_STIPPLE_DISABLE:
+    dither_enabled = 0;
+    glActiveTexture(GL_TEXTURE2);
+    glDisable(GL_TEXTURE_2D);
+    break;
+  case GR_STIPPLE_PATTERN:
+    setPattern();
+    dither_enabled = 1;
+    glActiveTexture(GL_TEXTURE2);
+    glEnable(GL_TEXTURE_2D);
+    break;
+  case GR_STIPPLE_ROTATE:
+    setPattern();
+    dither_enabled = 1;
+    glActiveTexture(GL_TEXTURE2);
+    glEnable(GL_TEXTURE_2D);
+    break;
+  default:
+    display_warning("grStippleMode:%x", mode);
+  }
+  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)
+{
+  LOG("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)
+{
+  LOG("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;
+  LOG("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;
+  LOG("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;
+  LOG("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);
+  }
+
+  vbo_draw();
+  if(num_tex == 0)
+  {
+    ccolor0_location = glGetUniformLocation(program_object, "ccolor0");
+    glUniform4f(ccolor0_location, ccolor0[0], ccolor0[1], ccolor0[2], ccolor0[3]);
+  }
+  else
+  {
+    ccolor1_location = glGetUniformLocation(program_object, "ccolor1");
+    glUniform4f(ccolor1_location, ccolor1[0], ccolor1[1], ccolor1[2], ccolor1[3]);
+  }
+}
diff --git a/source/gles2glide64/src/Glitch64/geometry.cpp b/source/gles2glide64/src/Glitch64/geometry.cpp
new file mode 100755 (executable)
index 0000000..92e79eb
--- /dev/null
@@ -0,0 +1,658 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <stdio.h>
+#include <string.h>
+#ifdef _WIN32
+#include <windows.h>
+#endif // _WIN32
+#include "glide.h"
+#include "main.h"
+#include "../Glide64/winlnxdefs.h"
+#include "../Glide64/rdp.h"
+
+
+
+#define Z_MAX (65536.0f)
+#define VERTEX_SIZE sizeof(VERTEX) //Size of vertex struct
+
+#ifdef PAULSCODE
+//#include "ae_bridge.h"
+static float polygonOffsetFactor;
+static float polygonOffsetUnits;
+#endif
+
+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;
+
+#define VERTEX_BUFFER_SIZE 1500 //Max amount of vertices to buffer, this seems large enough.
+static VERTEX vertex_buffer[VERTEX_BUFFER_SIZE];
+static int vertex_buffer_count = 0;
+static GLenum vertex_draw_mode;
+static bool vertex_buffer_enabled = false;
+
+void vbo_init()
+{
+  
+}
+
+void vbo_draw()
+{
+  if(vertex_buffer_count)
+  {
+    glDrawArrays(vertex_draw_mode,0,vertex_buffer_count);
+    vertex_buffer_count = 0;
+  }
+}
+
+#ifdef PAULSCODE
+void vbo_resetcount()
+{
+       vertex_buffer_count = 0;
+}
+#endif
+
+//Buffer vertices instead of glDrawArrays(...)
+void vbo_buffer(GLenum mode,GLint first,GLsizei count,void* pointers)
+{
+  if((count != 3 && mode != GL_TRIANGLES) || vertex_buffer_count + count > VERTEX_BUFFER_SIZE)
+  {
+    vbo_draw();
+  }
+
+  memcpy(&vertex_buffer[vertex_buffer_count],pointers,count * VERTEX_SIZE);
+  vertex_buffer_count += count;
+
+  if(count == 3 || mode == GL_TRIANGLES)
+  {
+    vertex_draw_mode = GL_TRIANGLES;
+  }
+  else
+  {
+    vertex_draw_mode = mode;
+    vbo_draw(); //Triangle fans and strips can't be joined as easily, just draw them straight away.
+  }
+
+
+}
+
+void vbo_enable()
+{
+  if(vertex_buffer_enabled)
+    return;
+
+  vertex_buffer_enabled = true;
+  glEnableVertexAttribArray(POSITION_ATTR);
+  glVertexAttribPointer(POSITION_ATTR, 4, GL_FLOAT, false, VERTEX_SIZE, &vertex_buffer[0].x); //Position
+
+  glEnableVertexAttribArray(COLOUR_ATTR);
+  glVertexAttribPointer(COLOUR_ATTR, 4, GL_UNSIGNED_BYTE, true, VERTEX_SIZE, &vertex_buffer[0].b); //Colour
+
+  glEnableVertexAttribArray(TEXCOORD_0_ATTR);
+  glVertexAttribPointer(TEXCOORD_0_ATTR, 2, GL_FLOAT, false, VERTEX_SIZE, &vertex_buffer[0].coord[2]); //Tex0
+
+  glEnableVertexAttribArray(TEXCOORD_1_ATTR);
+  glVertexAttribPointer(TEXCOORD_1_ATTR, 2, GL_FLOAT, false, VERTEX_SIZE, &vertex_buffer[0].coord[0]); //Tex1
+
+  glEnableVertexAttribArray(FOG_ATTR);
+  glVertexAttribPointer(FOG_ATTR, 1, GL_FLOAT, false, VERTEX_SIZE, &vertex_buffer[0].f); //Fog
+}
+
+void vbo_disable()
+{
+  vbo_draw();
+  vertex_buffer_enabled = false;
+}
+
+
+inline float ZCALC(const float & z, const float & q) {
+  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<zclamp) c = zclamp;
+  glVertex4f(a,b,c,d);
+}
+#define glVertex4f(a,b,c,d) zclamp_glVertex4f(a,b,c,d)
+*/
+
+
+static inline float ytex(int tmu, float y) {
+  if (invtex[tmu])
+    return invtex[tmu] - y;
+  else
+    return y;
+}
+
+void init_geometry()
+{
+  xy_en = q_en = pargb_en = st0_en = st1_en = z_en = 0;
+  w_buffer_mode = 0;
+  inverted_culling = 0;
+
+  glDisable(GL_CULL_FACE);
+  glDisable(GL_DEPTH_TEST);
+
+  vbo_init();
+}
+
+FX_ENTRY void FX_CALL
+grCoordinateSpace( GrCoordinateSpaceMode_t mode )
+{
+  LOG("grCoordinateSpace(%d)\r\n", mode);
+  switch(mode)
+  {
+  case GR_WINDOW_COORDS:
+    break;
+  default:
+    display_warning("unknwown coordinate space : %x", mode);
+  }
+}
+
+FX_ENTRY void FX_CALL
+grVertexLayout(FxU32 param, FxI32 offset, FxU32 mode)
+{
+  LOG("grVertexLayout(%d,%d,%d)\r\n", param, offset, mode);
+  switch(param)
+  {
+  case GR_PARAM_XY:
+    xy_en = mode;
+    xy_off = offset;
+    break;
+  case GR_PARAM_Z:
+    z_en = mode;
+    z_off = offset;
+    break;
+  case GR_PARAM_Q:
+    q_en = mode;
+    q_off = offset;
+    break;
+  case GR_PARAM_FOG_EXT:
+    fog_ext_en = mode;
+    fog_ext_off = offset;
+    break;
+  case GR_PARAM_PARGB:
+    pargb_en = mode;
+    pargb_off = offset;
+    break;
+  case GR_PARAM_ST0:
+    st0_en = mode;
+    st0_off = offset;
+    break;
+  case GR_PARAM_ST1:
+    st1_en = mode;
+    st1_off = offset;
+    break;
+  default:
+    display_warning("unknown grVertexLayout parameter : %x", param);
+  }
+}
+
+FX_ENTRY void FX_CALL
+grCullMode( GrCullMode_t mode )
+{
+  LOG("grCullMode(%d)\r\n", mode);
+  static int oldmode = -1, oldinv = -1;
+  culling_mode = mode;
+  if (inverted_culling == oldinv && oldmode == mode)
+    return;
+  oldmode = mode;
+  oldinv = inverted_culling;
+  switch(mode)
+  {
+  case GR_CULL_DISABLE:
+    glDisable(GL_CULL_FACE);
+    break;
+  case GR_CULL_NEGATIVE:
+    if (!inverted_culling)
+      glCullFace(GL_FRONT);
+    else
+      glCullFace(GL_BACK);
+    glEnable(GL_CULL_FACE);
+    break;
+  case GR_CULL_POSITIVE:
+    if (!inverted_culling)
+      glCullFace(GL_BACK);
+    else
+      glCullFace(GL_FRONT);
+    glEnable(GL_CULL_FACE);
+    break;
+  default:
+    display_warning("unknown cull mode : %x", mode);
+  }
+}
+
+// Depth buffer
+
+FX_ENTRY void FX_CALL
+grDepthBufferMode( GrDepthBufferMode_t mode )
+{
+  LOG("grDepthBufferMode(%d)\r\n", mode);
+  switch(mode)
+  {
+  case GR_DEPTHBUFFER_DISABLE:
+    glDisable(GL_DEPTH_TEST);
+    w_buffer_mode = 0;
+    return;
+  case GR_DEPTHBUFFER_WBUFFER:
+  case GR_DEPTHBUFFER_WBUFFER_COMPARE_TO_BIAS:
+    glEnable(GL_DEPTH_TEST);
+    w_buffer_mode = 1;
+    break;
+  case GR_DEPTHBUFFER_ZBUFFER:
+  case GR_DEPTHBUFFER_ZBUFFER_COMPARE_TO_BIAS:
+    glEnable(GL_DEPTH_TEST);
+    w_buffer_mode = 0;
+    break;
+  default:
+    display_warning("unknown depth buffer mode : %x", mode);
+  }
+}
+
+FX_ENTRY void FX_CALL
+grDepthBufferFunction( GrCmpFnc_t function )
+{
+  LOG("grDepthBufferFunction(%d)\r\n", function);
+  switch(function)
+  {
+  case GR_CMP_GEQUAL:
+    if (w_buffer_mode)
+      glDepthFunc(GL_LEQUAL);
+    else
+      glDepthFunc(GL_GEQUAL);
+    break;
+  case GR_CMP_LEQUAL:
+    if (w_buffer_mode)
+      glDepthFunc(GL_GEQUAL);
+    else
+      glDepthFunc(GL_LEQUAL);
+    break;
+  case GR_CMP_LESS:
+    if (w_buffer_mode)
+      glDepthFunc(GL_GREATER);
+    else
+      glDepthFunc(GL_LESS);
+    break;
+  case GR_CMP_ALWAYS:
+    glDepthFunc(GL_ALWAYS);
+    break;
+  case GR_CMP_EQUAL:
+    glDepthFunc(GL_EQUAL);
+    break;
+  case GR_CMP_GREATER:
+    if (w_buffer_mode)
+      glDepthFunc(GL_LESS);
+    else
+      glDepthFunc(GL_GREATER);
+    break;
+  case GR_CMP_NEVER:
+    glDepthFunc(GL_NEVER);
+    break;
+  case GR_CMP_NOTEQUAL:
+    glDepthFunc(GL_NOTEQUAL);
+    break;
+
+  default:
+    display_warning("unknown depth buffer function : %x", function);
+  }
+}
+
+FX_ENTRY void FX_CALL
+grDepthMask( FxBool mask )
+{
+  LOG("grDepthMask(%d)\r\n", mask);
+  glDepthMask(mask);
+}
+
+float biasFactor = 0;
+void FindBestDepthBias()
+{
+#ifdef PAULSCODE
+/*  int hardwareType = Android_JNI_GetHardwareType();
+  Android_JNI_GetPolygonOffset(hardwareType, 1, &polygonOffsetFactor, &polygonOffsetUnits);*/
+//  glPolygonOffset(0.2f, 0.2f);
+       polygonOffsetFactor=0.2f;
+       polygonOffsetUnits=0.2f;
+#else
+  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 > 0.01f) continue;
+    if (z < bestz) {
+      bestz = z;
+      biasFactor = f;
+    }
+    //printf("f %g z %g\n", f, z);
+  }
+  //printf(" --> bias factor %g\n", biasFactor);
+  glPopAttrib();
+#endif
+}
+
+FX_ENTRY void FX_CALL
+grDepthBiasLevel( FxI32 level )
+{
+  LOG("grDepthBiasLevel(%d)\r\n", level);
+  if (level)
+  {
+    #ifdef PAULSCODE
+    glPolygonOffset(polygonOffsetFactor, polygonOffsetUnits);
+/*    if(w_buffer_mode)
+      glPolygonOffset(1.0f, -(float)level*polygonOffsetUnits);
+    else
+      glPolygonOffset(0, (float)level*3.0f);*/
+    #else
+    if(w_buffer_mode)
+      glPolygonOffset(1.0f, -(float)level*zscale/255.0f);
+    else
+      glPolygonOffset(0, (float)level*biasFactor);
+    #endif
+    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 )
+{
+  LOG("grDrawTriangle()\r\n\t");
+/*  
+  if(nvidia_viewport_hack && !render_to_texture)
+  {
+    glViewport(0, viewport_offset, viewport_width, viewport_height);
+    nvidia_viewport_hack = 0;
+  }
+*/
+  reloadTexture();
+
+  if(need_to_compile) compile_shader();
+
+  if(vertex_buffer_count + 3 > VERTEX_BUFFER_SIZE)
+  {
+    vbo_draw();
+  }
+  vertex_draw_mode = GL_TRIANGLES;
+  memcpy(&vertex_buffer[vertex_buffer_count],a,VERTEX_SIZE);
+  memcpy(&vertex_buffer[vertex_buffer_count+1],b,VERTEX_SIZE);
+  memcpy(&vertex_buffer[vertex_buffer_count+2],c,VERTEX_SIZE);
+  vertex_buffer_count += 3;
+}
+
+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);
+  LOG("grDrawPoint()\r\n");
+
+  if(nvidia_viewport_hack && !render_to_texture)
+  {
+    glViewport(0, viewport_offset, viewport_width, viewport_height);
+    nvidia_viewport_hack = 0;
+  }
+
+  reloadTexture();
+
+  if(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(!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);
+  }
+  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);
+  LOG("grDrawLine()\r\n");
+
+  if(nvidia_viewport_hack && !render_to_texture)
+  {
+    glViewport(0, viewport_offset, viewport_width, viewport_height);
+    nvidia_viewport_hack = 0;
+  }
+
+  reloadTexture();
+
+  if(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(!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);
+  }
+  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(!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);
+  }
+  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)
+{
+  void **pointers = (void**)pointers2;
+  LOG("grDrawVertexArray(%d,%d)\r\n", mode, Count);
+/*
+  if(nvidia_viewport_hack && !render_to_texture)
+  {
+    glViewport(0, viewport_offset, viewport_width, viewport_height);
+    nvidia_viewport_hack = 0;
+  }
+*/
+  reloadTexture();
+
+  if(need_to_compile) compile_shader();
+
+  if(mode != GR_TRIANGLE_FAN)
+  {
+    display_warning("grDrawVertexArray : unknown mode : %x", mode);
+  }
+
+  vbo_enable();
+  vbo_buffer(GL_TRIANGLE_FAN,0,Count,pointers[0]);
+}
+
+FX_ENTRY void FX_CALL
+grDrawVertexArrayContiguous(FxU32 mode, FxU32 Count, void *pointers, FxU32 stride)
+{
+  LOG("grDrawVertexArrayContiguous(%d,%d,%d)\r\n", mode, Count, stride);
+/*
+  if(nvidia_viewport_hack && !render_to_texture)
+  {
+    glViewport(0, viewport_offset, viewport_width, viewport_height);
+    nvidia_viewport_hack = 0;
+  }
+*/
+  if(stride != 156)
+  {
+         LOGINFO("Incompatible stride\n");
+  }
+
+  reloadTexture();
+
+  if(need_to_compile) compile_shader();
+
+  vbo_enable();
+
+  switch(mode)
+  {
+  case GR_TRIANGLE_STRIP:
+    vbo_buffer(GL_TRIANGLE_STRIP,0,Count,pointers);
+    break;
+  case GR_TRIANGLE_FAN:
+    vbo_buffer(GL_TRIANGLE_FAN,0,Count,pointers);
+    break;
+  default:
+    display_warning("grDrawVertexArrayContiguous : unknown mode : %x", mode);
+  }
+}
diff --git a/source/gles2glide64/src/Glitch64/glState.cpp b/source/gles2glide64/src/Glitch64/glState.cpp
new file mode 100644 (file)
index 0000000..d0bceb3
--- /dev/null
@@ -0,0 +1,360 @@
+void vbo_draw();
+
+static GLenum cached_ActiveTexture_texture;
+void inline cache_glActiveTexture (GLenum texture)
+{
+  if(texture != cached_ActiveTexture_texture)
+  {
+    vbo_draw();
+    glActiveTexture(texture);
+    cached_ActiveTexture_texture = texture;
+  }
+}
+#define glActiveTexture(texture) cache_glActiveTexture(texture)
+
+void inline cache_glBindTexture (GLenum target, GLuint texture)
+{
+    vbo_draw();
+    glBindTexture(target, texture);
+}
+#define glBindTexture(target, texture) cache_glBindTexture(target, texture)
+
+static GLenum cached_BlendEquation_mode;
+void inline cache_glBlendEquation ( GLenum mode )
+{
+  if(mode != cached_BlendEquation_mode)
+  {
+    vbo_draw();
+    glBlendEquation(mode);
+    cached_BlendEquation_mode = mode;
+  }
+}
+#define glBlendEquation(mode) cache_glBlendEquation(mode)
+
+static GLenum cached_BlendEquationSeparate_modeRGB;
+static GLenum cached_BlendEquationSeparate_modeAlpha;
+void inline cache_glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha)
+{
+  if(modeRGB != cached_BlendEquationSeparate_modeRGB || modeAlpha != cached_BlendEquationSeparate_modeAlpha)
+  {
+    vbo_draw();
+    glBlendEquationSeparate(modeRGB, modeAlpha);
+    cached_BlendEquationSeparate_modeRGB = modeRGB;
+    cached_BlendEquationSeparate_modeAlpha = modeAlpha;
+  }
+}
+#define glBlendEquationSeparate(modeRGB, modeAlpha) cache_glBlendEquationSeparate(modeRGB, modeAlpha)
+
+static GLenum cached_BlendFunc_sfactor;
+static GLenum cached_BlendFunc_dfactor;
+void inline cache_glBlendFunc (GLenum sfactor, GLenum dfactor)
+{
+  if(sfactor != cached_BlendFunc_sfactor || dfactor != cached_BlendFunc_dfactor)
+  {
+    vbo_draw();
+    glBlendFunc(sfactor, dfactor);
+    cached_BlendFunc_sfactor = sfactor;
+    cached_BlendFunc_dfactor = dfactor;
+  }
+}
+#define glBlendFunc(sfactor, dfactor) cache_glBlendFunc(sfactor, dfactor)
+
+static GLenum cached_BlendFuncSeparate_srcRGB;
+static GLenum cached_BlendFuncSeparate_dstRGB;
+static GLenum cached_BlendFuncSeparate_srcAlpha;
+static GLenum cached_BlendFuncSeparate_dstAlpha;
+void inline cache_glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+{
+  if(srcRGB != cached_BlendFuncSeparate_srcRGB || dstRGB != cached_BlendFuncSeparate_dstRGB || srcAlpha != cached_BlendFuncSeparate_srcAlpha || dstAlpha != cached_BlendFuncSeparate_dstAlpha)
+  {
+    vbo_draw();
+    glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
+    cached_BlendFuncSeparate_srcRGB = srcRGB;
+    cached_BlendFuncSeparate_dstRGB = dstRGB;
+    cached_BlendFuncSeparate_srcAlpha = srcAlpha;
+    cached_BlendFuncSeparate_dstAlpha = dstAlpha;
+  }
+}
+#define glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha) cache_glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha)
+
+static GLclampf cached_ClearColor_red;
+static GLclampf cached_ClearColor_green;
+static GLclampf cached_ClearColor_blue;
+static GLclampf cached_ClearColor_alpha;
+void inline cache_glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+  if(red != cached_ClearColor_red || green != cached_ClearColor_green || blue != cached_ClearColor_blue || alpha != cached_ClearColor_alpha)
+  {
+    vbo_draw();
+    glClearColor(red, green, blue, alpha);
+    cached_ClearColor_red = red;
+    cached_ClearColor_green = green;
+    cached_ClearColor_blue = blue;
+    cached_ClearColor_alpha = alpha;
+  }
+}
+#define glClearColor(red, green, blue, alpha) cache_glClearColor(red, green, blue, alpha)
+
+static GLclampf cached_ClearDepthf_depth;
+void inline cache_glClearDepthf (GLclampf depth)
+{
+  if(depth != cached_ClearDepthf_depth)
+  {
+    vbo_draw();
+    glClearDepthf(depth);
+    cached_ClearDepthf_depth = depth;
+  }
+}
+#define glClearDepthf(depth) cache_glClearDepthf(depth)
+
+static GLenum cached_CullFace_mode;
+void inline cache_glCullFace (GLenum mode)
+{
+  if(mode != cached_CullFace_mode)
+  {
+    vbo_draw();
+    glCullFace(mode);
+    cached_CullFace_mode = mode;
+  }
+}
+#define glCullFace(mode) cache_glCullFace(mode)
+
+static GLenum cached_DepthFunc_func;
+void inline cache_glDepthFunc (GLenum func)
+{
+  if(func != cached_DepthFunc_func)
+  {
+    vbo_draw();
+    glDepthFunc(func);
+    cached_DepthFunc_func = func;
+  }
+}
+#define glDepthFunc(func) cache_glDepthFunc(func)
+
+static GLboolean cached_DepthMask_flag;
+void inline cache_glDepthMask (GLboolean flag)
+{
+  if(flag != cached_DepthMask_flag)
+  {
+    vbo_draw();
+    glDepthMask(flag);
+    cached_DepthMask_flag = flag;
+  }
+}
+#define glDepthMask(flag) cache_glDepthMask(flag)
+
+static GLclampf cached_DepthRangef_zNear;
+static GLclampf cached_DepthRangef_zFar;
+void inline cache_glDepthRangef (GLclampf zNear, GLclampf zFar)
+{
+  if(zNear != cached_DepthRangef_zNear || zFar != cached_DepthRangef_zFar)
+  {
+    vbo_draw();
+    glDepthRangef(zNear, zFar);
+    cached_DepthRangef_zNear = zNear;
+    cached_DepthRangef_zFar = zFar;
+  }
+}
+#define glDepthRangef(zNear, zFar) cache_glDepthRangef(zNear, zFar)
+
+static bool cached_BLEND = false;
+static bool cached_CULL_FACE = false;
+static bool cached_DEPTH_TEST = false;
+static bool cached_DITHER = false;
+static bool cached_POLYGON_OFFSET_FILL = false;
+static bool cached_SAMPLE_ALPHA_TO_COVERAGE = false;
+static bool cached_SAMPLE_COVERAGE = false;
+static bool cached_SCISSOR_TEST = false;
+static bool cached_STENCIL_TEST = false;
+void inline cache_glDisable (GLenum cap)
+{
+  if(cap == GL_BLEND && cached_BLEND)
+  {
+    vbo_draw();
+    glDisable(GL_BLEND);
+    cached_BLEND = false;
+  }
+  else if(cap == GL_CULL_FACE && cached_CULL_FACE)
+  {
+    vbo_draw();
+    glDisable(GL_CULL_FACE);
+    cached_CULL_FACE = false;
+  }
+  else if(cap == GL_DEPTH_TEST && cached_DEPTH_TEST)
+  {
+    vbo_draw();
+    glDisable(GL_DEPTH_TEST);
+    cached_DEPTH_TEST = false;
+  }
+  else if(cap == GL_DITHER && cached_DITHER)
+  {
+    vbo_draw();
+    glDisable(GL_DITHER);
+    cached_DITHER = false;
+  }
+  else if(cap == GL_POLYGON_OFFSET_FILL && cached_POLYGON_OFFSET_FILL)
+  {
+    vbo_draw();
+    glDisable(GL_POLYGON_OFFSET_FILL);
+    cached_POLYGON_OFFSET_FILL = false;
+  }
+  else if(cap == GL_SAMPLE_ALPHA_TO_COVERAGE && cached_SAMPLE_ALPHA_TO_COVERAGE)
+  {
+    vbo_draw();
+    glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
+    cached_SAMPLE_ALPHA_TO_COVERAGE = false;
+  }
+  else if(cap == GL_SAMPLE_COVERAGE && cached_SAMPLE_COVERAGE)
+  {
+    vbo_draw();
+    glDisable(GL_SAMPLE_COVERAGE);
+    cached_SAMPLE_COVERAGE = false;
+  }
+  else if(cap == GL_SCISSOR_TEST && cached_SCISSOR_TEST)
+  {
+    vbo_draw();
+    glDisable(GL_SCISSOR_TEST);
+    cached_SCISSOR_TEST = false;
+  }
+  else if(cap == GL_STENCIL_TEST && cached_STENCIL_TEST)
+  {
+    vbo_draw();
+    glDisable(GL_STENCIL_TEST);
+    cached_STENCIL_TEST = false;
+  }
+}
+#define glDisable(cap) cache_glDisable(cap)
+
+void inline cache_glEnable (GLenum cap)
+{
+  if(cap == GL_BLEND && !cached_BLEND)
+  {
+    vbo_draw();
+    glEnable(GL_BLEND);
+    cached_BLEND = true;
+  }
+  else if(cap == GL_CULL_FACE && !cached_CULL_FACE)
+  {
+    vbo_draw();
+    glEnable(GL_CULL_FACE);
+    cached_CULL_FACE = true;
+  }
+  else if(cap == GL_DEPTH_TEST && !cached_DEPTH_TEST)
+  {
+    vbo_draw();
+    glEnable(GL_DEPTH_TEST);
+    cached_DEPTH_TEST = true;
+  }
+  else if(cap == GL_DITHER && !cached_DITHER)
+  {
+    vbo_draw();
+    glEnable(GL_DITHER);
+    cached_DITHER = true;
+  }
+  else if(cap == GL_POLYGON_OFFSET_FILL && !cached_POLYGON_OFFSET_FILL)
+  {
+    vbo_draw();
+    glEnable(GL_POLYGON_OFFSET_FILL);
+    cached_POLYGON_OFFSET_FILL = true;
+  }
+  else if(cap == GL_SAMPLE_ALPHA_TO_COVERAGE && !cached_SAMPLE_ALPHA_TO_COVERAGE)
+  {
+    vbo_draw();
+    glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
+    cached_SAMPLE_ALPHA_TO_COVERAGE = true;
+  }
+  else if(cap == GL_SAMPLE_COVERAGE && !cached_SAMPLE_COVERAGE)
+  {
+    vbo_draw();
+    glEnable(GL_SAMPLE_COVERAGE);
+    cached_SAMPLE_COVERAGE = true;
+  }
+  else if(cap == GL_SCISSOR_TEST && !cached_SCISSOR_TEST)
+  {
+    vbo_draw();
+    glEnable(GL_SCISSOR_TEST);
+    cached_SCISSOR_TEST = true;
+  }
+  else if(cap == GL_STENCIL_TEST && !cached_STENCIL_TEST)
+  {
+    vbo_draw();
+    glEnable(GL_STENCIL_TEST);
+    cached_STENCIL_TEST = true;
+  }
+}
+#define glEnable(cap) cache_glEnable(cap)
+
+static GLenum cached_FrontFace_mode;
+void inline cache_glFrontFace (GLenum mode)
+{
+  if(mode != cached_FrontFace_mode)
+  {
+    vbo_draw();
+    glFrontFace(mode);
+    cached_FrontFace_mode = mode;
+  }
+}
+#define glFrontFace(mode) cache_glFrontFace(mode)
+
+static GLfloat cached_PolygonOffset_factor;
+static GLfloat cached_PolygonOffset_units;
+void inline cache_glPolygonOffset (GLfloat factor, GLfloat units)
+{
+  if(factor != cached_PolygonOffset_factor || units != cached_PolygonOffset_units)
+  {
+    vbo_draw();
+    glPolygonOffset(factor, units);
+    cached_PolygonOffset_factor = factor;
+    cached_PolygonOffset_units = units;
+  }
+}
+#define glPolygonOffset(factor, units) cache_glPolygonOffset(factor, units)
+
+static GLint cached_Scissor_x;
+static GLint cached_Scissor_y;
+static GLsizei cached_Scissor_width;
+static GLsizei cached_Scissor_height;
+void inline cache_glScissor (GLint x, GLint y, GLsizei width, GLsizei height)
+{
+  if(x != cached_Scissor_x || y != cached_Scissor_y || width != cached_Scissor_width || height != cached_Scissor_height)
+  {
+    vbo_draw();
+    glScissor(x, y, width, height);
+    cached_Scissor_x = x;
+    cached_Scissor_y = y;
+    cached_Scissor_width = width;
+    cached_Scissor_height = height;
+  }
+}
+#define glScissor(x, y, width, height) cache_glScissor(x, y, width, height)
+
+static GLuint cached_UseProgram_program;
+void inline cache_glUseProgram (GLuint program)
+{
+  if(program != cached_UseProgram_program)
+  {
+    vbo_draw();
+    glUseProgram(program);
+    cached_UseProgram_program = program;
+  }
+}
+#define glUseProgram(program) cache_glUseProgram(program)
+
+static GLint cached_Viewport_x;
+static GLint cached_Viewport_y;
+static GLsizei cached_Viewport_width;
+static GLsizei cached_Viewport_height;
+void inline cache_glViewport (GLint x, GLint y, GLsizei width, GLsizei height)
+{
+  if(x != cached_Viewport_x || y != cached_Viewport_y || width != cached_Viewport_width || height != cached_Viewport_height)
+  {
+    vbo_draw();
+    glViewport(x, y, width, height);
+    cached_Viewport_x = x;
+    cached_Viewport_y = y;
+    cached_Viewport_width = width;
+    cached_Viewport_height = height;
+  }
+}
+#define glViewport(x, y, width, height) cache_glViewport(x, y, width, height)
+
diff --git a/source/gles2glide64/src/Glitch64/glitchmain.cpp b/source/gles2glide64/src/Glitch64/glitchmain.cpp
new file mode 100755 (executable)
index 0000000..21e16b7
--- /dev/null
@@ -0,0 +1,2682 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#define SAVE_CBUFFER
+
+#ifdef _WIN32
+#include <windows.h>
+#include <commctrl.h>
+#else
+#include <stdint.h>
+#include <stdarg.h>
+#include <string.h>
+#include <SDL.h>
+#endif // _WIN32
+#include <stdlib.h>
+#include <stdio.h>
+#include <iostream>
+#include <fstream>
+#include <math.h>
+#include "glide.h"
+#include "g3ext.h"
+#include "main.h"
+#include "m64p.h"
+
+#define OPENGL_CHECK_ERRORS { const GLenum errcode = glGetError(); if (errcode != GL_NO_ERROR) LOG("OpenGL Error code %i in '%s' line %i\n", errcode, __FILE__, __LINE__-1); }
+
+#ifdef VPDEBUG
+#include <IL/il.h>
+#endif
+
+#include "../Glide64/ticks.h"  //*SEB*
+
+extern void (*renderCallback)(int);
+
+wrapper_config config = {0, 0, 0, 0};
+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 )
+
+{
+  int w, h, 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, &fmt);
+  //printf("copyteximage %dx%d fmt %x oldfmt %x\n", width, height, internalFormat, fmt);
+  if (w == (int) width && h == (int) height && fmt == (int) 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 {
+    //printf("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
+*/
+
+
+#ifdef _WIN32
+PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
+PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT;
+PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB;
+PFNGLFOGCOORDFPROC glFogCoordfEXT;
+
+PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB;
+
+PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT;
+PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT;
+PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT;
+PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT = NULL;
+PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT = NULL;
+PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT = NULL;
+PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT;
+PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
+
+PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
+PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
+PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
+PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
+PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
+PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
+PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
+PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
+PFNGLUNIFORM1IARBPROC glUniform1iARB;
+PFNGLUNIFORM4IARBPROC glUniform4iARB;
+PFNGLUNIFORM4FARBPROC glUniform4fARB;
+PFNGLUNIFORM1FARBPROC glUniform1fARB;
+PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
+PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
+PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
+PFNGLSECONDARYCOLOR3FPROC glSecondaryColor3f;
+
+// FXT1,DXT1,DXT5 support - Hiroshi Morii <koolsmoky(at)users.sourceforge.net>
+// NOTE: Glide64 + GlideHQ use the following formats
+// GL_COMPRESSED_RGB_S3TC_DXT1_EXT
+// GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
+// GL_COMPRESSED_RGB_FXT1_3DFX
+// GL_COMPRESSED_RGBA_FXT1_3DFX
+PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2DARB;
+#endif // _WIN32
+
+
+
+typedef struct
+{
+  unsigned int address;
+  int width;
+  int height;
+  int fb_width;
+  int fb_height;
+  unsigned int fbid;
+  unsigned int zbid;
+  unsigned int texid;
+  int buff_clear;
+} fb;
+
+int nbTextureUnits;
+int 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 = 1;
+int viewport_width, viewport_height, viewport_offset = 0, nvidia_viewport_hack = 0;
+int save_w, save_h;
+int lfb_color_fmt;
+float invtex[2];
+//Gonetz
+int UMAmode = 0; //support for VSA-100 UMA mode;
+
+#ifdef _WIN32
+static HDC hDC = NULL;
+static HGLRC hGLRC = NULL;
+static HWND hToolBar = NULL;
+static HWND hwnd_win = NULL;
+static unsigned long windowedExStyle, windowedStyle;
+#endif // _WIN32
+static unsigned long fullscreen;
+#ifdef _WIN32
+static RECT windowedRect;
+static HMENU windowedMenu;
+#endif // _WIN32
+
+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 TMU_USAGE { int min, max; } tmu_usage[2] = { {0xfffffff, 0}, {0xfffffff, 0} };
+
+struct texbuf_t {
+  FxU32 start, end;
+  int fmt;
+};
+#define NB_TEXBUFS 128 // MUST be a power of two
+static texbuf_t texbufs[NB_TEXBUFS];
+static int texbuf_i;
+
+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[4096];
+
+    va_list ap;
+
+    va_start(ap, text);
+    vsprintf(buf, text, ap);
+    va_end(ap);
+    first_message--;
+    LOGINFO(buf);
+  }
+}
+
+#ifdef _WIN32
+void display_error()
+{
+  LPVOID lpMsgBuf;
+  if (!FormatMessage(
+    FORMAT_MESSAGE_ALLOCATE_BUFFER |
+    FORMAT_MESSAGE_FROM_SYSTEM |
+    FORMAT_MESSAGE_IGNORE_INSERTS,
+    NULL,
+    GetLastError(),
+    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+    (LPTSTR) &lpMsgBuf,
+    0,
+    NULL ))
+  {
+    // Handle the error.
+    return;
+  }
+  // Process any inserts in lpMsgBuf.
+  // ...
+  // Display the string.
+  MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
+
+  // Free the buffer.
+  LocalFree( lpMsgBuf );
+}
+#endif // _WIN32
+
+#ifdef LOGGING
+char out_buf[256];
+bool log_open = false;
+std::ofstream log_file;
+
+void OPEN_LOG()
+{
+  if (!log_open)
+  {
+    log_file.open ("wrapper_log.txt", std::ios_base::out|std::ios_base::app);
+    log_open = true;
+  }
+}
+
+void CLOSE_LOG()
+{
+  if (log_open)
+  {
+    log_file.close();
+    log_open = false;
+  }
+}
+
+void LOG(const char *text, ...)
+{
+#ifdef VPDEBUG
+  if (!dumping) return;
+#endif
+       if (!log_open)
+    return;
+       va_list ap;
+       va_start(ap, text);
+       vsprintf(out_buf, text, ap);
+  log_file << out_buf;
+  log_file.flush();
+       va_end(ap);
+}
+
+class LogManager {
+public:
+       LogManager() {
+               OPEN_LOG();
+       }
+       ~LogManager() {
+               CLOSE_LOG();
+       }
+};
+
+LogManager logManager;
+
+#else // LOGGING
+#define OPEN_LOG()
+#define CLOSE_LOG()
+//#define LOG
+#endif // LOGGING
+
+FX_ENTRY void FX_CALL
+grSstOrigin(GrOriginLocation_t  origin)
+{
+  LOG("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 )
+{
+  LOG("grClipWindow(%d,%d,%d,%d)\r\n", minx, miny, maxx, maxy);
+
+  if (use_fbo && render_to_texture) {
+    if (int(minx) < 0) minx = 0;
+    if (int(miny) < 0) miny = 0;
+    if (maxx < minx) maxx = minx;
+    if (maxy < miny) maxy = miny;
+    glScissor(minx, miny, maxx - minx, maxy - miny);
+    glEnable(GL_SCISSOR_TEST);
+    return;
+  }
+
+  if (!use_fbo) {
+    int th = height;
+    if (th > screen_height)
+      th = screen_height;
+    maxy = th - maxy;
+    miny = th - miny;
+    FxU32 tmp = maxy; maxy = miny; miny = tmp;
+    if (maxx > (FxU32) width) maxx = width;
+    if (maxy > (FxU32) height) maxy = height;
+    if (int(minx) < 0) minx = 0;
+    if (int(miny) < 0) miny = 0;
+    if (maxx < minx) maxx = minx;
+    if (maxy < miny) maxy = miny;
+    glScissor(minx, miny+viewport_offset, maxx - minx, maxy - miny);
+    //printf("gl scissor %d %d %d %d\n", minx, miny, maxx, maxy);
+  } 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 )
+{
+  LOG("grColorMask(%d, %d)\r\n", rgb, a);
+  glColorMask(rgb, rgb, rgb, a);
+}
+
+FX_ENTRY void FX_CALL
+grGlideInit( void )
+{
+  LOG("grGlideInit()\r\n");
+}
+
+FX_ENTRY void FX_CALL
+grSstSelect( int which_sst )
+{
+  LOG("grSstSelect(%d)\r\n", which_sst);
+}
+
+int isExtensionSupported(const char *extension)
+{
+  return 0;
+  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 1;
+
+    start = terminator;
+  }
+
+  return 0;
+}
+
+#ifdef _WIN32
+int isWglExtensionSupported(const char *extension)
+{
+  const GLubyte *extensions = NULL;
+  const GLubyte *start;
+  GLubyte *where, *terminator;
+
+  where = (GLubyte *)strchr(extension, ' ');
+  if (where || *extension == '\0')
+    return 0;
+
+  extensions = (GLubyte*)wglGetExtensionsStringARB(wglGetCurrentDC());
+
+  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 1;
+
+    start = terminator;
+  }
+
+  return 0;
+}
+#endif // _WIN32
+
+#define GrPixelFormat_t int
+
+FX_ENTRY GrContext_t FX_CALL
+grSstWinOpenExt(
+                HWND                 hWnd,
+                GrScreenResolution_t screen_resolution,
+                GrScreenRefresh_t    refresh_rate,
+                GrColorFormat_t      color_format,
+                GrOriginLocation_t   origin_location,
+                GrPixelFormat_t      pixelformat,
+                int                  nColBuffers,
+                int                  nAuxBuffers)
+{
+  LOG("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);
+}
+
+#ifdef WIN32
+# include <fcntl.h>
+# ifndef ATTACH_PARENT_PROCESS
+#  define ATTACH_PARENT_PROCESS ((FxU32)-1)
+# endif
+#endif
+
+FX_ENTRY GrContext_t FX_CALL
+grSstWinOpen(
+             HWND                 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;
+
+  // 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++;
+
+  LOG("grSstWinOpen(%08lx, %d, %d, %d, %d, %d %d)\r\n", hWnd, screen_resolution&~0x80000000, refresh_rate, color_format, origin_location, nColBuffers, nAuxBuffers);
+
+#ifdef _WIN32
+  if ((HWND)hWnd == NULL) hWnd = GetActiveWindow();
+  hwnd_win = (HWND)hWnd;
+#endif // _WIN32
+  width = height = 0;
+
+  m64p_handle video_general_section;
+  printf("&ConfigOpenSection is %p\n", &ConfigOpenSection);
+  if (ConfigOpenSection("Video-General", &video_general_section) != M64ERR_SUCCESS)
+  {
+    printf("Could not open video settings");
+    return false;
+  }
+  width = ConfigGetParamInt(video_general_section, "ScreenWidth");
+  height = ConfigGetParamInt(video_general_section, "ScreenHeight");
+  fullscreen = ConfigGetParamBool(video_general_section, "Fullscreen");
+  int vsync = ConfigGetParamBool(video_general_section, "VerticalSync");
+  //viewport_offset = ((screen_resolution>>2) > 20) ? screen_resolution >> 2 : 20;
+  // ZIGGY viewport_offset is WIN32 specific, with SDL just set it to zero
+  viewport_offset = 0; //-10 //-20;
+
+  // ZIGGY not sure, but it might be better to let the system choose
+  CoreVideo_GL_SetAttribute(M64P_GL_DOUBLEBUFFER, 1);
+  CoreVideo_GL_SetAttribute(M64P_GL_SWAP_CONTROL, vsync);
+  CoreVideo_GL_SetAttribute(M64P_GL_BUFFER_SIZE, 16);
+  //   SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
+  //   SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+  //   SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+  //   SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+  //   SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
+  CoreVideo_GL_SetAttribute(M64P_GL_DEPTH_SIZE, 16);
+
+  printf("(II) Setting video mode %dx%d...\n", width, height);
+  if(CoreVideo_SetVideoMode(width, height, 0, fullscreen ? M64VIDEO_FULLSCREEN : M64VIDEO_WINDOWED, (m64p_video_flags) 0) != M64ERR_SUCCESS)
+  {
+    printf("(EE) Error setting videomode %dx%d\n", width, height);
+    return false;
+  }
+
+  char caption[500];
+# ifdef _DEBUG
+  sprintf(caption, "Glide64mk2 debug");
+# else // _DEBUG
+  sprintf(caption, "Glide64mk2");
+# endif // _DEBUG
+  CoreVideo_SetCaption(caption);
+
+  glViewport(0, viewport_offset, width, height);
+  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") == 0 &&
+    isExtensionSupported("GL_EXT_texture_env_combine") == 0 &&
+    show_warning)
+    display_warning("Your video card doesn't support GL_ARB_texture_env_combine extension");
+  if (isExtensionSupported("GL_ARB_multitexture") == 0 && show_warning)
+    display_warning("Your video card doesn't support GL_ARB_multitexture extension");
+  if (isExtensionSupported("GL_ARB_texture_mirrored_repeat") == 0 && show_warning)
+    display_warning("Your video card doesn't support GL_ARB_texture_mirrored_repeat extension");
+  show_warning = 0;
+
+#ifdef _WIN32
+  glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)wglGetProcAddress("glActiveTextureARB");
+  glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC)wglGetProcAddress("glMultiTexCoord2fARB");
+#endif // _WIN32
+
+  nbTextureUnits = 4;
+  //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 = 4;
+  //glGetIntegerv(GL_AUX_BUFFERS, &nbAuxBuffers);
+  if (nbAuxBuffers > 0)
+    printf("Congratulations, you have %d auxilliary buffers, we'll use them wisely !\n", nbAuxBuffers);
+#ifdef VOODOO1
+  nbTextureUnits = 2;
+#endif
+
+  blend_func_separate_support = 1;
+  packed_pixels_support = 0;
+/*
+  if (isExtensionSupported("GL_EXT_blend_func_separate") == 0)
+    blend_func_separate_support = 0;
+  else
+    blend_func_separate_support = 1;
+
+  if (isExtensionSupported("GL_EXT_packed_pixels") == 0)
+    packed_pixels_support = 0;
+  else {
+    printf("packed pixels extension used\n");
+    packed_pixels_support = 1;
+  }
+*/
+
+  if (isExtensionSupported("GL_ARB_texture_non_power_of_two") == 0)
+    npot_support = 0;
+  else {
+    printf("NPOT extension used\n");
+    npot_support = 1;
+  }
+
+#ifdef _WIN32
+  glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC)wglGetProcAddress("glBlendFuncSeparateEXT");
+#endif // _WIN32
+
+  if (isExtensionSupported("GL_EXT_fog_coord") == 0)
+    fog_coord_support = 0;
+  else
+    fog_coord_support = 1;
+
+#ifdef _WIN32
+  glFogCoordfEXT = (PFNGLFOGCOORDFPROC)wglGetProcAddress("glFogCoordfEXT");
+#endif // _WIN32
+
+#ifdef _WIN32
+  wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");
+#endif // _WIN32
+
+#ifdef _WIN32
+  glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)wglGetProcAddress("glBindFramebufferEXT");
+  glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)wglGetProcAddress("glFramebufferTexture2DEXT");
+  glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)wglGetProcAddress("glGenFramebuffersEXT");
+  glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)wglGetProcAddress("glCheckFramebufferStatusEXT");
+  glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)wglGetProcAddress("glDeleteFramebuffersEXT");
+
+  glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC)wglGetProcAddress("glBindRenderbufferEXT");
+  glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)wglGetProcAddress("glDeleteRenderbuffersEXT");
+  glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)wglGetProcAddress("glGenRenderbuffersEXT");
+  glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)wglGetProcAddress("glRenderbufferStorageEXT");
+  glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)wglGetProcAddress("glFramebufferRenderbufferEXT");
+  use_fbo = config.fbo && (glFramebufferRenderbufferEXT != NULL);
+#else
+  use_fbo = config.fbo;
+#endif // _WIN32
+
+  LOGINFO("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"))
+  {
+
+#ifdef _WIN32
+    glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)wglGetProcAddress("glCreateShaderObjectARB");
+    glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)wglGetProcAddress("glShaderSourceARB");
+    glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)wglGetProcAddress("glCompileShaderARB");
+    glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)wglGetProcAddress("glCreateProgramObjectARB");
+    glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)wglGetProcAddress("glAttachObjectARB");
+    glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)wglGetProcAddress("glLinkProgramARB");
+    glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)wglGetProcAddress("glUseProgramObjectARB");
+    glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)wglGetProcAddress("glGetUniformLocationARB");
+    glUniform1iARB = (PFNGLUNIFORM1IARBPROC)wglGetProcAddress("glUniform1iARB");
+    glUniform4iARB = (PFNGLUNIFORM4IARBPROC)wglGetProcAddress("glUniform4iARB");
+    glUniform4fARB = (PFNGLUNIFORM4FARBPROC)wglGetProcAddress("glUniform4fARB");
+    glUniform1fARB = (PFNGLUNIFORM1FARBPROC)wglGetProcAddress("glUniform1fARB");
+    glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)wglGetProcAddress("glDeleteObjectARB");
+    glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)wglGetProcAddress("glGetInfoLogARB");
+    glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)wglGetProcAddress("glGetObjectParameterivARB");
+
+    glSecondaryColor3f = (PFNGLSECONDARYCOLOR3FPROC)wglGetProcAddress("glSecondaryColor3f");
+#endif // _WIN32
+  }
+
+  if (isExtensionSupported("GL_EXT_texture_compression_s3tc") == 0  && show_warning)
+    display_warning("Your video card doesn't support GL_EXT_texture_compression_s3tc extension");
+  if (isExtensionSupported("GL_3DFX_texture_compression_FXT1") == 0  && show_warning)
+    display_warning("Your video card doesn't support GL_3DFX_texture_compression_FXT1 extension");
+
+#ifdef _WIN32
+  glCompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)wglGetProcAddress("glCompressedTexImage2DARB");
+#endif
+/*SEB*/
+  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+  glPixelStorei(GL_PACK_ALIGNMENT, 1);
+
+
+#ifdef _WIN32
+  glViewport(0, viewport_offset, width, height);
+  viewport_width = width;
+  viewport_height = height;
+  nvidia_viewport_hack = 1;
+#else
+  glViewport(0, viewport_offset, width, height);
+  viewport_width = width;
+  viewport_height = height;
+#endif // _WIN32
+
+  //   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);
+
+  widtho = width/2;
+  heighto = height/2;
+
+  pBufferWidth = pBufferHeight = -1;
+
+  current_buffer = GL_BACK;
+
+  texture_unit = GL_TEXTURE0;
+
+  {
+    int i;
+    for (i=0; i<NB_TEXBUFS; i++)
+      texbufs[i].start = texbufs[i].end = 0xffffffff;
+  }
+
+  if (!use_fbo && nbAuxBuffers == 0) {
+    // create the framebuffer saving texture
+    int w = width, h = height;
+    glBindTexture(GL_TEXTURE_2D, color_texture);
+    if (!npot_support) {
+      w = h = 1;
+      while (w<width) w*=2;
+      while (h<height) h*=2;
+    }
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
+    glBindTexture(GL_TEXTURE_2D, 0);
+    save_w = save_h = 0;
+  }
+
+  void FindBestDepthBias();
+  FindBestDepthBias();
+
+  init_geometry();
+  init_textures();
+  init_combiner();
+
+/*
+  // Aniso filter check
+  if (config.anisofilter > 0 )
+    glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy);
+
+  // ATI hack - certain texture formats are slow on ATI?
+  // Hmm, perhaps the internal format need to be specified explicitly...
+  {
+    GLint ifmt;
+    glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, NULL);
+    glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &ifmt);
+    if (ifmt != GL_RGB5_A1) {
+      display_warning("ATI SUCKS %x\n", ifmt);
+      ati_sucks = 1;
+    } else
+      ati_sucks = 0;
+  }
+*/
+
+  return 1;
+}
+
+FX_ENTRY void FX_CALL
+grGlideShutdown( void )
+{
+  LOG("grGlideShutdown\r\n");
+}
+
+FX_ENTRY FxBool FX_CALL
+grSstWinClose( GrContext_t context )
+{
+  int i, clear_texbuff = use_fbo;
+  LOG("grSstWinClose(%d)\r\n", context);
+
+  for (i=0; i<2; i++) {
+    tmu_usage[i].min = 0xfffffff;
+    tmu_usage[i].max = 0;
+    invtex[i] = 0;
+  }
+
+  free_combiners();
+#ifndef WIN32
+  try // I don't know why, but opengl can be killed before this function call when emulator is closed (Gonetz).
+    // ZIGGY : I found the problem : it is a function pointer, when the extension isn't supported , it is then zero, so just need to check the pointer prior to do the call.
+  {
+    if (use_fbo)
+      glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+  }
+  catch (...)
+  {
+    clear_texbuff = 0;
+  }
+
+  if (clear_texbuff)
+  {
+    for (i=0; i<nb_fb; i++)
+    {
+      glDeleteTextures( 1, &(fbs[i].texid) );
+      glDeleteFramebuffers( 1, &(fbs[i].fbid) );
+      glDeleteRenderbuffers( 1, &(fbs[i].zbid) );
+    }
+  }
+#endif
+  nb_fb = 0;
+
+  free_textures();
+#ifndef WIN32
+  // ZIGGY for some reasons, Pj64 doesn't like remove_tex on exit
+  remove_tex(0, 0xfffffff);
+#endif
+
+  //*/
+#ifdef _WIN32
+  if (hGLRC)
+  {
+    wglMakeCurrent(hDC,NULL);
+    wglDeleteContext(hGLRC);
+    hGLRC = NULL;
+  }
+  if (fullscreen)
+  {
+    ChangeDisplaySettings(NULL, 0);
+    SetWindowPos(hwnd_win, NULL,
+      windowedRect.left, windowedRect.top,
+      0, 0,
+      SWP_NOZORDER | SWP_NOSIZE);
+    SetWindowLong(hwnd_win, GWL_STYLE, windowedStyle);
+    SetWindowLong(hwnd_win, GWL_EXSTYLE, windowedExStyle);
+    if (windowedMenu) SetMenu(hwnd_win, windowedMenu);
+    fullscreen = 0;
+  }
+#else
+  CoreVideo_Quit();
+  //SDL_QuitSubSystem(SDL_INIT_VIDEO);
+  //sleep(2);
+#endif
+  return FXTRUE;
+}
+
+FX_ENTRY void FX_CALL grTextureBufferExt( GrChipID_t           tmu,
+                                         FxU32                                 startAddress,
+                                         GrLOD_t                       lodmin,
+                                         GrLOD_t                       lodmax,
+                                         GrAspectRatio_t       aspect,
+                                         GrTextureFormat_t     fmt,
+                                         FxU32                                 evenOdd)
+{
+  int i;
+  static int fbs_init = 0;
+
+  LOG("grTextureBufferExt(%d, %d, %d, %d %d, %d, %d)\r\n", tmu, startAddress, lodmin, lodmax, aspect, fmt, evenOdd);
+  if (lodmin != lodmax) display_warning("grTextureBufferExt : loading more than one LOD");
+  if (!use_fbo) {
+
+    if (!render_to_texture) { //initialization
+      return;
+    }
+
+    render_to_texture = 2;
+
+    if (aspect < 0)
+    {
+      pBufferHeight = 1 << lodmin;
+      pBufferWidth = pBufferHeight >> -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);
+      glActiveTexture(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 = 0;
+
+    curBufferAddr = pBufferAddress = startAddress+1;
+    pBufferFmt = fmt;
+
+    int rtmu = startAddress < grTexMinAddress(GR_TMU1)? 0 : 1;
+    int size = pBufferWidth*pBufferHeight*2; //grTexFormatSize(fmt);
+    if ((unsigned int) tmu_usage[rtmu].min > pBufferAddress)
+      tmu_usage[rtmu].min = pBufferAddress;
+    if ((unsigned int) 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);
+
+
+  } 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;
+
+    for (i=0; i<nb_fb; i++)
+    {
+      if (fbs[i].address == pBufferAddress)
+      {
+//        if (fbs[i].width == width && fbs[i].height == height) //select already allocated FBO
+        if (fbs[i].width >= width && fbs[i].height >= height) //select already allocated FBO, or large enough
+        {
+//unsigned int tticks = ticksGetTicks();
+          glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+          glBindFramebuffer( GL_FRAMEBUFFER, fbs[i].fbid );
+          glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbs[i].texid, 0 );
+          glBindRenderbuffer( GL_RENDERBUFFER, fbs[i].zbid );
+          glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbs[i].zbid );
+          glViewport( 0, 0, width, height);
+          glScissor( 0, 0, width, height);
+                 fbs[i].fb_width=width;
+                 fbs[i].fb_height=height;
+          if (fbs[i].buff_clear)
+          {
+            glDepthMask(1);
+            glClear( GL_DEPTH_BUFFER_BIT ); //clear z-buffer only. we may need content, stored in the frame buffer
+            fbs[i].buff_clear = 0;
+          }
+          CHECK_FRAMEBUFFER_STATUS();
+          curBufferAddr = pBufferAddress;
+//printf("select existing fbo (%u ms)\n", ticksGetTicks()-tticks);
+          return;
+        }
+        else //create new FBO at the same address, delete old one 
+        {
+//unsigned int tticks = ticksGetTicks();
+          glDeleteFramebuffers( 1, &(fbs[i].fbid) );
+          glDeleteRenderbuffers( 1, &(fbs[i].zbid) );
+          if (nb_fb > 1)
+            memmove(&(fbs[i]), &(fbs[i+1]), sizeof(fb)*(nb_fb-i));
+          nb_fb--;
+//printf("delete existing fbo (%u ms)\n", ticksGetTicks()-tticks);
+          break;
+        }
+      }
+    }
+//unsigned int tticks = ticksGetTicks();
+    remove_tex(pBufferAddress, pBufferAddress + width*height*2/*grTexFormatSize(fmt)*/);
+//printf("delete texture (%u ms)\n", ticksGetTicks()-tticks);
+    //create new FBO
+    glGenFramebuffers( 1, &(fbs[nb_fb].fbid) );
+    glGenRenderbuffers( 1, &(fbs[nb_fb].zbid) );
+    glBindRenderbuffer( GL_RENDERBUFFER, fbs[nb_fb].zbid );
+    glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
+    fbs[nb_fb].address = pBufferAddress;
+    fbs[nb_fb].width = width;
+    fbs[nb_fb].height = height;
+    fbs[nb_fb].fb_width = width;
+    fbs[nb_fb].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 );
+
+    glBindFramebuffer( GL_FRAMEBUFFER, fbs[nb_fb].fbid);
+    glFramebufferTexture2D(GL_FRAMEBUFFER,
+      GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbs[nb_fb].texid, 0);
+    glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbs[nb_fb].zbid );
+    glViewport(0,0,width,height);
+    glScissor(0,0,width,height);
+    glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
+    glDepthMask(1);
+    glClear( GL_DEPTH_BUFFER_BIT );
+    CHECK_FRAMEBUFFER_STATUS();
+    curBufferAddr = pBufferAddress;
+    nb_fb++;
+//printf("create new fbo=fb[%i] (%u ms)\n", nb_fb-1, ticksGetTicks()-tticks);
+  }
+}
+
+int CheckTextureBufferFormat(GrChipID_t tmu, FxU32 startAddress, GrTexInfo *info )
+{
+  int found, i;
+  if (!use_fbo) {
+    for (found=i=0; i<2; i++)
+      if ((FxU32) tmu_usage[i].min <= startAddress && (FxU32) tmu_usage[i].max > startAddress) {
+        //printf("tmu %d == framebuffer %x\n", tmu, startAddress);
+        found = 1;
+        break;
+      }
+  } else {
+    found = i = 0;
+    while (i < nb_fb)
+    {
+      unsigned int end = fbs[i].address + fbs[i].fb_width*fbs[i].fb_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;
+    }
+    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 )
+{
+  LOG("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( char *procName )
+{
+  LOG("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;
+  // ZIGGY framebuffer copy extension
+  if(!strcmp(procName, "grFramebufferCopyExt"))
+    return (GrProc)grFramebufferCopyExt;
+  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;
+  if(!strcmp(procName, "grWrapperFullScreenResolutionExt"))
+    return (GrProc)grWrapperFullScreenResolutionExt;
+  if(!strcmp(procName, "grConfigWrapperExt"))
+    return (GrProc)grConfigWrapperExt;
+  if(!strcmp(procName, "grKeyPressedExt"))
+    return (GrProc)grKeyPressedExt;
+  if(!strcmp(procName, "grQueryResolutionsExt"))
+    return (GrProc)grQueryResolutionsExt;
+  if(!strcmp(procName, "grGetGammaTableExt"))
+    return (GrProc)grGetGammaTableExt;
+  display_warning("grGetProcAddress : %s", procName);
+  return 0;
+}
+
+FX_ENTRY FxU32 FX_CALL
+grGet( FxU32 pname, FxU32 plength, FxI32 *params )
+{
+  LOG("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 | 0x80000000, 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:
+    if (plength < 4 || params == NULL) return 0;
+    params[0] = 8;
+    return 4;
+    break;
+  case GR_GAMMA_TABLE_ENTRIES:
+    if (plength < 4 || params == NULL) return 0;
+    params[0] = 256;
+    return 4;
+    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 )
+{
+  LOG("grGetString(%d)\r\n", pname);
+  switch(pname)
+  {
+  case GR_EXTENSION:
+    {
+      static char extension[] = "CHROMARANGE TEXCHROMA TEXMIRROR PALETTE6666 FOGCOORD EVOODOO TEXTUREBUFFER TEXUMA TEXFMT COMBINE GETGAMMA";
+      return extension;
+    }
+    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)
+{
+  LOGINFO("render_rectangle(%d,%d,%d,%d,%d,%d,%d,%d)",texture_number,dst_x,dst_y,src_width,src_height,tex_width,tex_height,invert);
+  int vertexOffset_location;
+  int textureSizes_location;
+  static float data[] = {
+    ((int)dst_x),                             //X 0
+    invert*-((int)dst_y),                     //Y 0 
+    0.0f,                                     //U 0 
+    0.0f,                                     //V 0
+
+    ((int)dst_x),                             //X 1
+    invert*-((int)dst_y + (int)src_height),   //Y 1
+    0.0f,                                     //U 1
+    (float)src_height / (float)tex_height,    //V 1
+
+    ((int)dst_x + (int)src_width), 
+    invert*-((int)dst_y + (int)src_height),
+    (float)src_width / (float)tex_width,
+    (float)src_height / (float)tex_height,
+
+    ((int)dst_x),
+    invert*-((int)dst_y),
+    0.0f,
+    0.0f
+  };
+
+  vbo_disable();
+  glDisableVertexAttribArray(COLOUR_ATTR);
+  glDisableVertexAttribArray(TEXCOORD_1_ATTR);
+  glDisableVertexAttribArray(FOG_ATTR);
+
+  glVertexAttribPointer(POSITION_ATTR,2,GL_FLOAT,false,2,data); //Position
+  glVertexAttribPointer(TEXCOORD_0_ATTR,2,GL_FLOAT,false,2,&data[2]); //Tex
+
+  glEnableVertexAttribArray(COLOUR_ATTR);
+  glEnableVertexAttribArray(TEXCOORD_1_ATTR);
+  glEnableVertexAttribArray(FOG_ATTR);
+
+
+  disable_textureSizes();
+
+  glDrawArrays(GL_TRIANGLE_STRIP,0,4);
+  vbo_enable();
+
+
+/*
+  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();
+*/
+
+  compile_shader();
+
+  glEnable(GL_DEPTH_TEST);
+  glEnable(GL_BLEND);
+}
+
+void reloadTexture()
+{
+  if (use_fbo || !render_to_texture || buffer_cleared)
+    return;
+
+  LOG("reload texture %dx%d\n", width, height);
+  //printf("reload texture %dx%d\n", width, height);
+
+  buffer_cleared = 1;
+
+  //glPushAttrib(GL_ALL_ATTRIB_BITS);
+  glActiveTexture(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 (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) {
+    LOG("update texture %x\n", pBufferAddress);
+    //printf("update texture %x\n", pBufferAddress);
+
+    // nothing changed, don't update the texture
+    if (!buffer_cleared) {
+      LOG("update cancelled\n", pBufferAddress);
+      return;
+    }
+
+    //glPushAttrib(GL_ALL_ATTRIB_BITS);
+
+    // save result of render to texture into actual texture
+    //glReadBuffer(current_buffer);
+    glActiveTexture(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, 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) {
+
+    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) {
+      //printf("save depth buffer %d\n", render_to_texture);
+      // save the depth image in a texture
+      //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) {
+      //printf("writing to depth buffer %d\n", render_to_texture);
+      //glPushAttrib(GL_ALL_ATTRIB_BITS);
+      //glDisable(GL_ALPHA_TEST);
+      //glDrawBuffer(current_buffer);
+      glActiveTexture(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 )
+{
+#ifdef _WIN32
+  static HANDLE region = NULL;
+  int realWidth = pBufferWidth, realHeight = pBufferHeight;
+#endif // _WIN32
+  LOG("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) {
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+        glBindRenderbuffer( GL_RENDERBUFFER, 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);
+          glActiveTexture(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
+      render_to_texture = 0;
+    }
+    //glDrawBuffer(GL_BACK);
+    break;
+  case 6: // RENDER TO TEXTURE
+    if(!render_to_texture)
+    {
+      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 )
+{
+  LOG("grAuxBufferExt(%d)\r\n", buffer);
+  //display_warning("grAuxBufferExt");
+
+  if (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);
+  } 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 )
+{
+  vbo_draw();
+  LOG("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)
+    glClearDepthf(1.0f - ((1.0f + (depth >> 4) / 4096.0f) * (1 << (depth & 0xF))) / 65528.0);
+  else
+    glClearDepthf(depth / 65535.0f);
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  // ZIGGY TODO check that color mask is on
+  buffer_cleared = 1;
+
+}
+
+// #include <unistd.h>
+FX_ENTRY void FX_CALL
+grBufferSwap( FxU32 swap_interval )
+{
+  vbo_draw();
+//     glFinish();
+//  printf("rendercallback is %p\n", renderCallback);
+  if(renderCallback)
+      (*renderCallback)(1);
+  int i;
+  LOG("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;
+          }
+  }
+  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 )
+{
+  LOG("grLfbLock(%d,%d,%d,%d,%d)\r\n", type, buffer, writeMode, origin, pixelPipeline);
+printf("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;
+    default:
+      display_warning("grLfbLock : unknown buffer : %x", buffer);
+    }
+
+    if(buffer != GR_BUFFER_AUXBUFFER)
+    {
+      if (writeMode == GR_LFBWRITEMODE_888) {
+/*SEB*/
+        buf = (unsigned char*)malloc(width*height*4);
+        //printf("LfbLock GR_LFBWRITEMODE_888\n");
+        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);
+        glReadPixels(0, viewport_offset, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buf);
+
+/*SEB*/
+           unsigned char *p=buf;
+        for (j=0; j<height; j++)
+        {
+           short unsigned int *f=frameBuffer+(height-j-1)*width;
+          for (i=0; i<width; i++)
+          {
+            *(f++) =
+              (*(p)   <<24) |
+              (*(p+1) <<16) |
+              (*(p+2) << 8) |
+                 (0xff);
+              p+=4;
+          }
+        }
+        free(buf);
+      } 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);
+
+/*SEB*/
+           unsigned char *p=buf;
+        for (j=0; j<height; j++)
+        {
+             short unsigned int *f=frameBuffer+(height-j-1)*width;
+          for (i=0; i<width; i++)
+          {
+/*            frameBuffer[(height-j-1)*width+i] =
+              ((buf[j*width*4+i*4+0] >> 3) << 11) |
+              ((buf[j*width*4+i*4+1] >> 2) <<  5) |
+              (buf[j*width*4+i*4+2] >> 3);*/
+            *(f++) =
+              ((*(p)   >> 3) << 11) |
+              ((*(p+1) >> 2) <<  5) |
+              (*(p+2)  >> 3);
+              p+=4;
+          }
+        }
+        free(buf);
+      }
+    }
+    else
+    {
+      info->lfbPtr = depthBuffer;
+      info->strideInBytes = width*2;
+      info->writeMode = GR_LFBWRITEMODE_ZA16;
+      info->origin = origin;
+      //*SEB* *TODO* check alignment
+      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 )
+{
+  LOG("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;
+  LOG("grLfbReadRegion(%d,%d,%d,%d,%d,%d)\r\n", src_buffer, src_x, src_y, src_width, src_height, dst_stride);
+//printf("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<src_height; j++)
+    {
+/*SEB*/
+      unsigned char *p=buf+(src_height-j-1)*src_width*4;
+      unsigned short *f=frameBuffer+(j*dst_stride/2);
+      for (i=0; i<src_width; i++)
+      {
+/*        frameBuffer[j*(dst_stride/2)+i] =
+          ((buf[(src_height-j-1)*src_width*4+i*4+0] >> 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);*/
+        *(f++) =
+          ((*(p) >> 3) << 11) |
+          ((*(p+1) >> 2) <<  5) |
+          (*(p+2) >> 3);
+         p+=4;
+      }
+    }
+    free(buf);
+  }
+  else
+  {
+    buf = (unsigned char*)malloc(src_width*src_height*2);
+//*SEB read in buf, not depthBuffer.
+    glReadPixels(src_x, (viewport_offset)+height-src_y-src_height, src_width, src_height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, buf);
+
+    for (j=0;j<src_height; j++)
+    {
+//*SEB*
+      unsigned short *d=depthBuffer+j*dst_stride/2;
+      unsigned short *p=(unsigned short*)buf+(src_height-j-1)*src_width; //orignal look fishy. why *4???
+      for (i=0; i<src_width; i++)
+      {
+/*        depthBuffer[j*(dst_stride/2)+i] =
+          ((unsigned short*)buf)[(src_height-j-1)*src_width*4+i*4];*/
+        *(d++) = *(p++); //why *4 (prob. GL_PACK was=4), plus transcoding to short, that make *8 ???
+      }
+    }
+    free(buf);
+  }
+
+  return FXTRUE;
+}
+
+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 )
+{
+  unsigned char *buf;
+  unsigned int i,j;
+  unsigned short *frameBuffer = (unsigned short*)src_data;
+  int texture_number;
+  unsigned int tex_width = 1, tex_height = 1;
+  LOG("grLfbWriteRegion(%d,%d,%d,%d,%d,%d,%d,%d)\r\n",dst_buffer, dst_x, dst_y, src_format, src_width, src_height, pixelPipeline, src_stride);
+//printf("grLfbWriteRegion(%d,%d,%d,%d,%d,%d,%d,%d)\r\n",dst_buffer, dst_x, dst_y, src_format, src_width, src_height, pixelPipeline, src_stride);
+
+  //glPushAttrib(GL_ALL_ATTRIB_BITS);
+
+  while (tex_width < src_width) tex_width <<= 1;
+  while (tex_height < src_height) tex_height <<= 1;
+
+  switch(dst_buffer)
+  {
+  case GR_BUFFER_BACKBUFFER:
+    //glDrawBuffer(GL_BACK);
+    break;
+  case GR_BUFFER_AUXBUFFER:
+    //glDrawBuffer(current_buffer);
+    break;
+  default:
+    display_warning("grLfbWriteRegion : unknown buffer : %x", dst_buffer);
+  }
+
+  if(dst_buffer != GR_BUFFER_AUXBUFFER)
+  {
+    buf = (unsigned char*)malloc(tex_width*tex_height*4);
+
+    texture_number = GL_TEXTURE0;
+    glActiveTexture(texture_number);
+
+    const unsigned int half_stride = src_stride / 2;
+
+    const int comp_stride = half_stride - src_width;
+    const int comp_tex = (tex_width - src_width)*4;
+    unsigned short *f=frameBuffer;
+    unsigned char *p=buf;
+
+    switch(src_format)
+    {
+    case GR_LFB_SRC_FMT_1555:
+      for (j=0; j<src_height; j++)
+      {
+        for (i=0; i<src_width; i++)
+        {
+/*          const unsigned int col = frameBuffer[j*half_stride+i];
+          buf[j*tex_width*4+i*4+0]=((col>>10)&0x1F)<<3;
+          buf[j*tex_width*4+i*4+1]=((col>>5)&0x1F)<<3;
+          buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3;
+          buf[j*tex_width*4+i*4+3]= (col>>15) ? 0xFF : 0;*/
+          const unsigned int col = *(f++);
+          *(p)=((col>>10)&0x1F)<<3;
+          *(p+1)=((col>>5)&0x1F)<<3;
+          *(p+2)=((col>>0)&0x1F)<<3;
+          *(p+3)= (col>>15) ? 0xFF : 0;
+         p+=4;
+        }
+       p+=comp_tex;
+       f+=comp_stride;
+      }
+      break;
+    case GR_LFBWRITEMODE_555:
+      for (j=0; j<src_height; j++)
+      {
+        for (i=0; i<src_width; i++)
+        {
+/*          const unsigned int col = frameBuffer[j*half_stride+i];
+          buf[j*tex_width*4+i*4+0]=((col>>10)&0x1F)<<3;
+          buf[j*tex_width*4+i*4+1]=((col>>5)&0x1F)<<3;
+          buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3;
+          buf[j*tex_width*4+i*4+3]=0xFF;*/
+          const unsigned int col = *(f++);
+          *(p)=((col>>10)&0x1F)<<3;
+          *(p+1)=((col>>5)&0x1F)<<3;
+          *(p+2)=((col>>0)&0x1F)<<3;
+          *(p+3)=0xFF;
+         p+=4;
+        }
+       p+=comp_tex;
+       f+=comp_stride;
+      }
+      break;
+    case GR_LFBWRITEMODE_565:
+      for (j=0; j<src_height; j++)
+      {
+        for (i=0; i<src_width; i++)
+        {
+/*          const unsigned int col = frameBuffer[j*half_stride+i];
+          buf[j*tex_width*4+i*4+0]=((col>>11)&0x1F)<<3;
+          buf[j*tex_width*4+i*4+1]=((col>>5)&0x3F)<<2;
+          buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3;
+          buf[j*tex_width*4+i*4+3]=0xFF;*/
+          const unsigned int col = *(f++);
+          *(p)=((col>>11)&0x1F)<<3;
+          *(p+1)=((col>>5)&0x3F)<<2;
+          *(p+2)=((col>>0)&0x1F)<<3;
+          *(p+3)=0xFF;
+         p+=4;
+        }
+       p+=comp_tex;
+       f+=comp_stride;
+      }
+      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, GL_RGBA, 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; j<src_height; j++)
+    {
+      for (i=0; i<src_width; i++)
+      {
+        buf[(j+(viewport_offset))*src_width+i] =
+          (frameBuffer[(src_height-j-1)*(src_stride/2)+i]/(65536.0f*(2.0f/zscale)))+1-zscale/2.0f;
+      }
+    }
+
+#ifdef VPDEBUG
+    if (dumping) {
+      unsigned char * buf2 = (unsigned char *)malloc(src_width*(src_height+(viewport_offset)));
+      for (i=0; i<src_width*src_height ; i++)
+        buf2[i] = buf[i]*255.0f;
+      ilTexImage(src_width, src_height, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, buf2);
+      char name[128];
+      static int id;
+      sprintf(name, "dump/writedepth%d.png", id++);
+      ilSaveImage(name);
+      //printf("dumped gdLfbWriteRegion %s\n", name);
+      free(buf2);
+    }
+#endif
+
+    glEnable(GL_DEPTH_TEST);
+    glDepthFunc(GL_ALWAYS);
+
+    //glDrawBuffer(GL_BACK);
+    glClear( GL_DEPTH_BUFFER_BIT );
+    glDepthMask(1);
+    //glDrawPixels(src_width, src_height+(viewport_offset), GL_DEPTH_COMPONENT, GL_FLOAT, buf);
+
+    free(buf);
+  }
+  //glDrawBuffer(current_buffer);
+  //glPopAttrib();
+  return FXTRUE;
+}
+
+/* wrapper-specific glide extensions */
+
+FX_ENTRY char ** FX_CALL
+grQueryResolutionsExt(FxI32 * Size)
+{
+  return 0;
+/*
+  LOG("grQueryResolutionsExt\r\n");
+  return g_FullScreenResolutions.getResolutionsList(Size);
+*/
+}
+
+FX_ENTRY GrScreenResolution_t FX_CALL grWrapperFullScreenResolutionExt(FxU32* width, FxU32* height)
+{
+  return 0;
+/*
+  LOG("grWrapperFullScreenResolutionExt\r\n");
+  g_FullScreenResolutions.getResolution(config.res, width, height);
+  return config.res;
+*/
+}
+
+FX_ENTRY FxBool FX_CALL grKeyPressedExt(FxU32 key)
+{
+  return 0;
+/*
+#ifdef _WIN32
+  return (GetAsyncKeyState(key) & 0x8000);
+#else
+  if (key == 1) //LBUTTON
+  {
+    Uint8 mstate = SDL_GetMouseState(NULL, NULL);
+    return (mstate & SDL_BUTTON_LMASK);
+  }
+  else
+  {
+    Uint8 *keystates = SDL_GetKeyState( NULL );
+    if( keystates[ key ] )
+    {
+      return 1;
+    }
+    else
+    {
+      return 0;
+    }
+  }
+#endif
+*/
+}
+
+FX_ENTRY void FX_CALL grConfigWrapperExt(FxI32 resolution, FxI32 vram, FxBool fbo, FxBool aniso)
+{
+  LOG("grConfigWrapperExt\r\n");
+  config.res = resolution;
+  config.vram_size = vram;
+  config.fbo = fbo;
+  config.anisofilter = aniso;
+}
+
+// unused by glide64
+
+FX_ENTRY FxI32 FX_CALL
+grQueryResolutions( const GrResolution *resTemplate, GrResolution *output )
+{
+  int res_inf = 0;
+  int res_sup = 0xf;
+  int i;
+  int n=0;
+  LOG("grQueryResolutions\r\n");
+  display_warning("grQueryResolutions");
+  if ((unsigned int)resTemplate->resolution != 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 )
+{
+  LOG("grEnable(%d)\r\n", mode);
+  if (mode == GR_TEXTURE_UMA_EXT)
+    UMAmode = 1;
+}
+
+FX_ENTRY void FX_CALL
+grDisable( GrEnableMode_t mode )
+{
+  LOG("grDisable(%d)\r\n", mode);
+  if (mode == GR_TEXTURE_UMA_EXT)
+    UMAmode = 0;
+}
+
+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");
+}
+
+/*
+inline void MySleep(FxU32 ms)
+{
+#ifdef _WIN32
+  Sleep(ms);
+#else
+  SDL_Delay(ms);
+#endif
+}
+*/
+
+#ifdef _WIN32
+static void CorrectGamma(LPVOID apGammaRamp)
+{
+  HDC hdc = GetDC(NULL);
+  if (hdc != NULL)
+  {
+    SetDeviceGammaRamp(hdc, apGammaRamp);
+    ReleaseDC(NULL, hdc);
+  }
+}
+#else
+static void CorrectGamma(const FxU16 aGammaRamp[3][256])
+{
+  //TODO?
+  //int res = SDL_SetGammaRamp(aGammaRamp[0], aGammaRamp[1], aGammaRamp[2]);
+  //LOG("SDL_SetGammaRamp returned %d\r\n", res);
+}
+#endif
+
+FX_ENTRY void FX_CALL
+grLoadGammaTable( FxU32 nentries, FxU32 *red, FxU32 *green, FxU32 *blue)
+{
+  LOG("grLoadGammaTable\r\n");
+  if (!fullscreen)
+    return;
+  FxU16 aGammaRamp[3][256];
+  for (int i = 0; i < 256; i++)
+  {
+    aGammaRamp[0][i] = (FxU16)((red[i] << 8) & 0xFFFF);
+    aGammaRamp[1][i] = (FxU16)((green[i] << 8) & 0xFFFF);
+    aGammaRamp[2][i] = (FxU16)((blue[i] << 8) & 0xFFFF);
+  }
+  CorrectGamma(aGammaRamp);
+  //MySleep(1000); //workaround for Mupen64
+}
+
+FX_ENTRY void FX_CALL
+grGetGammaTableExt(FxU32 nentries, FxU32 *red, FxU32 *green, FxU32 *blue)
+{
+  return;
+  //TODO?
+  /*
+  LOG("grGetGammaTableExt()\r\n");
+  FxU16 aGammaRamp[3][256];
+#ifdef _WIN32
+  HDC hdc = GetDC(NULL);
+  if (hdc == NULL)
+    return;
+  if (GetDeviceGammaRamp(hdc, aGammaRamp) == TRUE)
+  {
+    ReleaseDC(NULL, hdc);
+#else
+  if (SDL_GetGammaRamp(aGammaRamp[0], aGammaRamp[1], aGammaRamp[2]) != -1)
+  {
+#endif
+    for (int i = 0; i < 256; i++)
+    {
+      red[i] = aGammaRamp[0][i] >> 8;
+      green[i] = aGammaRamp[1][i] >> 8;
+      blue[i] = aGammaRamp[2][i] >> 8;
+    }
+  }
+  */
+}
+
+FX_ENTRY void FX_CALL
+guGammaCorrectionRGB( FxFloat gammaR, FxFloat gammaG, FxFloat gammaB )
+{
+  LOG("guGammaCorrectionRGB()\r\n");
+  if (!fullscreen)
+    return;
+  FxU16 aGammaRamp[3][256];
+  for (int i = 0; i < 256; i++)
+  {
+    aGammaRamp[0][i] = (((FxU16)((pow(i/255.0F, 1.0F/gammaR)) * 255.0F + 0.5F)) << 8) & 0xFFFF;
+    aGammaRamp[1][i] = (((FxU16)((pow(i/255.0F, 1.0F/gammaG)) * 255.0F + 0.5F)) << 8) & 0xFFFF;
+    aGammaRamp[2][i] = (((FxU16)((pow(i/255.0F, 1.0F/gammaB)) * 255.0F + 0.5F)) << 8) & 0xFFFF;
+  }
+  CorrectGamma(aGammaRamp);
+}
+
+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
+#ifdef VPDEBUG
+int dumping = 0;
+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<nb_fb; i++) {
+    dump_tex(fbs[i].texid);
+  }
+  dump_tex(default_texture);
+  dump_tex(depth_texture);
+
+  dumping = 0;
+
+  glReadBuffer(GL_FRONT);
+  glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, frameBuffer);
+  ilTexImage(width, height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, frameBuffer);
+  ilSaveImage("dump/framecolor.png");
+  glReadPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, depthBuffer);
+  //   FILE * fp = fopen("glide_depth1.bin", "rb");
+  //   fread(depthBuffer, 2, width*height, fp);
+  //   fclose(fp);
+  for (j=0; j<height; j++) {
+    for (i=0; i<width; i++) {
+      //uint16_t d = ( (uint16_t *)depthBuffer )[i+(height-1-j)*width]/2 + 0x8000;
+      uint16_t d = ( (uint16_t *)depthBuffer )[i+j*width];
+      uint32_t c = ( (uint32_t *)frameBuffer )[i+j*width];
+      ( (unsigned char *)frameBuffer )[(i+j*width)*3] = d&0xff;
+      ( (unsigned char *)frameBuffer )[(i+j*width)*3+1] = d>>8;
+      ( (unsigned char *)frameBuffer )[(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<tl_i; i++) {
+    glBindTexture(GL_TEXTURE_2D, tl[i]);
+    GLint w, h, 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, &fmt);
+    fprintf(stderr, "Texture %d %dx%d fmt %x\n", tl[i], (int)w, (int)h, (int) fmt);
+
+    uint32_t * pixels = (uint32_t *) malloc(w*h*4);
+    // 0x1902 is another constant meaning GL_DEPTH_COMPONENT
+    // (but isn't defined in gl's headers !!)
+    if (fmt != GL_DEPTH_COMPONENT && fmt != 0x1902) {
+      glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+      ilTexImage(w, h, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, pixels);
+    } else {
+      glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, pixels);
+      int i;
+      for (i=0; i<w*h; i++)
+        ((unsigned char *)frameBuffer)[i] = ((unsigned short *)pixels)[i]/256;
+      ilTexImage(w, h, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, frameBuffer);
+    }
+    char name[128];
+    //     sprintf(name, "mkdir -p dump ; rm -f dump/tex%04d.png", i);
+    //     system(name);
+    sprintf(name, "dump/tex%04d.png", i);
+    fprintf(stderr, "Writing '%s'\n", name);
+    ilSaveImage(name);
+
+    //     SDL_FreeSurface(surf);
+    free(pixels);
+  }
+  glBindTexture(GL_TEXTURE_2D, default_texture);
+}
+
+void dump_tex(int id)
+{
+  if (!dumping) return;
+
+  int n;
+  // yes, it's inefficient
+  for (n=0; n<tl_i; n++)
+    if (tl[n] == id)
+      return;
+
+  tl[tl_i++] = id;
+
+  int i = tl_i-1;
+}
+
+#endif
diff --git a/source/gles2glide64/src/Glitch64/inc/3dfx.h b/source/gles2glide64/src/Glitch64/inc/3dfx.h
new file mode 100644 (file)
index 0000000..40fa672
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+** 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__
+
+/*
+** 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 __declspec(dllexport) 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(__APPLE__)
+#  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 */
+#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/source/gles2glide64/src/Glitch64/inc/g3ext.h b/source/gles2glide64/src/Glitch64/inc/g3ext.h
new file mode 100644 (file)
index 0000000..ebb1682
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+** 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
+*/
+
+/*
+** H3EXT.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 __H3EXT_H__
+#define __H3EXT_H__
+
+#include <3dfx.h>
+#include <glidesys.h>
+#include <sst1vid.h>
+
+#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 <glideutl.h>
+
+#endif /* __H3EXT_H__ */
diff --git a/source/gles2glide64/src/Glitch64/inc/glide.h b/source/gles2glide64/src/Glitch64/inc/glide.h
new file mode 100644 (file)
index 0000000..f79f5cf
--- /dev/null
@@ -0,0 +1,950 @@
+/*
+** 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 <glidesys.h>
+#include <sst1vid.h>
+
+#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)();
+
+#ifndef WIN32
+typedef int HWND;
+#endif
+
+/*
+** -----------------------------------------------------------------------
+** 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(
+          HWND                 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( 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 <glideutl.h>
+
+#endif /* __GLIDE_H__ */
diff --git a/source/gles2glide64/src/Glitch64/inc/glidesys.h b/source/gles2glide64/src/Glitch64/inc/glidesys.h
new file mode 100644 (file)
index 0000000..b19845a
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+** 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__)
+#  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) || defined(__APPLE__)
+#  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/source/gles2glide64/src/Glitch64/inc/glideutl.h b/source/gles2glide64/src/Glitch64/inc/glideutl.h
new file mode 100644 (file)
index 0000000..16c6e32
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+** 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/source/gles2glide64/src/Glitch64/inc/sst1vid.h b/source/gles2glide64/src/Glitch64/inc/sst1vid.h
new file mode 100644 (file)
index 0000000..d76e714
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+** 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/source/gles2glide64/src/Glitch64/m64p.h b/source/gles2glide64/src/Glitch64/m64p.h
new file mode 100644 (file)
index 0000000..59bc28a
--- /dev/null
@@ -0,0 +1,43 @@
+/******************************************************************************
+ * 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
+
+#include "m64p_types.h"
+#include "m64p_config.h"
+#include "m64p_vidext.h"
+
+extern ptr_ConfigOpenSection      ConfigOpenSection;
+extern ptr_ConfigGetParamInt      ConfigGetParamInt;
+extern ptr_ConfigGetParamBool     ConfigGetParamBool;
+
+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/source/gles2glide64/src/Glitch64/main.h b/source/gles2glide64/src/Glitch64/main.h
new file mode 100644 (file)
index 0000000..f213fe9
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MAIN_H
+#define MAIN_H
+
+#include <m64p_types.h>
+
+#define LOG(...) // WriteLog(M64MSG_VERBOSE, __VA_ARGS__)
+#define LOGINFO(...) WriteLog(M64MSG_INFO, __VA_ARGS__)
+void WriteLog(m64p_msg_level level, const char *msg, ...);
+
+
+#ifndef _WIN32
+//#define VPDEBUG
+#endif
+#ifdef VPDEBUG
+void dump_tex(int id);
+void dump_start();
+void dump_stop();
+extern int dumping;
+#endif
+
+#define zscale 1.0f
+
+typedef struct _wrapper_config
+{
+  int res;
+  int fbo;
+  int anisofilter;
+  int vram_size;
+} wrapper_config;
+extern wrapper_config config;
+
+
+// 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 ati_sucks;
+extern float largest_supported_anisotropy;
+
+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
+
+#ifdef _WIN32
+#include <windows.h>
+extern "C" {
+    #include <SDL_opengl.h>
+    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;
+    typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc);
+}
+#else
+#include <stdio.h>
+//#define printf(...)
+#define GL_GLEXT_PROTOTYPES
+#include <SDL_opengles2.h>
+#endif // _WIN32
+#include "glide.h"
+#include "glState.cpp"
+
+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);
+
+#ifdef _WIN32
+extern PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
+extern PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB;
+extern PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT;
+extern PFNGLFOGCOORDFPROC glFogCoordfEXT;
+
+extern PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
+extern PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
+extern PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
+extern PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
+extern PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
+extern PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
+extern PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
+extern PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
+extern PFNGLUNIFORM1IARBPROC glUniform1iARB;
+extern PFNGLUNIFORM4IARBPROC glUniform4iARB;
+extern PFNGLUNIFORM4FARBPROC glUniform4fARB;
+extern PFNGLUNIFORM1FARBPROC glUniform1fARB;
+extern PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
+extern PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
+extern PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
+extern PFNGLSECONDARYCOLOR3FPROC glSecondaryColor3f;
+#endif
+void check_compile(GLuint shader);
+void check_link(GLuint program);
+void vbo_enable();
+void vbo_disable();
+
+//Vertex Attribute Locations
+#define POSITION_ATTR 0
+#define COLOUR_ATTR 1
+#define TEXCOORD_0_ATTR 2
+#define TEXCOORD_1_ATTR 3
+#define FOG_ATTR 4
+
+extern int w_buffer_mode;
+extern int 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 TMU_SIZE;
+
+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, nvidia_viewport_hack;
+extern int UMAmode;
+
+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();
+void disable_textureSizes();
+
+// config functions
+
+//FX_ENTRY void FX_CALL grConfigWrapperExt(HINSTANCE instance, HWND hwnd);
+FX_ENTRY void FX_CALL grConfigWrapperExt(FxI32, FxI32, FxBool, FxBool);
+FX_ENTRY GrScreenResolution_t FX_CALL grWrapperFullScreenResolutionExt(FxU32*, FxU32*);
+FX_ENTRY char ** FX_CALL grQueryResolutionsExt(FxI32*);
+FX_ENTRY FxBool FX_CALL grKeyPressedExt(FxU32 key);
+FX_ENTRY void FX_CALL grGetGammaTableExt(FxU32, FxU32*, FxU32*, FxU32*);
+
+int getFullScreenWidth();
+int getFullScreenHeight();
+
+// 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);
+
+#define CHECK_FRAMEBUFFER_STATUS() \
+{\
+ GLenum status; \
+ status = glCheckFramebufferStatus(GL_FRAMEBUFFER); \
+ /*display_warning("%x\n", status);*/\
+ switch(status) { \
+ case GL_FRAMEBUFFER_COMPLETE: \
+   /*display_warning("framebuffer complete!\n");*/\
+   break; \
+ case GL_FRAMEBUFFER_UNSUPPORTED: \
+   display_warning("framebuffer GL_FRAMEBUFFER_UNSUPPORTED_EXT\n");\
+    /* you gotta choose different formats */ \
+   /*assert(0);*/ \
+   break; \
+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: \
+   display_warning("framebuffer INCOMPLETE_ATTACHMENT\n");\
+   break; \
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: \
+   display_warning("framebuffer FRAMEBUFFER_MISSING_ATTACHMENT\n");\
+   break; \
+ case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: \
+   display_warning("framebuffer FRAMEBUFFER_DIMENSIONS\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(const char *text, ...);
+#else // LOGGING
+#define OPEN_LOG()
+#define CLOSE_LOG()
+//#define LOG
+#endif // LOGGING
+
+#endif
diff --git a/source/gles2glide64/src/Glitch64/textures.cpp b/source/gles2glide64/src/Glitch64/textures.cpp
new file mode 100755 (executable)
index 0000000..298d59c
--- /dev/null
@@ -0,0 +1,1231 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifdef _WIN32
+#include <windows.h>
+#else // _WIN32
+#include <stdlib.h>
+#endif // _WIN32
+#include "glide.h"
+#include "main.h"
+#include <stdio.h>
+
+#include "../Glide64/ticks.h"
+
+/* 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
+
+int TMU_SIZE = 8*2048*2048;
+static unsigned char* texture = NULL;
+
+int packed_pixels_support = -1;
+int ati_sucks = -1;
+float largest_supported_anisotropy = 1.0f;
+
+#ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+#endif
+
+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);
+
+#define TEXBSP
+#ifdef TEXBSP
+typedef struct _texbsp
+{
+  unsigned int id;
+  struct _texbsp *left;
+  struct _texbsp *right;
+} texbsp;
+
+static int nbTex = 0;
+static texbsp *list = NULL;
+#elif defined(TEXREDBLACK)
+typedef struct _texbsp
+{
+  unsigned int id;
+  int color;
+  struct _texbsp *left;
+  struct _texbsp *right;
+  struct _texbsp *parent;
+} texbsp;
+
+static int nbTex = 0;
+static texbsp *list = NULL;
+#else
+typedef struct _texlist
+{
+  unsigned int id;
+  struct _texlist *next;
+} texlist;
+
+static int nbTex = 0;
+static texlist *list = NULL;
+#endif
+
+#ifdef _WIN32
+extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT;
+extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
+extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB;
+#endif
+#ifdef TEXREDBLACK
+// utilitie function for red-black tree
+// taken from Wikipedia
+// http://en.wikipedia.org/wiki/Red-black_tree
+#define BLACK  0
+#define RED            1
+//**** Family stuff ****
+texbsp *grandparent(texbsp *n)
+{
+ if ((n != NULL) && (n->parent != NULL))
+  return n->parent->parent;
+ else
+  return NULL;
+}
+texbsp *sibling(texbsp *n) 
+{
+ if ((n != NULL) && (n->parent != NULL))
+  if (n == n->parent->left)
+    return n->parent->right;
+  else
+    return n->parent->left;
+ else
+       return NULL;
+}
+texbsp *uncle(texbsp *n)
+{
+ texbsp *g = grandparent(n);
+ if (g == NULL)
+  return NULL; // No grandparent means no uncle
+ if (n->parent == g->left)
+  return g->right;
+ else
+  return g->left;
+}
+//**** Search functions ****
+texbsp* lookup_node(GLuint key) 
+{
+ texbsp* n = texlist;
+ while (n != NULL) {
+  int comp_result = (int)key - (int)n->id;
+  if (comp_result == 0) {
+   return n;
+  } else if (comp_result < 0) {
+   n = n->left;
+  } else {
+   n = n->right;
+  }
+ }
+ return n;
+}
+GLuint rbtree_lookup(GLuint key) 
+{
+ texbsp* n = lookup_node(key);
+ return n == NULL ? NULL : n->id;
+}
+//**** Basic insertion / replace ****
+texbsp* new_node(GLuint id, int node_color, texbsp* left, texbsp* right) 
+{
+  texbsp* result = malloc(sizeof(texbsp));
+  result->id = id;
+  result->color = node_color;
+  result->left = left;
+  result->right = right;
+  if (left  != NULL)  left->parent = result;
+  if (right != NULL) right->parent = result;
+  result->parent = NULL;
+  return result;
+}
+void replace_node(texbsp* oldn, texbsp* newn) 
+{
+ if (oldn->parent == NULL) {
+  list = newn;
+ } else {
+  if (oldn == oldn->parent->left)
+   oldn->parent->left = newn;
+  else
+   oldn->parent->right = newn;
+ }
+ if (newn != NULL) {
+  newn->parent = oldn->parent;
+ }
+}
+//**** Rotation functions ****
+void rotate_left(texbsp* n) 
+{
+ texbsp* r = n->right;
+ replace_node(n, r);
+ n->right = r->left;
+ if (r->left != NULL) {
+  r->left->parent = n;
+ }
+ r->left = n;
+ n->parent = r;
+}
+void rotate_right(texbsp* n) 
+{
+ node L = n->left;
+ replace_node(n, L);
+ n->left = L->right;
+ if (L->right != NULL) {
+  L->right->parent = n;
+ }
+ L->right = n;
+ n->parent = L;
+}
+//**** Insertion cases ****
+void insert_case1(texbsp *n)
+{
+ if (n->parent == NULL)
+  n->color = BLACK;
+ else
+  insert_case2(n);
+}
+void insert_case2(texbsp *n)
+{
+ if (n->parent->color == BLACK)
+  return; 
+ else
+  insert_case3(n);
+}
+void insert_case3(texbsp *n)
+{
+ texbsp *u = uncle(n), *g;
+ if ((u != NULL) && (u->color == RED)) {
+  n->parent->color = BLACK;
+  u->color = BLACK;
+  g = grandparent(n);
+  g->color = RED;
+  insert_case1(g);
+ } else {
+  insert_case4(n);
+ }
+}
+void insert_case4(texbsp *n)
+{
+ texbsp *g = grandparent(n);
+ if ((n == n->parent->right) && (n->parent == g->left)) {
+  rotate_left(n->parent);
+  n = n->left; 
+ } else if ((n == n->parent->left) && (n->parent == g->right)) {
+  rotate_right(n->parent);
+  n = n->right; 
+ }
+ insert_case5(n);
+}
+void insert_case5(texbsp *n)
+{
+ struct node *g = grandparent(n);
+ n->parent->color = BLACK;
+ g->color = RED;
+ if (n == n->parent->left)
+  rotate_right(g);
+ else
+  rotate_left(g);
+}
+void rbtree_insert(GLuint key) 
+{
+ texbsp* inserted_node = new_node(key, RED, NULL, NULL);
+ if (list == NULL) {
+  list = inserted_node;
+ } else {
+  texbsp* n = t->root;
+  while (1) {
+   int comp_result = (int)key - (int)n->id;
+   if (comp_result == 0) {
+    free (inserted_node);
+    return;
+   } else if (comp_result < 0) {
+    if (n->left == NULL) {
+     n->left = inserted_node;
+     break;
+    } else {
+     n = n->left;
+    }
+   } else {
+    if (n->right == NULL) {
+     n->right = inserted_node;
+     break;
+    } else {
+     n = n->right;
+    }
+   }
+  }
+  inserted_node->parent = n;
+ }
+ insert_case1(t, inserted_node);
+}
+//**** Removing cases ****
+
+#endif
+void remove_tex(unsigned int idmin, unsigned int idmax)
+{
+#ifdef TEXBSP
+       GLuint texlist[nbTex];
+       int     nbdel = 0;
+       // 1st look at initial point that is <= at idmin and than go right until id > idmax. Deleting all in between, and reattach list is needed
+       texbsp *aux = list;
+       bool reattach = false;
+       texbsp *debut, *fin, *temp;
+       // Empty list, easy
+       if (list==NULL) return;
+       if ((idmin==0x00000000) && (idmax==0xffffffff)) {
+               // delete everything, quite easy
+               debut = list->right;
+               fin = list->left;
+               while ((debut) && (fin)) {
+                       if (debut) {
+                               texlist[nbdel++]=debut->id;
+                               temp = debut->right;
+                               free(debut);
+                               debut = temp;
+                       }
+                       if (fin) {
+                               texlist[nbdel++]=fin->id;
+                               temp = fin->left;
+                               free(fin);
+                               fin = temp;
+                       }
+               }
+               texlist[nbdel++]=list->id;
+               free(list);
+               list=NULL;
+               glDeleteTextures(nbdel, texlist);
+               nbTex = 0;
+               return;
+       }
+       // General case, range delete
+       // find starting point.
+       debut = list;
+       while ((debut->id > idmin) && (debut->right!=NULL)) {
+          debut = debut->right;
+       }
+       while ((debut->left!=NULL) && (debut->left->id < idmin)) {
+               debut = debut->left;
+       }
+       fin = debut->right;
+       // and now delete
+       while ((debut!=NULL) && (debut->id >= idmin) && (debut->id < idmax))
+       {
+               temp = debut->left;
+               texlist[nbdel++]=debut->id;
+               free(debut);
+               debut=temp;
+       }
+       // rechain the list
+       if (fin) fin->left = debut;
+       if (debut) debut->right = fin;
+       if (debut) list = debut; else list = fin;               //change ankor
+       glDeleteTextures(nbdel, texlist);
+       nbTex -= nbdel;
+       return;
+#else
+  unsigned int *t;
+  int n = 0;
+  texlist *aux = list;
+  int sz = nbTex;
+  if (aux == NULL) return;
+  t = (unsigned int*)malloc(sz * sizeof(int));
+  while (aux && aux->id >= idmin && aux->id < idmax)
+  {
+    if (n >= sz)
+      t = (unsigned int *) 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 = (unsigned int *) 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);
+#endif
+}
+
+
+void add_tex(unsigned int id)
+{
+#ifdef TEXBSP
+//printf("add_tex(%u)\n", id);
+ if (list == NULL) {
+//printf("add root\n");
+       list = (texbsp*)malloc(sizeof(texbsp));
+       list->left = NULL; list->right = NULL;
+       list->id = id;
+       nbTex++;
+       return;
+ }
+ texbsp *bsp = list;
+ if (bsp->id>=id) {    // go left
+// printf("Go left\n");
+       while ((bsp->left!=NULL) && (bsp->left->id > id))
+       {
+               bsp=bsp->left;
+       }
+       if (bsp->id = id) return;
+       texbsp *aux = bsp->left;
+       texbsp *ins = (texbsp*)malloc(sizeof(texbsp)); 
+       ins->left = aux;
+       ins->right = bsp;
+       ins->id = id;
+       bsp->left = ins;
+       if (aux) aux->right = ins;
+       nbTex++;
+       list=bsp;       // new ankor
+       return;
+ } else {                      // go right
+//printf("Go right\n");
+       while ((bsp->right!=NULL) && (bsp->right->id < id))
+       {
+//printf("right\n");
+               bsp=bsp->right;
+       }
+//printf("stopped at %u\n", bsp->id);
+       if (bsp->id = id) return;
+       texbsp *aux = bsp->right;
+       texbsp *ins = (texbsp*)malloc(sizeof(texbsp)); 
+       ins->right = aux;
+       ins->left = bsp;
+       ins->id = id;
+       bsp->right = ins;
+       if (aux) aux->left = ins;
+       nbTex++;
+       list=bsp;       // new ankor
+       return;
+ }
+#else
+  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;
+#endif
+}
+
+void init_textures()
+{
+  tex0_width = tex0_height = tex1_width = tex1_height = 2;
+  // ZIGGY because remove_tex 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;
+
+  if (!texture)        texture = (unsigned char*)malloc(2048*2048*4);
+}
+
+void free_textures()
+{
+#ifndef WIN32
+  // ZIGGY for some reasons, Pj64 doesn't like remove_tex on exit
+  remove_tex(0x00000000, 0xFFFFFFFF);
+#endif
+  if (texture != NULL) {
+    free(texture);
+    texture = NULL;
+  }
+}
+
+FX_ENTRY FxU32 FX_CALL
+grTexMinAddress( GrChipID_t tmu )
+{
+  LOG("grTexMinAddress(%d)\r\n", tmu);
+  if (UMAmode)
+    return 0;
+  else
+    return tmu*TMU_SIZE;
+}
+
+FX_ENTRY FxU32 FX_CALL
+grTexMaxAddress( GrChipID_t tmu )
+{
+  LOG("grTexMaxAddress(%d)\r\n", tmu);
+  if (UMAmode)
+    return TMU_SIZE*2 - 1;
+  else
+    return tmu*TMU_SIZE + TMU_SIZE - 1;
+}
+
+FX_ENTRY FxU32 FX_CALL
+grTexTextureMemRequired( FxU32     evenOdd,
+                        GrTexInfo *info   )
+{
+  int width, height;
+  LOG("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_INTENSITY_8: // I8 support - H.Morii
+  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)<<1;
+    break;
+  case GR_TEXFMT_ARGB_8888:
+    return (width*height)<<2;
+    break;
+  case GR_TEXFMT_ARGB_CMP_DXT1:  // FXT1,DXT1,5 support - H.Morii
+    return ((((width+0x3)&~0x3)*((height+0x3)&~0x3))>>1);
+  case GR_TEXFMT_ARGB_CMP_DXT3:
+    return ((width+0x3)&~0x3)*((height+0x3)&~0x3);
+  case GR_TEXFMT_ARGB_CMP_DXT5:
+    return ((width+0x3)&~0x3)*((height+0x3)&~0x3);
+  case GR_TEXFMT_ARGB_CMP_FXT1:
+    return ((((width+0x7)&~0x7)*((height+0x3)&~0x3))>>1);
+  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;
+  LOG("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_INTENSITY_8: // I8 support - H.Morii
+  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)<<1;
+    break;
+  case GR_TEXFMT_ARGB_8888:
+    return (width*height)<<2;
+    break;
+  case GR_TEXFMT_ARGB_CMP_DXT1:  // FXT1,DXT1,5 support - H.Morii
+    return ((((width+0x3)&~0x3)*((height+0x3)&~0x3))>>1);
+  case GR_TEXFMT_ARGB_CMP_DXT3:
+    return ((width+0x3)&~0x3)*((height+0x3)&~0x3);
+  case GR_TEXFMT_ARGB_CMP_DXT5:
+    return ((width+0x3)&~0x3)*((height+0x3)&~0x3);
+  case GR_TEXFMT_ARGB_CMP_FXT1:
+    return ((((width+0x7)&~0x7)*((height+0x3)&~0x3))>>1);
+  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:
+  case GR_TEXFMT_INTENSITY_8: // I8 support - H.Morii
+    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;
+  case GR_TEXFMT_ARGB_CMP_DXT1:  // FXT1,DXT1,5 support - H.Morii
+    factor = 8;                  // HACKALERT: factor holds block bytes
+    break;
+  case GR_TEXFMT_ARGB_CMP_DXT3:  // FXT1,DXT1,5 support - H.Morii
+    factor = 16;                  // HACKALERT: factor holds block bytes
+    break;
+  case GR_TEXFMT_ARGB_CMP_DXT5:
+    factor = 16;
+    break;
+  case GR_TEXFMT_ARGB_CMP_FXT1:
+    factor = 8;
+    break;
+  default:
+    display_warning("grTexFormatSize : unknown texture format: %x", fmt);
+  }
+  return factor;
+}
+
+int grTexFormat2GLPackedFmt(int fmt, int * gltexfmt, int * glpixfmt, int * glpackfmt)
+{
+    *gltexfmt = GL_RGBA;
+    *glpixfmt = GL_RGBA;
+    *glpackfmt = GL_UNSIGNED_BYTE;
+    return 0;
+/*
+  int factor = -1;
+  switch(fmt) {
+  case GR_TEXFMT_ALPHA_8:
+    factor = 1;
+    *gltexfmt = GL_INTENSITY8;
+    *glpixfmt = GL_LUMINANCE;
+    *glpackfmt = GL_UNSIGNED_BYTE;
+    break;
+  case GR_TEXFMT_INTENSITY_8: // I8 support - H.Morii
+    factor = 1;
+    *gltexfmt = GL_LUMINANCE8;
+    *glpixfmt = GL_LUMINANCE;
+    *glpackfmt = GL_UNSIGNED_BYTE;
+    break;
+  case GR_TEXFMT_ALPHA_INTENSITY_44:
+    break;
+  case GR_TEXFMT_RGB_565:
+    factor = 2;
+    *gltexfmt = GL_RGB;
+    *glpixfmt = GL_RGB;
+    *glpackfmt = GL_UNSIGNED_SHORT_5_6_5;
+    break;
+  case GR_TEXFMT_ARGB_1555:
+    if (ati_sucks > 0) return -1; // ATI sucks as usual (fixes slowdown on ATI)
+    factor = 2;
+    *gltexfmt = GL_RGB5_A1;
+    *glpixfmt = GL_BGRA;
+    *glpackfmt = GL_UNSIGNED_SHORT_1_5_5_5_REV;
+    break;
+  case GR_TEXFMT_ALPHA_INTENSITY_88:
+    factor = 2;
+    *gltexfmt = GL_LUMINANCE8_ALPHA8;
+    *glpixfmt = GL_LUMINANCE_ALPHA;
+    *glpackfmt = GL_UNSIGNED_BYTE;
+    break;
+  case GR_TEXFMT_ARGB_4444:
+    factor = 2;
+    *gltexfmt = GL_RGBA4;
+    *glpixfmt = GL_BGRA;
+    *glpackfmt = GL_UNSIGNED_SHORT_4_4_4_4_REV;
+    break;
+  case GR_TEXFMT_ARGB_8888:
+    factor = 4;
+    *gltexfmt = GL_RGBA8;
+    *glpixfmt = GL_BGRA;
+    *glpackfmt = GL_UNSIGNED_INT_8_8_8_8_REV;
+    break;
+  case GR_TEXFMT_ARGB_CMP_DXT1:  // FXT1,DXT1,5 support - H.Morii
+    // HACKALERT: 3Dfx Glide uses GR_TEXFMT_ARGB_CMP_DXT1 for both opaque DXT1 and DXT1 with 1bit alpha.
+    // GlideHQ compiled with GLIDE64_DXTN option enabled, uses opaqe DXT1 only.
+    factor = 8; // HACKALERT: factor holds block bytes
+    *gltexfmt = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; // these variables aren't used
+    *glpixfmt = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+    *glpackfmt = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+    break;
+  case GR_TEXFMT_ARGB_CMP_DXT3:
+    factor = 16;
+    *gltexfmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+    *glpixfmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+    *glpackfmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+    break;
+  case GR_TEXFMT_ARGB_CMP_DXT5:
+    factor = 16;
+    *gltexfmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+    *glpixfmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+    *glpackfmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+    break;
+  case GR_TEXFMT_ARGB_CMP_FXT1:
+    factor = 8;
+    *gltexfmt = GL_COMPRESSED_RGBA_FXT1_3DFX;
+    *glpixfmt = GL_COMPRESSED_RGBA_FXT1_3DFX;
+    *glpackfmt = GL_COMPRESSED_RGBA_FXT1_3DFX; // XXX: what should we do about GL_COMPRESSED_RGB_FXT1_3DFX?
+    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;
+  int factor;
+  int glformat = 0;
+  int gltexfmt, glpixfmt, glpackfmt;
+  LOG("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)
+    factor = -1;
+  else
+    factor = grTexFormat2GLPackedFmt(info->format, &gltexfmt, &glpixfmt, &glpackfmt);
+
+  if (factor < 0) {
+
+    // 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
+    register int n = 0, m = 0;
+    switch(info->format)
+    {
+    case GR_TEXFMT_ALPHA_8:
+      for (i=0; i<height; i++)
+      {
+        for (j=0; j<width; j++)
+        {
+          unsigned int texel = (unsigned int)((unsigned char*)info->data)[m];
+          texel |= (texel << 8);
+          texel |= (texel << 16);
+          ((unsigned int*)texture)[n] = texel;
+          m++;
+          n++;
+        }
+      }
+      factor = 1;
+      glformat = GL_RGBA;
+      break;
+    case GR_TEXFMT_INTENSITY_8: // I8 support - H.Morii
+      for (i=0; i<height; i++)
+      {
+        for (j=0; j<width; j++)
+        {
+          unsigned int texel = (unsigned int)((unsigned char*)info->data)[m];
+          texel |= (0xFF000000 | (texel << 16) | (texel << 8));
+          ((unsigned int*)texture)[n] = texel;
+          m++;
+          n++;
+        }
+      }
+      factor = 1;
+      glformat = GL_ALPHA;
+      break;
+    case GR_TEXFMT_ALPHA_INTENSITY_44:
+#if 1
+      for (i=0; i<height; i++)
+      {
+        for (j=0; j<width; j++)
+        {
+          unsigned int texel = (unsigned int)((unsigned char*)info->data)[m];
+#if 1
+          /* accurate conversion */
+          unsigned int texel_hi = (texel & 0x000000F0) << 20;
+          unsigned int texel_low = texel & 0x0000000F;
+          texel_low |= (texel_low << 4);
+          texel_hi |= ((texel_hi << 4) | (texel_low << 16) | (texel_low << 8) | texel_low);
+#else
+          unsigned int texel_hi = (texel & 0x000000F0) << 24;
+          unsigned int texel_low = (texel & 0x0000000F) << 4;
+          texel_hi |= ((texel_low << 16) | (texel_low << 8) | texel_low);
+#endif
+          ((unsigned int*)texture)[n] = texel_hi;
+          m++;
+          n++;
+        }
+      }
+      factor = 1;
+      glformat = GL_LUMINANCE_ALPHA;
+#endif
+      break;
+    case GR_TEXFMT_RGB_565:
+      for (i=0; i<height; i++)
+      {
+        for (j=0; j<width; j++)
+        {
+          unsigned int texel = (unsigned int)((unsigned short*)info->data)[m];
+          unsigned int B = texel & 0x0000F800;
+          unsigned int G = texel & 0x000007E0;
+          unsigned int R = texel & 0x0000001F;
+#if 0
+          /* accurate conversion */
+          ((unsigned int*)texture)[n] = 0xFF000000 | (R << 19) | ((R >> 2) << 16) | (G << 5) | ((G >> 9) << 8) | (B >> 8) | (B >> 13);
+#else
+          ((unsigned int*)texture)[n] = 0xFF000000 | (R << 19) | (G << 5) | (B >> 8);
+#endif
+          m++;
+          n++;
+        }
+      }
+      factor = 2;
+      glformat = GL_RGB;
+      break;
+    case GR_TEXFMT_ARGB_1555:
+      for (i=0; i<height; i++)
+      {
+        for (j=0; j<width; j++)
+        {
+          unsigned int texel = (unsigned int)((unsigned short*)info->data)[m];
+          unsigned int A = texel & 0x00008000 ? 0xFF000000 : 0;
+          unsigned int B = texel & 0x00007C00;
+          unsigned int G = texel & 0x000003E0;
+          unsigned int R = texel & 0x0000001F;
+#if 0
+          /* accurate conversion */
+          ((unsigned int*)texture)[n] = A | (R << 19) | ((R >> 2) << 16) | (G << 6) | ((G >> 8) << 8) | (B >> 7) | (B >> 12);
+#else
+          ((unsigned int*)texture)[n] = A | (R << 19) | (G << 6) | (B >> 7);
+#endif
+          m++;
+          n++;
+        }
+      }
+      factor = 2;
+      glformat = GL_RGBA;
+      break;
+    case GR_TEXFMT_ALPHA_INTENSITY_88:
+      for (i=0; i<height; i++)
+      {
+        for (j=0; j<width; j++)
+        {
+          unsigned int AI = (unsigned int)((unsigned short*)info->data)[m];
+          unsigned int I = (unsigned int)(AI & 0x000000FF);
+          ((unsigned int*)texture)[n] = (AI << 16) | (I << 8) | I;
+          m++;
+          n++;
+        }
+      }
+      factor = 2;
+      glformat = GL_LUMINANCE_ALPHA;
+      break;
+    case GR_TEXFMT_ARGB_4444:
+
+      for (i=0; i<height; i++)
+      {
+        for (j=0; j<width; j++)
+        {
+          unsigned int texel = (unsigned int)((unsigned short*)info->data)[m];
+          unsigned int A = texel & 0x0000F000;
+          unsigned int B = texel & 0x00000F00;
+          unsigned int G = texel & 0x000000F0;
+          unsigned int R = texel & 0x0000000F;
+#if 0
+          /* accurate conversion */
+          ((unsigned int*)texture)[n] = (A << 16) | (A << 12) | (R << 20) | (R << 16) | (G << 8) | (G << 4) | (B >> 4) | (B >> 8);
+#else
+          ((unsigned int*)texture)[n] = (A << 16) | (R << 20) | (G << 8) | (B >> 4);
+#endif
+          m++;
+          n++;
+        }
+      }
+      factor = 2;
+      glformat = GL_RGBA;
+      break;
+    case GR_TEXFMT_ARGB_8888:
+      for (i=0; i<height; i++)
+      {
+        for (j=0; j<width; j++)
+        {
+          unsigned int texel = ((unsigned int*)info->data)[m];
+          unsigned int A = texel & 0xFF000000;
+          unsigned int B = texel & 0x00FF0000;
+          unsigned int G = texel & 0x0000FF00;
+          unsigned int R = texel & 0x000000FF;
+          ((unsigned int*)texture)[n] = A | (R << 16) | G | (B >> 16);
+          m++;
+          n++;
+        }
+      }
+      factor = 4;
+      glformat = GL_RGBA;
+      break;
+/*
+    case GR_TEXFMT_ARGB_CMP_DXT1: // FXT1,DXT1,5 support - H.Morii
+      factor = 8;                 // HACKALERT: factor holds block bytes
+      glformat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+      break;
+    case GR_TEXFMT_ARGB_CMP_DXT3: // FXT1,DXT1,5 support - H.Morii
+      factor = 16;                 // HACKALERT: factor holds block bytes
+      glformat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+      break;
+    case GR_TEXFMT_ARGB_CMP_DXT5:
+      factor = 16;
+      glformat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+      break;
+    case GR_TEXFMT_ARGB_CMP_FXT1:
+      factor = 8;
+      glformat = GL_COMPRESSED_RGBA_FXT1_3DFX;
+      break;
+*/
+    default:
+      display_warning("grTexDownloadMipMap : unknown texture format: %x", info->format);
+      factor = 0;
+    }
+  }
+
+  if (nbTextureUnits <= 2)
+    glActiveTexture(GL_TEXTURE1);
+  else
+    glActiveTexture(GL_TEXTURE2);
+
+  switch(info->format)
+  {
+  case GR_TEXFMT_ARGB_CMP_DXT1:
+  case GR_TEXFMT_ARGB_CMP_DXT3:
+  case GR_TEXFMT_ARGB_CMP_DXT5:
+  case GR_TEXFMT_ARGB_CMP_FXT1:
+    remove_tex(startAddress+1, startAddress+1+((width*height*factor)>>4));
+    break;
+  default:
+    remove_tex(startAddress+1, startAddress+1+(width*height*factor));
+  }
+
+  add_tex(startAddress+1);
+  glBindTexture(GL_TEXTURE_2D, startAddress+1);
+
+  if (largest_supported_anisotropy > 1.0f)
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy);
+
+  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
+/*
+  switch(info->format)
+  {
+  case GR_TEXFMT_ARGB_CMP_DXT1:
+  case GR_TEXFMT_ARGB_CMP_DXT3:
+  case GR_TEXFMT_ARGB_CMP_DXT5:
+  case GR_TEXFMT_ARGB_CMP_FXT1:
+    glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, (glformat ? glformat : gltexfmt), width, height, 0, (width*height*factor)>>4, info->data);
+    break;
+  default:
+    if (glformat) {
+      glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
+    } else
+      glTexImage2D(GL_TEXTURE_2D, 0, gltexfmt, width, height, 0, glpixfmt, glpackfmt, info->data);
+  }
+*/
+
+  glBindTexture(GL_TEXTURE_2D, default_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 )
+{
+  LOG("grTexSource(%d,%d,%d)\r\n", tmu, startAddress, evenOdd);
+
+  if (tmu == GR_TMU1 || nbTextureUnits <= 2)
+  {
+    if (tmu == GR_TMU1 && nbTextureUnits <= 2) return;
+    glActiveTexture(GL_TEXTURE0);
+
+    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);
+  }
+  else
+  {
+    glActiveTexture(GL_TEXTURE1);
+
+    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(!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;
+    }
+  }
+
+#if 0
+  extern int auxbuffer;
+  static int oldbuffer;
+  FX_ENTRY void FX_CALL grAuxBufferExt( GrBuffer_t buffer );
+  if (auxbuffer == GR_BUFFER_AUXBUFFER && auxbuffer != oldbuffer)
+    grAuxBufferExt(auxbuffer);
+  oldbuffer = auxbuffer;
+#endif
+}
+
+FX_ENTRY void FX_CALL
+grTexDetailControl(
+                   GrChipID_t tmu,
+                   int lod_bias,
+                   FxU8 detail_scale,
+                   float detail_max
+                   )
+{
+  LOG("grTexDetailControl(%d,%d,%d,%d)\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);
+
+  set_lambda();
+}
+
+FX_ENTRY void FX_CALL
+grTexLodBiasValue(GrChipID_t tmu, float bias )
+{
+  LOG("grTexLodBiasValue(%d,%f)\r\n", tmu, bias);
+}
+
+FX_ENTRY void FX_CALL
+grTexFilterMode(
+                GrChipID_t tmu,
+                GrTextureFilterMode_t minfilter_mode,
+                GrTextureFilterMode_t magfilter_mode
+                )
+{
+  LOG("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;
+
+    glActiveTexture(GL_TEXTURE0);
+    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;
+
+    glActiveTexture(GL_TEXTURE1);
+    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
+               )
+{
+  LOG("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;
+      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;
+      break;
+    default:
+      display_warning("grTexClampMode : unknown t_clampmode : %x", t_clampmode);
+    }
+    glActiveTexture(GL_TEXTURE0);
+    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;
+      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;
+      break;
+    default:
+      display_warning("grTexClampMode : unknown t_clampmode : %x", t_clampmode);
+    }
+    glActiveTexture(GL_TEXTURE1);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s1);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t1);
+  }
+}
diff --git a/source/gles2glide64/src/Glitch64/textures.cpp.sav b/source/gles2glide64/src/Glitch64/textures.cpp.sav
new file mode 100755 (executable)
index 0000000..d779862
--- /dev/null
@@ -0,0 +1,963 @@
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002  Dave2001
+* Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifdef _WIN32
+#include <windows.h>
+#else // _WIN32
+#include <stdlib.h>
+#endif // _WIN32
+#include "glide.h"
+#include "main.h"
+#include <stdio.h>
+#include <string.h>
+
+/* 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
+
+int TMU_SIZE = 8*2048*2048;
+static unsigned char* texture = NULL;
+
+int packed_pixels_support = -1;
+int ati_sucks = -1;
+float largest_supported_anisotropy = 1.0f;
+
+#ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+#endif
+
+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;
+
+#ifdef _WIN32
+extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT;
+extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
+extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB;
+#endif
+void remove_tex(unsigned int idmin, unsigned int idmax)
+{
+  unsigned int *t;
+  int n = 0;
+  texlist *aux = list;
+  int sz = nbTex;
+  if (aux == NULL) return;
+  t = (unsigned int*)malloc(sz * sizeof(int));
+  while (aux && aux->id >= idmin && aux->id < idmax)
+  {
+    if (n >= sz)
+      t = (unsigned int *) 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 = (unsigned int *) 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 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 remove_tex 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;
+
+  if (!texture)        texture = (unsigned char*)malloc(2048*2048*4);
+}
+
+void free_textures()
+{
+#ifndef WIN32
+  // ZIGGY for some reasons, Pj64 doesn't like remove_tex on exit
+  remove_tex(0x00000000, 0xFFFFFFFF);
+#endif
+  if (texture != NULL) {
+    free(texture);
+    texture = NULL;
+  }
+}
+
+FX_ENTRY FxU32 FX_CALL
+grTexMinAddress( GrChipID_t tmu )
+{
+  LOG("grTexMinAddress(%d)\r\n", tmu);
+  if (UMAmode)
+    return 0;
+  else
+    return tmu*TMU_SIZE;
+}
+
+FX_ENTRY FxU32 FX_CALL
+grTexMaxAddress( GrChipID_t tmu )
+{
+  LOG("grTexMaxAddress(%d)\r\n", tmu);
+  if (UMAmode)
+    return TMU_SIZE*2 - 1;
+  else
+    return tmu*TMU_SIZE + TMU_SIZE - 1;
+}
+
+FX_ENTRY FxU32 FX_CALL
+grTexTextureMemRequired( FxU32     evenOdd,
+                        GrTexInfo *info   )
+{
+  int width, height;
+  LOG("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_INTENSITY_8: // I8 support - H.Morii
+  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)<<1;
+    break;
+  case GR_TEXFMT_ARGB_8888:
+    return (width*height)<<2;
+    break;
+  case GR_TEXFMT_ARGB_CMP_DXT1:  // FXT1,DXT1,5 support - H.Morii
+    return ((((width+0x3)&~0x3)*((height+0x3)&~0x3))>>1);
+  case GR_TEXFMT_ARGB_CMP_DXT3:
+    return ((width+0x3)&~0x3)*((height+0x3)&~0x3);
+  case GR_TEXFMT_ARGB_CMP_DXT5:
+    return ((width+0x3)&~0x3)*((height+0x3)&~0x3);
+  case GR_TEXFMT_ARGB_CMP_FXT1:
+    return ((((width+0x7)&~0x7)*((height+0x3)&~0x3))>>1);
+  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;
+  LOG("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_INTENSITY_8: // I8 support - H.Morii
+  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)<<1;
+    break;
+  case GR_TEXFMT_ARGB_8888:
+    return (width*height)<<2;
+    break;
+  case GR_TEXFMT_ARGB_CMP_DXT1:  // FXT1,DXT1,5 support - H.Morii
+    return ((((width+0x3)&~0x3)*((height+0x3)&~0x3))>>1);
+  case GR_TEXFMT_ARGB_CMP_DXT3:
+    return ((width+0x3)&~0x3)*((height+0x3)&~0x3);
+  case GR_TEXFMT_ARGB_CMP_DXT5:
+    return ((width+0x3)&~0x3)*((height+0x3)&~0x3);
+  case GR_TEXFMT_ARGB_CMP_FXT1:
+    return ((((width+0x7)&~0x7)*((height+0x3)&~0x3))>>1);
+  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:
+  case GR_TEXFMT_INTENSITY_8: // I8 support - H.Morii
+    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;
+  case GR_TEXFMT_ARGB_CMP_DXT1:  // FXT1,DXT1,5 support - H.Morii
+    factor = 8;                  // HACKALERT: factor holds block bytes
+    break;
+  case GR_TEXFMT_ARGB_CMP_DXT3:  // FXT1,DXT1,5 support - H.Morii
+    factor = 16;                  // HACKALERT: factor holds block bytes
+    break;
+  case GR_TEXFMT_ARGB_CMP_DXT5:
+    factor = 16;
+    break;
+  case GR_TEXFMT_ARGB_CMP_FXT1:
+    factor = 8;
+    break;
+  default:
+    display_warning("grTexFormatSize : unknown texture format: %x", fmt);
+  }
+  return factor;
+}
+
+int grTexFormat2GLPackedFmt(int fmt, int * gltexfmt, int * glpixfmt, int * glpackfmt)
+{
+    *gltexfmt = GL_RGBA;
+    *glpixfmt = GL_RGBA;
+    *glpackfmt = GL_UNSIGNED_BYTE;
+    return 0;
+/*
+  int factor = -1;
+  switch(fmt) {
+  case GR_TEXFMT_ALPHA_8:
+    factor = 1;
+    *gltexfmt = GL_INTENSITY8;
+    *glpixfmt = GL_LUMINANCE;
+    *glpackfmt = GL_UNSIGNED_BYTE;
+    break;
+  case GR_TEXFMT_INTENSITY_8: // I8 support - H.Morii
+    factor = 1;
+    *gltexfmt = GL_LUMINANCE8;
+    *glpixfmt = GL_LUMINANCE;
+    *glpackfmt = GL_UNSIGNED_BYTE;
+    break;
+  case GR_TEXFMT_ALPHA_INTENSITY_44:
+    break;
+  case GR_TEXFMT_RGB_565:
+    factor = 2;
+    *gltexfmt = GL_RGB;
+    *glpixfmt = GL_RGB;
+    *glpackfmt = GL_UNSIGNED_SHORT_5_6_5;
+    break;
+  case GR_TEXFMT_ARGB_1555:
+    if (ati_sucks > 0) return -1; // ATI sucks as usual (fixes slowdown on ATI)
+    factor = 2;
+    *gltexfmt = GL_RGB5_A1;
+    *glpixfmt = GL_BGRA;
+    *glpackfmt = GL_UNSIGNED_SHORT_1_5_5_5_REV;
+    break;
+  case GR_TEXFMT_ALPHA_INTENSITY_88:
+    factor = 2;
+    *gltexfmt = GL_LUMINANCE8_ALPHA8;
+    *glpixfmt = GL_LUMINANCE_ALPHA;
+    *glpackfmt = GL_UNSIGNED_BYTE;
+    break;
+  case GR_TEXFMT_ARGB_4444:
+    factor = 2;
+    *gltexfmt = GL_RGBA4;
+    *glpixfmt = GL_BGRA;
+    *glpackfmt = GL_UNSIGNED_SHORT_4_4_4_4_REV;
+    break;
+  case GR_TEXFMT_ARGB_8888:
+    factor = 4;
+    *gltexfmt = GL_RGBA8;
+    *glpixfmt = GL_BGRA;
+    *glpackfmt = GL_UNSIGNED_INT_8_8_8_8_REV;
+    break;
+  case GR_TEXFMT_ARGB_CMP_DXT1:  // FXT1,DXT1,5 support - H.Morii
+    // HACKALERT: 3Dfx Glide uses GR_TEXFMT_ARGB_CMP_DXT1 for both opaque DXT1 and DXT1 with 1bit alpha.
+    // GlideHQ compiled with GLIDE64_DXTN option enabled, uses opaqe DXT1 only.
+    factor = 8; // HACKALERT: factor holds block bytes
+    *gltexfmt = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; // these variables aren't used
+    *glpixfmt = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+    *glpackfmt = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+    break;
+  case GR_TEXFMT_ARGB_CMP_DXT3:
+    factor = 16;
+    *gltexfmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+    *glpixfmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+    *glpackfmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+    break;
+  case GR_TEXFMT_ARGB_CMP_DXT5:
+    factor = 16;
+    *gltexfmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+    *glpixfmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+    *glpackfmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+    break;
+  case GR_TEXFMT_ARGB_CMP_FXT1:
+    factor = 8;
+    *gltexfmt = GL_COMPRESSED_RGBA_FXT1_3DFX;
+    *glpixfmt = GL_COMPRESSED_RGBA_FXT1_3DFX;
+    *glpackfmt = GL_COMPRESSED_RGBA_FXT1_3DFX; // XXX: what should we do about GL_COMPRESSED_RGB_FXT1_3DFX?
+    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;
+  int factor;
+  int glformat = 0;
+  int gltexfmt, glpixfmt, glpackfmt;
+  LOG("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)
+    factor = -1;
+  else
+    factor = grTexFormat2GLPackedFmt(info->format, &gltexfmt, &glpixfmt, &glpackfmt);
+//printf("grTexDownloadMipmap, id=%x, size=%ix%i, format=%x\n", startAddress+1, width, height, info->format);
+  if (factor < 0) {
+    gltexfmt = GL_RGBA;
+    glpixfmt = GL_RGBA;
+    glpackfmt = GL_UNSIGNED_BYTE;
+
+    // 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
+    register int n = 0, m = 0;
+    switch(info->format)
+    {
+    case GR_TEXFMT_ALPHA_8:
+ /*     for (i=0; i<height; i++)
+      {
+        for (j=0; j<width; j++)
+        {
+          unsigned int texel = (unsigned int)((unsigned char*)info->data)[m];
+          texel |= (texel << 8);
+          texel |= (texel << 16);
+          ((unsigned int*)texture)[n] = texel;
+          m++;
+          n++;
+        }
+      }
+      factor = 1;
+      glformat = GL_RGBA;*/
+
+     for (i=0; i<height; i++)
+      {
+        for (j=0; j<width; j++)
+        {
+          unsigned short texel = (unsigned short)((unsigned char*)info->data)[m];
+          ((unsigned short*)texture)[n] = texel|(texel<<8);
+          m++;
+          n++;
+        }
+      }
+
+      glformat = gltexfmt = glpixfmt = GL_LUMINANCE_ALPHA;
+      glpackfmt = GL_UNSIGNED_BYTE;
+      factor = 1;
+      break;
+    case GR_TEXFMT_INTENSITY_8: // I8 support - H.Morii
+/*      for (i=0; i<height; i++)
+      {
+        for (j=0; j<width; j++)
+        {
+          unsigned int texel = (unsigned int)((unsigned char*)info->data)[m];
+          texel |= (0xFF000000 | (texel << 16) | (texel << 8));
+          ((unsigned int*)texture)[n] = texel;
+          m++;
+          n++;
+        }
+      }*/
+      factor = 1;
+//      glformat = GL_ALPHA;
+      memcpy(texture, info->data, width*height);
+      glformat = gltexfmt = glpixfmt = GL_LUMINANCE;
+      glpackfmt = GL_UNSIGNED_BYTE;
+      factor = 1;
+      break;
+    case GR_TEXFMT_ALPHA_INTENSITY_44:
+#if 1
+      for (i=0; i<height; i++)
+      {
+        for (j=0; j<width; j++)
+        {
+/*          unsigned int texel = (unsigned int)((unsigned char*)info->data)[m];
+#if 1
+          // accurate conversion
+          unsigned int texel_hi = (texel & 0x000000F0) << 20;
+          unsigned int texel_low = texel & 0x0000000F;
+          texel_low |= (texel_low << 4);
+          texel_hi |= ((texel_hi << 4) | (texel_low << 16) | (texel_low << 8) | texel_low);
+#else
+          unsigned int texel_hi = (texel & 0x000000F0) << 24;
+          unsigned int texel_low = (texel & 0x0000000F) << 4;
+          texel_hi |= ((texel_low << 16) | (texel_low << 8) | texel_low);
+#endif
+          ((unsigned int*)texture)[n] = texel_hi;
+*/
+         unsigned char texel = ((unsigned char*)info->data)[m];
+          unsigned short texel_hi = (texel & 0x000000F0) << 4;
+          unsigned short texel_low = texel & 0x0000000F;
+          texel_low |= (texel_low << 4);
+          texel_hi |= ((texel_hi << 4) | (texel_low));
+         ((unsigned short*)texture)[n] = texel_hi;
+          m++;
+          n++;
+        }
+      }
+      factor = 1;
+      glformat = gltexfmt = glpixfmt = GL_LUMINANCE_ALPHA;
+      glpackfmt = GL_UNSIGNED_BYTE;
+//      glformat = GL_LUMINANCE_ALPHA;
+#endif
+      break;
+    case GR_TEXFMT_RGB_565:
+/*      for (i=0; i<height; i++)
+      {
+        for (j=0; j<width; j++)
+        {*/
+/*          unsigned int texel = (unsigned int)((unsigned short*)info->data)[m];
+          unsigned int B = texel & 0x0000F800;
+          unsigned int G = texel & 0x000007E0;
+          unsigned int R = texel & 0x0000001F;
+#if 0
+          // accurate conversion 
+          ((unsigned int*)texture)[n] = 0xFF000000 | (R << 19) | ((R >> 2) << 16) | (G << 5) | ((G >> 9) << 8) | (B >> 8) | (B >> 13);
+#else
+          ((unsigned int*)texture)[n] = 0xFF000000 | (R << 19) | (G << 5) | (B >> 8);
+#endif
+*/
+/*       const unsigned short texel = ((unsigned short*)info->data)[m];
+          const unsigned short B = (texel & 0xF800)>>11;
+          const unsigned short G = texel & 0x07E0;
+          const unsigned short R = (texel & 0x001F)<<11;
+          ((unsigned short*)texture)[n] = R|G|B;
+          m++;
+          n++;
+        }
+      }*/
+      memcpy(texture, info->data, width*height*2);
+      factor = 2;
+//      glformat = GL_RGB;
+      glformat = gltexfmt = glpixfmt = GL_RGB;
+      glpackfmt = GL_UNSIGNED_SHORT_5_6_5;
+      break;
+    case GR_TEXFMT_ARGB_1555:
+      for (i=0; i<height; i++)
+      {
+        for (j=0; j<width; j++)
+        {
+/*          unsigned int texel = (unsigned int)((unsigned short*)info->data)[m];
+          unsigned int A = texel & 0x00008000 ? 0xFF000000 : 0;
+          unsigned int B = texel & 0x00007C00;
+          unsigned int G = texel & 0x000003E0;
+          unsigned int R = texel & 0x0000001F;
+#if 0
+          // accurate conversion
+          ((unsigned int*)texture)[n] = A | (R << 19) | ((R >> 2) << 16) | (G << 6) | ((G >> 8) << 8) | (B >> 7) | (B >> 12);
+#else
+          ((unsigned int*)texture)[n] = A | (R << 19) | (G << 6) | (B >> 7);
+#endif
+*/
+          unsigned short texel = ((unsigned short*)info->data)[m];
+          unsigned short A = (texel & 0x8000)>>15;
+         ((unsigned short*)texture)[n] = A|(texel&0x7fff)<<1;
+/*
+          unsigned short B = (texel & 0x7C00)>>9;
+          unsigned short G = texel & 0x03E0<<1;
+          unsigned short R = (texel & 0x001F)<<11;
+          ((unsigned short*)texture)[n] = A|R|G|B;*/
+          m++;
+          n++;
+        }
+      }
+      factor = 2;
+//      glformat = GL_RGBA;
+      glformat = gltexfmt = glpixfmt = GL_RGBA;
+      glpackfmt = GL_UNSIGNED_SHORT_5_5_5_1;
+      break;
+    case GR_TEXFMT_ALPHA_INTENSITY_88:
+/*      for (i=0; i<height; i++)
+      {
+        for (j=0; j<width; j++)
+        {
+          unsigned int AI = (unsigned int)((unsigned short*)info->data)[m];
+          unsigned int I = (unsigned int)(AI & 0x000000FF);
+          ((unsigned int*)texture)[n] = (AI << 16) | (I << 8) | I;
+          m++;
+          n++;
+        }
+      }*/
+      memcpy(texture, info->data, width*height*2);
+      factor = 2;
+      glformat = GL_LUMINANCE_ALPHA;
+      glformat = gltexfmt = glpixfmt = GL_LUMINANCE_ALPHA;
+      glpackfmt = GL_UNSIGNED_BYTE;
+      break;
+    case GR_TEXFMT_ARGB_4444:
+
+      for (i=0; i<height; i++)
+      {
+        for (j=0; j<width; j++)
+        {
+/*          unsigned int texel = (unsigned int)((unsigned short*)info->data)[m];
+          unsigned int A = texel & 0x0000F000;
+          unsigned int B = texel & 0x00000F00;
+          unsigned int G = texel & 0x000000F0;
+          unsigned int R = texel & 0x0000000F;
+#if 0
+          // accurate conversion
+          ((unsigned int*)texture)[n] = (A << 16) | (A << 12) | (R << 20) | (R << 16) | (G << 8) | (G << 4) | (B >> 4) | (B >> 8);
+#else
+          ((unsigned int*)texture)[n] = (A << 16) | (R << 20) | (G << 8) | (B >> 4);
+#endif
+*/
+          unsigned short texel = ((unsigned short*)info->data)[m];
+          unsigned int A = (texel & 0xF000)>>12;
+          ((unsigned short*)texture)[n] = A|(texel&0x0fff)<<4;
+          m++;
+          n++;
+        }
+      }
+      factor = 2;
+      glformat = GL_RGBA;
+      glformat = gltexfmt = glpixfmt = GL_RGBA;
+      glpackfmt = GL_UNSIGNED_SHORT_4_4_4_4;
+      break;
+    case GR_TEXFMT_ARGB_8888:
+      for (i=0; i<height; i++)
+      {
+        for (j=0; j<width; j++)
+        {
+          unsigned int texel = ((unsigned int*)info->data)[m];
+          unsigned int A = texel & 0xFF000000;
+          unsigned int B = texel & 0x00FF0000;
+          unsigned int G = texel & 0x0000FF00;
+          unsigned int R = texel & 0x000000FF;
+          ((unsigned int*)texture)[n] = A | (R << 16) | G | (B >> 16);
+          m++;
+          n++;
+        }
+      }
+      factor = 4;
+      glformat = GL_RGBA;
+      break;
+/*
+    case GR_TEXFMT_ARGB_CMP_DXT1: // FXT1,DXT1,5 support - H.Morii
+      factor = 8;                 // HACKALERT: factor holds block bytes
+      glformat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+      break;
+    case GR_TEXFMT_ARGB_CMP_DXT3: // FXT1,DXT1,5 support - H.Morii
+      factor = 16;                 // HACKALERT: factor holds block bytes
+      glformat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+      break;
+    case GR_TEXFMT_ARGB_CMP_DXT5:
+      factor = 16;
+      glformat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+      break;
+    case GR_TEXFMT_ARGB_CMP_FXT1:
+      factor = 8;
+      glformat = GL_COMPRESSED_RGBA_FXT1_3DFX;
+      break;
+*/
+    default:
+      display_warning("grTexDownloadMipMap : unknown texture format: %x", info->format);
+      factor = 0;
+    }
+  }
+
+  if (nbTextureUnits <= 2)
+    glActiveTexture(GL_TEXTURE1);
+  else
+    glActiveTexture(GL_TEXTURE2);
+
+  switch(info->format)
+  {
+  case GR_TEXFMT_ARGB_CMP_DXT1:
+  case GR_TEXFMT_ARGB_CMP_DXT3:
+  case GR_TEXFMT_ARGB_CMP_DXT5:
+  case GR_TEXFMT_ARGB_CMP_FXT1:
+    remove_tex(startAddress+1, startAddress+1+((width*height*factor)>>4));
+    break;
+  default:
+    remove_tex(startAddress+1, startAddress+1+(width*height*factor));
+  }
+
+  add_tex(startAddress+1);
+  glBindTexture(GL_TEXTURE_2D, startAddress+1);
+
+  if (largest_supported_anisotropy > 1.0f)
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy);
+
+//*SEB*  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
+//printf("new texture, id=%x, size=%ix%i, fmt=%x/%x\n", startAddress+1, width, height, gltexfmt, glpackfmt);
+  glTexImage2D(GL_TEXTURE_2D, 0, gltexfmt, width, height, 0, glpixfmt, glpackfmt, texture);
+/*
+  switch(info->format)
+  {
+  case GR_TEXFMT_ARGB_CMP_DXT1:
+  case GR_TEXFMT_ARGB_CMP_DXT3:
+  case GR_TEXFMT_ARGB_CMP_DXT5:
+  case GR_TEXFMT_ARGB_CMP_FXT1:
+    glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, (glformat ? glformat : gltexfmt), width, height, 0, (width*height*factor)>>4, info->data);
+    break;
+  default:
+    if (glformat) {
+      glTexImage2D(GL_TEXTURE_2D, 0, glformat, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
+    } else
+      glTexImage2D(GL_TEXTURE_2D, 0, gltexfmt, width, height, 0, glpixfmt, glpackfmt, info->data);
+  }
+*/
+
+  glBindTexture(GL_TEXTURE_2D, default_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 )
+{
+  LOG("grTexSource(%d,%d,%d)\r\n", tmu, startAddress, evenOdd);
+
+  if (tmu == GR_TMU1 || nbTextureUnits <= 2)
+  {
+    if (tmu == GR_TMU1 && nbTextureUnits <= 2) return;
+    glActiveTexture(GL_TEXTURE0);
+
+    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);
+  }
+  else
+  {
+    glActiveTexture(GL_TEXTURE1);
+
+    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(!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;
+    }
+  }
+
+#if 0
+  extern int auxbuffer;
+  static int oldbuffer;
+  FX_ENTRY void FX_CALL grAuxBufferExt( GrBuffer_t buffer );
+  if (auxbuffer == GR_BUFFER_AUXBUFFER && auxbuffer != oldbuffer)
+    grAuxBufferExt(auxbuffer);
+  oldbuffer = auxbuffer;
+#endif
+}
+
+FX_ENTRY void FX_CALL
+grTexDetailControl(
+                   GrChipID_t tmu,
+                   int lod_bias,
+                   FxU8 detail_scale,
+                   float detail_max
+                   )
+{
+  LOG("grTexDetailControl(%d,%d,%d,%d)\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);
+
+  set_lambda();
+}
+
+FX_ENTRY void FX_CALL
+grTexLodBiasValue(GrChipID_t tmu, float bias )
+{
+  LOG("grTexLodBiasValue(%d,%f)\r\n", tmu, bias);
+}
+
+FX_ENTRY void FX_CALL
+grTexFilterMode(
+                GrChipID_t tmu,
+                GrTextureFilterMode_t minfilter_mode,
+                GrTextureFilterMode_t magfilter_mode
+                )
+{
+  LOG("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;
+
+    glActiveTexture(GL_TEXTURE0);
+    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;
+
+    glActiveTexture(GL_TEXTURE1);
+    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
+               )
+{
+  LOG("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;
+      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;
+      break;
+    default:
+      display_warning("grTexClampMode : unknown t_clampmode : %x", t_clampmode);
+    }
+    glActiveTexture(GL_TEXTURE0);
+    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;
+      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;
+      break;
+    default:
+      display_warning("grTexClampMode : unknown t_clampmode : %x", t_clampmode);
+    }
+    glActiveTexture(GL_TEXTURE1);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_s1);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t1);
+  }
+}
diff --git a/source/gles2glide64/src/video_api_export.ver b/source/gles2glide64/src/video_api_export.ver
new file mode 100644 (file)
index 0000000..8d2496c
--- /dev/null
@@ -0,0 +1,23 @@
+{ global:
+PluginStartup;
+PluginShutdown;
+PluginGetVersion;
+ChangeWindow;
+InitiateGFX;
+MoveScreen;
+ProcessDList;
+ProcessRDPList;
+RomClosed;
+RomOpen;
+RomResumed;
+ShowCFB;
+UpdateScreen;
+ViStatusChanged;
+ViWidthChanged;
+ReadScreen2;
+SetRenderingCallback;
+ResizeVideoOutput;
+FBRead;
+FBWrite;
+FBGetFrameBufferInfo;
+local: *; };
diff --git a/source/gles2glide64/todo!.txt b/source/gles2glide64/todo!.txt
new file mode 100644 (file)
index 0000000..7c297c5
--- /dev/null
@@ -0,0 +1,16 @@
+ToDo!
+
+Glide64
+-      Add tlut support for 16bit textures. Remove hacks.
+-      Add trapezoid support to le_triangle. Remove hacks.
+-      Reduce "Known issues" list :)
+-   Port over C ports of NASM functions from balrog's fork
+
+GlideHQ
+-      Add OpenGL texture format support.
+
+Glitch64
+-      Improve hardware frame buffer emulation support.
+        (FBO depth copies, MSAAed FBO based HWFBE)
+-      Add functions, necessary for interactive debugger.
+